Blame view

drivers/net/xen-netfront.c 55.4 KB
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  /*
   * Virtual network driver for conversing with remote driver backends.
   *
   * Copyright (c) 2002-2005, K A Fraser
   * Copyright (c) 2005, XenSource Ltd
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version 2
   * as published by the Free Software Foundation; or, when distributed
   * separately from the Linux kernel or incorporated into other
   * software packages, subject to the following license:
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this source file (the "Software"), to deal in the Software without
   * restriction, including without limitation the rights to use, copy, modify,
   * merge, publish, distribute, sublicense, and/or sell copies of the Software,
   * and to permit persons to whom the Software is furnished to do so, subject to
   * the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   * IN THE SOFTWARE.
   */
383eda32b   Joe Perches   xen: Use more cur...
31
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
32
33
34
35
36
37
38
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/skbuff.h>
  #include <linux/ethtool.h>
  #include <linux/if_ether.h>
9ecd1a75d   Wei Liu   xen-netfront: red...
39
  #include <net/tcp.h>
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
40
41
42
  #include <linux/udp.h>
  #include <linux/moduleparam.h>
  #include <linux/mm.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
43
  #include <linux/slab.h>
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
44
  #include <net/ip.h>
1ccbf5344   Jeremy Fitzhardinge   xen: move Xen-tes...
45
  #include <xen/xen.h>
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
46
47
48
  #include <xen/xenbus.h>
  #include <xen/events.h>
  #include <xen/page.h>
b9136d207   Igor Mammedov   xen: initialize p...
49
  #include <xen/platform_pci.h>
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
50
51
52
53
54
  #include <xen/grant_table.h>
  
  #include <xen/interface/io/netif.h>
  #include <xen/interface/memory.h>
  #include <xen/interface/grant_table.h>
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
55
  /* Module parameters */
034702a64   Juergen Gross   xen/netfront: set...
56
  #define MAX_QUEUES_DEFAULT 8
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
57
58
59
60
  static unsigned int xennet_max_queues;
  module_param_named(max_queues, xennet_max_queues, uint, 0644);
  MODULE_PARM_DESC(max_queues,
  		 "Maximum number of queues per virtual interface");
e3043abb5   Andrea Righi   xen-netfront: fix...
61
  #define XENNET_TIMEOUT  (5 * HZ)
0fc0b732e   Stephen Hemminger   netdev: drivers s...
62
  static const struct ethtool_ops xennet_ethtool_ops;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
63
64
  
  struct netfront_cb {
3683243b2   Ian Campbell   xen-netfront: use...
65
  	int pull_to;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
66
67
68
69
70
71
72
  };
  
  #define NETFRONT_SKB_CB(skb)	((struct netfront_cb *)((skb)->cb))
  
  #define RX_COPY_THRESHOLD 256
  
  #define GRANT_INVALID_REF	0
30c5d7f0d   Julien Grall   net/xen-netfront:...
73
74
  #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, XEN_PAGE_SIZE)
  #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, XEN_PAGE_SIZE)
1f3c2eba1   David Vrabel   xen-netfront: alw...
75
76
77
  
  /* Minimum number of Rx slots (includes slot for GSO metadata). */
  #define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
78

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
79
80
81
82
83
  /* Queue name is interface name with "-qNNN" appended */
  #define QUEUE_NAME_SIZE (IFNAMSIZ + 6)
  
  /* IRQ name is queue name with "-tx" or "-rx" appended */
  #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
8edfe2e99   Juergen Gross   xen/netfront: fix...
84
  static DECLARE_WAIT_QUEUE_HEAD(module_wq);
5b5971df3   Eduardo Otubo   xen-netfront: rem...
85

e00f85bec   stephen hemminger   xen: convert to 6...
86
  struct netfront_stats {
900e18330   David Vrabel   xen-netfront: use...
87
88
  	u64			packets;
  	u64			bytes;
e00f85bec   stephen hemminger   xen: convert to 6...
89
90
  	struct u64_stats_sync	syncp;
  };
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
91
92
93
94
95
96
  struct netfront_info;
  
  struct netfront_queue {
  	unsigned int id; /* Queue ID, 0-based */
  	char name[QUEUE_NAME_SIZE]; /* DEVNAME-qN */
  	struct netfront_info *info;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
97

bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
98
  	struct napi_struct napi;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
99

d634bf2cb   Wei Liu   xen-netfront: spl...
100
101
102
103
104
105
  	/* Split event channels support, tx_* == rx_* when using
  	 * single event channel.
  	 */
  	unsigned int tx_evtchn, rx_evtchn;
  	unsigned int tx_irq, rx_irq;
  	/* Only used when split event channels support is enabled */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
106
107
  	char tx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-tx */
  	char rx_irq_name[IRQ_NAME_SIZE]; /* DEVNAME-qN-rx */
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
108

84284d3c1   Jeremy Fitzhardinge   xen-netfront: rea...
109
110
111
  	spinlock_t   tx_lock;
  	struct xen_netif_tx_front_ring tx;
  	int tx_ring_ref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
112
113
114
115
116
117
118
119
120
121
122
123
  
  	/*
  	 * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
  	 * are linked from tx_skb_freelist through skb_entry.link.
  	 *
  	 *  NB. Freelist index entries are always going to be less than
  	 *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
  	 *  greater than PAGE_OFFSET: we use this property to distinguish
  	 *  them.
  	 */
  	union skb_entry {
  		struct sk_buff *skb;
1ffb40b8e   Isaku Yamahata   xen-netfront: fix...
124
  		unsigned long link;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
125
126
127
  	} tx_skbs[NET_TX_RING_SIZE];
  	grant_ref_t gref_tx_head;
  	grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
cefe0078e   Annie Li   xen-netfront: fix...
128
  	struct page *grant_tx_page[NET_TX_RING_SIZE];
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
129
  	unsigned tx_skb_freelist;
84284d3c1   Jeremy Fitzhardinge   xen-netfront: rea...
130
131
132
  	spinlock_t   rx_lock ____cacheline_aligned_in_smp;
  	struct xen_netif_rx_front_ring rx;
  	int rx_ring_ref;
84284d3c1   Jeremy Fitzhardinge   xen-netfront: rea...
133
  	struct timer_list rx_refill_timer;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
134
135
136
  	struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
  	grant_ref_t gref_rx_head;
  	grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
137
138
139
140
141
142
143
144
145
146
  };
  
  struct netfront_info {
  	struct list_head list;
  	struct net_device *netdev;
  
  	struct xenbus_device *xbdev;
  
  	/* Multi-queue support */
  	struct netfront_queue *queues;
e0ce4af92   Ian Campbell   xen: netfront: ha...
147
148
  
  	/* Statistics */
900e18330   David Vrabel   xen-netfront: use...
149
150
  	struct netfront_stats __percpu *rx_stats;
  	struct netfront_stats __percpu *tx_stats;
e00f85bec   stephen hemminger   xen: convert to 6...
151

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
152
  	atomic_t rx_gso_checksum_fixup;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
153
154
155
156
157
158
  };
  
  struct netfront_rx_info {
  	struct xen_netif_rx_response rx;
  	struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
  };
1ffb40b8e   Isaku Yamahata   xen-netfront: fix...
159
160
161
162
163
164
165
166
  static void skb_entry_set_link(union skb_entry *list, unsigned short id)
  {
  	list->link = id;
  }
  
  static int skb_entry_is_link(const union skb_entry *list)
  {
  	BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
807540baa   Eric Dumazet   drivers/net: retu...
167
  	return (unsigned long)list->skb < PAGE_OFFSET;
1ffb40b8e   Isaku Yamahata   xen-netfront: fix...
168
  }
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
169
170
171
172
173
174
175
  /*
   * Access macros for acquiring freeing slots in tx_skbs[].
   */
  
  static void add_id_to_freelist(unsigned *head, union skb_entry *list,
  			       unsigned short id)
  {
1ffb40b8e   Isaku Yamahata   xen-netfront: fix...
176
  	skb_entry_set_link(&list[id], *head);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
  	*head = id;
  }
  
  static unsigned short get_id_from_freelist(unsigned *head,
  					   union skb_entry *list)
  {
  	unsigned int id = *head;
  	*head = list[id].link;
  	return id;
  }
  
  static int xennet_rxidx(RING_IDX idx)
  {
  	return idx & (NET_RX_RING_SIZE - 1);
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
192
  static struct sk_buff *xennet_get_rx_skb(struct netfront_queue *queue,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
193
194
195
  					 RING_IDX ri)
  {
  	int i = xennet_rxidx(ri);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
196
197
  	struct sk_buff *skb = queue->rx_skbs[i];
  	queue->rx_skbs[i] = NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
198
199
  	return skb;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
200
  static grant_ref_t xennet_get_rx_ref(struct netfront_queue *queue,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
201
202
203
  					    RING_IDX ri)
  {
  	int i = xennet_rxidx(ri);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
204
205
  	grant_ref_t ref = queue->grant_rx_ref[i];
  	queue->grant_rx_ref[i] = GRANT_INVALID_REF;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
206
207
208
209
  	return ref;
  }
  
  #ifdef CONFIG_SYSFS
27b917e54   Takashi Iwai   xen-netfront: Use...
210
  static const struct attribute_group xennet_dev_group;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
211
  #endif
3ad9b358e   Michał Mirosław   net: drivers: use...
212
  static bool xennet_can_sg(struct net_device *dev)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
213
  {
3ad9b358e   Michał Mirosław   net: drivers: use...
214
  	return dev->features & NETIF_F_SG;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
215
  }
e99e88a9d   Kees Cook   treewide: setup_t...
216
  static void rx_refill_timeout(struct timer_list *t)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
217
  {
e99e88a9d   Kees Cook   treewide: setup_t...
218
  	struct netfront_queue *queue = from_timer(queue, t, rx_refill_timer);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
219
  	napi_schedule(&queue->napi);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
220
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
221
  static int netfront_tx_slot_available(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
222
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
223
  	return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) <
57f230ab0   Juergen Gross   xen/netfront: rai...
224
  		(NET_TX_RING_SIZE - XEN_NETIF_NR_SLOTS_MIN - 1);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
225
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
226
  static void xennet_maybe_wake_tx(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
227
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
228
229
  	struct net_device *dev = queue->info->netdev;
  	struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, queue->id);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
230

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
231
232
  	if (unlikely(netif_tx_queue_stopped(dev_queue)) &&
  	    netfront_tx_slot_available(queue) &&
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
233
  	    likely(netif_running(dev)))
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
234
  		netif_tx_wake_queue(netdev_get_tx_queue(dev, queue->id));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
235
  }
1f3c2eba1   David Vrabel   xen-netfront: alw...
236
237
  
  static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
238
  {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
239
240
  	struct sk_buff *skb;
  	struct page *page;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
241

1f3c2eba1   David Vrabel   xen-netfront: alw...
242
243
244
245
246
  	skb = __netdev_alloc_skb(queue->info->netdev,
  				 RX_COPY_THRESHOLD + NET_IP_ALIGN,
  				 GFP_ATOMIC | __GFP_NOWARN);
  	if (unlikely(!skb))
  		return NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
247

1f3c2eba1   David Vrabel   xen-netfront: alw...
248
249
250
251
  	page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
  	if (!page) {
  		kfree_skb(skb);
  		return NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
252
  	}
1f3c2eba1   David Vrabel   xen-netfront: alw...
253
254
255
256
257
258
259
260
  	skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
  
  	/* Align ip header to a 16 bytes boundary */
  	skb_reserve(skb, NET_IP_ALIGN);
  	skb->dev = queue->info->netdev;
  
  	return skb;
  }
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
261

1f3c2eba1   David Vrabel   xen-netfront: alw...
262
263
264
265
266
  
  static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
  {
  	RING_IDX req_prod = queue->rx.req_prod_pvt;
  	int notify;
538d92912   Vineeth Remanan Pillai   xen-netfront: Rew...
267
  	int err = 0;
1f3c2eba1   David Vrabel   xen-netfront: alw...
268
269
  
  	if (unlikely(!netif_carrier_ok(queue->info->netdev)))
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
270
  		return;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
271

1f3c2eba1   David Vrabel   xen-netfront: alw...
272
273
274
275
276
277
  	for (req_prod = queue->rx.req_prod_pvt;
  	     req_prod - queue->rx.rsp_cons < NET_RX_RING_SIZE;
  	     req_prod++) {
  		struct sk_buff *skb;
  		unsigned short id;
  		grant_ref_t ref;
30c5d7f0d   Julien Grall   net/xen-netfront:...
278
  		struct page *page;
1f3c2eba1   David Vrabel   xen-netfront: alw...
279
  		struct xen_netif_rx_request *req;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
280

1f3c2eba1   David Vrabel   xen-netfront: alw...
281
  		skb = xennet_alloc_one_rx_buffer(queue);
538d92912   Vineeth Remanan Pillai   xen-netfront: Rew...
282
283
  		if (!skb) {
  			err = -ENOMEM;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
284
  			break;
538d92912   Vineeth Remanan Pillai   xen-netfront: Rew...
285
  		}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
286

1f3c2eba1   David Vrabel   xen-netfront: alw...
287
  		id = xennet_rxidx(req_prod);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
288

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
289
290
  		BUG_ON(queue->rx_skbs[id]);
  		queue->rx_skbs[id] = skb;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
291

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
292
  		ref = gnttab_claim_grant_reference(&queue->gref_rx_head);
269ebce45   Dongli Zhang   xen-netfront: cas...
293
  		WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref));
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
294
  		queue->grant_rx_ref[id] = ref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
295

30c5d7f0d   Julien Grall   net/xen-netfront:...
296
  		page = skb_frag_page(&skb_shinfo(skb)->frags[0]);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
297

1f3c2eba1   David Vrabel   xen-netfront: alw...
298
  		req = RING_GET_REQUEST(&queue->rx, req_prod);
30c5d7f0d   Julien Grall   net/xen-netfront:...
299
300
301
302
  		gnttab_page_grant_foreign_access_ref_one(ref,
  							 queue->info->xbdev->otherend_id,
  							 page,
  							 0);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
303
304
305
  		req->id = id;
  		req->gref = ref;
  	}
1f3c2eba1   David Vrabel   xen-netfront: alw...
306
  	queue->rx.req_prod_pvt = req_prod;
538d92912   Vineeth Remanan Pillai   xen-netfront: Rew...
307
308
309
310
311
312
313
  	/* Try again later if there are not enough requests or skb allocation
  	 * failed.
  	 * Enough requests is quantified as the sum of newly created slots and
  	 * the unconsumed slots at the backend.
  	 */
  	if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN ||
  	    unlikely(err)) {
1f3c2eba1   David Vrabel   xen-netfront: alw...
314
315
316
  		mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
  		return;
  	}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
317
  	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->rx, notify);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
318
  	if (notify)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
319
  		notify_remote_via_irq(queue->rx_irq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
320
321
322
323
324
  }
  
  static int xennet_open(struct net_device *dev)
  {
  	struct netfront_info *np = netdev_priv(dev);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
325
326
327
  	unsigned int num_queues = dev->real_num_tx_queues;
  	unsigned int i = 0;
  	struct netfront_queue *queue = NULL;
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
328
329
  	if (!np->queues)
  		return -ENODEV;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
330
331
332
333
334
335
336
337
338
339
340
341
  	for (i = 0; i < num_queues; ++i) {
  		queue = &np->queues[i];
  		napi_enable(&queue->napi);
  
  		spin_lock_bh(&queue->rx_lock);
  		if (netif_carrier_ok(dev)) {
  			xennet_alloc_rx_buffers(queue);
  			queue->rx.sring->rsp_event = queue->rx.rsp_cons + 1;
  			if (RING_HAS_UNCONSUMED_RESPONSES(&queue->rx))
  				napi_schedule(&queue->napi);
  		}
  		spin_unlock_bh(&queue->rx_lock);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
342
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
343

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
344
  	netif_tx_start_all_queues(dev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
345
346
347
  
  	return 0;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
348
  static void xennet_tx_buf_gc(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
349
350
351
  {
  	RING_IDX cons, prod;
  	unsigned short id;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
352
  	struct sk_buff *skb;
7d0105b53   Malcolm Crossley   xen-netfront: req...
353
  	bool more_to_do;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
354

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
355
  	BUG_ON(!netif_carrier_ok(queue->info->netdev));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
356
357
  
  	do {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
358
  		prod = queue->tx.sring->rsp_prod;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
359
  		rmb(); /* Ensure we see responses up to 'rp'. */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
360
  		for (cons = queue->tx.rsp_cons; cons != prod; cons++) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
361
  			struct xen_netif_tx_response *txrsp;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
362
  			txrsp = RING_GET_RESPONSE(&queue->tx, cons);
f942dc255   Ian Campbell   xen network backe...
363
  			if (txrsp->status == XEN_NETIF_RSP_NULL)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
364
365
366
  				continue;
  
  			id  = txrsp->id;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
367
  			skb = queue->tx_skbs[id].skb;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
368
  			if (unlikely(gnttab_query_foreign_access(
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
369
  				queue->grant_tx_ref[id]) != 0)) {
383eda32b   Joe Perches   xen: Use more cur...
370
371
372
  				pr_alert("%s: warning -- grant still in use by backend domain
  ",
  					 __func__);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
373
374
375
  				BUG();
  			}
  			gnttab_end_foreign_access_ref(
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
376
  				queue->grant_tx_ref[id], GNTMAP_readonly);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
377
  			gnttab_release_grant_reference(
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
378
379
380
381
  				&queue->gref_tx_head, queue->grant_tx_ref[id]);
  			queue->grant_tx_ref[id] = GRANT_INVALID_REF;
  			queue->grant_tx_page[id] = NULL;
  			add_id_to_freelist(&queue->tx_skb_freelist, queue->tx_skbs, id);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
382
383
  			dev_kfree_skb_irq(skb);
  		}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
384
  		queue->tx.rsp_cons = prod;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
385

7d0105b53   Malcolm Crossley   xen-netfront: req...
386
387
  		RING_FINAL_CHECK_FOR_RESPONSES(&queue->tx, more_to_do);
  	} while (more_to_do);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
388

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
389
  	xennet_maybe_wake_tx(queue);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
390
  }
30c5d7f0d   Julien Grall   net/xen-netfront:...
391
392
393
394
395
396
397
398
399
400
  struct xennet_gnttab_make_txreq {
  	struct netfront_queue *queue;
  	struct sk_buff *skb;
  	struct page *page;
  	struct xen_netif_tx_request *tx; /* Last request */
  	unsigned int size;
  };
  
  static void xennet_tx_setup_grant(unsigned long gfn, unsigned int offset,
  				  unsigned int len, void *data)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
401
  {
30c5d7f0d   Julien Grall   net/xen-netfront:...
402
  	struct xennet_gnttab_make_txreq *info = data;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
403
  	unsigned int id;
a55e8bb8f   David Vrabel   xen-netfront: ref...
404
  	struct xen_netif_tx_request *tx;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
405
  	grant_ref_t ref;
30c5d7f0d   Julien Grall   net/xen-netfront:...
406
407
408
409
  	/* convenient aliases */
  	struct page *page = info->page;
  	struct netfront_queue *queue = info->queue;
  	struct sk_buff *skb = info->skb;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
410

a55e8bb8f   David Vrabel   xen-netfront: ref...
411
412
413
  	id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs);
  	tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
  	ref = gnttab_claim_grant_reference(&queue->gref_tx_head);
269ebce45   Dongli Zhang   xen-netfront: cas...
414
  	WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
415

30c5d7f0d   Julien Grall   net/xen-netfront:...
416
417
  	gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id,
  					gfn, GNTMAP_readonly);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
418

a55e8bb8f   David Vrabel   xen-netfront: ref...
419
420
421
  	queue->tx_skbs[id].skb = skb;
  	queue->grant_tx_page[id] = page;
  	queue->grant_tx_ref[id] = ref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
422

a55e8bb8f   David Vrabel   xen-netfront: ref...
423
424
425
426
427
  	tx->id = id;
  	tx->gref = ref;
  	tx->offset = offset;
  	tx->size = len;
  	tx->flags = 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
428

30c5d7f0d   Julien Grall   net/xen-netfront:...
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  	info->tx = tx;
  	info->size += tx->size;
  }
  
  static struct xen_netif_tx_request *xennet_make_first_txreq(
  	struct netfront_queue *queue, struct sk_buff *skb,
  	struct page *page, unsigned int offset, unsigned int len)
  {
  	struct xennet_gnttab_make_txreq info = {
  		.queue = queue,
  		.skb = skb,
  		.page = page,
  		.size = 0,
  	};
  
  	gnttab_for_one_grant(page, offset, len, xennet_tx_setup_grant, &info);
  
  	return info.tx;
  }
  
  static void xennet_make_one_txreq(unsigned long gfn, unsigned int offset,
  				  unsigned int len, void *data)
  {
  	struct xennet_gnttab_make_txreq *info = data;
  
  	info->tx->flags |= XEN_NETTXF_more_data;
  	skb_get(info->skb);
  	xennet_tx_setup_grant(gfn, offset, len, data);
a55e8bb8f   David Vrabel   xen-netfront: ref...
457
  }
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
458

a55e8bb8f   David Vrabel   xen-netfront: ref...
459
460
461
462
463
  static struct xen_netif_tx_request *xennet_make_txreqs(
  	struct netfront_queue *queue, struct xen_netif_tx_request *tx,
  	struct sk_buff *skb, struct page *page,
  	unsigned int offset, unsigned int len)
  {
30c5d7f0d   Julien Grall   net/xen-netfront:...
464
465
466
467
468
  	struct xennet_gnttab_make_txreq info = {
  		.queue = queue,
  		.skb = skb,
  		.tx = tx,
  	};
a55e8bb8f   David Vrabel   xen-netfront: ref...
469
470
471
  	/* Skip unused frames from start of page */
  	page += offset >> PAGE_SHIFT;
  	offset &= ~PAGE_MASK;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
472

a55e8bb8f   David Vrabel   xen-netfront: ref...
473
  	while (len) {
30c5d7f0d   Julien Grall   net/xen-netfront:...
474
475
476
477
478
479
  		info.page = page;
  		info.size = 0;
  
  		gnttab_foreach_grant_in_range(page, offset, len,
  					      xennet_make_one_txreq,
  					      &info);
a55e8bb8f   David Vrabel   xen-netfront: ref...
480
481
  		page++;
  		offset = 0;
30c5d7f0d   Julien Grall   net/xen-netfront:...
482
  		len -= info.size;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
483
  	}
30c5d7f0d   Julien Grall   net/xen-netfront:...
484
  	return info.tx;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
485
  }
f36c37478   Ian Campbell   xen/netfront: han...
486
  /*
e84448d52   David Vrabel   xen-netfront: ref...
487
488
   * Count how many ring slots are required to send this skb. Each frag
   * might be a compound page.
f36c37478   Ian Campbell   xen/netfront: han...
489
   */
e84448d52   David Vrabel   xen-netfront: ref...
490
  static int xennet_count_skb_slots(struct sk_buff *skb)
f36c37478   Ian Campbell   xen/netfront: han...
491
492
  {
  	int i, frags = skb_shinfo(skb)->nr_frags;
30c5d7f0d   Julien Grall   net/xen-netfront:...
493
  	int slots;
e84448d52   David Vrabel   xen-netfront: ref...
494

30c5d7f0d   Julien Grall   net/xen-netfront:...
495
496
  	slots = gnttab_count_grant(offset_in_page(skb->data),
  				   skb_headlen(skb));
f36c37478   Ian Campbell   xen/netfront: han...
497
498
499
500
  
  	for (i = 0; i < frags; i++) {
  		skb_frag_t *frag = skb_shinfo(skb)->frags + i;
  		unsigned long size = skb_frag_size(frag);
b54c9d5bd   Jonathan Lemon   net: Use skb_frag...
501
  		unsigned long offset = skb_frag_off(frag);
f36c37478   Ian Campbell   xen/netfront: han...
502
503
504
  
  		/* Skip unused frames from start of page */
  		offset &= ~PAGE_MASK;
30c5d7f0d   Julien Grall   net/xen-netfront:...
505
  		slots += gnttab_count_grant(offset, size);
f36c37478   Ian Campbell   xen/netfront: han...
506
  	}
30c5d7f0d   Julien Grall   net/xen-netfront:...
507
  	return slots;
f36c37478   Ian Campbell   xen/netfront: han...
508
  }
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
509
  static u16 xennet_select_queue(struct net_device *dev, struct sk_buff *skb,
a350eccee   Paolo Abeni   net: remove 'fall...
510
  			       struct net_device *sb_dev)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
511
  {
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
512
513
514
515
516
517
518
519
520
521
522
523
524
  	unsigned int num_queues = dev->real_num_tx_queues;
  	u32 hash;
  	u16 queue_idx;
  
  	/* First, check if there is only one queue */
  	if (num_queues == 1) {
  		queue_idx = 0;
  	} else {
  		hash = skb_get_hash(skb);
  		queue_idx = hash % num_queues;
  	}
  
  	return queue_idx;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
525
  }
30c5d7f0d   Julien Grall   net/xen-netfront:...
526
  #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
24a94b3c1   Luc Van Oostenryck   xen-netfront: fix...
527
  static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
528
  {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
529
  	struct netfront_info *np = netdev_priv(dev);
900e18330   David Vrabel   xen-netfront: use...
530
  	struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats);
a55e8bb8f   David Vrabel   xen-netfront: ref...
531
532
  	struct xen_netif_tx_request *tx, *first_tx;
  	unsigned int i;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
533
  	int notify;
f36c37478   Ian Campbell   xen/netfront: han...
534
  	int slots;
a55e8bb8f   David Vrabel   xen-netfront: ref...
535
536
537
  	struct page *page;
  	unsigned int offset;
  	unsigned int len;
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
538
  	unsigned long flags;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
539
540
541
  	struct netfront_queue *queue = NULL;
  	unsigned int num_queues = dev->real_num_tx_queues;
  	u16 queue_index;
fd07160bb   Vitaly Kuznetsov   xen-netfront: avo...
542
  	struct sk_buff *nskb;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
543
544
545
546
547
548
549
  
  	/* Drop the packet if no queues are set up */
  	if (num_queues < 1)
  		goto drop;
  	/* Determine which queue to transmit this SKB on */
  	queue_index = skb_get_queue_mapping(skb);
  	queue = &np->queues[queue_index];
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
550

9ecd1a75d   Wei Liu   xen-netfront: red...
551
552
553
554
555
556
557
558
559
560
  	/* If skb->len is too big for wire format, drop skb and alert
  	 * user about misconfiguration.
  	 */
  	if (unlikely(skb->len > XEN_NETIF_MAX_TX_SIZE)) {
  		net_alert_ratelimited(
  			"xennet: skb->len = %u, too big for wire format
  ",
  			skb->len);
  		goto drop;
  	}
e84448d52   David Vrabel   xen-netfront: ref...
561
  	slots = xennet_count_skb_slots(skb);
30c5d7f0d   Julien Grall   net/xen-netfront:...
562
  	if (unlikely(slots > MAX_XEN_SKB_FRAGS + 1)) {
97a6d1bb2   Zoltan Kiss   xen-netfront: Fix...
563
564
565
566
567
  		net_dbg_ratelimited("xennet: skb rides the rocket: %d slots, %d bytes
  ",
  				    slots, skb->len);
  		if (skb_linearize(skb))
  			goto drop;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
568
  	}
a55e8bb8f   David Vrabel   xen-netfront: ref...
569
570
  	page = virt_to_page(skb->data);
  	offset = offset_in_page(skb->data);
fd07160bb   Vitaly Kuznetsov   xen-netfront: avo...
571
572
573
574
575
576
577
578
  
  	/* The first req should be at least ETH_HLEN size or the packet will be
  	 * dropped by netback.
  	 */
  	if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
  		nskb = skb_copy(skb, GFP_ATOMIC);
  		if (!nskb)
  			goto drop;
62f3250f3   Eric Dumazet   xen-netfront: be ...
579
  		dev_consume_skb_any(skb);
fd07160bb   Vitaly Kuznetsov   xen-netfront: avo...
580
581
582
583
  		skb = nskb;
  		page = virt_to_page(skb->data);
  		offset = offset_in_page(skb->data);
  	}
a55e8bb8f   David Vrabel   xen-netfront: ref...
584
  	len = skb_headlen(skb);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
585
  	spin_lock_irqsave(&queue->tx_lock, flags);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
586
587
  
  	if (unlikely(!netif_carrier_ok(dev) ||
f36c37478   Ian Campbell   xen/netfront: han...
588
  		     (slots > 1 && !xennet_can_sg(dev)) ||
8b86a61da   Johannes Berg   net: remove unuse...
589
  		     netif_needs_gso(skb, netif_skb_features(skb)))) {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
590
  		spin_unlock_irqrestore(&queue->tx_lock, flags);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
591
592
  		goto drop;
  	}
a55e8bb8f   David Vrabel   xen-netfront: ref...
593
  	/* First request for the linear area. */
30c5d7f0d   Julien Grall   net/xen-netfront:...
594
595
596
597
598
599
600
  	first_tx = tx = xennet_make_first_txreq(queue, skb,
  						page, offset, len);
  	offset += tx->size;
  	if (offset == PAGE_SIZE) {
  		page++;
  		offset = 0;
  	}
a55e8bb8f   David Vrabel   xen-netfront: ref...
601
  	len -= tx->size;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
602

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
603
604
  	if (skb->ip_summed == CHECKSUM_PARTIAL)
  		/* local packet? */
f942dc255   Ian Campbell   xen network backe...
605
  		tx->flags |= XEN_NETTXF_csum_blank | XEN_NETTXF_data_validated;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
606
607
  	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
  		/* remote but checksummed. */
f942dc255   Ian Campbell   xen network backe...
608
  		tx->flags |= XEN_NETTXF_data_validated;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
609

a55e8bb8f   David Vrabel   xen-netfront: ref...
610
  	/* Optional extra info after the first request. */
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
611
612
613
614
  	if (skb_shinfo(skb)->gso_size) {
  		struct xen_netif_extra_info *gso;
  
  		gso = (struct xen_netif_extra_info *)
a55e8bb8f   David Vrabel   xen-netfront: ref...
615
  			RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
616

e2d617c0c   Wei Liu   xen-netfront: rem...
617
  		tx->flags |= XEN_NETTXF_extra_info;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
618
619
  
  		gso->u.gso.size = skb_shinfo(skb)->gso_size;
2c0057dec   Paul Durrant   xen-netfront: add...
620
621
622
  		gso->u.gso.type = (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) ?
  			XEN_NETIF_GSO_TYPE_TCPV6 :
  			XEN_NETIF_GSO_TYPE_TCPV4;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
623
624
625
626
627
  		gso->u.gso.pad = 0;
  		gso->u.gso.features = 0;
  
  		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
  		gso->flags = 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
628
  	}
a55e8bb8f   David Vrabel   xen-netfront: ref...
629
630
631
632
633
634
  	/* Requests for the rest of the linear area. */
  	tx = xennet_make_txreqs(queue, tx, skb, page, offset, len);
  
  	/* Requests for all the frags. */
  	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
  		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
b54c9d5bd   Jonathan Lemon   net: Use skb_frag...
635
636
  		tx = xennet_make_txreqs(queue, tx, skb, skb_frag_page(frag),
  					skb_frag_off(frag),
a55e8bb8f   David Vrabel   xen-netfront: ref...
637
638
  					skb_frag_size(frag));
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
639

a55e8bb8f   David Vrabel   xen-netfront: ref...
640
641
  	/* First request has the packet length. */
  	first_tx->size = skb->len;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
642

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
643
  	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->tx, notify);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
644
  	if (notify)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
645
  		notify_remote_via_irq(queue->tx_irq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
646

900e18330   David Vrabel   xen-netfront: use...
647
648
649
650
  	u64_stats_update_begin(&tx_stats->syncp);
  	tx_stats->bytes += skb->len;
  	tx_stats->packets++;
  	u64_stats_update_end(&tx_stats->syncp);
10a273a67   Jeremy Fitzhardinge   xen-netfront: Avo...
651
652
  
  	/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
653
  	xennet_tx_buf_gc(queue);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
654

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
655
656
  	if (!netfront_tx_slot_available(queue))
  		netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
657

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
658
  	spin_unlock_irqrestore(&queue->tx_lock, flags);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
659

6ed106549   Patrick McHardy   net: use NETDEV_T...
660
  	return NETDEV_TX_OK;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
661
662
  
   drop:
09f75cd7b   Jeff Garzik   [NET] drivers/net...
663
  	dev->stats.tx_dropped++;
979de8a09   Eric W. Biederman   xen-netfront: Cal...
664
  	dev_kfree_skb_any(skb);
6ed106549   Patrick McHardy   net: use NETDEV_T...
665
  	return NETDEV_TX_OK;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
666
667
668
669
670
  }
  
  static int xennet_close(struct net_device *dev)
  {
  	struct netfront_info *np = netdev_priv(dev);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
671
672
673
674
675
676
677
678
  	unsigned int num_queues = dev->real_num_tx_queues;
  	unsigned int i;
  	struct netfront_queue *queue;
  	netif_tx_stop_all_queues(np->netdev);
  	for (i = 0; i < num_queues; ++i) {
  		queue = &np->queues[i];
  		napi_disable(&queue->napi);
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
679
680
  	return 0;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
681
  static void xennet_move_rx_slot(struct netfront_queue *queue, struct sk_buff *skb,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
682
683
  				grant_ref_t ref)
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
684
685
686
687
688
689
690
691
  	int new = xennet_rxidx(queue->rx.req_prod_pvt);
  
  	BUG_ON(queue->rx_skbs[new]);
  	queue->rx_skbs[new] = skb;
  	queue->grant_rx_ref[new] = ref;
  	RING_GET_REQUEST(&queue->rx, queue->rx.req_prod_pvt)->id = new;
  	RING_GET_REQUEST(&queue->rx, queue->rx.req_prod_pvt)->gref = ref;
  	queue->rx.req_prod_pvt++;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
692
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
693
  static int xennet_get_extras(struct netfront_queue *queue,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
694
695
696
697
698
  			     struct xen_netif_extra_info *extras,
  			     RING_IDX rp)
  
  {
  	struct xen_netif_extra_info *extra;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
699
700
  	struct device *dev = &queue->info->netdev->dev;
  	RING_IDX cons = queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  	int err = 0;
  
  	do {
  		struct sk_buff *skb;
  		grant_ref_t ref;
  
  		if (unlikely(cons + 1 == rp)) {
  			if (net_ratelimit())
  				dev_warn(dev, "Missing extra info
  ");
  			err = -EBADR;
  			break;
  		}
  
  		extra = (struct xen_netif_extra_info *)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
716
  			RING_GET_RESPONSE(&queue->rx, ++cons);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
717
718
719
720
721
722
723
724
725
726
727
728
  
  		if (unlikely(!extra->type ||
  			     extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
  			if (net_ratelimit())
  				dev_warn(dev, "Invalid extra type: %d
  ",
  					extra->type);
  			err = -EINVAL;
  		} else {
  			memcpy(&extras[extra->type - 1], extra,
  			       sizeof(*extra));
  		}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
729
730
731
  		skb = xennet_get_rx_skb(queue, cons);
  		ref = xennet_get_rx_ref(queue, cons);
  		xennet_move_rx_slot(queue, skb, ref);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
732
  	} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
733
  	queue->rx.rsp_cons = cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
734
735
  	return err;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
736
  static int xennet_get_responses(struct netfront_queue *queue,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
737
738
739
740
741
  				struct netfront_rx_info *rinfo, RING_IDX rp,
  				struct sk_buff_head *list)
  {
  	struct xen_netif_rx_response *rx = &rinfo->rx;
  	struct xen_netif_extra_info *extras = rinfo->extras;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
742
743
744
745
  	struct device *dev = &queue->info->netdev->dev;
  	RING_IDX cons = queue->rx.rsp_cons;
  	struct sk_buff *skb = xennet_get_rx_skb(queue, cons);
  	grant_ref_t ref = xennet_get_rx_ref(queue, cons);
57f230ab0   Juergen Gross   xen/netfront: rai...
746
  	int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
7158ff6d0   Wei Liu   xen-netfront: fra...
747
  	int slots = 1;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
748
749
  	int err = 0;
  	unsigned long ret;
f942dc255   Ian Campbell   xen network backe...
750
  	if (rx->flags & XEN_NETRXF_extra_info) {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
751
752
  		err = xennet_get_extras(queue, extras, rp);
  		cons = queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
753
754
755
756
  	}
  
  	for (;;) {
  		if (unlikely(rx->status < 0 ||
30c5d7f0d   Julien Grall   net/xen-netfront:...
757
  			     rx->offset + rx->status > XEN_PAGE_SIZE)) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
758
  			if (net_ratelimit())
6c10127d9   Julien Grall   net/xen-netfront:...
759
760
  				dev_warn(dev, "rx->offset: %u, size: %d
  ",
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
761
  					 rx->offset, rx->status);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
762
  			xennet_move_rx_slot(queue, skb, ref);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
763
764
765
766
767
768
769
  			err = -EINVAL;
  			goto next;
  		}
  
  		/*
  		 * This definitely indicates a bug, either in this driver or in
  		 * the backend driver. In future this should flag the bad
697089dc1   Wei Liu   xen-netfront: fra...
770
  		 * situation to the system controller to reboot the backend.
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
771
772
773
774
775
776
777
778
779
780
781
782
  		 */
  		if (ref == GRANT_INVALID_REF) {
  			if (net_ratelimit())
  				dev_warn(dev, "Bad rx response id %d.
  ",
  					 rx->id);
  			err = -EINVAL;
  			goto next;
  		}
  
  		ret = gnttab_end_foreign_access_ref(ref, 0);
  		BUG_ON(!ret);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
783
  		gnttab_release_grant_reference(&queue->gref_rx_head, ref);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
784
785
786
787
  
  		__skb_queue_tail(list, skb);
  
  next:
f942dc255   Ian Campbell   xen network backe...
788
  		if (!(rx->flags & XEN_NETRXF_more_data))
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
789
  			break;
7158ff6d0   Wei Liu   xen-netfront: fra...
790
  		if (cons + slots == rp) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
791
  			if (net_ratelimit())
7158ff6d0   Wei Liu   xen-netfront: fra...
792
793
  				dev_warn(dev, "Need more slots
  ");
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
794
795
796
  			err = -ENOENT;
  			break;
  		}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
797
798
799
  		rx = RING_GET_RESPONSE(&queue->rx, cons + slots);
  		skb = xennet_get_rx_skb(queue, cons + slots);
  		ref = xennet_get_rx_ref(queue, cons + slots);
7158ff6d0   Wei Liu   xen-netfront: fra...
800
  		slots++;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
801
  	}
7158ff6d0   Wei Liu   xen-netfront: fra...
802
  	if (unlikely(slots > max)) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
803
  		if (net_ratelimit())
697089dc1   Wei Liu   xen-netfront: fra...
804
805
  			dev_warn(dev, "Too many slots
  ");
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
806
807
808
809
  		err = -E2BIG;
  	}
  
  	if (unlikely(err))
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
810
  		queue->rx.rsp_cons = cons + slots;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
811
812
813
814
815
816
817
818
819
  
  	return err;
  }
  
  static int xennet_set_skb_gso(struct sk_buff *skb,
  			      struct xen_netif_extra_info *gso)
  {
  	if (!gso->u.gso.size) {
  		if (net_ratelimit())
383eda32b   Joe Perches   xen: Use more cur...
820
821
  			pr_warn("GSO size must not be zero
  ");
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
822
823
  		return -EINVAL;
  	}
2c0057dec   Paul Durrant   xen-netfront: add...
824
825
  	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4 &&
  	    gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV6) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
826
  		if (net_ratelimit())
383eda32b   Joe Perches   xen: Use more cur...
827
828
  			pr_warn("Bad GSO type %d
  ", gso->u.gso.type);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
829
830
831
832
  		return -EINVAL;
  	}
  
  	skb_shinfo(skb)->gso_size = gso->u.gso.size;
2c0057dec   Paul Durrant   xen-netfront: add...
833
834
835
836
  	skb_shinfo(skb)->gso_type =
  		(gso->u.gso.type == XEN_NETIF_GSO_TYPE_TCPV4) ?
  		SKB_GSO_TCPV4 :
  		SKB_GSO_TCPV6;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
837
838
839
840
841
842
843
  
  	/* Header must be checked, and gso_segs computed. */
  	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
  	skb_shinfo(skb)->gso_segs = 0;
  
  	return 0;
  }
a761129e3   Dongli Zhang   xen-netfront: do ...
844
845
846
  static int xennet_fill_frags(struct netfront_queue *queue,
  			     struct sk_buff *skb,
  			     struct sk_buff_head *list)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
847
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
848
  	RING_IDX cons = queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
849
850
851
852
  	struct sk_buff *nskb;
  
  	while ((nskb = __skb_dequeue(list))) {
  		struct xen_netif_rx_response *rx =
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
853
  			RING_GET_RESPONSE(&queue->rx, ++cons);
01c68026e   Ian Campbell   xen: netfront: co...
854
  		skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
855

d472b3a6c   Juergen Gross   xen/netfront: don...
856
  		if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) {
093b9c71b   Jan Beulich   xen-netfront: pul...
857
  			unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
858

d81c5054a   Juergen Gross   xen/netfront: tol...
859
  			BUG_ON(pull_to < skb_headlen(skb));
093b9c71b   Jan Beulich   xen-netfront: pul...
860
861
  			__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
  		}
ad4f15dc2   Juergen Gross   xen/netfront: don...
862
  		if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
00b368502   Dongli Zhang   xen-netfront: do ...
863
  			queue->rx.rsp_cons = ++cons + skb_queue_len(list);
ad4f15dc2   Juergen Gross   xen/netfront: don...
864
  			kfree_skb(nskb);
a761129e3   Dongli Zhang   xen-netfront: do ...
865
  			return -ENOENT;
ad4f15dc2   Juergen Gross   xen/netfront: don...
866
  		}
093b9c71b   Jan Beulich   xen-netfront: pul...
867

d472b3a6c   Juergen Gross   xen/netfront: don...
868
869
  		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
  				skb_frag_page(nfrag),
093b9c71b   Jan Beulich   xen-netfront: pul...
870
  				rx->offset, rx->status, PAGE_SIZE);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
871
872
873
  
  		skb_shinfo(nskb)->nr_frags = 0;
  		kfree_skb(nskb);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
874
  	}
a761129e3   Dongli Zhang   xen-netfront: do ...
875
876
877
  	queue->rx.rsp_cons = cons;
  
  	return 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
878
  }
e0ce4af92   Ian Campbell   xen: netfront: ha...
879
  static int checksum_setup(struct net_device *dev, struct sk_buff *skb)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
880
  {
b5cf66cd1   Paul Durrant   xen-netfront: use...
881
  	bool recalculate_partial_csum = false;
e0ce4af92   Ian Campbell   xen: netfront: ha...
882
883
884
885
886
887
888
889
890
  
  	/*
  	 * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
  	 * peers can fail to set NETRXF_csum_blank when sending a GSO
  	 * frame. In this case force the SKB to CHECKSUM_PARTIAL and
  	 * recalculate the partial checksum.
  	 */
  	if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) {
  		struct netfront_info *np = netdev_priv(dev);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
891
  		atomic_inc(&np->rx_gso_checksum_fixup);
e0ce4af92   Ian Campbell   xen: netfront: ha...
892
  		skb->ip_summed = CHECKSUM_PARTIAL;
b5cf66cd1   Paul Durrant   xen-netfront: use...
893
  		recalculate_partial_csum = true;
e0ce4af92   Ian Campbell   xen: netfront: ha...
894
895
896
897
898
  	}
  
  	/* A non-CHECKSUM_PARTIAL SKB does not require setup. */
  	if (skb->ip_summed != CHECKSUM_PARTIAL)
  		return 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
899

b5cf66cd1   Paul Durrant   xen-netfront: use...
900
  	return skb_checksum_setup(skb, recalculate_partial_csum);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
901
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
902
  static int handle_incoming_queue(struct netfront_queue *queue,
09f75cd7b   Jeff Garzik   [NET] drivers/net...
903
  				 struct sk_buff_head *rxq)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
904
  {
900e18330   David Vrabel   xen-netfront: use...
905
  	struct netfront_stats *rx_stats = this_cpu_ptr(queue->info->rx_stats);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
906
907
908
909
  	int packets_dropped = 0;
  	struct sk_buff *skb;
  
  	while ((skb = __skb_dequeue(rxq)) != NULL) {
3683243b2   Ian Campbell   xen-netfront: use...
910
  		int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
911

093b9c71b   Jan Beulich   xen-netfront: pul...
912
913
  		if (pull_to > skb_headlen(skb))
  			__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
914
915
  
  		/* Ethernet work: Delayed to here as it peeks the header. */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
916
  		skb->protocol = eth_type_trans(skb, queue->info->netdev);
d554f73df   Wei Liu   xen-netfront: res...
917
  		skb_reset_network_header(skb);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
918

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
919
  		if (checksum_setup(queue->info->netdev, skb)) {
e0ce4af92   Ian Campbell   xen: netfront: ha...
920
921
  			kfree_skb(skb);
  			packets_dropped++;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
922
  			queue->info->netdev->stats.rx_errors++;
e0ce4af92   Ian Campbell   xen: netfront: ha...
923
  			continue;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
924
  		}
900e18330   David Vrabel   xen-netfront: use...
925
926
927
928
  		u64_stats_update_begin(&rx_stats->syncp);
  		rx_stats->packets++;
  		rx_stats->bytes += skb->len;
  		u64_stats_update_end(&rx_stats->syncp);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
929
930
  
  		/* Pass it up. */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
931
  		napi_gro_receive(&queue->napi, skb);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
932
933
934
935
  	}
  
  	return packets_dropped;
  }
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
936
  static int xennet_poll(struct napi_struct *napi, int budget)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
937
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
938
939
  	struct netfront_queue *queue = container_of(napi, struct netfront_queue, napi);
  	struct net_device *dev = queue->info->netdev;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
940
941
942
943
944
  	struct sk_buff *skb;
  	struct netfront_rx_info rinfo;
  	struct xen_netif_rx_response *rx = &rinfo.rx;
  	struct xen_netif_extra_info *extras = rinfo.extras;
  	RING_IDX i, rp;
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
945
  	int work_done;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
946
947
948
  	struct sk_buff_head rxq;
  	struct sk_buff_head errq;
  	struct sk_buff_head tmpq;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
949
  	int err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
950
  	spin_lock(&queue->rx_lock);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
951

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
952
953
954
  	skb_queue_head_init(&rxq);
  	skb_queue_head_init(&errq);
  	skb_queue_head_init(&tmpq);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
955
  	rp = queue->rx.sring->rsp_prod;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
956
  	rmb(); /* Ensure we see queued responses up to 'rp'. */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
957
  	i = queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
958
959
  	work_done = 0;
  	while ((i != rp) && (work_done < budget)) {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
960
  		memcpy(rx, RING_GET_RESPONSE(&queue->rx, i), sizeof(*rx));
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
961
  		memset(extras, 0, sizeof(rinfo.extras));
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
962
  		err = xennet_get_responses(queue, &rinfo, rp, &tmpq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
963
964
965
966
967
  
  		if (unlikely(err)) {
  err:
  			while ((skb = __skb_dequeue(&tmpq)))
  				__skb_queue_tail(&errq, skb);
09f75cd7b   Jeff Garzik   [NET] drivers/net...
968
  			dev->stats.rx_errors++;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
969
  			i = queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
970
971
972
973
974
975
976
977
978
979
980
  			continue;
  		}
  
  		skb = __skb_dequeue(&tmpq);
  
  		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
  			struct xen_netif_extra_info *gso;
  			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
  
  			if (unlikely(xennet_set_skb_gso(skb, gso))) {
  				__skb_queue_head(&tmpq, skb);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
981
  				queue->rx.rsp_cons += skb_queue_len(&tmpq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
982
983
984
  				goto err;
  			}
  		}
3683243b2   Ian Campbell   xen-netfront: use...
985
986
987
  		NETFRONT_SKB_CB(skb)->pull_to = rx->status;
  		if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
  			NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
988

b54c9d5bd   Jonathan Lemon   net: Use skb_frag...
989
  		skb_frag_off_set(&skb_shinfo(skb)->frags[0], rx->offset);
3683243b2   Ian Campbell   xen-netfront: use...
990
991
  		skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
  		skb->data_len = rx->status;
093b9c71b   Jan Beulich   xen-netfront: pul...
992
  		skb->len += rx->status;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
993

a761129e3   Dongli Zhang   xen-netfront: do ...
994
  		if (unlikely(xennet_fill_frags(queue, skb, &tmpq)))
ad4f15dc2   Juergen Gross   xen/netfront: don...
995
  			goto err;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
996

f942dc255   Ian Campbell   xen network backe...
997
  		if (rx->flags & XEN_NETRXF_csum_blank)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
998
  			skb->ip_summed = CHECKSUM_PARTIAL;
f942dc255   Ian Campbell   xen network backe...
999
  		else if (rx->flags & XEN_NETRXF_data_validated)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1000
1001
1002
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
  
  		__skb_queue_tail(&rxq, skb);
a761129e3   Dongli Zhang   xen-netfront: do ...
1003
  		i = ++queue->rx.rsp_cons;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1004
1005
  		work_done++;
  	}
56cfe5d02   Wang Chen   NETFRONT: Use __s...
1006
  	__skb_queue_purge(&errq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1007

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1008
  	work_done -= handle_incoming_queue(queue, &rxq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1009

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1010
  	xennet_alloc_rx_buffers(queue);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1011

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1012
  	if (work_done < budget) {
bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
1013
  		int more_to_do = 0;
6ad20165d   Eric Dumazet   drivers: net: gen...
1014
  		napi_complete_done(napi, work_done);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1015

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1016
  		RING_FINAL_CHECK_FOR_RESPONSES(&queue->rx, more_to_do);
6a6dc08ff   David Vrabel   xen-netfront: use...
1017
1018
  		if (more_to_do)
  			napi_schedule(napi);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1019
  	}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1020
  	spin_unlock(&queue->rx_lock);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1021

bea3348ee   Stephen Hemminger   [NET]: Make NAPI ...
1022
  	return work_done;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1023
1024
1025
1026
  }
  
  static int xennet_change_mtu(struct net_device *dev, int mtu)
  {
0c36820e2   Jonathan Davies   xen-netfront: tra...
1027
  	int max = xennet_can_sg(dev) ? XEN_NETIF_MAX_TX_SIZE : ETH_DATA_LEN;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1028
1029
1030
1031
1032
1033
  
  	if (mtu > max)
  		return -EINVAL;
  	dev->mtu = mtu;
  	return 0;
  }
bc1f44709   stephen hemminger   net: make ndo_get...
1034
1035
  static void xennet_get_stats64(struct net_device *dev,
  			       struct rtnl_link_stats64 *tot)
e00f85bec   stephen hemminger   xen: convert to 6...
1036
1037
1038
1039
1040
  {
  	struct netfront_info *np = netdev_priv(dev);
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
900e18330   David Vrabel   xen-netfront: use...
1041
1042
  		struct netfront_stats *rx_stats = per_cpu_ptr(np->rx_stats, cpu);
  		struct netfront_stats *tx_stats = per_cpu_ptr(np->tx_stats, cpu);
e00f85bec   stephen hemminger   xen: convert to 6...
1043
1044
1045
1046
  		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
  		unsigned int start;
  
  		do {
900e18330   David Vrabel   xen-netfront: use...
1047
1048
1049
1050
  			start = u64_stats_fetch_begin_irq(&tx_stats->syncp);
  			tx_packets = tx_stats->packets;
  			tx_bytes = tx_stats->bytes;
  		} while (u64_stats_fetch_retry_irq(&tx_stats->syncp, start));
e00f85bec   stephen hemminger   xen: convert to 6...
1051

900e18330   David Vrabel   xen-netfront: use...
1052
1053
1054
1055
1056
  		do {
  			start = u64_stats_fetch_begin_irq(&rx_stats->syncp);
  			rx_packets = rx_stats->packets;
  			rx_bytes = rx_stats->bytes;
  		} while (u64_stats_fetch_retry_irq(&rx_stats->syncp, start));
e00f85bec   stephen hemminger   xen: convert to 6...
1057
1058
1059
1060
1061
1062
1063
1064
1065
  
  		tot->rx_packets += rx_packets;
  		tot->tx_packets += tx_packets;
  		tot->rx_bytes   += rx_bytes;
  		tot->tx_bytes   += tx_bytes;
  	}
  
  	tot->rx_errors  = dev->stats.rx_errors;
  	tot->tx_dropped = dev->stats.tx_dropped;
e00f85bec   stephen hemminger   xen: convert to 6...
1066
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1067
  static void xennet_release_tx_bufs(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1068
1069
1070
1071
1072
1073
  {
  	struct sk_buff *skb;
  	int i;
  
  	for (i = 0; i < NET_TX_RING_SIZE; i++) {
  		/* Skip over entries which are actually freelist references */
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1074
  		if (skb_entry_is_link(&queue->tx_skbs[i]))
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1075
  			continue;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1076
1077
1078
  		skb = queue->tx_skbs[i].skb;
  		get_page(queue->grant_tx_page[i]);
  		gnttab_end_foreign_access(queue->grant_tx_ref[i],
cefe0078e   Annie Li   xen-netfront: fix...
1079
  					  GNTMAP_readonly,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1080
1081
1082
1083
  					  (unsigned long)page_address(queue->grant_tx_page[i]));
  		queue->grant_tx_page[i] = NULL;
  		queue->grant_tx_ref[i] = GRANT_INVALID_REF;
  		add_id_to_freelist(&queue->tx_skb_freelist, queue->tx_skbs, i);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1084
1085
1086
  		dev_kfree_skb_irq(skb);
  	}
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1087
  static void xennet_release_rx_bufs(struct netfront_queue *queue)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1088
  {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1089
  	int id, ref;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1090
  	spin_lock_bh(&queue->rx_lock);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1091
1092
  
  	for (id = 0; id < NET_RX_RING_SIZE; id++) {
cefe0078e   Annie Li   xen-netfront: fix...
1093
1094
  		struct sk_buff *skb;
  		struct page *page;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1095

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1096
  		skb = queue->rx_skbs[id];
cefe0078e   Annie Li   xen-netfront: fix...
1097
  		if (!skb)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1098
  			continue;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1099

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1100
  		ref = queue->grant_rx_ref[id];
cefe0078e   Annie Li   xen-netfront: fix...
1101
1102
  		if (ref == GRANT_INVALID_REF)
  			continue;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1103

cefe0078e   Annie Li   xen-netfront: fix...
1104
  		page = skb_frag_page(&skb_shinfo(skb)->frags[0]);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1105

cefe0078e   Annie Li   xen-netfront: fix...
1106
1107
1108
1109
1110
1111
  		/* gnttab_end_foreign_access() needs a page ref until
  		 * foreign access is ended (which may be deferred).
  		 */
  		get_page(page);
  		gnttab_end_foreign_access(ref, 0,
  					  (unsigned long)page_address(page));
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1112
  		queue->grant_rx_ref[id] = GRANT_INVALID_REF;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1113

cefe0078e   Annie Li   xen-netfront: fix...
1114
  		kfree_skb(skb);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1115
  	}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1116
  	spin_unlock_bh(&queue->rx_lock);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1117
  }
c8f44affb   Michał Mirosław   net: introduce an...
1118
1119
  static netdev_features_t xennet_fix_features(struct net_device *dev,
  	netdev_features_t features)
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1120
1121
  {
  	struct netfront_info *np = netdev_priv(dev);
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1122

2890ea5c1   Juergen Gross   xen: make use of ...
1123
1124
1125
  	if (features & NETIF_F_SG &&
  	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-sg", 0))
  		features &= ~NETIF_F_SG;
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1126

2890ea5c1   Juergen Gross   xen: make use of ...
1127
1128
1129
1130
  	if (features & NETIF_F_IPV6_CSUM &&
  	    !xenbus_read_unsigned(np->xbdev->otherend,
  				  "feature-ipv6-csum-offload", 0))
  		features &= ~NETIF_F_IPV6_CSUM;
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1131

2890ea5c1   Juergen Gross   xen: make use of ...
1132
1133
1134
  	if (features & NETIF_F_TSO &&
  	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv4", 0))
  		features &= ~NETIF_F_TSO;
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1135

2890ea5c1   Juergen Gross   xen: make use of ...
1136
1137
1138
  	if (features & NETIF_F_TSO6 &&
  	    !xenbus_read_unsigned(np->xbdev->otherend, "feature-gso-tcpv6", 0))
  		features &= ~NETIF_F_TSO6;
2c0057dec   Paul Durrant   xen-netfront: add...
1139

8f7b01a17   Eric Dumazet   xen: netfront: fi...
1140
1141
  	return features;
  }
c8f44affb   Michał Mirosław   net: introduce an...
1142
1143
  static int xennet_set_features(struct net_device *dev,
  	netdev_features_t features)
8f7b01a17   Eric Dumazet   xen: netfront: fi...
1144
1145
1146
1147
1148
1149
1150
1151
  {
  	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN) {
  		netdev_info(dev, "Reducing MTU because no SG offload");
  		dev->mtu = ETH_DATA_LEN;
  	}
  
  	return 0;
  }
d634bf2cb   Wei Liu   xen-netfront: spl...
1152
  static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id)
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1153
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1154
  	struct netfront_queue *queue = dev_id;
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1155
  	unsigned long flags;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1156
1157
1158
  	spin_lock_irqsave(&queue->tx_lock, flags);
  	xennet_tx_buf_gc(queue);
  	spin_unlock_irqrestore(&queue->tx_lock, flags);
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1159

d634bf2cb   Wei Liu   xen-netfront: spl...
1160
1161
1162
1163
1164
  	return IRQ_HANDLED;
  }
  
  static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id)
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1165
1166
  	struct netfront_queue *queue = dev_id;
  	struct net_device *dev = queue->info->netdev;
d634bf2cb   Wei Liu   xen-netfront: spl...
1167
1168
  
  	if (likely(netif_carrier_ok(dev) &&
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1169
  		   RING_HAS_UNCONSUMED_RESPONSES(&queue->rx)))
765418694   David Vrabel   xen-netfront: fix...
1170
  		napi_schedule(&queue->napi);
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1171

d634bf2cb   Wei Liu   xen-netfront: spl...
1172
1173
  	return IRQ_HANDLED;
  }
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1174

d634bf2cb   Wei Liu   xen-netfront: spl...
1175
1176
1177
1178
  static irqreturn_t xennet_interrupt(int irq, void *dev_id)
  {
  	xennet_tx_interrupt(irq, dev_id);
  	xennet_rx_interrupt(irq, dev_id);
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1179
1180
1181
1182
1183
1184
  	return IRQ_HANDLED;
  }
  
  #ifdef CONFIG_NET_POLL_CONTROLLER
  static void xennet_poll_controller(struct net_device *dev)
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1185
1186
1187
1188
1189
1190
  	/* Poll each queue */
  	struct netfront_info *info = netdev_priv(dev);
  	unsigned int num_queues = dev->real_num_tx_queues;
  	unsigned int i;
  	for (i = 0; i < num_queues; ++i)
  		xennet_interrupt(0, &info->queues[i]);
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1191
1192
  }
  #endif
0a0b9d2ed   Stephen Hemminger   xen-netfront: con...
1193
1194
  static const struct net_device_ops xennet_netdev_ops = {
  	.ndo_open            = xennet_open,
0a0b9d2ed   Stephen Hemminger   xen-netfront: con...
1195
1196
1197
  	.ndo_stop            = xennet_close,
  	.ndo_start_xmit      = xennet_start_xmit,
  	.ndo_change_mtu	     = xennet_change_mtu,
e00f85bec   stephen hemminger   xen: convert to 6...
1198
  	.ndo_get_stats64     = xennet_get_stats64,
0a0b9d2ed   Stephen Hemminger   xen-netfront: con...
1199
1200
  	.ndo_set_mac_address = eth_mac_addr,
  	.ndo_validate_addr   = eth_validate_addr,
fb507934f   Michał Mirosław   net: convert xen-...
1201
1202
  	.ndo_fix_features    = xennet_fix_features,
  	.ndo_set_features    = xennet_set_features,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1203
  	.ndo_select_queue    = xennet_select_queue,
cf66f9d48   Konrad Rzeszutek Wilk   xen/netfront: add...
1204
1205
1206
  #ifdef CONFIG_NET_POLL_CONTROLLER
  	.ndo_poll_controller = xennet_poll_controller,
  #endif
0a0b9d2ed   Stephen Hemminger   xen-netfront: con...
1207
  };
900e18330   David Vrabel   xen-netfront: use...
1208
1209
1210
1211
1212
1213
1214
1215
  static void xennet_free_netdev(struct net_device *netdev)
  {
  	struct netfront_info *np = netdev_priv(netdev);
  
  	free_percpu(np->rx_stats);
  	free_percpu(np->tx_stats);
  	free_netdev(netdev);
  }
8e0e46bb3   Bill Pemberton   xen-netfront: rem...
1216
  static struct net_device *xennet_create_dev(struct xenbus_device *dev)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1217
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1218
  	int err;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1219
1220
  	struct net_device *netdev;
  	struct netfront_info *np;
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1221
  	netdev = alloc_etherdev_mq(sizeof(struct netfront_info), xennet_max_queues);
41de8d4cf   Joe Perches   drivers/net: Remo...
1222
  	if (!netdev)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1223
  		return ERR_PTR(-ENOMEM);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1224
1225
1226
  
  	np                   = netdev_priv(netdev);
  	np->xbdev            = dev;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1227
  	np->queues = NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1228

e00f85bec   stephen hemminger   xen: convert to 6...
1229
  	err = -ENOMEM;
900e18330   David Vrabel   xen-netfront: use...
1230
1231
1232
1233
1234
  	np->rx_stats = netdev_alloc_pcpu_stats(struct netfront_stats);
  	if (np->rx_stats == NULL)
  		goto exit;
  	np->tx_stats = netdev_alloc_pcpu_stats(struct netfront_stats);
  	if (np->tx_stats == NULL)
e00f85bec   stephen hemminger   xen: convert to 6...
1235
  		goto exit;
0a0b9d2ed   Stephen Hemminger   xen-netfront: con...
1236
  	netdev->netdev_ops	= &xennet_netdev_ops;
fb507934f   Michał Mirosław   net: convert xen-...
1237
1238
  	netdev->features        = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
  				  NETIF_F_GSO_ROBUST;
2c0057dec   Paul Durrant   xen-netfront: add...
1239
1240
1241
  	netdev->hw_features	= NETIF_F_SG |
  				  NETIF_F_IPV6_CSUM |
  				  NETIF_F_TSO | NETIF_F_TSO6;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1242

fc3e59412   Ian Campbell   xen: netfront: as...
1243
1244
1245
1246
1247
1248
1249
  	/*
           * Assume that all hw features are available for now. This set
           * will be adjusted by the call to netdev_update_features() in
           * xennet_connect() which is the earliest point where we can
           * negotiate with the backend regarding supported features.
           */
  	netdev->features |= netdev->hw_features;
7ad24ea4b   Wilfried Klaebe   net: get rid of S...
1250
  	netdev->ethtool_ops = &xennet_ethtool_ops;
e1043a4bb   Mohammed Gamal   xen-netfront, xen...
1251
  	netdev->min_mtu = ETH_MIN_MTU;
d0c2c9973   Jarod Wilson   net: use core MTU...
1252
  	netdev->max_mtu = XEN_NETIF_MAX_TX_SIZE;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1253
1254
1255
1256
1257
  	SET_NETDEV_DEV(netdev, &dev->dev);
  
  	np->netdev = netdev;
  
  	netif_carrier_off(netdev);
e3043abb5   Andrea Righi   xen-netfront: fix...
1258
1259
1260
1261
1262
1263
1264
1265
  	do {
  		xenbus_switch_state(dev, XenbusStateInitialising);
  		err = wait_event_timeout(module_wq,
  				 xenbus_read_driver_state(dev->otherend) !=
  				 XenbusStateClosed &&
  				 xenbus_read_driver_state(dev->otherend) !=
  				 XenbusStateUnknown, XENNET_TIMEOUT);
  	} while (!err);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1266
  	return netdev;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1267
   exit:
900e18330   David Vrabel   xen-netfront: use...
1268
  	xennet_free_netdev(netdev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1269
1270
1271
1272
1273
1274
1275
1276
  	return ERR_PTR(err);
  }
  
  /**
   * Entry point to this code when a new device is created.  Allocate the basic
   * structures and the ring buffers for communication with the backend, and
   * inform the backend of the appropriate details for those.
   */
8e0e46bb3   Bill Pemberton   xen-netfront: rem...
1277
  static int netfront_probe(struct xenbus_device *dev,
1dd06ae8d   Greg Kroah-Hartman   drivers/net: fix ...
1278
  			  const struct xenbus_device_id *id)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
  {
  	int err;
  	struct net_device *netdev;
  	struct netfront_info *info;
  
  	netdev = xennet_create_dev(dev);
  	if (IS_ERR(netdev)) {
  		err = PTR_ERR(netdev);
  		xenbus_dev_fatal(dev, err, "creating netdev");
  		return err;
  	}
  
  	info = netdev_priv(netdev);
1b713e005   Greg Kroah-Hartman   xen: remove drive...
1292
  	dev_set_drvdata(&dev->dev, info);
27b917e54   Takashi Iwai   xen-netfront: Use...
1293
1294
1295
  #ifdef CONFIG_SYSFS
  	info->netdev->sysfs_groups[0] = &xennet_dev_group;
  #endif
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1296

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1297
  	return 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  }
  
  static void xennet_end_access(int ref, void *page)
  {
  	/* This frees the page as a side-effect */
  	if (ref != GRANT_INVALID_REF)
  		gnttab_end_foreign_access(ref, 0, (unsigned long)page);
  }
  
  static void xennet_disconnect_backend(struct netfront_info *info)
  {
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1309
  	unsigned int i = 0;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1310
  	unsigned int num_queues = info->netdev->real_num_tx_queues;
f9feb1e6a   David Vrabel   xen-netfront: cal...
1311
  	netif_carrier_off(info->netdev);
9a873c71e   Chas Williams   net/xen-netfront:...
1312
  	for (i = 0; i < num_queues && info->queues; ++i) {
765418694   David Vrabel   xen-netfront: fix...
1313
  		struct netfront_queue *queue = &info->queues[i];
744709548   Boris Ostrovsky   xen-netfront: Del...
1314
  		del_timer_sync(&queue->rx_refill_timer);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1315
1316
1317
1318
1319
1320
1321
1322
  		if (queue->tx_irq && (queue->tx_irq == queue->rx_irq))
  			unbind_from_irqhandler(queue->tx_irq, queue);
  		if (queue->tx_irq && (queue->tx_irq != queue->rx_irq)) {
  			unbind_from_irqhandler(queue->tx_irq, queue);
  			unbind_from_irqhandler(queue->rx_irq, queue);
  		}
  		queue->tx_evtchn = queue->rx_evtchn = 0;
  		queue->tx_irq = queue->rx_irq = 0;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1323

274b04550   Chas Williams   net/xen-netfront:...
1324
1325
  		if (netif_running(info->netdev))
  			napi_synchronize(&queue->napi);
f9feb1e6a   David Vrabel   xen-netfront: cal...
1326

a5b5dc3ce   David Vrabel   xen-netfront: rel...
1327
1328
1329
1330
  		xennet_release_tx_bufs(queue);
  		xennet_release_rx_bufs(queue);
  		gnttab_free_grant_references(queue->gref_tx_head);
  		gnttab_free_grant_references(queue->gref_rx_head);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1331
1332
1333
  		/* End access and free the pages */
  		xennet_end_access(queue->tx_ring_ref, queue->tx.sring);
  		xennet_end_access(queue->rx_ring_ref, queue->rx.sring);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1334

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1335
1336
1337
1338
1339
  		queue->tx_ring_ref = GRANT_INVALID_REF;
  		queue->rx_ring_ref = GRANT_INVALID_REF;
  		queue->tx.sring = NULL;
  		queue->rx.sring = NULL;
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
  }
  
  /**
   * We are reconnecting to the backend, due to a suspend/resume, or a backend
   * driver restart.  We tear down our netif structure and recreate it, but
   * leave the device-layer structures intact so that this is transparent to the
   * rest of the kernel.
   */
  static int netfront_resume(struct xenbus_device *dev)
  {
1b713e005   Greg Kroah-Hartman   xen: remove drive...
1350
  	struct netfront_info *info = dev_get_drvdata(&dev->dev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
  
  	dev_dbg(&dev->dev, "%s
  ", dev->nodename);
  
  	xennet_disconnect_backend(info);
  	return 0;
  }
  
  static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
  {
  	char *s, *e, *macstr;
  	int i;
  
  	macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
  	if (IS_ERR(macstr))
  		return PTR_ERR(macstr);
  
  	for (i = 0; i < ETH_ALEN; i++) {
  		mac[i] = simple_strtoul(s, &e, 16);
  		if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
  			kfree(macstr);
  			return -ENOENT;
  		}
  		s = e+1;
  	}
  
  	kfree(macstr);
  	return 0;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1380
  static int setup_netfront_single(struct netfront_queue *queue)
d634bf2cb   Wei Liu   xen-netfront: spl...
1381
1382
  {
  	int err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1383
  	err = xenbus_alloc_evtchn(queue->info->xbdev, &queue->tx_evtchn);
d634bf2cb   Wei Liu   xen-netfront: spl...
1384
1385
  	if (err < 0)
  		goto fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1386
  	err = bind_evtchn_to_irqhandler(queue->tx_evtchn,
d634bf2cb   Wei Liu   xen-netfront: spl...
1387
  					xennet_interrupt,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1388
  					0, queue->info->netdev->name, queue);
d634bf2cb   Wei Liu   xen-netfront: spl...
1389
1390
  	if (err < 0)
  		goto bind_fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1391
1392
  	queue->rx_evtchn = queue->tx_evtchn;
  	queue->rx_irq = queue->tx_irq = err;
d634bf2cb   Wei Liu   xen-netfront: spl...
1393
1394
1395
1396
  
  	return 0;
  
  bind_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1397
1398
  	xenbus_free_evtchn(queue->info->xbdev, queue->tx_evtchn);
  	queue->tx_evtchn = 0;
d634bf2cb   Wei Liu   xen-netfront: spl...
1399
1400
1401
  fail:
  	return err;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1402
  static int setup_netfront_split(struct netfront_queue *queue)
d634bf2cb   Wei Liu   xen-netfront: spl...
1403
1404
  {
  	int err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1405
  	err = xenbus_alloc_evtchn(queue->info->xbdev, &queue->tx_evtchn);
d634bf2cb   Wei Liu   xen-netfront: spl...
1406
1407
  	if (err < 0)
  		goto fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1408
  	err = xenbus_alloc_evtchn(queue->info->xbdev, &queue->rx_evtchn);
d634bf2cb   Wei Liu   xen-netfront: spl...
1409
1410
  	if (err < 0)
  		goto alloc_rx_evtchn_fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1411
1412
1413
  	snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name),
  		 "%s-tx", queue->name);
  	err = bind_evtchn_to_irqhandler(queue->tx_evtchn,
d634bf2cb   Wei Liu   xen-netfront: spl...
1414
  					xennet_tx_interrupt,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1415
  					0, queue->tx_irq_name, queue);
d634bf2cb   Wei Liu   xen-netfront: spl...
1416
1417
  	if (err < 0)
  		goto bind_tx_fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1418
  	queue->tx_irq = err;
d634bf2cb   Wei Liu   xen-netfront: spl...
1419

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1420
1421
1422
  	snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name),
  		 "%s-rx", queue->name);
  	err = bind_evtchn_to_irqhandler(queue->rx_evtchn,
d634bf2cb   Wei Liu   xen-netfront: spl...
1423
  					xennet_rx_interrupt,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1424
  					0, queue->rx_irq_name, queue);
d634bf2cb   Wei Liu   xen-netfront: spl...
1425
1426
  	if (err < 0)
  		goto bind_rx_fail;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1427
  	queue->rx_irq = err;
d634bf2cb   Wei Liu   xen-netfront: spl...
1428
1429
1430
1431
  
  	return 0;
  
  bind_rx_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1432
1433
  	unbind_from_irqhandler(queue->tx_irq, queue);
  	queue->tx_irq = 0;
d634bf2cb   Wei Liu   xen-netfront: spl...
1434
  bind_tx_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1435
1436
  	xenbus_free_evtchn(queue->info->xbdev, queue->rx_evtchn);
  	queue->rx_evtchn = 0;
d634bf2cb   Wei Liu   xen-netfront: spl...
1437
  alloc_rx_evtchn_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1438
1439
  	xenbus_free_evtchn(queue->info->xbdev, queue->tx_evtchn);
  	queue->tx_evtchn = 0;
d634bf2cb   Wei Liu   xen-netfront: spl...
1440
1441
1442
  fail:
  	return err;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1443
1444
  static int setup_netfront(struct xenbus_device *dev,
  			struct netfront_queue *queue, unsigned int feature_split_evtchn)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1445
1446
1447
  {
  	struct xen_netif_tx_sring *txs;
  	struct xen_netif_rx_sring *rxs;
ccc9d90a9   Wei Liu   xenbus_client: Ex...
1448
  	grant_ref_t gref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1449
  	int err;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1450

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1451
1452
1453
1454
  	queue->tx_ring_ref = GRANT_INVALID_REF;
  	queue->rx_ring_ref = GRANT_INVALID_REF;
  	queue->rx.sring = NULL;
  	queue->tx.sring = NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1455

a144ff09b   Ian Campbell   xen: Avoid alloca...
1456
  	txs = (struct xen_netif_tx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1457
1458
1459
1460
1461
1462
  	if (!txs) {
  		err = -ENOMEM;
  		xenbus_dev_fatal(dev, err, "allocating tx ring page");
  		goto fail;
  	}
  	SHARED_RING_INIT(txs);
30c5d7f0d   Julien Grall   net/xen-netfront:...
1463
  	FRONT_RING_INIT(&queue->tx, txs, XEN_PAGE_SIZE);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1464

ccc9d90a9   Wei Liu   xenbus_client: Ex...
1465
  	err = xenbus_grant_ring(dev, txs, 1, &gref);
1ca2983aa   Wei Liu   xen-netfront: avo...
1466
1467
  	if (err < 0)
  		goto grant_tx_ring_fail;
ccc9d90a9   Wei Liu   xenbus_client: Ex...
1468
  	queue->tx_ring_ref = gref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1469

a144ff09b   Ian Campbell   xen: Avoid alloca...
1470
  	rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1471
1472
1473
  	if (!rxs) {
  		err = -ENOMEM;
  		xenbus_dev_fatal(dev, err, "allocating rx ring page");
1ca2983aa   Wei Liu   xen-netfront: avo...
1474
  		goto alloc_rx_ring_fail;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1475
1476
  	}
  	SHARED_RING_INIT(rxs);
30c5d7f0d   Julien Grall   net/xen-netfront:...
1477
  	FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1478

ccc9d90a9   Wei Liu   xenbus_client: Ex...
1479
  	err = xenbus_grant_ring(dev, rxs, 1, &gref);
1ca2983aa   Wei Liu   xen-netfront: avo...
1480
1481
  	if (err < 0)
  		goto grant_rx_ring_fail;
ccc9d90a9   Wei Liu   xenbus_client: Ex...
1482
  	queue->rx_ring_ref = gref;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1483

d634bf2cb   Wei Liu   xen-netfront: spl...
1484
  	if (feature_split_evtchn)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1485
  		err = setup_netfront_split(queue);
d634bf2cb   Wei Liu   xen-netfront: spl...
1486
1487
1488
1489
1490
  	/* setup single event channel if
  	 *  a) feature-split-event-channels == 0
  	 *  b) feature-split-event-channels == 1 but failed to setup
  	 */
  	if (!feature_split_evtchn || (feature_split_evtchn && err))
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1491
  		err = setup_netfront_single(queue);
d634bf2cb   Wei Liu   xen-netfront: spl...
1492

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1493
  	if (err)
1ca2983aa   Wei Liu   xen-netfront: avo...
1494
  		goto alloc_evtchn_fail;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1495

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1496
  	return 0;
1ca2983aa   Wei Liu   xen-netfront: avo...
1497
1498
1499
  	/* If we fail to setup netfront, it is safe to just revoke access to
  	 * granted pages because backend is not accessing it at this point.
  	 */
1ca2983aa   Wei Liu   xen-netfront: avo...
1500
  alloc_evtchn_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1501
  	gnttab_end_foreign_access_ref(queue->rx_ring_ref, 0);
1ca2983aa   Wei Liu   xen-netfront: avo...
1502
1503
1504
  grant_rx_ring_fail:
  	free_page((unsigned long)rxs);
  alloc_rx_ring_fail:
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1505
  	gnttab_end_foreign_access_ref(queue->tx_ring_ref, 0);
1ca2983aa   Wei Liu   xen-netfront: avo...
1506
1507
1508
  grant_tx_ring_fail:
  	free_page((unsigned long)txs);
  fail:
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1509
1510
  	return err;
  }
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1511
1512
1513
1514
1515
1516
1517
1518
  /* Queue-specific initialisation
   * This used to be done in xennet_create_dev() but must now
   * be run per-queue.
   */
  static int xennet_init_queue(struct netfront_queue *queue)
  {
  	unsigned short i;
  	int err = 0;
21f2706b2   Xiao Liang   xen-netfront: fix...
1519
  	char *devid;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1520
1521
1522
  
  	spin_lock_init(&queue->tx_lock);
  	spin_lock_init(&queue->rx_lock);
e99e88a9d   Kees Cook   treewide: setup_t...
1523
  	timer_setup(&queue->rx_refill_timer, rx_refill_timeout, 0);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1524

21f2706b2   Xiao Liang   xen-netfront: fix...
1525
1526
1527
  	devid = strrchr(queue->info->xbdev->nodename, '/') + 1;
  	snprintf(queue->name, sizeof(queue->name), "vif%s-q%u",
  		 devid, queue->id);
8b715010a   Wei Liu   xen-netfront: ini...
1528

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  	/* Initialise tx_skbs as a free chain containing every entry. */
  	queue->tx_skb_freelist = 0;
  	for (i = 0; i < NET_TX_RING_SIZE; i++) {
  		skb_entry_set_link(&queue->tx_skbs[i], i+1);
  		queue->grant_tx_ref[i] = GRANT_INVALID_REF;
  		queue->grant_tx_page[i] = NULL;
  	}
  
  	/* Clear out rx_skbs */
  	for (i = 0; i < NET_RX_RING_SIZE; i++) {
  		queue->rx_skbs[i] = NULL;
  		queue->grant_rx_ref[i] = GRANT_INVALID_REF;
  	}
  
  	/* A grant for every tx ring slot */
1f3c2eba1   David Vrabel   xen-netfront: alw...
1544
  	if (gnttab_alloc_grant_references(NET_TX_RING_SIZE,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1545
1546
1547
1548
1549
1550
1551
1552
  					  &queue->gref_tx_head) < 0) {
  		pr_alert("can't alloc tx grant refs
  ");
  		err = -ENOMEM;
  		goto exit;
  	}
  
  	/* A grant for every rx ring slot */
1f3c2eba1   David Vrabel   xen-netfront: alw...
1553
  	if (gnttab_alloc_grant_references(NET_RX_RING_SIZE,
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1554
1555
1556
1557
1558
1559
  					  &queue->gref_rx_head) < 0) {
  		pr_alert("can't alloc rx grant refs
  ");
  		err = -ENOMEM;
  		goto exit_free_tx;
  	}
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1560
1561
1562
1563
1564
1565
1566
  	return 0;
  
   exit_free_tx:
  	gnttab_free_grant_references(queue->gref_tx_head);
   exit:
  	return err;
  }
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
  static int write_queue_xenstore_keys(struct netfront_queue *queue,
  			   struct xenbus_transaction *xbt, int write_hierarchical)
  {
  	/* Write the queue-specific keys into XenStore in the traditional
  	 * way for a single queue, or in a queue subkeys for multiple
  	 * queues.
  	 */
  	struct xenbus_device *dev = queue->info->xbdev;
  	int err;
  	const char *message;
  	char *path;
  	size_t pathsize;
  
  	/* Choose the correct place to write the keys */
  	if (write_hierarchical) {
  		pathsize = strlen(dev->nodename) + 10;
  		path = kzalloc(pathsize, GFP_KERNEL);
  		if (!path) {
  			err = -ENOMEM;
  			message = "out of memory while writing ring references";
  			goto error;
  		}
  		snprintf(path, pathsize, "%s/queue-%u",
  				dev->nodename, queue->id);
  	} else {
  		path = (char *)dev->nodename;
  	}
  
  	/* Write ring references */
  	err = xenbus_printf(*xbt, path, "tx-ring-ref", "%u",
  			queue->tx_ring_ref);
  	if (err) {
  		message = "writing tx-ring-ref";
  		goto error;
  	}
  
  	err = xenbus_printf(*xbt, path, "rx-ring-ref", "%u",
  			queue->rx_ring_ref);
  	if (err) {
  		message = "writing rx-ring-ref";
  		goto error;
  	}
  
  	/* Write event channels; taking into account both shared
  	 * and split event channel scenarios.
  	 */
  	if (queue->tx_evtchn == queue->rx_evtchn) {
  		/* Shared event channel */
  		err = xenbus_printf(*xbt, path,
  				"event-channel", "%u", queue->tx_evtchn);
  		if (err) {
  			message = "writing event-channel";
  			goto error;
  		}
  	} else {
  		/* Split event channels */
  		err = xenbus_printf(*xbt, path,
  				"event-channel-tx", "%u", queue->tx_evtchn);
  		if (err) {
  			message = "writing event-channel-tx";
  			goto error;
  		}
  
  		err = xenbus_printf(*xbt, path,
  				"event-channel-rx", "%u", queue->rx_evtchn);
  		if (err) {
  			message = "writing event-channel-rx";
  			goto error;
  		}
  	}
  
  	if (write_hierarchical)
  		kfree(path);
  	return 0;
  
  error:
  	if (write_hierarchical)
  		kfree(path);
  	xenbus_dev_fatal(dev, err, "%s", message);
  	return err;
  }
ce58725fe   David Vrabel   xen-netfront: rec...
1648
1649
1650
  static void xennet_destroy_queues(struct netfront_info *info)
  {
  	unsigned int i;
ce58725fe   David Vrabel   xen-netfront: rec...
1651
1652
1653
1654
1655
1656
1657
  	for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
  		struct netfront_queue *queue = &info->queues[i];
  
  		if (netif_running(info->netdev))
  			napi_disable(&queue->napi);
  		netif_napi_del(&queue->napi);
  	}
ce58725fe   David Vrabel   xen-netfront: rec...
1658
1659
1660
1661
1662
  	kfree(info->queues);
  	info->queues = NULL;
  }
  
  static int xennet_create_queues(struct netfront_info *info,
ca88ea124   Joe Jin   xen-netfront: upd...
1663
  				unsigned int *num_queues)
ce58725fe   David Vrabel   xen-netfront: rec...
1664
1665
1666
  {
  	unsigned int i;
  	int ret;
ca88ea124   Joe Jin   xen-netfront: upd...
1667
  	info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue),
ce58725fe   David Vrabel   xen-netfront: rec...
1668
1669
1670
  			       GFP_KERNEL);
  	if (!info->queues)
  		return -ENOMEM;
ca88ea124   Joe Jin   xen-netfront: upd...
1671
  	for (i = 0; i < *num_queues; i++) {
ce58725fe   David Vrabel   xen-netfront: rec...
1672
1673
1674
1675
1676
1677
1678
  		struct netfront_queue *queue = &info->queues[i];
  
  		queue->id = i;
  		queue->info = info;
  
  		ret = xennet_init_queue(queue);
  		if (ret < 0) {
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1679
  			dev_warn(&info->xbdev->dev,
69cb85242   David Vrabel   xen-netfront: pri...
1680
1681
  				 "only created %d queues
  ", i);
ca88ea124   Joe Jin   xen-netfront: upd...
1682
  			*num_queues = i;
ce58725fe   David Vrabel   xen-netfront: rec...
1683
1684
1685
1686
1687
1688
1689
1690
  			break;
  		}
  
  		netif_napi_add(queue->info->netdev, &queue->napi,
  			       xennet_poll, 64);
  		if (netif_running(info->netdev))
  			napi_enable(&queue->napi);
  	}
ca88ea124   Joe Jin   xen-netfront: upd...
1691
  	netif_set_real_num_tx_queues(info->netdev, *num_queues);
ce58725fe   David Vrabel   xen-netfront: rec...
1692

ca88ea124   Joe Jin   xen-netfront: upd...
1693
  	if (*num_queues == 0) {
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1694
1695
  		dev_err(&info->xbdev->dev, "no queues
  ");
ce58725fe   David Vrabel   xen-netfront: rec...
1696
1697
1698
1699
  		return -EINVAL;
  	}
  	return 0;
  }
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1700
  /* Common code used when first setting up, and when resuming. */
f502bf2bc   Ian Campbell   xen: use less gen...
1701
  static int talk_to_netback(struct xenbus_device *dev,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1702
1703
1704
1705
1706
  			   struct netfront_info *info)
  {
  	const char *message;
  	struct xenbus_transaction xbt;
  	int err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1707
1708
  	unsigned int feature_split_evtchn;
  	unsigned int i = 0;
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1709
  	unsigned int max_queues = 0;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1710
1711
  	struct netfront_queue *queue = NULL;
  	unsigned int num_queues = 1;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1712

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1713
  	info->netdev->irq = 0;
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1714
  	/* Check if backend supports multiple queues */
2890ea5c1   Juergen Gross   xen: make use of ...
1715
1716
  	max_queues = xenbus_read_unsigned(info->xbdev->otherend,
  					  "multi-queue-max-queues", 1);
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1717
  	num_queues = min(max_queues, xennet_max_queues);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1718
  	/* Check feature-split-event-channels */
2890ea5c1   Juergen Gross   xen: make use of ...
1719
1720
  	feature_split_evtchn = xenbus_read_unsigned(info->xbdev->otherend,
  					"feature-split-event-channels", 0);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1721
1722
1723
1724
1725
  
  	/* Read mac addr. */
  	err = xen_net_read_mac(dev, info->netdev->dev_addr);
  	if (err) {
  		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
cb257783c   Ross Lagerwall   xen-netfront: Fix...
1726
  		goto out_unlocked;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1727
  	}
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1728
  	rtnl_lock();
ce58725fe   David Vrabel   xen-netfront: rec...
1729
1730
  	if (info->queues)
  		xennet_destroy_queues(info);
ca88ea124   Joe Jin   xen-netfront: upd...
1731
  	err = xennet_create_queues(info, &num_queues);
e2e004acc   Ross Lagerwall   xen-netfront: Imp...
1732
1733
1734
1735
1736
1737
  	if (err < 0) {
  		xenbus_dev_fatal(dev, err, "creating queues");
  		kfree(info->queues);
  		info->queues = NULL;
  		goto out;
  	}
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1738
  	rtnl_unlock();
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1739
1740
1741
1742
  
  	/* Create shared ring, alloc event channel -- for each queue */
  	for (i = 0; i < num_queues; ++i) {
  		queue = &info->queues[i];
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1743
  		err = setup_netfront(dev, queue, feature_split_evtchn);
e2e004acc   Ross Lagerwall   xen-netfront: Imp...
1744
1745
  		if (err)
  			goto destroy_ring;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1746
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1747
1748
1749
1750
1751
1752
1753
  
  again:
  	err = xenbus_transaction_start(&xbt);
  	if (err) {
  		xenbus_dev_fatal(dev, err, "starting transaction");
  		goto destroy_ring;
  	}
812494d9a   chas williams   xen-netfront: alw...
1754
1755
  	if (xenbus_exists(XBT_NIL,
  			  info->xbdev->otherend, "multi-queue-max-queues")) {
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1756
  		/* Write the number of queues */
812494d9a   chas williams   xen-netfront: alw...
1757
1758
  		err = xenbus_printf(xbt, dev->nodename,
  				    "multi-queue-num-queues", "%u", num_queues);
d634bf2cb   Wei Liu   xen-netfront: spl...
1759
  		if (err) {
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1760
1761
  			message = "writing multi-queue-num-queues";
  			goto abort_transaction_no_dev_fatal;
d634bf2cb   Wei Liu   xen-netfront: spl...
1762
  		}
812494d9a   chas williams   xen-netfront: alw...
1763
  	}
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1764

812494d9a   chas williams   xen-netfront: alw...
1765
1766
1767
1768
1769
  	if (num_queues == 1) {
  		err = write_queue_xenstore_keys(&info->queues[0], &xbt, 0); /* flat */
  		if (err)
  			goto abort_transaction_no_dev_fatal;
  	} else {
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1770
1771
1772
1773
1774
1775
  		/* Write the keys for each queue */
  		for (i = 0; i < num_queues; ++i) {
  			queue = &info->queues[i];
  			err = write_queue_xenstore_keys(queue, &xbt, 1); /* hierarchical */
  			if (err)
  				goto abort_transaction_no_dev_fatal;
d634bf2cb   Wei Liu   xen-netfront: spl...
1776
  		}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1777
  	}
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1778
  	/* The remaining keys are not queue-specific */
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
  	err = xenbus_printf(xbt, dev->nodename, "request-rx-copy", "%u",
  			    1);
  	if (err) {
  		message = "writing request-rx-copy";
  		goto abort_transaction;
  	}
  
  	err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
  	if (err) {
  		message = "writing feature-rx-notify";
  		goto abort_transaction;
  	}
  
  	err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
  	if (err) {
  		message = "writing feature-sg";
  		goto abort_transaction;
  	}
  
  	err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
  	if (err) {
  		message = "writing feature-gso-tcpv4";
  		goto abort_transaction;
  	}
2c0057dec   Paul Durrant   xen-netfront: add...
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
  	err = xenbus_write(xbt, dev->nodename, "feature-gso-tcpv6", "1");
  	if (err) {
  		message = "writing feature-gso-tcpv6";
  		goto abort_transaction;
  	}
  
  	err = xenbus_write(xbt, dev->nodename, "feature-ipv6-csum-offload",
  			   "1");
  	if (err) {
  		message = "writing feature-ipv6-csum-offload";
  		goto abort_transaction;
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
  	err = xenbus_transaction_end(xbt, 0);
  	if (err) {
  		if (err == -EAGAIN)
  			goto again;
  		xenbus_dev_fatal(dev, err, "completing transaction");
  		goto destroy_ring;
  	}
  
  	return 0;
  
   abort_transaction:
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1826
  	xenbus_dev_fatal(dev, err, "%s", message);
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
1827
1828
  abort_transaction_no_dev_fatal:
  	xenbus_transaction_end(xbt, 1);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1829
1830
   destroy_ring:
  	xennet_disconnect_backend(info);
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1831
  	rtnl_lock();
e2e004acc   Ross Lagerwall   xen-netfront: Imp...
1832
  	xennet_destroy_queues(info);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1833
   out:
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1834
  	rtnl_unlock();
cb257783c   Ross Lagerwall   xen-netfront: Fix...
1835
  out_unlocked:
d86b5672b   Vitaly Kuznetsov   xen-netfront: avo...
1836
  	device_unregister(&dev->dev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1837
1838
  	return err;
  }
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1839
1840
1841
  static int xennet_connect(struct net_device *dev)
  {
  	struct netfront_info *np = netdev_priv(dev);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1842
  	unsigned int num_queues = 0;
a5b5dc3ce   David Vrabel   xen-netfront: rel...
1843
  	int err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1844
1845
  	unsigned int j = 0;
  	struct netfront_queue *queue = NULL;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1846

2890ea5c1   Juergen Gross   xen: make use of ...
1847
  	if (!xenbus_read_unsigned(np->xbdev->otherend, "feature-rx-copy", 0)) {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1848
  		dev_info(&dev->dev,
898eb71cb   Joe Perches   Add missing newli...
1849
1850
  			 "backend does not support copying receive path
  ");
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1851
1852
  		return -ENODEV;
  	}
f502bf2bc   Ian Campbell   xen: use less gen...
1853
  	err = talk_to_netback(np->xbdev, np);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1854
1855
  	if (err)
  		return err;
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1856
1857
  	/* talk_to_netback() sets the correct number of queues */
  	num_queues = dev->real_num_tx_queues;
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
1858
1859
1860
1861
1862
1863
1864
1865
1866
  	if (dev->reg_state == NETREG_UNINITIALIZED) {
  		err = register_netdev(dev);
  		if (err) {
  			pr_warn("%s: register_netdev err=%d
  ", __func__, err);
  			device_unregister(&np->xbdev->dev);
  			return err;
  		}
  	}
45c8184c1   Ross Lagerwall   xen-netfront: Upd...
1867
1868
1869
  	rtnl_lock();
  	netdev_update_features(dev);
  	rtnl_unlock();
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1870
  	/*
a5b5dc3ce   David Vrabel   xen-netfront: rel...
1871
  	 * All public and private state should now be sane.  Get
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1872
1873
1874
1875
1876
  	 * ready to start sending and receiving packets and give the driver
  	 * domain a kick because we've probably just requeued some
  	 * packets.
  	 */
  	netif_carrier_on(np->netdev);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1877
1878
  	for (j = 0; j < num_queues; ++j) {
  		queue = &np->queues[j];
f50b40765   David Vrabel   xen-netfront: don...
1879

2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1880
1881
1882
  		notify_remote_via_irq(queue->tx_irq);
  		if (queue->tx_irq != queue->rx_irq)
  			notify_remote_via_irq(queue->rx_irq);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1883

f50b40765   David Vrabel   xen-netfront: don...
1884
1885
  		spin_lock_irq(&queue->tx_lock);
  		xennet_tx_buf_gc(queue);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1886
  		spin_unlock_irq(&queue->tx_lock);
f50b40765   David Vrabel   xen-netfront: don...
1887
1888
1889
  
  		spin_lock_bh(&queue->rx_lock);
  		xennet_alloc_rx_buffers(queue);
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1890
1891
  		spin_unlock_bh(&queue->rx_lock);
  	}
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1892
1893
1894
1895
1896
1897
1898
  
  	return 0;
  }
  
  /**
   * Callback received when the backend's state changes.
   */
f502bf2bc   Ian Campbell   xen: use less gen...
1899
  static void netback_changed(struct xenbus_device *dev,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1900
1901
  			    enum xenbus_state backend_state)
  {
1b713e005   Greg Kroah-Hartman   xen: remove drive...
1902
  	struct netfront_info *np = dev_get_drvdata(&dev->dev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1903
1904
1905
1906
  	struct net_device *netdev = np->netdev;
  
  	dev_dbg(&dev->dev, "%s
  ", xenbus_strstate(backend_state));
8edfe2e99   Juergen Gross   xen/netfront: fix...
1907
  	wake_up_all(&module_wq);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1908
1909
1910
  	switch (backend_state) {
  	case XenbusStateInitialising:
  	case XenbusStateInitialised:
b78c95125   Noboru Iwamatsu   xenbus: prevent w...
1911
1912
  	case XenbusStateReconfiguring:
  	case XenbusStateReconfigured:
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1913
  	case XenbusStateUnknown:
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1914
1915
1916
1917
1918
1919
1920
1921
  		break;
  
  	case XenbusStateInitWait:
  		if (dev->state != XenbusStateInitialising)
  			break;
  		if (xennet_connect(netdev) != 0)
  			break;
  		xenbus_switch_state(dev, XenbusStateConnected);
08e34eb14   Laszlo Ersek   xen-netfront: del...
1922
1923
1924
  		break;
  
  	case XenbusStateConnected:
ee89bab14   Amerigo Wang   net: move and ren...
1925
  		netdev_notify_peers(netdev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1926
  		break;
bce3ea81d   David Vrabel   xen-netfront: han...
1927
1928
1929
  	case XenbusStateClosed:
  		if (dev->state == XenbusStateClosed)
  			break;
a32b9d91b   Gustavo A. R. Silva   xen-netfront: mar...
1930
  		/* Fall through - Missed the backend's CLOSING state. */
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1931
1932
1933
1934
1935
  	case XenbusStateClosing:
  		xenbus_frontend_closed(dev);
  		break;
  	}
  }
e0ce4af92   Ian Campbell   xen: netfront: ha...
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
  static const struct xennet_stat {
  	char name[ETH_GSTRING_LEN];
  	u16 offset;
  } xennet_stats[] = {
  	{
  		"rx_gso_checksum_fixup",
  		offsetof(struct netfront_info, rx_gso_checksum_fixup)
  	},
  };
  
  static int xennet_get_sset_count(struct net_device *dev, int string_set)
  {
  	switch (string_set) {
  	case ETH_SS_STATS:
  		return ARRAY_SIZE(xennet_stats);
  	default:
  		return -EINVAL;
  	}
  }
  
  static void xennet_get_ethtool_stats(struct net_device *dev,
  				     struct ethtool_stats *stats, u64 * data)
  {
  	void *np = netdev_priv(dev);
  	int i;
  
  	for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
2688fcb79   Andrew J. Bennieston   xen-netfront: Fac...
1963
  		data[i] = atomic_read((atomic_t *)(np + xennet_stats[i].offset));
e0ce4af92   Ian Campbell   xen: netfront: ha...
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
  }
  
  static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data)
  {
  	int i;
  
  	switch (stringset) {
  	case ETH_SS_STATS:
  		for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
  			memcpy(data + i * ETH_GSTRING_LEN,
  			       xennet_stats[i].name, ETH_GSTRING_LEN);
  		break;
  	}
  }
0fc0b732e   Stephen Hemminger   netdev: drivers s...
1978
  static const struct ethtool_ops xennet_ethtool_ops =
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1979
  {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1980
  	.get_link = ethtool_op_get_link,
e0ce4af92   Ian Campbell   xen: netfront: ha...
1981
1982
1983
1984
  
  	.get_sset_count = xennet_get_sset_count,
  	.get_ethtool_stats = xennet_get_ethtool_stats,
  	.get_strings = xennet_get_strings,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1985
1986
1987
  };
  
  #ifdef CONFIG_SYSFS
1f3c2eba1   David Vrabel   xen-netfront: alw...
1988
1989
  static ssize_t show_rxbuf(struct device *dev,
  			  struct device_attribute *attr, char *buf)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1990
  {
1f3c2eba1   David Vrabel   xen-netfront: alw...
1991
1992
  	return sprintf(buf, "%lu
  ", NET_RX_RING_SIZE);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1993
  }
1f3c2eba1   David Vrabel   xen-netfront: alw...
1994
1995
1996
  static ssize_t store_rxbuf(struct device *dev,
  			   struct device_attribute *attr,
  			   const char *buf, size_t len)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1997
  {
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
1998
1999
2000
2001
2002
2003
2004
2005
2006
  	char *endp;
  	unsigned long target;
  
  	if (!capable(CAP_NET_ADMIN))
  		return -EPERM;
  
  	target = simple_strtoul(buf, &endp, 0);
  	if (endp == buf)
  		return -EBADMSG;
1f3c2eba1   David Vrabel   xen-netfront: alw...
2007
  	/* rxbuf_min and rxbuf_max are no longer configurable. */
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2008

0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2009
2010
  	return len;
  }
d61e40385   Joe Perches   drivers/net: Use ...
2011
2012
2013
  static DEVICE_ATTR(rxbuf_min, 0644, show_rxbuf, store_rxbuf);
  static DEVICE_ATTR(rxbuf_max, 0644, show_rxbuf, store_rxbuf);
  static DEVICE_ATTR(rxbuf_cur, 0444, show_rxbuf, NULL);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2014

27b917e54   Takashi Iwai   xen-netfront: Use...
2015
2016
2017
2018
2019
2020
  static struct attribute *xennet_dev_attrs[] = {
  	&dev_attr_rxbuf_min.attr,
  	&dev_attr_rxbuf_max.attr,
  	&dev_attr_rxbuf_cur.attr,
  	NULL
  };
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2021

27b917e54   Takashi Iwai   xen-netfront: Use...
2022
2023
2024
  static const struct attribute_group xennet_dev_group = {
  	.attrs = xennet_dev_attrs
  };
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2025
  #endif /* CONFIG_SYSFS */
e3043abb5   Andrea Righi   xen-netfront: fix...
2026
  static void xennet_bus_close(struct xenbus_device *dev)
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2027
  {
e3043abb5   Andrea Righi   xen-netfront: fix...
2028
  	int ret;
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2029

e3043abb5   Andrea Righi   xen-netfront: fix...
2030
2031
2032
  	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
  		return;
  	do {
5b5971df3   Eduardo Otubo   xen-netfront: rem...
2033
  		xenbus_switch_state(dev, XenbusStateClosing);
e3043abb5   Andrea Righi   xen-netfront: fix...
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
  		ret = wait_event_timeout(module_wq,
  				   xenbus_read_driver_state(dev->otherend) ==
  				   XenbusStateClosing ||
  				   xenbus_read_driver_state(dev->otherend) ==
  				   XenbusStateClosed ||
  				   xenbus_read_driver_state(dev->otherend) ==
  				   XenbusStateUnknown,
  				   XENNET_TIMEOUT);
  	} while (!ret);
  
  	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
  		return;
5b5971df3   Eduardo Otubo   xen-netfront: rem...
2046

e3043abb5   Andrea Righi   xen-netfront: fix...
2047
  	do {
5b5971df3   Eduardo Otubo   xen-netfront: rem...
2048
  		xenbus_switch_state(dev, XenbusStateClosed);
e3043abb5   Andrea Righi   xen-netfront: fix...
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
  		ret = wait_event_timeout(module_wq,
  				   xenbus_read_driver_state(dev->otherend) ==
  				   XenbusStateClosed ||
  				   xenbus_read_driver_state(dev->otherend) ==
  				   XenbusStateUnknown,
  				   XENNET_TIMEOUT);
  	} while (!ret);
  }
  
  static int xennet_remove(struct xenbus_device *dev)
  {
  	struct netfront_info *info = dev_get_drvdata(&dev->dev);
5b5971df3   Eduardo Otubo   xen-netfront: rem...
2061

e3043abb5   Andrea Righi   xen-netfront: fix...
2062
  	xennet_bus_close(dev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2063
  	xennet_disconnect_backend(info);
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
2064
2065
  	if (info->netdev->reg_state == NETREG_REGISTERED)
  		unregister_netdev(info->netdev);
6bc96d047   Ian Campbell   xen/netfront: tea...
2066

f599c64fd   Ross Lagerwall   xen-netfront: Fix...
2067
2068
  	if (info->queues) {
  		rtnl_lock();
9a873c71e   Chas Williams   net/xen-netfront:...
2069
  		xennet_destroy_queues(info);
f599c64fd   Ross Lagerwall   xen-netfront: Fix...
2070
2071
  		rtnl_unlock();
  	}
900e18330   David Vrabel   xen-netfront: use...
2072
  	xennet_free_netdev(info->netdev);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2073
2074
2075
  
  	return 0;
  }
95afae481   David Vrabel   xen: remove DEFIN...
2076
2077
2078
2079
2080
2081
2082
  static const struct xenbus_device_id netfront_ids[] = {
  	{ "vif" },
  	{ "" }
  };
  
  static struct xenbus_driver netfront_driver = {
  	.ids = netfront_ids,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2083
  	.probe = netfront_probe,
8e0e46bb3   Bill Pemberton   xen-netfront: rem...
2084
  	.remove = xennet_remove,
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2085
  	.resume = netfront_resume,
f502bf2bc   Ian Campbell   xen: use less gen...
2086
  	.otherend_changed = netback_changed,
95afae481   David Vrabel   xen: remove DEFIN...
2087
  };
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2088
2089
2090
  
  static int __init netif_init(void)
  {
6e833587e   Jeremy Fitzhardinge   xen: clean up dom...
2091
  	if (!xen_domain())
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2092
  		return -ENODEV;
51c71a3bb   Konrad Rzeszutek Wilk   xen/pvhvm: If xen...
2093
  	if (!xen_has_pv_nic_devices())
b9136d207   Igor Mammedov   xen: initialize p...
2094
  		return -ENODEV;
383eda32b   Joe Perches   xen: Use more cur...
2095
2096
  	pr_info("Initialising Xen virtual ethernet driver
  ");
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2097

034702a64   Juergen Gross   xen/netfront: set...
2098
  	/* Allow as many queues as there are CPUs inut max. 8 if user has not
32a844056   Wei Liu   xen-netfront: res...
2099
2100
2101
  	 * specified a value.
  	 */
  	if (xennet_max_queues == 0)
034702a64   Juergen Gross   xen/netfront: set...
2102
2103
  		xennet_max_queues = min_t(unsigned int, MAX_QUEUES_DEFAULT,
  					  num_online_cpus());
50ee60611   Andrew J. Bennieston   xen-netfront: Add...
2104

ffb78a261   Al Viro   get xenbus_driver...
2105
  	return xenbus_register_frontend(&netfront_driver);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2106
2107
2108
2109
2110
2111
  }
  module_init(netif_init);
  
  
  static void __exit netif_exit(void)
  {
ffb78a261   Al Viro   get xenbus_driver...
2112
  	xenbus_unregister_driver(&netfront_driver);
0d1602119   Jeremy Fitzhardinge   xen: add virtual ...
2113
2114
2115
2116
2117
  }
  module_exit(netif_exit);
  
  MODULE_DESCRIPTION("Xen virtual network device frontend");
  MODULE_LICENSE("GPL");
d2f0c52be   Mark McLoughlin   xen: Module autop...
2118
  MODULE_ALIAS("xen:vif");
4f93f09b7   Mark McLoughlin   xen: Add compatib...
2119
  MODULE_ALIAS("xennet");