Move the connection code of xbdback(4) and xvif(4) backends in separate
functions. The frontend watch function is easier to read, and mixing switch() with goto's error paths is rather error-prone. While here, sprinkle some aprint_*. Tested under amd64 dom0 with i386 PAE and amd64 domUs.
This commit is contained in:
parent
e0258609a4
commit
bf7437481f
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: xbdback_xenbus.c,v 1.33 2011/03/05 15:12:16 bouyer Exp $ */
|
/* $NetBSD: xbdback_xenbus.c,v 1.34 2011/04/29 22:58:46 jym Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Manuel Bouyer.
|
* Copyright (c) 2006 Manuel Bouyer.
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.33 2011/03/05 15:12:16 bouyer Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.34 2011/04/29 22:58:46 jym Exp $");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -479,20 +479,152 @@ xbdback_xenbus_destroy(void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xbdback_connect(struct xbdback_instance *xbdi)
|
||||||
|
{
|
||||||
|
int len, err;
|
||||||
|
struct gnttab_map_grant_ref grop;
|
||||||
|
struct gnttab_unmap_grant_ref ungrop;
|
||||||
|
evtchn_op_t evop;
|
||||||
|
u_long ring_ref, revtchn;
|
||||||
|
char *xsproto;
|
||||||
|
char evname[16];
|
||||||
|
const char *proto;
|
||||||
|
struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
|
||||||
|
|
||||||
|
/* read comunication informations */
|
||||||
|
err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
|
||||||
|
"ring-ref", &ring_ref, 10);
|
||||||
|
if (err) {
|
||||||
|
xenbus_dev_fatal(xbusd, err, "reading %s/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(NULL, xbusd->xbusd_otherend, "protocol",
|
||||||
|
&len, &xsproto);
|
||||||
|
if (err) {
|
||||||
|
xbdi->xbdi_proto = XBDIP_NATIVE;
|
||||||
|
proto = "unspecified";
|
||||||
|
} else {
|
||||||
|
if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) {
|
||||||
|
xbdi->xbdi_proto = XBDIP_NATIVE;
|
||||||
|
proto = XEN_IO_PROTO_ABI_NATIVE;
|
||||||
|
} else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) {
|
||||||
|
xbdi->xbdi_proto = XBDIP_32;
|
||||||
|
proto = XEN_IO_PROTO_ABI_X86_32;
|
||||||
|
} else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) {
|
||||||
|
xbdi->xbdi_proto = XBDIP_64;
|
||||||
|
proto = XEN_IO_PROTO_ABI_X86_64;
|
||||||
|
} else {
|
||||||
|
aprint_error("xbd domain %d: unknown proto %s\n",
|
||||||
|
xbdi->xbdi_domid, xsproto);
|
||||||
|
free(xsproto, M_DEVBUF);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(xsproto, M_DEVBUF);
|
||||||
|
|
||||||
|
/* allocate VA space and map rings */
|
||||||
|
xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
|
||||||
|
UVM_KMF_VAONLY);
|
||||||
|
if (xbdi->xbdi_ring_va == 0) {
|
||||||
|
xenbus_dev_fatal(xbusd, ENOMEM,
|
||||||
|
"can't get VA for ring", xbusd->xbusd_otherend);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
grop.host_addr = xbdi->xbdi_ring_va;
|
||||||
|
grop.flags = GNTMAP_host_map;
|
||||||
|
grop.ref = ring_ref;
|
||||||
|
grop.dom = xbdi->xbdi_domid;
|
||||||
|
err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
|
||||||
|
&grop, 1);
|
||||||
|
if (err || grop.status) {
|
||||||
|
aprint_error("xbdback %s: can't map grant ref: %d/%d\n",
|
||||||
|
xbusd->xbusd_path, err, grop.status);
|
||||||
|
xenbus_dev_fatal(xbusd, EINVAL,
|
||||||
|
"can't map ring", xbusd->xbusd_otherend);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
xbdi->xbdi_ring_handle = grop.handle;
|
||||||
|
|
||||||
|
switch(xbdi->xbdi_proto) {
|
||||||
|
case XBDIP_NATIVE:
|
||||||
|
{
|
||||||
|
blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va;
|
||||||
|
BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XBDIP_32:
|
||||||
|
{
|
||||||
|
blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va;
|
||||||
|
BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XBDIP_64:
|
||||||
|
{
|
||||||
|
blkif_x86_64_sring_t *sring = (void *)xbdi->xbdi_ring_va;
|
||||||
|
BACK_RING_INIT(&xbdi->xbdi_ring.ring_64, sring, PAGE_SIZE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evop.cmd = EVTCHNOP_bind_interdomain;
|
||||||
|
evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid;
|
||||||
|
evop.u.bind_interdomain.remote_port = revtchn;
|
||||||
|
err = HYPERVISOR_event_channel_op(&evop);
|
||||||
|
if (err) {
|
||||||
|
aprint_error("blkback %s: "
|
||||||
|
"can't get event channel: %d\n",
|
||||||
|
xbusd->xbusd_otherend, err);
|
||||||
|
xenbus_dev_fatal(xbusd, err,
|
||||||
|
"can't bind event channel", xbusd->xbusd_otherend);
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port;
|
||||||
|
|
||||||
|
snprintf(evname, sizeof(evname), "xbd%d.%d",
|
||||||
|
xbdi->xbdi_domid, xbdi->xbdi_handle);
|
||||||
|
event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
|
||||||
|
xbdi, IPL_BIO, evname);
|
||||||
|
aprint_verbose("xbd backend 0x%x for domain %d "
|
||||||
|
"using event channel %d, protocol %s\n", xbdi->xbdi_handle,
|
||||||
|
xbdi->xbdi_domid, xbdi->xbdi_evtchn, proto);
|
||||||
|
hypervisor_enable_event(xbdi->xbdi_evtchn);
|
||||||
|
hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn);
|
||||||
|
xbdi->xbdi_status = CONNECTED;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
/* unmap ring */
|
||||||
|
ungrop.host_addr = xbdi->xbdi_ring_va;
|
||||||
|
ungrop.handle = xbdi->xbdi_ring_handle;
|
||||||
|
ungrop.dev_bus_addr = 0;
|
||||||
|
err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
|
||||||
|
&ungrop, 1);
|
||||||
|
if (err)
|
||||||
|
aprint_error("xbdback %s: unmap_grant_ref failed: %d\n",
|
||||||
|
xbusd->xbusd_path, err);
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* free ring VA space */
|
||||||
|
uvm_km_free(kernel_map, xbdi->xbdi_ring_va, PAGE_SIZE, UVM_KMF_VAONLY);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xbdback_frontend_changed(void *arg, XenbusState new_state)
|
xbdback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
{
|
{
|
||||||
struct xbdback_instance *xbdi = arg;
|
struct xbdback_instance *xbdi = arg;
|
||||||
struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
|
struct xenbus_device *xbusd = xbdi->xbdi_xbusd;
|
||||||
u_long ring_ref, revtchn;
|
int s;
|
||||||
struct gnttab_map_grant_ref grop;
|
|
||||||
struct gnttab_unmap_grant_ref ungrop;
|
|
||||||
evtchn_op_t evop;
|
|
||||||
char evname[16];
|
|
||||||
const char *proto;
|
|
||||||
char *xsproto;
|
|
||||||
int len;
|
|
||||||
int err, s;
|
|
||||||
|
|
||||||
XENPRINTF(("xbdback %s: new state %d\n", xbusd->xbusd_path, new_state));
|
XENPRINTF(("xbdback %s: new state %d\n", xbusd->xbusd_path, new_state));
|
||||||
switch(new_state) {
|
switch(new_state) {
|
||||||
|
@ -502,114 +634,7 @@ xbdback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
case XenbusStateConnected:
|
case XenbusStateConnected:
|
||||||
if (xbdi->xbdi_status == CONNECTED)
|
if (xbdi->xbdi_status == CONNECTED)
|
||||||
break;
|
break;
|
||||||
/* read comunication informations */
|
xbdback_connect(xbdi);
|
||||||
err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
|
|
||||||
"ring-ref", &ring_ref, 10);
|
|
||||||
if (err) {
|
|
||||||
xenbus_dev_fatal(xbusd, err, "reading %s/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(NULL, xbusd->xbusd_otherend, "protocol",
|
|
||||||
&len, &xsproto);
|
|
||||||
if (err) {
|
|
||||||
proto = "unspecified";
|
|
||||||
xbdi->xbdi_proto = XBDIP_NATIVE;
|
|
||||||
} else {
|
|
||||||
if(strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) {
|
|
||||||
xbdi->xbdi_proto = XBDIP_NATIVE;
|
|
||||||
proto = XEN_IO_PROTO_ABI_NATIVE;
|
|
||||||
} else if(strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) {
|
|
||||||
xbdi->xbdi_proto = XBDIP_32;
|
|
||||||
proto = XEN_IO_PROTO_ABI_X86_32;
|
|
||||||
} else if(strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) {
|
|
||||||
xbdi->xbdi_proto = XBDIP_64;
|
|
||||||
proto = XEN_IO_PROTO_ABI_X86_64;
|
|
||||||
} else {
|
|
||||||
printf("xbd domain %d: unknown proto %s\n",
|
|
||||||
xbdi->xbdi_domid, xsproto);
|
|
||||||
free(xsproto, M_DEVBUF);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
free(xsproto, M_DEVBUF);
|
|
||||||
}
|
|
||||||
/* allocate VA space and map rings */
|
|
||||||
xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
|
|
||||||
UVM_KMF_VAONLY);
|
|
||||||
if (xbdi->xbdi_ring_va == 0) {
|
|
||||||
xenbus_dev_fatal(xbusd, ENOMEM,
|
|
||||||
"can't get VA for ring", xbusd->xbusd_otherend);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
grop.host_addr = xbdi->xbdi_ring_va;
|
|
||||||
grop.flags = GNTMAP_host_map;
|
|
||||||
grop.ref = ring_ref;
|
|
||||||
grop.dom = xbdi->xbdi_domid;
|
|
||||||
err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
|
|
||||||
&grop, 1);
|
|
||||||
if (err || grop.status) {
|
|
||||||
printf("xbdback %s: can't map grant ref: %d/%d\n",
|
|
||||||
xbusd->xbusd_path, err, grop.status);
|
|
||||||
xenbus_dev_fatal(xbusd, EINVAL,
|
|
||||||
"can't map ring", xbusd->xbusd_otherend);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
xbdi->xbdi_ring_handle = grop.handle;
|
|
||||||
switch(xbdi->xbdi_proto) {
|
|
||||||
case XBDIP_NATIVE:
|
|
||||||
{
|
|
||||||
blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va;
|
|
||||||
BACK_RING_INIT(&xbdi->xbdi_ring.ring_n,
|
|
||||||
sring, PAGE_SIZE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XBDIP_32:
|
|
||||||
{
|
|
||||||
blkif_x86_32_sring_t *sring =
|
|
||||||
(void *)xbdi->xbdi_ring_va;
|
|
||||||
BACK_RING_INIT(&xbdi->xbdi_ring.ring_32,
|
|
||||||
sring, PAGE_SIZE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XBDIP_64:
|
|
||||||
{
|
|
||||||
blkif_x86_64_sring_t *sring =
|
|
||||||
(void *)xbdi->xbdi_ring_va;
|
|
||||||
BACK_RING_INIT(&xbdi->xbdi_ring.ring_64,
|
|
||||||
sring, PAGE_SIZE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
evop.cmd = EVTCHNOP_bind_interdomain;
|
|
||||||
evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid;
|
|
||||||
evop.u.bind_interdomain.remote_port = revtchn;
|
|
||||||
err = HYPERVISOR_event_channel_op(&evop);
|
|
||||||
if (err) {
|
|
||||||
aprint_error("blkback %s: "
|
|
||||||
"can't get event channel: %d\n",
|
|
||||||
xbusd->xbusd_otherend, err);
|
|
||||||
xenbus_dev_fatal(xbusd, err,
|
|
||||||
"can't bind event channel", xbusd->xbusd_otherend);
|
|
||||||
goto err2;
|
|
||||||
}
|
|
||||||
xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port;
|
|
||||||
snprintf(evname, sizeof(evname), "xbd%d.%d",
|
|
||||||
xbdi->xbdi_domid, xbdi->xbdi_handle);
|
|
||||||
event_set_handler(xbdi->xbdi_evtchn, xbdback_evthandler,
|
|
||||||
xbdi, IPL_BIO, evname);
|
|
||||||
aprint_verbose("xbd backend 0x%x for domain %d "
|
|
||||||
"using event channel %d, protocol %s\n", xbdi->xbdi_handle,
|
|
||||||
xbdi->xbdi_domid, xbdi->xbdi_evtchn, proto);
|
|
||||||
hypervisor_enable_event(xbdi->xbdi_evtchn);
|
|
||||||
hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn);
|
|
||||||
xbdi->xbdi_status = CONNECTED;
|
|
||||||
break;
|
break;
|
||||||
case XenbusStateClosing:
|
case XenbusStateClosing:
|
||||||
hypervisor_mask_event(xbdi->xbdi_evtchn);
|
hypervisor_mask_event(xbdi->xbdi_evtchn);
|
||||||
|
@ -634,19 +659,6 @@ xbdback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
xbusd->xbusd_path, new_state);
|
xbusd->xbusd_path, new_state);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
err2:
|
|
||||||
/* unmap ring */
|
|
||||||
ungrop.host_addr = xbdi->xbdi_ring_va;
|
|
||||||
ungrop.handle = xbdi->xbdi_ring_handle;
|
|
||||||
ungrop.dev_bus_addr = 0;
|
|
||||||
err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
|
|
||||||
&ungrop, 1);
|
|
||||||
if (err)
|
|
||||||
printf("xbdback %s: unmap_grant_ref failed: %d\n",
|
|
||||||
xbusd->xbusd_path, err);
|
|
||||||
err:
|
|
||||||
uvm_km_free(kernel_map, xbdi->xbdi_ring_va, PAGE_SIZE, UVM_KMF_VAONLY);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: xennetback_xenbus.c,v 1.44 2011/04/25 00:22:37 jym Exp $ */
|
/* $NetBSD: xennetback_xenbus.c,v 1.45 2011/04/29 22:58:46 jym Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Manuel Bouyer.
|
* Copyright (c) 2006 Manuel Bouyer.
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.44 2011/04/25 00:22:37 jym Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: xennetback_xenbus.c,v 1.45 2011/04/29 22:58:46 jym Exp $");
|
||||||
|
|
||||||
#include "opt_xen.h"
|
#include "opt_xen.h"
|
||||||
|
|
||||||
|
@ -427,11 +427,9 @@ xennetback_xenbus_destroy(void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
xennetback_frontend_changed(void *arg, XenbusState new_state)
|
xennetback_connect(struct xnetback_instance *xneti)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -440,6 +438,166 @@ xennetback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
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) {
|
||||||
|
@ -450,112 +608,8 @@ xennetback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
case XenbusStateConnected:
|
case XenbusStateConnected:
|
||||||
if (xneti->xni_status == CONNECTED)
|
if (xneti->xni_status == CONNECTED)
|
||||||
break;
|
break;
|
||||||
/* read comunication informations */
|
if (xennetback_connect(xneti) == 0)
|
||||||
err = xenbus_read_ul(NULL, xbusd->xbusd_otherend,
|
xenbus_switch_state(xbusd, NULL, XenbusStateConnected);
|
||||||
"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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 err0;
|
|
||||||
}
|
|
||||||
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 err3;
|
|
||||||
}
|
|
||||||
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:
|
||||||
|
@ -577,33 +631,6 @@ xennetback_frontend_changed(void *arg, XenbusState new_state)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err3:
|
|
||||||
uop.dev_bus_addr = 0;
|
|
||||||
|
|
||||||
uop.host_addr = xneti->xni_rx_ring_va;
|
|
||||||
uop.handle = xneti->xni_rx_ring_handle;
|
|
||||||
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);
|
|
||||||
|
|
||||||
uop.host_addr = xneti->xni_tx_ring_va;
|
|
||||||
uop.handle = xneti->xni_tx_ring_handle;
|
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
err0:
|
|
||||||
softint_disestablish(xneti->xni_softintr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lookup a xneti based on domain id and interface handle */
|
/* lookup a xneti based on domain id and interface handle */
|
||||||
|
|
Loading…
Reference in New Issue