diff options
| -rw-r--r-- | drivers/net/phy/phy_device.c | 118 | ||||
| -rw-r--r-- | include/linux/phy.h | 5 |
2 files changed, 90 insertions, 33 deletions
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9352ca8fa2c..a2ece89622d 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -292,6 +292,33 @@ void phy_prepare_link(struct phy_device *phydev, | |||
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | /** | 294 | /** |
| 295 | * phy_connect_direct - connect an ethernet device to a specific phy_device | ||
| 296 | * @dev: the network device to connect | ||
| 297 | * @phydev: the pointer to the phy device | ||
| 298 | * @handler: callback function for state change notifications | ||
| 299 | * @flags: PHY device's dev_flags | ||
| 300 | * @interface: PHY device's interface | ||
| 301 | */ | ||
| 302 | int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, | ||
| 303 | void (*handler)(struct net_device *), u32 flags, | ||
| 304 | phy_interface_t interface) | ||
| 305 | { | ||
| 306 | int rc; | ||
| 307 | |||
| 308 | rc = phy_attach_direct(dev, phydev, flags, interface); | ||
| 309 | if (rc) | ||
| 310 | return rc; | ||
| 311 | |||
| 312 | phy_prepare_link(phydev, handler); | ||
| 313 | phy_start_machine(phydev, NULL); | ||
| 314 | if (phydev->irq > 0) | ||
| 315 | phy_start_interrupts(phydev); | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | EXPORT_SYMBOL(phy_connect_direct); | ||
| 320 | |||
| 321 | /** | ||
| 295 | * phy_connect - connect an ethernet device to a PHY device | 322 | * phy_connect - connect an ethernet device to a PHY device |
| 296 | * @dev: the network device to connect | 323 | * @dev: the network device to connect |
| 297 | * @bus_id: the id string of the PHY device to connect | 324 | * @bus_id: the id string of the PHY device to connect |
| @@ -312,18 +339,21 @@ struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, | |||
| 312 | phy_interface_t interface) | 339 | phy_interface_t interface) |
| 313 | { | 340 | { |
| 314 | struct phy_device *phydev; | 341 | struct phy_device *phydev; |
| 342 | struct device *d; | ||
| 343 | int rc; | ||
| 315 | 344 | ||
| 316 | phydev = phy_attach(dev, bus_id, flags, interface); | 345 | /* Search the list of PHY devices on the mdio bus for the |
| 317 | 346 | * PHY with the requested name */ | |
| 318 | if (IS_ERR(phydev)) | 347 | d = bus_find_device_by_name(&mdio_bus_type, NULL, bus_id); |
| 319 | return phydev; | 348 | if (!d) { |
| 320 | 349 | pr_err("PHY %s not found\n", bus_id); | |
| 321 | phy_prepare_link(phydev, handler); | 350 | return ERR_PTR(-ENODEV); |
| 322 | 351 | } | |
| 323 | phy_start_machine(phydev, NULL); | 352 | phydev = to_phy_device(d); |
| 324 | 353 | ||
| 325 | if (phydev->irq > 0) | 354 | rc = phy_connect_direct(dev, phydev, handler, flags, interface); |
| 326 | phy_start_interrupts(phydev); | 355 | if (rc) |
| 356 | return ERR_PTR(rc); | ||
| 327 | 357 | ||
| 328 | return phydev; | 358 | return phydev; |
| 329 | } | 359 | } |
| @@ -347,9 +377,9 @@ void phy_disconnect(struct phy_device *phydev) | |||
| 347 | EXPORT_SYMBOL(phy_disconnect); | 377 | EXPORT_SYMBOL(phy_disconnect); |
| 348 | 378 | ||
| 349 | /** | 379 | /** |
| 350 | * phy_attach - attach a network device to a particular PHY device | 380 | * phy_attach_direct - attach a network device to a given PHY device pointer |
| 351 | * @dev: network device to attach | 381 | * @dev: network device to attach |
| 352 | * @bus_id: PHY device to attach | 382 | * @phydev: Pointer to phy_device to attach |
| 353 | * @flags: PHY device's dev_flags | 383 | * @flags: PHY device's dev_flags |
| 354 | * @interface: PHY device's interface | 384 | * @interface: PHY device's interface |
| 355 | * | 385 | * |
| @@ -360,22 +390,10 @@ EXPORT_SYMBOL(phy_disconnect); | |||
| 360 | * the attaching device, and given a callback for link status | 390 | * the attaching device, and given a callback for link status |
| 361 | * change. The phy_device is returned to the attaching driver. | 391 | * change. The phy_device is returned to the attaching driver. |
| 362 | */ | 392 | */ |
| 363 | struct phy_device *phy_attach(struct net_device *dev, | 393 | int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, |
| 364 | const char *bus_id, u32 flags, phy_interface_t interface) | 394 | u32 flags, phy_interface_t interface) |
| 365 | { | 395 | { |
| 366 | struct bus_type *bus = &mdio_bus_type; | 396 | struct device *d = &phydev->dev; |
| 367 | struct phy_device *phydev; | ||
| 368 | struct device *d; | ||
| 369 | |||
| 370 | /* Search the list of PHY devices on the mdio bus for the | ||
| 371 | * PHY with the requested name */ | ||
| 372 | d = bus_find_device_by_name(bus, NULL, bus_id); | ||
| 373 | if (d) { | ||
| 374 | phydev = to_phy_device(d); | ||
| 375 | } else { | ||
| 376 | printk(KERN_ERR "%s not found\n", bus_id); | ||
| 377 | return ERR_PTR(-ENODEV); | ||
| 378 | } | ||
| 379 | 397 | ||
| 380 | /* Assume that if there is no driver, that it doesn't | 398 | /* Assume that if there is no driver, that it doesn't |
| 381 | * exist, and we should use the genphy driver. */ | 399 | * exist, and we should use the genphy driver. */ |
| @@ -388,13 +406,12 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
| 388 | err = device_bind_driver(d); | 406 | err = device_bind_driver(d); |
| 389 | 407 | ||
| 390 | if (err) | 408 | if (err) |
| 391 | return ERR_PTR(err); | 409 | return err; |
| 392 | } | 410 | } |
| 393 | 411 | ||
| 394 | if (phydev->attached_dev) { | 412 | if (phydev->attached_dev) { |
| 395 | printk(KERN_ERR "%s: %s already attached\n", | 413 | dev_err(&dev->dev, "PHY already attached\n"); |
| 396 | dev->name, bus_id); | 414 | return -EBUSY; |
| 397 | return ERR_PTR(-EBUSY); | ||
| 398 | } | 415 | } |
| 399 | 416 | ||
| 400 | phydev->attached_dev = dev; | 417 | phydev->attached_dev = dev; |
| @@ -412,13 +429,48 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
| 412 | err = phy_scan_fixups(phydev); | 429 | err = phy_scan_fixups(phydev); |
| 413 | 430 | ||
| 414 | if (err < 0) | 431 | if (err < 0) |
| 415 | return ERR_PTR(err); | 432 | return err; |
| 416 | 433 | ||
| 417 | err = phydev->drv->config_init(phydev); | 434 | err = phydev->drv->config_init(phydev); |
| 418 | 435 | ||
| 419 | if (err < 0) | 436 | if (err < 0) |
| 420 | return ERR_PTR(err); | 437 | return err; |
| 438 | } | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | EXPORT_SYMBOL(phy_attach_direct); | ||
| 443 | |||
| 444 | /** | ||
| 445 | * phy_attach - attach a network device to a particular PHY device | ||
| 446 | * @dev: network device to attach | ||
| 447 | * @bus_id: Bus ID of PHY device to attach | ||
| 448 | * @flags: PHY device's dev_flags | ||
| 449 | * @interface: PHY device's interface | ||
| 450 | * | ||
| 451 | * Description: Same as phy_attach_direct() except that a PHY bus_id | ||
| 452 | * string is passed instead of a pointer to a struct phy_device. | ||
| 453 | */ | ||
| 454 | struct phy_device *phy_attach(struct net_device *dev, | ||
| 455 | const char *bus_id, u32 flags, phy_interface_t interface) | ||
| 456 | { | ||
| 457 | struct bus_type *bus = &mdio_bus_type; | ||
| 458 | struct phy_device *phydev; | ||
| 459 | struct device *d; | ||
| 460 | int rc; | ||
| 461 | |||
| 462 | /* Search the list of PHY devices on the mdio bus for the | ||
| 463 | * PHY with the requested name */ | ||
| 464 | d = bus_find_device_by_name(bus, NULL, bus_id); | ||
| 465 | if (!d) { | ||
| 466 | pr_err("PHY %s not found\n", bus_id); | ||
| 467 | return ERR_PTR(-ENODEV); | ||
| 421 | } | 468 | } |
| 469 | phydev = to_phy_device(d); | ||
| 470 | |||
| 471 | rc = phy_attach_direct(dev, phydev, flags, interface); | ||
| 472 | if (rc) | ||
| 473 | return ERR_PTR(rc); | ||
| 422 | 474 | ||
| 423 | return phydev; | 475 | return phydev; |
| 424 | } | 476 | } |
diff --git a/include/linux/phy.h b/include/linux/phy.h index bf0b5f112dc..c216e4e503b 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
| @@ -447,8 +447,13 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); | |||
| 447 | int phy_device_register(struct phy_device *phy); | 447 | int phy_device_register(struct phy_device *phy); |
| 448 | int phy_clear_interrupt(struct phy_device *phydev); | 448 | int phy_clear_interrupt(struct phy_device *phydev); |
| 449 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); | 449 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); |
| 450 | int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, | ||
| 451 | u32 flags, phy_interface_t interface); | ||
| 450 | struct phy_device * phy_attach(struct net_device *dev, | 452 | struct phy_device * phy_attach(struct net_device *dev, |
| 451 | const char *bus_id, u32 flags, phy_interface_t interface); | 453 | const char *bus_id, u32 flags, phy_interface_t interface); |
| 454 | int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, | ||
| 455 | void (*handler)(struct net_device *), u32 flags, | ||
| 456 | phy_interface_t interface); | ||
| 452 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, | 457 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, |
| 453 | void (*handler)(struct net_device *), u32 flags, | 458 | void (*handler)(struct net_device *), u32 flags, |
| 454 | phy_interface_t interface); | 459 | phy_interface_t interface); |
