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;
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;
};
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);
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 =
__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,
}
}
-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,
.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,
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
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);
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
if (retval < 0)
goto err_free_rx_1;
- INIT_DELAYED_WORK(&tp->task, NULL);
+ INIT_WORK(&tp->task, NULL, dev);
smp_mb();
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);
if (ret < 0)
goto out;
-#ifdef CONFIG_R8169_NAPI
- napi_enable(&tp->napi);
-#endif
+ netif_poll_enable(dev);
rtl_hw_start(dev);
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);
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);
}
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();
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();
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) {
{
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++) {
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;
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
err_update_stats:
- dev->stats.tx_dropped++;
+ tp->stats.tx_dropped++;
goto out;
}
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);
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;
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;
"%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 {
* 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;
}
tp->Rx_skbuff[entry] = NULL;
}
+ skb->dev = dev;
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, 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. */
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);
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);
#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))
}
#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
RTL_W16(IntrMask, tp->intr_event);
}
- return work_done;
+ return (work_done >= work_to_do);
}
#endif
netif_stop_queue(dev);
#ifdef CONFIG_R8169_NAPI
- napi_disable(&tp->napi);
+ netif_poll_disable(dev);
#endif
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);
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,
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
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);
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)