Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[cascardo/linux.git] / drivers / net / phy / phy.c
index 38f0b31..36c6994 100644 (file)
@@ -294,7 +294,8 @@ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd)
        cmd->duplex = phydev->duplex;
        cmd->port = PORT_MII;
        cmd->phy_address = phydev->addr;
-       cmd->transceiver = XCVR_EXTERNAL;
+       cmd->transceiver = phy_is_internal(phydev) ?
+               XCVR_INTERNAL : XCVR_EXTERNAL;
        cmd->autoneg = phydev->autoneg;
 
        return 0;
@@ -419,8 +420,6 @@ out_unlock:
 EXPORT_SYMBOL(phy_start_aneg);
 
 
-static void phy_change(struct work_struct *work);
-
 /**
  * phy_start_machine - start PHY state machine tracking
  * @phydev: the phy_device struct
@@ -439,7 +438,7 @@ void phy_start_machine(struct phy_device *phydev,
 {
        phydev->adjust_state = handler;
 
-       schedule_delayed_work(&phydev->state_queue, HZ);
+       queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, HZ);
 }
 
 /**
@@ -500,7 +499,7 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
        disable_irq_nosync(irq);
        atomic_inc(&phydev->irq_disable);
 
-       schedule_work(&phydev->phy_queue);
+       queue_work(system_power_efficient_wq, &phydev->phy_queue);
 
        return IRQ_HANDLED;
 }
@@ -565,8 +564,6 @@ int phy_start_interrupts(struct phy_device *phydev)
 {
        int err = 0;
 
-       INIT_WORK(&phydev->phy_queue, phy_change);
-
        atomic_set(&phydev->irq_disable, 0);
        if (request_irq(phydev->irq, phy_interrupt,
                                IRQF_SHARED,
@@ -623,7 +620,7 @@ EXPORT_SYMBOL(phy_stop_interrupts);
  * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
  * @work: work_struct that describes the work to be done
  */
-static void phy_change(struct work_struct *work)
+void phy_change(struct work_struct *work)
 {
        int err;
        struct phy_device *phydev =
@@ -655,7 +652,7 @@ static void phy_change(struct work_struct *work)
 
        /* reschedule state queue work to run as soon as possible */
        cancel_delayed_work_sync(&phydev->state_queue);
-       schedule_delayed_work(&phydev->state_queue, 0);
+       queue_delayed_work(system_power_efficient_wq, &phydev->state_queue, 0);
 
        return;
 
@@ -682,7 +679,7 @@ void phy_stop(struct phy_device *phydev)
        if (PHY_HALTED == phydev->state)
                goto out_unlock;
 
-       if (phydev->irq != PHY_POLL) {
+       if (phy_interrupt_is_valid(phydev)) {
                /* Disable PHY Interrupts */
                phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
 
@@ -828,8 +825,9 @@ void phy_state_machine(struct work_struct *work)
                        break;
                case PHY_RUNNING:
                        /* Only register a CHANGE if we are
-                        * polling */
-                       if (PHY_POLL == phydev->irq)
+                        * polling or ignoring interrupts
+                        */
+                       if (!phy_interrupt_is_valid(phydev))
                                phydev->state = PHY_CHANGELINK;
                        break;
                case PHY_CHANGELINK:
@@ -848,7 +846,7 @@ void phy_state_machine(struct work_struct *work)
 
                        phydev->adjust_link(phydev->attached_dev);
 
-                       if (PHY_POLL != phydev->irq)
+                       if (phy_interrupt_is_valid(phydev))
                                err = phy_config_interrupt(phydev,
                                                PHY_INTERRUPT_ENABLED);
                        break;
@@ -918,8 +916,17 @@ void phy_state_machine(struct work_struct *work)
        if (err < 0)
                phy_error(phydev);
 
-       schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
+       queue_delayed_work(system_power_efficient_wq, &phydev->state_queue,
+                       PHY_STATE_TIME * HZ);
+}
+
+void phy_mac_interrupt(struct phy_device *phydev, int new_link)
+{
+       cancel_work_sync(&phydev->phy_queue);
+       phydev->link = new_link;
+       schedule_work(&phydev->phy_queue);
 }
+EXPORT_SYMBOL(phy_mac_interrupt);
 
 static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
                                    int addr)