aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/phy/Kconfig8
-rw-r--r--drivers/net/phy/mdio_bus.c74
-rw-r--r--drivers/net/phy/phy.c197
-rw-r--r--drivers/net/phy/phy_device.c130
4 files changed, 12 insertions, 397 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index c2f1bf1d02d2..6450bd71deb4 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -12,14 +12,6 @@ config PHYLIB
12 devices. This option provides infrastructure for 12 devices. This option provides infrastructure for
13 managing PHY devices. 13 managing PHY devices.
14 14
15config PHYCONTROL
16 bool "Support for automatically handling PHY state changes"
17 depends on PHYLIB
18 help
19 Adds code to perform all the work for keeping PHY link
20 state (speed/duplex/etc) up-to-date. Also handles
21 interrupts.
22
23comment "MII PHY device drivers" 15comment "MII PHY device drivers"
24 depends on PHYLIB 16 depends on PHYLIB
25 17
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 5fbea6acfe80..d5a05be28818 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -38,80 +38,6 @@
38#include <asm/irq.h> 38#include <asm/irq.h>
39#include <asm/uaccess.h> 39#include <asm/uaccess.h>
40 40
41/* mdiobus_register
42 *
43 * description: Called by a bus driver to bring up all the PHYs
44 * on a given bus, and attach them to the bus
45 */
46int mdiobus_register(struct mii_bus *bus)
47{
48 int i;
49 int err = 0;
50
51 spin_lock_init(&bus->mdio_lock);
52
53 if (NULL == bus || NULL == bus->name ||
54 NULL == bus->read ||
55 NULL == bus->write)
56 return -EINVAL;
57
58 if (bus->reset)
59 bus->reset(bus);
60
61 for (i = 0; i < PHY_MAX_ADDR; i++) {
62 struct phy_device *phydev;
63
64 phydev = get_phy_device(bus, i);
65
66 if (IS_ERR(phydev))
67 return PTR_ERR(phydev);
68
69 /* There's a PHY at this address
70 * We need to set:
71 * 1) IRQ
72 * 2) bus_id
73 * 3) parent
74 * 4) bus
75 * 5) mii_bus
76 * And, we need to register it */
77 if (phydev) {
78 phydev->irq = bus->irq[i];
79
80 phydev->dev.parent = bus->dev;
81 phydev->dev.bus = &mdio_bus_type;
82 sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i);
83
84 phydev->bus = bus;
85
86 err = device_register(&phydev->dev);
87
88 if (err)
89 printk(KERN_ERR "phy %d failed to register\n",
90 i);
91 }
92
93 bus->phy_map[i] = phydev;
94 }
95
96 pr_info("%s: probed\n", bus->name);
97
98 return err;
99}
100EXPORT_SYMBOL(mdiobus_register);
101
102void mdiobus_unregister(struct mii_bus *bus)
103{
104 int i;
105
106 for (i = 0; i < PHY_MAX_ADDR; i++) {
107 if (bus->phy_map[i]) {
108 device_unregister(&bus->phy_map[i]->dev);
109 kfree(bus->phy_map[i]);
110 }
111 }
112}
113EXPORT_SYMBOL(mdiobus_unregister);
114
115/* mdio_bus_match 41/* mdio_bus_match
116 * 42 *
117 * description: Given a PHY device, and a PHY driver, return 1 if 43 * description: Given a PHY device, and a PHY driver, return 1 if
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 934065dd6371..d3e43631b89b 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -40,21 +40,9 @@
40#include <asm/uaccess.h> 40#include <asm/uaccess.h>
41 41
42static void phy_timer(unsigned long data); 42static void phy_timer(unsigned long data);
43 43static int phy_disable_interrupts(struct phy_device *phydev);
44/* Convenience function to print out the current phy status 44static void phy_sanitize_settings(struct phy_device *phydev);
45 */ 45static int phy_stop_interrupts(struct phy_device *phydev);
46void phy_print_status(struct phy_device *phydev)
47{
48 pr_info("%s: Link is %s", phydev->dev.bus_id,
49 phydev->link ? "Up" : "Down");
50 if (phydev->link)
51 printk(" - %d/%s", phydev->speed,
52 DUPLEX_FULL == phydev->duplex ?
53 "Full" : "Half");
54
55 printk("\n");
56}
57EXPORT_SYMBOL(phy_print_status);
58 46
59 47
60/* Convenience functions for reading/writing a given PHY 48/* Convenience functions for reading/writing a given PHY
@@ -133,7 +121,7 @@ static inline int phy_aneg_done(struct phy_device *phydev)
133 * and to PHY_FORCING if auto-negotiation is disabled. Unless 121 * and to PHY_FORCING if auto-negotiation is disabled. Unless
134 * the PHY is currently HALTED. 122 * the PHY is currently HALTED.
135 */ 123 */
136int phy_start_aneg(struct phy_device *phydev) 124static int phy_start_aneg(struct phy_device *phydev)
137{ 125{
138 int err; 126 int err;
139 127
@@ -161,8 +149,6 @@ out_unlock:
161 spin_unlock(&phydev->lock); 149 spin_unlock(&phydev->lock);
162 return err; 150 return err;
163} 151}
164EXPORT_SYMBOL(phy_start_aneg);
165
166 152
167/* A structure for mapping a particular speed and duplex 153/* A structure for mapping a particular speed and duplex
168 * combination to a particular SUPPORTED and ADVERTISED value */ 154 * combination to a particular SUPPORTED and ADVERTISED value */
@@ -255,7 +241,7 @@ static inline int phy_find_valid(int idx, u32 features)
255 * duplexes. Drop down by one in this order: 1000/FULL, 241 * duplexes. Drop down by one in this order: 1000/FULL,
256 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF 242 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF
257 */ 243 */
258void phy_sanitize_settings(struct phy_device *phydev) 244static void phy_sanitize_settings(struct phy_device *phydev)
259{ 245{
260 u32 features = phydev->supported; 246 u32 features = phydev->supported;
261 int idx; 247 int idx;
@@ -270,7 +256,6 @@ void phy_sanitize_settings(struct phy_device *phydev)
270 phydev->speed = settings[idx].speed; 256 phydev->speed = settings[idx].speed;
271 phydev->duplex = settings[idx].duplex; 257 phydev->duplex = settings[idx].duplex;
272} 258}
273EXPORT_SYMBOL(phy_sanitize_settings);
274 259
275/* phy_force_reduction 260/* phy_force_reduction
276 * 261 *
@@ -477,48 +462,22 @@ void phy_error(struct phy_device *phydev)
477 spin_unlock(&phydev->lock); 462 spin_unlock(&phydev->lock);
478} 463}
479 464
480#ifdef CONFIG_PHYCONTROL 465static int phy_stop_interrupts(struct phy_device *phydev)
481
482static void phy_change(void *data);
483
484/* phy_interrupt
485 *
486 * description: When a PHY interrupt occurs, the handler disables
487 * interrupts, and schedules a work task to clear the interrupt.
488 */
489static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs)
490{
491 struct phy_device *phydev = phy_dat;
492
493 /* The MDIO bus is not allowed to be written in interrupt
494 * context, so we need to disable the irq here. A work
495 * queue will write the PHY to disable and clear the
496 * interrupt, and then reenable the irq line. */
497 disable_irq_nosync(irq);
498
499 schedule_work(&phydev->phy_queue);
500
501 return IRQ_HANDLED;
502}
503
504/* Enable the interrupts from the PHY side */
505int phy_enable_interrupts(struct phy_device *phydev)
506{ 466{
507 int err; 467 int err;
508 468
509 err = phy_clear_interrupt(phydev); 469 err = phy_disable_interrupts(phydev);
510 470
511 if (err < 0) 471 if (err)
512 return err; 472 phy_error(phydev);
513 473
514 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 474 free_irq(phydev->irq, phydev);
515 475
516 return err; 476 return err;
517} 477}
518EXPORT_SYMBOL(phy_enable_interrupts);
519 478
520/* Disable the PHY interrupts from the PHY side */ 479/* Disable the PHY interrupts from the PHY side */
521int phy_disable_interrupts(struct phy_device *phydev) 480static int phy_disable_interrupts(struct phy_device *phydev)
522{ 481{
523 int err; 482 int err;
524 483
@@ -541,140 +500,6 @@ phy_err:
541 500
542 return err; 501 return err;
543} 502}
544EXPORT_SYMBOL(phy_disable_interrupts);
545
546/* phy_start_interrupts
547 *
548 * description: Request the interrupt for the given PHY. If
549 * this fails, then we set irq to PHY_POLL.
550 * Otherwise, we enable the interrupts in the PHY.
551 * Returns 0 on success.
552 * This should only be called with a valid IRQ number.
553 */
554int phy_start_interrupts(struct phy_device *phydev)
555{
556 int err = 0;
557
558 INIT_WORK(&phydev->phy_queue, phy_change, phydev);
559
560 if (request_irq(phydev->irq, phy_interrupt,
561 SA_SHIRQ,
562 "phy_interrupt",
563 phydev) < 0) {
564 printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n",
565 phydev->bus->name,
566 phydev->irq);
567 phydev->irq = PHY_POLL;
568 return 0;
569 }
570
571 err = phy_enable_interrupts(phydev);
572
573 return err;
574}
575EXPORT_SYMBOL(phy_start_interrupts);
576
577int phy_stop_interrupts(struct phy_device *phydev)
578{
579 int err;
580
581 err = phy_disable_interrupts(phydev);
582
583 if (err)
584 phy_error(phydev);
585
586 free_irq(phydev->irq, phydev);
587
588 return err;
589}
590EXPORT_SYMBOL(phy_stop_interrupts);
591
592
593/* Scheduled by the phy_interrupt/timer to handle PHY changes */
594static void phy_change(void *data)
595{
596 int err;
597 struct phy_device *phydev = data;
598
599 err = phy_disable_interrupts(phydev);
600
601 if (err)
602 goto phy_err;
603
604 spin_lock(&phydev->lock);
605 if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
606 phydev->state = PHY_CHANGELINK;
607 spin_unlock(&phydev->lock);
608
609 enable_irq(phydev->irq);
610
611 /* Reenable interrupts */
612 err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
613
614 if (err)
615 goto irq_enable_err;
616
617 return;
618
619irq_enable_err:
620 disable_irq(phydev->irq);
621phy_err:
622 phy_error(phydev);
623}
624
625/* Bring down the PHY link, and stop checking the status. */
626void phy_stop(struct phy_device *phydev)
627{
628 spin_lock(&phydev->lock);
629
630 if (PHY_HALTED == phydev->state)
631 goto out_unlock;
632
633 if (phydev->irq != PHY_POLL) {
634 /* Clear any pending interrupts */
635 phy_clear_interrupt(phydev);
636
637 /* Disable PHY Interrupts */
638 phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
639 }
640
641 phydev->state = PHY_HALTED;
642
643out_unlock:
644 spin_unlock(&phydev->lock);
645}
646
647
648/* phy_start
649 *
650 * description: Indicates the attached device's readiness to
651 * handle PHY-related work. Used during startup to start the
652 * PHY, and after a call to phy_stop() to resume operation.
653 * Also used to indicate the MDIO bus has cleared an error
654 * condition.
655 */
656void phy_start(struct phy_device *phydev)
657{
658 spin_lock(&phydev->lock);
659
660 switch (phydev->state) {
661 case PHY_STARTING:
662 phydev->state = PHY_PENDING;
663 break;
664 case PHY_READY:
665 phydev->state = PHY_UP;
666 break;
667 case PHY_HALTED:
668 phydev->state = PHY_RESUMING;
669 default:
670 break;
671 }
672 spin_unlock(&phydev->lock);
673}
674EXPORT_SYMBOL(phy_stop);
675EXPORT_SYMBOL(phy_start);
676
677#endif /* CONFIG_PHYCONTROL */
678 503
679/* PHY timer which handles the state machine */ 504/* PHY timer which handles the state machine */
680static void phy_timer(unsigned long data) 505static void phy_timer(unsigned long data)
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index c11138330fed..c44d54f6310a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -124,133 +124,6 @@ void phy_prepare_link(struct phy_device *phydev,
124 phydev->adjust_link = handler; 124 phydev->adjust_link = handler;
125} 125}
126 126
127#ifdef CONFIG_PHYCONTROL
128/* phy_connect:
129 *
130 * description: Convenience function for connecting ethernet
131 * devices to PHY devices. The default behavior is for
132 * the PHY infrastructure to handle everything, and only notify
133 * the connected driver when the link status changes. If you
134 * don't want, or can't use the provided functionality, you may
135 * choose to call only the subset of functions which provide
136 * the desired functionality.
137 */
138struct phy_device * phy_connect(struct net_device *dev, const char *phy_id,
139 void (*handler)(struct net_device *), u32 flags)
140{
141 struct phy_device *phydev;
142
143 phydev = phy_attach(dev, phy_id, flags);
144
145 if (IS_ERR(phydev))
146 return phydev;
147
148 phy_prepare_link(phydev, handler);
149
150 phy_start_machine(phydev, NULL);
151
152 if (phydev->irq > 0)
153 phy_start_interrupts(phydev);
154
155 return phydev;
156}
157EXPORT_SYMBOL(phy_connect);
158
159void phy_disconnect(struct phy_device *phydev)
160{
161 if (phydev->irq > 0)
162 phy_stop_interrupts(phydev);
163
164 phy_stop_machine(phydev);
165
166 phydev->adjust_link = NULL;
167
168 phy_detach(phydev);
169}
170EXPORT_SYMBOL(phy_disconnect);
171
172#endif /* CONFIG_PHYCONTROL */
173
174/* phy_attach:
175 *
176 * description: Called by drivers to attach to a particular PHY
177 * device. The phy_device is found, and properly hooked up
178 * to the phy_driver. If no driver is attached, then the
179 * genphy_driver is used. The phy_device is given a ptr to
180 * the attaching device, and given a callback for link status
181 * change. The phy_device is returned to the attaching
182 * driver.
183 */
184static int phy_compare_id(struct device *dev, void *data)
185{
186 return strcmp((char *)data, dev->bus_id) ? 0 : 1;
187}
188
189struct phy_device *phy_attach(struct net_device *dev,
190 const char *phy_id, u32 flags)
191{
192 struct bus_type *bus = &mdio_bus_type;
193 struct phy_device *phydev;
194 struct device *d;
195
196 /* Search the list of PHY devices on the mdio bus for the
197 * PHY with the requested name */
198 d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id);
199
200 if (d) {
201 phydev = to_phy_device(d);
202 } else {
203 printk(KERN_ERR "%s not found\n", phy_id);
204 return ERR_PTR(-ENODEV);
205 }
206
207 /* Assume that if there is no driver, that it doesn't
208 * exist, and we should use the genphy driver. */
209 if (NULL == d->driver) {
210 int err;
211 down_write(&d->bus->subsys.rwsem);
212 d->driver = &genphy_driver.driver;
213
214 err = d->driver->probe(d);
215
216 if (err < 0)
217 return ERR_PTR(err);
218
219 device_bind_driver(d);
220 up_write(&d->bus->subsys.rwsem);
221 }
222
223 if (phydev->attached_dev) {
224 printk(KERN_ERR "%s: %s already attached\n",
225 dev->name, phy_id);
226 return ERR_PTR(-EBUSY);
227 }
228
229 phydev->attached_dev = dev;
230
231 phydev->dev_flags = flags;
232
233 return phydev;
234}
235EXPORT_SYMBOL(phy_attach);
236
237void phy_detach(struct phy_device *phydev)
238{
239 phydev->attached_dev = NULL;
240
241 /* If the device had no specific driver before (i.e. - it
242 * was using the generic driver), we unbind the device
243 * from the generic driver so that there's a chance a
244 * real driver could be loaded */
245 if (phydev->dev.driver == &genphy_driver.driver) {
246 down_write(&phydev->dev.bus->subsys.rwsem);
247 device_release_driver(&phydev->dev);
248 up_write(&phydev->dev.bus->subsys.rwsem);
249 }
250}
251EXPORT_SYMBOL(phy_detach);
252
253
254/* Generic PHY support and helper functions */ 127/* Generic PHY support and helper functions */
255 128
256/* genphy_config_advert 129/* genphy_config_advert
@@ -259,7 +132,7 @@ EXPORT_SYMBOL(phy_detach);
259 * after sanitizing the values to make sure we only advertise 132 * after sanitizing the values to make sure we only advertise
260 * what is supported 133 * what is supported
261 */ 134 */
262int genphy_config_advert(struct phy_device *phydev) 135static int genphy_config_advert(struct phy_device *phydev)
263{ 136{
264 u32 advertise; 137 u32 advertise;
265 int adv; 138 int adv;
@@ -317,7 +190,6 @@ int genphy_config_advert(struct phy_device *phydev)
317 190
318 return adv; 191 return adv;
319} 192}
320EXPORT_SYMBOL(genphy_config_advert);
321 193
322/* genphy_setup_forced 194/* genphy_setup_forced
323 * 195 *