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 <brice@myri.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Brice Goglin 2006-08-31 01:55:15 -04:00 committed by Greg Kroah-Hartman
parent 24334a1253
commit fe97064c28

View File

@ -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,
};