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 3/5] take 2: PCIe IO space multiplexing: Linux part:

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 3/5] take 2: PCIe IO space multiplexing: Linux part: guestdev kernel paremeter enhance
From: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Date: Fri, 17 Apr 2009 17:09:20 +0900
Cc: shimada-yxb@xxxxxxxxxxxxxxx, Ian.Jackson@xxxxxxxxxxxxx, Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
Delivery-date: Fri, 17 Apr 2009 01:13:55 -0700
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: Mutt/1.5.18 (2008-05-17)
pci/guestdev: enhance guestdev to accept +iomul.

enhance guestdev to accept +iomul and use it.

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -577,11 +577,15 @@ running once the system is up.
 
        guestdev=       [PCI,ACPI]
                        Format: {<device path>|<sbdf>}][,{<device 
path>|<sbdf>}[,...]]
-                       Format of device path: 
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]]
-                       Format of sbdf: [<segment>:]<bus>:<dev>.<func>
+                       Format of device path: 
<hid>[:<uid>]-<dev>.<func>[-<dev>.<func>[,...]][+iomul]
+                       Format of sbdf: [<segment>:]<bus>:<dev>.<func>[+iomul]
                        Specifies PCI device for guest domain.
                        If PCI-PCI bridge is specified, all PCI devices
                        behind PCI-PCI bridge are reserved.
+                       +iomul means that this PCI function will share
+                       IO ports with other +iomul functions under same
+                       switch. NOTE: if +iomul is specfied, all the functions
+                       of the device will share IO ports.
 
        guestiomuldev=  [PCI]
                        Format: [sbd][,<sbd>][,...]
diff --git a/drivers/pci/guestdev.c b/drivers/pci/guestdev.c
--- a/drivers/pci/guestdev.c
+++ b/drivers/pci/guestdev.c
@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2008, 2009 NEC Corporation.
+ * Copyright (c) 2009 Isaku Yamahata
+ *                    VA Linux Systems Japan K.K.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -38,8 +40,11 @@
 #define GUESTDEV_FLAG_DEVICEPATH 0x1
 #define GUESTDEV_FLAG_SBDF 0x2
 
+#define GUESTDEV_OPT_IOMUL     0x1
+
 struct guestdev {
        int flags;
+       int options;
        struct list_head root_list;
        union {
                struct devicepath {
@@ -276,6 +281,7 @@ struct guestdev __init *pci_copy_guestde
        memset(gdev, 0, sizeof(*gdev));
        INIT_LIST_HEAD(&gdev->root_list);
        gdev->flags = gdev_src->flags;
+       gdev->options = gdev_src->options;
        strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid);
        strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid);
        gdev->u.devicepath.seg = gdev_src->u.devicepath.seg;
@@ -309,7 +315,7 @@ allocate_err_end:
 }
 
 /* Make guestdev from path strings */
-static int __init pci_make_devicepath_guestdev(char *path_str)
+static int __init pci_make_devicepath_guestdev(char *path_str, int options)
 {
        char hid[HID_LEN + 1], uid[UID_LEN + 1];
        char *sp, *ep;
@@ -337,6 +343,7 @@ static int __init pci_make_devicepath_gu
        memset(gdev_org, 0, sizeof(*gdev_org));
        INIT_LIST_HEAD(&gdev_org->root_list);
        gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH;
+       gdev_org->options = options;
        strcpy(gdev_org->u.devicepath.hid, hid);
        strcpy(gdev_org->u.devicepath.uid, uid);
        gdev_org->u.devicepath.seg = INVALID_SEG;
@@ -436,7 +443,7 @@ end:
        return ret_val;
 }
 
-static int __init pci_make_sbdf_guestdev(char* str)
+static int __init pci_make_sbdf_guestdev(char* str, int options)
 {
        struct guestdev *gdev;
        int seg, bus, dev, func;
@@ -453,6 +460,7 @@ static int __init pci_make_sbdf_guestdev
        }
        INIT_LIST_HEAD(&gdev->root_list);
        gdev->flags = GUESTDEV_FLAG_SBDF;
+       gdev->options = options;
        gdev->u.sbdf.seg = seg;
        gdev->u.sbdf.bus = bus;
        gdev->u.sbdf.dev = dev;
@@ -461,11 +469,31 @@ static int __init pci_make_sbdf_guestdev
        return 0;
 }
 
+static int __init pci_parse_options(const char *str)
+{
+       int options = 0;
+       char *ep;
+
+       while (str) {
+               str++;
+               ep = strchr(str, '+');
+               if (ep)
+                       ep = '\0';      /* Chop */
+
+               if (!strcmp(str, "iomul"))
+                       options |= GUESTDEV_OPT_IOMUL;
+
+               str = ep;
+       }
+       return options;
+}
+
 /* Parse guestdev parameter */
 static int __init pci_parse_guestdev(void)
 {
        int len;
-       char *sp, *ep;
+       char *sp, *ep, *op;
+       int options;
        struct list_head *head;
        struct guestdev *gdev;
        char path_str[GUESTDEV_STR_MAX];
@@ -482,16 +510,26 @@ static int __init pci_parse_guestdev(voi
                /* Chop */
                if (ep)
                        *ep = '\0';
-               ret_val = pci_make_sbdf_guestdev(sp);
+               options = 0;
+               op = strchr(sp, '+');
+               if (op && (!ep || op < ep)) {
+                       options = pci_parse_options(op);
+                       *op = '\0';     /* Chop */
+               }
+               ret_val = pci_make_sbdf_guestdev(sp, options);
                if (ret_val == -EINVAL) {
                        if (pci_check_extended_guestdev_format(sp)) {
-                               ret_val = pci_make_devicepath_guestdev(sp);
+                               ret_val = pci_make_devicepath_guestdev(
+                                       sp, options);
                                if (ret_val && ret_val != -EINVAL)
                                        break;
                        }
                } else if (ret_val)
                        break;
-               sp = ep + 1;
+
+               if (ep)
+                       ep++;
+               sp = ep;
        } while (ep);
 
        list_for_each(head, &guestdev_list) {
@@ -532,8 +570,21 @@ static void pci_free_sbdf(struct pcidev_
 }
 
 /* Does PCI device belong to sub tree specified by guestdev with device path? 
*/
+typedef int (*pci_node_match_t)(const struct devicepath_node *gdev_node,
+                               const struct pcidev_sbdf_node *sbdf_node,
+                               int options);
+
+static int pci_node_match(const struct devicepath_node *gdev_node,
+                         const struct pcidev_sbdf_node *sbdf_node,
+                         int options_unused)
+{
+       return (gdev_node->dev == sbdf_node->dev &&
+               gdev_node->func == sbdf_node->func);
+}
+
 static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev,
-                                       struct pcidev_sbdf *sbdf)
+                                        struct pcidev_sbdf *sbdf,
+                                        pci_node_match_t match)
 {
        int seg, bbn;
        struct devicepath_node *gdev_node;
@@ -566,8 +617,7 @@ static int pci_is_in_devicepath_sub_tree
        while (gdev_node) {
                if (!sbdf_node)
                        return FALSE;
-               if (gdev_node->dev != sbdf_node->dev ||
-                   gdev_node->func != sbdf_node->func)
+               if (!match(gdev_node, sbdf_node, gdev->options))
                        return FALSE;
                gdev_node = gdev_node->child;
                sbdf_node = sbdf_node->child;
@@ -616,16 +666,29 @@ err_end:
 }
 
 /* Does PCI device belong to sub tree specified by guestdev with sbdf? */
-static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev)
+typedef int (*pci_sbdf_match_t)(const struct guestdev *gdev,
+                               const  struct pci_dev *dev);
+
+static int pci_sbdf_match(const struct guestdev *gdev,
+                         const struct pci_dev *dev)
 {
        int seg, bus;
+
+       if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
+               return FALSE;
+
+       return gdev->u.sbdf.seg == seg &&
+               gdev->u.sbdf.bus == bus &&
+               gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
+               gdev->u.sbdf.func == PCI_FUNC(dev->devfn);
+}
+
+static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev,
+                                  pci_sbdf_match_t match)
+{
        BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF));
        for (;;) {
-               if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
-                       continue;
-               if (gdev->u.sbdf.seg == seg && gdev->u.sbdf.bus == bus &&
-                       gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) &&
-                       gdev->u.sbdf.func == PCI_FUNC(dev->devfn))
+               if (match(gdev, dev))
                        return TRUE;
                if (!dev->bus || !dev->bus->self)
                        break;
@@ -635,7 +698,8 @@ static int pci_is_in_sbdf_sub_tree(struc
 }
 
 /* Does PCI device belong to sub tree specified by guestdev parameter? */
-int pci_is_guestdev(struct pci_dev *dev)
+static int __pci_is_guestdev(struct pci_dev *dev, pci_node_match_t node_match,
+                            pci_sbdf_match_t sbdf_match)
 {
        struct guestdev *gdev;
        struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL;
@@ -655,13 +719,14 @@ int pci_is_guestdev(struct pci_dev *dev)
                                if (!pci_get_sbdf_from_pcidev(dev, sbdf))
                                        goto out;
                        }
-                       if (pci_is_in_devicepath_sub_tree(gdev, sbdf)) {
+                       if (pci_is_in_devicepath_sub_tree(gdev, sbdf,
+                                                         node_match)) {
                                result = TRUE;
                                goto out;
                        }
                        break;
                case GUESTDEV_FLAG_SBDF:
-                       if (pci_is_in_sbdf_sub_tree(gdev, dev)) {
+                       if (pci_is_in_sbdf_sub_tree(gdev, dev, sbdf_match)) {
                                result = TRUE;
                                goto out;
                        }
@@ -675,6 +740,11 @@ out:
                pci_free_sbdf(sbdf);
        return result;
 }
+
+int pci_is_guestdev(struct pci_dev *dev)
+{
+       return __pci_is_guestdev(dev, pci_node_match, pci_sbdf_match);
+}
 EXPORT_SYMBOL(pci_is_guestdev);
 
 static int __init pci_set_reassign_resources(char *str)
@@ -694,6 +764,43 @@ int pci_is_reassigndev(struct pci_dev *d
 }
 EXPORT_SYMBOL(pci_is_reassigndev);
 
+#ifdef CONFIG_PCI_IOMULTI
+static int pci_iomul_node_match(const struct devicepath_node *gdev_node,
+                               const struct pcidev_sbdf_node *sbdf_node,
+                               int options)
+{
+       return (options & GUESTDEV_OPT_IOMUL) &&
+               ((gdev_node->child != NULL &&
+                 sbdf_node->child != NULL &&
+                 gdev_node->dev == sbdf_node->dev &&
+                 gdev_node->func == sbdf_node->func) ||
+                (gdev_node->child == NULL &&
+                 sbdf_node->child == NULL &&
+                 gdev_node->dev == sbdf_node->dev));
+}
+
+static int pci_iomul_sbdf_match(const struct guestdev *gdev,
+                               const struct pci_dev *dev)
+{
+       int seg, bus;
+
+       if (sscanf(dev->dev.bus_id, "%04x:%02x", &seg, &bus) != 2)
+               return FALSE;
+
+       return (gdev->options & GUESTDEV_OPT_IOMUL) &&
+               gdev->u.sbdf.seg == seg &&
+               gdev->u.sbdf.bus == bus &&
+               gdev->u.sbdf.dev == PCI_SLOT(dev->devfn);
+}
+
+int pci_is_iomuldev(struct pci_dev *dev)
+{
+       return __pci_is_guestdev(dev,
+                                pci_iomul_node_match, pci_iomul_sbdf_match);
+}
+EXPORT_SYMBOL_GPL(pci_is_iomuldev);
+#endif /* CONFIG_PCI_IOMULTI */
+
 /* Check whether the devicepath exists under the pci root bus */
 static int __init pci_check_devicepath_exists(
                struct guestdev *gdev, struct pci_bus *bus)
diff --git a/drivers/pci/iomulti.c b/drivers/pci/iomulti.c
--- a/drivers/pci/iomulti.c
+++ b/drivers/pci/iomulti.c
@@ -27,6 +27,7 @@
 #include <asm/setup.h>
 #include <asm/uaccess.h>
 
+#include "pci.h"
 #include "iomulti.h"
 
 #define PCI_NUM_BARS           6
@@ -423,7 +424,8 @@ static int pci_is_iomul_dev_param(struct
                        break;
        }
 
-       return 0;
+       /* check guestcev=<device>+iomul option */
+       return pci_is_iomuldev(pdev);
 }
 
 /*
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -105,9 +105,13 @@ pci_match_one_device(const struct pci_de
 extern void pci_disable_bridge_window(struct pci_dev *dev);
 #endif
 #ifdef CONFIG_PCI_GUESTDEV
+extern int pci_is_guestdev(struct pci_dev *dev);
 extern int pci_is_reassigndev(struct pci_dev *dev);
+extern int pci_is_iomuldev(struct pci_dev *dev);
 #else
-#define pci_is_reassigndev(dev) 0
+#define pci_is_guestdev(dev)   0
+#define pci_is_reassigndev(dev)        0
+#define pci_is_iomuldev(dev)   0
 #endif
 
 #ifdef CONFIG_PCI_GUESTDEV

Attachment: guestdev-iomul.patch
Description: Text Data

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH 3/5] take 2: PCIe IO space multiplexing: Linux part: guestdev kernel paremeter enhance, Isaku Yamahata <=