[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH 07/10] plat/xen/drivers/cons: Start Consfront
This patch adds start for the xen console frontend. Uses XenStore in order to establish connection to backend. Signed-off-by: Birlea Costin <costin.birlea@xxxxxxxxx> --- plat/xen/drivers/cons/consfront.c | 38 ++++++++ plat/xen/drivers/cons/consfront_xb.h | 19 ++++ plat/xen/drivers/cons/consfront_xs.c | 176 +++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+) diff --git a/plat/xen/drivers/cons/consfront.c b/plat/xen/drivers/cons/consfront.c index cdbed0f5..4dd57151 100644 --- a/plat/xen/drivers/cons/consfront.c +++ b/plat/xen/drivers/cons/consfront.c @@ -216,6 +216,42 @@ static int consfront_release(struct uk_consdev *dev) return 0; } +static int consfront_start(struct uk_consdev *dev) +{ + struct consfront_dev *cfdev; + int rc = 0; + + UK_ASSERT(dev); + + cfdev = to_consfront(dev); + UK_ASSERT(cfdev); + + rc = consfront_xb_connect(cfdev); + if (rc < 0) { + uk_pr_err("Error connecting to backend: %d.\n", rc); + return rc; + } + uk_pr_info(DRIVER_NAME": %"PRIu16" started\n", cfdev->uid); + + return rc; +} + +static int consfront_stop(struct uk_consdev *dev) +{ + struct consfront_dev *cfdev; + + UK_ASSERT(dev); + + cfdev = to_consfront(dev); + UK_ASSERT(cfdev); + + consfront_xb_disconnect(cfdev); + + uk_pr_info(DRIVER_NAME": %"PRIu16" stopped\n", cfdev->uid); + + return 0; +} + static void consfront_close(struct uk_consdev *dev) { struct consfront_dev *cfdev; @@ -240,6 +276,8 @@ static const struct uk_consdev_ops consfront_ops = { .rx_configure = consfront_rx_configure, .tx_configure = consfront_tx_configure, .release = consfront_release, + .start = consfront_start, + .stop = consfront_stop, .close = consfront_close, }; diff --git a/plat/xen/drivers/cons/consfront_xb.h b/plat/xen/drivers/cons/consfront_xb.h index 0ca1abaf..6b5475f3 100644 --- a/plat/xen/drivers/cons/consfront_xb.h +++ b/plat/xen/drivers/cons/consfront_xb.h @@ -44,6 +44,25 @@ #include "consfront.h" +/** + * Write ring entries to Xenstore. + * Device changes its state to Connected. + * It waits until the backend is connected. + * + * Return 0 on success, a negative errno value on error. + */ +int consfront_xb_connect(struct consfront_dev *cfdev); + +/** + * Stops the connection with the backend. + * The following states are: + * Connected -> Closing -> Closed. + * Delete ring entries + * + * Return 0 on success, a negative errno value on error. + */ +int consfront_xb_disconnect(struct consfront_dev *cfdev); + /* * Get initial info from the xenstore. * Ex: backend path. diff --git a/plat/xen/drivers/cons/consfront_xs.c b/plat/xen/drivers/cons/consfront_xs.c index 066a23d9..a1554ae0 100644 --- a/plat/xen/drivers/cons/consfront_xs.c +++ b/plat/xen/drivers/cons/consfront_xs.c @@ -40,6 +40,182 @@ #include "consfront_xb.h" +static void consfront_xb_front_fini(struct consfront_dev *cfdev, + xenbus_transaction_t xbt); + +#define WAIT_BE_STATE_CHANGE_WHILE_COND(state_cond) \ + do { \ + rc = xs_read_integer(XBT_NIL, path, (int *) &be_state); \ + if (rc < 0) \ + goto out; \ + while (!rc && (state_cond)) \ + rc = xenbus_wait_for_state_change(path, &be_state, \ + xendev->otherend_watch); \ + if (rc < 0) \ + goto out; \ + } while (0) + + +static int consfront_xb_front_init(struct consfront_dev *cfdev, + xenbus_transaction_t xbt) +{ + int rc = 0; + struct xenbus_device *xendev = cfdev->xendev; + + rc = xs_printf(xbt, xendev->nodename, "ring-ref", "%u", + cfdev->ring_ref); + if (rc < 0) + goto out; + + rc = xs_printf(xbt, xendev->nodename, + "port", "%u", cfdev->evtchn); + if (rc < 0) + goto out; + +out: + return rc; +} + +static int consfront_xb_transactions(struct consfront_dev *cfdev) +{ + struct xenbus_device *xendev = cfdev->xendev; + xenbus_transaction_t xbt; + char *message = NULL; + int rc = 0; + + rc = xs_transaction_start(&xbt); + if (rc < 0) { + message = "starting transaction"; + goto abort_transaction; + } + + rc = consfront_xb_front_init(cfdev, xbt); + if (rc < 0) { + message = "writing something"; + goto abort_transaction; + } + + rc = xenbus_switch_state(xbt, xendev, XenbusStateConnected); + if (rc < 0) { + message = "switching state"; + goto abort_transaction; + } + + rc = xs_transaction_end(xbt, 0); + if (rc < 0) { + message = "ending transaction"; + goto abort_transaction; + } + + return rc; + +abort_transaction: + xs_transaction_end(xbt, 1); + uk_pr_info("Abort transaction %s: code: %d\n", message, rc); + return rc; +} + +static int consfront_xb_wait_be_connect(struct consfront_dev *cfdev) +{ + struct xenbus_device *xendev = cfdev->xendev; + char path[strlen(xendev->otherend) + strlen("/state") + 1]; + XenbusState be_state; + int rc = 0; + + snprintf(path, sizeof(path), "%s/state", xendev->otherend); + + xendev->otherend_watch = xs_watch_path(XBT_NIL, path); + if (PTRISERR(xendev->otherend_watch)) { + rc = PTR2ERR(xendev->otherend_watch); + goto out; + } + + WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateConnected); + if (be_state != XenbusStateConnected) { + uk_pr_err("Backend not available, state=%s\n", + xenbus_state_to_str(be_state)); + xs_unwatch(XBT_NIL, xendev->otherend_watch); + } + +out: + return rc; +} + +int consfront_xb_connect(struct consfront_dev *cfdev) +{ + int rc = 0; + + UK_ASSERT(cfdev); + + rc = consfront_xb_transactions(cfdev); + if (rc < 0) + goto error; + + rc = consfront_xb_wait_be_connect(cfdev); + if (rc < 0) + consfront_xb_front_fini(cfdev, XBT_NIL); + +error: + return rc; +} + +static void consfront_xb_front_fini(struct consfront_dev *cfdev, + xenbus_transaction_t xbt) +{ + struct xenbus_device *xendev = cfdev->xendev; + char path[strlen(xendev->nodename) + sizeof("/ring_ref")]; + + sprintf(path, "%s/ring-ref", xendev->nodename); + xs_rm(xbt, path); + + sprintf(path, "%s/port", xendev->nodename); + xs_rm(xbt, path); +} + +static int consfront_xb_wait_be_disconnect(struct consfront_dev *cfdev) +{ + struct xenbus_device *xendev = cfdev->xendev; + char path[strlen(xendev->otherend) + strlen("/state") + 1]; + XenbusState be_state; + int rc = 0; + + snprintf(path, sizeof(path), "%s/state", xendev->otherend); + + WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateClosing); + + rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosed); + if (rc < 0) + goto out; + + WAIT_BE_STATE_CHANGE_WHILE_COND(be_state < XenbusStateClosed); + + xs_unwatch(XBT_NIL, xendev->otherend_watch); + +out: + return rc; +} + +int consfront_xb_disconnect(struct consfront_dev *cfdev) +{ + struct xenbus_device *xendev = cfdev->xendev; + int rc = 0; + + uk_pr_info("Close console: backend at %s\n", xendev->otherend); + + rc = xenbus_switch_state(XBT_NIL, xendev, XenbusStateClosing); + if (rc < 0) + goto out; + + rc = consfront_xb_wait_be_disconnect(cfdev); + if (rc < 0) + goto out; + + consfront_xb_front_fini(cfdev, XBT_NIL); + +out: + return rc; +} + int consfront_xb_init(struct consfront_dev *cfdev) { struct xenbus_device *xendev; -- 2.11.0 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |