Sun Sep 27 19:48:57 2009 UTC ()
Don't disestablish a soft interrupt which has not been established.


(bouyer)
diff -r1.29 -r1.30 src/sys/arch/xen/xen/xennetback_xenbus.c

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

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