From 8323478d5bd96cb1c00cd67da33f59a42965d9be Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 3 Jun 2009 11:09:14 +0100 Subject: minios: refactor xenbus state machine Implement xenbus_wait_for_state_change and xenbus_switch_state and change the various frontends to use the two functions and do proper error checking. Signed-off-by: Stefano Stabellini --- extras/mini-os/pcifront.c | 71 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 15 deletions(-) (limited to 'extras/mini-os/pcifront.c') diff --git a/extras/mini-os/pcifront.c b/extras/mini-os/pcifront.c index 5b68d86b56..70ea89b82d 100644 --- a/extras/mini-os/pcifront.c +++ b/extras/mini-os/pcifront.c @@ -111,9 +111,12 @@ again: goto abort_transaction; } - err = xenbus_printf(xbt, nodename, "state", "%u", - 3); /* initialised */ - + snprintf(path, sizeof(path), "%s/state", nodename); + err = xenbus_switch_state(xbt, path, XenbusStateInitialised); + if (err) { + message = "switching state"; + goto abort_transaction; + } err = xenbus_transaction_end(xbt, 0, &retry); if (retry) { @@ -140,13 +143,29 @@ done: { char path[strlen(dev->backend) + 1 + 5 + 1]; + char frontpath[strlen(nodename) + 1 + 5 + 1]; + XenbusState state; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); - xenbus_wait_for_value(path, "4", &dev->events); + err = NULL; + state = xenbus_read_integer(path); + while (err == NULL && state < XenbusStateConnected) + err = xenbus_wait_for_state_change(path, &state, &dev->events); + if (state != XenbusStateConnected) { + printk("backend not avalable, state=%d\n", state); + xenbus_unwatch_path(XBT_NIL, path); + goto error; + } - xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */ + snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); + if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) + != NULL) { + printk("error switching state %s\n", err); + xenbus_unwatch_path(XBT_NIL, path); + goto error; + } } unmask_evtchn(dev->evtchn); @@ -190,23 +209,45 @@ void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, u void shutdown_pcifront(struct pcifront_dev *dev) { - char* err; - char *nodename = dev->nodename; + char* err = NULL; + XenbusState state; char path[strlen(dev->backend) + 1 + 5 + 1]; + char nodename[strlen(dev->nodename) + 1 + 5 + 1]; printk("close pci: backend at %s\n",dev->backend); snprintf(path, sizeof(path), "%s/state", dev->backend); - err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */ - xenbus_wait_for_value(path, "5", &dev->events); - - err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6); - xenbus_wait_for_value(path, "6", &dev->events); - - err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1); - xenbus_wait_for_value(path, "2", &dev->events); + snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename); + if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) { + printk("shutdown_pcifront: error changing state to %d: %s\n", + XenbusStateClosing, err); + goto close_pcifront; + } + state = xenbus_read_integer(path); + while (err == NULL && state < XenbusStateClosing) + err = xenbus_wait_for_state_change(path, &state, &dev->events); + + if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) { + printk("shutdown_pcifront: error changing state to %d: %s\n", + XenbusStateClosed, err); + goto close_pcifront; + } + state = xenbus_read_integer(path); + if (state < XenbusStateClosed) + xenbus_wait_for_state_change(path, &state, &dev->events); + + if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) { + printk("shutdown_pcifront: error changing state to %d: %s\n", + XenbusStateInitialising, err); + goto close_pcifront; + } + err = NULL; + state = xenbus_read_integer(path); + while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed)) + err = xenbus_wait_for_state_change(path, &state, &dev->events); +close_pcifront: xenbus_unwatch_path(XBT_NIL, path); snprintf(path, sizeof(path), "%s/info-ref", nodename); -- cgit v1.2.3