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
This commit is contained in:
commit
d1a2523d2a
@ -250,3 +250,24 @@ Description:
|
|||||||
valid. For example, writing a 2 to this file when sriov_numvfs
|
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
|
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.
|
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.
|
||||||
|
@ -49,9 +49,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
|
|||||||
* type BRIDGE, or CARDBUS. Host to PCI controllers use
|
* type BRIDGE, or CARDBUS. Host to PCI controllers use
|
||||||
* PCI header type NORMAL.
|
* PCI header type NORMAL.
|
||||||
*/
|
*/
|
||||||
if (bridge
|
if (bridge && (pci_is_bridge(bridge))) {
|
||||||
&&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
|
||||||
||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
|
|
||||||
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
|
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
|
||||||
&config);
|
&config);
|
||||||
if (!(config & PCI_BRIDGE_CTL_VGA))
|
if (!(config & PCI_BRIDGE_CTL_VGA))
|
||||||
|
@ -98,8 +98,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
|
|||||||
max = bus->busn_res.start;
|
max = bus->busn_res.start;
|
||||||
for (pass = 0; pass < 2; pass++) {
|
for (pass = 0; pass < 2; pass++) {
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
max = pci_scan_bridge(bus, dev,
|
max = pci_scan_bridge(bus, dev,
|
||||||
max, pass);
|
max, pass);
|
||||||
}
|
}
|
||||||
|
@ -362,8 +362,7 @@ static void __of_scan_bus(struct device_node *node, struct pci_bus *bus,
|
|||||||
|
|
||||||
/* Now scan child busses */
|
/* Now scan child busses */
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev)) {
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
|
||||||
of_scan_pci_bridge(dev);
|
of_scan_pci_bridge(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -543,8 +543,7 @@ static void pci_of_scan_bus(struct pci_pbm_info *pbm,
|
|||||||
printk("PCI: dev header type: %x\n",
|
printk("PCI: dev header type: %x\n",
|
||||||
dev->hdr_type);
|
dev->hdr_type);
|
||||||
|
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
of_scan_pci_bridge(pbm, child, dev);
|
of_scan_pci_bridge(pbm, child, dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,9 +338,7 @@ static void pci_fixup_video(struct pci_dev *pdev)
|
|||||||
* type BRIDGE, or CARDBUS. Host to PCI controllers use
|
* type BRIDGE, or CARDBUS. Host to PCI controllers use
|
||||||
* PCI header type NORMAL.
|
* PCI header type NORMAL.
|
||||||
*/
|
*/
|
||||||
if (bridge
|
if (bridge && (pci_is_bridge(bridge))) {
|
||||||
&& ((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE)
|
|
||||||
|| (bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) {
|
|
||||||
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
|
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL,
|
||||||
&config);
|
&config);
|
||||||
if (!(config & PCI_BRIDGE_CTL_VGA))
|
if (!(config & PCI_BRIDGE_CTL_VGA))
|
||||||
|
@ -2775,6 +2775,16 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||||||
return result;
|
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)
|
static void nvme_shutdown(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct nvme_dev *dev = pci_get_drvdata(pdev);
|
struct nvme_dev *dev = pci_get_drvdata(pdev);
|
||||||
@ -2839,6 +2849,7 @@ static const struct pci_error_handlers nvme_err_handler = {
|
|||||||
.link_reset = nvme_link_reset,
|
.link_reset = nvme_link_reset,
|
||||||
.slot_reset = nvme_slot_reset,
|
.slot_reset = nvme_slot_reset,
|
||||||
.resume = nvme_error_resume,
|
.resume = nvme_error_resume,
|
||||||
|
.reset_notify = nvme_reset_notify,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Move to pci_ids.h later */
|
/* Move to pci_ids.h later */
|
||||||
|
@ -515,8 +515,7 @@ static void enable_slot(struct acpiphp_slot *slot)
|
|||||||
if (PCI_SLOT(dev->devfn) != slot->device)
|
if (PCI_SLOT(dev->devfn) != slot->device)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev)) {
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
|
||||||
max = pci_scan_bridge(bus, dev, max, pass);
|
max = pci_scan_bridge(bus, dev, max, pass);
|
||||||
if (pass && dev->subordinate) {
|
if (pass && dev->subordinate) {
|
||||||
check_hotplug_bridge(slot, dev);
|
check_hotplug_bridge(slot, dev);
|
||||||
|
@ -289,8 +289,7 @@ int cpci_configure_slot(struct slot *slot)
|
|||||||
list_for_each_entry(dev, &parent->devices, bus_list)
|
list_for_each_entry(dev, &parent->devices, bus_list)
|
||||||
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
|
||||||
continue;
|
continue;
|
||||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
if (pci_is_bridge(dev))
|
||||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
|
||||||
pci_hp_add_bridge(dev);
|
pci_hp_add_bridge(dev);
|
||||||
|
|
||||||
|
|
||||||
|
@ -709,7 +709,8 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
|
|||||||
temp = temp->next;
|
temp = temp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp->next = max->next;
|
if (temp)
|
||||||
|
temp->next = max->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
max->next = NULL;
|
max->next = NULL;
|
||||||
|
@ -62,8 +62,7 @@ int pciehp_configure_device(struct slot *p_slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(dev, &parent->devices, bus_list)
|
list_for_each_entry(dev, &parent->devices, bus_list)
|
||||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
if (pci_is_bridge(dev))
|
||||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
|
||||||
pci_hp_add_bridge(dev);
|
pci_hp_add_bridge(dev);
|
||||||
|
|
||||||
pci_assign_unassigned_bridge_resources(bridge);
|
pci_assign_unassigned_bridge_resources(bridge);
|
||||||
|
@ -157,8 +157,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Scan below the new bridge */
|
/* Scan below the new bridge */
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
of_scan_pci_bridge(dev);
|
of_scan_pci_bridge(dev);
|
||||||
|
|
||||||
/* Map IO space for child bus, which may or may not succeed */
|
/* Map IO space for child bus, which may or may not succeed */
|
||||||
|
@ -64,8 +64,7 @@ int shpchp_configure_device(struct slot *p_slot)
|
|||||||
list_for_each_entry(dev, &parent->devices, bus_list) {
|
list_for_each_entry(dev, &parent->devices, bus_list) {
|
||||||
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
if (PCI_SLOT(dev->devfn) != p_slot->device)
|
||||||
continue;
|
continue;
|
||||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
if (pci_is_bridge(dev))
|
||||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
|
||||||
pci_hp_add_bridge(dev);
|
pci_hp_add_bridge(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,13 +309,7 @@ static struct acpi_device *acpi_pci_find_companion(struct device *dev)
|
|||||||
bool check_children;
|
bool check_children;
|
||||||
u64 addr;
|
u64 addr;
|
||||||
|
|
||||||
/*
|
check_children = pci_is_bridge(pci_dev);
|
||||||
* 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;
|
|
||||||
/* Please ref to ACPI spec for the syntax of _ADR */
|
/* Please ref to ACPI spec for the syntax of _ADR */
|
||||||
addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
|
addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
|
||||||
return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,
|
return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr,
|
||||||
|
@ -236,6 +236,13 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
|
|||||||
return NULL;
|
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
|
* pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
|
||||||
* @drv: the PCI driver to match against
|
* @drv: the PCI driver to match against
|
||||||
@ -249,18 +256,30 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
|||||||
struct pci_dev *dev)
|
struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
struct pci_dynid *dynid;
|
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 */
|
/* Look at the dynamic ids first, before the static ones */
|
||||||
spin_lock(&drv->dynids.lock);
|
spin_lock(&drv->dynids.lock);
|
||||||
list_for_each_entry(dynid, &drv->dynids.list, node) {
|
list_for_each_entry(dynid, &drv->dynids.list, node) {
|
||||||
if (pci_match_one_device(&dynid->id, dev)) {
|
if (pci_match_one_device(&dynid->id, dev)) {
|
||||||
spin_unlock(&drv->dynids.lock);
|
found_id = &dynid->id;
|
||||||
return &dynid->id;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock(&drv->dynids.lock);
|
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 {
|
struct drv_dev_and_id {
|
||||||
@ -600,14 +619,14 @@ static void pci_pm_default_resume(struct pci_dev *pci_dev)
|
|||||||
{
|
{
|
||||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
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);
|
pci_enable_wake(pci_dev, PCI_D0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pci_pm_default_suspend(struct pci_dev *pci_dev)
|
static void pci_pm_default_suspend(struct pci_dev *pci_dev)
|
||||||
{
|
{
|
||||||
/* Disable non-bridge devices without PM support */
|
/* 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);
|
pci_disable_enabled_device(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -737,7 +756,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
|
|||||||
|
|
||||||
if (!pci_dev->state_saved) {
|
if (!pci_dev->state_saved) {
|
||||||
pci_save_state(pci_dev);
|
pci_save_state(pci_dev);
|
||||||
if (!pci_is_bridge(pci_dev))
|
if (!pci_has_subordinate(pci_dev))
|
||||||
pci_prepare_to_sleep(pci_dev);
|
pci_prepare_to_sleep(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,7 +1010,7 @@ static int pci_pm_poweroff_noirq(struct device *dev)
|
|||||||
return error;
|
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);
|
pci_prepare_to_sleep(pci_dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -514,6 +514,45 @@ static struct device_attribute sriov_numvfs_attr =
|
|||||||
sriov_numvfs_show, sriov_numvfs_store);
|
sriov_numvfs_show, sriov_numvfs_store);
|
||||||
#endif /* CONFIG_PCI_IOV */
|
#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[] = {
|
static struct attribute *pci_dev_attrs[] = {
|
||||||
&dev_attr_resource.attr,
|
&dev_attr_resource.attr,
|
||||||
&dev_attr_vendor.attr,
|
&dev_attr_vendor.attr,
|
||||||
@ -539,6 +578,7 @@ static struct attribute *pci_dev_attrs[] = {
|
|||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
&dev_attr_devspec.attr,
|
&dev_attr_devspec.attr,
|
||||||
#endif
|
#endif
|
||||||
|
&dev_attr_driver_override.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3305,8 +3305,27 @@ static void pci_dev_unlock(struct pci_dev *dev)
|
|||||||
pci_cfg_access_unlock(dev);
|
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)
|
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
|
* Wake-up device prior to save. PM registers default to D0 after
|
||||||
* reset and a simple register restore doesn't reliably return
|
* reset and a simple register restore doesn't reliably return
|
||||||
@ -3328,6 +3347,7 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)
|
|||||||
static void pci_dev_restore(struct pci_dev *dev)
|
static void pci_dev_restore(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
pci_restore_state(dev);
|
pci_restore_state(dev);
|
||||||
|
pci_reset_notify(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pci_dev_reset(struct pci_dev *dev, int probe)
|
static int pci_dev_reset(struct pci_dev *dev, int probe)
|
||||||
@ -3344,6 +3364,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __pci_reset_function - reset a PCI device function
|
* __pci_reset_function - reset a PCI device function
|
||||||
* @dev: PCI device to reset
|
* @dev: PCI device to reset
|
||||||
|
@ -77,7 +77,7 @@ static inline void pci_wakeup_event(struct pci_dev *dev)
|
|||||||
pm_wakeup_event(&dev->dev, 100);
|
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);
|
return !!(pci_dev->subordinate);
|
||||||
}
|
}
|
||||||
|
@ -1225,6 +1225,7 @@ static void pci_release_dev(struct device *dev)
|
|||||||
pci_release_of_node(pci_dev);
|
pci_release_of_node(pci_dev);
|
||||||
pcibios_release_device(pci_dev);
|
pcibios_release_device(pci_dev);
|
||||||
pci_bus_put(pci_dev->bus);
|
pci_bus_put(pci_dev->bus);
|
||||||
|
kfree(pci_dev->driver_override);
|
||||||
kfree(pci_dev);
|
kfree(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1680,8 +1681,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
|
|||||||
|
|
||||||
for (pass=0; pass < 2; pass++)
|
for (pass=0; pass < 2; pass++)
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
max = pci_scan_bridge(bus, dev, max, pass);
|
max = pci_scan_bridge(bus, dev, max, pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1716,9 +1716,7 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
|
|||||||
|
|
||||||
down_read(&pci_bus_sem);
|
down_read(&pci_bus_sem);
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev) && pci_has_subordinate(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
if (dev->subordinate)
|
|
||||||
__pci_bus_size_bridges(dev->subordinate,
|
__pci_bus_size_bridges(dev->subordinate,
|
||||||
&add_list);
|
&add_list);
|
||||||
up_read(&pci_bus_sem);
|
up_read(&pci_bus_sem);
|
||||||
|
@ -78,8 +78,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
|
|||||||
max = bus->busn_res.start;
|
max = bus->busn_res.start;
|
||||||
for (pass = 0; pass < 2; pass++)
|
for (pass = 0; pass < 2; pass++)
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
if (pci_is_bridge(dev))
|
||||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
|
|
||||||
max = pci_scan_bridge(bus, dev, max, pass);
|
max = pci_scan_bridge(bus, dev, max, pass);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -365,6 +365,7 @@ struct pci_dev {
|
|||||||
#endif
|
#endif
|
||||||
phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
|
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 */
|
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)
|
static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
|
||||||
@ -477,6 +478,19 @@ static inline bool pci_is_root_bus(struct pci_bus *pbus)
|
|||||||
return !(pbus->parent);
|
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)
|
static inline struct pci_dev *pci_upstream_bridge(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
dev = pci_physfn(dev);
|
dev = pci_physfn(dev);
|
||||||
@ -603,6 +617,9 @@ struct pci_error_handlers {
|
|||||||
/* PCI slot has been reset */
|
/* PCI slot has been reset */
|
||||||
pci_ers_result_t (*slot_reset)(struct pci_dev *dev);
|
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 */
|
/* Device driver may resume normal operations */
|
||||||
void (*resume)(struct pci_dev *dev);
|
void (*resume)(struct pci_dev *dev);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user