aboutsummaryrefslogtreecommitdiff
path: root/net/core/netpoll.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-30 08:08:40 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-30 08:08:40 -0700
commit2d175d438f297bcd75a7b88baf3a304137047af6 (patch)
tree22fa745d13f85dd8fd74bb35ba0e3bf01cab12f8 /net/core/netpoll.c
parentc2db6376c934b9e4c0b905bee5222d5475bbd98a (diff)
parent502ef38da15d817f8e67acefc12dc2212f7f8aa1 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: [TIPC]: Add tipc_config.h to include/linux/Kbuild. [WAN]: lmc_ioctl: don't return with locks held [SUNRPC]: fix rpc debugging [TCP]: Saner thash_entries default with much memory. [SUNRPC] rpc_rdma: we need to cast u64 to unsigned long long for printing [IPv4] SNMP: Refer correct memory location to display ICMP out-going statistics [NET]: Fix error reporting in sys_socketpair(). [NETFILTER]: nf_ct_alloc_hashtable(): use __GFP_NOWARN [NET]: Fix race between poll_napi() and net_rx_action() [TCP] MD5: Remove some more unnecessary casting. [TCP] vegas: Fix a bug in disabling slow start by gamma parameter. [IPVS]: use proper timeout instead of fixed value [IPV6] NDISC: Fix setting base_reachable_time_ms variable.
Diffstat (limited to 'net/core/netpoll.c')
-rw-r--r--net/core/netpoll.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index bf8d18f1b013..c499b5c69bed 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -116,6 +116,29 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
* network adapter, forcing superfluous retries and possibly timeouts.
* Thus, we set our budget to greater than 1.
*/
+static int poll_one_napi(struct netpoll_info *npinfo,
+ struct napi_struct *napi, int budget)
+{
+ int work;
+
+ /* net_rx_action's ->poll() invocations and our's are
+ * synchronized by this test which is only made while
+ * holding the napi->poll_lock.
+ */
+ if (!test_bit(NAPI_STATE_SCHED, &napi->state))
+ return budget;
+
+ npinfo->rx_flags |= NETPOLL_RX_DROP;
+ atomic_inc(&trapped);
+
+ work = napi->poll(napi, budget);
+
+ atomic_dec(&trapped);
+ npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+
+ return budget - work;
+}
+
static void poll_napi(struct netpoll *np)
{
struct netpoll_info *npinfo = np->dev->npinfo;
@@ -123,17 +146,13 @@ static void poll_napi(struct netpoll *np)
int budget = 16;
list_for_each_entry(napi, &np->dev->napi_list, dev_list) {
- if (test_bit(NAPI_STATE_SCHED, &napi->state) &&
- napi->poll_owner != smp_processor_id() &&
+ if (napi->poll_owner != smp_processor_id() &&
spin_trylock(&napi->poll_lock)) {
- npinfo->rx_flags |= NETPOLL_RX_DROP;
- atomic_inc(&trapped);
-
- napi->poll(napi, budget);
-
- atomic_dec(&trapped);
- npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+ budget = poll_one_napi(npinfo, napi, budget);
spin_unlock(&napi->poll_lock);
+
+ if (!budget)
+ break;
}
}
}