Merge branches 'pci/hotplug', 'pci/pci_is_bridge' and 'pci/virtualization' into next
* pci/hotplug:
PCI: cpqphp: Fix possible null pointer dereference
NVMe: Implement PCIe reset notification callback
PCI: Notify driver before and after device reset
* pci/pci_is_bridge:
pcmcia: Use pci_is_bridge() to simplify code
PCI: pciehp: Use pci_is_bridge() to simplify code
PCI: acpiphp: Use pci_is_bridge() to simplify code
PCI: cpcihp: Use pci_is_bridge() to simplify code
PCI: shpchp: Use pci_is_bridge() to simplify code
PCI: rpaphp: Use pci_is_bridge() to simplify code
sparc/PCI: Use pci_is_bridge() to simplify code
powerpc/PCI: Use pci_is_bridge() to simplify code
ia64/PCI: Use pci_is_bridge() to simplify code
x86/PCI: Use pci_is_bridge() to simplify code
PCI: Use pci_is_bridge() to simplify code
PCI: Add new pci_is_bridge() interface
PCI: Rename pci_is_bridge() to pci_has_subordinate()
* pci/virtualization:
PCI: Introduce new device binding path using pci_dev.driver_override
Conflicts:
drivers/pci/pci-sysfs.c
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index ab8d76d..6615fda 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -250,3 +250,24 @@
valid. For example, writing a 2 to this file when sriov_numvfs
is not 0 and not 2 already will return an error. Writing a 10
when the value of sriov_totalvfs is 8 will return an error.
+
+What: /sys/bus/pci/devices/.../driver_override
+Date: April 2014
+Contact: Alex Williamson <alex.williamson@redhat.com>
+Description:
+ This file allows the driver for a device to be specified which
+ will override standard static and dynamic ID matching. When
+ specified, only a driver with a name matching the value written
+ to driver_override will have an opportunity to bind to the
+ device. The override is specified by writing a string to the
+ driver_override file (echo pci-stub > driver_override) and
+ may be cleared with an empty string (echo > driver_override).
+ This returns the device to standard matching rules binding.
+ Writing to driver_override does not automatically unbind the
+ device from its current driver or make any attempt to
+ automatically load the specified driver. If no driver with a
+ matching name is currently loaded in the kernel, the device
+ will not bind to any driver. This also allows devices to
+ opt-out of driver binding using a driver_override name such as
+ "none". Only a single driver may be specified in the override,
+ there is no support for parsing delimiters.
diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c
index eee069a..1fe9aa5 100644
--- a/arch/ia64/pci/fixup.c
+++ b/arch/ia64/pci/fixup.c
@@ -49,9 +49,7 @@
* type BRIDGE, or CARDBUS. Host to PCI controllers use
* PCI header type NORMAL.
*/
- if (bridge
- &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
+ if (bridge && (pci_is_bridge(bridge))) {
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
&config);
if (!(config & PCI_BRIDGE_CTL_VGA))
diff --git a/arch/powerpc/kernel/pci-hotplug.c b/arch/powerpc/kernel/pci-hotplug.c
index c1e17ae..5b78917 100644
--- a/arch/powerpc/kernel/pci-hotplug.c
+++ b/arch/powerpc/kernel/pci-hotplug.c
@@ -98,8 +98,7 @@
max = bus->busn_res.start;
for (pass = 0; pass < 2; pass++) {
list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
max = pci_scan_bridge(bus, dev,
max, pass);
}
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 83c26d8..059e244 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -362,8 +362,7 @@
/* Now scan child busses */
list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+ if (pci_is_bridge(dev)) {
of_scan_pci_bridge(dev);
}
}
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 1555bbc..857ad77 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -543,8 +543,7 @@
printk("PCI: dev header type: %x\n",
dev->hdr_type);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
of_scan_pci_bridge(pbm, child, dev);
}
}
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index ef334a0..b5e6026 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -338,9 +338,7 @@
* type BRIDGE, or CARDBUS. Host to PCI controllers use
* PCI header type NORMAL.
*/
- if (bridge
- && ((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- || (bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
+ if (bridge && (pci_is_bridge(bridge))) {
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
&config);
if (!(config & PCI_BRIDGE_CTL_VGA))
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 7c64fa7..a842c71 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -2775,6 +2775,16 @@
return result;
}
+static void nvme_reset_notify(struct pci_dev *pdev, bool prepare)
+{
+ struct nvme_dev *dev = pci_get_drvdata(pdev);
+
+ if (prepare)
+ nvme_dev_shutdown(dev);
+ else
+ nvme_dev_resume(dev);
+}
+
static void nvme_shutdown(struct pci_dev *pdev)
{
struct nvme_dev *dev = pci_get_drvdata(pdev);
@@ -2839,6 +2849,7 @@
.link_reset = nvme_link_reset,
.slot_reset = nvme_slot_reset,
.resume = nvme_error_resume,
+ .reset_notify = nvme_reset_notify,
};
/* Move to pci_ids.h later */
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index bb945e3..75e1783 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -515,8 +515,7 @@
if (PCI_SLOT(dev->devfn) != slot->device)
continue;
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+ if (pci_is_bridge(dev)) {
max = pci_scan_bridge(bus, dev, max, pass);
if (pass && dev->subordinate) {
check_hotplug_bridge(slot, dev);
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index b238a1a2..f6ef64c 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -289,8 +289,7 @@
list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
continue;
- if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
- (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+ if (pci_is_bridge(dev))
pci_hp_add_bridge(dev);
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 11845b7..f593585 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -709,7 +709,8 @@
temp = temp->next;
}
- temp->next = max->next;
+ if (temp)
+ temp->next = max->next;
}
max->next = NULL;
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 1b53306..b6cb1df 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -62,8 +62,7 @@
}
list_for_each_entry(dev, &parent->devices, bus_list)
- if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
- (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+ if (pci_is_bridge(dev))
pci_hp_add_bridge(dev);
pci_assign_unassigned_bridge_resources(bridge);
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index 4fcdeed..7660232 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -157,8 +157,7 @@
}
/* Scan below the new bridge */
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
of_scan_pci_bridge(dev);
/* Map IO space for child bus, which may or may not succeed */
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 18209eb..9202d13 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -64,8 +64,7 @@
list_for_each_entry(dev, &parent->devices, bus_list) {
if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
- if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
- (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
+ if (pci_is_bridge(dev))
pci_hp_add_bridge(dev);
}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index f49abef8..ca4927ba 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -309,13 +309,7 @@
bool check_children;
u64 addr;
- /*
- * pci_is_bridge() is not suitable here, because pci_dev->subordinate
- * is set only after acpi_pci_find_device() has been called for the
- * given device.
- */
- check_children = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE
- || pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
+ check_children = pci_is_bridge(pci_dev);
/* Please ref to ACPI spec for the syntax of _ADR */
addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index ff236ed..837d71f 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -236,6 +236,13 @@
return NULL;
}
+static const struct pci_device_id pci_device_id_any = {
+ .vendor = PCI_ANY_ID,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+};
+
/**
* pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
* @drv: the PCI driver to match against
@@ -249,18 +256,30 @@
struct pci_dev *dev)
{
struct pci_dynid *dynid;
+ const struct pci_device_id *found_id = NULL;
+
+ /* When driver_override is set, only bind to the matching driver */
+ if (dev->driver_override && strcmp(dev->driver_override, drv->name))
+ return NULL;
/* Look at the dynamic ids first, before the static ones */
spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) {
- spin_unlock(&drv->dynids.lock);
- return &dynid->id;
+ found_id = &dynid->id;
+ break;
}
}
spin_unlock(&drv->dynids.lock);
- return pci_match_id(drv->id_table, dev);
+ if (!found_id)
+ found_id = pci_match_id(drv->id_table, dev);
+
+ /* driver_override will always match, send a dummy id */
+ if (!found_id && dev->driver_override)
+ found_id = &pci_device_id_any;
+
+ return found_id;
}
struct drv_dev_and_id {
@@ -600,14 +619,14 @@
{
pci_fixup_device(pci_fixup_resume, pci_dev);
- if (!pci_is_bridge(pci_dev))
+ if (!pci_has_subordinate(pci_dev))
pci_enable_wake(pci_dev, PCI_D0, false);
}
static void pci_pm_default_suspend(struct pci_dev *pci_dev)
{
/* Disable non-bridge devices without PM support */
- if (!pci_is_bridge(pci_dev))
+ if (!pci_has_subordinate(pci_dev))
pci_disable_enabled_device(pci_dev);
}
@@ -737,7 +756,7 @@
if (!pci_dev->state_saved) {
pci_save_state(pci_dev);
- if (!pci_is_bridge(pci_dev))
+ if (!pci_has_subordinate(pci_dev))
pci_prepare_to_sleep(pci_dev);
}
@@ -991,7 +1010,7 @@
return error;
}
- if (!pci_dev->state_saved && !pci_is_bridge(pci_dev))
+ if (!pci_dev->state_saved && !pci_has_subordinate(pci_dev))
pci_prepare_to_sleep(pci_dev);
/*
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index b7333fa..84c3509 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -514,6 +514,45 @@
sriov_numvfs_show, sriov_numvfs_store);
#endif /* CONFIG_PCI_IOV */
+static ssize_t driver_override_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ char *driver_override, *old = pdev->driver_override, *cp;
+
+ if (count > PATH_MAX)
+ return -EINVAL;
+
+ driver_override = kstrndup(buf, count, GFP_KERNEL);
+ if (!driver_override)
+ return -ENOMEM;
+
+ cp = strchr(driver_override, '\n');
+ if (cp)
+ *cp = '\0';
+
+ if (strlen(driver_override)) {
+ pdev->driver_override = driver_override;
+ } else {
+ kfree(driver_override);
+ pdev->driver_override = NULL;
+ }
+
+ kfree(old);
+
+ return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return sprintf(buf, "%s\n", pdev->driver_override);
+}
+static DEVICE_ATTR_RW(driver_override);
+
static struct attribute *pci_dev_attrs[] = {
&dev_attr_resource.attr,
&dev_attr_vendor.attr,
@@ -539,6 +578,7 @@
#ifdef CONFIG_OF
&dev_attr_devspec.attr,
#endif
+ &dev_attr_driver_override.attr,
NULL,
};
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3901283..f988bb1 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -3305,8 +3305,27 @@
pci_cfg_access_unlock(dev);
}
+/**
+ * pci_reset_notify - notify device driver of reset
+ * @dev: device to be notified of reset
+ * @prepare: 'true' if device is about to be reset; 'false' if reset attempt
+ * completed
+ *
+ * Must be called prior to device access being disabled and after device
+ * access is restored.
+ */
+static void pci_reset_notify(struct pci_dev *dev, bool prepare)
+{
+ const struct pci_error_handlers *err_handler =
+ dev->driver ? dev->driver->err_handler : NULL;
+ if (err_handler && err_handler->reset_notify)
+ err_handler->reset_notify(dev, prepare);
+}
+
static void pci_dev_save_and_disable(struct pci_dev *dev)
{
+ pci_reset_notify(dev, true);
+
/*
* Wake-up device prior to save. PM registers default to D0 after
* reset and a simple register restore doesn't reliably return
@@ -3328,6 +3347,7 @@
static void pci_dev_restore(struct pci_dev *dev)
{
pci_restore_state(dev);
+ pci_reset_notify(dev, false);
}
static int pci_dev_reset(struct pci_dev *dev, int probe)
@@ -3344,6 +3364,7 @@
return rc;
}
+
/**
* __pci_reset_function - reset a PCI device function
* @dev: PCI device to reset
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fe233a3..0601890 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -77,7 +77,7 @@
pm_wakeup_event(&dev->dev, 100);
}
-static inline bool pci_is_bridge(struct pci_dev *pci_dev)
+static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
{
return !!(pci_dev->subordinate);
}
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 52d05e0..36f1fd1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1225,6 +1225,7 @@
pci_release_of_node(pci_dev);
pcibios_release_device(pci_dev);
pci_bus_put(pci_dev->bus);
+ kfree(pci_dev->driver_override);
kfree(pci_dev);
}
@@ -1680,8 +1681,7 @@
for (pass=0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
max = pci_scan_bridge(bus, dev, max, pass);
}
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index d9fdcea..fd9b545 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1716,9 +1716,7 @@
down_read(&pci_bus_sem);
list_for_each_entry(dev, &bus->devices, bus_list)
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
- if (dev->subordinate)
+ if (pci_is_bridge(dev) && pci_has_subordinate(dev))
__pci_bus_size_bridges(dev->subordinate,
&add_list);
up_read(&pci_bus_sem);
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 8bde619..4fe4cc4 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -78,8 +78,7 @@
max = bus->busn_res.start;
for (pass = 0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list)
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ if (pci_is_bridge(dev))
max = pci_scan_bridge(bus, dev, max, pass);
/*
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5dbd154..4eb9996 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -365,6 +365,7 @@
#endif
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
size_t romlen; /* Length of ROM if it's not from the BAR */
+ char *driver_override; /* Driver name to force a match */
};
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@ -477,6 +478,19 @@
return !(pbus->parent);
}
+/**
+ * pci_is_bridge - check if the PCI device is a bridge
+ * @dev: PCI device
+ *
+ * Return true if the PCI device is bridge whether it has subordinate
+ * or not.
+ */
+static inline bool pci_is_bridge(struct pci_dev *dev)
+{
+ return dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS;
+}
+
static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev)
{
dev = pci_physfn(dev);
@@ -603,6 +617,9 @@
/* PCI slot has been reset */
pci_ers_result_t (*slot_reset)(struct pci_dev *dev);
+ /* PCI function reset prepare or completed */
+ void (*reset_notify)(struct pci_dev *dev, bool prepare);
+
/* Device driver may resume normal operations */
void (*resume)(struct pci_dev *dev);
};