From: Brice Goglin Date: Thu, 31 Aug 2006 05:55:15 +0000 (-0400) Subject: MSI: Export the PCI_BUS_FLAGS_NO_MSI flag in sysfs X-Git-Tag: v2.6.19-rc1~1004^2~24 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=fe97064c2870e174a6ff4a93feb11a70c4b71cc5;p=linux-2.6-omap-h63xx.git MSI: Export the PCI_BUS_FLAGS_NO_MSI flag in sysfs Export the PCI_BUS_FLAGS_NO_MSI flag of a PCI bus in the sysfs files of its parent device and make it writable. Could be used to: * disable MSI on a device which has not been blacklisted yet * allow MSI when some setpci hacks enable MSI support (for instance on the ServerWorks HT2000 chipset where the MSI HT cap is disabled by default). Architecture where some bus have no parent chipset cannot use this strategy to change MSI support. If the chipset does not have a subordinate bus, its 'bus_msi' file is empty. Also document and warn about the possible danger of changing the flag. Signed-off-by: Brice Goglin Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index fdefa7dcd15..010e01c4bd4 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -131,6 +131,46 @@ is_enabled_store(struct device *dev, struct device_attribute *attr, return count; } +static ssize_t +msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + if (!pdev->subordinate) + return 0; + + return sprintf (buf, "%u\n", + !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI)); +} + +static ssize_t +msi_bus_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pci_dev *pdev = to_pci_dev(dev); + + /* bad things may happen if the no_msi flag is changed + * while some drivers are loaded */ + if (!capable(CAP_SYS_ADMIN)) + return count; + + if (!pdev->subordinate) + return count; + + if (*buf == '0') { + pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; + dev_warn(&pdev->dev, "forced subordinate bus to not support MSI," + " bad things could happen.\n"); + } + + if (*buf == '1') { + pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI; + dev_warn(&pdev->dev, "forced subordinate bus to support MSI," + " bad things could happen.\n"); + } + + return count; +} struct device_attribute pci_dev_attrs[] = { __ATTR_RO(resource), @@ -145,6 +185,7 @@ struct device_attribute pci_dev_attrs[] = { __ATTR(enable, 0600, is_enabled_show, is_enabled_store), __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), broken_parity_status_show,broken_parity_status_store), + __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), __ATTR_NULL, };