From dfc2b5cec87644899e70304844b0f012c2b44e55 Mon Sep 17 00:00:00 2001 From: t_jeang Date: Tue, 6 Jan 2009 12:05:59 +0000 Subject: [PATCH] imported patch r8169-backport-to-2.6.18 --- drivers/net/r8169.c | 161 +++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 86 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 65724250..c00b48ad 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -393,10 +393,7 @@ enum features { struct rtl8169_private { void __iomem *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; -#ifdef CONFIG_R8169_NAPI - struct napi_struct napi; -#endif + struct net_device_stats stats; spinlock_t lock; /* spin lock flag */ u32 msg_enable; int chipset; @@ -429,7 +426,7 @@ struct rtl8169_private { void (*hw_start)(struct net_device *); unsigned int (*phy_reset_pending)(void __iomem *); unsigned int (*link_ok)(void __iomem *); - struct delayed_work task; + struct work_struct task; unsigned features; }; @@ -446,7 +443,8 @@ MODULE_VERSION(RTL8169_VERSION); static int rtl8169_open(struct net_device *dev); static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance); +static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, + struct pt_regs *regs); static int rtl8169_init_ring(struct net_device *dev); static void rtl_hw_start(struct net_device *dev); static int rtl8169_close(struct net_device *dev); @@ -454,13 +452,13 @@ static void rtl_set_rx_mode(struct net_device *dev); static void rtl8169_tx_timeout(struct net_device *dev); static struct net_device_stats *rtl8169_get_stats(struct net_device *dev); static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *, - void __iomem *, u32 budget); + void __iomem *); static int rtl8169_change_mtu(struct net_device *dev, int new_mtu); static void rtl8169_down(struct net_device *dev); static void rtl8169_rx_clear(struct rtl8169_private *tp); #ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget); +static int rtl8169_poll(struct net_device *dev, int *budget); #endif static const unsigned int rtl8169_rx_config = @@ -1008,14 +1006,9 @@ struct rtl8169_counters { __le16 tx_underun; }; -static int rtl8169_get_sset_count(struct net_device *dev, int sset) +static int rtl8169_get_stats_count(struct net_device *dev) { - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } + return ARRAY_SIZE(rtl8169_gstrings); } static void rtl8169_get_ethtool_stats(struct net_device *dev, @@ -1072,7 +1065,7 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) } } -static const struct ethtool_ops rtl8169_ethtool_ops = { +static struct ethtool_ops rtl8169_ethtool_ops = { .get_drvinfo = rtl8169_get_drvinfo, .get_regs_len = rtl8169_get_regs_len, .get_link = ethtool_op_get_link, @@ -1081,16 +1074,20 @@ static const struct ethtool_ops rtl8169_ethtool_ops = { .get_msglevel = rtl8169_get_msglevel, .set_msglevel = rtl8169_set_msglevel, .get_rx_csum = rtl8169_get_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, .set_rx_csum = rtl8169_set_rx_csum, .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, .set_tso = ethtool_op_set_tso, .get_regs = rtl8169_get_regs, .get_wol = rtl8169_get_wol, .set_wol = rtl8169_set_wol, .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, + .get_stats_count = rtl8169_get_stats_count, .get_ethtool_stats = rtl8169_get_ethtool_stats, + .get_perm_addr = ethtool_op_get_perm_addr, }; static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, @@ -1402,7 +1399,7 @@ static void rtl8169_netpoll(struct net_device *dev) struct pci_dev *pdev = tp->pci_dev; disable_irq(pdev->irq); - rtl8169_interrupt(pdev->irq, dev); + rtl8169_interrupt(pdev->irq, dev, NULL); enable_irq(pdev->irq); } #endif @@ -1614,9 +1611,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out; } + SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); tp = netdev_priv(dev); - tp->dev = dev; tp->pci_dev = pdev; tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); @@ -1765,7 +1762,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->set_mac_address = rtl_set_mac_address; #ifdef CONFIG_R8169_NAPI - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; #endif #ifdef CONFIG_R8169_VLAN @@ -1877,7 +1875,7 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_free_rx_1; - INIT_DELAYED_WORK(&tp->task, NULL); + INIT_WORK(&tp->task, NULL, dev); smp_mb(); @@ -1887,10 +1885,6 @@ static int rtl8169_open(struct net_device *dev) if (retval < 0) goto err_release_ring_2; -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif - rtl_hw_start(dev); rtl8169_request_timer(dev); @@ -2197,9 +2191,7 @@ static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) if (ret < 0) goto out; -#ifdef CONFIG_R8169_NAPI - napi_enable(&tp->napi); -#endif + netif_poll_enable(dev); rtl_hw_start(dev); @@ -2257,7 +2249,7 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct pci_dev *pdev, if (!skb) goto err_out; - skb_reserve(skb, align ? ((pad - 1) & (unsigned long)skb->data) : pad); + skb_reserve(skb, align ? ((pad - 1) & (u32)skb->data) : pad); mapping = pci_map_single(pdev, skb->data, rx_buf_sz, PCI_DMA_FROMDEVICE); @@ -2369,17 +2361,17 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) dev_kfree_skb(skb); tx_skb->skb = NULL; } - tp->dev->stats.tx_dropped++; + tp->stats.tx_dropped++; } } tp->cur_tx = tp->dirty_tx = 0; } -static void rtl8169_schedule_work(struct net_device *dev, work_func_t task) +static void rtl8169_schedule_work(struct net_device *dev, void (*task)(void *)) { struct rtl8169_private *tp = netdev_priv(dev); - PREPARE_DELAYED_WORK(&tp->task, task); + PREPARE_WORK(&tp->task, task, dev); schedule_delayed_work(&tp->task, 4); } @@ -2391,24 +2383,17 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) synchronize_irq(dev->irq); /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); -#endif + netif_poll_disable(dev); rtl8169_irq_mask_and_ack(ioaddr); -#ifdef CONFIG_R8169_NAPI - tp->intr_mask = 0xffff; - RTL_W16(IntrMask, tp->intr_event); - napi_enable(&tp->napi); -#endif + netif_poll_enable(dev); } -static void rtl8169_reinit_task(struct work_struct *work) +static void rtl8169_reinit_task(void *_data) { - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; + struct net_device *dev = _data; + struct rtl8169_private *tp = netdev_priv(dev); int ret; rtnl_lock(); @@ -2432,11 +2417,10 @@ out_unlock: rtnl_unlock(); } -static void rtl8169_reset_task(struct work_struct *work) +static void rtl8169_reset_task(void *_data) { - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, task.work); - struct net_device *dev = tp->dev; + struct net_device *dev = _data; + struct rtl8169_private *tp = netdev_priv(dev); rtnl_lock(); @@ -2445,7 +2429,7 @@ static void rtl8169_reset_task(struct work_struct *work) rtl8169_wait_for_quiescence(dev); - rtl8169_rx_interrupt(dev, tp, tp->mmio_addr, ~(u32)0); + rtl8169_rx_interrupt(dev, tp, tp->mmio_addr); rtl8169_tx_clear(tp); if (tp->dirty_rx == tp->cur_rx) { @@ -2480,7 +2464,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, { struct skb_shared_info *info = skb_shinfo(skb); unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); + struct TxDesc * txd; entry = tp->cur_tx; for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { @@ -2522,7 +2506,7 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) return LargeSend | ((mss & MSSMask) << MSSShift); } if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); + const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) return IPCS | TCPCS; @@ -2609,7 +2593,7 @@ err_stop: netif_stop_queue(dev); ret = NETDEV_TX_BUSY; err_update_stats: - dev->stats.tx_dropped++; + tp->stats.tx_dropped++; goto out; } @@ -2684,8 +2668,8 @@ static void rtl8169_tx_interrupt(struct net_device *dev, if (status & DescOwn) break; - dev->stats.tx_bytes += len; - dev->stats.tx_packets++; + tp->stats.tx_bytes += len; + tp->stats.tx_packets++; rtl8169_unmap_tx_skb(tp->pci_dev, tx_skb, tp->TxDescArray + entry); @@ -2734,17 +2718,17 @@ static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc) skb->ip_summed = CHECKSUM_NONE; } -static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, +static inline int rtl8169_try_rx_copy(struct sk_buff **sk_buff, struct rtl8169_private *tp, int pkt_size, dma_addr_t addr) { struct sk_buff *skb; - bool done = false; + int done = 0; if (pkt_size >= rx_copybreak) goto out; - skb = netdev_alloc_skb(tp->dev, pkt_size + NET_IP_ALIGN); + skb = dev_alloc_skb(pkt_size + NET_IP_ALIGN); if (!skb) goto out; @@ -2753,21 +2737,21 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, skb_reserve(skb, NET_IP_ALIGN); skb_copy_from_linear_data(*sk_buff, skb->data, pkt_size); *sk_buff = skb; - done = true; + done = 1; out: return done; } static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, - void __iomem *ioaddr, u32 budget) + void __iomem *ioaddr) { unsigned int cur_rx, rx_left; unsigned int delta, count; cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = rtl8169_rx_quota(rx_left, budget); + rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); for (; rx_left > 0; rx_left--, cur_rx++) { unsigned int entry = cur_rx % NUM_RX_DESC; @@ -2785,14 +2769,14 @@ static int rtl8169_rx_interrupt(struct net_device *dev, "%s: Rx ERROR. status = %08x\n", dev->name, status); } - dev->stats.rx_errors++; + tp->stats.rx_errors++; if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; + tp->stats.rx_length_errors++; if (status & RxCRC) - dev->stats.rx_crc_errors++; + tp->stats.rx_crc_errors++; if (status & RxFOVF) { rtl8169_schedule_work(dev, rtl8169_reset_task); - dev->stats.rx_fifo_errors++; + tp->stats.rx_fifo_errors++; } rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { @@ -2807,8 +2791,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev, * sized frames. */ if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; + tp->stats.rx_dropped++; + tp->stats.rx_length_errors++; rtl8169_mark_to_asic(desc, tp->rx_buf_sz); continue; } @@ -2825,6 +2809,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, tp->Rx_skbuff[entry] = NULL; } + skb->dev = dev; skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); @@ -2832,8 +2817,8 @@ static int rtl8169_rx_interrupt(struct net_device *dev, rtl8169_rx_skb(skb); dev->last_rx = jiffies; - dev->stats.rx_bytes += pkt_size; - dev->stats.rx_packets++; + tp->stats.rx_bytes += pkt_size; + tp->stats.rx_packets++; } /* Work around for AMD plateform. */ @@ -2865,7 +2850,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, return count; } -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) +static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = dev_instance; struct rtl8169_private *tp = netdev_priv(dev); @@ -2916,8 +2901,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event); tp->intr_mask = ~tp->napi_event; - if (likely(netif_rx_schedule_prep(dev, &tp->napi))) - __netif_rx_schedule(dev, &tp->napi); + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); else if (netif_msg_intr(tp)) { printk(KERN_INFO "%s: interrupt %04x in poll\n", dev->name, status); @@ -2927,7 +2912,7 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) #else /* Rx interrupt */ if (status & (RxOK | RxOverflow | RxFIFOOver)) - rtl8169_rx_interrupt(dev, tp, ioaddr, ~(u32)0); + rtl8169_rx_interrupt(dev, tp, ioaddr); /* Tx interrupt */ if (status & (TxOK | TxErr)) @@ -2950,18 +2935,20 @@ out: } #ifdef CONFIG_R8169_NAPI -static int rtl8169_poll(struct napi_struct *napi, int budget) +static int rtl8169_poll(struct net_device *dev, int *budget) { - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; + unsigned int work_done, work_to_do = min(*budget, dev->quota); + struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; - int work_done; - work_done = rtl8169_rx_interrupt(dev, tp, ioaddr, (u32) budget); + work_done = rtl8169_rx_interrupt(dev, tp, ioaddr); rtl8169_tx_interrupt(dev, tp, ioaddr); - if (work_done < budget) { - netif_rx_complete(dev, napi); + *budget -= work_done; + dev->quota -= work_done; + + if (work_done < work_to_do) { + netif_rx_complete(dev); tp->intr_mask = 0xffff; /* * 20040426: the barrier is not strictly required but the @@ -2973,7 +2960,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) RTL_W16(IntrMask, tp->intr_event); } - return work_done; + return (work_done >= work_to_do); } #endif @@ -2988,7 +2975,7 @@ static void rtl8169_down(struct net_device *dev) netif_stop_queue(dev); #ifdef CONFIG_R8169_NAPI - napi_disable(&tp->napi); + netif_poll_disable(dev); #endif core_down: @@ -2997,7 +2984,7 @@ core_down: rtl8169_asic_down(ioaddr); /* Update the error counts. */ - dev->stats.rx_missed_errors += RTL_R32(RxMissed); + tp->stats.rx_missed_errors += RTL_R32(RxMissed); RTL_W32(RxMissed, 0); spin_unlock_irq(&tp->lock); @@ -3038,6 +3025,8 @@ static int rtl8169_close(struct net_device *dev) free_irq(dev->irq, dev); + netif_poll_enable(dev); + pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray, tp->RxPhyAddr); pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray, @@ -3124,12 +3113,12 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) if (netif_running(dev)) { spin_lock_irqsave(&tp->lock, flags); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); + tp->stats.rx_missed_errors += RTL_R32(RxMissed); RTL_W32(RxMissed, 0); spin_unlock_irqrestore(&tp->lock, flags); } - return &dev->stats; + return &tp->stats; } #ifdef CONFIG_PM @@ -3150,7 +3139,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) rtl8169_asic_down(ioaddr); - dev->stats.rx_missed_errors += RTL_R32(RxMissed); + tp->stats.rx_missed_errors += RTL_R32(RxMissed); RTL_W32(RxMissed, 0); spin_unlock_irq(&tp->lock); @@ -3197,7 +3186,7 @@ static struct pci_driver rtl8169_pci_driver = { static int __init rtl8169_init_module(void) { - return pci_register_driver(&rtl8169_pci_driver); + return pci_module_init(&rtl8169_pci_driver); } static void __exit rtl8169_cleanup_module(void) -- 2.39.5