r8169: reset chip synchronously in __rtl8169_resume
[linux-2.6-microblaze.git] / drivers / net / ethernet / realtek / r8169.c
index 298930d..c7a89d2 100644 (file)
@@ -205,6 +205,8 @@ enum cfg_version {
 };
 
 static const struct pci_device_id rtl8169_pci_tbl[] = {
+       { PCI_VDEVICE(REALTEK,  0x2502), RTL_CFG_1 },
+       { PCI_VDEVICE(REALTEK,  0x2600), RTL_CFG_1 },
        { PCI_VDEVICE(REALTEK,  0x8129), RTL_CFG_0 },
        { PCI_VDEVICE(REALTEK,  0x8136), RTL_CFG_2 },
        { PCI_VDEVICE(REALTEK,  0x8161), RTL_CFG_1 },
@@ -706,6 +708,7 @@ module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_SOFTDEP("pre: realtek");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
@@ -742,6 +745,16 @@ static void rtl_unlock_work(struct rtl8169_private *tp)
        mutex_unlock(&tp->wk.mutex);
 }
 
+static void rtl_lock_config_regs(struct rtl8169_private *tp)
+{
+       RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+}
+
+static void rtl_unlock_config_regs(struct rtl8169_private *tp)
+{
+       RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+}
+
 static void rtl_tx_performance_tweak(struct rtl8169_private *tp, u16 force)
 {
        pcie_capability_clear_and_set_word(tp->pci_dev, PCI_EXP_DEVCTL,
@@ -1275,11 +1288,6 @@ static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
                RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
 }
 
-static u16 rtl_get_events(struct rtl8169_private *tp)
-{
-       return RTL_R16(tp, IntrStatus);
-}
-
 static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
 {
        RTL_W16(tp, IntrStatus, bits);
@@ -1428,7 +1436,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
        };
        u8 options;
 
-       RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+       rtl_unlock_config_regs(tp);
 
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
@@ -1476,7 +1484,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
                break;
        }
 
-       RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+       rtl_lock_config_regs(tp);
 
        device_set_wakeup_enable(tp_to_dev(tp), wolopts);
 }
@@ -1679,11 +1687,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp)
 
 static bool rtl8169_update_counters(struct rtl8169_private *tp)
 {
+       u8 val = RTL_R8(tp, ChipCmd);
+
        /*
         * Some chips are unable to dump tally counters when the receiver
-        * is disabled.
+        * is disabled. If 0xff chip may be in a PCI power-save state.
         */
-       if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0)
+       if (!(val & CmdRxEnb) || val == 0xff)
                return true;
 
        return rtl8169_do_counters(tp, CounterDump);
@@ -4006,7 +4016,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
 {
        rtl_lock_work(tp);
 
-       RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+       rtl_unlock_config_regs(tp);
 
        RTL_W32(tp, MAC4, addr[4] | addr[5] << 8);
        RTL_R32(tp, MAC4);
@@ -4017,7 +4027,7 @@ static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
        if (tp->mac_version == RTL_GIGA_MAC_VER_34)
                rtl_rar_exgmac_set(tp, addr);
 
-       RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+       rtl_lock_config_regs(tp);
 
        rtl_unlock_work(tp);
 }
@@ -4229,18 +4239,18 @@ static void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
 static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
 {
        if (tp->jumbo_ops.enable) {
-               RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+               rtl_unlock_config_regs(tp);
                tp->jumbo_ops.enable(tp);
-               RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+               rtl_lock_config_regs(tp);
        }
 }
 
 static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
 {
        if (tp->jumbo_ops.disable) {
-               RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+               rtl_unlock_config_regs(tp);
                tp->jumbo_ops.disable(tp);
-               RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+               rtl_lock_config_regs(tp);
        }
 }
 
@@ -4561,13 +4571,13 @@ static void rtl_set_rx_mode(struct net_device *dev)
 
 static void rtl_hw_start(struct  rtl8169_private *tp)
 {
-       RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+       rtl_unlock_config_regs(tp);
 
        tp->hw_start(tp);
 
        rtl_set_rx_max_size(tp);
        rtl_set_rx_tx_desc_registers(tp);
-       RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+       rtl_lock_config_regs(tp);
 
        /* Initially a 10 us delay. Turned it into a PCI commit. - FR */
        RTL_R8(tp, IntrMask);
@@ -4691,18 +4701,10 @@ static void rtl_enable_clock_request(struct rtl8169_private *tp)
                                 PCI_EXP_LNKCTL_CLKREQ_EN);
 }
 
-static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable)
+static void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp)
 {
-       u8 data;
-
-       data = RTL_R8(tp, Config3);
-
-       if (enable)
-               data |= Rdy_to_L23;
-       else
-               data &= ~Rdy_to_L23;
-
-       RTL_W8(tp, Config3, data);
+       /* work around an issue when PCI reset occurs during L2/L3 state */
+       RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23);
 }
 
 static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
@@ -5023,7 +5025,7 @@ static void rtl_hw_start_8411(struct rtl8169_private *tp)
        };
 
        rtl_hw_start_8168f(tp);
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 
        rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1));
 
@@ -5057,7 +5059,7 @@ static void rtl_hw_start_8168g(struct rtl8169_private *tp)
        rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC);
        rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 }
 
 static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
@@ -5163,7 +5165,7 @@ static void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
 
        rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC);
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 
        rtl_writephy(tp, 0x1f, 0x0c42);
        rg_saw_cnt = (rtl_readphy(tp, 0x13) & 0x3fff);
@@ -5240,7 +5242,7 @@ static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
 
        RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 }
 
 static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
@@ -5511,7 +5513,7 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
 
        rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 }
 
 static void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
@@ -5546,7 +5548,7 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
        rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
        rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC);
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
 }
 
 static void rtl_hw_start_8106(struct rtl8169_private *tp)
@@ -5560,7 +5562,7 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
        RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
 
-       rtl_pcie_state_l2l3_enable(tp, false);
+       rtl_pcie_state_l2l3_disable(tp);
        rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
@@ -6196,8 +6198,6 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
                dev->features &= ~NETIF_F_HIGHDMA;
        }
 
-       rtl8169_hw_reset(tp);
-
        rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
 }
 
@@ -6404,7 +6404,7 @@ release_descriptor:
 static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
 {
        struct rtl8169_private *tp = dev_instance;
-       u16 status = rtl_get_events(tp);
+       u16 status = RTL_R16(tp, IntrStatus);
        u16 irq_mask = RTL_R16(tp, IntrMask);
 
        if (status == 0xffff || !(status & irq_mask))
@@ -6632,10 +6632,6 @@ static int rtl_open(struct net_device *dev)
        if (retval < 0)
                goto err_free_rx_1;
 
-       INIT_WORK(&tp->wk.work, rtl_task);
-
-       smp_mb();
-
        rtl_request_firmware(tp);
 
        retval = pci_request_irq(pdev, 0, rtl8169_interrupt, NULL, tp,
@@ -6791,9 +6787,8 @@ static void __rtl8169_resume(struct net_device *dev)
        rtl_lock_work(tp);
        napi_enable(&tp->napi);
        set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+       rtl_reset_work(tp);
        rtl_unlock_work(tp);
-
-       rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
 }
 
 static int rtl8169_resume(struct device *device)
@@ -6990,9 +6985,9 @@ static int rtl_alloc_irq(struct rtl8169_private *tp)
        unsigned int flags;
 
        if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
-               RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
+               rtl_unlock_config_regs(tp);
                RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
-               RTL_W8(tp, Cfg9346, Cfg9346_Lock);
+               rtl_lock_config_regs(tp);
                flags = PCI_IRQ_LEGACY;
        } else {
                flags = PCI_IRQ_ALL_TYPES;
@@ -7295,6 +7290,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->saved_wolopts = __rtl8169_get_wol(tp);
 
        mutex_init(&tp->wk.mutex);
+       INIT_WORK(&tp->wk.work, rtl_task);
        u64_stats_init(&tp->rx_stats.syncp);
        u64_stats_init(&tp->tx_stats.syncp);