diff options
Diffstat (limited to 'drivers/net/ethernet/realtek/r8169.c')
-rw-r--r-- | drivers/net/ethernet/realtek/r8169.c | 172 |
1 files changed, 58 insertions, 114 deletions
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 9a5e2969df61..006b0aa8cec3 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -77,8 +77,6 @@ static const int multicast_filter_limit = 32; #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) -#define RTL8169_TX_TIMEOUT (6*HZ) - /* write/read MMIO register */ #define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) #define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) @@ -633,7 +631,6 @@ struct rtl8169_tc_offsets { enum rtl_flag { RTL_FLAG_TASK_ENABLED = 0, - RTL_FLAG_TASK_SLOW_PENDING, RTL_FLAG_TASK_RESET_PENDING, RTL_FLAG_MAX }; @@ -1354,7 +1351,8 @@ static void rtl_irq_enable_all(struct rtl8169_private *tp) static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) { rtl_irq_disable(tp); - rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow); + rtl_ack_events(tp, 0xffff); + /* PCI commit */ RTL_R8(tp, ChipCmd); } @@ -4048,23 +4046,11 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) rtl_hw_phy_config(dev); if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - netif_dbg(tp, drv, dev, - "Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(tp, 0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) + pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { netif_dbg(tp, drv, dev, "Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); RTL_W8(tp, 0x82, 0x01); - netif_dbg(tp, drv, dev, - "Set PHY Reg 0x0bh = 0x00h\n"); - rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0 } /* We may have called phy_speed_down before */ @@ -4282,8 +4268,8 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp) RTL_W32(tp, RxConfig, RX_FIFO_THRESH | RX_DMA_BURST); break; case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: + case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36: + case RTL_GIGA_MAC_VER_38: RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); break; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51: @@ -4566,27 +4552,19 @@ static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp) static void rtl8169_set_magic_reg(struct rtl8169_private *tp, unsigned mac_version) { - static const struct rtl_cfg2_info { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }; - const struct rtl_cfg2_info *p = cfg2_info; - unsigned int i; - u32 clk; + u32 val; - clk = RTL_R8(tp, Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(tp, 0x7c, p->val); - break; - } - } + if (tp->mac_version == RTL_GIGA_MAC_VER_05) + val = 0x000fff00; + else if (tp->mac_version == RTL_GIGA_MAC_VER_06) + val = 0x00ffff00; + else + return; + + if (RTL_R8(tp, Config2) & PCI_Clock_66MHz) + val |= 0xff; + + RTL_W32(tp, 0x7c, val); } static void rtl_set_rx_mode(struct net_device *dev) @@ -5873,6 +5851,7 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) { rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); tp->cur_tx = tp->dirty_tx = 0; + netdev_reset_queue(tp->dev); } static void rtl_reset_work(struct rtl8169_private *tp) @@ -6175,6 +6154,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); + netdev_sent_queue(dev, skb->len); + skb_tx_timestamp(skb); /* Force memory writes to complete before releasing descriptor */ @@ -6273,7 +6254,7 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) { - unsigned int dirty_tx, tx_left; + unsigned int dirty_tx, tx_left, bytes_compl = 0, pkts_compl = 0; dirty_tx = tp->dirty_tx; smp_rmb(); @@ -6297,10 +6278,8 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) rtl8169_unmap_tx_skb(tp_to_dev(tp), tx_skb, tp->TxDescArray + entry); if (status & LastFrag) { - u64_stats_update_begin(&tp->tx_stats.syncp); - tp->tx_stats.packets++; - tp->tx_stats.bytes += tx_skb->skb->len; - u64_stats_update_end(&tp->tx_stats.syncp); + pkts_compl++; + bytes_compl += tx_skb->skb->len; dev_consume_skb_any(tx_skb->skb); tx_skb->skb = NULL; } @@ -6309,6 +6288,13 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) } if (tp->dirty_tx != dirty_tx) { + netdev_completed_queue(dev, pkts_compl, bytes_compl); + + u64_stats_update_begin(&tp->tx_stats.syncp); + tp->tx_stats.packets += pkts_compl; + tp->tx_stats.bytes += bytes_compl; + u64_stats_update_end(&tp->tx_stats.syncp); + tp->dirty_tx = dirty_tx; /* Sync with rtl8169_start_xmit: * - publish dirty_tx ring index (write barrier) @@ -6473,42 +6459,29 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) if (status == 0xffff || !(status & (RTL_EVENT_NAPI | tp->event_slow))) return IRQ_NONE; - rtl_irq_disable(tp); - napi_schedule_irqoff(&tp->napi); - - return IRQ_HANDLED; -} - -/* - * Workqueue context. - */ -static void rtl_slow_event_work(struct rtl8169_private *tp) -{ - struct net_device *dev = tp->dev; - u16 status; + if (unlikely(status & SYSErr)) { + rtl8169_pcierr_interrupt(tp->dev); + goto out; + } - status = rtl_get_events(tp) & tp->event_slow; - rtl_ack_events(tp, status); + if (status & LinkChg) + phy_mac_interrupt(tp->dev->phydev); - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - netif_stop_queue(dev); - /* XXX - Hack alert. See rtl_task(). */ - set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); - default: - break; - } + if (unlikely(status & RxFIFOOver && + tp->mac_version == RTL_GIGA_MAC_VER_11)) { + netif_stop_queue(tp->dev); + /* XXX - Hack alert. See rtl_task(). */ + set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); } - if (unlikely(status & SYSErr)) - rtl8169_pcierr_interrupt(dev); - - if (status & LinkChg) - phy_mac_interrupt(dev->phydev); + if (status & RTL_EVENT_NAPI) { + rtl_irq_disable(tp); + napi_schedule_irqoff(&tp->napi); + } +out: + rtl_ack_events(tp, status); - rtl_irq_enable_all(tp); + return IRQ_HANDLED; } static void rtl_task(struct work_struct *work) @@ -6517,8 +6490,6 @@ static void rtl_task(struct work_struct *work) int bitnr; void (*action)(struct rtl8169_private *); } rtl_work[] = { - /* XXX - keep rtl_slow_event_work() as first element. */ - { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work }, { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, }; struct rtl8169_private *tp = @@ -6548,29 +6519,16 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) { struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); struct net_device *dev = tp->dev; - u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; - int work_done= 0; - u16 status; + int work_done; - status = rtl_get_events(tp); - rtl_ack_events(tp, status & ~tp->event_slow); + work_done = rtl_rx(dev, tp, (u32) budget); - if (status & RTL_EVENT_NAPI_RX) - work_done = rtl_rx(dev, tp, (u32) budget); - - if (status & RTL_EVENT_NAPI_TX) - rtl_tx(dev, tp); - - if (status & tp->event_slow) { - enable_mask &= ~tp->event_slow; - - rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING); - } + rtl_tx(dev, tp); if (work_done < budget) { napi_complete_done(napi, work_done); - rtl_irq_enable(tp, enable_mask); + rtl_irq_enable_all(tp); mmiowb(); } @@ -6846,7 +6804,6 @@ static void rtl8169_net_suspend(struct net_device *dev) phy_stop(dev->phydev); netif_device_detach(dev); - netif_stop_queue(dev); rtl_lock_work(tp); napi_disable(&tp->napi); @@ -7093,20 +7050,12 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) { unsigned int flags; - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_06: + if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { RTL_W8(tp, Cfg9346, Cfg9346_Unlock); RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); RTL_W8(tp, Cfg9346, Cfg9346_Lock); flags = PCI_IRQ_LEGACY; - break; - case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_40: - /* This version was reported to have issues with resume - * from suspend when using MSI-X - */ - flags = PCI_IRQ_LEGACY | PCI_IRQ_MSI; - break; - default: + } else { flags = PCI_IRQ_ALL_TYPES; } @@ -7368,11 +7317,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->cp_cmd = RTL_R16(tp, CPlusCmd); - if ((sizeof(dma_addr_t) > 4) && - (use_dac == 1 || (use_dac == -1 && pci_is_pcie(pdev) && - tp->mac_version >= RTL_GIGA_MAC_VER_18)) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + if (sizeof(dma_addr_t) > 4 && (use_dac == 1 || (use_dac == -1 && + tp->mac_version >= RTL_GIGA_MAC_VER_18)) && + !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { /* CPlusCmd Dual Access Cycle is only needed for non-PCIe */ if (!pci_is_pcie(pdev)) @@ -7388,14 +7335,12 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_init_rxcfg(tp); - rtl_irq_disable(tp); + rtl8169_irq_mask_and_ack(tp); rtl_hw_initialize(tp); rtl_hw_reset(tp); - rtl_ack_events(tp, 0xffff); - pci_set_master(pdev); rtl_init_mdio_ops(tp); @@ -7435,7 +7380,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); dev->ethtool_ops = &rtl8169_ethtool_ops; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT); |