]> xenbits.xen.org Git - xenclient/kernel.git/commitdiff
FLR - intermediate checkin 2 3/25 - unified ID lists, fixed flr
authorRoss Philipson <ross.philipson@citrix.com>
Wed, 25 Mar 2009 13:25:01 +0000 (09:25 -0400)
committerRoss Philipson <ross.philipson@citrix.com>
Wed, 25 Mar 2009 13:25:01 +0000 (09:25 -0400)
logic routine.

 Changes to be committed:
modified:   drivers/xen/pciback/pci_stub.c
modified:   drivers/xen/pciback/pciback.h
modified:   drivers/xen/pciback/pciback_ops.c

drivers/xen/pciback/pci_stub.c
drivers/xen/pciback/pciback.h
drivers/xen/pciback/pciback_ops.c

index bc6af30b4641db5871022272e0844d1a4ca1c5d2..55932a4278632d4f1070e29c06d69572013fb2a1 100644 (file)
@@ -26,8 +26,16 @@ module_param_named(sbr, pci_devs_use_sbr, charp, S_IRUGO);
 static char *pci_devs_use_d3r = NULL;
 module_param_named(d3r, pci_devs_use_d3r, charp, S_IRUGO);
 
+/* Device id list holding different device type listings
+ * for hiding devices and reset logic.
+ */
+#define PCIBACK_ID_TYPE_HIDE  1
+#define PCIBACK_ID_TYPE_SBR   2
+#define PCIBACK_ID_TYPE_D3R   3
+
 struct pcistub_device_id {
        struct list_head slot_list;
+       int type;
        int domain;
        unsigned char bus;
        unsigned int devfn;
@@ -35,11 +43,6 @@ struct pcistub_device_id {
 static LIST_HEAD(pcistub_device_ids);
 static DEFINE_SPINLOCK(device_ids_lock);
 
-/* reset usage lists */
-static LIST_HEAD(pcistub_sbr_device_ids);
-static LIST_HEAD(pcistub_d3r_device_ids);
-static DEFINE_SPINLOCK(device_reset_ids_lock);
-
 struct pcistub_device {
        struct kref kref;
        struct list_head dev_list;
@@ -315,26 +318,22 @@ static int __devinit pcistub_match_one(struct pci_dev *dev,
        return 0;
 }
 
-static int __devinit pcistub_match(struct pci_dev *dev, struct list_head *list)
+static int __devinit pcistub_match(struct pci_dev *dev, int type)
 {
        struct pcistub_device_id *pdev_id;
        unsigned long flags;
        int found = 0;
-       spinlock_t *lock;
 
-       if (list == &pcistub_device_ids)
-               lock = &device_ids_lock;
-       else
-               lock = &device_reset_ids_lock;
-
-       spin_lock_irqsave(lock, flags);
-       list_for_each_entry(pdev_id, list, slot_list) {
+       spin_lock_irqsave(&device_ids_lock, flags);
+       list_for_each_entry(pdev_id, &pcistub_device_ids, slot_list) {
+               if (pdev_id->type != type)
+                       continue;
                if (pcistub_match_one(dev, pdev_id)) {
                        found = 1;
                        break;
                }
        }
-       spin_unlock_irqrestore(lock, flags);
+       spin_unlock_irqrestore(&device_ids_lock, flags);
 
        return found;
 }
@@ -385,8 +384,8 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
      * values if SBR/D3R reset logic was requested.
         */
        pciback_classify_device(dev);
-       dev_data->use_sbr = pcistub_match(dev, &pcistub_sbr_device_ids);
-       dev_data->use_d3r = pcistub_match(dev, &pcistub_d3r_device_ids);
+       dev_data->use_sbr = pcistub_match(dev, PCIBACK_ID_TYPE_SBR);
+       dev_data->use_d3r = pcistub_match(dev, PCIBACK_ID_TYPE_D3R);
 
        /* Store the config space here where the device is off and ready to be 
         * exported before any FLRs or other resets are done
@@ -490,7 +489,7 @@ static int __devinit pcistub_probe(struct pci_dev *dev,
 
        dev_dbg(&dev->dev, "probing...\n");
 
-       if (pcistub_match(dev, &pcistub_device_ids)) {
+       if (pcistub_match(dev, PCIBACK_ID_TYPE_HIDE)) {
 
                if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL
                    && dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
@@ -614,7 +613,7 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
        return -EINVAL;
 }
 
-static int pcistub_device_id_add(int domain, int bus, int slot, int func)
+static int pcistub_device_id_add(int domain, int bus, int slot, int func, int type)
 {
        struct pcistub_device_id *pci_dev_id;
        unsigned long flags;
@@ -623,12 +622,13 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
        if (!pci_dev_id)
                return -ENOMEM;
 
+       pci_dev_id->type = type;
        pci_dev_id->domain = domain;
        pci_dev_id->bus = bus;
        pci_dev_id->devfn = PCI_DEVFN(slot, func);
 
-       pr_debug("pciback: wants to seize %04x:%02x:%02x.%01x\n",
-                domain, bus, slot, func);
+       pr_debug("pciback: adding device ID type: %d for %04x:%02x:%02x.%01x\n",
+                type, domain, bus, slot, func);
 
        spin_lock_irqsave(&device_ids_lock, flags);
        list_add_tail(&pci_dev_id->slot_list, &pcistub_device_ids);
@@ -724,52 +724,6 @@ out:
        return err;
 }
 
-static int pcistub_device_id_sbr_add(int domain, int bus, int slot, int func)
-{
-       struct pcistub_device_id *pci_dev_id;
-       unsigned long flags;
-
-       pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
-       if (!pci_dev_id)
-               return -ENOMEM;
-
-       pci_dev_id->domain = domain;
-       pci_dev_id->bus = bus;
-       pci_dev_id->devfn = PCI_DEVFN(slot, func);
-
-       pr_debug("pciback: adding sbr device %04x:%02x:%02x.%01x\n",
-                domain, bus, slot, func);
-
-       spin_lock_irqsave(&device_reset_ids_lock, flags);
-       list_add_tail(&pci_dev_id->slot_list, &pcistub_sbr_device_ids);
-       spin_unlock_irqrestore(&device_reset_ids_lock, flags);
-
-       return 0;
-}
-
-static int pcistub_device_id_d3r_add(int domain, int bus, int slot, int func)
-{
-       struct pcistub_device_id *pci_dev_id;
-       unsigned long flags;
-
-       pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
-       if (!pci_dev_id)
-               return -ENOMEM;
-
-       pci_dev_id->domain = domain;
-       pci_dev_id->bus = bus;
-       pci_dev_id->devfn = PCI_DEVFN(slot, func);
-
-       pr_debug("pciback: adding d3r device %04x:%02x:%02x.%01x\n",
-                domain, bus, slot, func);
-
-       spin_lock_irqsave(&device_reset_ids_lock, flags);
-       list_add_tail(&pci_dev_id->slot_list, &pcistub_d3r_device_ids);
-       spin_unlock_irqrestore(&device_reset_ids_lock, flags);
-
-       return 0;
-}
-
 static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
                                size_t count)
 {
@@ -780,7 +734,7 @@ static ssize_t pcistub_slot_add(struct device_driver *drv, const char *buf,
        if (err)
                goto out;
 
-       err = pcistub_device_id_add(domain, bus, slot, func);
+       err = pcistub_device_id_add(domain, bus, slot, func, PCIBACK_ID_TYPE_HIDE);
 
 out:
        if (!err)
@@ -989,14 +943,14 @@ static ssize_t pcistub_resets(struct device_driver *drv, const char *buf,
                                   size_t count)
 {
        int domain, bus, slot, func;
-       int is_sbr, err;
+       int type, err;
 
        /* string begins with reset type specifier sbr=|dr3= */
        if (!strncmp(buf, "sbr=", 4)) {
-               is_sbr = 1;
+               type = PCIBACK_ID_TYPE_SBR;
                buf += 4;
        } else if (!strncmp(buf, "d3r=", 4)) {
-               is_sbr = 0;
+               type = PCIBACK_ID_TYPE_D3R;
                buf += 4;
        } else {
                err = -EINVAL;
@@ -1007,10 +961,7 @@ static ssize_t pcistub_resets(struct device_driver *drv, const char *buf,
        if (err)
                goto out;
 
-       if (is_sbr)
-               err = pcistub_device_id_sbr_add(domain, bus, slot, func);
-       else
-               err = pcistub_device_id_d3r_add(domain, bus, slot, func);
+       err = pcistub_device_id_add(domain, bus, slot, func, type);
 
 out:
        if (!err)
@@ -1056,15 +1007,15 @@ static int __init pcistub_init(void)
        int err = 0;
 
        /* Parse device lists for hide, sbr, and d3r */
-       err = pciback_parse_device_params(pci_devs_to_hide, pcistub_device_id_add);
+       err = pciback_parse_device_params(pci_devs_to_hide, PCIBACK_ID_TYPE_HIDE, pcistub_device_id_add);
        if (err)
                goto out;
 
-       err = pciback_parse_device_params(pci_devs_use_sbr, pcistub_device_id_sbr_add);
+       err = pciback_parse_device_params(pci_devs_use_sbr, PCIBACK_ID_TYPE_SBR, pcistub_device_id_add);
        if (err)
                goto out;
 
-       err = pciback_parse_device_params(pci_devs_use_d3r, pcistub_device_id_d3r_add);
+       err = pciback_parse_device_params(pci_devs_use_d3r, PCIBACK_ID_TYPE_D3R, pcistub_device_id_add);
        if (err)
                goto out;
 
index e908e7fa7825a127a974d14a010a7381f0b8da88..7086ca6fae89652d980b8ea3390e443332ad0eea 100644 (file)
@@ -108,10 +108,10 @@ int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev,
 void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev);
 struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
                                    unsigned int domain, unsigned int bus,
-                                   unsigned int devfn);
+                                       unsigned int devfn);
 int pciback_init_devices(struct pciback_device *pdev);
 int pciback_publish_pci_roots(struct pciback_device *pdev,
-                             publish_pci_root_cb cb);
+                                       publish_pci_root_cb cb);
 void pciback_release_devices(struct pciback_device *pdev);
 
 /* Handles events from front-end */
@@ -119,7 +119,8 @@ irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs);
 void pciback_do_op(void *data);
 
 /* Parse and load device specific module parameters */
-int pciback_parse_device_params(const char *device_args, int (*add_func) (int domain, int bus, int slot, int func));
+int pciback_parse_device_params(const char *device_args, int type,
+                                       int (*add_func) (int domain, int bus, int slot, int func, int type));
 
 int pciback_xenbus_register(void);
 void pciback_xenbus_unregister(void);
index 09a027cbbd59f1ccfc9b06bb6230eb8139b4f1c2..07fae104bfae62f53bd5f35a5f1be1d0e556346e 100644 (file)
@@ -248,7 +248,7 @@ static int pciback_do_secondary_bus_reset(struct pci_dev *dev)
        goto cleanup;
 
 failed:
-       err = -ENXIO
+       err = -ENXIO;
        dev_warn(&dev->dev, 
                "secondary bus reset failed for device - all functions need to be co-assigned!\n");
 
@@ -260,74 +260,61 @@ cleanup:
        return err;
 }
 
-/* This function is used to do a function level reset on a singe device/function.
- * FLRs must be done on devices before they are unassigned from one domain and
- * passed through to another. The preferred method is to do an actual FLR on the
- * device but the functionality may not be present or exposed. In the later case
- * we attempt to locate the capability even though it is not chained into the 
- * capabilities list.
+/* This function is used to do a function level reset on a singe 
+ * device/function. FLRs must be done on devices before they are 
+ * unassigned from one domain and passed through to another. The 
+ * preferred method is to do an actual FLR on the device but the 
+ * functionality may not be present or exposed. In the later case
+ * we attempt to locate the capability even though it is not 
+ * chained into the capabilities list.
  *
- * In some cases, there are no TODO...
+ * In some cases, there is no way to perform the actual FLR so we 
+ * fall back to some alternate methods (which are not as effective
+ * or useful).
  */
 void pciback_flr_device(struct pci_dev *dev)
 {
        struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
        int err = 0;
 
-       if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT) {
-               if (dev_data->exp_flr_offset != 0) {
+       do {
+               /* First, always try to do an FLR */
+               if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT &&
+                       dev_data->exp_flr_offset != 0) {
                        pciback_do_pcie_flr(dev, dev_data->exp_flr_offset);
-                       goto out;
+                       break;
                }
-               
-               if (dev->bus->number == 0) {
-                       err = pciback_do_vendor_specific_reset(dev);
-                       if (err && dev_data->use_d3r)
-                               err = pciback_do_dstate_transition_reset(dev);
-                       if (err) {
-                               dev_warn(&dev->dev, "FLR functionality not supported; "
-                                               "attempts to use vendor specific FLR and D-state transitions failed; "
-                                               "FLR not performed for device\n");
-                       }
-                               
-               }
-               else if (dev_data->use_sbr) {
-                       err = pciback_do_dstate_transition_reset(dev);
-                       if (err) {
-                               dev_warn(&dev->dev, "FLR functionality not supported; "
-                                               "attempts to use secondary bus reset failed; "
-                                               "FLR not performed for device\n");
-                       }
-               }
-       }
-       else if (dev_data->dev_type == PCIBACK_TYPE_PCI) {
-               if (dev_data->af_flr_offset != 0) {
+               if (dev_data->dev_type == PCIBACK_TYPE_PCI &&
+                       dev_data->af_flr_offset != 0) {
                        pciback_do_pci_flr(dev, dev_data->af_flr_offset);
-                       goto out;
+                       break;
                }
+               
+               /* Next for integrated devices on the host bus 0, try some other methods */
                if (dev->bus->number == 0) {
                        err = pciback_do_vendor_specific_reset(dev);
                        if (err && dev_data->use_d3r)
                                err = pciback_do_dstate_transition_reset(dev);
-                       if (err) {
+                       if (err)
                                dev_warn(&dev->dev, "FLR functionality not supported; "
-                                               "attempts to use vendor specific FLR and D-state transitions failed; "
-                                               "FLR not performed for device\n");
-                       }
+                                               "attempts to use vendor FLR or D-states failed\n");
+                       break;
                }
-               else {
-                       dev_warn(&dev->dev, "FLR functionality not supported; "
-                                       "no secondary bus reset functionality available; "
-                                       "FLR not performed for device\n");
+
+               /* Else for PCIe devices behind root port, attempt a secondary bus reset */
+               if (dev_data->dev_type == PCIBACK_TYPE_PCIe_ENDPOINT && dev_data->use_sbr) {
+                       err = pciback_do_secondary_bus_reset(dev);
+                       if (err)
+                               dev_warn(&dev->dev, "FLR functionality not supported; "
+                                               "attempts to use secondary bus reset failed;\n");
+                       break;
                }
-       }
-       else {
-               dev_warn(&dev->dev, 
-                       "FLR not being used for bridge devices.\n");
-       }
-       
-       /* no return, trace warning about activity */
-out:
+
+               err = -ENODEV;          
+       } while (0);
+
+       if (err)
+               dev_warn(&dev->dev, "FLR not performed for device\n");
 }
 
 /* Helper used to location the FLR capabilities for a PCIe device.
@@ -515,7 +502,7 @@ irqreturn_t pciback_handle_event(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-int pciback_parse_device_params(const char *device_args, int (*add_func) (int domain, int bus, int slot, int func))
+int pciback_parse_device_params(const char *device_args, int type, int (*add_func) (int domain, int bus, int slot, int func, int type))
 {
        int pos = 0;
        int err = 0;
@@ -538,7 +525,7 @@ int pciback_parse_device_params(const char *device_args, int (*add_func) (int do
                                        goto parse_error;
                        }
 
-                       err = add_func(domain, bus, slot, func);
+                       err = add_func(domain, bus, slot, func, type);
                        if (err)
                                goto out;