|
@@ -38,7 +38,8 @@ struct backend_info {
|
|
const char *hotplug_script;
|
|
const char *hotplug_script;
|
|
};
|
|
};
|
|
|
|
|
|
-static int connect_rings(struct backend_info *be, struct xenvif_queue *queue);
|
|
|
|
|
|
+static int connect_data_rings(struct backend_info *be,
|
|
|
|
+ struct xenvif_queue *queue);
|
|
static void connect(struct backend_info *be);
|
|
static void connect(struct backend_info *be);
|
|
static int read_xenbus_vif_flags(struct backend_info *be);
|
|
static int read_xenbus_vif_flags(struct backend_info *be);
|
|
static int backend_create_xenvif(struct backend_info *be);
|
|
static int backend_create_xenvif(struct backend_info *be);
|
|
@@ -367,6 +368,12 @@ static int netback_probe(struct xenbus_device *dev,
|
|
if (err)
|
|
if (err)
|
|
pr_debug("Error writing multi-queue-max-queues\n");
|
|
pr_debug("Error writing multi-queue-max-queues\n");
|
|
|
|
|
|
|
|
+ err = xenbus_printf(XBT_NIL, dev->nodename,
|
|
|
|
+ "feature-ctrl-ring",
|
|
|
|
+ "%u", true);
|
|
|
|
+ if (err)
|
|
|
|
+ pr_debug("Error writing feature-ctrl-ring\n");
|
|
|
|
+
|
|
script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL);
|
|
script = xenbus_read(XBT_NIL, dev->nodename, "script", NULL);
|
|
if (IS_ERR(script)) {
|
|
if (IS_ERR(script)) {
|
|
err = PTR_ERR(script);
|
|
err = PTR_ERR(script);
|
|
@@ -457,7 +464,8 @@ static void backend_disconnect(struct backend_info *be)
|
|
#ifdef CONFIG_DEBUG_FS
|
|
#ifdef CONFIG_DEBUG_FS
|
|
xenvif_debugfs_delif(be->vif);
|
|
xenvif_debugfs_delif(be->vif);
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
#endif /* CONFIG_DEBUG_FS */
|
|
- xenvif_disconnect(be->vif);
|
|
|
|
|
|
+ xenvif_disconnect_data(be->vif);
|
|
|
|
+ xenvif_disconnect_ctrl(be->vif);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -825,6 +833,48 @@ static void hotplug_status_changed(struct xenbus_watch *watch,
|
|
kfree(str);
|
|
kfree(str);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int connect_ctrl_ring(struct backend_info *be)
|
|
|
|
+{
|
|
|
|
+ struct xenbus_device *dev = be->dev;
|
|
|
|
+ struct xenvif *vif = be->vif;
|
|
|
|
+ unsigned int val;
|
|
|
|
+ grant_ref_t ring_ref;
|
|
|
|
+ unsigned int evtchn;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ err = xenbus_gather(XBT_NIL, dev->otherend,
|
|
|
|
+ "ctrl-ring-ref", "%u", &val, NULL);
|
|
|
|
+ if (err)
|
|
|
|
+ goto done; /* The frontend does not have a control ring */
|
|
|
|
+
|
|
|
|
+ ring_ref = val;
|
|
|
|
+
|
|
|
|
+ err = xenbus_gather(XBT_NIL, dev->otherend,
|
|
|
|
+ "event-channel-ctrl", "%u", &val, NULL);
|
|
|
|
+ if (err) {
|
|
|
|
+ xenbus_dev_fatal(dev, err,
|
|
|
|
+ "reading %s/event-channel-ctrl",
|
|
|
|
+ dev->otherend);
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ evtchn = val;
|
|
|
|
+
|
|
|
|
+ err = xenvif_connect_ctrl(vif, ring_ref, evtchn);
|
|
|
|
+ if (err) {
|
|
|
|
+ xenbus_dev_fatal(dev, err,
|
|
|
|
+ "mapping shared-frame %u port %u",
|
|
|
|
+ ring_ref, evtchn);
|
|
|
|
+ goto fail;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+done:
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+fail:
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
static void connect(struct backend_info *be)
|
|
static void connect(struct backend_info *be)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
@@ -861,6 +911,12 @@ static void connect(struct backend_info *be)
|
|
xen_register_watchers(dev, be->vif);
|
|
xen_register_watchers(dev, be->vif);
|
|
read_xenbus_vif_flags(be);
|
|
read_xenbus_vif_flags(be);
|
|
|
|
|
|
|
|
+ err = connect_ctrl_ring(be);
|
|
|
|
+ if (err) {
|
|
|
|
+ xenbus_dev_fatal(dev, err, "connecting control ring");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Use the number of queues requested by the frontend */
|
|
/* Use the number of queues requested by the frontend */
|
|
be->vif->queues = vzalloc(requested_num_queues *
|
|
be->vif->queues = vzalloc(requested_num_queues *
|
|
sizeof(struct xenvif_queue));
|
|
sizeof(struct xenvif_queue));
|
|
@@ -896,11 +952,12 @@ static void connect(struct backend_info *be)
|
|
queue->remaining_credit = credit_bytes;
|
|
queue->remaining_credit = credit_bytes;
|
|
queue->credit_usec = credit_usec;
|
|
queue->credit_usec = credit_usec;
|
|
|
|
|
|
- err = connect_rings(be, queue);
|
|
|
|
|
|
+ err = connect_data_rings(be, queue);
|
|
if (err) {
|
|
if (err) {
|
|
- /* connect_rings() cleans up after itself on failure,
|
|
|
|
- * but we need to clean up after xenvif_init_queue() here,
|
|
|
|
- * and also clean up any previously initialised queues.
|
|
|
|
|
|
+ /* connect_data_rings() cleans up after itself on
|
|
|
|
+ * failure, but we need to clean up after
|
|
|
|
+ * xenvif_init_queue() here, and also clean up any
|
|
|
|
+ * previously initialised queues.
|
|
*/
|
|
*/
|
|
xenvif_deinit_queue(queue);
|
|
xenvif_deinit_queue(queue);
|
|
be->vif->num_queues = queue_index;
|
|
be->vif->num_queues = queue_index;
|
|
@@ -935,15 +992,17 @@ static void connect(struct backend_info *be)
|
|
|
|
|
|
err:
|
|
err:
|
|
if (be->vif->num_queues > 0)
|
|
if (be->vif->num_queues > 0)
|
|
- xenvif_disconnect(be->vif); /* Clean up existing queues */
|
|
|
|
|
|
+ xenvif_disconnect_data(be->vif); /* Clean up existing queues */
|
|
vfree(be->vif->queues);
|
|
vfree(be->vif->queues);
|
|
be->vif->queues = NULL;
|
|
be->vif->queues = NULL;
|
|
be->vif->num_queues = 0;
|
|
be->vif->num_queues = 0;
|
|
|
|
+ xenvif_disconnect_ctrl(be->vif);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
|
|
|
|
|
|
+static int connect_data_rings(struct backend_info *be,
|
|
|
|
+ struct xenvif_queue *queue)
|
|
{
|
|
{
|
|
struct xenbus_device *dev = be->dev;
|
|
struct xenbus_device *dev = be->dev;
|
|
unsigned int num_queues = queue->vif->num_queues;
|
|
unsigned int num_queues = queue->vif->num_queues;
|
|
@@ -1007,8 +1066,8 @@ static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
|
|
}
|
|
}
|
|
|
|
|
|
/* Map the shared frame, irq etc. */
|
|
/* Map the shared frame, irq etc. */
|
|
- err = xenvif_connect(queue, tx_ring_ref, rx_ring_ref,
|
|
|
|
- tx_evtchn, rx_evtchn);
|
|
|
|
|
|
+ err = xenvif_connect_data(queue, tx_ring_ref, rx_ring_ref,
|
|
|
|
+ tx_evtchn, rx_evtchn);
|
|
if (err) {
|
|
if (err) {
|
|
xenbus_dev_fatal(dev, err,
|
|
xenbus_dev_fatal(dev, err,
|
|
"mapping shared-frames %lu/%lu port tx %u rx %u",
|
|
"mapping shared-frames %lu/%lu port tx %u rx %u",
|