bk://gkernel.bkbits.net/netdev-2.6 jgarzik@redhat.com|ChangeSet|20040519235345|34584 jgarzik # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/05/28 14:06:50-07:00 akpm@bix.(none) # Merge # # drivers/net/e1000/e1000_main.c # 2004/05/28 14:06:46-07:00 akpm@bix.(none) +0 -0 # SCCS merged # # drivers/net/e1000/e1000_ethtool.c # 2004/05/28 14:06:39-07:00 akpm@bix.(none) +0 -0 # SCCS merged # # drivers/net/Makefile # 2004/05/28 13:31:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/28 13:31:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/8139too.c # 2004/05/28 13:31:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/25 13:37:44-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/Kconfig # 2004/05/25 13:37:40-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/19 18:21:11-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/Makefile # 2004/05/19 18:21:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/19 18:21:08-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/19 19:53:45-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/sis900 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/Makefile # 2004/05/19 19:53:42-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/19 19:53:42-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/05/18 14:43:15-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/Makefile # 2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/8139too.c # 2004/05/18 14:43:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/18 14:42:19-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/Makefile # 2004/05/18 14:42:16-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/18 14:42:16-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/17 14:12:59-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/r8169 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/Kconfig # 2004/05/17 14:12:56-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/05/17 14:11:35-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/linux-2.6 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/Makefile # 2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/8139too.c # 2004/05/17 14:11:31-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/05/17 14:07:14-04:00 romieu@fr.zoreil.com # [PATCH] r8169: janitoring # # Spring cleanup # - unsigned int (u32) should be slightly faster on ppc64 (Jon D Mason); # - misc minor de-uglyfication. # # drivers/net/r8169.c # 2004/05/14 17:08:45-04:00 romieu@fr.zoreil.com +47 -47 # 2.6.6-mm2 - r8169 janitoring # # ChangeSet # 2004/05/17 14:07:06-04:00 romieu@fr.zoreil.com # [PATCH] r8169: cosmetic renaming of a register # # RxUnderrun status bit renamed to LinkChg (identical to the 8139cp driver). # # drivers/net/r8169.c # 2004/05/14 17:08:47-04:00 romieu@fr.zoreil.com +5 -5 # 2.6.6-mm2 - r8169 register rename # # ChangeSet # 2004/05/17 14:06:58-04:00 romieu@fr.zoreil.com # [PATCH] r8169: napi support # # Napi for r8169 (Jon D Mason ). # Both Tx and Rx processing are moved to the ->poll() function. # # drivers/net/r8169.c # 2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +78 -11 # 2.6.6-mm2 - r8169 napi # # drivers/net/Kconfig # 2004/05/14 17:07:18-04:00 romieu@fr.zoreil.com +5 -0 # 2.6.6-mm2 - r8169 napi # # ChangeSet # 2004/05/14 21:37:15-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/Makefile # 2004/05/14 21:37:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/05/14 21:37:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/14 21:36:21-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/8139too.c # 2004/05/14 21:36:18-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/11 16:49:58-07:00 akpm@bix.(none) # Merge bk://gkernel.bkbits.net/netdev-2.6 # into bix.(none):/usr/src/bk-netdev # # drivers/net/8139too.c # 2004/05/11 16:49:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/11 16:49:05-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-netdev # # drivers/net/8139too.c # 2004/05/11 16:49:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/05/10 21:11:08-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/linux-2.6 # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/8139too.c # 2004/05/10 21:11:04-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/04/21 23:30:47-04:00 romieu@fr.zoreil.com # [PATCH] epic100: code removal in irq handler # # The loop in the irq handler is not needed any more as the high frequency # events have been deferred due to napi usage. # # drivers/net/epic100.c # 2004/04/19 18:37:16-04:00 romieu@fr.zoreil.com +52 -64 # 2.6.6-rc1-mm1 - code removal in the epic100 irq handler # # ChangeSet # 2004/04/21 23:30:40-04:00 romieu@fr.zoreil.com # [PATCH] epic100: spin_unlock_irqrestore avoidance # # This patch avoids to duplicate a spin_unlock: # - it is mostly an artifact due to wild goto; # - it makes the generated code smaller. # # drivers/net/epic100.c # 2004/04/19 18:37:05-04:00 romieu@fr.zoreil.com +16 -10 # 2.6.6-rc1-mm1 - spin_unlock_irqrestore avoidance in epic100 # # ChangeSet # 2004/04/21 08:29:19-04:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/8139too # into redhat.com:/spare/repo/netdev-2.6/ALL # # drivers/net/8139too.c # 2004/04/21 08:29:16-04:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/04/21 08:24:06-04:00 jgarzik@redhat.com # [netdrvr e1000] Eliminate code duplicating ethtool_op_xxx helpers # # drivers/net/e1000/e1000_ethtool.c # 2004/04/21 08:24:01-04:00 jgarzik@redhat.com +4 -33 # [netdrvr e1000] Eliminate code duplicating ethtool_op_xxx helpers # # ChangeSet # 2004/04/21 08:19:08-04:00 jgarzik@redhat.com # Manual merge of e1000 upstream changes. # # drivers/net/e1000/e1000_ethtool.c # 2004/04/21 08:19:04-04:00 jgarzik@redhat.com +0 -3 # Manual merge of e1000 upstream changes. # # ChangeSet # 2004/04/19 12:33:23-04:00 shemminger@osdl.org # [PATCH] e1000 ethtool_ops support # # Okay, here is a first cut at ethtool ops integration for e1000. # # It has been touch tested for the basic operations on a card on # a lab machine. Please review before including in the 2.6.6 kernel. # # drivers/net/e1000/e1000_main.c # 2004/04/16 11:50:02-04:00 shemminger@osdl.org +7 -28 # e1000 ethtool_ops support # # drivers/net/e1000/e1000_ethtool.c # 2004/04/16 11:50:02-04:00 shemminger@osdl.org +234 -382 # e1000 ethtool_ops support # # ChangeSet # 2004/03/25 23:52:21-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi fixes # # Multiple invocation of __netif_rx_schedule() in epic_interrupt() while # epic_poll loops over __netif_rx_complete() leads to serious device # refcount leak. # # drivers/net/epic100.c # 2004/03/25 23:52:16-05:00 romieu@fr.zoreil.com +18 -15 # [netdrvr epic100] napi fixes # # Multiple invocation of __netif_rx_schedule() in epic_interrupt() while # epic_poll loops over __netif_rx_complete() leads to serious device # refcount leak. # # ChangeSet # 2004/03/22 19:07:18-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 3/3 - transmit path # # drivers/net/epic100.c # 2004/03/22 18:18:40-05:00 romieu@fr.zoreil.com +9 -11 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:07:11-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 2/3 - receive path # # drivers/net/epic100.c # 2004/03/22 18:18:33-05:00 romieu@fr.zoreil.com +116 -21 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:07:03-05:00 romieu@fr.zoreil.com # [netdrvr epic100] napi 1/3 - just shuffle some code around # # Isolate the classical TX part of epic_interrupt. Innocent code shuffling. # # drivers/net/epic100.c # 2004/03/22 16:53:18-05:00 romieu@fr.zoreil.com +76 -61 # 2.6.5-rc2 - epic100 napi # # ChangeSet # 2004/03/22 19:06:56-05:00 romieu@fr.zoreil.com # [netdrvr epic100] minor cleanups # # - extra pci_disable_device() to balance invocation of pci_enable_device() # in epic_init_one() (-> error path + epic_remove_one()); # - lazy return status in epic_init_one(), tsss...; # - memory dedicated to Rx descriptors was not freed after failure of # register_netdev() in epic_init_one(); # - use of epic_pause() in epic_close() offers a small window for a late # interruption just before the final free_irq(). Let's close the window to # avoid two epic_rx() threads racing with each other. # # drivers/net/epic100.c # 2004/03/22 16:53:16-05:00 romieu@fr.zoreil.com +40 -19 # 2.6.5-rc2 - epic100 fixup # diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig 2004-05-31 16:18:26 -07:00 +++ b/drivers/net/Kconfig 2004-05-31 16:18:26 -07:00 @@ -2033,6 +2033,11 @@ To compile this driver as a module, choose M here: the module will be called r8169. This is recommended. +config R8169_NAPI + bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" + depends on R8169 && EXPERIMENTAL + + config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" depends on PCI && NET_GIGE diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c 2004-05-31 16:18:26 -07:00 +++ b/drivers/net/e1000/e1000_ethtool.c 2004-05-31 16:18:26 -07:00 @@ -54,6 +54,7 @@ #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \ offsetof(struct e1000_adapter, m) static const struct e1000_stats e1000_gstrings_stats[] = { +static const struct e1000_stats e1000_gstrings_stats[] = { { "rx_packets", E1000_STAT(net_stats.rx_packets) }, { "tx_packets", E1000_STAT(net_stats.tx_packets) }, { "rx_bytes", E1000_STAT(net_stats.rx_bytes) }, @@ -103,8 +104,11 @@ static int e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +static int +e1000_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(hw->media_type == e1000_media_type_copper) { @@ -172,12 +176,15 @@ ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); return 0; + return 0; } static int e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +e1000_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; if(ecmd->autoneg == AUTONEG_ENABLE) { @@ -204,6 +211,7 @@ struct ethtool_pauseparam *pause) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; pause->autoneg = (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); @@ -223,6 +231,7 @@ struct ethtool_pauseparam *pause) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; adapter->fc_autoneg = pause->autoneg; @@ -344,6 +353,65 @@ return adapter->msg_enable; } +static u32 +e1000_get_rx_csum(struct net_device *netdev) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + return adapter->rx_csum; +} + +static int +e1000_set_rx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + adapter->rx_csum = data; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + return 0; +} + +static u32 +e1000_get_tx_csum(struct net_device *netdev) +{ + return (netdev->features & NETIF_F_HW_CSUM) != 0; +} + +static int +e1000_set_tx_csum(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(adapter->hw.mac_type < e1000_82543) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_HW_CSUM; + else + netdev->features &= ~NETIF_F_HW_CSUM; + return 0; +} + +static int +e1000_set_tso(struct net_device *netdev, u32 data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + + if (adapter->hw.mac_type < e1000_82544 || + adapter->hw.mac_type == e1000_82547) + return data ? -EINVAL : 0; + + if (data) + netdev->features |= NETIF_F_TSO; + else + netdev->features &= ~NETIF_F_TSO; + return 0; +} + + static void e1000_set_msglevel(struct net_device *netdev, uint32_t data) { @@ -353,22 +421,38 @@ static int e1000_get_regs_len(struct net_device *netdev) +e1000_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *drvinfo) +{ + struct e1000_adapter *adapter = netdev_priv(dev); + +} + +static int +e1000_get_regs_len(struct net_device *dev) { #define E1000_REGS_LEN 32 return E1000_REGS_LEN * sizeof(uint32_t); + return E1000_REGS_LEN * sizeof(uint32_t); } static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) +e1000_get_regs(struct net_device *dev, + struct ethtool_regs *regs, void *p) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; uint32_t *regs_buff = p; + u32 *regs_buff = p; uint16_t phy_data; memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t)); + memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t)); + regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; regs_buff[0] = E1000_READ_REG(hw, CTRL); @@ -442,27 +526,40 @@ regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ } +} + +static int +e1000_get_eeprom_len(struct net_device *dev) +{ + struct e1000_adapter *adapter = netdev_priv(dev); static int e1000_get_eeprom_len(struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; return adapter->hw.eeprom.word_size * 2; + return adapter->hw.eeprom.word_size * 2; } static int e1000_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) +e1000_get_eeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *bytes) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; + uint16_t *eeprom_buff = (uint16_t *) bytes; int first_word, last_word; int ret_val = 0; uint16_t i; if(eeprom->len == 0) return -EINVAL; + if(eeprom->len == 0) + return -EINVAL; eeprom->magic = hw->vendor_id | (hw->device_id << 16); @@ -500,8 +597,11 @@ static int e1000_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, uint8_t *bytes) +e1000_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; @@ -543,6 +643,7 @@ le16_to_cpus(&eeprom_buff[i]); memcpy(ptr, bytes, eeprom->len); + memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_word - first_word + 1; i++) eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); @@ -575,9 +676,12 @@ static void e1000_get_ringparam(struct net_device *netdev, +static void +e1000_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_mac_type mac_type = adapter->hw.mac_type; struct e1000_desc_ring *txdr = &adapter->tx_ring; struct e1000_desc_ring *rxdr = &adapter->rx_ring; @@ -594,10 +698,12 @@ ring->rx_jumbo_pending = 0; } + static int e1000_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) +e1000_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { + struct e1000_adapter *adapter = netdev_priv(netdev); int err; struct e1000_adapter *adapter = netdev->priv; e1000_mac_type mac_type = adapter->hw.mac_type; @@ -923,8 +1029,6 @@ kfree(txdr->buffer_info); if(rxdr->buffer_info) kfree(rxdr->buffer_info); - - return; } static int @@ -1372,6 +1476,7 @@ return *data; } + static int e1000_diag_test_count(struct net_device *netdev) { @@ -1380,10 +1485,19 @@ static void e1000_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, uint64_t *data) +e1000_diag_test_count(struct net_device *dev) { struct e1000_adapter *adapter = netdev->priv; boolean_t if_running = netif_running(netdev); + return E1000_TEST_LEN; +} + +static void +e1000_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + struct e1000_adapter *adapter = netdev_priv(netdev); + boolean_t if_running = netif_running(netdev); if(eth_test->flags == ETH_TEST_FL_OFFLINE) { /* Offline tests */ @@ -1440,8 +1554,10 @@ static void e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +e1000_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1479,11 +1595,12 @@ return; } } - static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +e1000_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct e1000_adapter *adapter = netdev->priv; + struct e1000_adapter *adapter = netdev_priv(dev); struct e1000_hw *hw = &adapter->hw; switch(adapter->hw.device_id) { @@ -1540,12 +1657,18 @@ static int e1000_phys_id(struct net_device *netdev, uint32_t data) +e1000_phys_id(struct net_device *netdev, u32 data) { struct e1000_adapter *adapter = netdev->priv; if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ)) data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ); + struct e1000_adapter *adapter = netdev_priv(netdev); + + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + if(!adapter->blink_timer.function) { init_timer(&adapter->blink_timer); adapter->blink_timer.function = e1000_led_blink_callback; @@ -1556,7 +1679,7 @@ mod_timer(&adapter->blink_timer, jiffies); set_current_state(TASK_INTERRUPTIBLE); - + schedule_timeout(data * HZ); schedule_timeout(data * HZ); del_timer_sync(&adapter->blink_timer); e1000_led_off(&adapter->hw); @@ -1568,47 +1691,49 @@ static int e1000_nway_reset(struct net_device *netdev) +static int +e1000_nway_reset(struct net_device *netdev) { - struct e1000_adapter *adapter = netdev->priv; if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); - } return 0; } - static uint32_t e1000_get_link(struct net_device *netdev) { return netif_carrier_ok(netdev); } - static int e1000_get_stats_count(struct net_device *netdev) { return E1000_STATS_LEN; } - static void e1000_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, uint64_t *data) { struct e1000_adapter *adapter = netdev->priv; int i; + struct e1000_adapter *adapter = netdev_priv(netdev); e1000_update_stats(adapter); for(i = 0; i < E1000_STATS_LEN; i++) { char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset; data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p; + if(netif_running(netdev)) { + e1000_down(adapter); + e1000_up(adapter); } } + return 0; +} static void e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) { int i; - switch(stringset) { case ETH_SS_TEST: memcpy(data, *e1000_gstrings_test, @@ -1619,10 +1744,15 @@ memcpy(data + i * ETH_GSTRING_LEN, e1000_gstrings_stats[i].stat_string, ETH_GSTRING_LEN); - } break; + e1000_update_stats(adapter); + for(i = 0; i < E1000_STATS_LEN; i++) { + char *p = (char *) adapter + e1000_gstrings_stats[i].stat_offset; + data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) + ? *(uint64_t *)p : *(uint32_t *)p; } } +} struct ethtool_ops e1000_ethtool_ops = { .get_settings = e1000_get_settings, @@ -1649,10 +1779,8 @@ .set_tx_csum = e1000_set_tx_csum, .get_sg = e1000_get_sg, .set_sg = e1000_set_sg, -#ifdef NETIF_F_TSO .get_tso = e1000_get_tso, .set_tso = e1000_set_tso, -#endif .self_test_count = e1000_diag_test_count, .self_test = e1000_diag_test, .get_strings = e1000_get_strings, @@ -1665,3 +1793,35 @@ { SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); } +struct ethtool_ops e1000_ethtool_ops = { + .get_settings = e1000_get_settings, + .set_settings = e1000_set_settings, + .get_drvinfo = e1000_get_drvinfo, + .get_regs_len = e1000_get_regs_len, + .get_regs = e1000_get_regs, + .get_wol = e1000_get_wol, + .set_wol = e1000_set_wol, + .nway_reset = e1000_nway_reset, + .get_link = ethtool_op_get_link, + .get_eeprom_len = e1000_get_eeprom_len, + .get_eeprom = e1000_get_eeprom, + .set_eeprom = e1000_set_eeprom, + .get_ringparam = e1000_get_ringparam, + .set_ringparam = e1000_set_ringparam, + .get_pauseparam = e1000_get_pauseparam, + .set_pauseparam = e1000_set_pauseparam, + .get_rx_csum = e1000_get_rx_csum, + .set_rx_csum = e1000_set_rx_csum, + .get_tx_csum = e1000_get_tx_csum, + .set_tx_csum = e1000_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = e1000_set_tso, + .self_test_count = e1000_diag_test_count, + .self_test = e1000_diag_test, + .get_strings = e1000_get_strings, + .phys_id = e1000_phys_id, + .get_stats_count = e1000_get_stats_count, + .get_ethtool_stats = e1000_get_ethtool_stats, +}; diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2004-05-31 16:18:26 -07:00 +++ b/drivers/net/e1000/e1000_main.c 2004-05-31 16:18:26 -07:00 @@ -144,10 +144,10 @@ static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); void set_ethtool_ops(struct net_device *netdev); + +static int e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +extern struct ethtool_ops e1000_ethtool_ops; static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static inline void e1000_rx_checksum(struct e1000_adapter *adapter, @@ -433,8 +433,9 @@ netdev->set_multicast_list = &e1000_set_multi; netdev->set_mac_address = &e1000_set_mac; netdev->change_mtu = &e1000_change_mtu; - netdev->do_ioctl = &e1000_ioctl; set_ethtool_ops(netdev); + netdev->do_ioctl = &e1000_do_ioctl; + SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; #ifdef CONFIG_E1000_NAPI @@ -2472,35 +2473,16 @@ adapter->smartspeed = 0; } -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ - -static int -e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} /** - * e1000_mii_ioctl - + * e1000_do_ioctl - * @netdev: * @ifreq: * @cmd: **/ static int -e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +e1000_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { struct e1000_adapter *adapter = netdev->priv; struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c --- a/drivers/net/epic100.c 2004-05-31 16:18:26 -07:00 +++ b/drivers/net/epic100.c 2004-05-31 16:18:26 -07:00 @@ -77,8 +77,6 @@ These may be modified when a driver module is loaded.*/ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 32; /* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8 /* More are supported, limit only on options */ @@ -96,9 +94,9 @@ Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 16 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#define RX_RING_SIZE 32 +#define TX_RING_SIZE 256 +#define TX_QUEUE_LEN 240 /* Limit ring entries actually used. */ +#define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc) @@ -155,12 +153,10 @@ MODULE_LICENSE("GPL"); MODULE_PARM(debug, "i"); -MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)"); -MODULE_PARM_DESC(max_interrupt_work, "EPIC/100 maximum events handled per interrupt"); MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex"); MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)"); @@ -292,6 +288,12 @@ StopTxDMA=0x20, StopRxDMA=0x40, RestartTx=0x80, }; +#define EpicRemoved 0xffffffff /* Chip failed or removed (CardBus) */ + +#define EpicNapiEvent (TxEmpty | TxDone | \ + RxDone | RxStarted | RxEarlyWarn | RxOverflow | RxFull) +#define EpicNormalEvent (0x0000ffff & ~EpicNapiEvent) + static u16 media2miictl[16] = { 0, 0x0C00, 0x0C00, 0x2000, 0x0100, 0x2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -330,9 +332,12 @@ /* Ring pointers. */ spinlock_t lock; /* Group with Tx control cache line. */ + spinlock_t napi_lock; + unsigned int reschedule_in_poll; unsigned int cur_tx, dirty_tx; unsigned int cur_rx, dirty_rx; + u32 irq_mask; unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct pci_dev *pci_dev; /* PCI bus location. */ @@ -359,7 +364,8 @@ static void epic_tx_timeout(struct net_device *dev); static void epic_init_ring(struct net_device *dev); static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int epic_rx(struct net_device *dev); +static int epic_rx(struct net_device *dev, int budget); +static int epic_poll(struct net_device *dev, int *budget); static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static struct ethtool_ops netdev_ethtool_ops; @@ -378,7 +384,7 @@ int irq; struct net_device *dev; struct epic_private *ep; - int i, option = 0, duplex = 0; + int i, ret, option = 0, duplex = 0; void *ring_space; dma_addr_t ring_dma; @@ -392,29 +398,33 @@ card_idx++; - i = pci_enable_device(pdev); - if (i) - return i; + ret = pci_enable_device(pdev); + if (ret) + goto out; irq = pdev->irq; if (pci_resource_len(pdev, 0) < pci_id_tbl[chip_idx].io_size) { printk (KERN_ERR "card %d: no PCI region space\n", card_idx); - return -ENODEV; + ret = -ENODEV; + goto err_out_disable; } pci_set_master(pdev); + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) + goto err_out_disable; + + ret = -ENOMEM; + dev = alloc_etherdev(sizeof (*ep)); if (!dev) { printk (KERN_ERR "card %d: no memory for eth device\n", card_idx); - return -ENOMEM; + goto err_out_free_res; } SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (pci_request_regions(pdev, DRV_NAME)) - goto err_out_free_netdev; - #ifdef USE_IO_OPS ioaddr = pci_resource_start (pdev, 0); #else @@ -422,7 +432,7 @@ ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1)); if (!ioaddr) { printk (KERN_ERR DRV_NAME " %d: ioremap failed\n", card_idx); - goto err_out_free_res; + goto err_out_free_netdev; } #endif @@ -459,7 +469,9 @@ dev->base_addr = ioaddr; dev->irq = irq; - spin_lock_init (&ep->lock); + spin_lock_init(&ep->lock); + spin_lock_init(&ep->napi_lock); + ep->reschedule_in_poll = 0; /* Bring the chip out of low-power mode. */ outl(0x4200, ioaddr + GENCTL); @@ -489,6 +501,9 @@ ep->pci_dev = pdev; ep->chip_id = chip_idx; ep->chip_flags = pci_id_tbl[chip_idx].drv_flags; + ep->irq_mask = + (ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) + | CntFull | TxUnderrun | EpicNapiEvent; /* Find the connected MII xcvrs. Doing this in open() would allow detecting external xcvrs later, but @@ -543,10 +558,12 @@ dev->ethtool_ops = &netdev_ethtool_ops; dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = &epic_tx_timeout; + dev->poll = epic_poll; + dev->weight = 64; - i = register_netdev(dev); - if (i) - goto err_out_unmap_tx; + ret = register_netdev(dev); + if (ret < 0) + goto err_out_unmap_rx; printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq); @@ -554,19 +571,24 @@ printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x.\n", dev->dev_addr[i]); - return 0; +out: + return ret; +err_out_unmap_rx: + pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma); err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma); err_out_iounmap: #ifndef USE_IO_OPS iounmap(ioaddr); -err_out_free_res: -#endif - pci_release_regions(pdev); err_out_free_netdev: +#endif free_netdev(dev); - return -ENODEV; +err_out_free_res: + pci_release_regions(pdev); +err_out_disable: + pci_disable_device(pdev); + goto out; } /* Serial EEPROM section. */ @@ -592,6 +614,38 @@ #define EE_READ256_CMD (6 << 8) #define EE_ERASE_CMD (7 << 6) +static void epic_disable_int(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(0x00000000, ioaddr + INTMASK); +} + +static inline void __epic_pci_commit(long ioaddr) +{ +#ifndef USE_IO_OPS + inl(ioaddr + INTMASK); +#endif +} + +static inline void epic_napi_irq_off(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + outl(ep->irq_mask & ~EpicNapiEvent, ioaddr + INTMASK); + __epic_pci_commit(ioaddr); +} + +static inline void epic_napi_irq_on(struct net_device *dev, + struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + + /* No need to commit possible posted write */ + outl(ep->irq_mask | EpicNapiEvent, ioaddr + INTMASK); +} + static int __devinit read_eeprom(long ioaddr, int location) { int i; @@ -752,9 +806,8 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); if (debug > 1) printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x " @@ -795,7 +848,7 @@ } /* Remove the packets on the Rx queue. */ - epic_rx(dev); + epic_rx(dev, RX_RING_SIZE); } static void epic_restart(struct net_device *dev) @@ -841,9 +894,9 @@ /* Enable interrupts by setting the interrupt mask. */ outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170) - | CntFull | TxUnderrun | TxDone | TxEmpty - | RxError | RxOverflow | RxFull | RxHeader | RxDone, - ioaddr + INTMASK); + | CntFull | TxUnderrun + | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK); + printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x" " interrupt %4.4x.\n", dev->name, (int)inl(ioaddr + COMMAND), (int)inl(ioaddr + GENCTL), @@ -929,7 +982,6 @@ int i; ep->tx_full = 0; - ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; ep->dirty_tx = ep->cur_tx = 0; ep->cur_rx = ep->dirty_rx = 0; ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); @@ -1029,6 +1081,76 @@ return 0; } +static void epic_tx_error(struct net_device *dev, struct epic_private *ep, + int status) +{ + struct net_device_stats *stats = &ep->stats; + +#ifndef final_version + /* There was an major error, log it. */ + if (debug > 1) + printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", + dev->name, status); +#endif + stats->tx_errors++; + if (status & 0x1050) + stats->tx_aborted_errors++; + if (status & 0x0008) + stats->tx_carrier_errors++; + if (status & 0x0040) + stats->tx_window_errors++; + if (status & 0x0010) + stats->tx_fifo_errors++; +} + +static void epic_tx(struct net_device *dev, struct epic_private *ep) +{ + unsigned int dirty_tx, cur_tx; + + /* + * Note: if this lock becomes a problem we can narrow the locked + * region at the cost of occasionally grabbing the lock more times. + */ + cur_tx = ep->cur_tx; + for (dirty_tx = ep->dirty_tx; cur_tx - dirty_tx > 0; dirty_tx++) { + struct sk_buff *skb; + int entry = dirty_tx % TX_RING_SIZE; + int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + + if (txstatus & DescOwn) + break; /* It still hasn't been Txed */ + + if (likely(txstatus & 0x0001)) { + ep->stats.collisions += (txstatus >> 8) & 15; + ep->stats.tx_packets++; + ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; + } else + epic_tx_error(dev, ep, txstatus); + + /* Free the original skb. */ + skb = ep->tx_skbuff[entry]; + pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + ep->tx_skbuff[entry] = 0; + } + +#ifndef final_version + if (cur_tx - dirty_tx > TX_RING_SIZE) { + printk(KERN_WARNING + "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", + dev->name, dirty_tx, cur_tx, ep->tx_full); + dirty_tx += TX_RING_SIZE; + } +#endif + ep->dirty_tx = dirty_tx; + if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { + /* The ring is no longer full, allow new TX entries. */ + ep->tx_full = 0; + netif_wake_queue(dev); + } +} + /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs) @@ -1036,135 +1158,71 @@ struct net_device *dev = dev_instance; struct epic_private *ep = dev->priv; long ioaddr = dev->base_addr; - int status, boguscnt = max_interrupt_work; unsigned int handled = 0; + int status; - do { - status = inl(ioaddr + INTSTAT); - /* Acknowledge all of the current interrupt sources ASAP. */ - outl(status & 0x00007fff, ioaddr + INTSTAT); - - if (debug > 4) - printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " - "intstat=%#8.8x.\n", - dev->name, status, (int)inl(ioaddr + INTSTAT)); - - if ((status & IntrSummary) == 0) - break; - handled = 1; + status = inl(ioaddr + INTSTAT); + /* Acknowledge all of the current interrupt sources ASAP. */ + outl(status & EpicNormalEvent, ioaddr + INTSTAT); - if (status & (RxDone | RxStarted | RxEarlyWarn | RxOverflow)) - epic_rx(dev); + if (debug > 4) { + printk(KERN_DEBUG "%s: Interrupt, status=%#8.8x new " + "intstat=%#8.8x.\n", dev->name, status, + (int)inl(ioaddr + INTSTAT)); + } - if (status & (TxEmpty | TxDone)) { - unsigned int dirty_tx, cur_tx; + if ((status & IntrSummary) == 0) + goto out; - /* Note: if this lock becomes a problem we can narrow the locked - region at the cost of occasionally grabbing the lock more - times. */ - spin_lock(&ep->lock); - cur_tx = ep->cur_tx; - dirty_tx = ep->dirty_tx; - for (; cur_tx - dirty_tx > 0; dirty_tx++) { - struct sk_buff *skb; - int entry = dirty_tx % TX_RING_SIZE; - int txstatus = le32_to_cpu(ep->tx_ring[entry].txstatus); + handled = 1; - if (txstatus & DescOwn) - break; /* It still hasn't been Txed */ + if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) { + spin_lock(&ep->napi_lock); + if (netif_rx_schedule_prep(dev)) { + epic_napi_irq_off(dev, ep); + __netif_rx_schedule(dev); + } else + ep->reschedule_in_poll++; + spin_unlock(&ep->napi_lock); + } + status &= ~EpicNapiEvent; - if ( ! (txstatus & 0x0001)) { - /* There was an major error, log it. */ -#ifndef final_version - if (debug > 1) - printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", - dev->name, txstatus); -#endif - ep->stats.tx_errors++; - if (txstatus & 0x1050) ep->stats.tx_aborted_errors++; - if (txstatus & 0x0008) ep->stats.tx_carrier_errors++; - if (txstatus & 0x0040) ep->stats.tx_window_errors++; - if (txstatus & 0x0010) ep->stats.tx_fifo_errors++; - } else { - ep->stats.collisions += (txstatus >> 8) & 15; - ep->stats.tx_packets++; - ep->stats.tx_bytes += ep->tx_skbuff[entry]->len; - } - - /* Free the original skb. */ - skb = ep->tx_skbuff[entry]; - pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - ep->tx_skbuff[entry] = 0; - } + /* Check uncommon events all at once. */ + if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { + if (status == EpicRemoved) + goto out; -#ifndef final_version - if (cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_WARNING "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, cur_tx, ep->tx_full); - dirty_tx += TX_RING_SIZE; - } -#endif - ep->dirty_tx = dirty_tx; - if (ep->tx_full - && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { - /* The ring is no longer full, allow new TX entries. */ - ep->tx_full = 0; - spin_unlock(&ep->lock); - netif_wake_queue(dev); - } else - spin_unlock(&ep->lock); - } + /* Always update the error counts to avoid overhead later. */ + ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); + ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); + ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - /* Check uncommon events all at once. */ - if (status & (CntFull | TxUnderrun | RxOverflow | RxFull | - PCIBusErr170 | PCIBusErr175)) { - if (status == 0xffffffff) /* Chip failed or removed (CardBus). */ - break; - /* Always update the error counts to avoid overhead later. */ - ep->stats.rx_missed_errors += inb(ioaddr + MPCNT); - ep->stats.rx_frame_errors += inb(ioaddr + ALICNT); - ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT); - - if (status & TxUnderrun) { /* Tx FIFO underflow. */ - ep->stats.tx_fifo_errors++; - outl(ep->tx_threshold += 128, ioaddr + TxThresh); - /* Restart the transmit process. */ - outl(RestartTx, ioaddr + COMMAND); - } - if (status & RxOverflow) { /* Missed a Rx frame. */ - ep->stats.rx_errors++; - } - if (status & (RxOverflow | RxFull)) - outw(RxQueued, ioaddr + COMMAND); - if (status & PCIBusErr170) { - printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n", - dev->name, status); - epic_pause(dev); - epic_restart(dev); - } - /* Clear all error sources. */ - outl(status & 0x7f18, ioaddr + INTSTAT); + if (status & TxUnderrun) { /* Tx FIFO underflow. */ + ep->stats.tx_fifo_errors++; + outl(ep->tx_threshold += 128, ioaddr + TxThresh); + /* Restart the transmit process. */ + outl(RestartTx, ioaddr + COMMAND); } - if (--boguscnt < 0) { - printk(KERN_ERR "%s: Too much work at interrupt, " - "IntrStatus=0x%8.8x.\n", - dev->name, status); - /* Clear all interrupt sources. */ - outl(0x0001ffff, ioaddr + INTSTAT); - break; + if (status & PCIBusErr170) { + printk(KERN_ERR "%s: PCI Bus Error! status %4.4x.\n", + dev->name, status); + epic_pause(dev); + epic_restart(dev); } - } while (1); + /* Clear all error sources. */ + outl(status & 0x7f18, ioaddr + INTSTAT); + } - if (debug > 3) - printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n", - dev->name, status); +out: + if (debug > 3) { + printk(KERN_DEBUG "%s: exit interrupt, intr_status=%#4.4x.\n", + dev->name, status); + } return IRQ_RETVAL(handled); } -static int epic_rx(struct net_device *dev) +static int epic_rx(struct net_device *dev, int budget) { struct epic_private *ep = dev->priv; int entry = ep->cur_rx % RX_RING_SIZE; @@ -1174,6 +1232,10 @@ if (debug > 4) printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry, ep->rx_ring[entry].rxstatus); + + if (rx_work_limit > budget) + rx_work_limit = budget; + /* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & cpu_to_le32(DescOwn)) == 0) { int status = le32_to_cpu(ep->rx_ring[entry].rxstatus); @@ -1234,7 +1296,7 @@ ep->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + netif_receive_skb(skb); dev->last_rx = jiffies; ep->stats.rx_packets++; ep->stats.rx_bytes += pkt_len; @@ -1262,6 +1324,65 @@ return work_done; } +static void epic_rx_err(struct net_device *dev, struct epic_private *ep) +{ + long ioaddr = dev->base_addr; + int status; + + status = inl(ioaddr + INTSTAT); + + if (status == EpicRemoved) + return; + if (status & RxOverflow) /* Missed a Rx frame. */ + ep->stats.rx_errors++; + if (status & (RxOverflow | RxFull)) + outw(RxQueued, ioaddr + COMMAND); +} + +static int epic_poll(struct net_device *dev, int *budget) +{ + struct epic_private *ep = dev->priv; + int work_done, orig_budget; + long ioaddr = dev->base_addr; + + orig_budget = (*budget > dev->quota) ? dev->quota : *budget; + +rx_action: + + epic_tx(dev, ep); + + work_done = epic_rx(dev, *budget); + + epic_rx_err(dev, ep); + + *budget -= work_done; + dev->quota -= work_done; + + if (netif_running(dev) && (work_done < orig_budget)) { + unsigned long flags; + int more; + + /* A bit baroque but it avoids a (space hungry) spin_unlock */ + + spin_lock_irqsave(&ep->napi_lock, flags); + + more = ep->reschedule_in_poll; + if (!more) { + __netif_rx_complete(dev); + outl(EpicNapiEvent, ioaddr + INTSTAT); + epic_napi_irq_on(dev, ep); + } else + ep->reschedule_in_poll--; + + spin_unlock_irqrestore(&ep->napi_lock, flags); + + if (more) + goto rx_action; + } + + return (work_done >= orig_budget); +} + static int epic_close(struct net_device *dev) { long ioaddr = dev->base_addr; @@ -1276,9 +1397,13 @@ dev->name, (int)inl(ioaddr + INTSTAT)); del_timer_sync(&ep->timer); - epic_pause(dev); + + epic_disable_int(dev, ep); + free_irq(dev->irq, dev); + epic_pause(dev); + /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { skb = ep->rx_skbuff[i]; @@ -1476,6 +1601,7 @@ #endif pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); /* pci_power_off(pdev, -1); */ } diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c 2004-05-31 16:18:26 -07:00 +++ b/drivers/net/r8169.c 2004-05-31 16:18:26 -07:00 @@ -64,6 +64,14 @@ #define dprintk(fmt, args...) do {} while (0) #endif /* RTL8169_DEBUG */ +#ifdef CONFIG_R8169_NAPI +#define rtl8169_rx_skb netif_receive_skb +#define rtl8169_rx_quota(count, quota) min(count, quota) +#else +#define rtl8169_rx_skb netif_rx +#define rtl8169_rx_quota(count, quota) count +#endif + /* media options */ #define MAX_UNITS 8 static int media[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; @@ -90,8 +98,9 @@ #define RxPacketMaxSize 0x0800 /* Maximum size supported is 16K-1 */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ +#define R8169_NAPI_WEIGHT 64 #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ +#define NUM_RX_DESC 256 /* Number of Rx descriptor registers */ #define RX_BUF_SIZE 1536 /* Rx Buffer size */ #define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) #define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) @@ -194,7 +203,7 @@ SWInt = 0x0100, TxDescUnavail = 0x80, RxFIFOOver = 0x40, - RxUnderrun = 0x20, + LinkChg = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, @@ -306,10 +315,10 @@ }; struct rtl8169_private { - void *mmio_addr; /* memory map physical address */ + void *mmio_addr; /* memory map physical address */ struct pci_dev *pci_dev; /* Index of PCI device */ struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ + spinlock_t lock; /* spin lock flag */ int chipset; int mac_version; int phy_version; @@ -317,15 +326,16 @@ u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ u32 dirty_rx; u32 dirty_tx; - struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */ - struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */ + struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ + struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ dma_addr_t TxPhyAddr; dma_addr_t RxPhyAddr; struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */ + struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffers */ struct timer_list timer; unsigned long phy_link_down_cnt; u16 cp_cmd; + u16 intr_mask; }; MODULE_AUTHOR("Realtek"); @@ -344,9 +354,14 @@ static void rtl8169_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 *netdev); +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget); +#endif static const u16 rtl8169_intr_mask = - RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; + LinkChg | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK; +static const u16 rtl8169_napi_event = + RxOK | LinkChg | RxOverflow | RxFIFOOver | TxOK | TxErr; static const unsigned int rtl8169_rx_config = (RX_FIFO_THRESH << RxCfgFIFOShift) | (RX_DMA_BURST << RxCfgDMAShift); @@ -364,11 +379,9 @@ for (i = 2000; i > 0; i--) { // Check if the RTL8169 has completed writing to the specified MII register - if (!(RTL_R32(PHYAR) & 0x80000000)) { + if (!(RTL_R32(PHYAR) & 0x80000000)) break; - } else { - udelay(100); - } + udelay(100); } } @@ -393,7 +406,7 @@ static void rtl8169_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); strcpy(info->driver, RTL8169_DRIVER_NAME); strcpy(info->version, RTL8169_VERSION ); @@ -500,7 +513,7 @@ static void rtl8169_hw_phy_config(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; struct { u16 regs[5]; /* Beware of bit-sign propagation */ @@ -568,7 +581,7 @@ static void rtl8169_hw_phy_reset(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; int i, val; @@ -592,7 +605,7 @@ static void rtl8169_phy_timer(unsigned long __opaque) { struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; void *ioaddr = tp->mmio_addr; @@ -620,7 +633,7 @@ static inline void rtl8169_delete_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -634,7 +647,7 @@ static inline void rtl8169_request_timer(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct timer_list *timer = &tp->timer; if ((tp->mac_version <= RTL_GIGA_MAC_VER_B) || @@ -681,7 +694,7 @@ // enable device (incl. PCI PM wakeup and hotplug setup) rc = pci_enable_device(pdev); if (rc) { - printk(KERN_ERR PFX "%s: unable to enable device\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name); goto err_out; } @@ -693,7 +706,8 @@ pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } else { - printk(KERN_ERR PFX "Cannot find PowerManagement capability, aborting.\n"); + printk(KERN_ERR PFX + "Cannot find PowerManagement capability, aborting.\n"); goto err_out_free_res; } @@ -718,7 +732,8 @@ rc = pci_request_regions(pdev, dev->name); if (rc) { - printk(KERN_ERR PFX "%s: Could not request regions.\n", pdev->slot_name); + printk(KERN_ERR PFX "%s: could not request regions.\n", + pdev->slot_name); goto err_out_disable; } @@ -836,9 +851,12 @@ dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; -// dev->do_ioctl = mii_ioctl; - - tp = dev->priv; // private data // +#ifdef CONFIG_R8169_NAPI + dev->poll = rtl8169_poll; + dev->weight = R8169_NAPI_WEIGHT; + printk(KERN_INFO PFX "NAPI enabled\n"); +#endif + tp->intr_mask = 0xffff; tp->pci_dev = pdev; tp->mmio_addr = ioaddr; @@ -919,13 +937,16 @@ default: break; } - mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F)); //leave PHY_AUTO_NEGO_REG bit4:0 unchanged + // leave PHY_AUTO_NEGO_REG bit4:0 unchanged + mdio_write(ioaddr, PHY_AUTO_NEGO_REG, + Cap10_100 | (val & 0x1F)); mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000); } else { printk(KERN_INFO "%s: Auto-negotiation Enabled.\n", dev->name); - // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged + // enable 10/100 Full/Half Mode + // leave PHY_AUTO_NEGO_REG bit4:0 unchanged mdio_write(ioaddr, PHY_AUTO_NEGO_REG, PHY_Cap_100_Full_Or_Less | (val & 0x1f)); @@ -964,7 +985,7 @@ } else { udelay(100); } - } // end for-loop to wait for auto-negotiation process + } // end for-loop to wait for auto-negotiation process } else { udelay(100); @@ -972,7 +993,6 @@ "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n", dev->name, (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed"); - } return 0; @@ -982,7 +1002,7 @@ rtl8169_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); assert(dev != NULL); assert(tp != NULL); @@ -1001,7 +1021,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, u32 state) { struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -1042,7 +1062,7 @@ static int rtl8169_open(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; int retval; @@ -1091,7 +1111,7 @@ static void rtl8169_hw_start(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u32 i; @@ -1102,8 +1122,7 @@ for (i = 1000; i > 0; i--) { if ((RTL_R8(ChipCmd) & CmdReset) == 0) break; - else - udelay(10); + udelay(10); } RTL_W8(Cfg9346, Cfg9346_Unlock); @@ -1114,8 +1133,8 @@ RTL_W16(RxMaxSize, RxPacketMaxSize); // Set Rx Config register - i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset]. - RxConfigMask); + i = rtl8169_rx_config | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, i); /* Set DMA burst size and Interframe Gap Time */ @@ -1126,7 +1145,8 @@ RTL_W16(CPlusCmd, tp->cp_cmd); if (tp->mac_version == RTL_GIGA_MAC_VER_D) { - dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n"); + dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0. " + "Bit-3 and bit-14 MUST be 1\n"); tp->cp_cmd |= (1 << 14) | PCIMulRW; RTL_W16(CPlusCmd, tp->cp_cmd); } @@ -1151,7 +1171,6 @@ RTL_W16(IntrMask, rtl8169_intr_mask); netif_start_queue(dev); - } static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) @@ -1248,7 +1267,7 @@ static int rtl8169_init_ring(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); tp->cur_rx = tp->dirty_rx = 0; tp->cur_tx = tp->dirty_tx = 0; @@ -1302,10 +1321,11 @@ static void rtl8169_tx_timeout(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; u8 tmp8; + printk(KERN_INFO "%s: TX Timeout\n", dev->name); /* disable Tx, if not already */ tmp8 = RTL_R8(ChipCmd); if (tmp8 & CmdTxEnb) @@ -1328,9 +1348,9 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned int entry = tp->cur_tx % NUM_TX_DESC; u32 len = skb->len; if (unlikely(skb->len < ETH_ZLEN)) { @@ -1382,7 +1402,7 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); @@ -1392,7 +1412,7 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { - int entry = dirty_tx % NUM_TX_DESC; + unsigned int entry = dirty_tx % NUM_TX_DESC; struct sk_buff *skb = tp->Tx_skbuff[entry]; u32 status; @@ -1442,11 +1462,11 @@ return ret; } -static void +static int rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp, void *ioaddr) { - unsigned long cur_rx, rx_left; + unsigned int cur_rx, rx_left, count; int delta; assert(dev != NULL); @@ -1455,9 +1475,10 @@ cur_rx = tp->cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; + rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota); while (rx_left > 0) { - int entry = cur_rx % NUM_RX_DESC; + unsigned int entry = cur_rx % NUM_RX_DESC; u32 status; rmb(); @@ -1494,7 +1515,7 @@ skb_put(skb, pkt_size); skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); + rtl8169_rx_skb(skb); dev->last_rx = jiffies; tp->stats.rx_bytes += pkt_size; @@ -1505,13 +1526,15 @@ rx_left--; } + count = cur_rx - tp->cur_rx; tp->cur_rx = cur_rx; delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx); - if (delta > 0) - tp->dirty_rx += delta; - else if (delta < 0) + if (delta < 0) { printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); + delta = 0; + } + tp->dirty_rx += delta; /* * FIXME: until there is periodic timer to try and refill the ring, @@ -1522,6 +1545,8 @@ */ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); + + return count; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ @@ -1529,7 +1554,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0; @@ -1544,17 +1569,30 @@ handled = 1; /* - if (status & RxUnderrun) + if (status & LinkChg) link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit; */ + status &= tp->intr_mask; RTL_W16(IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status); if (!(status & rtl8169_intr_mask)) break; +#ifdef CONFIG_R8169_NAPI + RTL_W16(IntrMask, rtl8169_intr_mask & ~rtl8169_napi_event); + tp->intr_mask = ~rtl8169_napi_event; + + if (likely(netif_rx_schedule_prep(dev))) + __netif_rx_schedule(dev); + else { + printk(KERN_INFO "%s: interrupt %x taken in poll\n", + dev->name, status); + } + break; +#else // Rx interrupt - if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver)) { + if (status & (RxOK | LinkChg | RxOverflow | RxFIFOOver)) { rtl8169_rx_interrupt(dev, tp, ioaddr); } // Tx interrupt @@ -1563,6 +1601,7 @@ rtl8169_tx_interrupt(dev, tp, ioaddr); spin_unlock(&tp->lock); } +#endif boguscnt--; } while (boguscnt > 0); @@ -1576,10 +1615,40 @@ return IRQ_RETVAL(handled); } +#ifdef CONFIG_R8169_NAPI +static int rtl8169_poll(struct net_device *dev, int *budget) +{ + unsigned int work_done, work_to_do = min(*budget, dev->quota); + struct rtl8169_private *tp = netdev_priv(dev); + void *ioaddr = tp->mmio_addr; + + work_done = rtl8169_rx_interrupt(dev, tp, ioaddr); + rtl8169_tx_interrupt(dev, tp, ioaddr); + + *budget -= work_done; + dev->quota -= work_done; + + if ((work_done < work_to_do) || !netif_running(dev)) { + netif_rx_complete(dev); + tp->intr_mask = 0xffff; + /* + * 20040426: the barrier is not strictly required but the + * behavior of the irq handler could be less predictable + * without it. Btw, the lack of flush for the posted pci + * write is safe - FR + */ + smp_wmb(); + RTL_W16(IntrMask, rtl8169_intr_mask); + } + + return (work_done >= work_to_do); +} +#endif + static int rtl8169_close(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); struct pci_dev *pdev = tp->pci_dev; void *ioaddr = tp->mmio_addr; @@ -1621,7 +1690,7 @@ static void rtl8169_set_rx_mode(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags; u32 mc_filter[2]; /* Multicast hash filter */ @@ -1655,10 +1724,8 @@ spin_lock_irqsave(&tp->lock, flags); - tmp = - rtl8169_rx_config | rx_mode | (RTL_R32(RxConfig) & - rtl_chip_info[tp->chipset]. - RxConfigMask); + tmp = rtl8169_rx_config | rx_mode | + (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); RTL_W32(RxConfig, tmp); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -1675,7 +1742,7 @@ */ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) { - struct rtl8169_private *tp = dev->priv; + struct rtl8169_private *tp = netdev_priv(dev); void *ioaddr = tp->mmio_addr; unsigned long flags;