Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] PHY Layer fixup

This patch adds back the code that was taken out, thus re-enabling:

* The PHY Layer to initialize without crashing
* Drivers to actually connect to PHYs
* The entire PHY Control Layer

This patch is used by the gianfar driver, and other drivers which are in
development.

Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>

authored by

Andy Fleming and committed by
Jeff Garzik
e1393456 86f0cd50

+510 -102
+8
drivers/net/phy/Kconfig
··· 12 12 devices. This option provides infrastructure for 13 13 managing PHY devices. 14 14 15 + config 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 + 15 23 comment "MII PHY device drivers" 16 24 depends on PHYLIB 17 25
+6 -5
drivers/net/phy/Makefile
··· 2 2 3 3 libphy-objs := phy.o phy_device.o mdio_bus.o 4 4 5 - obj-$(CONFIG_MARVELL_PHY) += libphy.o marvell.o 6 - obj-$(CONFIG_DAVICOM_PHY) += libphy.o davicom.o 7 - obj-$(CONFIG_CICADA_PHY) += libphy.o cicada.o 8 - obj-$(CONFIG_LXT_PHY) += libphy.o lxt.o 9 - obj-$(CONFIG_QSEMI_PHY) += libphy.o qsemi.o 5 + obj-$(CONFIG_PHYLIB) += libphy.o 6 + obj-$(CONFIG_MARVELL_PHY) += marvell.o 7 + obj-$(CONFIG_DAVICOM_PHY) += davicom.o 8 + obj-$(CONFIG_CICADA_PHY) += cicada.o 9 + obj-$(CONFIG_LXT_PHY) += lxt.o 10 + obj-$(CONFIG_QSEMI_PHY) += qsemi.o
+78 -1
drivers/net/phy/mdio_bus.c
··· 38 38 #include <asm/irq.h> 39 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 + */ 46 + int 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 + } 100 + EXPORT_SYMBOL(mdiobus_register); 101 + 102 + void 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 + } 113 + EXPORT_SYMBOL(mdiobus_unregister); 114 + 41 115 /* mdio_bus_match 42 116 * 43 117 * description: Given a PHY device, and a PHY driver, return 1 if ··· 170 96 return bus_register(&mdio_bus_type); 171 97 } 172 98 173 - 99 + void __exit mdio_bus_exit(void) 100 + { 101 + bus_unregister(&mdio_bus_type); 102 + }
+253 -72
drivers/net/phy/phy.c
··· 39 39 #include <asm/irq.h> 40 40 #include <asm/uaccess.h> 41 41 42 - static void phy_timer(unsigned long data); 43 - static int phy_disable_interrupts(struct phy_device *phydev); 44 - static void phy_sanitize_settings(struct phy_device *phydev); 45 - static int phy_stop_interrupts(struct phy_device *phydev); 42 + /* Convenience function to print out the current phy status 43 + */ 44 + void phy_print_status(struct phy_device *phydev) 45 + { 46 + pr_info("%s: Link is %s", phydev->dev.bus_id, 47 + phydev->link ? "Up" : "Down"); 48 + if (phydev->link) 49 + printk(" - %d/%s", phydev->speed, 50 + DUPLEX_FULL == phydev->duplex ? 51 + "Full" : "Half"); 52 + 53 + printk("\n"); 54 + } 55 + EXPORT_SYMBOL(phy_print_status); 46 56 47 57 48 58 /* Convenience functions for reading/writing a given PHY ··· 122 112 retval = phy_read(phydev, MII_BMSR); 123 113 124 114 return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE); 125 - } 126 - 127 - /* phy_start_aneg 128 - * 129 - * description: Calls the PHY driver's config_aneg, and then 130 - * sets the PHY state to PHY_AN if auto-negotiation is enabled, 131 - * and to PHY_FORCING if auto-negotiation is disabled. Unless 132 - * the PHY is currently HALTED. 133 - */ 134 - static int phy_start_aneg(struct phy_device *phydev) 135 - { 136 - int err; 137 - 138 - spin_lock(&phydev->lock); 139 - 140 - if (AUTONEG_DISABLE == phydev->autoneg) 141 - phy_sanitize_settings(phydev); 142 - 143 - err = phydev->drv->config_aneg(phydev); 144 - 145 - if (err < 0) 146 - goto out_unlock; 147 - 148 - if (phydev->state != PHY_HALTED) { 149 - if (AUTONEG_ENABLE == phydev->autoneg) { 150 - phydev->state = PHY_AN; 151 - phydev->link_timeout = PHY_AN_TIMEOUT; 152 - } else { 153 - phydev->state = PHY_FORCING; 154 - phydev->link_timeout = PHY_FORCE_TIMEOUT; 155 - } 156 - } 157 - 158 - out_unlock: 159 - spin_unlock(&phydev->lock); 160 - return err; 161 115 } 162 116 163 117 /* A structure for mapping a particular speed and duplex ··· 215 241 * duplexes. Drop down by one in this order: 1000/FULL, 216 242 * 1000/HALF, 100/FULL, 100/HALF, 10/FULL, 10/HALF 217 243 */ 218 - static void phy_sanitize_settings(struct phy_device *phydev) 244 + void phy_sanitize_settings(struct phy_device *phydev) 219 245 { 220 246 u32 features = phydev->supported; 221 247 int idx; ··· 230 256 phydev->speed = settings[idx].speed; 231 257 phydev->duplex = settings[idx].duplex; 232 258 } 233 - 234 - /* phy_force_reduction 235 - * 236 - * description: Reduces the speed/duplex settings by 237 - * one notch. The order is so: 238 - * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 239 - * 10/FULL, 10/HALF. The function bottoms out at 10/HALF. 240 - */ 241 - static void phy_force_reduction(struct phy_device *phydev) 242 - { 243 - int idx; 244 - 245 - idx = phy_find_setting(phydev->speed, phydev->duplex); 246 - 247 - idx++; 248 - 249 - idx = phy_find_valid(idx, phydev->supported); 250 - 251 - phydev->speed = settings[idx].speed; 252 - phydev->duplex = settings[idx].duplex; 253 - 254 - pr_info("Trying %d/%s\n", phydev->speed, 255 - DUPLEX_FULL == phydev->duplex ? 256 - "FULL" : "HALF"); 257 - } 259 + EXPORT_SYMBOL(phy_sanitize_settings); 258 260 259 261 /* phy_ethtool_sset: 260 262 * A generic ethtool sset function. Handles all the details ··· 241 291 * - phy_start_aneg() will make sure forced settings are sane, and 242 292 * choose the next best ones from the ones selected, so we don't 243 293 * care if ethtool tries to give us bad values 294 + * 295 + * A note about the PHYCONTROL Layer. If you turn off 296 + * CONFIG_PHYCONTROL, you will need to read the PHY status 297 + * registers after this function completes, and update your 298 + * controller manually. 244 299 */ 245 300 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd) 246 301 { ··· 361 406 return 0; 362 407 } 363 408 409 + /* phy_start_aneg 410 + * 411 + * description: Sanitizes the settings (if we're not 412 + * autonegotiating them), and then calls the driver's 413 + * config_aneg function. If the PHYCONTROL Layer is operating, 414 + * we change the state to reflect the beginning of 415 + * Auto-negotiation or forcing. 416 + */ 417 + int phy_start_aneg(struct phy_device *phydev) 418 + { 419 + int err; 420 + 421 + spin_lock(&phydev->lock); 422 + 423 + if (AUTONEG_DISABLE == phydev->autoneg) 424 + phy_sanitize_settings(phydev); 425 + 426 + err = phydev->drv->config_aneg(phydev); 427 + 428 + #ifdef CONFIG_PHYCONTROL 429 + if (err < 0) 430 + goto out_unlock; 431 + 432 + if (phydev->state != PHY_HALTED) { 433 + if (AUTONEG_ENABLE == phydev->autoneg) { 434 + phydev->state = PHY_AN; 435 + phydev->link_timeout = PHY_AN_TIMEOUT; 436 + } else { 437 + phydev->state = PHY_FORCING; 438 + phydev->link_timeout = PHY_FORCE_TIMEOUT; 439 + } 440 + } 441 + 442 + out_unlock: 443 + #endif 444 + spin_unlock(&phydev->lock); 445 + return err; 446 + } 447 + EXPORT_SYMBOL(phy_start_aneg); 448 + 449 + 450 + #ifdef CONFIG_PHYCONTROL 451 + static void phy_change(void *data); 452 + static void phy_timer(unsigned long data); 453 + 364 454 /* phy_start_machine: 365 455 * 366 456 * description: The PHY infrastructure can run a state machine ··· 448 448 phydev->adjust_state = NULL; 449 449 } 450 450 451 + /* phy_force_reduction 452 + * 453 + * description: Reduces the speed/duplex settings by 454 + * one notch. The order is so: 455 + * 1000/FULL, 1000/HALF, 100/FULL, 100/HALF, 456 + * 10/FULL, 10/HALF. The function bottoms out at 10/HALF. 457 + */ 458 + static void phy_force_reduction(struct phy_device *phydev) 459 + { 460 + int idx; 461 + 462 + idx = phy_find_setting(phydev->speed, phydev->duplex); 463 + 464 + idx++; 465 + 466 + idx = phy_find_valid(idx, phydev->supported); 467 + 468 + phydev->speed = settings[idx].speed; 469 + phydev->duplex = settings[idx].duplex; 470 + 471 + pr_info("Trying %d/%s\n", phydev->speed, 472 + DUPLEX_FULL == phydev->duplex ? 473 + "FULL" : "HALF"); 474 + } 475 + 476 + 451 477 /* phy_error: 452 478 * 453 479 * Moves the PHY to the HALTED state in response to a read ··· 488 462 spin_unlock(&phydev->lock); 489 463 } 490 464 491 - static int phy_stop_interrupts(struct phy_device *phydev) 465 + /* phy_interrupt 466 + * 467 + * description: When a PHY interrupt occurs, the handler disables 468 + * interrupts, and schedules a work task to clear the interrupt. 469 + */ 470 + static irqreturn_t phy_interrupt(int irq, void *phy_dat, struct pt_regs *regs) 471 + { 472 + struct phy_device *phydev = phy_dat; 473 + 474 + /* The MDIO bus is not allowed to be written in interrupt 475 + * context, so we need to disable the irq here. A work 476 + * queue will write the PHY to disable and clear the 477 + * interrupt, and then reenable the irq line. */ 478 + disable_irq_nosync(irq); 479 + 480 + schedule_work(&phydev->phy_queue); 481 + 482 + return IRQ_HANDLED; 483 + } 484 + 485 + /* Enable the interrupts from the PHY side */ 486 + int phy_enable_interrupts(struct phy_device *phydev) 492 487 { 493 488 int err; 494 489 495 - err = phy_disable_interrupts(phydev); 490 + err = phy_clear_interrupt(phydev); 496 491 497 - if (err) 498 - phy_error(phydev); 492 + if (err < 0) 493 + return err; 499 494 500 - free_irq(phydev->irq, phydev); 495 + err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 501 496 502 497 return err; 503 498 } 499 + EXPORT_SYMBOL(phy_enable_interrupts); 504 500 505 501 /* Disable the PHY interrupts from the PHY side */ 506 - static int phy_disable_interrupts(struct phy_device *phydev) 502 + int phy_disable_interrupts(struct phy_device *phydev) 507 503 { 508 504 int err; 509 505 ··· 548 500 549 501 return err; 550 502 } 503 + EXPORT_SYMBOL(phy_disable_interrupts); 504 + 505 + /* phy_start_interrupts 506 + * 507 + * description: Request the interrupt for the given PHY. If 508 + * this fails, then we set irq to PHY_POLL. 509 + * Otherwise, we enable the interrupts in the PHY. 510 + * Returns 0 on success. 511 + * This should only be called with a valid IRQ number. 512 + */ 513 + int phy_start_interrupts(struct phy_device *phydev) 514 + { 515 + int err = 0; 516 + 517 + INIT_WORK(&phydev->phy_queue, phy_change, phydev); 518 + 519 + if (request_irq(phydev->irq, phy_interrupt, 520 + SA_SHIRQ, 521 + "phy_interrupt", 522 + phydev) < 0) { 523 + printk(KERN_WARNING "%s: Can't get IRQ %d (PHY)\n", 524 + phydev->bus->name, 525 + phydev->irq); 526 + phydev->irq = PHY_POLL; 527 + return 0; 528 + } 529 + 530 + err = phy_enable_interrupts(phydev); 531 + 532 + return err; 533 + } 534 + EXPORT_SYMBOL(phy_start_interrupts); 535 + 536 + int phy_stop_interrupts(struct phy_device *phydev) 537 + { 538 + int err; 539 + 540 + err = phy_disable_interrupts(phydev); 541 + 542 + if (err) 543 + phy_error(phydev); 544 + 545 + free_irq(phydev->irq, phydev); 546 + 547 + return err; 548 + } 549 + EXPORT_SYMBOL(phy_stop_interrupts); 550 + 551 + 552 + /* Scheduled by the phy_interrupt/timer to handle PHY changes */ 553 + static void phy_change(void *data) 554 + { 555 + int err; 556 + struct phy_device *phydev = data; 557 + 558 + err = phy_disable_interrupts(phydev); 559 + 560 + if (err) 561 + goto phy_err; 562 + 563 + spin_lock(&phydev->lock); 564 + if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) 565 + phydev->state = PHY_CHANGELINK; 566 + spin_unlock(&phydev->lock); 567 + 568 + enable_irq(phydev->irq); 569 + 570 + /* Reenable interrupts */ 571 + err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); 572 + 573 + if (err) 574 + goto irq_enable_err; 575 + 576 + return; 577 + 578 + irq_enable_err: 579 + disable_irq(phydev->irq); 580 + phy_err: 581 + phy_error(phydev); 582 + } 583 + 584 + /* Bring down the PHY link, and stop checking the status. */ 585 + void phy_stop(struct phy_device *phydev) 586 + { 587 + spin_lock(&phydev->lock); 588 + 589 + if (PHY_HALTED == phydev->state) 590 + goto out_unlock; 591 + 592 + if (phydev->irq != PHY_POLL) { 593 + /* Clear any pending interrupts */ 594 + phy_clear_interrupt(phydev); 595 + 596 + /* Disable PHY Interrupts */ 597 + phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); 598 + } 599 + 600 + phydev->state = PHY_HALTED; 601 + 602 + out_unlock: 603 + spin_unlock(&phydev->lock); 604 + } 605 + 606 + 607 + /* phy_start 608 + * 609 + * description: Indicates the attached device's readiness to 610 + * handle PHY-related work. Used during startup to start the 611 + * PHY, and after a call to phy_stop() to resume operation. 612 + * Also used to indicate the MDIO bus has cleared an error 613 + * condition. 614 + */ 615 + void phy_start(struct phy_device *phydev) 616 + { 617 + spin_lock(&phydev->lock); 618 + 619 + switch (phydev->state) { 620 + case PHY_STARTING: 621 + phydev->state = PHY_PENDING; 622 + break; 623 + case PHY_READY: 624 + phydev->state = PHY_UP; 625 + break; 626 + case PHY_HALTED: 627 + phydev->state = PHY_RESUMING; 628 + default: 629 + break; 630 + } 631 + spin_unlock(&phydev->lock); 632 + } 633 + EXPORT_SYMBOL(phy_stop); 634 + EXPORT_SYMBOL(phy_start); 551 635 552 636 /* PHY timer which handles the state machine */ 553 637 static void phy_timer(unsigned long data) ··· 868 688 mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ); 869 689 } 870 690 691 + #endif /* CONFIG_PHYCONTROL */
+148 -24
drivers/net/phy/phy_device.c
··· 39 39 #include <asm/irq.h> 40 40 #include <asm/uaccess.h> 41 41 42 - static int genphy_config_init(struct phy_device *phydev); 43 - 44 - static struct phy_driver genphy_driver = { 45 - .phy_id = 0xffffffff, 46 - .phy_id_mask = 0xffffffff, 47 - .name = "Generic PHY", 48 - .config_init = genphy_config_init, 49 - .features = 0, 50 - .config_aneg = genphy_config_aneg, 51 - .read_status = genphy_read_status, 52 - .driver = {.owner = THIS_MODULE, }, 53 - }; 42 + static struct phy_driver genphy_driver; 43 + extern int mdio_bus_init(void); 44 + extern void mdio_bus_exit(void); 54 45 55 46 /* get_phy_device 56 47 * ··· 101 110 return dev; 102 111 } 103 112 113 + #ifdef CONFIG_PHYCONTROL 104 114 /* phy_prepare_link: 105 115 * 106 116 * description: Tells the PHY infrastructure to handle the ··· 116 124 phydev->adjust_link = handler; 117 125 } 118 126 127 + /* phy_connect: 128 + * 129 + * description: Convenience function for connecting ethernet 130 + * devices to PHY devices. The default behavior is for 131 + * the PHY infrastructure to handle everything, and only notify 132 + * the connected driver when the link status changes. If you 133 + * don't want, or can't use the provided functionality, you may 134 + * choose to call only the subset of functions which provide 135 + * the desired functionality. 136 + */ 137 + struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, 138 + void (*handler)(struct net_device *), u32 flags) 139 + { 140 + struct phy_device *phydev; 141 + 142 + phydev = phy_attach(dev, phy_id, flags); 143 + 144 + if (IS_ERR(phydev)) 145 + return phydev; 146 + 147 + phy_prepare_link(phydev, handler); 148 + 149 + phy_start_machine(phydev, NULL); 150 + 151 + if (phydev->irq > 0) 152 + phy_start_interrupts(phydev); 153 + 154 + return phydev; 155 + } 156 + EXPORT_SYMBOL(phy_connect); 157 + 158 + void phy_disconnect(struct phy_device *phydev) 159 + { 160 + if (phydev->irq > 0) 161 + phy_stop_interrupts(phydev); 162 + 163 + phy_stop_machine(phydev); 164 + 165 + phydev->adjust_link = NULL; 166 + 167 + phy_detach(phydev); 168 + } 169 + EXPORT_SYMBOL(phy_disconnect); 170 + 171 + #endif /* CONFIG_PHYCONTROL */ 172 + 173 + /* phy_attach: 174 + * 175 + * description: Called by drivers to attach to a particular PHY 176 + * device. The phy_device is found, and properly hooked up 177 + * to the phy_driver. If no driver is attached, then the 178 + * genphy_driver is used. The phy_device is given a ptr to 179 + * the attaching device, and given a callback for link status 180 + * change. The phy_device is returned to the attaching 181 + * driver. 182 + */ 183 + static int phy_compare_id(struct device *dev, void *data) 184 + { 185 + return strcmp((char *)data, dev->bus_id) ? 0 : 1; 186 + } 187 + 188 + struct phy_device *phy_attach(struct net_device *dev, 189 + const char *phy_id, u32 flags) 190 + { 191 + struct bus_type *bus = &mdio_bus_type; 192 + struct phy_device *phydev; 193 + struct device *d; 194 + 195 + /* Search the list of PHY devices on the mdio bus for the 196 + * PHY with the requested name */ 197 + d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id); 198 + 199 + if (d) { 200 + phydev = to_phy_device(d); 201 + } else { 202 + printk(KERN_ERR "%s not found\n", phy_id); 203 + return ERR_PTR(-ENODEV); 204 + } 205 + 206 + /* Assume that if there is no driver, that it doesn't 207 + * exist, and we should use the genphy driver. */ 208 + if (NULL == d->driver) { 209 + int err; 210 + down_write(&d->bus->subsys.rwsem); 211 + d->driver = &genphy_driver.driver; 212 + 213 + err = d->driver->probe(d); 214 + 215 + if (err < 0) 216 + return ERR_PTR(err); 217 + 218 + device_bind_driver(d); 219 + up_write(&d->bus->subsys.rwsem); 220 + } 221 + 222 + if (phydev->attached_dev) { 223 + printk(KERN_ERR "%s: %s already attached\n", 224 + dev->name, phy_id); 225 + return ERR_PTR(-EBUSY); 226 + } 227 + 228 + phydev->attached_dev = dev; 229 + 230 + phydev->dev_flags = flags; 231 + 232 + return phydev; 233 + } 234 + EXPORT_SYMBOL(phy_attach); 235 + 236 + void phy_detach(struct phy_device *phydev) 237 + { 238 + phydev->attached_dev = NULL; 239 + 240 + /* If the device had no specific driver before (i.e. - it 241 + * was using the generic driver), we unbind the device 242 + * from the generic driver so that there's a chance a 243 + * real driver could be loaded */ 244 + if (phydev->dev.driver == &genphy_driver.driver) { 245 + down_write(&phydev->dev.bus->subsys.rwsem); 246 + device_release_driver(&phydev->dev); 247 + up_write(&phydev->dev.bus->subsys.rwsem); 248 + } 249 + } 250 + EXPORT_SYMBOL(phy_detach); 251 + 252 + 119 253 /* Generic PHY support and helper functions */ 120 254 121 255 /* genphy_config_advert ··· 250 132 * after sanitizing the values to make sure we only advertise 251 133 * what is supported 252 134 */ 253 - static int genphy_config_advert(struct phy_device *phydev) 135 + int genphy_config_advert(struct phy_device *phydev) 254 136 { 255 137 u32 advertise; 256 138 int adv; ··· 308 190 309 191 return adv; 310 192 } 193 + EXPORT_SYMBOL(genphy_config_advert); 311 194 312 195 /* genphy_setup_forced 313 196 * ··· 660 541 } 661 542 EXPORT_SYMBOL(phy_driver_unregister); 662 543 544 + static struct phy_driver genphy_driver = { 545 + .phy_id = 0xffffffff, 546 + .phy_id_mask = 0xffffffff, 547 + .name = "Generic PHY", 548 + .config_init = genphy_config_init, 549 + .features = 0, 550 + .config_aneg = genphy_config_aneg, 551 + .read_status = genphy_read_status, 552 + .driver = {.owner= THIS_MODULE, }, 553 + }; 663 554 664 555 static int __init phy_init(void) 665 556 { 666 557 int rc; 667 - extern int mdio_bus_init(void); 668 - 669 - rc = phy_driver_register(&genphy_driver); 670 - if (rc) 671 - goto out; 672 558 673 559 rc = mdio_bus_init(); 674 560 if (rc) 675 - goto out_unreg; 561 + return rc; 676 562 677 - return 0; 563 + rc = phy_driver_register(&genphy_driver); 564 + if (rc) 565 + mdio_bus_exit(); 678 566 679 - out_unreg: 680 - phy_driver_unregister(&genphy_driver); 681 - out: 682 567 return rc; 683 568 } 684 569 685 570 static void __exit phy_exit(void) 686 571 { 687 572 phy_driver_unregister(&genphy_driver); 573 + mdio_bus_exit(); 688 574 } 689 575 690 - module_init(phy_init); 576 + subsys_initcall(phy_init); 691 577 module_exit(phy_exit);
+17
include/linux/phy.h
··· 334 334 struct phy_device* get_phy_device(struct mii_bus *bus, int addr); 335 335 int phy_clear_interrupt(struct phy_device *phydev); 336 336 int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); 337 + struct phy_device * phy_attach(struct net_device *dev, 338 + const char *phy_id, u32 flags); 339 + struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, 340 + void (*handler)(struct net_device *), u32 flags); 341 + void phy_disconnect(struct phy_device *phydev); 342 + void phy_detach(struct phy_device *phydev); 343 + void phy_start(struct phy_device *phydev); 344 + void phy_stop(struct phy_device *phydev); 345 + int phy_start_aneg(struct phy_device *phydev); 346 + 347 + int mdiobus_register(struct mii_bus *bus); 348 + void mdiobus_unregister(struct mii_bus *bus); 349 + void phy_sanitize_settings(struct phy_device *phydev); 350 + int phy_stop_interrupts(struct phy_device *phydev); 337 351 338 352 static inline int phy_read_status(struct phy_device *phydev) { 339 353 return phydev->drv->read_status(phydev); 340 354 } 341 355 356 + int genphy_config_advert(struct phy_device *phydev); 342 357 int genphy_setup_forced(struct phy_device *phydev); 343 358 int genphy_restart_aneg(struct phy_device *phydev); 344 359 int genphy_config_aneg(struct phy_device *phydev); ··· 370 355 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); 371 356 int phy_mii_ioctl(struct phy_device *phydev, 372 357 struct mii_ioctl_data *mii_data, int cmd); 358 + int phy_start_interrupts(struct phy_device *phydev); 359 + void phy_print_status(struct phy_device *phydev); 373 360 374 361 extern struct bus_type mdio_bus_type; 375 362 #endif /* __PHY_H */