/* * Handle the creation of the hotplug script environment. We add the script * and vif variables to the environment, for the benefit of the vif-* hotplug * scripts.
*/ staticint netback_uevent(conststruct xenbus_device *xdev, struct kobj_uevent_env *env)
{ struct backend_info *be = dev_get_drvdata(&xdev->dev);
if (!be) return0;
if (add_uevent_var(env, "script=%s", be->hotplug_script)) return -ENOMEM;
/* At this point some of the handlers may still be active * so we need to have additional synchronization here.
*/
vif->num_queues = 0;
synchronize_net();
for (queue_index = 0; queue_index < num_queues; ++queue_index)
xenvif_deinit_queue(&vif->queues[queue_index]);
vfree(vif->queues);
vif->queues = NULL;
xenvif_disconnect_ctrl(vif);
}
}
staticvoid backend_connect(struct backend_info *be)
{ if (be->vif)
connect(be);
}
/* If we are waiting for a hotplug script then defer the * actual xenbus state change.
*/ if (!be->have_hotplug_status_watch)
xenbus_switch_state(dev, state);
}
/* Handle backend state transitions: * * The backend state starts in Initialising and the following transitions are * allowed. * * Initialising -> InitWait -> Connected * \ * \ ^ \ | * \ | \ | * \ | \ | * \ | \ | * \ | \ | * \ | \ | * V | V V * * Closed <-> Closing * * The state argument specifies the eventual state of the backend and the * function transitions to that state via the shortest path.
*/ staticvoid set_backend_state(struct backend_info *be, enum xenbus_state state)
{ while (be->state != state) { switch (be->state) { case XenbusStateInitialising: switch (state) { case XenbusStateInitWait: case XenbusStateConnected: case XenbusStateClosing:
backend_switch_state(be, XenbusStateInitWait); break; case XenbusStateClosed:
backend_switch_state(be, XenbusStateClosed); break; default:
BUG();
} break; case XenbusStateClosed: switch (state) { case XenbusStateInitWait: case XenbusStateConnected:
backend_switch_state(be, XenbusStateInitWait); break; case XenbusStateClosing:
backend_switch_state(be, XenbusStateClosing); break; default:
BUG();
} break; case XenbusStateInitWait: switch (state) { case XenbusStateConnected:
backend_connect(be);
backend_switch_state(be, XenbusStateConnected); break; case XenbusStateClosing: case XenbusStateClosed:
backend_switch_state(be, XenbusStateClosing); break; default:
BUG();
} break; case XenbusStateConnected: switch (state) { case XenbusStateInitWait: case XenbusStateClosing: case XenbusStateClosed:
backend_disconnect(be);
backend_switch_state(be, XenbusStateClosing); break; default:
BUG();
} break; case XenbusStateClosing: switch (state) { case XenbusStateInitWait: case XenbusStateConnected: case XenbusStateClosed:
backend_switch_state(be, XenbusStateClosed); break; default:
BUG();
} break; default:
BUG();
}
}
}
switch (frontend_state) { case XenbusStateInitialising:
set_backend_state(be, XenbusStateInitWait); break;
case XenbusStateInitialised: break;
case XenbusStateConnected:
set_backend_state(be, XenbusStateConnected); break;
case XenbusStateReconfiguring:
read_xenbus_frontend_xdp(be, dev);
xenbus_switch_state(dev, XenbusStateReconfigured); break;
case XenbusStateClosing:
set_backend_state(be, XenbusStateClosing); break;
case XenbusStateClosed:
set_backend_state(be, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break;
fallthrough; /* if not online */ case XenbusStateUnknown:
set_backend_state(be, XenbusStateClosed);
device_unregister(&dev->dev); break;
default:
xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
frontend_state); break;
}
}
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 */
be->vif->queues = vzalloc(array_size(requested_num_queues, sizeof(struct xenvif_queue))); if (!be->vif->queues) {
xenbus_dev_fatal(dev, -ENOMEM, "allocating queues"); return;
}
err = xenvif_init_queue(queue); if (err) { /* xenvif_init_queue() cleans up after itself on * failure, but we need to clean up any previously * initialised queues. Set num_queues to i so that * earlier queues can be destroyed using the regular * disconnect logic.
*/
be->vif->num_queues = queue_index; goto err;
}
err = connect_data_rings(be, queue); if (err) { /* 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);
be->vif->num_queues = queue_index; goto err;
}
}
/* Initialisation completed, tell core driver the number of * active queues.
*/
rtnl_lock();
netif_set_real_num_tx_queues(be->vif->dev, requested_num_queues);
netif_set_real_num_rx_queues(be->vif->dev, requested_num_queues);
rtnl_unlock();
/* If the frontend requested 1 queue, or we have fallen back * to single queue due to lack of frontend support for multi- * queue, expect the remaining XenStore keys in the toplevel * directory. Otherwise, expect them in a subdirectory called * queue-N.
*/ if (num_queues == 1) {
xspath = kstrdup(dev->otherend, GFP_KERNEL); if (!xspath) {
xenbus_dev_fatal(dev, -ENOMEM, "reading ring references"); return -ENOMEM;
}
} else {
xspathsize = strlen(dev->otherend) + xenstore_path_ext_size;
xspath = kzalloc(xspathsize, GFP_KERNEL); if (!xspath) {
xenbus_dev_fatal(dev, -ENOMEM, "reading ring references"); return -ENOMEM;
}
snprintf(xspath, xspathsize, "%s/queue-%u", dev->otherend,
queue->id);
}
/* * Entry point to this code when a new device is created. Allocate the basic * structures and switch to InitWait.
*/ staticint netback_probe(struct xenbus_device *dev, conststruct xenbus_device_id *id)
{ constchar *message; struct xenbus_transaction xbt; int err; int sg; constchar *script; struct backend_info *be = kzalloc(sizeof(*be), GFP_KERNEL);
err = xenbus_transaction_end(xbt, 0);
} while (err == -EAGAIN);
if (err) {
xenbus_dev_fatal(dev, err, "completing transaction"); goto fail;
}
/* Split event channels support, this is optional so it is not * put inside the above loop.
*/
err = xenbus_printf(XBT_NIL, dev->nodename, "feature-split-event-channels", "%u", separate_tx_rx_irq); if (err)
pr_debug("Error writing feature-split-event-channels\n");
/* Multi-queue support: This is an optional feature. */
err = xenbus_printf(XBT_NIL, dev->nodename, "multi-queue-max-queues", "%u", xenvif_max_queues); if (err)
pr_debug("Error writing multi-queue-max-queues\n");
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet am 2026-06-07)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.