xen-netback: add control ring boilerplate
My recent patch to include/xen/interface/io/netif.h defines a new shared ring (in addition to the rx and tx rings) for passing control messages from a VM frontend driver to a backend driver. This patch adds the necessary code to xen-netback to map this new shared ring, should it be created by a frontend, but does not add implementations for any of the defined protocol messages. These are added in a subsequent patch for clarity. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Acked-by: Wei Liu <wei.liu2@citrix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
1ca4673432
commit
4e15ee2cb4
@@ -128,6 +128,15 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t xenvif_ctrl_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct xenvif *vif = dev_id;
|
||||
|
||||
wake_up(&vif->ctrl_wq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int xenvif_queue_stopped(struct xenvif_queue *queue)
|
||||
{
|
||||
struct net_device *dev = queue->vif->dev;
|
||||
@@ -527,9 +536,66 @@ void xenvif_carrier_on(struct xenvif *vif)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
|
||||
unsigned long rx_ring_ref, unsigned int tx_evtchn,
|
||||
unsigned int rx_evtchn)
|
||||
int xenvif_connect_ctrl(struct xenvif *vif, grant_ref_t ring_ref,
|
||||
unsigned int evtchn)
|
||||
{
|
||||
struct net_device *dev = vif->dev;
|
||||
void *addr;
|
||||
struct xen_netif_ctrl_sring *shared;
|
||||
struct task_struct *task;
|
||||
int err = -ENOMEM;
|
||||
|
||||
err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif),
|
||||
&ring_ref, 1, &addr);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
shared = (struct xen_netif_ctrl_sring *)addr;
|
||||
BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE);
|
||||
|
||||
init_waitqueue_head(&vif->ctrl_wq);
|
||||
|
||||
err = bind_interdomain_evtchn_to_irqhandler(vif->domid, evtchn,
|
||||
xenvif_ctrl_interrupt,
|
||||
0, dev->name, vif);
|
||||
if (err < 0)
|
||||
goto err_unmap;
|
||||
|
||||
vif->ctrl_irq = err;
|
||||
|
||||
task = kthread_create(xenvif_ctrl_kthread, (void *)vif,
|
||||
"%s-control", dev->name);
|
||||
if (IS_ERR(task)) {
|
||||
pr_warn("Could not allocate kthread for %s\n", dev->name);
|
||||
err = PTR_ERR(task);
|
||||
goto err_deinit;
|
||||
}
|
||||
|
||||
get_task_struct(task);
|
||||
vif->ctrl_task = task;
|
||||
|
||||
wake_up_process(vif->ctrl_task);
|
||||
|
||||
return 0;
|
||||
|
||||
err_deinit:
|
||||
unbind_from_irqhandler(vif->ctrl_irq, vif);
|
||||
vif->ctrl_irq = 0;
|
||||
|
||||
err_unmap:
|
||||
xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
|
||||
vif->ctrl.sring);
|
||||
vif->ctrl.sring = NULL;
|
||||
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
int xenvif_connect_data(struct xenvif_queue *queue,
|
||||
unsigned long tx_ring_ref,
|
||||
unsigned long rx_ring_ref,
|
||||
unsigned int tx_evtchn,
|
||||
unsigned int rx_evtchn)
|
||||
{
|
||||
struct task_struct *task;
|
||||
int err = -ENOMEM;
|
||||
@@ -538,7 +604,8 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
|
||||
BUG_ON(queue->task);
|
||||
BUG_ON(queue->dealloc_task);
|
||||
|
||||
err = xenvif_map_frontend_rings(queue, tx_ring_ref, rx_ring_ref);
|
||||
err = xenvif_map_frontend_data_rings(queue, tx_ring_ref,
|
||||
rx_ring_ref);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
|
||||
@@ -614,7 +681,7 @@ err_tx_unbind:
|
||||
unbind_from_irqhandler(queue->tx_irq, queue);
|
||||
queue->tx_irq = 0;
|
||||
err_unmap:
|
||||
xenvif_unmap_frontend_rings(queue);
|
||||
xenvif_unmap_frontend_data_rings(queue);
|
||||
netif_napi_del(&queue->napi);
|
||||
err:
|
||||
module_put(THIS_MODULE);
|
||||
@@ -634,7 +701,7 @@ void xenvif_carrier_off(struct xenvif *vif)
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
void xenvif_disconnect(struct xenvif *vif)
|
||||
void xenvif_disconnect_data(struct xenvif *vif)
|
||||
{
|
||||
struct xenvif_queue *queue = NULL;
|
||||
unsigned int num_queues = vif->num_queues;
|
||||
@@ -668,12 +735,32 @@ void xenvif_disconnect(struct xenvif *vif)
|
||||
queue->tx_irq = 0;
|
||||
}
|
||||
|
||||
xenvif_unmap_frontend_rings(queue);
|
||||
xenvif_unmap_frontend_data_rings(queue);
|
||||
}
|
||||
|
||||
xenvif_mcast_addr_list_free(vif);
|
||||
}
|
||||
|
||||
void xenvif_disconnect_ctrl(struct xenvif *vif)
|
||||
{
|
||||
if (vif->ctrl_task) {
|
||||
kthread_stop(vif->ctrl_task);
|
||||
put_task_struct(vif->ctrl_task);
|
||||
vif->ctrl_task = NULL;
|
||||
}
|
||||
|
||||
if (vif->ctrl_irq) {
|
||||
unbind_from_irqhandler(vif->ctrl_irq, vif);
|
||||
vif->ctrl_irq = 0;
|
||||
}
|
||||
|
||||
if (vif->ctrl.sring) {
|
||||
xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif),
|
||||
vif->ctrl.sring);
|
||||
vif->ctrl.sring = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reverse the relevant parts of xenvif_init_queue().
|
||||
* Used for queue teardown from xenvif_free(), and on the
|
||||
* error handling paths in xenbus.c:connect().
|
||||
|
Reference in New Issue
Block a user