forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/drivers/net/phy/mdio_bus.c
....@@ -1,46 +1,39 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /* MDIO Bus interface
23 *
34 * Author: Andy Fleming
45 *
56 * Copyright (c) 2004 Freescale Semiconductor, Inc.
6
- *
7
- * This program is free software; you can redistribute it and/or modify it
8
- * under the terms of the GNU General Public License as published by the
9
- * Free Software Foundation; either version 2 of the License, or (at your
10
- * option) any later version.
11
- *
127 */
138
149 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1510
16
-#include <linux/kernel.h>
17
-#include <linux/string.h>
18
-#include <linux/errno.h>
19
-#include <linux/unistd.h>
20
-#include <linux/slab.h>
21
-#include <linux/interrupt.h>
22
-#include <linux/init.h>
2311 #include <linux/delay.h>
2412 #include <linux/device.h>
13
+#include <linux/errno.h>
14
+#include <linux/etherdevice.h>
15
+#include <linux/ethtool.h>
2516 #include <linux/gpio.h>
2617 #include <linux/gpio/consumer.h>
27
-#include <linux/of_device.h>
28
-#include <linux/of_mdio.h>
29
-#include <linux/of_gpio.h>
30
-#include <linux/netdevice.h>
31
-#include <linux/etherdevice.h>
32
-#include <linux/skbuff.h>
33
-#include <linux/spinlock.h>
18
+#include <linux/init.h>
19
+#include <linux/interrupt.h>
20
+#include <linux/io.h>
21
+#include <linux/kernel.h>
22
+#include <linux/mii.h>
3423 #include <linux/mm.h>
3524 #include <linux/module.h>
36
-#include <linux/mii.h>
37
-#include <linux/ethtool.h>
25
+#include <linux/netdevice.h>
26
+#include <linux/of_device.h>
27
+#include <linux/of_gpio.h>
28
+#include <linux/of_mdio.h>
3829 #include <linux/phy.h>
39
-#include <linux/io.h>
30
+#include <linux/reset.h>
31
+#include <linux/skbuff.h>
32
+#include <linux/slab.h>
33
+#include <linux/spinlock.h>
34
+#include <linux/string.h>
4035 #include <linux/uaccess.h>
41
-#include <linux/gpio/consumer.h>
42
-
43
-#include <asm/irq.h>
36
+#include <linux/unistd.h>
4437
4538 #define CREATE_TRACE_POINTS
4639 #include <trace/events/mdio.h>
....@@ -49,24 +42,27 @@
4942
5043 static int mdiobus_register_gpiod(struct mdio_device *mdiodev)
5144 {
52
- struct gpio_desc *gpiod = NULL;
53
-
5445 /* Deassert the optional reset signal */
55
- if (mdiodev->dev.of_node)
56
- gpiod = fwnode_get_named_gpiod(&mdiodev->dev.of_node->fwnode,
57
- "reset-gpios", 0, GPIOD_OUT_LOW,
58
- "PHY reset");
59
- if (IS_ERR(gpiod)) {
60
- if (PTR_ERR(gpiod) == -ENOENT || PTR_ERR(gpiod) == -ENOSYS)
61
- gpiod = NULL;
62
- else
63
- return PTR_ERR(gpiod);
64
- }
46
+ mdiodev->reset_gpio = gpiod_get_optional(&mdiodev->dev,
47
+ "reset", GPIOD_OUT_LOW);
48
+ if (IS_ERR(mdiodev->reset_gpio))
49
+ return PTR_ERR(mdiodev->reset_gpio);
6550
66
- mdiodev->reset = gpiod;
51
+ if (mdiodev->reset_gpio)
52
+ gpiod_set_consumer_name(mdiodev->reset_gpio, "PHY reset");
6753
68
- /* Assert the reset signal again */
69
- mdio_device_reset(mdiodev, 1);
54
+ return 0;
55
+}
56
+
57
+static int mdiobus_register_reset(struct mdio_device *mdiodev)
58
+{
59
+ struct reset_control *reset;
60
+
61
+ reset = reset_control_get_optional_exclusive(&mdiodev->dev, "phy");
62
+ if (IS_ERR(reset))
63
+ return PTR_ERR(reset);
64
+
65
+ mdiodev->reset_ctrl = reset;
7066
7167 return 0;
7268 }
....@@ -82,6 +78,13 @@
8278 err = mdiobus_register_gpiod(mdiodev);
8379 if (err)
8480 return err;
81
+
82
+ err = mdiobus_register_reset(mdiodev);
83
+ if (err)
84
+ return err;
85
+
86
+ /* Assert the reset signal */
87
+ mdio_device_reset(mdiodev, 1);
8588 }
8689
8790 mdiodev->bus->mdio_map[mdiodev->addr] = mdiodev;
....@@ -94,6 +97,8 @@
9497 {
9598 if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
9699 return -EINVAL;
100
+
101
+ reset_control_put(mdiodev->reset_ctrl);
97102
98103 mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
99104
....@@ -150,80 +155,15 @@
150155 if (size)
151156 bus->priv = (void *)bus + aligned_size;
152157
153
- /* Initialise the interrupts to polling */
154
- for (i = 0; i < PHY_MAX_ADDR; i++)
158
+ /* Initialise the interrupts to polling and 64-bit seqcounts */
159
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
155160 bus->irq[i] = PHY_POLL;
156
-
157
- return bus;
158
-}
159
-EXPORT_SYMBOL(mdiobus_alloc_size);
160
-
161
-static void _devm_mdiobus_free(struct device *dev, void *res)
162
-{
163
- mdiobus_free(*(struct mii_bus **)res);
164
-}
165
-
166
-static int devm_mdiobus_match(struct device *dev, void *res, void *data)
167
-{
168
- struct mii_bus **r = res;
169
-
170
- if (WARN_ON(!r || !*r))
171
- return 0;
172
-
173
- return *r == data;
174
-}
175
-
176
-/**
177
- * devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
178
- * @dev: Device to allocate mii_bus for
179
- * @sizeof_priv: Space to allocate for private structure.
180
- *
181
- * Managed mdiobus_alloc_size. mii_bus allocated with this function is
182
- * automatically freed on driver detach.
183
- *
184
- * If an mii_bus allocated with this function needs to be freed separately,
185
- * devm_mdiobus_free() must be used.
186
- *
187
- * RETURNS:
188
- * Pointer to allocated mii_bus on success, NULL on failure.
189
- */
190
-struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
191
-{
192
- struct mii_bus **ptr, *bus;
193
-
194
- ptr = devres_alloc(_devm_mdiobus_free, sizeof(*ptr), GFP_KERNEL);
195
- if (!ptr)
196
- return NULL;
197
-
198
- /* use raw alloc_dr for kmalloc caller tracing */
199
- bus = mdiobus_alloc_size(sizeof_priv);
200
- if (bus) {
201
- *ptr = bus;
202
- devres_add(dev, ptr);
203
- } else {
204
- devres_free(ptr);
161
+ u64_stats_init(&bus->stats[i].syncp);
205162 }
206163
207164 return bus;
208165 }
209
-EXPORT_SYMBOL_GPL(devm_mdiobus_alloc_size);
210
-
211
-/**
212
- * devm_mdiobus_free - Resource-managed mdiobus_free()
213
- * @dev: Device this mii_bus belongs to
214
- * @bus: the mii_bus associated with the device
215
- *
216
- * Free mii_bus allocated with devm_mdiobus_alloc_size().
217
- */
218
-void devm_mdiobus_free(struct device *dev, struct mii_bus *bus)
219
-{
220
- int rc;
221
-
222
- rc = devres_release(dev, _devm_mdiobus_free,
223
- devm_mdiobus_match, bus);
224
- WARN_ON(rc);
225
-}
226
-EXPORT_SYMBOL_GPL(devm_mdiobus_free);
166
+EXPORT_SYMBOL(mdiobus_alloc_size);
227167
228168 /**
229169 * mdiobus_release - mii_bus device release callback
....@@ -241,17 +181,235 @@
241181 kfree(bus);
242182 }
243183
184
+struct mdio_bus_stat_attr {
185
+ int addr;
186
+ unsigned int field_offset;
187
+};
188
+
189
+static u64 mdio_bus_get_stat(struct mdio_bus_stats *s, unsigned int offset)
190
+{
191
+ const char *p = (const char *)s + offset;
192
+ unsigned int start;
193
+ u64 val = 0;
194
+
195
+ do {
196
+ start = u64_stats_fetch_begin(&s->syncp);
197
+ val = u64_stats_read((const u64_stats_t *)p);
198
+ } while (u64_stats_fetch_retry(&s->syncp, start));
199
+
200
+ return val;
201
+}
202
+
203
+static u64 mdio_bus_get_global_stat(struct mii_bus *bus, unsigned int offset)
204
+{
205
+ unsigned int i;
206
+ u64 val = 0;
207
+
208
+ for (i = 0; i < PHY_MAX_ADDR; i++)
209
+ val += mdio_bus_get_stat(&bus->stats[i], offset);
210
+
211
+ return val;
212
+}
213
+
214
+static ssize_t mdio_bus_stat_field_show(struct device *dev,
215
+ struct device_attribute *attr,
216
+ char *buf)
217
+{
218
+ struct mii_bus *bus = to_mii_bus(dev);
219
+ struct mdio_bus_stat_attr *sattr;
220
+ struct dev_ext_attribute *eattr;
221
+ u64 val;
222
+
223
+ eattr = container_of(attr, struct dev_ext_attribute, attr);
224
+ sattr = eattr->var;
225
+
226
+ if (sattr->addr < 0)
227
+ val = mdio_bus_get_global_stat(bus, sattr->field_offset);
228
+ else
229
+ val = mdio_bus_get_stat(&bus->stats[sattr->addr],
230
+ sattr->field_offset);
231
+
232
+ return sprintf(buf, "%llu\n", val);
233
+}
234
+
235
+static ssize_t mdio_bus_device_stat_field_show(struct device *dev,
236
+ struct device_attribute *attr,
237
+ char *buf)
238
+{
239
+ struct mdio_device *mdiodev = to_mdio_device(dev);
240
+ struct mii_bus *bus = mdiodev->bus;
241
+ struct mdio_bus_stat_attr *sattr;
242
+ struct dev_ext_attribute *eattr;
243
+ int addr = mdiodev->addr;
244
+ u64 val;
245
+
246
+ eattr = container_of(attr, struct dev_ext_attribute, attr);
247
+ sattr = eattr->var;
248
+
249
+ val = mdio_bus_get_stat(&bus->stats[addr], sattr->field_offset);
250
+
251
+ return sprintf(buf, "%llu\n", val);
252
+}
253
+
254
+#define MDIO_BUS_STATS_ATTR_DECL(field, file) \
255
+static struct dev_ext_attribute dev_attr_mdio_bus_##field = { \
256
+ .attr = { .attr = { .name = file, .mode = 0444 }, \
257
+ .show = mdio_bus_stat_field_show, \
258
+ }, \
259
+ .var = &((struct mdio_bus_stat_attr) { \
260
+ -1, offsetof(struct mdio_bus_stats, field) \
261
+ }), \
262
+}; \
263
+static struct dev_ext_attribute dev_attr_mdio_bus_device_##field = { \
264
+ .attr = { .attr = { .name = file, .mode = 0444 }, \
265
+ .show = mdio_bus_device_stat_field_show, \
266
+ }, \
267
+ .var = &((struct mdio_bus_stat_attr) { \
268
+ -1, offsetof(struct mdio_bus_stats, field) \
269
+ }), \
270
+};
271
+
272
+#define MDIO_BUS_STATS_ATTR(field) \
273
+ MDIO_BUS_STATS_ATTR_DECL(field, __stringify(field))
274
+
275
+MDIO_BUS_STATS_ATTR(transfers);
276
+MDIO_BUS_STATS_ATTR(errors);
277
+MDIO_BUS_STATS_ATTR(writes);
278
+MDIO_BUS_STATS_ATTR(reads);
279
+
280
+#define MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, file) \
281
+static struct dev_ext_attribute dev_attr_mdio_bus_addr_##field##_##addr = { \
282
+ .attr = { .attr = { .name = file, .mode = 0444 }, \
283
+ .show = mdio_bus_stat_field_show, \
284
+ }, \
285
+ .var = &((struct mdio_bus_stat_attr) { \
286
+ addr, offsetof(struct mdio_bus_stats, field) \
287
+ }), \
288
+}
289
+
290
+#define MDIO_BUS_STATS_ADDR_ATTR(field, addr) \
291
+ MDIO_BUS_STATS_ADDR_ATTR_DECL(field, addr, \
292
+ __stringify(field) "_" __stringify(addr))
293
+
294
+#define MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(addr) \
295
+ MDIO_BUS_STATS_ADDR_ATTR(transfers, addr); \
296
+ MDIO_BUS_STATS_ADDR_ATTR(errors, addr); \
297
+ MDIO_BUS_STATS_ADDR_ATTR(writes, addr); \
298
+ MDIO_BUS_STATS_ADDR_ATTR(reads, addr) \
299
+
300
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(0);
301
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(1);
302
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(2);
303
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(3);
304
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(4);
305
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(5);
306
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(6);
307
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(7);
308
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(8);
309
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(9);
310
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(10);
311
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(11);
312
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(12);
313
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(13);
314
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(14);
315
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(15);
316
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(16);
317
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(17);
318
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(18);
319
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(19);
320
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(20);
321
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(21);
322
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(22);
323
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(23);
324
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(24);
325
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(25);
326
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(26);
327
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(27);
328
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(28);
329
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(29);
330
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(30);
331
+MDIO_BUS_STATS_ADDR_ATTR_GROUP_DECL(31);
332
+
333
+#define MDIO_BUS_STATS_ADDR_ATTR_GROUP(addr) \
334
+ &dev_attr_mdio_bus_addr_transfers_##addr.attr.attr, \
335
+ &dev_attr_mdio_bus_addr_errors_##addr.attr.attr, \
336
+ &dev_attr_mdio_bus_addr_writes_##addr.attr.attr, \
337
+ &dev_attr_mdio_bus_addr_reads_##addr.attr.attr \
338
+
339
+static struct attribute *mdio_bus_statistics_attrs[] = {
340
+ &dev_attr_mdio_bus_transfers.attr.attr,
341
+ &dev_attr_mdio_bus_errors.attr.attr,
342
+ &dev_attr_mdio_bus_writes.attr.attr,
343
+ &dev_attr_mdio_bus_reads.attr.attr,
344
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(0),
345
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(1),
346
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(2),
347
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(3),
348
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(4),
349
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(5),
350
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(6),
351
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(7),
352
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(8),
353
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(9),
354
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(10),
355
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(11),
356
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(12),
357
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(13),
358
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(14),
359
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(15),
360
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(16),
361
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(17),
362
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(18),
363
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(19),
364
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(20),
365
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(21),
366
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(22),
367
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(23),
368
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(24),
369
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(25),
370
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(26),
371
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(27),
372
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(28),
373
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(29),
374
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(30),
375
+ MDIO_BUS_STATS_ADDR_ATTR_GROUP(31),
376
+ NULL,
377
+};
378
+
379
+static const struct attribute_group mdio_bus_statistics_group = {
380
+ .name = "statistics",
381
+ .attrs = mdio_bus_statistics_attrs,
382
+};
383
+
384
+static const struct attribute_group *mdio_bus_groups[] = {
385
+ &mdio_bus_statistics_group,
386
+ NULL,
387
+};
388
+
244389 static struct class mdio_bus_class = {
245390 .name = "mdio_bus",
246391 .dev_release = mdiobus_release,
392
+ .dev_groups = mdio_bus_groups,
247393 };
248394
249
-#if IS_ENABLED(CONFIG_OF_MDIO)
250
-/* Helper function for of_mdio_find_bus */
251
-static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np)
395
+/**
396
+ * mdio_find_bus - Given the name of a mdiobus, find the mii_bus.
397
+ * @mdio_name: The name of a mdiobus.
398
+ *
399
+ * Returns a reference to the mii_bus, or NULL if none found. The
400
+ * embedded struct device will have its reference count incremented,
401
+ * and this must be put_deviced'ed once the bus is finished with.
402
+ */
403
+struct mii_bus *mdio_find_bus(const char *mdio_name)
252404 {
253
- return dev->of_node == mdio_bus_np;
405
+ struct device *d;
406
+
407
+ d = class_find_device_by_name(&mdio_bus_class, mdio_name);
408
+ return d ? to_mii_bus(d) : NULL;
254409 }
410
+EXPORT_SYMBOL(mdio_find_bus);
411
+
412
+#if IS_ENABLED(CONFIG_OF_MDIO)
255413 /**
256414 * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
257415 * @mdio_bus_np: Pointer to the mii_bus.
....@@ -272,9 +430,7 @@
272430 if (!mdio_bus_np)
273431 return NULL;
274432
275
- d = class_find_device(&mdio_bus_class, NULL, mdio_bus_np,
276
- of_mdio_bus_match);
277
-
433
+ d = class_find_device_by_of_node(&mdio_bus_class, mdio_bus_np);
278434 return d ? to_mii_bus(d) : NULL;
279435 }
280436 EXPORT_SYMBOL(of_mdio_find_bus);
....@@ -392,6 +548,7 @@
392548 }
393549
394550 mutex_init(&bus->mdio_lock);
551
+ mutex_init(&bus->shared_lock);
395552
396553 /* de-assert bus level PHY GPIO reset */
397554 gpiod = devm_gpiod_get_optional(&bus->dev, "reset", GPIOD_OUT_LOW);
....@@ -404,15 +561,20 @@
404561 bus->reset_gpiod = gpiod;
405562
406563 gpiod_set_value_cansleep(gpiod, 1);
407
- udelay(bus->reset_delay_us);
564
+ fsleep(bus->reset_delay_us);
408565 gpiod_set_value_cansleep(gpiod, 0);
566
+ if (bus->reset_post_delay_us > 0)
567
+ fsleep(bus->reset_post_delay_us);
409568 }
410569
411
- if (bus->reset)
412
- bus->reset(bus);
570
+ if (bus->reset) {
571
+ err = bus->reset(bus);
572
+ if (err)
573
+ goto error_reset_gpiod;
574
+ }
413575
414576 for (i = 0; i < PHY_MAX_ADDR; i++) {
415
- if ((bus->phy_mask & (1 << i)) == 0) {
577
+ if ((bus->phy_mask & BIT(i)) == 0) {
416578 struct phy_device *phydev;
417579
418580 phydev = mdiobus_scan(bus, i);
....@@ -438,7 +600,7 @@
438600 mdiodev->device_remove(mdiodev);
439601 mdiodev->device_free(mdiodev);
440602 }
441
-
603
+error_reset_gpiod:
442604 /* Put PHYs in RESET to save power */
443605 if (bus->reset_gpiod)
444606 gpiod_set_value_cansleep(bus->reset_gpiod, 1);
....@@ -462,8 +624,8 @@
462624 if (!mdiodev)
463625 continue;
464626
465
- if (mdiodev->reset)
466
- gpiod_put(mdiodev->reset);
627
+ if (mdiodev->reset_gpio)
628
+ gpiod_put(mdiodev->reset_gpio);
467629
468630 mdiodev->device_remove(mdiodev);
469631 mdiodev->device_free(mdiodev);
....@@ -514,10 +676,24 @@
514676 */
515677 struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
516678 {
517
- struct phy_device *phydev;
679
+ struct phy_device *phydev = ERR_PTR(-ENODEV);
518680 int err;
519681
520
- phydev = get_phy_device(bus, addr, false);
682
+ switch (bus->probe_capabilities) {
683
+ case MDIOBUS_NO_CAP:
684
+ case MDIOBUS_C22:
685
+ phydev = get_phy_device(bus, addr, false);
686
+ break;
687
+ case MDIOBUS_C45:
688
+ phydev = get_phy_device(bus, addr, true);
689
+ break;
690
+ case MDIOBUS_C22_C45:
691
+ phydev = get_phy_device(bus, addr, false);
692
+ if (IS_ERR(phydev))
693
+ phydev = get_phy_device(bus, addr, true);
694
+ break;
695
+ }
696
+
521697 if (IS_ERR(phydev))
522698 return phydev;
523699
....@@ -536,6 +712,26 @@
536712 return phydev;
537713 }
538714 EXPORT_SYMBOL(mdiobus_scan);
715
+
716
+static void mdiobus_stats_acct(struct mdio_bus_stats *stats, bool op, int ret)
717
+{
718
+ preempt_disable();
719
+ u64_stats_update_begin(&stats->syncp);
720
+
721
+ u64_stats_inc(&stats->transfers);
722
+ if (ret < 0) {
723
+ u64_stats_inc(&stats->errors);
724
+ goto out;
725
+ }
726
+
727
+ if (op)
728
+ u64_stats_inc(&stats->reads);
729
+ else
730
+ u64_stats_inc(&stats->writes);
731
+out:
732
+ u64_stats_update_end(&stats->syncp);
733
+ preempt_enable();
734
+}
539735
540736 /**
541737 * __mdiobus_read - Unlocked version of the mdiobus_read function
....@@ -556,6 +752,7 @@
556752 retval = bus->read(bus, addr, regnum);
557753
558754 trace_mdio_access(bus, 1, addr, regnum, retval, retval);
755
+ mdiobus_stats_acct(&bus->stats[addr], true, retval);
559756
560757 return retval;
561758 }
....@@ -581,10 +778,43 @@
581778 err = bus->write(bus, addr, regnum, val);
582779
583780 trace_mdio_access(bus, 0, addr, regnum, val, err);
781
+ mdiobus_stats_acct(&bus->stats[addr], false, err);
584782
585783 return err;
586784 }
587785 EXPORT_SYMBOL(__mdiobus_write);
786
+
787
+/**
788
+ * __mdiobus_modify_changed - Unlocked version of the mdiobus_modify function
789
+ * @bus: the mii_bus struct
790
+ * @addr: the phy address
791
+ * @regnum: register number to modify
792
+ * @mask: bit mask of bits to clear
793
+ * @set: bit mask of bits to set
794
+ *
795
+ * Read, modify, and if any change, write the register value back to the
796
+ * device. Any error returns a negative number.
797
+ *
798
+ * NOTE: MUST NOT be called from interrupt context.
799
+ */
800
+int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
801
+ u16 mask, u16 set)
802
+{
803
+ int new, ret;
804
+
805
+ ret = __mdiobus_read(bus, addr, regnum);
806
+ if (ret < 0)
807
+ return ret;
808
+
809
+ new = (ret & ~mask) | set;
810
+ if (new == ret)
811
+ return 0;
812
+
813
+ ret = __mdiobus_write(bus, addr, regnum, new);
814
+
815
+ return ret < 0 ? ret : 1;
816
+}
817
+EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
588818
589819 /**
590820 * mdiobus_read_nested - Nested version of the mdiobus_read function
....@@ -602,8 +832,6 @@
602832 int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
603833 {
604834 int retval;
605
-
606
- BUG_ON(in_interrupt());
607835
608836 mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
609837 retval = __mdiobus_read(bus, addr, regnum);
....@@ -626,8 +854,6 @@
626854 int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
627855 {
628856 int retval;
629
-
630
- BUG_ON(in_interrupt());
631857
632858 mutex_lock(&bus->mdio_lock);
633859 retval = __mdiobus_read(bus, addr, regnum);
....@@ -655,8 +881,6 @@
655881 {
656882 int err;
657883
658
- BUG_ON(in_interrupt());
659
-
660884 mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
661885 err = __mdiobus_write(bus, addr, regnum, val);
662886 mutex_unlock(&bus->mdio_lock);
....@@ -680,8 +904,6 @@
680904 {
681905 int err;
682906
683
- BUG_ON(in_interrupt());
684
-
685907 mutex_lock(&bus->mdio_lock);
686908 err = __mdiobus_write(bus, addr, regnum, val);
687909 mutex_unlock(&bus->mdio_lock);
....@@ -689,6 +911,27 @@
689911 return err;
690912 }
691913 EXPORT_SYMBOL(mdiobus_write);
914
+
915
+/**
916
+ * mdiobus_modify - Convenience function for modifying a given mdio device
917
+ * register
918
+ * @bus: the mii_bus struct
919
+ * @addr: the phy address
920
+ * @regnum: register number to write
921
+ * @mask: bit mask of bits to clear
922
+ * @set: bit mask of bits to set
923
+ */
924
+int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask, u16 set)
925
+{
926
+ int err;
927
+
928
+ mutex_lock(&bus->mdio_lock);
929
+ err = __mdiobus_modify_changed(bus, addr, regnum, mask, set);
930
+ mutex_unlock(&bus->mdio_lock);
931
+
932
+ return err < 0 ? err : 0;
933
+}
934
+EXPORT_SYMBOL_GPL(mdiobus_modify);
692935
693936 /**
694937 * mdio_bus_match - determine if given MDIO driver supports the given
....@@ -726,8 +969,27 @@
726969 return 0;
727970 }
728971
972
+static struct attribute *mdio_bus_device_statistics_attrs[] = {
973
+ &dev_attr_mdio_bus_device_transfers.attr.attr,
974
+ &dev_attr_mdio_bus_device_errors.attr.attr,
975
+ &dev_attr_mdio_bus_device_writes.attr.attr,
976
+ &dev_attr_mdio_bus_device_reads.attr.attr,
977
+ NULL,
978
+};
979
+
980
+static const struct attribute_group mdio_bus_device_statistics_group = {
981
+ .name = "statistics",
982
+ .attrs = mdio_bus_device_statistics_attrs,
983
+};
984
+
985
+static const struct attribute_group *mdio_bus_dev_groups[] = {
986
+ &mdio_bus_device_statistics_group,
987
+ NULL,
988
+};
989
+
729990 struct bus_type mdio_bus_type = {
730991 .name = "mdio_bus",
992
+ .dev_groups = mdio_bus_dev_groups,
731993 .match = mdio_bus_match,
732994 .uevent = mdio_uevent,
733995 };
....@@ -746,7 +1008,6 @@
7461008
7471009 return ret;
7481010 }
749
-EXPORT_SYMBOL_GPL(mdio_bus_init);
7501011
7511012 #if IS_ENABLED(CONFIG_PHYLIB)
7521013 void mdio_bus_exit(void)