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-changelog

[Xen-changelog] [xen-unstable] pcifront: implement dynamic connections a

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] pcifront: implement dynamic connections and disconnections
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 13 Nov 2009 14:05:17 -0800
Delivery-date: Fri, 13 Nov 2009 14:05:30 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1258149510 0
# Node ID dd951d96304a8c036e3f2a076a7b1240696f9032
# Parent  377b7a8e0e0af8367b445cc317203ab1f97f9bdd
pcifront: implement dynamic connections and disconnections

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>
---
 extras/mini-os/include/pcifront.h |    1 
 extras/mini-os/main.c             |    2 
 extras/mini-os/pcifront.c         |  136 +++++++++++++++++++++++++++++++++++---
 extras/mini-os/xenbus/xenbus.c    |    5 +
 stubdom/pciutils.patch            |   20 -----
 5 files changed, 135 insertions(+), 29 deletions(-)

diff -r 377b7a8e0e0a -r dd951d96304a extras/mini-os/include/pcifront.h
--- a/extras/mini-os/include/pcifront.h Fri Nov 13 21:54:44 2009 +0000
+++ b/extras/mini-os/include/pcifront.h Fri Nov 13 21:58:30 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 377b7a8e0e0a -r dd951d96304a extras/mini-os/main.c
--- a/extras/mini-os/main.c     Fri Nov 13 21:54:44 2009 +0000
+++ b/extras/mini-os/main.c     Fri Nov 13 21:58:30 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 @@ static void call_main(void *p)
 #endif
     init_fs_frontend();
 #endif
+    create_thread("pcifront", pcifront_watches, NULL);
 
 #ifdef CONFIG_QEMU
     /* Fetch argc, argv from XenStore */
diff -r 377b7a8e0e0a -r dd951d96304a extras/mini-os/pcifront.c
--- a/extras/mini-os/pcifront.c Fri Nov 13 21:54:44 2009 +0000
+++ b/extras/mini-os/pcifront.c Fri Nov 13 21:58:30 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 @@ void pcifront_handler(evtchn_port_t port
 
 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 *init_pcifront(char 
     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 @@ done:
 
     printk("**************************\n");
 
+    if (!_nodename)
+        pcidev = dev;
+
     return dev;
 
 error:
@@ -182,16 +274,25 @@ error:
 
 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 @@ void pcifront_scan(struct pcifront_dev *
         }
         free(s);
 
-        func(domain, bus, slot, fun);
-    }
+        if (func)
+            func(domain, bus, slot, fun);
+    }
+    free(path);
 }
 
 void shutdown_pcifront(struct pcifront_dev *dev)
@@ -270,6 +373,9 @@ int pcifront_physical_to_virtual (struct
     int i, n;
     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 @@ int pcifront_physical_to_virtual (struct
 
 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 @@ int pcifront_conf_read(struct pcifront_d
 {
     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 @@ int pcifront_conf_write(struct pcifront_
 {
     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 @@ int pcifront_enable_msi(struct pcifront_
 {
     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 @@ int pcifront_disable_msi(struct pcifront
 {
     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 @@ int pcifront_enable_msix(struct pcifront
 {
     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 @@ int pcifront_disable_msix(struct pcifron
 {
     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 377b7a8e0e0a -r dd951d96304a extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Fri Nov 13 21:54:44 2009 +0000
+++ b/extras/mini-os/xenbus/xenbus.c    Fri Nov 13 21:58:30 2009 +0000
@@ -96,7 +96,10 @@ void xenbus_wait_for_watch(xenbus_event_
     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 377b7a8e0e0a -r dd951d96304a stubdom/pciutils.patch
--- a/stubdom/pciutils.patch    Fri Nov 13 21:54:44 2009 +0000
+++ b/stubdom/pciutils.patch    Fri Nov 13 21:58:30 2009 +0000
@@ -23,14 +23,6 @@ diff -urN pciutils-2.2.9.orig/lib/access
    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 @@
@@ -95,24 +87,19 @@ diff -urN pciutils-2.2.9.orig/lib/access
 +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 @@ diff -urN pciutils-2.2.9.orig/lib/access
 +    pci_link_dev(a, d);
 +  }
 +
-+  pcifront_scan(a->minios, func);
++  pcifront_scan(NULL, func);
 +}
 +
 +static int
@@ -134,17 +121,17 @@ diff -urN pciutils-2.2.9.orig/lib/access
 +  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 @@ diff -urN pciutils-2.2.9.orig/lib/access
 +    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-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] pcifront: implement dynamic connections and disconnections, Xen patchbot-unstable <=