WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] pcifront: implement dynamic connections and disconne

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] pcifront: implement dynamic connections and disconnections
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Date: Fri, 13 Nov 2009 17:54:42 +0000
Delivery-date: Fri, 13 Nov 2009 09:53:01 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Alpine 2.00 (DEB 1167 2008-08-23)
Hi all,
this patch implements dynamic connections and disconnections in pcifront.
This feature is required to properly support pci hotplug, because when
no pci devices are assigned to a guest, xend will remove the pci backend
altogether.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

---

diff -r ac9d4ba48b83 extras/mini-os/include/pcifront.h
--- a/extras/mini-os/include/pcifront.h Thu Nov 05 12:00:58 2009 +0000
+++ b/extras/mini-os/include/pcifront.h Fri Nov 13 17:53:03 2009 +0000
@@ -1,6 +1,7 @@
 #include <mini-os/types.h>
 #include <xen/io/pciif.h>
 struct pcifront_dev;
+void pcifront_watches(void *opaque);
 struct pcifront_dev *init_pcifront(char *nodename);
 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op);
 void pcifront_scan(struct pcifront_dev *dev, void (*fun)(unsigned int domain, 
unsigned int bus, unsigned slot, unsigned int fun));
diff -r ac9d4ba48b83 extras/mini-os/main.c
--- a/extras/mini-os/main.c     Thu Nov 05 12:00:58 2009 +0000
+++ b/extras/mini-os/main.c     Fri Nov 13 17:53:03 2009 +0000
@@ -9,6 +9,7 @@
 #include <sched.h>
 #include <console.h>
 #include <netfront.h>
+#include <pcifront.h>
 #include <time.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -67,6 +68,7 @@
 #endif
     init_fs_frontend();
 #endif
+    create_thread("pcifront", pcifront_watches, NULL);
 
 #ifdef CONFIG_QEMU
     /* Fetch argc, argv from XenStore */
diff -r ac9d4ba48b83 extras/mini-os/pcifront.c
--- a/extras/mini-os/pcifront.c Thu Nov 05 12:00:58 2009 +0000
+++ b/extras/mini-os/pcifront.c Fri Nov 13 17:53:03 2009 +0000
@@ -13,10 +13,12 @@
 #include <mini-os/xmalloc.h>
 #include <mini-os/wait.h>
 #include <mini-os/pcifront.h>
+#include <mini-os/sched.h>
 
 #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 
 DECLARE_WAIT_QUEUE_HEAD(pcifront_queue);
+static struct pcifront_dev *pcidev;
 
 struct pcifront_dev {
     domid_t dom;
@@ -38,17 +40,101 @@
 
 static void free_pcifront(struct pcifront_dev *dev)
 {
+    if (!dev)
+        dev = pcidev;
+
     mask_evtchn(dev->evtchn);
-
-    free(dev->backend);
 
     gnttab_end_access(dev->info_ref);
     free_page(dev->info);
 
     unbind_evtchn(dev->evtchn);
 
+    free(dev->backend);
     free(dev->nodename);
     free(dev);
+}
+
+void pcifront_watches(void *opaque)
+{
+    XenbusState state;
+    char *err = NULL, *msg = NULL;
+    char *be_path, *be_state;
+    char* nodename = opaque ? opaque : "device/pci/0";
+    char path[strlen(nodename) + 9];
+    char fe_state[strlen(nodename) + 7];
+    xenbus_event_queue events = NULL;
+    
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    snprintf(fe_state, sizeof(fe_state), "%s/state", nodename);
+    
+    while (1) {
+        printk("pcifront_watches: waiting for backend path to happear %s\n", 
path);
+        xenbus_watch_path_token(XBT_NIL, path, path, &events);
+        while ((err = xenbus_read(XBT_NIL, path, &be_path)) != NULL) {
+            free(err);
+            xenbus_wait_for_watch(&events);
+        }
+        xenbus_unwatch_path_token(XBT_NIL, path, path);
+        printk("pcifront_watches: waiting for backend to get into the right 
state %s\n", be_path);
+        be_state = (char *) malloc(strlen(be_path) +  7);
+        snprintf(be_state, strlen(be_path) +  7, "%s/state", be_path);
+        xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
+        while ((err = xenbus_read(XBT_NIL, be_state, &msg)) != NULL || msg[0] 
> '4') {
+            free(msg);
+            free(err);
+            xenbus_wait_for_watch(&events);
+        }
+        xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
+        if (init_pcifront(NULL) == NULL) {
+            free(be_state);
+            free(be_path);
+            continue;
+        }
+        xenbus_watch_path_token(XBT_NIL, be_state, be_state, &events);
+        state = XenbusStateConnected;
+        printk("pcifront_watches: waiting for backend events %s\n", be_state);
+        while ((err = xenbus_wait_for_state_change(be_state, &state, &events)) 
== NULL &&
+               (err = xenbus_read(XBT_NIL, pcidev->backend, &msg)) == NULL) {
+            free(msg);
+            printk("pcifront_watches: backend state changed: %s %d\n", 
be_state, state);
+            if (state == XenbusStateReconfiguring) {
+                printk("pcifront_watches: writing %s %d\n", fe_state, 
XenbusStateReconfiguring);
+                if ((err = xenbus_switch_state(XBT_NIL, fe_state, 
XenbusStateReconfiguring)) != NULL) {
+                    printk("pcifront_watches: error changing state to %d: 
%s\n",
+                            XenbusStateReconfiguring, err);
+                    if (!strcmp(err, "ENOENT")) {
+                        xenbus_write(XBT_NIL, fe_state, "7");
+                        free(err);
+                    }
+                }
+            } else if (state == XenbusStateReconfigured) {
+                printk("pcifront_watches: writing %s %d\n", fe_state, 
XenbusStateConnected);
+                printk("pcifront_watches: changing state to %d\n", 
XenbusStateConnected);
+                if ((err = xenbus_switch_state(XBT_NIL, fe_state, 
XenbusStateConnected)) != NULL) {
+                    printk("pcifront_watches: error changing state to %d: 
%s\n",
+                            XenbusStateConnected, err);
+                    if (!strcmp(err, "ENOENT")) {
+                        xenbus_write(XBT_NIL, fe_state, "4");
+                        free(err);
+                    }
+                }
+            } else if (state == XenbusStateClosing)
+                break;
+        }
+        if (err)
+            printk("pcifront_watches: done waiting err=%s\n", err);
+        else
+            printk("pcifront_watches: done waiting\n");
+        xenbus_unwatch_path_token(XBT_NIL, be_state, be_state);
+        shutdown_pcifront(pcidev);
+        free(be_state);
+        free(be_path);
+        free(err);
+        pcidev = NULL;
+    }
+
+    xenbus_unwatch_path_token(XBT_NIL, path, path);
 }
 
 struct pcifront_dev *init_pcifront(char *_nodename)
@@ -64,6 +150,9 @@
     struct pcifront_dev *dev;
 
     char path[strlen(nodename) + 1 + 10 + 1];
+
+    if (!_nodename && pcidev)
+        return pcidev;
 
     printk("******************* PCIFRONT for %s **********\n\n\n", nodename);
 
@@ -173,6 +262,9 @@
 
     printk("**************************\n");
 
+    if (!_nodename)
+        pcidev = dev;
+
     return dev;
 
 error:
@@ -182,16 +274,25 @@
 
 void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, 
unsigned int bus, unsigned slot, unsigned int fun))
 {
-    char path[strlen(dev->backend) + 1 + 5 + 10 + 1];
-    int i, n;
+    char *path;
+    int i, n, len;
     char *s, *msg;
     unsigned int domain, bus, slot, fun;
 
-    snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
+    if (!dev)
+        dev = pcidev;
+    if (!dev)
+        dev = init_pcifront(NULL);
+    if (!dev)
+        return;
+
+    len = strlen(dev->backend) + 1 + 5 + 10 + 1;
+    path = (char *) malloc(len);
+    snprintf(path, len, "%s/num_devs", dev->backend);
     n = xenbus_read_integer(path);
 
     for (i = 0; i < n; i++) {
-        snprintf(path, sizeof(path), "%s/dev-%d", dev->backend, i);
+        snprintf(path, len, "%s/dev-%d", dev->backend, i);
         msg = xenbus_read(XBT_NIL, path, &s);
         if (msg) {
             printk("Error %s when reading the PCI root name at %s\n", msg, 
path);
@@ -205,8 +306,10 @@
         }
         free(s);
 
-        func(domain, bus, slot, fun);
+        if (func)
+            func(domain, bus, slot, fun);
     }
+    free(path);
 }
 
 void shutdown_pcifront(struct pcifront_dev *dev)
@@ -271,6 +374,9 @@
     char *s, *msg = NULL;
     unsigned int dom1, bus1, slot1, fun1;
 
+    if (!dev)
+        dev = pcidev;
+
     snprintf(path, sizeof(path), "%s/num_devs", dev->backend);
     n = xenbus_read_integer(path);
 
@@ -312,6 +418,8 @@
 
 void pcifront_op(struct pcifront_dev *dev, struct xen_pci_op *op)
 {
+    if (!dev)
+        dev = pcidev;
     dev->info->op = *op;
     /* Make sure info is written before the flag */
     wmb();
@@ -332,6 +440,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     memset(&op, 0, sizeof(op));
@@ -360,6 +470,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     memset(&op, 0, sizeof(op));
@@ -384,6 +496,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     memset(&op, 0, sizeof(op));
@@ -407,6 +521,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     memset(&op, 0, sizeof(op));
@@ -428,6 +544,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     if (n > SH_INFO_MAX_VEC)
@@ -460,6 +578,8 @@
 {
     struct xen_pci_op op;
 
+    if (!dev)
+        dev = pcidev;
     if (pcifront_physical_to_virtual(dev, &dom, &bus, &slot, &fun) < 0)
         return XEN_PCI_ERR_dev_not_found;
     memset(&op, 0, sizeof(op));
diff -r ac9d4ba48b83 extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Thu Nov 05 12:00:58 2009 +0000
+++ b/extras/mini-os/xenbus/xenbus.c    Fri Nov 13 17:53:03 2009 +0000
@@ -96,7 +96,10 @@
     if (!queue)
         queue = &xenbus_events;
     ret = xenbus_wait_for_watch_return(queue);
-    free(ret);
+    if (ret)
+        free(ret);
+    else
+        printk("unexpected path returned by watch\n");
 }
 
 char* xenbus_wait_for_value(const char* path, const char* value, 
xenbus_event_queue *queue)
diff -r ac9d4ba48b83 stubdom/pciutils.patch
--- a/stubdom/pciutils.patch    Thu Nov 05 12:00:58 2009 +0000
+++ b/stubdom/pciutils.patch    Fri Nov 13 17:53:03 2009 +0000
@@ -23,14 +23,6 @@
    PCI_ACCESS_MAX
  };
  
-@@ -63,6 +64,7 @@
-   int fd_rw;                          /* proc: fd opened read-write */
-   struct pci_dev *cached_dev;         /* proc: device the fd is for */
-   int fd_pos;                         /* proc: current position */
-+  void *minios;
- };
- 
- /* Initialize PCI access */
 --- pciutils-2.2.9.orig/lib/internal.h 2006-09-09 11:52:47.000000000 +0100
 +++ pciutils-2.2.9/lib/internal.h      2008-07-01 10:46:24.968202000 +0100
 @@ -37,4 +37,4 @@
@@ -72,7 +64,7 @@
  
 --- pciutils-2.2.9.orig/lib/minios.c   1970-01-01 01:00:00.000000000 +0100
 +++ pciutils-2.2.9/lib/minios.c        2008-07-01 12:31:40.554260000 +0100
-@@ -0,0 +1,113 @@
+@@ -0,0 +1,108 @@
 +/*
 + *    The PCI Library -- MiniOS PCI frontend access
 + *
@@ -95,24 +87,19 @@
 +static void
 +minios_init(struct pci_access *a)
 +{
-+  a->minios = init_pcifront(NULL);
-+  if (!a->minios)
++  if (!init_pcifront(NULL))
 +    a->warning("minios_init open failed");
 +}
 +
 +static void
 +minios_cleanup(struct pci_access *a)
 +{
-+  if (a->minios)
-+    shutdown_pcifront(a->minios);
++  shutdown_pcifront(NULL);
 +}
 +
 +static void
 +minios_scan(struct pci_access *a)
 +{
-+  if (!a->minios)
-+    return;
-+
 +  void func(unsigned int domain, unsigned int bus, unsigned int slot, 
unsigned int fun)
 +  {
 +    struct pci_dev *d = pci_alloc_dev(a);
@@ -125,7 +112,7 @@
 +    pci_link_dev(a, d);
 +  }
 +
-+  pcifront_scan(a->minios, func);
++  pcifront_scan(NULL, func);
 +}
 +
 +static int
@@ -134,17 +121,17 @@
 +  unsigned int val;
 +  switch (len) {
 +    case 1:
-+      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++      if (pcifront_conf_read(NULL, d->domain, d->bus, d->dev, d->func, pos, 
len, &val))
 +        return 0;
 +      * buf = val;
 +      return 1;
 +    case 2:
-+      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++      if (pcifront_conf_read(NULL, d->domain, d->bus, d->dev, d->func, pos, 
len, &val))
 +        return 0;
 +      *(u16 *) buf = cpu_to_le16((u16) val);
 +      return 1;
 +    case 4:
-+      if (pcifront_conf_read(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, &val))
++      if (pcifront_conf_read(NULL, d->domain, d->bus, d->dev, d->func, pos, 
len, &val))
 +        return 0;
 +      *(u32 *) buf = cpu_to_le32((u32) val);
 +      return 1;
@@ -170,7 +157,7 @@
 +    default:
 +      return pci_generic_block_write(d, pos, buf, len);
 +  }
-+  return !pcifront_conf_write(d->access->minios, d->domain, d->bus, d->dev, 
d->func, pos, len, val);
++  return !pcifront_conf_write(NULL, d->domain, d->bus, d->dev, d->func, pos, 
len, val);
 +}
 +
 +struct pci_methods pm_minios = {

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] pcifront: implement dynamic connections and disconnections, Stefano Stabellini <=