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 (expand / 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,14 +1,14 @@ @@ -1,14 +1,14 @@
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
@@ -121,27 +121,28 @@ struct xnetback_instance { @@ -121,27 +121,28 @@ struct xnetback_instance {
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;
@@ -172,27 +173,28 @@ static void xennetback_get_new_mcl_pages @@ -172,27 +173,28 @@ static void xennetback_get_new_mcl_pages
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}
@@ -234,26 +236,27 @@ xvifattach(int n) @@ -234,26 +236,27 @@ xvifattach(int n)
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 }
@@ -264,33 +267,26 @@ xennetback_xenbus_create(struct xenbus_d @@ -264,33 +267,26 @@ xennetback_xenbus_create(struct xenbus_d
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",
@@ -318,38 +314,67 @@ xennetback_xenbus_create(struct xenbus_d @@ -318,38 +314,67 @@ xennetback_xenbus_create(struct xenbus_d
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
@@ -397,27 +422,27 @@ xennetback_xenbus_destroy(void *arg) @@ -397,27 +422,27 @@ xennetback_xenbus_destroy(void *arg)
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",
@@ -428,26 +453,49 @@ xennetback_frontend_changed(void *arg, X @@ -428,26 +453,49 @@ xennetback_frontend_changed(void *arg, X
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,
@@ -820,67 +868,67 @@ xennetback_ifioctl(struct ifnet *ifp, u_ @@ -820,67 +868,67 @@ xennetback_ifioctl(struct ifnet *ifp, u_
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",
@@ -999,36 +1047,36 @@ xennetback_ifsoftstart(void *arg) @@ -999,36 +1047,36 @@ xennetback_ifsoftstart(void *arg)
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;
@@ -1079,26 +1127,243 @@ xennetback_ifsoftstart(void *arg) @@ -1079,26 +1127,243 @@ xennetback_ifsoftstart(void *arg)
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);