Blame view

net/core/netpoll.c 21.3 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   * Common framework for low-level network console, dump, and debugger code
   *
   * Sep 8 2003  Matt Mackall <mpm@selenic.com>
   *
   * based on the netconsole code from:
   *
   * Copyright (C) 2001  Ingo Molnar <mingo@redhat.com>
   * Copyright (C) 2002  Red Hat, Inc.
   */
bff38771e   Anton Vorontsov   netpoll: Introduc...
11
  #include <linux/moduleparam.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/string.h>
14c850212   Arnaldo Carvalho de Melo   [INET_SOCK]: Move...
15
  #include <linux/if_arp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
21
22
23
  #include <linux/inetdevice.h>
  #include <linux/inet.h>
  #include <linux/interrupt.h>
  #include <linux/netpoll.h>
  #include <linux/sched.h>
  #include <linux/delay.h>
  #include <linux/rcupdate.h>
  #include <linux/workqueue.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
25
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  #include <net/tcp.h>
  #include <net/udp.h>
  #include <asm/unaligned.h>
9cbc1cb8c   David S. Miller   Merge branch 'mas...
29
  #include <trace/events/napi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
36
37
  
  /*
   * We maintain a small pool of fully-sized skbs, to make sure the
   * message gets out even in extreme OOM situations.
   */
  
  #define MAX_UDP_CHUNK 1460
  #define MAX_SKBS 32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

a1bcfacd0   Stephen Hemminger   netpoll: private ...
39
  static struct sk_buff_head skb_pool;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
  
  static atomic_t trapped;
2bdfe0bae   Stephen Hemminger   netpoll retry cle...
42
  #define USEC_PER_POLL	50
d9452e9f8   David S. Miller   [NETPOLL]: Revert...
43
44
  #define NETPOLL_RX_ENABLED  1
  #define NETPOLL_RX_DROP     2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  
  #define MAX_SKB_SIZE \
  		(MAX_UDP_CHUNK + sizeof(struct udphdr) + \
  				sizeof(struct iphdr) + sizeof(struct ethhdr))
3578b0c8a   David S. Miller   Revert "net: remo...
49
  static void zap_completion_queue(void);
068c6e98b   Neil Horman   [NET] netpoll: br...
50
  static void arp_reply(struct sk_buff *skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

bff38771e   Anton Vorontsov   netpoll: Introduc...
52
53
  static unsigned int carrier_timeout = 4;
  module_param(carrier_timeout, uint, 0644);
c4028958b   David Howells   WorkStruct: make ...
54
  static void queue_process(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
  {
4c1ac1b49   David Howells   Merge branch 'mas...
56
57
  	struct netpoll_info *npinfo =
  		container_of(work, struct netpoll_info, tx_work.work);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  	struct sk_buff *skb;
3640543df   Ingo Molnar   [PATCH] netpoll: ...
59
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60

6c43ff18f   Stephen Hemminger   netpoll deferred ...
61
62
  	while ((skb = skb_dequeue(&npinfo->txq))) {
  		struct net_device *dev = skb->dev;
008298231   Stephen Hemminger   netdev: add more ...
63
  		const struct net_device_ops *ops = dev->netdev_ops;
fd2ea0a79   David S. Miller   net: Use queue aw...
64
  		struct netdev_queue *txq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65

6c43ff18f   Stephen Hemminger   netpoll deferred ...
66
67
68
69
  		if (!netif_device_present(dev) || !netif_running(dev)) {
  			__kfree_skb(skb);
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

fd2ea0a79   David S. Miller   net: Use queue aw...
71
  		txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
3640543df   Ingo Molnar   [PATCH] netpoll: ...
72
  		local_irq_save(flags);
fd2ea0a79   David S. Miller   net: Use queue aw...
73
  		__netif_tx_lock(txq, smp_processor_id());
734664982   Tom Herbert   net: Add queue st...
74
  		if (netif_xmit_frozen_or_stopped(txq) ||
008298231   Stephen Hemminger   netdev: add more ...
75
  		    ops->ndo_start_xmit(skb, dev) != NETDEV_TX_OK) {
6c43ff18f   Stephen Hemminger   netpoll deferred ...
76
  			skb_queue_head(&npinfo->txq, skb);
fd2ea0a79   David S. Miller   net: Use queue aw...
77
  			__netif_tx_unlock(txq);
3640543df   Ingo Molnar   [PATCH] netpoll: ...
78
  			local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79

25442cafb   Jarek Poplawski   [NETPOLL]: Fixups...
80
  			schedule_delayed_work(&npinfo->tx_work, HZ/10);
6c43ff18f   Stephen Hemminger   netpoll deferred ...
81
82
  			return;
  		}
fd2ea0a79   David S. Miller   net: Use queue aw...
83
  		__netif_tx_unlock(txq);
3640543df   Ingo Molnar   [PATCH] netpoll: ...
84
  		local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  }
b51655b95   Al Viro   [NET]: Annotate _...
87
88
  static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
  			    unsigned short ulen, __be32 saddr, __be32 daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
d6f5493c1   Al Viro   [NET]: Annotate c...
90
  	__wsum psum;
fb286bb29   Herbert Xu   [NET]: Detect har...
91

604763722   Herbert Xu   [NET]: Treat CHEC...
92
  	if (uh->check == 0 || skb_csum_unnecessary(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
  		return 0;
fb286bb29   Herbert Xu   [NET]: Detect har...
94
  	psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
84fa7933a   Patrick McHardy   [NET]: Replace CH...
95
  	if (skb->ip_summed == CHECKSUM_COMPLETE &&
d3bc23e7e   Al Viro   [NET]: Annotate c...
96
  	    !csum_fold(csum_add(psum, skb->csum)))
fb286bb29   Herbert Xu   [NET]: Detect har...
97
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98

fb286bb29   Herbert Xu   [NET]: Detect har...
99
  	skb->csum = psum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100

fb286bb29   Herbert Xu   [NET]: Detect har...
101
  	return __skb_checksum_complete(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  }
  
  /*
   * Check whether delayed processing was scheduled for our NIC. If so,
   * we attempt to grab the poll lock and use ->poll() to pump the card.
   * If this fails, either we've recursed in ->poll() or it's already
   * running on another CPU.
   *
   * Note: we don't mask interrupts with this lock because we're using
   * trylock here and interrupts are already disabled in the softirq
   * case. Further, we test the poll_owner to avoid recursion on UP
   * systems where the lock doesn't exist.
   *
   * In cases where there is bi-directional communications, reading only
   * one message at a time can lead to packets being dropped by the
   * network adapter, forcing superfluous retries and possibly timeouts.
   * Thus, we set our budget to greater than 1.
   */
0a7606c12   David S. Miller   [NET]: Fix race b...
120
121
122
123
124
125
126
127
128
129
130
  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;
d9452e9f8   David S. Miller   [NETPOLL]: Revert...
131
  	npinfo->rx_flags |= NETPOLL_RX_DROP;
0a7606c12   David S. Miller   [NET]: Fix race b...
132
  	atomic_inc(&trapped);
7b363e440   Neil Horman   netpoll: fix race...
133
  	set_bit(NAPI_STATE_NPSVC, &napi->state);
0a7606c12   David S. Miller   [NET]: Fix race b...
134
135
  
  	work = napi->poll(napi, budget);
7d18f1148   David S. Miller   net: Fix arg to t...
136
  	trace_napi_poll(napi);
0a7606c12   David S. Miller   [NET]: Fix race b...
137

7b363e440   Neil Horman   netpoll: fix race...
138
  	clear_bit(NAPI_STATE_NPSVC, &napi->state);
0a7606c12   David S. Miller   [NET]: Fix race b...
139
  	atomic_dec(&trapped);
d9452e9f8   David S. Miller   [NETPOLL]: Revert...
140
  	npinfo->rx_flags &= ~NETPOLL_RX_DROP;
0a7606c12   David S. Miller   [NET]: Fix race b...
141
142
143
  
  	return budget - work;
  }
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
144
  static void poll_napi(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  {
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
146
  	struct napi_struct *napi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	int budget = 16;
f13d493d9   Neil Horman   netpoll: Revert n...
148
  	list_for_each_entry(napi, &dev->napi_list, dev_list) {
0a7606c12   David S. Miller   [NET]: Fix race b...
149
  		if (napi->poll_owner != smp_processor_id() &&
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
150
  		    spin_trylock(&napi->poll_lock)) {
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
151
  			budget = poll_one_napi(dev->npinfo, napi, budget);
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
152
  			spin_unlock(&napi->poll_lock);
0a7606c12   David S. Miller   [NET]: Fix race b...
153
154
155
  
  			if (!budget)
  				break;
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
156
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
  	}
  }
068c6e98b   Neil Horman   [NET] netpoll: br...
159
160
  static void service_arp_queue(struct netpoll_info *npi)
  {
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
161
162
  	if (npi) {
  		struct sk_buff *skb;
068c6e98b   Neil Horman   [NET] netpoll: br...
163

5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
164
165
  		while ((skb = skb_dequeue(&npi->arp_tx)))
  			arp_reply(skb);
068c6e98b   Neil Horman   [NET] netpoll: br...
166
  	}
068c6e98b   Neil Horman   [NET] netpoll: br...
167
  }
234b921db   Joe Perches   netpoll: Remove u...
168
  static void netpoll_poll_dev(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  {
5e392739d   Pavel Emelyanov   netpoll: don't de...
170
  	const struct net_device_ops *ops;
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
171

5e392739d   Pavel Emelyanov   netpoll: don't de...
172
173
174
175
176
  	if (!dev || !netif_running(dev))
  		return;
  
  	ops = dev->netdev_ops;
  	if (!ops->ndo_poll_controller)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
178
179
  		return;
  
  	/* Process pending work on NIC */
d314774cf   Stephen Hemminger   netdev: network d...
180
  	ops->ndo_poll_controller(dev);
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
181
182
  
  	poll_napi(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

5a698af53   Amerigo Wang   bond: service net...
184
185
186
187
188
189
190
191
192
193
  	if (dev->priv_flags & IFF_SLAVE) {
  		if (dev->npinfo) {
  			struct net_device *bond_dev = dev->master;
  			struct sk_buff *skb;
  			while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) {
  				skb->dev = bond_dev;
  				skb_queue_tail(&bond_dev->npinfo->arp_tx, skb);
  			}
  		}
  	}
5106930bd   Stephen Hemminger   [NETPOLL]: netpol...
194
  	service_arp_queue(dev->npinfo);
068c6e98b   Neil Horman   [NET] netpoll: br...
195

3578b0c8a   David S. Miller   Revert "net: remo...
196
  	zap_completion_queue();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
200
201
202
  }
  
  static void refill_skbs(void)
  {
  	struct sk_buff *skb;
  	unsigned long flags;
a1bcfacd0   Stephen Hemminger   netpoll: private ...
203
204
  	spin_lock_irqsave(&skb_pool.lock, flags);
  	while (skb_pool.qlen < MAX_SKBS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
206
207
  		skb = alloc_skb(MAX_SKB_SIZE, GFP_ATOMIC);
  		if (!skb)
  			break;
a1bcfacd0   Stephen Hemminger   netpoll: private ...
208
  		__skb_queue_tail(&skb_pool, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
  	}
a1bcfacd0   Stephen Hemminger   netpoll: private ...
210
  	spin_unlock_irqrestore(&skb_pool.lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  }
3578b0c8a   David S. Miller   Revert "net: remo...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  static void zap_completion_queue(void)
  {
  	unsigned long flags;
  	struct softnet_data *sd = &get_cpu_var(softnet_data);
  
  	if (sd->completion_queue) {
  		struct sk_buff *clist;
  
  		local_irq_save(flags);
  		clist = sd->completion_queue;
  		sd->completion_queue = NULL;
  		local_irq_restore(flags);
  
  		while (clist != NULL) {
  			struct sk_buff *skb = clist;
  			clist = clist->next;
  			if (skb->destructor) {
  				atomic_inc(&skb->users);
  				dev_kfree_skb_any(skb); /* put this one back */
  			} else {
  				__kfree_skb(skb);
  			}
  		}
  	}
  
  	put_cpu_var(softnet_data);
  }
a1bcfacd0   Stephen Hemminger   netpoll: private ...
239
  static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
  {
a1bcfacd0   Stephen Hemminger   netpoll: private ...
241
242
  	int count = 0;
  	struct sk_buff *skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243

3578b0c8a   David S. Miller   Revert "net: remo...
244
  	zap_completion_queue();
a1bcfacd0   Stephen Hemminger   netpoll: private ...
245
  	refill_skbs();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  repeat:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
  
  	skb = alloc_skb(len, GFP_ATOMIC);
a1bcfacd0   Stephen Hemminger   netpoll: private ...
249
250
  	if (!skb)
  		skb = skb_dequeue(&skb_pool);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
  
  	if (!skb) {
a1bcfacd0   Stephen Hemminger   netpoll: private ...
253
  		if (++count < 10) {
2a49e001c   Joe Perches   netpoll: Remove w...
254
  			netpoll_poll_dev(np->dev);
a1bcfacd0   Stephen Hemminger   netpoll: private ...
255
  			goto repeat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
  		}
a1bcfacd0   Stephen Hemminger   netpoll: private ...
257
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
  	}
  
  	atomic_set(&skb->users, 1);
  	skb_reserve(skb, reserve);
  	return skb;
  }
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
264
265
266
267
268
269
270
271
272
273
  static int netpoll_owner_active(struct net_device *dev)
  {
  	struct napi_struct *napi;
  
  	list_for_each_entry(napi, &dev->napi_list, dev_list) {
  		if (napi->poll_owner == smp_processor_id())
  			return 1;
  	}
  	return 0;
  }
c2355e1ab   Neil Horman   bonding: Fix bond...
274
275
  void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
  			     struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  {
2bdfe0bae   Stephen Hemminger   netpoll retry cle...
277
278
  	int status = NETDEV_TX_BUSY;
  	unsigned long tries;
008298231   Stephen Hemminger   netdev: add more ...
279
  	const struct net_device_ops *ops = dev->netdev_ops;
de85d99eb   Herbert Xu   netpoll: Fix RCU ...
280
  	/* It is up to the caller to keep npinfo alive. */
4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
281
  	struct netpoll_info *npinfo = np->dev->npinfo;
2bdfe0bae   Stephen Hemminger   netpoll retry cle...
282

4ec93edb1   YOSHIFUJI Hideaki   [NET] CORE: Fix w...
283
284
285
286
  	if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
  		__kfree_skb(skb);
  		return;
  	}
2bdfe0bae   Stephen Hemminger   netpoll retry cle...
287
288
  
  	/* don't get messages out of order, and no recursion */
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
289
  	if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
fd2ea0a79   David S. Miller   net: Use queue aw...
290
  		struct netdev_queue *txq;
a49f99ffc   Andrew Morton   [NETPOLL]: Fix lo...
291
  		unsigned long flags;
fd2ea0a79   David S. Miller   net: Use queue aw...
292
  		txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
a49f99ffc   Andrew Morton   [NETPOLL]: Fix lo...
293
  		local_irq_save(flags);
0db3dc73f   Stephen Hemminger   [NETPOLL]: tx loc...
294
295
296
  		/* try until next clock tick */
  		for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
  		     tries > 0; --tries) {
fd2ea0a79   David S. Miller   net: Use queue aw...
297
  			if (__netif_tx_trylock(txq)) {
734664982   Tom Herbert   net: Add queue st...
298
  				if (!netif_xmit_stopped(txq)) {
008298231   Stephen Hemminger   netdev: add more ...
299
  					status = ops->ndo_start_xmit(skb, dev);
08baf5610   Eric Dumazet   net: txq_trans_up...
300
301
302
  					if (status == NETDEV_TX_OK)
  						txq_trans_update(txq);
  				}
fd2ea0a79   David S. Miller   net: Use queue aw...
303
  				__netif_tx_unlock(txq);
e37b8d931   Andrew Morton   [NETPOLL]: Make s...
304
305
306
  
  				if (status == NETDEV_TX_OK)
  					break;
e37b8d931   Andrew Morton   [NETPOLL]: Make s...
307
  			}
0db3dc73f   Stephen Hemminger   [NETPOLL]: tx loc...
308
309
  
  			/* tickle device maybe there is some cleanup */
2a49e001c   Joe Perches   netpoll: Remove w...
310
  			netpoll_poll_dev(np->dev);
0db3dc73f   Stephen Hemminger   [NETPOLL]: tx loc...
311
312
  
  			udelay(USEC_PER_POLL);
0db1d6fc1   Matt Mackall   [NETPOLL]: add re...
313
  		}
79b1bee88   Dongdong Deng   netpoll: warning ...
314
315
316
317
318
  
  		WARN_ONCE(!irqs_disabled(),
  			"netpoll_send_skb(): %s enabled interrupts in poll (%pF)
  ",
  			dev->name, ops->ndo_start_xmit);
a49f99ffc   Andrew Morton   [NETPOLL]: Fix lo...
319
  		local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

2bdfe0bae   Stephen Hemminger   netpoll retry cle...
322
  	if (status != NETDEV_TX_OK) {
5de4a473b   Stephen Hemminger   netpoll queue cle...
323
  		skb_queue_tail(&npinfo->txq, skb);
4c1ac1b49   David Howells   Merge branch 'mas...
324
  		schedule_delayed_work(&npinfo->tx_work,0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  }
c2355e1ab   Neil Horman   bonding: Fix bond...
327
  EXPORT_SYMBOL(netpoll_send_skb_on_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  
  void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
  {
  	int total_len, eth_len, ip_len, udp_len;
  	struct sk_buff *skb;
  	struct udphdr *udph;
  	struct iphdr *iph;
  	struct ethhdr *eth;
  
  	udp_len = len + sizeof(*udph);
  	ip_len = eth_len = udp_len + sizeof(*iph);
  	total_len = eth_len + ETH_HLEN + NET_IP_ALIGN;
  
  	skb = find_skb(np, total_len, total_len - len);
  	if (!skb)
  		return;
27d7ff46a   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
344
  	skb_copy_to_linear_data(skb, msg, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  	skb->len += len;
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
346
347
348
  	skb_push(skb, sizeof(*udph));
  	skb_reset_transport_header(skb);
  	udph = udp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
352
  	udph->source = htons(np->local_port);
  	udph->dest = htons(np->remote_port);
  	udph->len = htons(udp_len);
  	udph->check = 0;
e7557af56   Harvey Harrison   netpoll: store lo...
353
354
  	udph->check = csum_tcpudp_magic(np->local_ip,
  					np->remote_ip,
8e365eec0   Chris Lalancette   [NETPOLL]: Comput...
355
  					udp_len, IPPROTO_UDP,
07f0757a6   Joe Perches   include/net net/ ...
356
  					csum_partial(udph, udp_len, 0));
8e365eec0   Chris Lalancette   [NETPOLL]: Comput...
357
  	if (udph->check == 0)
5e57dff2c   Al Viro   [NETPOLL]: Anothe...
358
  		udph->check = CSUM_MANGLED_0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359

e2d1bca7e   Arnaldo Carvalho de Melo   [SK_BUFF]: Use sk...
360
361
  	skb_push(skb, sizeof(*iph));
  	skb_reset_network_header(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
362
  	iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
369
370
371
372
  
  	/* iph->version = 4; iph->ihl = 5; */
  	put_unaligned(0x45, (unsigned char *)iph);
  	iph->tos      = 0;
  	put_unaligned(htons(ip_len), &(iph->tot_len));
  	iph->id       = 0;
  	iph->frag_off = 0;
  	iph->ttl      = 64;
  	iph->protocol = IPPROTO_UDP;
  	iph->check    = 0;
e7557af56   Harvey Harrison   netpoll: store lo...
373
374
  	put_unaligned(np->local_ip, &(iph->saddr));
  	put_unaligned(np->remote_ip, &(iph->daddr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
  	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
  
  	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
459a98ed8   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
378
  	skb_reset_mac_header(skb);
206daaf77   Stephen Hemminger   [NETPOLL]: initia...
379
  	skb->protocol = eth->h_proto = htons(ETH_P_IP);
095386416   Stephen Hemminger   [NETPOLL]: no nee...
380
381
  	memcpy(eth->h_source, np->dev->dev_addr, ETH_ALEN);
  	memcpy(eth->h_dest, np->remote_mac, ETH_ALEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
386
  
  	skb->dev = np->dev;
  
  	netpoll_send_skb(np, skb);
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
387
  EXPORT_SYMBOL(netpoll_send_udp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
  
  static void arp_reply(struct sk_buff *skb)
  {
115c1d6e6   Jeff Moyer   [NETPOLL]: Introd...
391
  	struct netpoll_info *npinfo = skb->dev->npinfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
393
394
  	struct arphdr *arp;
  	unsigned char *arp_ptr;
  	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
252e33467   Al Viro   [NET] net/core: A...
395
  	__be32 sip, tip;
47bbec028   Neil Horman   [NETPOLL]: make a...
396
  	unsigned char *sha;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397
  	struct sk_buff *send_skb;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
398
399
  	struct netpoll *np, *tmp;
  	unsigned long flags;
ae641949d   Herbert Xu   net: Remove all u...
400
  	int hlen, tlen;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
401
402
403
404
405
406
407
408
409
410
411
412
413
  	int hits = 0;
  
  	if (list_empty(&npinfo->rx_np))
  		return;
  
  	/* Before checking the packet, we do some early
  	   inspection whether this is interesting at all */
  	spin_lock_irqsave(&npinfo->rx_lock, flags);
  	list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
  		if (np->dev == skb->dev)
  			hits++;
  	}
  	spin_unlock_irqrestore(&npinfo->rx_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
414

508e14b4a   Daniel Borkmann   netpoll: allow ex...
415
416
  	/* No netpoll struct is using this dev */
  	if (!hits)
115c1d6e6   Jeff Moyer   [NETPOLL]: Introd...
417
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
420
421
  
  	/* No arp on this interface */
  	if (skb->dev->flags & IFF_NOARP)
  		return;
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
422
  	if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  		return;
c1d2bbe1c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
424
  	skb_reset_network_header(skb);
badff6d01   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
425
  	skb_reset_transport_header(skb);
d0a92be05   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
426
  	arp = arp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
432
  
  	if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
  	     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
  	    arp->ar_pro != htons(ETH_P_IP) ||
  	    arp->ar_op != htons(ARPOP_REQUEST))
  		return;
47bbec028   Neil Horman   [NETPOLL]: make a...
433
434
435
436
  	arp_ptr = (unsigned char *)(arp+1);
  	/* save the location of the src hw addr */
  	sha = arp_ptr;
  	arp_ptr += skb->dev->addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  	memcpy(&sip, arp_ptr, 4);
47bbec028   Neil Horman   [NETPOLL]: make a...
438
  	arp_ptr += 4;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
439
440
  	/* If we actually cared about dst hw addr,
  	   it would get copied here */
47bbec028   Neil Horman   [NETPOLL]: make a...
441
  	arp_ptr += skb->dev->addr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
443
444
  	memcpy(&tip, arp_ptr, 4);
  
  	/* Should we ignore arp? */
508e14b4a   Daniel Borkmann   netpoll: allow ex...
445
  	if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  		return;
988b70507   Pavel Emelyanov   [ARP]: Introduce ...
447
  	size = arp_hdr_len(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448

508e14b4a   Daniel Borkmann   netpoll: allow ex...
449
450
451
452
  	spin_lock_irqsave(&npinfo->rx_lock, flags);
  	list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
  		if (tip != np->local_ip)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453

ae641949d   Herbert Xu   net: Remove all u...
454
455
456
  		hlen = LL_RESERVED_SPACE(np->dev);
  		tlen = np->dev->needed_tailroom;
  		send_skb = find_skb(np, size + hlen + tlen, hlen);
508e14b4a   Daniel Borkmann   netpoll: allow ex...
457
458
  		if (!send_skb)
  			continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459

508e14b4a   Daniel Borkmann   netpoll: allow ex...
460
461
462
463
  		skb_reset_network_header(send_skb);
  		arp = (struct arphdr *) skb_put(send_skb, size);
  		send_skb->dev = skb->dev;
  		send_skb->protocol = htons(ETH_P_ARP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464

508e14b4a   Daniel Borkmann   netpoll: allow ex...
465
466
467
468
469
470
471
  		/* Fill the device header for the ARP frame */
  		if (dev_hard_header(send_skb, skb->dev, ptype,
  				    sha, np->dev->dev_addr,
  				    send_skb->len) < 0) {
  			kfree_skb(send_skb);
  			continue;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472

508e14b4a   Daniel Borkmann   netpoll: allow ex...
473
474
475
476
477
478
479
  		/*
  		 * Fill out the arp protocol part.
  		 *
  		 * we only support ethernet device type,
  		 * which (according to RFC 1390) should
  		 * always equal 1 (Ethernet).
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480

508e14b4a   Daniel Borkmann   netpoll: allow ex...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  		arp->ar_hrd = htons(np->dev->type);
  		arp->ar_pro = htons(ETH_P_IP);
  		arp->ar_hln = np->dev->addr_len;
  		arp->ar_pln = 4;
  		arp->ar_op = htons(type);
  
  		arp_ptr = (unsigned char *)(arp + 1);
  		memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
  		arp_ptr += np->dev->addr_len;
  		memcpy(arp_ptr, &tip, 4);
  		arp_ptr += 4;
  		memcpy(arp_ptr, sha, np->dev->addr_len);
  		arp_ptr += np->dev->addr_len;
  		memcpy(arp_ptr, &sip, 4);
  
  		netpoll_send_skb(np, send_skb);
  
  		/* If there are several rx_hooks for the same address,
  		   we're fine by sending a single reply */
  		break;
  	}
  	spin_unlock_irqrestore(&npinfo->rx_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
507
  }
  
  int __netpoll_rx(struct sk_buff *skb)
  {
  	int proto, len, ulen;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
508
  	int hits = 0;
b71d1d426   Eric Dumazet   inet: constify ip...
509
  	const struct iphdr *iph;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
  	struct udphdr *uh;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
511
512
  	struct netpoll_info *npinfo = skb->dev->npinfo;
  	struct netpoll *np, *tmp;
068c6e98b   Neil Horman   [NET] netpoll: br...
513

508e14b4a   Daniel Borkmann   netpoll: allow ex...
514
  	if (list_empty(&npinfo->rx_np))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  		goto out;
508e14b4a   Daniel Borkmann   netpoll: allow ex...
516

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
  	if (skb->dev->type != ARPHRD_ETHER)
  		goto out;
d9452e9f8   David S. Miller   [NETPOLL]: Revert...
519
  	/* check if netpoll clients need ARP */
724800d61   YOSHIFUJI Hideaki   [NET] CORE: Use h...
520
  	if (skb->protocol == htons(ETH_P_ARP) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  	    atomic_read(&trapped)) {
508e14b4a   Daniel Borkmann   netpoll: allow ex...
522
  		skb_queue_tail(&npinfo->arp_tx, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
527
528
529
530
531
532
  		return 1;
  	}
  
  	proto = ntohs(eth_hdr(skb)->h_proto);
  	if (proto != ETH_P_IP)
  		goto out;
  	if (skb->pkt_type == PACKET_OTHERHOST)
  		goto out;
  	if (skb_shared(skb))
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
534
  	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
  		goto out;
e9278a475   Eric Dumazet   netpoll: fix inco...
535
  	iph = (struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
  	if (iph->ihl < 5 || iph->version != 4)
  		goto out;
  	if (!pskb_may_pull(skb, iph->ihl*4))
  		goto out;
e9278a475   Eric Dumazet   netpoll: fix inco...
540
  	iph = (struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
  	if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
  		goto out;
  
  	len = ntohs(iph->tot_len);
  	if (skb->len < len || len < iph->ihl*4)
  		goto out;
5e7d7fa57   Aubrey.Li   [NET]: Fix UDP ch...
547
548
549
550
551
552
  	/*
  	 * Our transport medium may have padded the buffer out.
  	 * Now We trim to the true length of the frame.
  	 */
  	if (pskb_trim_rcsum(skb, len))
  		goto out;
e9278a475   Eric Dumazet   netpoll: fix inco...
553
  	iph = (struct iphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
557
558
559
560
561
562
  	if (iph->protocol != IPPROTO_UDP)
  		goto out;
  
  	len -= iph->ihl*4;
  	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
  	ulen = ntohs(uh->len);
  
  	if (ulen != len)
  		goto out;
fb286bb29   Herbert Xu   [NET]: Detect har...
563
  	if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565

508e14b4a   Daniel Borkmann   netpoll: allow ex...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  	list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
  		if (np->local_ip && np->local_ip != iph->daddr)
  			continue;
  		if (np->remote_ip && np->remote_ip != iph->saddr)
  			continue;
  		if (np->local_port && np->local_port != ntohs(uh->dest))
  			continue;
  
  		np->rx_hook(np, ntohs(uh->source),
  			       (char *)(uh+1),
  			       ulen - sizeof(struct udphdr));
  		hits++;
  	}
  
  	if (!hits)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
585
586
587
588
589
590
591
592
593
  
  	kfree_skb(skb);
  	return 1;
  
  out:
  	if (atomic_read(&trapped)) {
  		kfree_skb(skb);
  		return 1;
  	}
  
  	return 0;
  }
0bcc18161   Satyam Sharma   [NET] netconsole:...
594
595
596
597
598
  void netpoll_print_options(struct netpoll *np)
  {
  	printk(KERN_INFO "%s: local port %d
  ",
  			 np->name, np->local_port);
e7557af56   Harvey Harrison   netpoll: store lo...
599
600
601
  	printk(KERN_INFO "%s: local IP %pI4
  ",
  			 np->name, &np->local_ip);
5fc05f876   Amerigo Wang   netpoll: warn whe...
602
603
  	printk(KERN_INFO "%s: interface '%s'
  ",
0bcc18161   Satyam Sharma   [NET] netconsole:...
604
605
606
607
  			 np->name, np->dev_name);
  	printk(KERN_INFO "%s: remote port %d
  ",
  			 np->name, np->remote_port);
e7557af56   Harvey Harrison   netpoll: store lo...
608
609
610
  	printk(KERN_INFO "%s: remote IP %pI4
  ",
  			 np->name, &np->remote_ip);
e174961ca   Johannes Berg   net: convert prin...
611
612
613
  	printk(KERN_INFO "%s: remote ethernet address %pM
  ",
  	                 np->name, np->remote_mac);
0bcc18161   Satyam Sharma   [NET] netconsole:...
614
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
615
  EXPORT_SYMBOL(netpoll_print_options);
0bcc18161   Satyam Sharma   [NET] netconsole:...
616

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
618
619
  int netpoll_parse_options(struct netpoll *np, char *opt)
  {
  	char *cur=opt, *delim;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
620
  	if (*cur != '@') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
622
  		if ((delim = strchr(cur, '@')) == NULL)
  			goto parse_failed;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
623
624
625
  		*delim = 0;
  		np->local_port = simple_strtol(cur, NULL, 10);
  		cur = delim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
  	}
  	cur++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628

c68b90702   David S. Miller   [NETPOLL]: Minor ...
629
  	if (*cur != '/') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630
631
  		if ((delim = strchr(cur, '/')) == NULL)
  			goto parse_failed;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
632
  		*delim = 0;
e7557af56   Harvey Harrison   netpoll: store lo...
633
  		np->local_ip = in_aton(cur);
c68b90702   David S. Miller   [NETPOLL]: Minor ...
634
  		cur = delim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
636
  	}
  	cur++;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
637
  	if (*cur != ',') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
  		/* parse out dev name */
  		if ((delim = strchr(cur, ',')) == NULL)
  			goto parse_failed;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
641
  		*delim = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  		strlcpy(np->dev_name, cur, sizeof(np->dev_name));
c68b90702   David S. Miller   [NETPOLL]: Minor ...
643
  		cur = delim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
  	}
  	cur++;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
646
  	if (*cur != '@') {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
  		/* dst port */
  		if ((delim = strchr(cur, '@')) == NULL)
  			goto parse_failed;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
650
  		*delim = 0;
5fc05f876   Amerigo Wang   netpoll: warn whe...
651
652
653
654
  		if (*cur == ' ' || *cur == '\t')
  			printk(KERN_INFO "%s: warning: whitespace"
  					"is not allowed
  ", np->name);
c68b90702   David S. Miller   [NETPOLL]: Minor ...
655
656
  		np->remote_port = simple_strtol(cur, NULL, 10);
  		cur = delim;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
  	}
  	cur++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
  
  	/* dst ip */
  	if ((delim = strchr(cur, '/')) == NULL)
  		goto parse_failed;
c68b90702   David S. Miller   [NETPOLL]: Minor ...
663
  	*delim = 0;
e7557af56   Harvey Harrison   netpoll: store lo...
664
  	np->remote_ip = in_aton(cur);
c68b90702   David S. Miller   [NETPOLL]: Minor ...
665
  	cur = delim + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666

c68b90702   David S. Miller   [NETPOLL]: Minor ...
667
  	if (*cur != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
  		/* MAC address */
4940fc889   Alexey Dobriyan   net: add mac_pton...
669
  		if (!mac_pton(cur, np->remote_mac))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670
  			goto parse_failed;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
  	}
0bcc18161   Satyam Sharma   [NET] netconsole:...
672
  	netpoll_print_options(np);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
675
676
  
  	return 0;
  
   parse_failed:
5fc05f876   Amerigo Wang   netpoll: warn whe...
677
678
  	printk(KERN_INFO "%s: couldn't parse config at '%s'!
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
  	       np->name, cur);
  	return -1;
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
682
  EXPORT_SYMBOL(netpoll_parse_options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
684
  int __netpoll_setup(struct netpoll *np)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685
  {
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
686
  	struct net_device *ndev = np->dev;
115c1d6e6   Jeff Moyer   [NETPOLL]: Introd...
687
  	struct netpoll_info *npinfo;
4247e161b   Herbert Xu   netpoll: Add ndo_...
688
  	const struct net_device_ops *ops;
fbeec2e15   Jeff Moyer   [NETPOLL]: allow ...
689
  	unsigned long flags;
b41848b61   Stephen Hemminger   netpoll setup err...
690
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
691

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
  	if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
  	    !ndev->netdev_ops->ndo_poll_controller) {
  		printk(KERN_ERR "%s: %s doesn't support polling, aborting.
  ",
  		       np->name, np->dev_name);
  		err = -ENOTSUPP;
  		goto out;
  	}
  
  	if (!ndev->npinfo) {
  		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
  		if (!npinfo) {
  			err = -ENOMEM;
  			goto out;
  		}
  
  		npinfo->rx_flags = 0;
  		INIT_LIST_HEAD(&npinfo->rx_np);
  
  		spin_lock_init(&npinfo->rx_lock);
  		skb_queue_head_init(&npinfo->arp_tx);
  		skb_queue_head_init(&npinfo->txq);
  		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
  
  		atomic_set(&npinfo->refcnt, 1);
  
  		ops = np->dev->netdev_ops;
  		if (ops->ndo_netpoll_setup) {
  			err = ops->ndo_netpoll_setup(ndev, npinfo);
  			if (err)
  				goto free_npinfo;
  		}
  	} else {
  		npinfo = ndev->npinfo;
  		atomic_inc(&npinfo->refcnt);
  	}
  
  	npinfo->netpoll = np;
  
  	if (np->rx_hook) {
  		spin_lock_irqsave(&npinfo->rx_lock, flags);
  		npinfo->rx_flags |= NETPOLL_RX_ENABLED;
  		list_add_tail(&np->rx, &npinfo->rx_np);
  		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
  	}
  
  	/* last thing to do is link it to the net device structure */
cf778b00e   Eric Dumazet   net: reintroduce ...
739
  	rcu_assign_pointer(ndev->npinfo, npinfo);
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  
  	return 0;
  
  free_npinfo:
  	kfree(npinfo);
  out:
  	return err;
  }
  EXPORT_SYMBOL_GPL(__netpoll_setup);
  
  int netpoll_setup(struct netpoll *np)
  {
  	struct net_device *ndev = NULL;
  	struct in_device *in_dev;
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  	if (np->dev_name)
881d966b4   Eric W. Biederman   [NET]: Make the d...
756
  		ndev = dev_get_by_name(&init_net, np->dev_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
759
760
  	if (!ndev) {
  		printk(KERN_ERR "%s: %s doesn't exist, aborting.
  ",
  		       np->name, np->dev_name);
b41848b61   Stephen Hemminger   netpoll setup err...
761
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
  	}
0c1ad04ae   WANG Cong   netpoll: prevent ...
763
764
765
766
  	if (ndev->master) {
  		printk(KERN_ERR "%s: %s is a slave device, aborting.
  ",
  		       np->name, np->dev_name);
83fe32de6   Dan Carpenter   netpoll: call dev...
767
768
  		err = -EBUSY;
  		goto put;
0c1ad04ae   WANG Cong   netpoll: prevent ...
769
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
771
772
773
774
775
  	if (!netif_running(ndev)) {
  		unsigned long atmost, atleast;
  
  		printk(KERN_INFO "%s: device %s not up yet, forcing it
  ",
  		       np->name, np->dev_name);
6756ae4b4   Stephen Hemminger   [NET]: Convert RT...
776
  		rtnl_lock();
b41848b61   Stephen Hemminger   netpoll setup err...
777
778
779
780
  		err = dev_open(ndev);
  		rtnl_unlock();
  
  		if (err) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
781
782
  			printk(KERN_ERR "%s: failed to open %s
  ",
b41848b61   Stephen Hemminger   netpoll setup err...
783
  			       np->name, ndev->name);
dbaa15417   Herbert Xu   netpoll: Add lock...
784
  			goto put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
787
  
  		atleast = jiffies + HZ/10;
bff38771e   Anton Vorontsov   netpoll: Introduc...
788
  		atmost = jiffies + carrier_timeout * HZ;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
790
791
792
793
794
795
796
  		while (!netif_carrier_ok(ndev)) {
  			if (time_after(jiffies, atmost)) {
  				printk(KERN_NOTICE
  				       "%s: timeout waiting for carrier
  ",
  				       np->name);
  				break;
  			}
1b614fb9a   Anton Vorontsov   netpoll: Fix carr...
797
  			msleep(1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  		}
  
  		/* If carrier appears to come up instantly, we don't
  		 * trust it and pause so that we don't pump all our
  		 * queued console messages into the bitbucket.
  		 */
  
  		if (time_before(jiffies, atleast)) {
  			printk(KERN_NOTICE "%s: carrier detect appears"
  			       " untrustworthy, waiting 4 seconds
  ",
  			       np->name);
  			msleep(4000);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
  	if (!np->local_ip) {
  		rcu_read_lock();
e5ed63991   Herbert Xu   [IPV4]: Replace _...
815
  		in_dev = __in_dev_get_rcu(ndev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
817
818
819
820
821
  
  		if (!in_dev || !in_dev->ifa_list) {
  			rcu_read_unlock();
  			printk(KERN_ERR "%s: no IP address for %s, aborting
  ",
  			       np->name, np->dev_name);
b41848b61   Stephen Hemminger   netpoll setup err...
822
  			err = -EDESTADDRREQ;
dbaa15417   Herbert Xu   netpoll: Add lock...
823
  			goto put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
  		}
e7557af56   Harvey Harrison   netpoll: store lo...
825
  		np->local_ip = in_dev->ifa_list->ifa_local;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
  		rcu_read_unlock();
e7557af56   Harvey Harrison   netpoll: store lo...
827
828
  		printk(KERN_INFO "%s: local IP %pI4
  ", np->name, &np->local_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  	}
dbaa15417   Herbert Xu   netpoll: Add lock...
830
831
832
833
834
835
  	np->dev = ndev;
  
  	/* fill up the skb queue */
  	refill_skbs();
  
  	rtnl_lock();
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
836
  	err = __netpoll_setup(np);
dbaa15417   Herbert Xu   netpoll: Add lock...
837
  	rtnl_unlock();
53fb95d3c   Matt Mackall   [NETPOLL]: fix in...
838

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
839
840
  	if (err)
  		goto put;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  	return 0;
21edbb223   Jiri Slaby   NET: netpoll, fix...
842
  put:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
  	dev_put(ndev);
b41848b61   Stephen Hemminger   netpoll setup err...
844
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
846
  EXPORT_SYMBOL(netpoll_setup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
847

c68b90702   David S. Miller   [NETPOLL]: Minor ...
848
849
  static int __init netpoll_init(void)
  {
a1bcfacd0   Stephen Hemminger   netpoll: private ...
850
851
852
853
  	skb_queue_head_init(&skb_pool);
  	return 0;
  }
  core_initcall(netpoll_init);
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
854
  void __netpoll_cleanup(struct netpoll *np)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  {
fbeec2e15   Jeff Moyer   [NETPOLL]: allow ...
856
857
  	struct netpoll_info *npinfo;
  	unsigned long flags;
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
858
859
  	npinfo = np->dev->npinfo;
  	if (!npinfo)
dbaa15417   Herbert Xu   netpoll: Add lock...
860
  		return;
93ec2c723   Stephen Hemminger   netpoll info leak
861

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
862
863
864
865
866
867
868
  	if (!list_empty(&npinfo->rx_np)) {
  		spin_lock_irqsave(&npinfo->rx_lock, flags);
  		list_del(&np->rx);
  		if (list_empty(&npinfo->rx_np))
  			npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
  		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
  	}
de85d99eb   Herbert Xu   netpoll: Fix RCU ...
869

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
870
871
  	if (atomic_dec_and_test(&npinfo->refcnt)) {
  		const struct net_device_ops *ops;
de85d99eb   Herbert Xu   netpoll: Fix RCU ...
872

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
873
874
875
  		ops = np->dev->netdev_ops;
  		if (ops->ndo_netpoll_cleanup)
  			ops->ndo_netpoll_cleanup(np->dev);
de85d99eb   Herbert Xu   netpoll: Fix RCU ...
876

a9b3cd7f3   Stephen Hemminger   rcu: convert uses...
877
  		RCU_INIT_POINTER(np->dev->npinfo, NULL);
de85d99eb   Herbert Xu   netpoll: Fix RCU ...
878

dbaa15417   Herbert Xu   netpoll: Add lock...
879
880
  		/* avoid racing with NAPI reading npinfo */
  		synchronize_rcu_bh();
93ec2c723   Stephen Hemminger   netpoll info leak
881

dbaa15417   Herbert Xu   netpoll: Add lock...
882
883
  		skb_queue_purge(&npinfo->arp_tx);
  		skb_queue_purge(&npinfo->txq);
afe2c511f   Tejun Heo   workqueue: conver...
884
  		cancel_delayed_work_sync(&npinfo->tx_work);
93ec2c723   Stephen Hemminger   netpoll info leak
885

dbaa15417   Herbert Xu   netpoll: Add lock...
886
887
888
  		/* clean after last, unfinished work */
  		__skb_queue_purge(&npinfo->txq);
  		kfree(npinfo);
115c1d6e6   Jeff Moyer   [NETPOLL]: Introd...
889
  	}
8fdd95ec1   Herbert Xu   netpoll: Allow ne...
890
891
  }
  EXPORT_SYMBOL_GPL(__netpoll_cleanup);
fbeec2e15   Jeff Moyer   [NETPOLL]: allow ...
892

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
893
894
895
896
  void netpoll_cleanup(struct netpoll *np)
  {
  	if (!np->dev)
  		return;
dbaa15417   Herbert Xu   netpoll: Add lock...
897

8fdd95ec1   Herbert Xu   netpoll: Allow ne...
898
899
900
901
902
  	rtnl_lock();
  	__netpoll_cleanup(np);
  	rtnl_unlock();
  
  	dev_put(np->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
904
  	np->dev = NULL;
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
905
  EXPORT_SYMBOL(netpoll_cleanup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
906
907
908
909
910
  
  int netpoll_trap(void)
  {
  	return atomic_read(&trapped);
  }
9e34a5b51   Eric Dumazet   net/core: EXPORT_...
911
  EXPORT_SYMBOL(netpoll_trap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
915
916
917
918
919
  
  void netpoll_set_trap(int trap)
  {
  	if (trap)
  		atomic_inc(&trapped);
  	else
  		atomic_dec(&trapped);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
  EXPORT_SYMBOL(netpoll_set_trap);