[BACK]Return to xennetback_xenbus.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / xen / xen

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/arch/xen/xen/xennetback_xenbus.c between version 1.33.4.4 and 1.34

version 1.33.4.4, 2011/05/31 03:04:25 version 1.34, 2010/04/05 07:19:32
Line 25 
Line 25 
  *   *
  */   */
   
 #include <sys/cdefs.h>  
 __KERNEL_RCSID(0, "$NetBSD$");  
   
 #include "opt_xen.h"  #include "opt_xen.h"
   
 #include <sys/types.h>  #include <sys/types.h>
Line 245  xennetback_xenbus_create(struct xenbus_d
Line 242  xennetback_xenbus_create(struct xenbus_d
   
         if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,          if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,
             "frontend-id", &domid, 10)) != 0) {              "frontend-id", &domid, 10)) != 0) {
                 aprint_error("xvif: can't read %s/frontend-id: %d\n",                  aprint_error("xvif: can' read %s/frontend-id: %d\n",
                     xbusd->xbusd_path, err);                      xbusd->xbusd_path, err);
                 return err;                  return err;
         }          }
         if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,          if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path,
             "handle", &handle, 10)) != 0) {              "handle", &handle, 10)) != 0) {
                 aprint_error("xvif: can't read %s/handle: %d\n",                  aprint_error("xvif: can' read %s/handle: %d\n",
                     xbusd->xbusd_path, err);                      xbusd->xbusd_path, err);
                 return err;                  return err;
         }          }
Line 274  xennetback_xenbus_create(struct xenbus_d
Line 271  xennetback_xenbus_create(struct xenbus_d
   
         ifp = &xneti->xni_if;          ifp = &xneti->xni_if;
         ifp->if_softc = xneti;          ifp->if_softc = xneti;
         snprintf(ifp->if_xname, IFNAMSIZ, "xvif%di%d",  
             (int)domid, (int)handle);  
   
         /* read mac address */          /* read mac address */
         if ((err = xenbus_read(NULL, xbusd->xbusd_path, "mac", NULL, &val))) {          if ((err = xenbus_read(NULL, xbusd->xbusd_path, "mac", NULL, &val))) {
                 aprint_error_ifnet(ifp, "can't read %s/mac: %d\n",                  aprint_error("xvif: can' read %s/mac: %d\n",
                     xbusd->xbusd_path, err);                      xbusd->xbusd_path, err);
                 goto fail;                  goto fail;
         }          }
         for (i = 0, p = val; i < 6; i++) {          for (i = 0, p = val; i < 6; i++) {
                 xneti->xni_enaddr[i] = strtoul(p, &e, 16);                  xneti->xni_enaddr[i] = strtoul(p, &e, 16);
                 if ((e[0] == '\0' && i != 5) && e[0] != ':') {                  if ((e[0] == '\0' && i != 5) && e[0] != ':') {
                         aprint_error_ifnet(ifp,                          aprint_error("xvif: %s is not a valid mac address\n",
                             "%s is not a valid mac address\n", val);                              val);
                         err = EINVAL;                          err = EINVAL;
                         goto fail;                          goto fail;
                 }                  }
Line 298  xennetback_xenbus_create(struct xenbus_d
Line 293  xennetback_xenbus_create(struct xenbus_d
         /* we can't use the same MAC addr as our guest */          /* we can't use the same MAC addr as our guest */
         xneti->xni_enaddr[3]++;          xneti->xni_enaddr[3]++;
         /* create pseudo-interface */          /* create pseudo-interface */
           snprintf(xneti->xni_if.if_xname, IFNAMSIZ, "xvif%d.%d",
               (int)domid, (int)handle);
         aprint_verbose_ifnet(ifp, "Ethernet address %s\n",          aprint_verbose_ifnet(ifp, "Ethernet address %s\n",
             ether_sprintf(xneti->xni_enaddr));              ether_sprintf(xneti->xni_enaddr));
         ifp->if_flags =          ifp->if_flags =
Line 322  xennetback_xenbus_create(struct xenbus_d
Line 319  xennetback_xenbus_create(struct xenbus_d
         do {          do {
                 xbt = xenbus_transaction_start();                  xbt = xenbus_transaction_start();
                 if (xbt == NULL) {                  if (xbt == NULL) {
                         aprint_error_ifnet(ifp,                          printf("xbdback %s: can't start transaction\n",
                             "%s: can't start transaction\n",  
                             xbusd->xbusd_path);                              xbusd->xbusd_path);
                         goto fail;                          goto fail;
                 }                  }
                 err = xenbus_printf(xbt, xbusd->xbusd_path,                  err = xenbus_printf(xbt, xbusd->xbusd_path,
                     "vifname", "%s", ifp->if_xname);  
                 if (err) {  
                         aprint_error_ifnet(ifp,  
                             "failed to write %s/vifname: %d\n",  
                             xbusd->xbusd_path, err);  
                         goto abort_xbt;  
                 }  
                 err = xenbus_printf(xbt, xbusd->xbusd_path,  
                     "feature-rx-copy", "%d", 1);                      "feature-rx-copy", "%d", 1);
                 if (err) {                  if (err) {
                         aprint_error_ifnet(ifp,                          printf("xbdback: failed to write %s/feature-rx-copy: "
                             "failed to write %s/feature-rx-copy: %d\n",                              "%d\n", xbusd->xbusd_path, err);
                             xbusd->xbusd_path, err);  
                         goto abort_xbt;                          goto abort_xbt;
                 }                  }
                 err = xenbus_printf(xbt, xbusd->xbusd_path,                  err = xenbus_printf(xbt, xbusd->xbusd_path,
                     "feature-rx-flip", "%d", 1);                      "feature-rx-flip", "%d", 1);
                 if (err) {                  if (err) {
                         aprint_error_ifnet(ifp,                          printf("xbdback: failed to write %s/feature-rx-flip: "
                             "failed to write %s/feature-rx-flip: %d\n",                              "%d\n", xbusd->xbusd_path, err);
                             xbusd->xbusd_path, err);  
                         goto abort_xbt;                          goto abort_xbt;
                 }                  }
         } while ((err = xenbus_transaction_end(xbt, 0)) == EAGAIN);          } while ((err = xenbus_transaction_end(xbt, 0)) == EAGAIN);
         if (err) {          if (err) {
                 aprint_error_ifnet(ifp,                  printf("xbdback %s: can't end transaction: %d\n",
                     "%s: can't end transaction: %d\n",  
                     xbusd->xbusd_path, err);                      xbusd->xbusd_path, err);
         }          }
   
         err = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait);          err = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait);
         if (err) {          if (err) {
                 aprint_error_ifnet(ifp,                  printf("failed to switch state on %s: %d\n",
                     "failed to switch state on %s: %d\n",  
                     xbusd->xbusd_path, err);                      xbusd->xbusd_path, err);
                 goto fail;                  goto fail;
         }          }
Line 427  xennetback_xenbus_destroy(void *arg)
Line 411  xennetback_xenbus_destroy(void *arg)
         return 0;          return 0;
 }  }
   
 static int  static void
 xennetback_connect(struct xnetback_instance *xneti)  xennetback_frontend_changed(void *arg, XenbusState new_state)
 {  {
           struct xnetback_instance *xneti = arg;
           struct xenbus_device *xbusd = xneti->xni_xbusd;
         int err;          int err;
         netif_tx_sring_t *tx_ring;          netif_tx_sring_t *tx_ring;
         netif_rx_sring_t *rx_ring;          netif_rx_sring_t *rx_ring;
         struct gnttab_map_grant_ref op;          struct gnttab_map_grant_ref op;
         struct gnttab_unmap_grant_ref uop;  
         evtchn_op_t evop;          evtchn_op_t evop;
         u_long tx_ring_ref, rx_ring_ref;          u_long tx_ring_ref, rx_ring_ref;
         u_long revtchn, rx_copy;          u_long revtchn, rx_copy;
         struct xenbus_device *xbusd = xneti->xni_xbusd;  
   
         /* read comunication informations */  
         err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,  
             "tx-ring-ref", &tx_ring_ref, 10);  
         if (err) {  
                 xenbus_dev_fatal(xbusd, err, "reading %s/tx-ring-ref",  
                     xbusd->xbusd_otherend);  
                 return -1;  
         }  
         err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,  
             "rx-ring-ref", &rx_ring_ref, 10);  
         if (err) {  
                 xenbus_dev_fatal(xbusd, err, "reading %s/rx-ring-ref",  
                     xbusd->xbusd_otherend);  
                 return -1;  
         }  
         err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,  
             "event-channel", &revtchn, 10);  
         if (err) {  
                 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel",  
                     xbusd->xbusd_otherend);  
                 return -1;  
         }  
         err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,  
             "request-rx-copy", &rx_copy, 10);  
         if (err == ENOENT)  
                 rx_copy = 0;  
         else if (err) {  
                 xenbus_dev_fatal(xbusd, err, "reading %s/request-rx-copy",  
                     xbusd->xbusd_otherend);  
                 return -1;  
         }  
   
         if (rx_copy)  
                 xneti->xni_softintr = softint_establish(SOFTINT_NET,  
                     xennetback_ifsoftstart_copy, xneti);  
         else  
                 xneti->xni_softintr = softint_establish(SOFTINT_NET,  
                     xennetback_ifsoftstart_transfer, xneti);  
   
         if (xneti->xni_softintr == NULL) {  
                 err = ENOMEM;  
                 xenbus_dev_fatal(xbusd, ENOMEM,  
                     "can't allocate softint", xbusd->xbusd_otherend);  
                 return -1;  
         }  
   
         /* allocate VA space and map rings */  
         xneti->xni_tx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,  
             UVM_KMF_VAONLY);  
         if (xneti->xni_tx_ring_va == 0) {  
                 xenbus_dev_fatal(xbusd, ENOMEM,  
                     "can't get VA for TX ring", xbusd->xbusd_otherend);  
                 goto err1;  
         }  
         tx_ring = (void *)xneti->xni_tx_ring_va;  
   
         xneti->xni_rx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,  
             UVM_KMF_VAONLY);  
         if (xneti->xni_rx_ring_va == 0) {  
                 xenbus_dev_fatal(xbusd, ENOMEM,  
                     "can't get VA for RX ring", xbusd->xbusd_otherend);  
                 goto err1;  
         }  
         rx_ring = (void *)xneti->xni_rx_ring_va;  
   
         op.host_addr = xneti->xni_tx_ring_va;  
         op.flags = GNTMAP_host_map;  
         op.ref = tx_ring_ref;  
         op.dom = xneti->xni_domid;  
         err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);  
         if (err || op.status) {  
                 aprint_error_ifnet(&xneti->xni_if,  
                     "can't map TX grant ref: err %d status %d\n",  
                     err, op.status);  
                 goto err2;  
         }  
         xneti->xni_tx_ring_handle = op.handle;  
         BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE);  
   
         op.host_addr = xneti->xni_rx_ring_va;  
         op.flags = GNTMAP_host_map;  
         op.ref = rx_ring_ref;  
         op.dom = xneti->xni_domid;  
         err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);  
         if (err || op.status) {  
                 aprint_error_ifnet(&xneti->xni_if,  
                     "can't map RX grant ref: err %d status %d\n",  
                     err, op.status);  
                 goto err2;  
         }  
         xneti->xni_rx_ring_handle = op.handle;  
         BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE);  
   
         evop.cmd = EVTCHNOP_bind_interdomain;  
         evop.u.bind_interdomain.remote_dom = xneti->xni_domid;  
         evop.u.bind_interdomain.remote_port = revtchn;  
         err = HYPERVISOR_event_channel_op(&evop);  
         if (err) {  
                 aprint_error_ifnet(&xneti->xni_if,  
                     "can't get event channel: %d\n", err);  
                 goto err2;  
         }  
         xneti->xni_evtchn = evop.u.bind_interdomain.local_port;  
         xen_wmb();  
         xneti->xni_status = CONNECTED;  
         xen_wmb();  
   
         event_set_handler(xneti->xni_evtchn, xennetback_evthandler,  
             xneti, IPL_NET, xneti->xni_if.if_xname);  
         xennetback_ifinit(&xneti->xni_if);  
         hypervisor_enable_event(xneti->xni_evtchn);  
         hypervisor_notify_via_evtchn(xneti->xni_evtchn);  
         return 0;  
   
 err2:  
         /* unmap rings */  
         if (xneti->xni_tx_ring_handle != 0) {  
                 uop.host_addr = xneti->xni_tx_ring_va;  
                 uop.handle = xneti->xni_tx_ring_handle;  
                 uop.dev_bus_addr = 0;  
                 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,  
                     &uop, 1);  
                 if (err)  
                         aprint_error_ifnet(&xneti->xni_if,  
                             "unmap_grant_ref failed: %d\n", err);  
         }  
   
         if (xneti->xni_rx_ring_handle != 0) {  
                 uop.host_addr = xneti->xni_rx_ring_va;  
                 uop.handle = xneti->xni_rx_ring_handle;  
                 uop.dev_bus_addr = 0;  
                 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,  
                     &uop, 1);  
                 if (err)  
                         aprint_error_ifnet(&xneti->xni_if,  
                             "unmap_grant_ref failed: %d\n", err);  
         }  
   
 err1:  
         /* free rings VA space */  
         if (xneti->xni_rx_ring_va != 0)  
                 uvm_km_free(kernel_map, xneti->xni_rx_ring_va,  
                     PAGE_SIZE, UVM_KMF_VAONLY);  
   
         if (xneti->xni_tx_ring_va != 0)  
                 uvm_km_free(kernel_map, xneti->xni_tx_ring_va,  
                     PAGE_SIZE, UVM_KMF_VAONLY);  
   
         softint_disestablish(xneti->xni_softintr);  
         return -1;  
   
 }  
   
 static void  
 xennetback_frontend_changed(void *arg, XenbusState new_state)  
 {  
         struct xnetback_instance *xneti = arg;  
         struct xenbus_device *xbusd = xneti->xni_xbusd;  
   
         XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state));          XENPRINTF(("%s: new state %d\n", xneti->xni_if.if_xname, new_state));
         switch(new_state) {          switch(new_state) {
Line 606  xennetback_frontend_changed(void *arg, X
Line 431  xennetback_frontend_changed(void *arg, X
                 break;                  break;
   
         case XenbusStateConnected:          case XenbusStateConnected:
                 if (xneti->xni_status == CONNECTED)                  /* read comunication informations */
                   err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
                       "tx-ring-ref", &tx_ring_ref, 10);
                   if (err) {
                           xenbus_dev_fatal(xbusd, err, "reading %s/tx-ring-ref",
                               xbusd->xbusd_otherend);
                           break;
                   }
                   err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
                       "rx-ring-ref", &rx_ring_ref, 10);
                   if (err) {
                           xenbus_dev_fatal(xbusd, err, "reading %s/rx-ring-ref",
                               xbusd->xbusd_otherend);
                           break;
                   }
                   err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
                       "event-channel", &revtchn, 10);
                   if (err) {
                           xenbus_dev_fatal(xbusd, err, "reading %s/event-channel",
                               xbusd->xbusd_otherend);
                           break;
                   }
                   err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
                       "request-rx-copy", &rx_copy, 10);
                   if (err == ENOENT)
                           rx_copy = 0;
                   else if (err) {
                           xenbus_dev_fatal(xbusd, err, "reading %s/request-rx-copy",
                               xbusd->xbusd_otherend);
                           break;
                   }
   
                   if (rx_copy)
                           xneti->xni_softintr = softint_establish(SOFTINT_NET,
                               xennetback_ifsoftstart_copy, xneti);
                   else
                           xneti->xni_softintr = softint_establish(SOFTINT_NET,
                               xennetback_ifsoftstart_transfer, xneti);
                   if (xneti->xni_softintr == NULL) {
                           err = ENOMEM;
                           xenbus_dev_fatal(xbusd, ENOMEM,
                               "can't allocate softint", xbusd->xbusd_otherend);
                         break;                          break;
                 if (xennetback_connect(xneti) == 0)                  }
                         xenbus_switch_state(xbusd, NULL, XenbusStateConnected);  
                   /* allocate VA space and map rings */
                   xneti->xni_tx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
                       UVM_KMF_VAONLY);
                   if (xneti->xni_tx_ring_va == 0) {
                           xenbus_dev_fatal(xbusd, ENOMEM,
                               "can't get VA for tx ring", xbusd->xbusd_otherend);
                           break;
                   }
                   tx_ring = (void *)xneti->xni_tx_ring_va;
                   xneti->xni_rx_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
                       UVM_KMF_VAONLY);
                   if (xneti->xni_rx_ring_va == 0) {
                           xenbus_dev_fatal(xbusd, ENOMEM,
                               "can't get VA for rx ring", xbusd->xbusd_otherend);
                           goto err1;
                   }
                   rx_ring = (void *)xneti->xni_rx_ring_va;
                   op.host_addr = xneti->xni_tx_ring_va;
                   op.flags = GNTMAP_host_map;
                   op.ref = tx_ring_ref;
                   op.dom = xneti->xni_domid;
                   err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
                   if (err || op.status) {
                           printf("%s: can't map TX grant ref: %d/%d\n",
                               xneti->xni_if.if_xname, err, op.status);
                           goto err2;
                   }
                   xneti->xni_tx_ring_handle = op.handle;
   
                   op.host_addr = xneti->xni_rx_ring_va;
                   op.flags = GNTMAP_host_map;
                   op.ref = rx_ring_ref;
                   op.dom = xneti->xni_domid;
                   err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
                   if (err || op.status) {
                           printf("%s: can't map RX grant ref: %d/%d\n",
                               xneti->xni_if.if_xname, err, op.status);
                           goto err2;
                   }
                   xneti->xni_rx_ring_handle = op.handle;
                   BACK_RING_INIT(&xneti->xni_txring, tx_ring, PAGE_SIZE);
                   BACK_RING_INIT(&xneti->xni_rxring, rx_ring, PAGE_SIZE);
                   evop.cmd = EVTCHNOP_bind_interdomain;
                   evop.u.bind_interdomain.remote_dom = xneti->xni_domid;
                   evop.u.bind_interdomain.remote_port = revtchn;
                   err = HYPERVISOR_event_channel_op(&evop);
                   if (err) {
                           printf("%s: can't get event channel: %d\n",
                               xneti->xni_if.if_xname, err);
                           goto err2;
                   }
                   xneti->xni_evtchn = evop.u.bind_interdomain.local_port;
                   xen_wmb();
                   xneti->xni_status = CONNECTED;
                   xenbus_switch_state(xbusd, NULL, XenbusStateConnected);
                   xen_wmb();
                   event_set_handler(xneti->xni_evtchn, xennetback_evthandler,
                       xneti, IPL_NET, xneti->xni_if.if_xname);
                   xennetback_ifinit(&xneti->xni_if);
                   hypervisor_enable_event(xneti->xni_evtchn);
                   hypervisor_notify_via_evtchn(xneti->xni_evtchn);
                 break;                  break;
   
         case XenbusStateClosing:          case XenbusStateClosing:
Line 630  xennetback_frontend_changed(void *arg, X
Line 557  xennetback_frontend_changed(void *arg, X
                 break;                  break;
         }          }
         return;          return;
   err2:
           uvm_km_free(kernel_map, xneti->xni_rx_ring_va,
               PAGE_SIZE, UVM_KMF_VAONLY);
   err1:
           uvm_km_free(kernel_map, xneti->xni_tx_ring_va,
               PAGE_SIZE, UVM_KMF_VAONLY);
 }  }
   
 /* lookup a xneti based on domain id and interface handle */  /* lookup a xneti based on domain id and interface handle */

Legend:
Removed from v.1.33.4.4  
changed lines
  Added in v.1.34

CVSweb <webmaster@jp.NetBSD.org>