Wed Apr 20 20:32:38 2011 UTC ()
Unmap rings before freeing their associated VAs, or we will get a
non-recoverable fault in the error path.


(jym)
diff -r1.40 -r1.41 src/sys/arch/xen/xen/xennetback_xenbus.c

cvs diff -r1.40 -r1.41 src/sys/arch/xen/xen/xennetback_xenbus.c (expand / switch to unified diff)

--- src/sys/arch/xen/xen/xennetback_xenbus.c 2011/04/06 23:51:55 1.40
+++ src/sys/arch/xen/xen/xennetback_xenbus.c 2011/04/20 20:32:38 1.41
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: xennetback_xenbus.c,v 1.40 2011/04/06 23:51:55 jym Exp $ */ 1/* $NetBSD: xennetback_xenbus.c,v 1.41 2011/04/20 20:32:38 jym 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 * 14 *
@@ -423,26 +423,27 @@ xennetback_xenbus_destroy(void *arg) @@ -423,26 +423,27 @@ xennetback_xenbus_destroy(void *arg)
423 free(xneti, M_DEVBUF); 423 free(xneti, M_DEVBUF);
424 return 0; 424 return 0;
425} 425}
426 426
427static void 427static void
428xennetback_frontend_changed(void *arg, XenbusState new_state) 428xennetback_frontend_changed(void *arg, XenbusState new_state)
429{ 429{
430 struct xnetback_instance *xneti = arg; 430 struct xnetback_instance *xneti = arg;
431 struct xenbus_device *xbusd = xneti->xni_xbusd; 431 struct xenbus_device *xbusd = xneti->xni_xbusd;
432 int err; 432 int err;
433 netif_tx_sring_t *tx_ring; 433 netif_tx_sring_t *tx_ring;
434 netif_rx_sring_t *rx_ring; 434 netif_rx_sring_t *rx_ring;
435 struct gnttab_map_grant_ref op; 435 struct gnttab_map_grant_ref op;
 436 struct gnttab_unmap_grant_ref uop;
436 evtchn_op_t evop; 437 evtchn_op_t evop;
437 u_long tx_ring_ref, rx_ring_ref; 438 u_long tx_ring_ref, rx_ring_ref;
438 u_long revtchn, rx_copy; 439 u_long revtchn, rx_copy;
439 440
440 XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state)); 441 XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state));
441 switch(new_state) { 442 switch(new_state) {
442 case XenbusStateInitialising: 443 case XenbusStateInitialising:
443 case XenbusStateInitialised: 444 case XenbusStateInitialised:
444 break; 445 break;
445 446
446 case XenbusStateConnected: 447 case XenbusStateConnected:
447 /* read comunication informations */ 448 /* read comunication informations */
448 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 449 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
@@ -528,27 +529,27 @@ xennetback_frontend_changed(void *arg, X @@ -528,27 +529,27 @@ xennetback_frontend_changed(void *arg, X
528 xneti->xni_if.if_xname, err, op.status); 529 xneti->xni_if.if_xname, err, op.status);
529 goto err2; 530 goto err2;
530 } 531 }
531 xneti->xni_rx_ring_handle = op.handle; 532 xneti->xni_rx_ring_handle = op.handle;
532 BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE); 533 BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE);
533 BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE); 534 BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE);
534 evop.cmd = EVTCHNOP_bind_interdomain; 535 evop.cmd = EVTCHNOP_bind_interdomain;
535 evop.u.bind_interdomain.remote_dom = xneti->xni_domid; 536 evop.u.bind_interdomain.remote_dom = xneti->xni_domid;
536 evop.u.bind_interdomain.remote_port = revtchn; 537 evop.u.bind_interdomain.remote_port = revtchn;
537 err = HYPERVISOR_event_channel_op(&evop); 538 err = HYPERVISOR_event_channel_op(&evop);
538 if (err) { 539 if (err) {
539 printf("%s: can't get event channel: %d\n", 540 printf("%s: can't get event channel: %d\n",
540 xneti->xni_if.if_xname, err); 541 xneti->xni_if.if_xname, err);
541 goto err2; 542 goto err3;
542 } 543 }
543 xneti->xni_evtchn = evop.u.bind_interdomain.local_port; 544 xneti->xni_evtchn = evop.u.bind_interdomain.local_port;
544 xen_wmb(); 545 xen_wmb();
545 xneti->xni_status = CONNECTED; 546 xneti->xni_status = CONNECTED;
546 xenbus_switch_state(xbusd, NULL, XenbusStateConnected); 547 xenbus_switch_state(xbusd, NULL, XenbusStateConnected);
547 xen_wmb(); 548 xen_wmb();
548 event_set_handler(xneti->xni_evtchn, xennetback_evthandler, 549 event_set_handler(xneti->xni_evtchn, xennetback_evthandler,
549 xneti, IPL_NET, xneti->xni_if.if_xname); 550 xneti, IPL_NET, xneti->xni_if.if_xname);
550 xennetback_ifinit(&xneti->xni_if); 551 xennetback_ifinit(&xneti->xni_if);
551 hypervisor_enable_event(xneti->xni_evtchn); 552 hypervisor_enable_event(xneti->xni_evtchn);
552 hypervisor_notify_via_evtchn(xneti->xni_evtchn); 553 hypervisor_notify_via_evtchn(xneti->xni_evtchn);
553 break; 554 break;
554 555
@@ -560,26 +561,46 @@ xennetback_frontend_changed(void *arg, X @@ -560,26 +561,46 @@ xennetback_frontend_changed(void *arg, X
560 break; 561 break;
561 562
562 case XenbusStateClosed: 563 case XenbusStateClosed:
563 /* otherend_changed() should handle it for us */ 564 /* otherend_changed() should handle it for us */
564 panic("xennetback_frontend_changed: closed\n"); 565 panic("xennetback_frontend_changed: closed\n");
565 case XenbusStateUnknown: 566 case XenbusStateUnknown:
566 case XenbusStateInitWait: 567 case XenbusStateInitWait:
567 default: 568 default:
568 aprint_error("%s: invalid frontend state %d\n", 569 aprint_error("%s: invalid frontend state %d\n",
569 xneti->xni_if.if_xname, new_state); 570 xneti->xni_if.if_xname, new_state);
570 break; 571 break;
571 } 572 }
572 return; 573 return;
 574
 575err3:
 576 uop.dev_bus_addr = 0;
 577
 578 uop.host_addr = xneti->xni_rx_ring_va;
 579 uop.handle = xneti->xni_rx_ring_handle;
 580 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
 581 &uop, 1);
 582 if (err)
 583 aprint_error_ifnet(&xneti->xni_if,
 584 "unmap_grant_ref failed: %d\n", err);
 585
 586 uop.host_addr = xneti->xni_tx_ring_va;
 587 uop.handle = xneti->xni_tx_ring_handle;
 588 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
 589 &uop, 1);
 590 if (err)
 591 aprint_error_ifnet(&xneti->xni_if,
 592 "unmap_grant_ref failed: %d\n", err);
 593
573err2: 594err2:
574 uvm_km_free(kernel_map, xneti->xni_rx_ring_va, 595 uvm_km_free(kernel_map, xneti->xni_rx_ring_va,
575 PAGE_SIZE, UVM_KMF_VAONLY); 596 PAGE_SIZE, UVM_KMF_VAONLY);
576err1: 597err1:
577 uvm_km_free(kernel_map, xneti->xni_tx_ring_va, 598 uvm_km_free(kernel_map, xneti->xni_tx_ring_va,
578 PAGE_SIZE, UVM_KMF_VAONLY); 599 PAGE_SIZE, UVM_KMF_VAONLY);
579} 600}
580 601
581/* lookup a xneti based on domain id and interface handle */ 602/* lookup a xneti based on domain id and interface handle */
582static struct xnetback_instance * 603static struct xnetback_instance *
583xnetif_lookup(domid_t dom , uint32_t handle) 604xnetif_lookup(domid_t dom , uint32_t handle)
584{ 605{
585 struct xnetback_instance *xneti; 606 struct xnetback_instance *xneti;