diff options
| -rw-r--r-- | pci-msi-fix.patch | 172 |
1 files changed, 148 insertions, 24 deletions
diff --git a/pci-msi-fix.patch b/pci-msi-fix.patch index 5f000ccc930b5c..b713130a84109e 100644 --- a/pci-msi-fix.patch +++ b/pci-msi-fix.patch @@ -1,7 +1,39 @@ +From foo@baz Wed Nov 27 10:33:53 PST 2013 +Date: Wed, 27 Nov 2013 10:33:53 -0800 +To: Greg KH <gregkh@linuxfoundation.org> +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Subject: [PATCH] PCI: export MSI mode using attributes, not kobjects + +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + +The PCI MSI sysfs code is a mess with kobjects for things that don't +really need to be kobjects. This patch creates attributes dynamically +for the MSI interrupts instead of using kobjects. + +Note, this removes a directory from the current MSI interrupt sysfs +code: + +old MSI kobjects: +pci_device + └── msi_irqs + └── 40 + └── mode + +new MSI attributes: +pci_device + └── msi_irqs + └── 40 + +As there was only one file "mode" with the kobject model, the interrupt +number is now a file that returns the "mode" of the interrupt (msi vs. +msix). + +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> + --- - drivers/pci/msi.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - include/linux/pci.h | 1 - 2 files changed, 86 insertions(+) + drivers/pci/msi.c | 152 +++++++++++++++++++++++++--------------------------- + include/linux/pci.h | 2 + 2 files changed, 76 insertions(+), 78 deletions(-) --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -38,22 +70,66 @@ } static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) -@@ -527,13 +546,79 @@ static struct kobj_type msi_irq_ktype = - .default_attrs = msi_irq_default_attrs, - }; +@@ -471,96 +490,79 @@ void pci_restore_msi_state(struct pci_de + } + EXPORT_SYMBOL_GPL(pci_restore_msi_state); +- +-#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) +-#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) +- +-struct msi_attribute { +- struct attribute attr; +- ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, +- char *buf); +- ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, +- const char *buf, size_t count); +-}; +- +-static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, +static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ + char *buf) + { +- return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); +-} +- +-static ssize_t msi_irq_attr_show(struct kobject *kobj, +- struct attribute *attr, char *buf) +-{ +- struct msi_attribute *attribute = to_msi_attr(attr); +- struct msi_desc *entry = to_msi_desc(kobj); +- +- if (!attribute->show) +- return -EIO; +- +- return attribute->show(entry, attribute, buf); +-} +- +-static const struct sysfs_ops msi_irq_sysfs_ops = { +- .show = msi_irq_attr_show, +-}; +- +-static struct msi_attribute mode_attribute = +- __ATTR(mode, S_IRUGO, show_msi_mode, NULL); +- + struct pci_dev *pdev = to_pci_dev(dev); + struct msi_desc *entry; + unsigned long irq; + int retval; -+ + +-static struct attribute *msi_irq_default_attrs[] = { +- &mode_attribute.attr, +- NULL +-}; + retval = kstrtoul(attr->attr.name, 10, &irq); + if (retval) + return retval; -+ + +-static void msi_kobj_release(struct kobject *kobj) +-{ +- struct msi_desc *entry = to_msi_desc(kobj); +- +- pci_dev_put(entry->dev); + list_for_each_entry(entry, &pdev->msi_list, list) { + if (entry->irq == irq) { + return sprintf(buf, "%s\n", @@ -61,8 +137,14 @@ + } + } + return -ENODEV; -+} -+ + } + +-static struct kobj_type msi_irq_ktype = { +- .release = msi_kobj_release, +- .sysfs_ops = &msi_irq_sysfs_ops, +- .default_attrs = msi_irq_default_attrs, +-}; +- static int populate_msi_sysfs(struct pci_dev *pdev) { + struct attribute **msi_attrs; @@ -70,23 +152,44 @@ + struct attribute_group *msi_irq_group; + const struct attribute_group **msi_irq_groups; struct msi_desc *entry; - struct kobject *kobj; +- struct kobject *kobj; int ret; + int num_msi = 0; int count = 0; +- pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); +- if (!pdev->msi_kset) +- return -ENOMEM; +- + /* Determine how many msi entries we have */ -+ list_for_each_entry(entry, &pdev->msi_list, list) { + list_for_each_entry(entry, &pdev->msi_list, list) { +- kobj = &entry->kobj; +- kobj->kset = pdev->msi_kset; +- pci_dev_get(pdev); +- ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, +- "%u", entry->irq); +- if (ret) +- goto out_unroll; +- +- count++; + ++num_msi; -+ } + } + if (!num_msi) + return 0; -+ + +- return 0; +- +-out_unroll: + /* Dynamically create the MSI attributes for the PCI device */ + msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL); + if (!msi_attrs) + return -ENOMEM; -+ list_for_each_entry(entry, &pdev->msi_list, list) { + list_for_each_entry(entry, &pdev->msi_list, list) { +- if (!count) +- break; +- kobject_del(&entry->kobj); +- kobject_put(&entry->kobj); +- count--; + char *name = kmalloc(20, GFP_KERNEL); + msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); + if (!msi_dev_attr) @@ -97,12 +200,13 @@ + msi_dev_attr->show = msi_mode_show; + msi_attrs[count] = &msi_dev_attr->attr; + ++count; -+ } + } +- return ret; + + msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); + if (!msi_irq_group) + return -ENOMEM; -+ msi_irq_group->name = "msi_irqs_2"; ++ msi_irq_group->name = "msi_irqs"; + msi_irq_group->attrs = msi_attrs; + + msi_irq_groups = kzalloc(sizeof(void *) * 2, GFP_KERNEL); @@ -115,15 +219,35 @@ + return ret; + pdev->msi_irq_groups = msi_irq_groups; + - pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); - if (!pdev->msi_kset) - return -ENOMEM; ++ return 0; + } + + /** +@@ -925,8 +927,6 @@ void pci_disable_msi(struct pci_dev *dev + + pci_msi_shutdown(dev); + free_msi_irqs(dev); +- kset_unregister(dev->msi_kset); +- dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msi); + +@@ -1023,8 +1023,6 @@ void pci_disable_msix(struct pci_dev *de + + pci_msix_shutdown(dev); + free_msi_irqs(dev); +- kset_unregister(dev->msi_kset); +- dev->msi_kset = NULL; + } + EXPORT_SYMBOL(pci_disable_msix); + --- a/include/linux/pci.h +++ b/include/linux/pci.h -@@ -352,6 +352,7 @@ struct pci_dev { +@@ -351,7 +351,7 @@ struct pci_dev { + struct bin_attribute *res_attr_wc[DEVICE_COUNT_RESOURCE]; /* sysfs file for WC mapping of resources */ #ifdef CONFIG_PCI_MSI struct list_head msi_list; - struct kset *msi_kset; +- struct kset *msi_kset; + const struct attribute_group **msi_irq_groups; #endif struct pci_vpd *vpd; |
