aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2013-05-19 18:53:43 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-20 17:13:08 -0400
commit5ea94e7686a3aa04cc0d01a2d8bd3d0292b3f592 (patch)
treec698dd2f66fc211a06deab14696ed7d998616b0f
parent2c7b49212a86f13697281a4dace2cb96aec71d6b (diff)
phy: add phy_mac_interrupt() to use with PHY_IGNORE_INTERRUPT
There is currently no way for an Ethernet MAC driver servicing PHY link interrupts to notify this to the PHY state machine without defining its own state machine. Since most drivers are not so special, introduce a helper: phy_mac_interrupt() which can be called from a link up/down interrupt routine to update the PHY state machine. To avoid code duplication some refactoring has been done to expose the workqueue and its corresponding callback internally. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/phy.c14
-rw-r--r--drivers/net/phy/phy_device.c1
-rw-r--r--include/linux/phy.h2
3 files changed, 12 insertions, 5 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3bcf0994d3ba..2d28a0ef4572 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -419,8 +419,6 @@ out_unlock:
419EXPORT_SYMBOL(phy_start_aneg); 419EXPORT_SYMBOL(phy_start_aneg);
420 420
421 421
422static void phy_change(struct work_struct *work);
423
424/** 422/**
425 * phy_start_machine - start PHY state machine tracking 423 * phy_start_machine - start PHY state machine tracking
426 * @phydev: the phy_device struct 424 * @phydev: the phy_device struct
@@ -565,8 +563,6 @@ int phy_start_interrupts(struct phy_device *phydev)
565{ 563{
566 int err = 0; 564 int err = 0;
567 565
568 INIT_WORK(&phydev->phy_queue, phy_change);
569
570 atomic_set(&phydev->irq_disable, 0); 566 atomic_set(&phydev->irq_disable, 0);
571 if (request_irq(phydev->irq, phy_interrupt, 567 if (request_irq(phydev->irq, phy_interrupt,
572 IRQF_SHARED, 568 IRQF_SHARED,
@@ -623,7 +619,7 @@ EXPORT_SYMBOL(phy_stop_interrupts);
623 * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes 619 * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
624 * @work: work_struct that describes the work to be done 620 * @work: work_struct that describes the work to be done
625 */ 621 */
626static void phy_change(struct work_struct *work) 622void phy_change(struct work_struct *work)
627{ 623{
628 int err; 624 int err;
629 struct phy_device *phydev = 625 struct phy_device *phydev =
@@ -922,6 +918,14 @@ void phy_state_machine(struct work_struct *work)
922 schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ); 918 schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
923} 919}
924 920
921void phy_mac_interrupt(struct phy_device *phydev, int new_link)
922{
923 cancel_work_sync(&phydev->phy_queue);
924 phydev->link = new_link;
925 schedule_work(&phydev->phy_queue);
926}
927EXPORT_SYMBOL(phy_mac_interrupt);
928
925static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad, 929static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
926 int addr) 930 int addr)
927{ 931{
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8e29d22ba113..b55aa33a5b8b 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -189,6 +189,7 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
189 189
190 mutex_init(&dev->lock); 190 mutex_init(&dev->lock);
191 INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); 191 INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine);
192 INIT_WORK(&dev->phy_queue, phy_change);
192 193
193 /* Request the appropriate module unconditionally; don't 194 /* Request the appropriate module unconditionally; don't
194 bother trying to do so only if it isn't already loaded, 195 bother trying to do so only if it isn't already loaded,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 8e4bc8ab692d..fdfa11542974 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -557,6 +557,8 @@ void phy_drivers_unregister(struct phy_driver *drv, int n);
557int phy_driver_register(struct phy_driver *new_driver); 557int phy_driver_register(struct phy_driver *new_driver);
558int phy_drivers_register(struct phy_driver *new_driver, int n); 558int phy_drivers_register(struct phy_driver *new_driver, int n);
559void phy_state_machine(struct work_struct *work); 559void phy_state_machine(struct work_struct *work);
560void phy_change(struct work_struct *work);
561void phy_mac_interrupt(struct phy_device *phydev, int new_link);
560void phy_start_machine(struct phy_device *phydev, 562void phy_start_machine(struct phy_device *phydev,
561 void (*handler)(struct net_device *)); 563 void (*handler)(struct net_device *));
562void phy_stop_machine(struct phy_device *phydev); 564void phy_stop_machine(struct phy_device *phydev);