aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ixgb
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-03 19:41:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:45 -0400
commitbea3348eef27e6044b6161fd04c3152215f96411 (patch)
treef0990b263e5ce42505d290a4c346fe990bcd4c33 /drivers/net/ixgb
parentdde4e47e8fe333a5649a3fa0e7db1fa7c08d6158 (diff)
[NET]: Make NAPI polling independent of struct net_device objects.
Several devices have multiple independant RX queues per net device, and some have a single interrupt doorbell for several queues. In either case, it's easier to support layouts like that if the structure representing the poll is independant from the net device itself. The signature of the ->poll() call back goes from: int foo_poll(struct net_device *dev, int *budget) to int foo_poll(struct napi_struct *napi, int budget) The caller is returned the number of RX packets processed (or the number of "NAPI credits" consumed if you want to get abstract). The callee no longer messes around bumping dev->quota, *budget, etc. because that is all handled in the caller upon return. The napi_struct is to be embedded in the device driver private data structures. Furthermore, it is the driver's responsibility to disable all NAPI instances in it's ->stop() device close handler. Since the napi_struct is privatized into the driver's private data structures, only the driver knows how to get at all of the napi_struct instances it may have per-device. With lots of help and suggestions from Rusty Russell, Roland Dreier, Michael Chan, Jeff Garzik, and Jamal Hadi Salim. Bug fixes from Thomas Graf, Roland Dreier, Peter Zijlstra, Joseph Fannin, Scott Wood, Hans J. Koch, and Michael Chan. [ Ported to current tree and all drivers converted. Integrated Stephen's follow-on kerneldoc additions, and restored poll_list handling to the old style to fix mutual exclusion issues. -DaveM ] Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ixgb')
-rw-r--r--drivers/net/ixgb/ixgb.h1
-rw-r--r--drivers/net/ixgb/ixgb_main.c29
2 files changed, 13 insertions, 17 deletions
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 3569d5b03388..1eee8894c732 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -184,6 +184,7 @@ struct ixgb_adapter {
184 boolean_t rx_csum; 184 boolean_t rx_csum;
185 185
186 /* OS defined structs */ 186 /* OS defined structs */
187 struct napi_struct napi;
187 struct net_device *netdev; 188 struct net_device *netdev;
188 struct pci_dev *pdev; 189 struct pci_dev *pdev;
189 struct net_device_stats net_stats; 190 struct net_device_stats net_stats;
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 991c8833e23c..e3f27c67fb28 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -97,7 +97,7 @@ static irqreturn_t ixgb_intr(int irq, void *data);
97static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter); 97static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
98 98
99#ifdef CONFIG_IXGB_NAPI 99#ifdef CONFIG_IXGB_NAPI
100static int ixgb_clean(struct net_device *netdev, int *budget); 100static int ixgb_clean(struct napi_struct *napi, int budget);
101static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, 101static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
102 int *work_done, int work_to_do); 102 int *work_done, int work_to_do);
103#else 103#else
@@ -288,7 +288,7 @@ ixgb_up(struct ixgb_adapter *adapter)
288 mod_timer(&adapter->watchdog_timer, jiffies); 288 mod_timer(&adapter->watchdog_timer, jiffies);
289 289
290#ifdef CONFIG_IXGB_NAPI 290#ifdef CONFIG_IXGB_NAPI
291 netif_poll_enable(netdev); 291 napi_enable(&adapter->napi);
292#endif 292#endif
293 ixgb_irq_enable(adapter); 293 ixgb_irq_enable(adapter);
294 294
@@ -309,7 +309,7 @@ ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog)
309 if(kill_watchdog) 309 if(kill_watchdog)
310 del_timer_sync(&adapter->watchdog_timer); 310 del_timer_sync(&adapter->watchdog_timer);
311#ifdef CONFIG_IXGB_NAPI 311#ifdef CONFIG_IXGB_NAPI
312 netif_poll_disable(netdev); 312 napi_disable(&adapter->napi);
313#endif 313#endif
314 adapter->link_speed = 0; 314 adapter->link_speed = 0;
315 adapter->link_duplex = 0; 315 adapter->link_duplex = 0;
@@ -421,8 +421,7 @@ ixgb_probe(struct pci_dev *pdev,
421 netdev->tx_timeout = &ixgb_tx_timeout; 421 netdev->tx_timeout = &ixgb_tx_timeout;
422 netdev->watchdog_timeo = 5 * HZ; 422 netdev->watchdog_timeo = 5 * HZ;
423#ifdef CONFIG_IXGB_NAPI 423#ifdef CONFIG_IXGB_NAPI
424 netdev->poll = &ixgb_clean; 424 netif_napi_add(netdev, &adapter->napi, ixgb_clean, 64);
425 netdev->weight = 64;
426#endif 425#endif
427 netdev->vlan_rx_register = ixgb_vlan_rx_register; 426 netdev->vlan_rx_register = ixgb_vlan_rx_register;
428 netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid; 427 netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
@@ -1746,7 +1745,7 @@ ixgb_intr(int irq, void *data)
1746 } 1745 }
1747 1746
1748#ifdef CONFIG_IXGB_NAPI 1747#ifdef CONFIG_IXGB_NAPI
1749 if(netif_rx_schedule_prep(netdev)) { 1748 if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
1750 1749
1751 /* Disable interrupts and register for poll. The flush 1750 /* Disable interrupts and register for poll. The flush
1752 of the posted write is intentionally left out. 1751 of the posted write is intentionally left out.
@@ -1754,7 +1753,7 @@ ixgb_intr(int irq, void *data)
1754 1753
1755 atomic_inc(&adapter->irq_sem); 1754 atomic_inc(&adapter->irq_sem);
1756 IXGB_WRITE_REG(&adapter->hw, IMC, ~0); 1755 IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
1757 __netif_rx_schedule(netdev); 1756 __netif_rx_schedule(netdev, &adapter->napi);
1758 } 1757 }
1759#else 1758#else
1760 /* yes, that is actually a & and it is meant to make sure that 1759 /* yes, that is actually a & and it is meant to make sure that
@@ -1776,27 +1775,23 @@ ixgb_intr(int irq, void *data)
1776 **/ 1775 **/
1777 1776
1778static int 1777static int
1779ixgb_clean(struct net_device *netdev, int *budget) 1778ixgb_clean(struct napi_struct *napi, int budget)
1780{ 1779{
1781 struct ixgb_adapter *adapter = netdev_priv(netdev); 1780 struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi);
1782 int work_to_do = min(*budget, netdev->quota); 1781 struct net_device *netdev = adapter->netdev;
1783 int tx_cleaned; 1782 int tx_cleaned;
1784 int work_done = 0; 1783 int work_done = 0;
1785 1784
1786 tx_cleaned = ixgb_clean_tx_irq(adapter); 1785 tx_cleaned = ixgb_clean_tx_irq(adapter);
1787 ixgb_clean_rx_irq(adapter, &work_done, work_to_do); 1786 ixgb_clean_rx_irq(adapter, &work_done, budget);
1788
1789 *budget -= work_done;
1790 netdev->quota -= work_done;
1791 1787
1792 /* if no Tx and not enough Rx work done, exit the polling mode */ 1788 /* if no Tx and not enough Rx work done, exit the polling mode */
1793 if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { 1789 if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
1794 netif_rx_complete(netdev); 1790 netif_rx_complete(netdev, napi);
1795 ixgb_irq_enable(adapter); 1791 ixgb_irq_enable(adapter);
1796 return 0;
1797 } 1792 }
1798 1793
1799 return 1; 1794 return work_done;
1800} 1795}
1801#endif 1796#endif
1802 1797