Mon Sep 28 01:46:48 2009 UTC ()
Pull up following revision(s) (requested by bouyer in ticket #1030):
	sys/arch/xen/xen/xennetback_xenbus.c: revision 1.29 via patch
Announce feature-rx-copy and feature-rx-flip.
Add support for request-rx-copy. Tested with a Debian lenny install.
Should fix PR port-xen/40650


(snj)
diff -r1.24 -r1.24.4.1 src/sys/arch/xen/xen/xennetback_xenbus.c

cvs diff -r1.24 -r1.24.4.1 src/sys/arch/xen/xen/xennetback_xenbus.c (switch to unified diff)

--- src/sys/arch/xen/xen/xennetback_xenbus.c 2008/10/24 18:02:58 1.24
+++ src/sys/arch/xen/xen/xennetback_xenbus.c 2009/09/28 01:46:48 1.24.4.1
@@ -1,1140 +1,1405 @@ @@ -1,1140 +1,1405 @@
1/* $NetBSD: xennetback_xenbus.c,v 1.24 2008/10/24 18:02:58 jym Exp $ */ 1/* $NetBSD: xennetback_xenbus.c,v 1.24.4.1 2009/09/28 01:46:48 snj Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software 14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement: 15 * must display the following acknowledgement:
16 * This product includes software developed by Manuel Bouyer. 16 * This product includes software developed by Manuel Bouyer.
17 * 4. The name of the author may not be used to endorse or promote products 17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission. 18 * derived from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * 30 *
31 */ 31 */
32 32
33#include "opt_xen.h" 33#include "opt_xen.h"
34 34
35#include <sys/types.h> 35#include <sys/types.h>
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38#include <sys/malloc.h> 38#include <sys/malloc.h>
39#include <sys/queue.h> 39#include <sys/queue.h>
40#include <sys/kernel.h> 40#include <sys/kernel.h>
41#include <sys/mbuf.h> 41#include <sys/mbuf.h>
42#include <sys/protosw.h> 42#include <sys/protosw.h>
43#include <sys/socket.h> 43#include <sys/socket.h>
44#include <sys/ioctl.h> 44#include <sys/ioctl.h>
45#include <sys/errno.h> 45#include <sys/errno.h>
46#include <sys/device.h> 46#include <sys/device.h>
47#include <sys/intr.h> 47#include <sys/intr.h>
48 48
49#include <net/if.h> 49#include <net/if.h>
50#include <net/if_types.h> 50#include <net/if_types.h>
51#include <net/if_dl.h> 51#include <net/if_dl.h>
52#include <net/route.h> 52#include <net/route.h>
53#include <net/netisr.h> 53#include <net/netisr.h>
54#include "bpfilter.h" 54#include "bpfilter.h"
55#if NBPFILTER > 0 55#if NBPFILTER > 0
56#include <net/bpf.h> 56#include <net/bpf.h>
57#include <net/bpfdesc.h> 57#include <net/bpfdesc.h>
58#endif 58#endif
59 59
60#include <net/if_ether.h> 60#include <net/if_ether.h>
61 61
62 62
63#include <xen/xen.h> 63#include <xen/xen.h>
64#include <xen/xen_shm.h> 64#include <xen/xen_shm.h>
65#include <xen/evtchn.h> 65#include <xen/evtchn.h>
66#include <xen/xenbus.h> 66#include <xen/xenbus.h>
67#include <xen/xennet_checksum.h> 67#include <xen/xennet_checksum.h>
68 68
69#include <uvm/uvm.h> 69#include <uvm/uvm.h>
70 70
71#ifdef XENDEBUG_NET 71#ifdef XENDEBUG_NET
72#define XENPRINTF(x) printf x 72#define XENPRINTF(x) printf x
73#else 73#else
74#define XENPRINTF(x) 74#define XENPRINTF(x)
75#endif 75#endif
76 76
77#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)  77#define NET_TX_RING_SIZE __RING_SIZE((netif_tx_sring_t *)0, PAGE_SIZE)
78#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE) 78#define NET_RX_RING_SIZE __RING_SIZE((netif_rx_sring_t *)0, PAGE_SIZE)
79 79
80/* linux wants at last 16 bytes free in front of the packet */ 80/* linux wants at last 16 bytes free in front of the packet */
81#define LINUX_REQUESTED_OFFSET 16 81#define LINUX_REQUESTED_OFFSET 16
82 82
83/* hash list for TX requests */ 83/* hash list for TX requests */
84/* descriptor of a packet being handled by the kernel */ 84/* descriptor of a packet being handled by the kernel */
85struct xni_pkt { 85struct xni_pkt {
86 int pkt_id; /* packet's ID */ 86 int pkt_id; /* packet's ID */
87 grant_handle_t pkt_handle; 87 grant_handle_t pkt_handle;
88 struct xnetback_instance *pkt_xneti; /* pointer back to our softc */ 88 struct xnetback_instance *pkt_xneti; /* pointer back to our softc */
89}; 89};
90 90
91static inline void xni_pkt_unmap(struct xni_pkt *, vaddr_t); 91static inline void xni_pkt_unmap(struct xni_pkt *, vaddr_t);
92 92
93 93
94/* pools for xni_pkt */ 94/* pools for xni_pkt */
95struct pool xni_pkt_pool; 95struct pool xni_pkt_pool;
96/* ratecheck(9) for pool allocation failures */ 96/* ratecheck(9) for pool allocation failures */
97struct timeval xni_pool_errintvl = { 30, 0 }; /* 30s, each */ 97struct timeval xni_pool_errintvl = { 30, 0 }; /* 30s, each */
98/* 98/*
99 * Backend network device driver for Xen 99 * Backend network device driver for Xen
100 */ 100 */
101 101
102/* state of a xnetback instance */ 102/* state of a xnetback instance */
103typedef enum {CONNECTED, DISCONNECTING, DISCONNECTED} xnetback_state_t; 103typedef enum {CONNECTED, DISCONNECTING, DISCONNECTED} xnetback_state_t;
104 104
105/* we keep the xnetback instances in a linked list */ 105/* we keep the xnetback instances in a linked list */
106struct xnetback_instance { 106struct xnetback_instance {
107 SLIST_ENTRY(xnetback_instance) next;  107 SLIST_ENTRY(xnetback_instance) next;
108 struct xenbus_device *xni_xbusd; /* our xenstore entry */ 108 struct xenbus_device *xni_xbusd; /* our xenstore entry */
109 domid_t xni_domid; /* attached to this domain */ 109 domid_t xni_domid; /* attached to this domain */
110 uint32_t xni_handle; /* domain-specific handle */ 110 uint32_t xni_handle; /* domain-specific handle */
111 xnetback_state_t xni_status; 111 xnetback_state_t xni_status;
112 void *xni_softintr; 112 void *xni_softintr;
113 113
114 /* network interface stuff */ 114 /* network interface stuff */
115 struct ethercom xni_ec; 115 struct ethercom xni_ec;
116 struct callout xni_restart; 116 struct callout xni_restart;
117 uint8_t xni_enaddr[ETHER_ADDR_LEN]; 117 uint8_t xni_enaddr[ETHER_ADDR_LEN];
118 118
119 /* remote domain communication stuff */ 119 /* remote domain communication stuff */
120 unsigned int xni_evtchn; /* our even channel */ 120 unsigned int xni_evtchn; /* our even channel */
121 netif_tx_back_ring_t xni_txring; 121 netif_tx_back_ring_t xni_txring;
122 netif_rx_back_ring_t xni_rxring; 122 netif_rx_back_ring_t xni_rxring;
123 grant_handle_t xni_tx_ring_handle; /* to unmap the ring */ 123 grant_handle_t xni_tx_ring_handle; /* to unmap the ring */
124 grant_handle_t xni_rx_ring_handle; 124 grant_handle_t xni_rx_ring_handle;
125 vaddr_t xni_tx_ring_va; /* to unmap the ring */ 125 vaddr_t xni_tx_ring_va; /* to unmap the ring */
126 vaddr_t xni_rx_ring_va; 126 vaddr_t xni_rx_ring_va;
127}; 127};
128#define xni_if xni_ec.ec_if 128#define xni_if xni_ec.ec_if
129#define xni_bpf xni_if.if_bpf 129#define xni_bpf xni_if.if_bpf
130 130
131 void xvifattach(int); 131 void xvifattach(int);
132static int xennetback_ifioctl(struct ifnet *, u_long, void *); 132static int xennetback_ifioctl(struct ifnet *, u_long, void *);
133static void xennetback_ifstart(struct ifnet *); 133static void xennetback_ifstart(struct ifnet *);
134static void xennetback_ifsoftstart(void *); 134static void xennetback_ifsoftstart_transfer(void *);
 135static void xennetback_ifsoftstart_copy(void *);
135static void xennetback_ifwatchdog(struct ifnet *); 136static void xennetback_ifwatchdog(struct ifnet *);
136static int xennetback_ifinit(struct ifnet *); 137static int xennetback_ifinit(struct ifnet *);
137static void xennetback_ifstop(struct ifnet *, int); 138static void xennetback_ifstop(struct ifnet *, int);
138 139
139static int xennetback_xenbus_create(struct xenbus_device *); 140static int xennetback_xenbus_create(struct xenbus_device *);
140static int xennetback_xenbus_destroy(void *); 141static int xennetback_xenbus_destroy(void *);
141static void xennetback_frontend_changed(void *, XenbusState); 142static void xennetback_frontend_changed(void *, XenbusState);
142 143
143static inline void xennetback_tx_response(struct xnetback_instance *, 144static inline void xennetback_tx_response(struct xnetback_instance *,
144 int, int); 145 int, int);
145static void xennetback_tx_free(struct mbuf * , void *, size_t, void *); 146static void xennetback_tx_free(struct mbuf * , void *, size_t, void *);
146 147
147SLIST_HEAD(, xnetback_instance) xnetback_instances; 148SLIST_HEAD(, xnetback_instance) xnetback_instances;
148 149
149static struct xnetback_instance *xnetif_lookup(domid_t, uint32_t); 150static struct xnetback_instance *xnetif_lookup(domid_t, uint32_t);
150static int xennetback_evthandler(void *); 151static int xennetback_evthandler(void *);
151 152
152static struct xenbus_backend_driver xvif_backend_driver = { 153static struct xenbus_backend_driver xvif_backend_driver = {
153 .xbakd_create = xennetback_xenbus_create, 154 .xbakd_create = xennetback_xenbus_create,
154 .xbakd_type = "vif" 155 .xbakd_type = "vif"
155}; 156};
156 157
157/* 158/*
158 * Number of packets to transmit in one hypercall (= number of pages to 159 * Number of packets to transmit in one hypercall (= number of pages to
159 * transmit at once). 160 * transmit at once).
160 */ 161 */
161#define NB_XMIT_PAGES_BATCH 64 162#define NB_XMIT_PAGES_BATCH 64
162/* 163/*
163 * We will transfers a mapped page to the remote domain, and remap another 164 * We will transfers a mapped page to the remote domain, and remap another
164 * page in place immediatly. For this we keep a list of pages available. 165 * page in place immediatly. For this we keep a list of pages available.
165 * When the list is empty, we ask the hypervisor to give us 166 * When the list is empty, we ask the hypervisor to give us
166 * NB_XMIT_PAGES_BATCH pages back. 167 * NB_XMIT_PAGES_BATCH pages back.
167 */ 168 */
168static unsigned long mcl_pages[NB_XMIT_PAGES_BATCH]; /* our physical pages */ 169static unsigned long mcl_pages[NB_XMIT_PAGES_BATCH]; /* our physical pages */
169int mcl_pages_alloc; /* current index in mcl_pages */ 170int mcl_pages_alloc; /* current index in mcl_pages */
170static int xennetback_get_mcl_page(paddr_t *); 171static int xennetback_get_mcl_page(paddr_t *);
171static void xennetback_get_new_mcl_pages(void); 172static void xennetback_get_new_mcl_pages(void);
172/* 173/*
173 * If we can't transfer the mbuf directly, we have to copy it to a page which 174 * If we can't transfer the mbuf directly, we have to copy it to a page which
174 * will be transfered to the remote domain. We use a pool_cache 175 * will be transfered to the remote domain. We use a pool_cache
175 * for this, or the mbuf cluster pool cache if MCLBYTES == PAGE_SIZE 176 * for this, or the mbuf cluster pool cache if MCLBYTES == PAGE_SIZE
176 */ 177 */
177#if MCLBYTES != PAGE_SIZE 178#if MCLBYTES != PAGE_SIZE
178pool_cache_t xmit_pages_cache; 179pool_cache_t xmit_pages_cache;
179#endif 180#endif
180pool_cache_t xmit_pages_cachep; 181pool_cache_t xmit_pages_cachep;
181 182
182/* arrays used in xennetback_ifstart(), too large to allocate on stack */ 183/* arrays used in xennetback_ifstart(), too large to allocate on stack */
183static mmu_update_t xstart_mmu[NB_XMIT_PAGES_BATCH]; 184static mmu_update_t xstart_mmu[NB_XMIT_PAGES_BATCH];
184static multicall_entry_t xstart_mcl[NB_XMIT_PAGES_BATCH + 1]; 185static multicall_entry_t xstart_mcl[NB_XMIT_PAGES_BATCH + 1];
185static gnttab_transfer_t xstart_gop[NB_XMIT_PAGES_BATCH]; 186static gnttab_transfer_t xstart_gop_transfer[NB_XMIT_PAGES_BATCH];
 187static gnttab_copy_t xstart_gop_copy[NB_XMIT_PAGES_BATCH];
186struct mbuf *mbufs_sent[NB_XMIT_PAGES_BATCH]; 188struct mbuf *mbufs_sent[NB_XMIT_PAGES_BATCH];
187struct _pages_pool_free { 189struct _pages_pool_free {
188 vaddr_t va; 190 vaddr_t va;
189 paddr_t pa; 191 paddr_t pa;
190} pages_pool_free[NB_XMIT_PAGES_BATCH]; 192} pages_pool_free[NB_XMIT_PAGES_BATCH];
191 193
192 194
193static inline void 195static inline void
194xni_pkt_unmap(struct xni_pkt *pkt, vaddr_t pkt_va) 196xni_pkt_unmap(struct xni_pkt *pkt, vaddr_t pkt_va)
195{ 197{
196 xen_shm_unmap(pkt_va, 1, &pkt->pkt_handle); 198 xen_shm_unmap(pkt_va, 1, &pkt->pkt_handle);
197 pool_put(&xni_pkt_pool, pkt); 199 pool_put(&xni_pkt_pool, pkt);
198} 200}
199 201
200void 202void
201xvifattach(int n) 203xvifattach(int n)
202{ 204{
203 int i; 205 int i;
204 struct pglist mlist; 206 struct pglist mlist;
205 struct vm_page *pg; 207 struct vm_page *pg;
206 208
207 XENPRINTF(("xennetback_init\n")); 209 XENPRINTF(("xennetback_init\n"));
208 210
209 /* 211 /*
210 * steal some non-managed pages to the VM system, to remplace 212 * steal some non-managed pages to the VM system, to remplace
211 * mbuf cluster or xmit_pages_pool pages given to foreing domains. 213 * mbuf cluster or xmit_pages_pool pages given to foreing domains.
212 */ 214 */
213 if (uvm_pglistalloc(PAGE_SIZE * NB_XMIT_PAGES_BATCH, 0, 0xffffffff, 215 if (uvm_pglistalloc(PAGE_SIZE * NB_XMIT_PAGES_BATCH, 0, 0xffffffff,
214 0, 0, &mlist, NB_XMIT_PAGES_BATCH, 0) != 0) 216 0, 0, &mlist, NB_XMIT_PAGES_BATCH, 0) != 0)
215 panic("xennetback_init: uvm_pglistalloc"); 217 panic("xennetback_init: uvm_pglistalloc");
216 for (i = 0, pg = mlist.tqh_first; pg != NULL; 218 for (i = 0, pg = mlist.tqh_first; pg != NULL;
217 pg = pg->pageq.queue.tqe_next, i++) 219 pg = pg->pageq.queue.tqe_next, i++)
218 mcl_pages[i] = xpmap_ptom(VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT; 220 mcl_pages[i] = xpmap_ptom(VM_PAGE_TO_PHYS(pg)) >> PAGE_SHIFT;
219 if (i != NB_XMIT_PAGES_BATCH) 221 if (i != NB_XMIT_PAGES_BATCH)
220 panic("xennetback_init: %d mcl pages", i); 222 panic("xennetback_init: %d mcl pages", i);
221 mcl_pages_alloc = NB_XMIT_PAGES_BATCH - 1; 223 mcl_pages_alloc = NB_XMIT_PAGES_BATCH - 1;
222 224
223 /* initialise pools */ 225 /* initialise pools */
224 pool_init(&xni_pkt_pool, sizeof(struct xni_pkt), 0, 0, 0, 226 pool_init(&xni_pkt_pool, sizeof(struct xni_pkt), 0, 0, 0,
225 "xnbpkt", NULL, IPL_VM); 227 "xnbpkt", NULL, IPL_VM);
226#if MCLBYTES != PAGE_SIZE 228#if MCLBYTES != PAGE_SIZE
227 xmit_pages_cache = pool_cache_init(PAGE_SIZE, 0, 0, 0, "xnbxm", NULL, 229 xmit_pages_cache = pool_cache_init(PAGE_SIZE, 0, 0, 0, "xnbxm", NULL,
228 IPL_VM, NULL, NULL, NULL); 230 IPL_VM, NULL, NULL, NULL);
229 xmit_pages_cachep = xmit_pages_cache; 231 xmit_pages_cachep = xmit_pages_cache;
230#else 232#else
231 xmit_pages_cachep = mcl_cache; 233 xmit_pages_cachep = mcl_cache;
232#endif 234#endif
233 235
234 SLIST_INIT(&xnetback_instances); 236 SLIST_INIT(&xnetback_instances);
235 xenbus_backend_register(&xvif_backend_driver); 237 xenbus_backend_register(&xvif_backend_driver);
236} 238}
237 239
238static int 240static int
239xennetback_xenbus_create(struct xenbus_device *xbusd) 241xennetback_xenbus_create(struct xenbus_device *xbusd)
240{ 242{
241 struct xnetback_instance *xneti; 243 struct xnetback_instance *xneti;
242 long domid, handle; 244 long domid, handle;
243 struct ifnet *ifp; 245 struct ifnet *ifp;
244 extern int ifqmaxlen; /* XXX */ 246 extern int ifqmaxlen; /* XXX */
245 char *val, *e, *p; 247 char *val, *e, *p;
246 int i, err; 248 int i, err;
 249 struct xenbus_transaction *xbt;
247 250
248 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path, 251 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,
249 "frontend-id", &domid, 10)) != 0) { 252 "frontend-id", &domid, 10)) != 0) {
250 aprint_error("xvif: can' read %s/frontend-id: %d\n", 253 aprint_error("xvif: can' read %s/frontend-id: %d\n",
251 xbusd->xbusd_path, err); 254 xbusd->xbusd_path, err);
252 return err; 255 return err;
253 } 256 }
254 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path, 257 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,
255 "handle", &handle, 10)) != 0) { 258 "handle", &handle, 10)) != 0) {
256 aprint_error("xvif: can' read %s/handle: %d\n", 259 aprint_error("xvif: can' read %s/handle: %d\n",
257 xbusd->xbusd_path, err); 260 xbusd->xbusd_path, err);
258 return err; 261 return err;
259 } 262 }
260 263
261 if (xnetif_lookup(domid, handle) != NULL) { 264 if (xnetif_lookup(domid, handle) != NULL) {
262 return EEXIST; 265 return EEXIST;
263 } 266 }
264 xneti = malloc(sizeof(struct xnetback_instance), M_DEVBUF, 267 xneti = malloc(sizeof(struct xnetback_instance), M_DEVBUF,
265 M_NOWAIT | M_ZERO); 268 M_NOWAIT | M_ZERO);
266 if (xneti == NULL) { 269 if (xneti == NULL) {
267 return ENOMEM; 270 return ENOMEM;
268 } 271 }
269 xneti->xni_domid = domid; 272 xneti->xni_domid = domid;
270 xneti->xni_handle = handle; 273 xneti->xni_handle = handle;
271 xneti->xni_status = DISCONNECTED; 274 xneti->xni_status = DISCONNECTED;
272 275
273 xbusd->xbusd_u.b.b_cookie = xneti; 276 xbusd->xbusd_u.b.b_cookie = xneti;
274 xbusd->xbusd_u.b.b_detach = xennetback_xenbus_destroy; 277 xbusd->xbusd_u.b.b_detach = xennetback_xenbus_destroy;
275 xneti->xni_xbusd = xbusd; 278 xneti->xni_xbusd = xbusd;
276 279
277 xneti->xni_softintr = softint_establish(SOFTINT_NET, 
278 xennetback_ifsoftstart, xneti); 
279 if (xneti->xni_softintr == NULL) { 
280 err = ENOMEM; 
281 goto fail; 
282 } 
283 
284 ifp = &xneti->xni_if; 280 ifp = &xneti->xni_if;
285 ifp->if_softc = xneti; 281 ifp->if_softc = xneti;
286 282
287 /* read mac address */ 283 /* read mac address */
288 if ((err = xenbus_read(NULL, xbusd->xbusd_path, "mac", NULL, &val))) { 284 if ((err = xenbus_read(NULL, xbusd->xbusd_path, "mac", NULL, &val))) {
289 aprint_error("xvif: can' read %s/mac: %d\n", 285 aprint_error("xvif: can' read %s/mac: %d\n",
290 xbusd->xbusd_path, err); 286 xbusd->xbusd_path, err);
291 goto fail; 287 goto fail;
292 } 288 }
293 for (i = 0, p = val; i < 6; i++) { 289 for (i = 0, p = val; i < 6; i++) {
294 xneti->xni_enaddr[i] = strtoul(p, &e, 16); 290 xneti->xni_enaddr[i] = strtoul(p, &e, 16);
295 if ((e[0] == '\0' && i != 5) && e[0] != ':') { 291 if ((e[0] == '\0' && i != 5) && e[0] != ':') {
296 aprint_error("xvif: %s is not a valid mac address\n", 292 aprint_error("xvif: %s is not a valid mac address\n",
297 val); 293 val);
298 err = EINVAL; 294 err = EINVAL;
299 goto fail; 295 goto fail;
300 } 296 }
301 p = &e[1]; 297 p = &e[1];
302 } 298 }
303 free(val, M_DEVBUF); 299 free(val, M_DEVBUF);
304 300
305 /* we can't use the same MAC addr as our guest */ 301 /* we can't use the same MAC addr as our guest */
306 xneti->xni_enaddr[3]++; 302 xneti->xni_enaddr[3]++;
307 /* create pseudo-interface */ 303 /* create pseudo-interface */
308 snprintf(xneti->xni_if.if_xname, IFNAMSIZ, "xvif%d.%d", 304 snprintf(xneti->xni_if.if_xname, IFNAMSIZ, "xvif%d.%d",
309 (int)domid, (int)handle); 305 (int)domid, (int)handle);
310 aprint_verbose_ifnet(ifp, "Ethernet address %s\n", 306 aprint_verbose_ifnet(ifp, "Ethernet address %s\n",
311 ether_sprintf(xneti->xni_enaddr)); 307 ether_sprintf(xneti->xni_enaddr));
312 ifp->if_flags = 308 ifp->if_flags =
313 IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; 309 IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
314 ifp->if_snd.ifq_maxlen = 310 ifp->if_snd.ifq_maxlen =
315 max(ifqmaxlen, NET_TX_RING_SIZE * 2); 311 max(ifqmaxlen, NET_TX_RING_SIZE * 2);
316 ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx; 312 ifp->if_capabilities = IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_UDPv4_Tx;
317 ifp->if_ioctl = xennetback_ifioctl; 313 ifp->if_ioctl = xennetback_ifioctl;
318 ifp->if_start = xennetback_ifstart; 314 ifp->if_start = xennetback_ifstart;
319 ifp->if_watchdog = xennetback_ifwatchdog; 315 ifp->if_watchdog = xennetback_ifwatchdog;
320 ifp->if_init = xennetback_ifinit; 316 ifp->if_init = xennetback_ifinit;
321 ifp->if_stop = xennetback_ifstop; 317 ifp->if_stop = xennetback_ifstop;
322 ifp->if_timer = 0; 318 ifp->if_timer = 0;
323 IFQ_SET_READY(&ifp->if_snd); 319 IFQ_SET_READY(&ifp->if_snd);
324 if_attach(ifp); 320 if_attach(ifp);
325 ether_ifattach(&xneti->xni_if, xneti->xni_enaddr); 321 ether_ifattach(&xneti->xni_if, xneti->xni_enaddr);
326 322
327 SLIST_INSERT_HEAD(&xnetback_instances, xneti, next); 323 SLIST_INSERT_HEAD(&xnetback_instances, xneti, next);
328 324
329 xbusd->xbusd_otherend_changed = xennetback_frontend_changed; 325 xbusd->xbusd_otherend_changed = xennetback_frontend_changed;
330 326
 327 do {
 328 xbt = xenbus_transaction_start();
 329 if (xbt == NULL) {
 330 printf("xbdback %s: can't start transaction\n",
 331 xbusd->xbusd_path);
 332 goto fail;
 333 }
 334 err = xenbus_printf(xbt, xbusd->xbusd_path,
 335 "feature-rx-copy", "%d", 1);
 336 if (err) {
 337 printf("xbdback: failed to write %s/feature-rx-copy: "
 338 "%d\n", xbusd->xbusd_path, err);
 339 goto abort_xbt;
 340 }
 341 err = xenbus_printf(xbt, xbusd->xbusd_path,
 342 "feature-rx-flip", "%d", 1);
 343 if (err) {
 344 printf("xbdback: failed to write %s/feature-rx-flip: "
 345 "%d\n", xbusd->xbusd_path, err);
 346 goto abort_xbt;
 347 }
 348 } while ((err = xenbus_transaction_end(xbt, 0)) == EAGAIN);
 349 if (err) {
 350 printf("xbdback %s: can't end transaction: %d\n",
 351 xbusd->xbusd_path, err);
 352 }
 353
331 err = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait); 354 err = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait);
332 if (err) { 355 if (err) {
333 printf("failed to switch state on %s: %d\n", 356 printf("failed to switch state on %s: %d\n",
334 xbusd->xbusd_path, err); 357 xbusd->xbusd_path, err);
335 goto fail; 358 goto fail;
336 } 359 }
337 if (err) { 360 if (err) {
338 printf("failed to write %s/hotplug-status: %d\n", 361 printf("failed to write %s/hotplug-status: %d\n",
339 xbusd->xbusd_path, err); 362 xbusd->xbusd_path, err);
340 goto fail; 363 goto fail;
341 } 364 }
342 return 0; 365 return 0;
 366abort_xbt:
 367 xenbus_transaction_end(xbt, 1);
343fail: 368fail:
344 free(xneti, M_DEVBUF); 369 free(xneti, M_DEVBUF);
345 return err; 370 return err;
346} 371}
347 372
348int 373int
349xennetback_xenbus_destroy(void *arg) 374xennetback_xenbus_destroy(void *arg)
350{ 375{
351 struct xnetback_instance *xneti = arg; 376 struct xnetback_instance *xneti = arg;
352 struct gnttab_unmap_grant_ref op; 377 struct gnttab_unmap_grant_ref op;
353 int err; 378 int err;
354 379
355#if 0 380#if 0
356 if (xneti->xni_status == CONNECTED) { 381 if (xneti->xni_status == CONNECTED) {
357 return EBUSY; 382 return EBUSY;
358 } 383 }
359#endif 384#endif
360 aprint_verbose_ifnet(&xneti->xni_if, "disconnecting\n"); 385 aprint_verbose_ifnet(&xneti->xni_if, "disconnecting\n");
361 hypervisor_mask_event(xneti->xni_evtchn); 386 hypervisor_mask_event(xneti->xni_evtchn);
362 event_remove_handler(xneti->xni_evtchn, xennetback_evthandler, xneti); 387 event_remove_handler(xneti->xni_evtchn, xennetback_evthandler, xneti);
363 softint_disestablish(xneti->xni_softintr); 388 softint_disestablish(xneti->xni_softintr);
364 389
365 SLIST_REMOVE(&xnetback_instances, 390 SLIST_REMOVE(&xnetback_instances,
366 xneti, xnetback_instance, next); 391 xneti, xnetback_instance, next);
367 392
368 ether_ifdetach(&xneti->xni_if); 393 ether_ifdetach(&xneti->xni_if);
369 if_detach(&xneti->xni_if); 394 if_detach(&xneti->xni_if);
370 395
371 if (xneti->xni_txring.sring) { 396 if (xneti->xni_txring.sring) {
372 op.host_addr = xneti->xni_tx_ring_va; 397 op.host_addr = xneti->xni_tx_ring_va;
373 op.handle = xneti->xni_tx_ring_handle; 398 op.handle = xneti->xni_tx_ring_handle;
374 op.dev_bus_addr = 0; 399 op.dev_bus_addr = 0;
375 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 400 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
376 &op, 1); 401 &op, 1);
377 if (err) 402 if (err)
378 aprint_error_ifnet(&xneti->xni_if, 403 aprint_error_ifnet(&xneti->xni_if,
379 "unmap_grant_ref failed: %d\n", err); 404 "unmap_grant_ref failed: %d\n", err);
380 } 405 }
381 if (xneti->xni_rxring.sring) { 406 if (xneti->xni_rxring.sring) {
382 op.host_addr = xneti->xni_rx_ring_va; 407 op.host_addr = xneti->xni_rx_ring_va;
383 op.handle = xneti->xni_rx_ring_handle; 408 op.handle = xneti->xni_rx_ring_handle;
384 op.dev_bus_addr = 0; 409 op.dev_bus_addr = 0;
385 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 410 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
386 &op, 1); 411 &op, 1);
387 if (err) 412 if (err)
388 aprint_error_ifnet(&xneti->xni_if, 413 aprint_error_ifnet(&xneti->xni_if,
389 "unmap_grant_ref failed: %d\n", err); 414 "unmap_grant_ref failed: %d\n", err);
390 } 415 }
391 uvm_km_free(kernel_map, xneti->xni_tx_ring_va, 416 uvm_km_free(kernel_map, xneti->xni_tx_ring_va,
392 PAGE_SIZE, UVM_KMF_VAONLY); 417 PAGE_SIZE, UVM_KMF_VAONLY);
393 uvm_km_free(kernel_map, xneti->xni_rx_ring_va, 418 uvm_km_free(kernel_map, xneti->xni_rx_ring_va,
394 PAGE_SIZE, UVM_KMF_VAONLY); 419 PAGE_SIZE, UVM_KMF_VAONLY);
395 free(xneti, M_DEVBUF); 420 free(xneti, M_DEVBUF);
396 return 0; 421 return 0;
397} 422}
398 423
399static void 424static void
400xennetback_frontend_changed(void *arg, XenbusState new_state) 425xennetback_frontend_changed(void *arg, XenbusState new_state)
401{ 426{
402 struct xnetback_instance *xneti = arg; 427 struct xnetback_instance *xneti = arg;
403 struct xenbus_device *xbusd = xneti->xni_xbusd; 428 struct xenbus_device *xbusd = xneti->xni_xbusd;
404 int err; 429 int err;
405 netif_tx_sring_t *tx_ring; 430 netif_tx_sring_t *tx_ring;
406 netif_rx_sring_t *rx_ring; 431 netif_rx_sring_t *rx_ring;
407 struct gnttab_map_grant_ref op; 432 struct gnttab_map_grant_ref op;
408 evtchn_op_t evop; 433 evtchn_op_t evop;
409 u_long tx_ring_ref, rx_ring_ref; 434 u_long tx_ring_ref, rx_ring_ref;
410 u_long revtchn; 435 u_long revtchn, rx_copy;
411 436
412 XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state)); 437 XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state));
413 switch(new_state) { 438 switch(new_state) {
414 case XenbusStateInitialising: 439 case XenbusStateInitialising:
415 case XenbusStateInitialised: 440 case XenbusStateInitialised:
416 break; 441 break;
417 442
418 case XenbusStateConnected: 443 case XenbusStateConnected:
419 /* read comunication informations */ 444 /* read comunication informations */
420 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 445 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
421 "tx-ring-ref", &tx_ring_ref, 10); 446 "tx-ring-ref", &tx_ring_ref, 10);
422 if (err) { 447 if (err) {
423 xenbus_dev_fatal(xbusd, err, "reading %s/tx-ring-ref", 448 xenbus_dev_fatal(xbusd, err, "reading %s/tx-ring-ref",
424 xbusd->xbusd_otherend); 449 xbusd->xbusd_otherend);
425 break; 450 break;
426 } 451 }
427 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 452 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
428 "rx-ring-ref", &rx_ring_ref, 10); 453 "rx-ring-ref", &rx_ring_ref, 10);
429 if (err) { 454 if (err) {
430 xenbus_dev_fatal(xbusd, err, "reading %s/rx-ring-ref", 455 xenbus_dev_fatal(xbusd, err, "reading %s/rx-ring-ref",
431 xbusd->xbusd_otherend); 456 xbusd->xbusd_otherend);
432 break; 457 break;
433 } 458 }
434 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 459 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
435 "event-channel", &revtchn, 10); 460 "event-channel", &revtchn, 10);
436 if (err) { 461 if (err) {
437 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", 462 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel",
438 xbusd->xbusd_otherend); 463 xbusd->xbusd_otherend);
439 break; 464 break;
440 } 465 }
 466 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
 467 "request-rx-copy", &rx_copy, 10);
 468 if (err == ENOENT)
 469 rx_copy = 0;
 470 else if (err) {
 471 xenbus_dev_fatal(xbusd, err, "reading %s/request-rx-copy",
 472 xbusd->xbusd_otherend);
 473 break;
 474 }
 475
 476 if (rx_copy)
 477 xneti->xni_softintr = softint_establish(SOFTINT_NET,
 478 xennetback_ifsoftstart_copy, xneti);
 479 else
 480 xneti->xni_softintr = softint_establish(SOFTINT_NET,
 481 xennetback_ifsoftstart_transfer, xneti);
 482 if (xneti->xni_softintr == NULL) {
 483 err = ENOMEM;
 484 xenbus_dev_fatal(xbusd, ENOMEM,
 485 "can't allocate softint", xbusd->xbusd_otherend);
 486 break;
 487 }
 488
441 /* allocate VA space and map rings */ 489 /* allocate VA space and map rings */
442 xneti->xni_tx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 490 xneti->xni_tx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
443 UVM_KMF_VAONLY); 491 UVM_KMF_VAONLY);
444 if (xneti->xni_tx_ring_va == 0) { 492 if (xneti->xni_tx_ring_va == 0) {
445 xenbus_dev_fatal(xbusd, ENOMEM, 493 xenbus_dev_fatal(xbusd, ENOMEM,
446 "can't get VA for tx ring", xbusd->xbusd_otherend); 494 "can't get VA for tx ring", xbusd->xbusd_otherend);
447 break; 495 break;
448 } 496 }
449 tx_ring = (void *)xneti->xni_tx_ring_va; 497 tx_ring = (void *)xneti->xni_tx_ring_va;
450 xneti->xni_rx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 498 xneti->xni_rx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
451 UVM_KMF_VAONLY); 499 UVM_KMF_VAONLY);
452 if (xneti->xni_rx_ring_va == 0) { 500 if (xneti->xni_rx_ring_va == 0) {
453 xenbus_dev_fatal(xbusd, ENOMEM, 501 xenbus_dev_fatal(xbusd, ENOMEM,
454 "can't get VA for rx ring", xbusd->xbusd_otherend); 502 "can't get VA for rx ring", xbusd->xbusd_otherend);
455 goto err1; 503 goto err1;
456 } 504 }
457 rx_ring = (void *)xneti->xni_rx_ring_va; 505 rx_ring = (void *)xneti->xni_rx_ring_va;
458 op.host_addr = xneti->xni_tx_ring_va; 506 op.host_addr = xneti->xni_tx_ring_va;
459 op.flags = GNTMAP_host_map; 507 op.flags = GNTMAP_host_map;
460 op.ref = tx_ring_ref; 508 op.ref = tx_ring_ref;
461 op.dom = xneti->xni_domid; 509 op.dom = xneti->xni_domid;
462 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); 510 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
463 if (err || op.status) { 511 if (err || op.status) {
464 printf("%s: can't map TX grant ref: %d/%d\n", 512 printf("%s: can't map TX grant ref: %d/%d\n",
465 xneti->xni_if.if_xname, err, op.status); 513 xneti->xni_if.if_xname, err, op.status);
466 goto err2; 514 goto err2;
467 } 515 }
468 xneti->xni_tx_ring_handle = op.handle; 516 xneti->xni_tx_ring_handle = op.handle;
469 517
470 op.host_addr = xneti->xni_rx_ring_va; 518 op.host_addr = xneti->xni_rx_ring_va;
471 op.flags = GNTMAP_host_map; 519 op.flags = GNTMAP_host_map;
472 op.ref = rx_ring_ref; 520 op.ref = rx_ring_ref;
473 op.dom = xneti->xni_domid; 521 op.dom = xneti->xni_domid;
474 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); 522 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
475 if (err || op.status) { 523 if (err || op.status) {
476 printf("%s: can't map RX grant ref: %d/%d\n", 524 printf("%s: can't map RX grant ref: %d/%d\n",
477 xneti->xni_if.if_xname, err, op.status); 525 xneti->xni_if.if_xname, err, op.status);
478 goto err2; 526 goto err2;
479 } 527 }
480 xneti->xni_rx_ring_handle = op.handle; 528 xneti->xni_rx_ring_handle = op.handle;
481 BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE); 529 BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE);
482 BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE); 530 BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE);
483 evop.cmd = EVTCHNOP_bind_interdomain; 531 evop.cmd = EVTCHNOP_bind_interdomain;
484 evop.u.bind_interdomain.remote_dom = xneti->xni_domid; 532 evop.u.bind_interdomain.remote_dom = xneti->xni_domid;
485 evop.u.bind_interdomain.remote_port = revtchn; 533 evop.u.bind_interdomain.remote_port = revtchn;
486 err = HYPERVISOR_event_channel_op(&evop); 534 err = HYPERVISOR_event_channel_op(&evop);
487 if (err) { 535 if (err) {
488 printf("%s: can't get event channel: %d\n", 536 printf("%s: can't get event channel: %d\n",
489 xneti->xni_if.if_xname, err); 537 xneti->xni_if.if_xname, err);
490 goto err2; 538 goto err2;
491 } 539 }
492 xneti->xni_evtchn = evop.u.bind_interdomain.local_port; 540 xneti->xni_evtchn = evop.u.bind_interdomain.local_port;
493 x86_sfence(); 541 x86_sfence();
494 xneti->xni_status = CONNECTED; 542 xneti->xni_status = CONNECTED;
495 xenbus_switch_state(xbusd, NULL, XenbusStateConnected); 543 xenbus_switch_state(xbusd, NULL, XenbusStateConnected);
496 x86_sfence(); 544 x86_sfence();
497 event_set_handler(xneti->xni_evtchn, xennetback_evthandler, 545 event_set_handler(xneti->xni_evtchn, xennetback_evthandler,
498 xneti, IPL_NET, xneti->xni_if.if_xname); 546 xneti, IPL_NET, xneti->xni_if.if_xname);
499 xennetback_ifinit(&xneti->xni_if); 547 xennetback_ifinit(&xneti->xni_if);
500 hypervisor_enable_event(xneti->xni_evtchn); 548 hypervisor_enable_event(xneti->xni_evtchn);
501 hypervisor_notify_via_evtchn(xneti->xni_evtchn); 549 hypervisor_notify_via_evtchn(xneti->xni_evtchn);
502 break; 550 break;
503 551
504 case XenbusStateClosing: 552 case XenbusStateClosing:
505 xneti->xni_status = DISCONNECTING; 553 xneti->xni_status = DISCONNECTING;
506 xneti->xni_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 554 xneti->xni_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
507 xneti->xni_if.if_timer = 0; 555 xneti->xni_if.if_timer = 0;
508 xenbus_switch_state(xbusd, NULL, XenbusStateClosing); 556 xenbus_switch_state(xbusd, NULL, XenbusStateClosing);
509 break; 557 break;
510 558
511 case XenbusStateClosed: 559 case XenbusStateClosed:
512 /* otherend_changed() should handle it for us */ 560 /* otherend_changed() should handle it for us */
513 panic("xennetback_frontend_changed: closed\n"); 561 panic("xennetback_frontend_changed: closed\n");
514 case XenbusStateUnknown:  562 case XenbusStateUnknown:
515 case XenbusStateInitWait: 563 case XenbusStateInitWait:
516 default: 564 default:
517 aprint_error("%s: invalid frontend state %d\n", 565 aprint_error("%s: invalid frontend state %d\n",
518 xneti->xni_if.if_xname, new_state); 566 xneti->xni_if.if_xname, new_state);
519 break; 567 break;
520 } 568 }
521 return; 569 return;
522err2: 570err2:
523 uvm_km_free(kernel_map, xneti->xni_rx_ring_va, 571 uvm_km_free(kernel_map, xneti->xni_rx_ring_va,
524 PAGE_SIZE, UVM_KMF_VAONLY); 572 PAGE_SIZE, UVM_KMF_VAONLY);
525err1: 573err1:
526 uvm_km_free(kernel_map, xneti->xni_tx_ring_va, 574 uvm_km_free(kernel_map, xneti->xni_tx_ring_va,
527 PAGE_SIZE, UVM_KMF_VAONLY); 575 PAGE_SIZE, UVM_KMF_VAONLY);
528} 576}
529 577
530/* lookup a xneti based on domain id and interface handle */ 578/* lookup a xneti based on domain id and interface handle */
531static struct xnetback_instance * 579static struct xnetback_instance *
532xnetif_lookup(domid_t dom , uint32_t handle) 580xnetif_lookup(domid_t dom , uint32_t handle)
533{ 581{
534 struct xnetback_instance *xneti; 582 struct xnetback_instance *xneti;
535 583
536 SLIST_FOREACH(xneti, &xnetback_instances, next) { 584 SLIST_FOREACH(xneti, &xnetback_instances, next) {
537 if (xneti->xni_domid == dom && xneti->xni_handle == handle) 585 if (xneti->xni_domid == dom && xneti->xni_handle == handle)
538 return xneti; 586 return xneti;
539 } 587 }
540 return NULL; 588 return NULL;
541} 589}
542 590
543 591
544/* get a page to remplace a mbuf cluster page given to a domain */ 592/* get a page to remplace a mbuf cluster page given to a domain */
545static int 593static int
546xennetback_get_mcl_page(paddr_t *map) 594xennetback_get_mcl_page(paddr_t *map)
547{ 595{
548 if (mcl_pages_alloc < 0) 596 if (mcl_pages_alloc < 0)
549 /* 597 /*
550 * we exhausted our allocation. We can't allocate new ones yet 598 * we exhausted our allocation. We can't allocate new ones yet
551 * because the current pages may not have been loaned to 599 * because the current pages may not have been loaned to
552 * the remote domain yet. We have to let the caller do this. 600 * the remote domain yet. We have to let the caller do this.
553 */ 601 */
554 return -1; 602 return -1;
555 603
556 *map = mcl_pages[mcl_pages_alloc] << PAGE_SHIFT; 604 *map = mcl_pages[mcl_pages_alloc] << PAGE_SHIFT;
557 mcl_pages_alloc--; 605 mcl_pages_alloc--;
558 return 0; 606 return 0;
559  607
560} 608}
561 609
562static void 610static void
563xennetback_get_new_mcl_pages(void) 611xennetback_get_new_mcl_pages(void)
564{ 612{
565 int nb_pages; 613 int nb_pages;
566 struct xen_memory_reservation res; 614 struct xen_memory_reservation res;
567 615
568 /* get some new pages. */ 616 /* get some new pages. */
569 res.extent_start = mcl_pages; 617 res.extent_start = mcl_pages;
570 res.nr_extents = NB_XMIT_PAGES_BATCH; 618 res.nr_extents = NB_XMIT_PAGES_BATCH;
571 res.extent_order = 0; 619 res.extent_order = 0;
572 res.address_bits = 0; 620 res.address_bits = 0;
573 res.domid = DOMID_SELF; 621 res.domid = DOMID_SELF;
574 622
575 nb_pages = HYPERVISOR_memory_op(XENMEM_increase_reservation, &res); 623 nb_pages = HYPERVISOR_memory_op(XENMEM_increase_reservation, &res);
576 if (nb_pages <= 0) { 624 if (nb_pages <= 0) {
577 printf("xennetback: can't get new mcl pages (%d)\n", nb_pages); 625 printf("xennetback: can't get new mcl pages (%d)\n", nb_pages);
578 return; 626 return;
579 } 627 }
580 if (nb_pages != NB_XMIT_PAGES_BATCH) 628 if (nb_pages != NB_XMIT_PAGES_BATCH)
581 printf("xennetback: got only %d new mcl pages\n", nb_pages); 629 printf("xennetback: got only %d new mcl pages\n", nb_pages);
582 630
583 mcl_pages_alloc = nb_pages - 1; 631 mcl_pages_alloc = nb_pages - 1;
584} 632}
585 633
586static inline void 634static inline void
587xennetback_tx_response(struct xnetback_instance *xneti, int id, int status) 635xennetback_tx_response(struct xnetback_instance *xneti, int id, int status)
588{ 636{
589 RING_IDX resp_prod; 637 RING_IDX resp_prod;
590 netif_tx_response_t *txresp; 638 netif_tx_response_t *txresp;
591 int do_event; 639 int do_event;
592 640
593 resp_prod = xneti->xni_txring.rsp_prod_pvt; 641 resp_prod = xneti->xni_txring.rsp_prod_pvt;
594 txresp = RING_GET_RESPONSE(&xneti->xni_txring, resp_prod); 642 txresp = RING_GET_RESPONSE(&xneti->xni_txring, resp_prod);
595 643
596 txresp->id = id; 644 txresp->id = id;
597 txresp->status = status; 645 txresp->status = status;
598 xneti->xni_txring.rsp_prod_pvt++; 646 xneti->xni_txring.rsp_prod_pvt++;
599 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xneti->xni_txring, do_event); 647 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xneti->xni_txring, do_event);
600 if (do_event) { 648 if (do_event) {
601 XENPRINTF(("%s send event\n", xneti->xni_if.if_xname)); 649 XENPRINTF(("%s send event\n", xneti->xni_if.if_xname));
602 hypervisor_notify_via_evtchn(xneti->xni_evtchn); 650 hypervisor_notify_via_evtchn(xneti->xni_evtchn);
603 } 651 }
604} 652}
605 653
606static int 654static int
607xennetback_evthandler(void *arg) 655xennetback_evthandler(void *arg)
608{ 656{
609 struct xnetback_instance *xneti = arg; 657 struct xnetback_instance *xneti = arg;
610 struct ifnet *ifp = &xneti->xni_if; 658 struct ifnet *ifp = &xneti->xni_if;
611 netif_tx_request_t *txreq; 659 netif_tx_request_t *txreq;
612 struct xni_pkt *pkt; 660 struct xni_pkt *pkt;
613 vaddr_t pkt_va; 661 vaddr_t pkt_va;
614 struct mbuf *m; 662 struct mbuf *m;
615 int receive_pending, err; 663 int receive_pending, err;
616 RING_IDX req_cons; 664 RING_IDX req_cons;
617 665
618 XENPRINTF(("xennetback_evthandler ")); 666 XENPRINTF(("xennetback_evthandler "));
619 req_cons = xneti->xni_txring.req_cons; 667 req_cons = xneti->xni_txring.req_cons;
620 x86_lfence(); 668 x86_lfence();
621 while (1) { 669 while (1) {
622 x86_lfence(); /* be sure to read the request before updating */ 670 x86_lfence(); /* be sure to read the request before updating */
623 xneti->xni_txring.req_cons = req_cons; 671 xneti->xni_txring.req_cons = req_cons;
624 x86_sfence(); 672 x86_sfence();
625 RING_FINAL_CHECK_FOR_REQUESTS(&xneti->xni_txring, 673 RING_FINAL_CHECK_FOR_REQUESTS(&xneti->xni_txring,
626 receive_pending); 674 receive_pending);
627 if (receive_pending == 0) 675 if (receive_pending == 0)
628 break; 676 break;
629 txreq = RING_GET_REQUEST(&xneti->xni_txring, req_cons); 677 txreq = RING_GET_REQUEST(&xneti->xni_txring, req_cons);
630 x86_lfence(); 678 x86_lfence();
631 XENPRINTF(("%s pkt size %d\n", xneti->xni_if.if_xname, 679 XENPRINTF(("%s pkt size %d\n", xneti->xni_if.if_xname,
632 txreq->size)); 680 txreq->size));
633 req_cons++; 681 req_cons++;
634 if (__predict_false((ifp->if_flags & (IFF_UP | IFF_RUNNING)) != 682 if (__predict_false((ifp->if_flags & (IFF_UP | IFF_RUNNING)) !=
635 (IFF_UP | IFF_RUNNING))) { 683 (IFF_UP | IFF_RUNNING))) {
636 /* interface not up, drop */ 684 /* interface not up, drop */
637 xennetback_tx_response(xneti, txreq->id, 685 xennetback_tx_response(xneti, txreq->id,
638 NETIF_RSP_DROPPED); 686 NETIF_RSP_DROPPED);
639 continue; 687 continue;
640 } 688 }
641 /* 689 /*
642 * Do some sanity checks, and map the packet's page. 690 * Do some sanity checks, and map the packet's page.
643 */ 691 */
644 if (__predict_false(txreq->size < ETHER_HDR_LEN || 692 if (__predict_false(txreq->size < ETHER_HDR_LEN ||
645 txreq->size > (ETHER_MAX_LEN - ETHER_CRC_LEN))) { 693 txreq->size > (ETHER_MAX_LEN - ETHER_CRC_LEN))) {
646 printf("%s: packet size %d too big\n", 694 printf("%s: packet size %d too big\n",
647 ifp->if_xname, txreq->size); 695 ifp->if_xname, txreq->size);
648 xennetback_tx_response(xneti, txreq->id, 696 xennetback_tx_response(xneti, txreq->id,
649 NETIF_RSP_ERROR); 697 NETIF_RSP_ERROR);
650 ifp->if_ierrors++; 698 ifp->if_ierrors++;
651 continue; 699 continue;
652 } 700 }
653 /* don't cross page boundaries */ 701 /* don't cross page boundaries */
654 if (__predict_false( 702 if (__predict_false(
655 txreq->offset + txreq->size > PAGE_SIZE)) { 703 txreq->offset + txreq->size > PAGE_SIZE)) {
656 printf("%s: packet cross page boundary\n", 704 printf("%s: packet cross page boundary\n",
657 ifp->if_xname); 705 ifp->if_xname);
658 xennetback_tx_response(xneti, txreq->id, 706 xennetback_tx_response(xneti, txreq->id,
659 NETIF_RSP_ERROR); 707 NETIF_RSP_ERROR);
660 ifp->if_ierrors++; 708 ifp->if_ierrors++;
661 continue; 709 continue;
662 } 710 }
663 /* get a mbuf for this packet */ 711 /* get a mbuf for this packet */
664 MGETHDR(m, M_DONTWAIT, MT_DATA); 712 MGETHDR(m, M_DONTWAIT, MT_DATA);
665 if (__predict_false(m == NULL)) { 713 if (__predict_false(m == NULL)) {
666 static struct timeval lasttime; 714 static struct timeval lasttime;
667 if (ratecheck(&lasttime, &xni_pool_errintvl)) 715 if (ratecheck(&lasttime, &xni_pool_errintvl))
668 printf("%s: mbuf alloc failed\n", 716 printf("%s: mbuf alloc failed\n",
669 ifp->if_xname); 717 ifp->if_xname);
670 xennetback_tx_response(xneti, txreq->id, 718 xennetback_tx_response(xneti, txreq->id,
671 NETIF_RSP_DROPPED); 719 NETIF_RSP_DROPPED);
672 ifp->if_ierrors++; 720 ifp->if_ierrors++;
673 continue; 721 continue;
674 } 722 }
675 723
676 XENPRINTF(("%s pkt offset %d size %d id %d req_cons %d\n", 724 XENPRINTF(("%s pkt offset %d size %d id %d req_cons %d\n",
677 xneti->xni_if.if_xname, txreq->offset, 725 xneti->xni_if.if_xname, txreq->offset,
678 txreq->size, txreq->id, MASK_NETIF_TX_IDX(req_cons))); 726 txreq->size, txreq->id, MASK_NETIF_TX_IDX(req_cons)));
679  727
680 pkt = pool_get(&xni_pkt_pool, PR_NOWAIT); 728 pkt = pool_get(&xni_pkt_pool, PR_NOWAIT);
681 if (__predict_false(pkt == NULL)) { 729 if (__predict_false(pkt == NULL)) {
682 static struct timeval lasttime; 730 static struct timeval lasttime;
683 if (ratecheck(&lasttime, &xni_pool_errintvl)) 731 if (ratecheck(&lasttime, &xni_pool_errintvl))
684 printf("%s: xnbpkt alloc failed\n", 732 printf("%s: xnbpkt alloc failed\n",
685 ifp->if_xname); 733 ifp->if_xname);
686 xennetback_tx_response(xneti, txreq->id, 734 xennetback_tx_response(xneti, txreq->id,
687 NETIF_RSP_DROPPED); 735 NETIF_RSP_DROPPED);
688 ifp->if_ierrors++; 736 ifp->if_ierrors++;
689 m_freem(m); 737 m_freem(m);
690 continue; 738 continue;
691 } 739 }
692 err = xen_shm_map(1, xneti->xni_domid, &txreq->gref, &pkt_va, 740 err = xen_shm_map(1, xneti->xni_domid, &txreq->gref, &pkt_va,
693 &pkt->pkt_handle, XSHM_RO); 741 &pkt->pkt_handle, XSHM_RO);
694 if (__predict_false(err == ENOMEM)) { 742 if (__predict_false(err == ENOMEM)) {
695 xennetback_tx_response(xneti, txreq->id, 743 xennetback_tx_response(xneti, txreq->id,
696 NETIF_RSP_DROPPED); 744 NETIF_RSP_DROPPED);
697 ifp->if_ierrors++; 745 ifp->if_ierrors++;
698 pool_put(&xni_pkt_pool, pkt); 746 pool_put(&xni_pkt_pool, pkt);
699 m_freem(m); 747 m_freem(m);
700 continue; 748 continue;
701 } 749 }
702  750
703 if (__predict_false(err)) { 751 if (__predict_false(err)) {
704 printf("%s: mapping foreing page failed: %d\n", 752 printf("%s: mapping foreing page failed: %d\n",
705 xneti->xni_if.if_xname, err); 753 xneti->xni_if.if_xname, err);
706 xennetback_tx_response(xneti, txreq->id, 754 xennetback_tx_response(xneti, txreq->id,
707 NETIF_RSP_ERROR); 755 NETIF_RSP_ERROR);
708 ifp->if_ierrors++; 756 ifp->if_ierrors++;
709 pool_put(&xni_pkt_pool, pkt); 757 pool_put(&xni_pkt_pool, pkt);
710 m_freem(m); 758 m_freem(m);
711 continue; 759 continue;
712 } 760 }
713 761
714 if ((ifp->if_flags & IFF_PROMISC) == 0) { 762 if ((ifp->if_flags & IFF_PROMISC) == 0) {
715 struct ether_header *eh = 763 struct ether_header *eh =
716 (void*)(pkt_va + txreq->offset); 764 (void*)(pkt_va + txreq->offset);
717 if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 && 765 if (ETHER_IS_MULTICAST(eh->ether_dhost) == 0 &&
718 memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, 766 memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost,
719 ETHER_ADDR_LEN) != 0) { 767 ETHER_ADDR_LEN) != 0) {
720 xni_pkt_unmap(pkt, pkt_va); 768 xni_pkt_unmap(pkt, pkt_va);
721 m_freem(m); 769 m_freem(m);
722 xennetback_tx_response(xneti, txreq->id, 770 xennetback_tx_response(xneti, txreq->id,
723 NETIF_RSP_OKAY); 771 NETIF_RSP_OKAY);
724 continue; /* packet is not for us */ 772 continue; /* packet is not for us */
725 } 773 }
726 } 774 }
727#ifdef notyet 775#ifdef notyet
728a lot of work is needed in the tcp stack to handle read-only ext storage 776a lot of work is needed in the tcp stack to handle read-only ext storage
729so always copy for now. 777so always copy for now.
730 if (((req_cons + 1) & (NET_TX_RING_SIZE - 1)) == 778 if (((req_cons + 1) & (NET_TX_RING_SIZE - 1)) ==
731 (xneti->xni_txring.rsp_prod_pvt & (NET_TX_RING_SIZE - 1))) 779 (xneti->xni_txring.rsp_prod_pvt & (NET_TX_RING_SIZE - 1)))
732#else 780#else
733 if (1) 781 if (1)
734#endif /* notyet */ 782#endif /* notyet */
735 { 783 {
736 /* 784 /*
737 * This is the last TX buffer. Copy the data and 785 * This is the last TX buffer. Copy the data and
738 * ack it. Delaying it until the mbuf is 786 * ack it. Delaying it until the mbuf is
739 * freed will stall transmit. 787 * freed will stall transmit.
740 */ 788 */
741 m->m_len = min(MHLEN, txreq->size); 789 m->m_len = min(MHLEN, txreq->size);
742 m->m_pkthdr.len = 0; 790 m->m_pkthdr.len = 0;
743 m_copyback(m, 0, txreq->size, 791 m_copyback(m, 0, txreq->size,
744 (void *)(pkt_va + txreq->offset)); 792 (void *)(pkt_va + txreq->offset));
745 xni_pkt_unmap(pkt, pkt_va); 793 xni_pkt_unmap(pkt, pkt_va);
746 if (m->m_pkthdr.len < txreq->size) { 794 if (m->m_pkthdr.len < txreq->size) {
747 ifp->if_ierrors++; 795 ifp->if_ierrors++;
748 m_freem(m); 796 m_freem(m);
749 xennetback_tx_response(xneti, txreq->id, 797 xennetback_tx_response(xneti, txreq->id,
750 NETIF_RSP_DROPPED); 798 NETIF_RSP_DROPPED);
751 continue; 799 continue;
752 } 800 }
753 xennetback_tx_response(xneti, txreq->id, 801 xennetback_tx_response(xneti, txreq->id,
754 NETIF_RSP_OKAY); 802 NETIF_RSP_OKAY);
755 } else { 803 } else {
756 804
757 pkt->pkt_id = txreq->id; 805 pkt->pkt_id = txreq->id;
758 pkt->pkt_xneti = xneti; 806 pkt->pkt_xneti = xneti;
759 807
760 MEXTADD(m, pkt_va + txreq->offset, 808 MEXTADD(m, pkt_va + txreq->offset,
761 txreq->size, M_DEVBUF, xennetback_tx_free, pkt); 809 txreq->size, M_DEVBUF, xennetback_tx_free, pkt);
762 m->m_pkthdr.len = m->m_len = txreq->size; 810 m->m_pkthdr.len = m->m_len = txreq->size;
763 m->m_flags |= M_EXT_ROMAP; 811 m->m_flags |= M_EXT_ROMAP;
764 } 812 }
765 if ((txreq->flags & NETTXF_csum_blank) != 0) { 813 if ((txreq->flags & NETTXF_csum_blank) != 0) {
766 xennet_checksum_fill(&m); 814 xennet_checksum_fill(&m);
767 if (m == NULL) { 815 if (m == NULL) {
768 ifp->if_ierrors++; 816 ifp->if_ierrors++;
769 continue; 817 continue;
770 } 818 }
771 } 819 }
772 m->m_pkthdr.rcvif = ifp; 820 m->m_pkthdr.rcvif = ifp;
773 ifp->if_ipackets++; 821 ifp->if_ipackets++;
774  822
775#if NBPFILTER > 0 823#if NBPFILTER > 0
776 if (ifp->if_bpf) 824 if (ifp->if_bpf)
777 bpf_mtap(ifp->if_bpf, m); 825 bpf_mtap(ifp->if_bpf, m);
778#endif 826#endif
779 (*ifp->if_input)(ifp, m); 827 (*ifp->if_input)(ifp, m);
780 } 828 }
781 x86_lfence(); /* be sure to read the request before updating pointer */ 829 x86_lfence(); /* be sure to read the request before updating pointer */
782 xneti->xni_txring.req_cons = req_cons; 830 xneti->xni_txring.req_cons = req_cons;
783 x86_sfence(); 831 x86_sfence();
784 /* check to see if we can transmit more packets */ 832 /* check to see if we can transmit more packets */
785 softint_schedule(xneti->xni_softintr); 833 softint_schedule(xneti->xni_softintr);
786 834
787 return 1; 835 return 1;
788} 836}
789 837
790static void 838static void
791xennetback_tx_free(struct mbuf *m, void *va, size_t size, void *arg) 839xennetback_tx_free(struct mbuf *m, void *va, size_t size, void *arg)
792{ 840{
793 int s = splnet(); 841 int s = splnet();
794 struct xni_pkt *pkt = arg; 842 struct xni_pkt *pkt = arg;
795 struct xnetback_instance *xneti = pkt->pkt_xneti; 843 struct xnetback_instance *xneti = pkt->pkt_xneti;
796 844
797 XENPRINTF(("xennetback_tx_free\n")); 845 XENPRINTF(("xennetback_tx_free\n"));
798 846
799 xennetback_tx_response(xneti, pkt->pkt_id, NETIF_RSP_OKAY); 847 xennetback_tx_response(xneti, pkt->pkt_id, NETIF_RSP_OKAY);
800 848
801 xni_pkt_unmap(pkt, (vaddr_t)va & ~PAGE_MASK); 849 xni_pkt_unmap(pkt, (vaddr_t)va & ~PAGE_MASK);
802 850
803 if (m) 851 if (m)
804 pool_cache_put(mb_cache, m); 852 pool_cache_put(mb_cache, m);
805 splx(s); 853 splx(s);
806} 854}
807 855
808static int 856static int
809xennetback_ifioctl(struct ifnet *ifp, u_long cmd, void *data) 857xennetback_ifioctl(struct ifnet *ifp, u_long cmd, void *data)
810{ 858{
811 //struct xnetback_instance *xneti = ifp->if_softc; 859 //struct xnetback_instance *xneti = ifp->if_softc;
812 //struct ifreq *ifr = (struct ifreq *)data; 860 //struct ifreq *ifr = (struct ifreq *)data;
813 int s, error; 861 int s, error;
814 862
815 s = splnet(); 863 s = splnet();
816 error = ether_ioctl(ifp, cmd, data); 864 error = ether_ioctl(ifp, cmd, data);
817 if (error == ENETRESET) 865 if (error == ENETRESET)
818 error = 0; 866 error = 0;
819 splx(s); 867 splx(s);
820 return error; 868 return error;
821} 869}
822 870
823static void 871static void
824xennetback_ifstart(struct ifnet *ifp) 872xennetback_ifstart(struct ifnet *ifp)
825{ 873{
826 struct xnetback_instance *xneti = ifp->if_softc; 874 struct xnetback_instance *xneti = ifp->if_softc;
827 875
828 /* 876 /*
829 * The Xen communication channel is much more efficient if we can 877 * The Xen communication channel is much more efficient if we can
830 * schedule batch of packets for the domain. To achieve this, we 878 * schedule batch of packets for the domain. To achieve this, we
831 * schedule a soft interrupt, and just return. This way, the network 879 * schedule a soft interrupt, and just return. This way, the network
832 * stack will enqueue all pending mbufs in the interface's send queue 880 * stack will enqueue all pending mbufs in the interface's send queue
833 * before it is processed by xennet_softstart(). 881 * before it is processed by the soft inetrrupt handler().
834 */ 882 */
835 softint_schedule(xneti->xni_softintr); 883 softint_schedule(xneti->xni_softintr);
836} 884}
837 885
838static void 886static void
839xennetback_ifsoftstart(void *arg) 887xennetback_ifsoftstart_transfer(void *arg)
840{ 888{
841 struct xnetback_instance *xneti = arg; 889 struct xnetback_instance *xneti = arg;
842 struct ifnet *ifp = &xneti->xni_if; 890 struct ifnet *ifp = &xneti->xni_if;
843 struct mbuf *m; 891 struct mbuf *m;
844 vaddr_t xmit_va; 892 vaddr_t xmit_va;
845 paddr_t xmit_pa; 893 paddr_t xmit_pa;
846 paddr_t xmit_ma; 894 paddr_t xmit_ma;
847 paddr_t newp_ma = 0; /* XXX gcc */ 895 paddr_t newp_ma = 0; /* XXX gcc */
848 int i, j, nppitems; 896 int i, j, nppitems;
849 mmu_update_t *mmup; 897 mmu_update_t *mmup;
850 multicall_entry_t *mclp; 898 multicall_entry_t *mclp;
851 netif_rx_response_t *rxresp; 899 netif_rx_response_t *rxresp;
852 RING_IDX req_prod, resp_prod; 900 RING_IDX req_prod, resp_prod;
853 int do_event = 0; 901 int do_event = 0;
854 gnttab_transfer_t *gop; 902 gnttab_transfer_t *gop;
855 int id, offset; 903 int id, offset;
856 904
857 XENPRINTF(("xennetback_ifsoftstart ")); 905 XENPRINTF(("xennetback_ifsoftstart_transfer "));
858 int s = splnet(); 906 int s = splnet();
859 if (__predict_false( 907 if (__predict_false(
860 (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) { 908 (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) {
861 splx(s); 909 splx(s);
862 return; 910 return;
863 } 911 }
864 912
865 while (!IFQ_IS_EMPTY(&ifp->if_snd)) { 913 while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
866 XENPRINTF(("pkt\n")); 914 XENPRINTF(("pkt\n"));
867 req_prod = xneti->xni_rxring.sring->req_prod; 915 req_prod = xneti->xni_rxring.sring->req_prod;
868 resp_prod = xneti->xni_rxring.rsp_prod_pvt; 916 resp_prod = xneti->xni_rxring.rsp_prod_pvt;
869 x86_lfence(); 917 x86_lfence();
870 918
871 mmup = xstart_mmu; 919 mmup = xstart_mmu;
872 mclp = xstart_mcl; 920 mclp = xstart_mcl;
873 gop = xstart_gop; 921 gop = xstart_gop_transfer;
874 for (nppitems = 0, i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) { 922 for (nppitems = 0, i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) {
875 XENPRINTF(("have a packet\n")); 923 XENPRINTF(("have a packet\n"));
876 IFQ_POLL(&ifp->if_snd, m); 924 IFQ_POLL(&ifp->if_snd, m);
877 if (__predict_false(m == NULL)) 925 if (__predict_false(m == NULL))
878 panic("xennetback_ifstart: IFQ_POLL"); 926 panic("xennetback_ifstart: IFQ_POLL");
879 if (__predict_false( 927 if (__predict_false(
880 req_prod == xneti->xni_rxring.req_cons || 928 req_prod == xneti->xni_rxring.req_cons ||
881 xneti->xni_rxring.req_cons - resp_prod == 929 xneti->xni_rxring.req_cons - resp_prod ==
882 NET_RX_RING_SIZE)) { 930 NET_RX_RING_SIZE)) {
883 /* out of ring space */ 931 /* out of ring space */
884 XENPRINTF(("xennetback_ifstart: ring full " 932 XENPRINTF(("xennetback_ifstart: ring full "
885 "req_prod 0x%x req_cons 0x%x resp_prod " 933 "req_prod 0x%x req_cons 0x%x resp_prod "
886 "0x%x\n", 934 "0x%x\n",
887 req_prod, xneti->xni_rxring.req_cons, 935 req_prod, xneti->xni_rxring.req_cons,
888 resp_prod)); 936 resp_prod));
889 ifp->if_timer = 1; 937 ifp->if_timer = 1;
890 break; 938 break;
891 } 939 }
892 if (__predict_false(i == NB_XMIT_PAGES_BATCH)) 940 if (__predict_false(i == NB_XMIT_PAGES_BATCH))
893 break; /* we filled the array */ 941 break; /* we filled the array */
894 if (__predict_false( 942 if (__predict_false(
895 xennetback_get_mcl_page(&newp_ma) != 0)) 943 xennetback_get_mcl_page(&newp_ma) != 0))
896 break; /* out of memory */ 944 break; /* out of memory */
897 if ((m->m_flags & M_CLUSTER) != 0 && 945 if ((m->m_flags & M_CLUSTER) != 0 &&
898 !M_READONLY(m) && MCLBYTES == PAGE_SIZE) { 946 !M_READONLY(m) && MCLBYTES == PAGE_SIZE) {
899 /* we can give this page away */ 947 /* we can give this page away */
900 xmit_pa = m->m_ext.ext_paddr; 948 xmit_pa = m->m_ext.ext_paddr;
901 xmit_ma = xpmap_ptom(xmit_pa); 949 xmit_ma = xpmap_ptom(xmit_pa);
902 xmit_va = (vaddr_t)m->m_ext.ext_buf; 950 xmit_va = (vaddr_t)m->m_ext.ext_buf;
903 KASSERT(xmit_pa != M_PADDR_INVALID); 951 KASSERT(xmit_pa != M_PADDR_INVALID);
904 KASSERT((xmit_va & PAGE_MASK) == 0); 952 KASSERT((xmit_va & PAGE_MASK) == 0);
905 offset = m->m_data - m->m_ext.ext_buf; 953 offset = m->m_data - m->m_ext.ext_buf;
906 } else { 954 } else {
907 /* we have to copy the packet */ 955 /* we have to copy the packet */
908 xmit_va = (vaddr_t)pool_cache_get_paddr( 956 xmit_va = (vaddr_t)pool_cache_get_paddr(
909 xmit_pages_cachep, 957 xmit_pages_cachep,
910 PR_NOWAIT, &xmit_pa); 958 PR_NOWAIT, &xmit_pa);
911 if (__predict_false(xmit_va == 0)) 959 if (__predict_false(xmit_va == 0))
912 break; /* out of memory */ 960 break; /* out of memory */
913 961
914 KASSERT(xmit_pa != POOL_PADDR_INVALID); 962 KASSERT(xmit_pa != POOL_PADDR_INVALID);
915 xmit_ma = xpmap_ptom(xmit_pa); 963 xmit_ma = xpmap_ptom(xmit_pa);
916 XENPRINTF(("xennetback_get_xmit_page: got va " 964 XENPRINTF(("xennetback_get_xmit_page: got va "
917 "0x%x ma 0x%x\n", (u_int)xmit_va, 965 "0x%x ma 0x%x\n", (u_int)xmit_va,
918 (u_int)xmit_ma)); 966 (u_int)xmit_ma));
919 m_copydata(m, 0, m->m_pkthdr.len, 967 m_copydata(m, 0, m->m_pkthdr.len,
920 (char *)xmit_va + LINUX_REQUESTED_OFFSET); 968 (char *)xmit_va + LINUX_REQUESTED_OFFSET);
921 offset = LINUX_REQUESTED_OFFSET; 969 offset = LINUX_REQUESTED_OFFSET;
922 pages_pool_free[nppitems].va = xmit_va; 970 pages_pool_free[nppitems].va = xmit_va;
923 pages_pool_free[nppitems].pa = xmit_pa; 971 pages_pool_free[nppitems].pa = xmit_pa;
924 nppitems++; 972 nppitems++;
925 } 973 }
926 /* start filling ring */ 974 /* start filling ring */
927 gop->ref = RING_GET_REQUEST(&xneti->xni_rxring, 975 gop->ref = RING_GET_REQUEST(&xneti->xni_rxring,
928 xneti->xni_rxring.req_cons)->gref; 976 xneti->xni_rxring.req_cons)->gref;
929 id = RING_GET_REQUEST(&xneti->xni_rxring, 977 id = RING_GET_REQUEST(&xneti->xni_rxring,
930 xneti->xni_rxring.req_cons)->id; 978 xneti->xni_rxring.req_cons)->id;
931 x86_lfence(); 979 x86_lfence();
932 xneti->xni_rxring.req_cons++; 980 xneti->xni_rxring.req_cons++;
933 rxresp = RING_GET_RESPONSE(&xneti->xni_rxring, 981 rxresp = RING_GET_RESPONSE(&xneti->xni_rxring,
934 resp_prod); 982 resp_prod);
935 rxresp->id = id; 983 rxresp->id = id;
936 rxresp->offset = offset; 984 rxresp->offset = offset;
937 rxresp->status = m->m_pkthdr.len; 985 rxresp->status = m->m_pkthdr.len;
938 if ((m->m_pkthdr.csum_flags & 986 if ((m->m_pkthdr.csum_flags &
939 (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) { 987 (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) {
940 rxresp->flags = NETRXF_csum_blank; 988 rxresp->flags = NETRXF_csum_blank;
941 } else { 989 } else {
942 rxresp->flags = 0; 990 rxresp->flags = 0;
943 } 991 }
944 /* 992 /*
945 * transfers the page containing the packet to the 993 * transfers the page containing the packet to the
946 * remote domain, and map newp in place. 994 * remote domain, and map newp in place.
947 */ 995 */
948 xpmap_phys_to_machine_mapping[ 996 xpmap_phys_to_machine_mapping[
949 (xmit_pa - XPMAP_OFFSET) >> PAGE_SHIFT] = 997 (xmit_pa - XPMAP_OFFSET) >> PAGE_SHIFT] =
950 newp_ma >> PAGE_SHIFT; 998 newp_ma >> PAGE_SHIFT;
951 MULTI_update_va_mapping(mclp, xmit_va, 999 MULTI_update_va_mapping(mclp, xmit_va,
952 newp_ma | PG_V | PG_RW | PG_U | PG_M, 0); 1000 newp_ma | PG_V | PG_RW | PG_U | PG_M, 0);
953 mclp++; 1001 mclp++;
954 gop->mfn = xmit_ma >> PAGE_SHIFT; 1002 gop->mfn = xmit_ma >> PAGE_SHIFT;
955 gop->domid = xneti->xni_domid; 1003 gop->domid = xneti->xni_domid;
956 gop++; 1004 gop++;
957 1005
958 mmup->ptr = newp_ma | MMU_MACHPHYS_UPDATE; 1006 mmup->ptr = newp_ma | MMU_MACHPHYS_UPDATE;
959 mmup->val = (xmit_pa - XPMAP_OFFSET) >> PAGE_SHIFT; 1007 mmup->val = (xmit_pa - XPMAP_OFFSET) >> PAGE_SHIFT;
960 mmup++; 1008 mmup++;
961 1009
962 /* done with this packet */ 1010 /* done with this packet */
963 IFQ_DEQUEUE(&ifp->if_snd, m); 1011 IFQ_DEQUEUE(&ifp->if_snd, m);
964 mbufs_sent[i] = m; 1012 mbufs_sent[i] = m;
965 resp_prod++; 1013 resp_prod++;
966 i++; /* this packet has been queued */ 1014 i++; /* this packet has been queued */
967 ifp->if_opackets++; 1015 ifp->if_opackets++;
968#if NBPFILTER > 0 1016#if NBPFILTER > 0
969 if (ifp->if_bpf) 1017 if (ifp->if_bpf)
970 bpf_mtap(ifp->if_bpf, m); 1018 bpf_mtap(ifp->if_bpf, m);
971#endif 1019#endif
972 } 1020 }
973 if (i != 0) { 1021 if (i != 0) {
974 /* 1022 /*
975 * We may have allocated buffers which have entries 1023 * We may have allocated buffers which have entries
976 * outstanding in the page update queue -- make sure 1024 * outstanding in the page update queue -- make sure
977 * we flush those first! 1025 * we flush those first!
978 */ 1026 */
979 int svm = splvm(); 1027 int svm = splvm();
980 xpq_flush_queue(); 1028 xpq_flush_queue();
981 splx(svm); 1029 splx(svm);
982 mclp[-1].args[MULTI_UVMFLAGS_INDEX] = 1030 mclp[-1].args[MULTI_UVMFLAGS_INDEX] =
983 UVMF_TLB_FLUSH|UVMF_ALL; 1031 UVMF_TLB_FLUSH|UVMF_ALL;
984 mclp->op = __HYPERVISOR_mmu_update; 1032 mclp->op = __HYPERVISOR_mmu_update;
985 mclp->args[0] = (unsigned long)xstart_mmu; 1033 mclp->args[0] = (unsigned long)xstart_mmu;
986 mclp->args[1] = i; 1034 mclp->args[1] = i;
987 mclp->args[2] = 0; 1035 mclp->args[2] = 0;
988 mclp->args[3] = DOMID_SELF; 1036 mclp->args[3] = DOMID_SELF;
989 mclp++; 1037 mclp++;
990 /* update the MMU */ 1038 /* update the MMU */
991 if (HYPERVISOR_multicall(xstart_mcl, i + 1) != 0) { 1039 if (HYPERVISOR_multicall(xstart_mcl, i + 1) != 0) {
992 panic("%s: HYPERVISOR_multicall failed",  1040 panic("%s: HYPERVISOR_multicall failed",
993 ifp->if_xname); 1041 ifp->if_xname);
994 } 1042 }
995 for (j = 0; j < i + 1; j++) { 1043 for (j = 0; j < i + 1; j++) {
996 if (xstart_mcl[j].result != 0) { 1044 if (xstart_mcl[j].result != 0) {
997 printf("%s: xstart_mcl[%d] " 1045 printf("%s: xstart_mcl[%d] "
998 "failed (%lu)\n", ifp->if_xname, 1046 "failed (%lu)\n", ifp->if_xname,
999 j, xstart_mcl[j].result); 1047 j, xstart_mcl[j].result);
1000 printf("%s: req_prod %u req_cons " 1048 printf("%s: req_prod %u req_cons "
1001 "%u rsp_prod %u rsp_prod_pvt %u " 1049 "%u rsp_prod %u rsp_prod_pvt %u "
1002 "i %u\n", 1050 "i %u\n",
1003 ifp->if_xname, 1051 ifp->if_xname,
1004 xneti->xni_rxring.sring->req_prod, 1052 xneti->xni_rxring.sring->req_prod,
1005 xneti->xni_rxring.req_cons, 1053 xneti->xni_rxring.req_cons,
1006 xneti->xni_rxring.sring->rsp_prod, 1054 xneti->xni_rxring.sring->rsp_prod,
1007 xneti->xni_rxring.rsp_prod_pvt, 1055 xneti->xni_rxring.rsp_prod_pvt,
1008 i); 1056 i);
1009 } 1057 }
1010 } 1058 }
1011 if (HYPERVISOR_grant_table_op(GNTTABOP_transfer, 1059 if (HYPERVISOR_grant_table_op(GNTTABOP_transfer,
1012 xstart_gop, i) != 0) { 1060 xstart_gop_transfer, i) != 0) {
1013 panic("%s: GNTTABOP_transfer failed",  1061 panic("%s: GNTTABOP_transfer failed",
1014 ifp->if_xname); 1062 ifp->if_xname);
1015 } 1063 }
1016 1064
1017 for (j = 0; j < i; j++) { 1065 for (j = 0; j < i; j++) {
1018 if (xstart_gop[j].status != 0) { 1066 if (xstart_gop_transfer[j].status != GNTST_okay) {
1019 printf("%s GNTTABOP_transfer[%d] %d\n", 1067 printf("%s GNTTABOP_transfer[%d] %d\n",
1020 ifp->if_xname, 1068 ifp->if_xname,
1021 j, xstart_gop[j].status); 1069 j, xstart_gop_transfer[j].status);
1022 printf("%s: req_prod %u req_cons " 1070 printf("%s: req_prod %u req_cons "
1023 "%u rsp_prod %u rsp_prod_pvt %u " 1071 "%u rsp_prod %u rsp_prod_pvt %u "
1024 "i %d\n", 1072 "i %d\n",
1025 ifp->if_xname, 1073 ifp->if_xname,
1026 xneti->xni_rxring.sring->req_prod, 1074 xneti->xni_rxring.sring->req_prod,
1027 xneti->xni_rxring.req_cons, 1075 xneti->xni_rxring.req_cons,
1028 xneti->xni_rxring.sring->rsp_prod, 1076 xneti->xni_rxring.sring->rsp_prod,
1029 xneti->xni_rxring.rsp_prod_pvt, 1077 xneti->xni_rxring.rsp_prod_pvt,
1030 i); 1078 i);
1031 rxresp = RING_GET_RESPONSE( 1079 rxresp = RING_GET_RESPONSE(
1032 &xneti->xni_rxring, 1080 &xneti->xni_rxring,
1033 xneti->xni_rxring.rsp_prod_pvt + j); 1081 xneti->xni_rxring.rsp_prod_pvt + j);
1034 rxresp->status = NETIF_RSP_ERROR; 1082 rxresp->status = NETIF_RSP_ERROR;
1035 } 1083 }
1036 } 1084 }
1037  1085
1038 /* update pointer */ 1086 /* update pointer */
1039 KASSERT( 1087 KASSERT(
1040 xneti->xni_rxring.rsp_prod_pvt + i == resp_prod); 1088 xneti->xni_rxring.rsp_prod_pvt + i == resp_prod);
1041 xneti->xni_rxring.rsp_prod_pvt = resp_prod; 1089 xneti->xni_rxring.rsp_prod_pvt = resp_prod;
1042 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY( 1090 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
1043 &xneti->xni_rxring, j); 1091 &xneti->xni_rxring, j);
1044 if (j) 1092 if (j)
1045 do_event = 1; 1093 do_event = 1;
1046 /* now we can free the mbufs */ 1094 /* now we can free the mbufs */
1047 for (j = 0; j < i; j++) { 1095 for (j = 0; j < i; j++) {
1048 m_freem(mbufs_sent[j]); 1096 m_freem(mbufs_sent[j]);
1049 } 1097 }
1050 for (j = 0; j < nppitems; j++) { 1098 for (j = 0; j < nppitems; j++) {
1051 pool_cache_put_paddr(xmit_pages_cachep, 1099 pool_cache_put_paddr(xmit_pages_cachep,
1052 (void *)pages_pool_free[j].va, 1100 (void *)pages_pool_free[j].va,
1053 pages_pool_free[j].pa); 1101 pages_pool_free[j].pa);
1054 } 1102 }
1055 } 1103 }
1056 /* send event */ 1104 /* send event */
1057 if (do_event) { 1105 if (do_event) {
1058 x86_lfence(); 1106 x86_lfence();
1059 XENPRINTF(("%s receive event\n", 1107 XENPRINTF(("%s receive event\n",
1060 xneti->xni_if.if_xname)); 1108 xneti->xni_if.if_xname));
1061 hypervisor_notify_via_evtchn(xneti->xni_evtchn); 1109 hypervisor_notify_via_evtchn(xneti->xni_evtchn);
1062 do_event = 0; 1110 do_event = 0;
1063 } 1111 }
1064 /* check if we need to get back some pages */ 1112 /* check if we need to get back some pages */
1065 if (mcl_pages_alloc < 0) { 1113 if (mcl_pages_alloc < 0) {
1066 xennetback_get_new_mcl_pages(); 1114 xennetback_get_new_mcl_pages();
1067 if (mcl_pages_alloc < 0) { 1115 if (mcl_pages_alloc < 0) {
1068 /* 1116 /*
1069 * setup the watchdog to try again, because  1117 * setup the watchdog to try again, because
1070 * xennetback_ifstart() will never be called 1118 * xennetback_ifstart() will never be called
1071 * again if queue is full. 1119 * again if queue is full.
1072 */ 1120 */
1073 printf("xennetback_ifstart: no mcl_pages\n"); 1121 printf("xennetback_ifstart: no mcl_pages\n");
1074 ifp->if_timer = 1; 1122 ifp->if_timer = 1;
1075 break; 1123 break;
1076 } 1124 }
1077 } 1125 }
1078 /* 1126 /*
1079 * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS() 1127 * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS()
1080 * here, as the frontend doesn't notify when adding 1128 * here, as the frontend doesn't notify when adding
1081 * requests anyway 1129 * requests anyway
1082 */ 1130 */
1083 if (__predict_false( 1131 if (__predict_false(
1084 !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) { 1132 !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) {
1085 /* ring full */ 1133 /* ring full */
1086 break; 1134 break;
1087 } 1135 }
1088 } 1136 }
1089 splx(s); 1137 splx(s);
1090} 1138}
1091 1139
 1140static void
 1141xennetback_ifsoftstart_copy(void *arg)
 1142{
 1143 struct xnetback_instance *xneti = arg;
 1144 struct ifnet *ifp = &xneti->xni_if;
 1145 struct mbuf *m, *new_m;
 1146 paddr_t xmit_pa;
 1147 paddr_t xmit_ma;
 1148 int i, j;
 1149 netif_rx_response_t *rxresp;
 1150 RING_IDX req_prod, resp_prod;
 1151 int do_event = 0;
 1152 gnttab_copy_t *gop;
 1153 int id, offset;
 1154
 1155 XENPRINTF(("xennetback_ifsoftstart_transfer "));
 1156 int s = splnet();
 1157 if (__predict_false(
 1158 (ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)) {
 1159 splx(s);
 1160 return;
 1161 }
 1162
 1163 while (!IFQ_IS_EMPTY(&ifp->if_snd)) {
 1164 XENPRINTF(("pkt\n"));
 1165 req_prod = xneti->xni_rxring.sring->req_prod;
 1166 resp_prod = xneti->xni_rxring.rsp_prod_pvt;
 1167 xen_rmb();
 1168
 1169 gop = xstart_gop_copy;
 1170 for (i = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) {
 1171 XENPRINTF(("have a packet\n"));
 1172 IFQ_POLL(&ifp->if_snd, m);
 1173 if (__predict_false(m == NULL))
 1174 panic("xennetback_ifstart: IFQ_POLL");
 1175 if (__predict_false(
 1176 req_prod == xneti->xni_rxring.req_cons ||
 1177 xneti->xni_rxring.req_cons - resp_prod ==
 1178 NET_RX_RING_SIZE)) {
 1179 /* out of ring space */
 1180 XENPRINTF(("xennetback_ifstart: ring full "
 1181 "req_prod 0x%x req_cons 0x%x resp_prod "
 1182 "0x%x\n",
 1183 req_prod, xneti->xni_rxring.req_cons,
 1184 resp_prod));
 1185 ifp->if_timer = 1;
 1186 break;
 1187 }
 1188 if (__predict_false(i == NB_XMIT_PAGES_BATCH))
 1189 break; /* we filled the array */
 1190 switch (m->m_flags & (M_EXT|M_EXT_CLUSTER)) {
 1191 case M_EXT|M_EXT_CLUSTER:
 1192 KASSERT(m->m_ext.ext_paddr != M_PADDR_INVALID);
 1193 xmit_pa = m->m_ext.ext_paddr;
 1194 offset = m->m_data - m->m_ext.ext_buf;
 1195 break;
 1196 case 0:
 1197 KASSERT(m->m_paddr != M_PADDR_INVALID);
 1198 xmit_pa = m->m_paddr;
 1199 offset = M_BUFOFFSET(m) +
 1200 (m->m_data - M_BUFADDR(m));
 1201 break;
 1202 default:
 1203 if (__predict_false(
 1204 !pmap_extract(pmap_kernel(),
 1205 (vaddr_t)m->m_data, &xmit_pa))) {
 1206 panic("xennet_start: no pa");
 1207 }
 1208 offset = 0;
 1209 break;
 1210 }
 1211 offset += (xmit_pa & ~PG_FRAME);
 1212 xmit_pa = (xmit_pa & PG_FRAME);
 1213 if (m->m_pkthdr.len != m->m_len ||
 1214 (offset + m->m_pkthdr.len) > PAGE_SIZE) {
 1215 MGETHDR(new_m, M_DONTWAIT, MT_DATA);
 1216 if (__predict_false(new_m == NULL)) {
 1217 printf("%s: cannot allocate new mbuf\n",
 1218 ifp->if_xname);
 1219 break;
 1220 }
 1221 if (m->m_pkthdr.len > MHLEN) {
 1222 MCLGET(new_m, M_DONTWAIT);
 1223 if (__predict_false(
 1224 (new_m->m_flags & M_EXT) == 0)) {
 1225 XENPRINTF((
 1226 "%s: no mbuf cluster\n",
 1227 ifp->if_xname));
 1228 m_freem(new_m);
 1229 break;
 1230 }
 1231 xmit_pa = new_m->m_ext.ext_paddr;
 1232 offset = new_m->m_data -
 1233 new_m->m_ext.ext_buf;
 1234 } else {
 1235 xmit_pa = new_m->m_paddr;
 1236 offset = M_BUFOFFSET(new_m) +
 1237 (new_m->m_data - M_BUFADDR(new_m));
 1238 }
 1239 offset += (xmit_pa & ~PG_FRAME);
 1240 xmit_pa = (xmit_pa & PG_FRAME);
 1241 m_copydata(m, 0, m->m_pkthdr.len,
 1242 mtod(new_m, void *));
 1243 new_m->m_len = new_m->m_pkthdr.len =
 1244 m->m_pkthdr.len;
 1245 IFQ_DEQUEUE(&ifp->if_snd, m);
 1246 m_freem(m);
 1247 m = new_m;
 1248 } else {
 1249 IFQ_DEQUEUE(&ifp->if_snd, m);
 1250 }
 1251
 1252 KASSERT(xmit_pa != POOL_PADDR_INVALID);
 1253 KASSERT((offset + m->m_pkthdr.len) <= PAGE_SIZE);
 1254 xmit_ma = xpmap_ptom(xmit_pa);
 1255 /* start filling ring */
 1256 gop->flags = GNTCOPY_dest_gref;
 1257 gop->source.offset = offset;
 1258 gop->source.domid = DOMID_SELF;
 1259 gop->source.u.gmfn = xmit_ma >> PAGE_SHIFT;
 1260
 1261 gop->dest.u.ref = RING_GET_REQUEST(&xneti->xni_rxring,
 1262 xneti->xni_rxring.req_cons)->gref;
 1263 gop->dest.offset = 0;
 1264 gop->dest.domid = xneti->xni_domid;
 1265
 1266 gop->len = m->m_pkthdr.len;
 1267 gop++;
 1268
 1269 id = RING_GET_REQUEST(&xneti->xni_rxring,
 1270 xneti->xni_rxring.req_cons)->id;
 1271 xen_rmb();
 1272 xneti->xni_rxring.req_cons++;
 1273 rxresp = RING_GET_RESPONSE(&xneti->xni_rxring,
 1274 resp_prod);
 1275 rxresp->id = id;
 1276 rxresp->offset = 0;
 1277 rxresp->status = m->m_pkthdr.len;
 1278 if ((m->m_pkthdr.csum_flags &
 1279 (M_CSUM_TCPv4 | M_CSUM_UDPv4)) != 0) {
 1280 rxresp->flags = NETRXF_csum_blank;
 1281 } else {
 1282 rxresp->flags = 0;
 1283 }
 1284
 1285 mbufs_sent[i] = m;
 1286 resp_prod++;
 1287 i++; /* this packet has been queued */
 1288 ifp->if_opackets++;
 1289#if NBPFILTER > 0
 1290 if (ifp->if_bpf)
 1291 bpf_mtap(ifp->if_bpf, m);
 1292#endif
 1293 }
 1294 if (i != 0) {
 1295 if (HYPERVISOR_grant_table_op(GNTTABOP_copy,
 1296 xstart_gop_copy, i) != 0) {
 1297 panic("%s: GNTTABOP_copy failed",
 1298 ifp->if_xname);
 1299 }
 1300
 1301 for (j = 0; j < i; j++) {
 1302 if (xstart_gop_copy[j].status != GNTST_okay) {
 1303 printf("%s GNTTABOP_copy[%d] %d\n",
 1304 ifp->if_xname,
 1305 j, xstart_gop_copy[j].status);
 1306 printf("%s: req_prod %u req_cons "
 1307 "%u rsp_prod %u rsp_prod_pvt %u "
 1308 "i %d\n",
 1309 ifp->if_xname,
 1310 xneti->xni_rxring.sring->req_prod,
 1311 xneti->xni_rxring.req_cons,
 1312 xneti->xni_rxring.sring->rsp_prod,
 1313 xneti->xni_rxring.rsp_prod_pvt,
 1314 i);
 1315 rxresp = RING_GET_RESPONSE(
 1316 &xneti->xni_rxring,
 1317 xneti->xni_rxring.rsp_prod_pvt + j);
 1318 rxresp->status = NETIF_RSP_ERROR;
 1319 }
 1320 }
 1321
 1322 /* update pointer */
 1323 KASSERT(
 1324 xneti->xni_rxring.rsp_prod_pvt + i == resp_prod);
 1325 xneti->xni_rxring.rsp_prod_pvt = resp_prod;
 1326 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(
 1327 &xneti->xni_rxring, j);
 1328 if (j)
 1329 do_event = 1;
 1330 /* now we can free the mbufs */
 1331 for (j = 0; j < i; j++) {
 1332 m_freem(mbufs_sent[j]);
 1333 }
 1334 }
 1335 /* send event */
 1336 if (do_event) {
 1337 xen_rmb();
 1338 XENPRINTF(("%s receive event\n",
 1339 xneti->xni_if.if_xname));
 1340 hypervisor_notify_via_evtchn(xneti->xni_evtchn);
 1341 do_event = 0;
 1342 }
 1343 /*
 1344 * note that we don't use RING_FINAL_CHECK_FOR_REQUESTS()
 1345 * here, as the frontend doesn't notify when adding
 1346 * requests anyway
 1347 */
 1348 if (__predict_false(
 1349 !RING_HAS_UNCONSUMED_REQUESTS(&xneti->xni_rxring))) {
 1350 /* ring full */
 1351 break;
 1352 }
 1353 }
 1354 splx(s);
 1355}
 1356
1092 1357
1093static void 1358static void
1094xennetback_ifwatchdog(struct ifnet * ifp) 1359xennetback_ifwatchdog(struct ifnet * ifp)
1095{ 1360{
1096 /* 1361 /*
1097 * We can get to the following condition:  1362 * We can get to the following condition:
1098 * transmit stalls because the ring is full when the ifq is full too. 1363 * transmit stalls because the ring is full when the ifq is full too.
1099 * In this case (as, unfortunably, we don't get an interrupt from xen 1364 * In this case (as, unfortunably, we don't get an interrupt from xen
1100 * on transmit) noting will ever call xennetback_ifstart() again. 1365 * on transmit) noting will ever call xennetback_ifstart() again.
1101 * Here we abuse the watchdog to get out of this condition. 1366 * Here we abuse the watchdog to get out of this condition.
1102 */ 1367 */
1103 XENPRINTF(("xennetback_ifwatchdog\n")); 1368 XENPRINTF(("xennetback_ifwatchdog\n"));
1104 xennetback_ifstart(ifp); 1369 xennetback_ifstart(ifp);
1105} 1370}
1106 1371
1107 1372
1108static int 1373static int
1109xennetback_ifinit(struct ifnet *ifp) 1374xennetback_ifinit(struct ifnet *ifp)
1110{ 1375{
1111 struct xnetback_instance *xneti = ifp->if_softc; 1376 struct xnetback_instance *xneti = ifp->if_softc;
1112 int s = splnet(); 1377 int s = splnet();
1113 1378
1114 if ((ifp->if_flags & IFF_UP) == 0) { 1379 if ((ifp->if_flags & IFF_UP) == 0) {
1115 splx(s); 1380 splx(s);
1116 return 0; 1381 return 0;
1117 } 1382 }
1118 if (xneti->xni_status == CONNECTED) 1383 if (xneti->xni_status == CONNECTED)
1119 ifp->if_flags |= IFF_RUNNING; 1384 ifp->if_flags |= IFF_RUNNING;
1120 splx(s); 1385 splx(s);
1121 return 0; 1386 return 0;
1122} 1387}
1123 1388
1124static void 1389static void
1125xennetback_ifstop(struct ifnet *ifp, int disable) 1390xennetback_ifstop(struct ifnet *ifp, int disable)
1126{ 1391{
1127 struct xnetback_instance *xneti = ifp->if_softc; 1392 struct xnetback_instance *xneti = ifp->if_softc;
1128 int s = splnet(); 1393 int s = splnet();
1129 1394
1130 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 1395 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1131 ifp->if_timer = 0; 1396 ifp->if_timer = 0;
1132 if (xneti->xni_status == CONNECTED) { 1397 if (xneti->xni_status == CONNECTED) {
1133 XENPRINTF(("%s: req_prod 0x%x resp_prod 0x%x req_cons 0x%x " 1398 XENPRINTF(("%s: req_prod 0x%x resp_prod 0x%x req_cons 0x%x "
1134 "event 0x%x\n", ifp->if_xname, xneti->xni_txring->req_prod, 1399 "event 0x%x\n", ifp->if_xname, xneti->xni_txring->req_prod,
1135 xneti->xni_txring->resp_prod, xneti->xni_txring->req_cons, 1400 xneti->xni_txring->resp_prod, xneti->xni_txring->req_cons,
1136 xneti->xni_txring->event)); 1401 xneti->xni_txring->event));
1137 xennetback_evthandler(ifp->if_softc); /* flush pending RX requests */ 1402 xennetback_evthandler(ifp->if_softc); /* flush pending RX requests */
1138 } 1403 }
1139 splx(s); 1404 splx(s);
1140} 1405}