Merge tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI update from Bjorn Helgaas:
 "Host bridge hotplug:
   - Untangle _PRT from struct pci_bus (Bjorn Helgaas)
   - Request _OSC control before scanning root bus (Taku Izumi)
   - Assign resources when adding host bridge (Yinghai Lu)
   - Remove root bus when removing host bridge (Yinghai Lu)
   - Remove _PRT during hot remove (Yinghai Lu)

  SRIOV
    - Add sysfs knobs to control numVFs (Don Dutile)

  Power management
   - Notify devices when power resource turned on (Huang Ying)

  Bug fixes
   - Work around broken _SEG on HP xw9300 (Bjorn Helgaas)
   - Keep runtime PM enabled for unbound PCI devices (Huang Ying)
   - Fix Optimus dual-GPU runtime D3 suspend issue (Dave Airlie)
   - Fix xen frontend shutdown issue (David Vrabel)
   - Work around PLX PCI 9050 BAR alignment erratum (Ian Abbott)

  Miscellaneous
   - Add GPL license for drivers/pci/ioapic (Andrew Cooks)
   - Add standard PCI-X, PCIe ASPM register #defines (Bjorn Helgaas)
   - NumaChip remote PCI support (Daniel Blueman)
   - Fix PCIe Link Capabilities Supported Link Speed definition (Jingoo
     Han)
   - Convert dev_printk() to dev_info(), etc (Joe Perches)
   - Add support for non PCI BAR ROM data (Matthew Garrett)
   - Add x86 support for host bridge translation offset (Mike Yoknis)
   - Report success only when every driver supports AER (Vijay
     Pandarathil)"

Fix up trivial conflicts.

* tag 'for-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (48 commits)
  PCI: Use phys_addr_t for physical ROM address
  x86/PCI: Add NumaChip remote PCI support
  ath9k: Use standard #defines for PCIe Capability ASPM fields
  iwlwifi: Use standard #defines for PCIe Capability ASPM fields
  iwlwifi: collapse wrapper for pcie_capability_read_word()
  iwlegacy: Use standard #defines for PCIe Capability ASPM fields
  iwlegacy: collapse wrapper for pcie_capability_read_word()
  cxgb3: Use standard #defines for PCIe Capability ASPM fields
  PCI: Add standard PCIe Capability Link ASPM field names
  PCI/portdrv: Use PCI Express Capability accessors
  PCI: Use standard PCIe Capability Link register field names
  x86: Use PCI setup data
  PCI: Add support for non-BAR ROMs
  PCI: Add pcibios_add_device
  EFI: Stash ROMs if they're not in the PCI BAR
  PCI: Add and use standard PCI-X Capability register names
  PCI/PM: Keep runtime PM enabled for unbound PCI devices
  xen-pcifront: Handle backend CLOSED without CLOSING
  PCI: SRIOV control and status via sysfs (documentation)
  PCI/AER: Report success only when every device has AER-aware driver
  ...
This commit is contained in:
Linus Torvalds
2012-12-13 12:14:47 -08:00
45 changed files with 1150 additions and 271 deletions
+5
View File
@@ -170,6 +170,11 @@ int pci_bus_add_device(struct pci_dev *dev)
int retval;
pci_fixup_device(pci_fixup_final, dev);
retval = pcibios_add_device(dev);
if (retval)
return retval;
retval = device_add(&dev->dev);
if (retval)
return retval;
+2
View File
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
module_init(ioapic_init);
module_exit(ioapic_exit);
MODULE_LICENSE("GPL");
+67 -20
View File
@@ -106,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
virtfn->resource[i].name = pci_name(virtfn);
virtfn->resource[i].flags = res->flags;
size = resource_size(res);
do_div(size, iov->total);
do_div(size, iov->total_VFs);
virtfn->resource[i].start = res->start + size * id;
virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
rc = request_resource(res, &virtfn->resource[i]);
@@ -194,7 +194,7 @@ static int sriov_migration(struct pci_dev *dev)
u16 status;
struct pci_sriov *iov = dev->sriov;
if (!iov->nr_virtfn)
if (!iov->num_VFs)
return 0;
if (!(iov->cap & PCI_SRIOV_CAP_VFM))
@@ -216,7 +216,7 @@ static void sriov_migration_task(struct work_struct *work)
u16 status;
struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask);
for (i = iov->initial; i < iov->nr_virtfn; i++) {
for (i = iov->initial_VFs; i < iov->num_VFs; i++) {
state = readb(iov->mstate + i);
if (state == PCI_SRIOV_VFM_MI) {
writeb(PCI_SRIOV_VFM_AV, iov->mstate + i);
@@ -244,7 +244,7 @@ static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn)
resource_size_t pa;
struct pci_sriov *iov = dev->sriov;
if (nr_virtfn <= iov->initial)
if (nr_virtfn <= iov->initial_VFs)
return 0;
pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table);
@@ -294,15 +294,15 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
if (!nr_virtfn)
return 0;
if (iov->nr_virtfn)
if (iov->num_VFs)
return -EINVAL;
pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial);
if (initial > iov->total ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total)))
if (initial > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total_VFs)))
return -EIO;
if (nr_virtfn < 0 || nr_virtfn > iov->total ||
if (nr_virtfn < 0 || nr_virtfn > iov->total_VFs ||
(!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial)))
return -EINVAL;
@@ -359,7 +359,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
msleep(100);
pci_cfg_access_unlock(dev);
iov->initial = initial;
iov->initial_VFs = initial;
if (nr_virtfn < initial)
initial = nr_virtfn;
@@ -376,7 +376,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
}
kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
iov->nr_virtfn = nr_virtfn;
iov->num_VFs = nr_virtfn;
return 0;
@@ -401,13 +401,13 @@ static void sriov_disable(struct pci_dev *dev)
int i;
struct pci_sriov *iov = dev->sriov;
if (!iov->nr_virtfn)
if (!iov->num_VFs)
return;
if (iov->cap & PCI_SRIOV_CAP_VFM)
sriov_disable_migration(dev);
for (i = 0; i < iov->nr_virtfn; i++)
for (i = 0; i < iov->num_VFs; i++)
virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
@@ -419,7 +419,7 @@ static void sriov_disable(struct pci_dev *dev)
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
iov->nr_virtfn = 0;
iov->num_VFs = 0;
}
static int sriov_init(struct pci_dev *dev, int pos)
@@ -496,7 +496,7 @@ found:
iov->pos = pos;
iov->nres = nres;
iov->ctrl = ctrl;
iov->total = total;
iov->total_VFs = total;
iov->offset = offset;
iov->stride = stride;
iov->pgsz = pgsz;
@@ -529,7 +529,7 @@ failed:
static void sriov_release(struct pci_dev *dev)
{
BUG_ON(dev->sriov->nr_virtfn);
BUG_ON(dev->sriov->num_VFs);
if (dev != dev->sriov->dev)
pci_dev_put(dev->sriov->dev);
@@ -554,7 +554,7 @@ static void sriov_restore_state(struct pci_dev *dev)
pci_update_resource(dev, i);
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->num_VFs);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
if (iov->ctrl & PCI_SRIOV_CTRL_VFE)
msleep(100);
@@ -661,7 +661,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
if (!dev->is_physfn)
continue;
busnr = virtfn_bus(dev, dev->sriov->total - 1);
busnr = virtfn_bus(dev, dev->sriov->total_VFs - 1);
if (busnr > max)
max = busnr;
}
@@ -729,9 +729,56 @@ EXPORT_SYMBOL_GPL(pci_sriov_migration);
*/
int pci_num_vf(struct pci_dev *dev)
{
if (!dev || !dev->is_physfn)
if (!dev->is_physfn)
return 0;
else
return dev->sriov->nr_virtfn;
return dev->sriov->num_VFs;
}
EXPORT_SYMBOL_GPL(pci_num_vf);
/**
* pci_sriov_set_totalvfs -- reduce the TotalVFs available
* @dev: the PCI PF device
* numvfs: number that should be used for TotalVFs supported
*
* Should be called from PF driver's probe routine with
* device's mutex held.
*
* Returns 0 if PF is an SRIOV-capable device and
* value of numvfs valid. If not a PF with VFS, return -EINVAL;
* if VFs already enabled, return -EBUSY.
*/
int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs)
{
if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs))
return -EINVAL;
/* Shouldn't change if VFs already enabled */
if (dev->sriov->ctrl & PCI_SRIOV_CTRL_VFE)
return -EBUSY;
else
dev->sriov->driver_max_VFs = numvfs;
return 0;
}
EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs);
/**
* pci_sriov_get_totalvfs -- get total VFs supported on this devic3
* @dev: the PCI PF device
*
* For a PCIe device with SRIOV support, return the PCIe
* SRIOV capability value of TotalVFs or the value of driver_max_VFs
* if the driver reduced it. Otherwise, -EINVAL.
*/
int pci_sriov_get_totalvfs(struct pci_dev *dev)
{
if (!dev->is_physfn)
return -EINVAL;
if (dev->sriov->driver_max_VFs)
return dev->sriov->driver_max_VFs;
return dev->sriov->total_VFs;
}
EXPORT_SYMBOL_GPL(pci_sriov_get_totalvfs);
+5 -5
View File
@@ -14,11 +14,11 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)
{
struct pci_dev *parent = to_pci_dev(pdev->dev.parent);
dev_printk(KERN_ERR, &pdev->dev,
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
dev_name(&parent->dev), parent->vendor, parent->device);
dev_printk(KERN_ERR, &pdev->dev, "%s\n", reason);
dev_printk(KERN_ERR, &pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
dev_err(&pdev->dev,
"Potentially misrouted IRQ (Bridge %s %04x:%04x)\n",
dev_name(&parent->dev), parent->vendor, parent->device);
dev_err(&pdev->dev, "%s\n", reason);
dev_err(&pdev->dev, "Please report to linux-kernel@vger.kernel.org\n");
WARN_ON(1);
}
+43 -30
View File
@@ -248,31 +248,26 @@ struct drv_dev_and_id {
static long local_pci_probe(void *_ddi)
{
struct drv_dev_and_id *ddi = _ddi;
struct device *dev = &ddi->dev->dev;
struct device *parent = dev->parent;
struct pci_dev *pci_dev = ddi->dev;
struct pci_driver *pci_drv = ddi->drv;
struct device *dev = &pci_dev->dev;
int rc;
/* The parent bridge must be in active state when probing */
if (parent)
pm_runtime_get_sync(parent);
/* Unbound PCI devices are always set to disabled and suspended.
* During probe, the device is set to enabled and active and the
* usage count is incremented. If the driver supports runtime PM,
* it should call pm_runtime_put_noidle() in its probe routine and
* pm_runtime_get_noresume() in its remove routine.
/*
* Unbound PCI devices are always put in D0, regardless of
* runtime PM status. During probe, the device is set to
* active and the usage count is incremented. If the driver
* supports runtime PM, it should call pm_runtime_put_noidle()
* in its probe routine and pm_runtime_get_noresume() in its
* remove routine.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
rc = ddi->drv->probe(ddi->dev, ddi->id);
pm_runtime_get_sync(dev);
pci_dev->driver = pci_drv;
rc = pci_drv->probe(pci_dev, ddi->id);
if (rc) {
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
pci_dev->driver = NULL;
pm_runtime_put_sync(dev);
}
if (parent)
pm_runtime_put(parent);
return rc;
}
@@ -322,10 +317,8 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
id = pci_match_device(drv, pci_dev);
if (id)
error = pci_call_probe(drv, pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
if (error >= 0)
error = 0;
}
}
return error;
}
@@ -361,9 +354,7 @@ static int pci_device_remove(struct device * dev)
}
/* Undo the runtime PM settings in local_pci_probe() */
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
pm_runtime_put_noidle(dev);
pm_runtime_put_sync(dev);
/*
* If the device is still on, set the power state as "unknown",
@@ -986,6 +977,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
pci_power_t prev = pci_dev->current_state;
int error;
/*
* If pci_dev->driver is not set (unbound), the device should
* always remain in D0 regardless of the runtime PM status
*/
if (!pci_dev->driver)
return 0;
if (!pm || !pm->runtime_suspend)
return -ENOSYS;
@@ -1007,10 +1005,10 @@ static int pci_pm_runtime_suspend(struct device *dev)
return 0;
}
if (!pci_dev->state_saved)
if (!pci_dev->state_saved) {
pci_save_state(pci_dev);
pci_finish_runtime_suspend(pci_dev);
pci_finish_runtime_suspend(pci_dev);
}
return 0;
}
@@ -1021,6 +1019,13 @@ static int pci_pm_runtime_resume(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
/*
* If pci_dev->driver is not set (unbound), the device should
* always remain in D0 regardless of the runtime PM status
*/
if (!pci_dev->driver)
return 0;
if (!pm || !pm->runtime_resume)
return -ENOSYS;
@@ -1038,8 +1043,16 @@ static int pci_pm_runtime_resume(struct device *dev)
static int pci_pm_runtime_idle(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
/*
* If pci_dev->driver is not set (unbound), the device should
* always remain in D0 regardless of the runtime PM status
*/
if (!pci_dev->driver)
goto out;
if (!pm)
return -ENOSYS;
@@ -1049,8 +1062,8 @@ static int pci_pm_runtime_idle(struct device *dev)
return ret;
}
out:
pm_runtime_suspend(dev);
return 0;
}
+1 -1
View File
@@ -28,7 +28,7 @@ MODULE_PARM_DESC(ids, "Initial PCI IDs to add to the stub driver, format is "
static int pci_stub_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
dev_printk(KERN_INFO, &dev->dev, "claimed by stub\n");
dev_info(&dev->dev, "claimed by stub\n");
return 0;
}
+161 -11
View File
@@ -401,6 +401,106 @@ static ssize_t d3cold_allowed_show(struct device *dev,
}
#endif
#ifdef CONFIG_PCI_IOV
static ssize_t sriov_totalvfs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
}
static ssize_t sriov_numvfs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
}
/*
* num_vfs > 0; number of vfs to enable
* num_vfs = 0; disable all vfs
*
* Note: SRIOV spec doesn't allow partial VF
* disable, so its all or none.
*/
static ssize_t sriov_numvfs_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
int num_vfs_enabled = 0;
int num_vfs;
int ret = 0;
u16 total;
if (kstrtoint(buf, 0, &num_vfs) < 0)
return -EINVAL;
/* is PF driver loaded w/callback */
if (!pdev->driver || !pdev->driver->sriov_configure) {
dev_info(&pdev->dev,
"Driver doesn't support SRIOV configuration via sysfs\n");
return -ENOSYS;
}
/* if enabling vf's ... */
total = pci_sriov_get_totalvfs(pdev);
/* Requested VFs to enable < totalvfs and none enabled already */
if ((num_vfs > 0) && (num_vfs <= total)) {
if (pdev->sriov->num_VFs == 0) {
num_vfs_enabled =
pdev->driver->sriov_configure(pdev, num_vfs);
if ((num_vfs_enabled >= 0) &&
(num_vfs_enabled != num_vfs)) {
dev_warn(&pdev->dev,
"Only %d VFs enabled\n",
num_vfs_enabled);
return count;
} else if (num_vfs_enabled < 0)
/* error code from driver callback */
return num_vfs_enabled;
} else if (num_vfs == pdev->sriov->num_VFs) {
dev_warn(&pdev->dev,
"%d VFs already enabled; no enable action taken\n",
num_vfs);
return count;
} else {
dev_warn(&pdev->dev,
"%d VFs already enabled. Disable before enabling %d VFs\n",
pdev->sriov->num_VFs, num_vfs);
return -EINVAL;
}
}
/* disable vfs */
if (num_vfs == 0) {
if (pdev->sriov->num_VFs != 0) {
ret = pdev->driver->sriov_configure(pdev, 0);
return ret ? ret : count;
} else {
dev_warn(&pdev->dev,
"All VFs disabled; no disable action taken\n");
return count;
}
}
dev_err(&pdev->dev,
"Invalid value for number of VFs to enable: %d\n", num_vfs);
return -EINVAL;
}
static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
static struct device_attribute sriov_numvfs_attr =
__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
sriov_numvfs_show, sriov_numvfs_store);
#endif /* CONFIG_PCI_IOV */
struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
@@ -1262,29 +1362,20 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
pdev->rom_attr = attr;
}
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
retval = device_create_file(&pdev->dev, &vga_attr);
if (retval)
goto err_rom_file;
}
/* add platform-specific attributes */
retval = pcibios_add_platform_entries(pdev);
if (retval)
goto err_vga_file;
goto err_rom_file;
/* add sysfs entries for various capabilities */
retval = pci_create_capabilities_sysfs(pdev);
if (retval)
goto err_vga_file;
goto err_rom_file;
pci_create_firmware_label_files(pdev);
return 0;
err_vga_file:
if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
device_remove_file(&pdev->dev, &vga_attr);
err_rom_file:
if (rom_size) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
@@ -1370,3 +1461,62 @@ static int __init pci_sysfs_init(void)
}
late_initcall(pci_sysfs_init);
static struct attribute *pci_dev_dev_attrs[] = {
&vga_attr.attr,
NULL,
};
static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct pci_dev *pdev = to_pci_dev(dev);
if (a == &vga_attr.attr)
if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
return 0;
return a->mode;
}
#ifdef CONFIG_PCI_IOV
static struct attribute *sriov_dev_attrs[] = {
&sriov_totalvfs_attr.attr,
&sriov_numvfs_attr.attr,
NULL,
};
static umode_t sriov_attrs_are_visible(struct kobject *kobj,
struct attribute *a, int n)
{
struct device *dev = container_of(kobj, struct device, kobj);
if (!dev_is_pf(dev))
return 0;
return a->mode;
}
static struct attribute_group sriov_dev_attr_group = {
.attrs = sriov_dev_attrs,
.is_visible = sriov_attrs_are_visible,
};
#endif /* CONFIG_PCI_IOV */
static struct attribute_group pci_dev_attr_group = {
.attrs = pci_dev_dev_attrs,
.is_visible = pci_dev_attrs_are_visible,
};
static const struct attribute_group *pci_dev_attr_groups[] = {
&pci_dev_attr_group,
#ifdef CONFIG_PCI_IOV
&sriov_dev_attr_group,
#endif
NULL,
};
struct device_type pci_dev_type = {
.groups = pci_dev_attr_groups,
};
+36 -12
View File
@@ -1333,6 +1333,19 @@ void pcim_pin_device(struct pci_dev *pdev)
dr->pinned = 1;
}
/*
* pcibios_add_device - provide arch specific hooks when adding device dev
* @dev: the PCI device being added
*
* Permits the platform to provide architecture specific functionality when
* devices are added. This is the default implementation. Architecture
* implementations can override this.
*/
int __weak pcibios_add_device (struct pci_dev *dev)
{
return 0;
}
/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
@@ -1578,15 +1591,25 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
/* PCI (as opposed to PCIe) PME requires that the device have
its PME# line hooked up correctly. Not all hardware vendors
do this, so the PME never gets delivered and the device
remains asleep. The easiest way around this is to
periodically walk the list of suspended devices and check
whether any have their PME flag set. The assumption is that
we'll wake up often enough anyway that this won't be a huge
hit, and the power savings from the devices will still be a
win. */
/*
* PCI (as opposed to PCIe) PME requires that the device have
* its PME# line hooked up correctly. Not all hardware vendors
* do this, so the PME never gets delivered and the device
* remains asleep. The easiest way around this is to
* periodically walk the list of suspended devices and check
* whether any have their PME flag set. The assumption is that
* we'll wake up often enough anyway that this won't be a huge
* hit, and the power savings from the devices will still be a
* win.
*
* Although PCIe uses in-band PME message instead of PME# line
* to report PME, PME does not work for some PCIe devices in
* reality. For example, there are devices that set their PME
* status bits, but don't really bother to send a PME message;
* there are PCI Express Root Ports that don't bother to
* trigger interrupts when they receive PME messages from the
* devices below. So PME poll is used for PCIe devices too.
*/
if (dev->pme_poll) {
struct pci_pme_device *pme_dev;
@@ -1900,6 +1923,8 @@ void pci_pm_init(struct pci_dev *dev)
u16 pmc;
pm_runtime_forbid(&dev->dev);
pm_runtime_set_active(&dev->dev);
pm_runtime_enable(&dev->dev);
device_enable_async_suspend(&dev->dev);
dev->wakeup_prepared = false;
@@ -3865,14 +3890,13 @@ static void pci_no_domains(void)
}
/**
* pci_ext_cfg_enabled - can we access extended PCI config space?
* @dev: The PCI device of the root bridge.
* pci_ext_cfg_avail - can we access extended PCI config space?
*
* Returns 1 if we can access PCI extended config space (offsets
* greater than 0xff). This is the default implementation. Architecture
* implementations can override this.
*/
int __weak pci_ext_cfg_avail(struct pci_dev *dev)
int __weak pci_ext_cfg_avail(void)
{
return 1;
}
+5 -3
View File
@@ -158,6 +158,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
}
extern struct device_attribute pci_dev_attrs[];
extern struct device_attribute pcibus_dev_attrs[];
extern struct device_type pci_dev_type;
extern struct bus_attribute pci_bus_attrs[];
@@ -229,13 +230,14 @@ struct pci_sriov {
int nres; /* number of resources */
u32 cap; /* SR-IOV Capabilities */
u16 ctrl; /* SR-IOV Control */
u16 total; /* total VFs associated with the PF */
u16 initial; /* initial VFs associated with the PF */
u16 nr_virtfn; /* number of VFs available */
u16 total_VFs; /* total VFs associated with the PF */
u16 initial_VFs; /* initial VFs associated with the PF */
u16 num_VFs; /* number of VFs available */
u16 offset; /* first VF Routing ID offset */
u16 stride; /* following VF stride */
u32 pgsz; /* page size for BAR alignment */
u8 link; /* Function Dependency Link */
u16 driver_max_VFs; /* max num VFs driver supports */
struct pci_dev *dev; /* lowest numbered PF */
struct pci_dev *self; /* this PF */
struct mutex lock; /* lock for VF bus */
+4 -1
View File
@@ -87,6 +87,9 @@ struct aer_broadcast_data {
static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
enum pci_ers_result new)
{
if (new == PCI_ERS_RESULT_NO_AER_DRIVER)
return PCI_ERS_RESULT_NO_AER_DRIVER;
if (new == PCI_ERS_RESULT_NONE)
return orig;
@@ -97,7 +100,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
break;
case PCI_ERS_RESULT_DISCONNECT:
if (new == PCI_ERS_RESULT_NEED_RESET)
orig = new;
orig = PCI_ERS_RESULT_NEED_RESET;
break;
default:
break;
+18 -4
View File
@@ -232,13 +232,27 @@ static int report_error_detected(struct pci_dev *dev, void *data)
dev->driver ?
"no AER-aware driver" : "no driver");
}
goto out;
/*
* If there's any device in the subtree that does not
* have an error_detected callback, returning
* PCI_ERS_RESULT_NO_AER_DRIVER prevents calling of
* the subsequent mmio_enabled/slot_reset/resume
* callbacks of "any" device in the subtree. All the
* devices in the subtree are left in the error state
* without recovery.
*/
if (!(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE))
vote = PCI_ERS_RESULT_NO_AER_DRIVER;
else
vote = PCI_ERS_RESULT_NONE;
} else {
err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state);
}
err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state);
result_data->result = merge_result(result_data->result, vote);
out:
device_unlock(&dev->dev);
return 0;
}
+8 -10
View File
@@ -242,8 +242,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
return;
/* Training failed. Restore common clock configurations */
dev_printk(KERN_ERR, &parent->dev,
"ASPM: Could not configure common clock\n");
dev_err(&parent->dev, "ASPM: Could not configure common clock\n");
list_for_each_entry(child, &linkbus->devices, bus_list)
pcie_capability_write_word(child, PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]);
@@ -427,7 +426,8 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{
pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, 0x3, val);
pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, val);
}
static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
@@ -442,12 +442,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
return;
/* Convert ASPM state to upstream/downstream ASPM register state */
if (state & ASPM_STATE_L0S_UP)
dwstream |= PCIE_LINK_STATE_L0S;
dwstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L0S_DW)
upstream |= PCIE_LINK_STATE_L0S;
upstream |= PCI_EXP_LNKCTL_ASPM_L0S;
if (state & ASPM_STATE_L1) {
upstream |= PCIE_LINK_STATE_L1;
dwstream |= PCIE_LINK_STATE_L1;
upstream |= PCI_EXP_LNKCTL_ASPM_L1;
dwstream |= PCI_EXP_LNKCTL_ASPM_L1;
}
/*
* Spec 2.0 suggests all functions should be configured the
@@ -507,9 +507,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
*/
pcie_capability_read_dword(child, PCI_EXP_DEVCAP, &reg32);
if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) {
dev_printk(KERN_INFO, &child->dev, "disabling ASPM"
" on pre-1.1 PCIe device. You can enable it"
" with 'pcie_aspm=force'\n");
dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n");
return -EINVAL;
}
}
+1 -2
View File
@@ -120,8 +120,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
* the value in this field indicates which MSI-X Table entry is
* used to generate the interrupt message."
*/
pos = pci_pcie_cap(dev);
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
if (entry >= nr_entries)
goto Error;
+34 -8
View File
@@ -521,7 +521,7 @@ static unsigned char pcie_link_speed[] = {
void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
{
bus->cur_bus_speed = pcie_link_speed[linksta & 0xf];
bus->cur_bus_speed = pcie_link_speed[linksta & PCI_EXP_LNKSTA_CLS];
}
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
@@ -579,14 +579,16 @@ static void pci_set_bus_speed(struct pci_bus *bus)
if (pos) {
u16 status;
enum pci_bus_speed max;
pci_read_config_word(bridge, pos + 2, &status);
if (status & 0x8000) {
pci_read_config_word(bridge, pos + PCI_X_BRIDGE_SSTATUS,
&status);
if (status & PCI_X_SSTATUS_533MHZ) {
max = PCI_SPEED_133MHz_PCIX_533;
} else if (status & 0x4000) {
} else if (status & PCI_X_SSTATUS_266MHZ) {
max = PCI_SPEED_133MHz_PCIX_266;
} else if (status & 0x0002) {
if (((status >> 12) & 0x3) == 2) {
} else if (status & PCI_X_SSTATUS_133MHZ) {
if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) {
max = PCI_SPEED_133MHz_PCIX_ECC;
} else {
max = PCI_SPEED_133MHz_PCIX;
@@ -596,7 +598,8 @@ static void pci_set_bus_speed(struct pci_bus *bus)
}
bus->max_bus_speed = max;
bus->cur_bus_speed = pcix_bus_speed[(status >> 6) & 0xf];
bus->cur_bus_speed = pcix_bus_speed[
(status & PCI_X_SSTATUS_FREQ) >> 6];
return;
}
@@ -607,7 +610,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)
u16 linksta;
pcie_capability_read_dword(bridge, PCI_EXP_LNKCAP, &linkcap);
bus->max_bus_speed = pcie_link_speed[linkcap & 0xf];
bus->max_bus_speed = pcie_link_speed[linkcap & PCI_EXP_LNKCAP_SLS];
pcie_capability_read_word(bridge, PCI_EXP_LNKSTA, &linksta);
pcie_update_link_speed(bus, linksta);
@@ -975,6 +978,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->sysdata = dev->bus->sysdata;
dev->dev.parent = dev->bus->bridge;
dev->dev.bus = &pci_bus_type;
dev->dev.type = &pci_dev_type;
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
@@ -1889,6 +1893,28 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
return max;
}
/**
* pci_rescan_bus - scan a PCI bus for devices.
* @bus: PCI bus to scan
*
* Scan a PCI bus and child buses for new devices, adds them,
* and enables them.
*
* Returns the max number of subordinate bus discovered.
*/
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
{
unsigned int max;
max = pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
return max;
}
EXPORT_SYMBOL_GPL(pci_rescan_bus);
EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge);
+39
View File
@@ -1790,6 +1790,45 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA_2,
PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE,
quirk_tc86c001_ide);
/*
* PLX PCI 9050 PCI Target bridge controller has an errata that prevents the
* local configuration registers accessible via BAR0 (memory) or BAR1 (i/o)
* being read correctly if bit 7 of the base address is set.
* The BAR0 or BAR1 region may be disabled (size 0) or enabled (size 128).
* Re-allocate the regions to a 256-byte boundary if necessary.
*/
static void quirk_plx_pci9050(struct pci_dev *dev)
{
unsigned int bar;
/* Fixed in revision 2 (PCI 9052). */
if (dev->revision >= 2)
return;
for (bar = 0; bar <= 1; bar++)
if (pci_resource_len(dev, bar) == 0x80 &&
(pci_resource_start(dev, bar) & 0x80)) {
struct resource *r = &dev->resource[bar];
dev_info(&dev->dev,
"Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",
bar);
r->start = 0;
r->end = 0xff;
}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
quirk_plx_pci9050);
/*
* The following Meilhaus (vendor ID 0x1402) device IDs (amongst others)
* may be using the PLX PCI 9050: 0x0630, 0x0940, 0x0950, 0x0960, 0x100b,
* 0x1400, 0x140a, 0x140b, 0x14e0, 0x14ea, 0x14eb, 0x1604, 0x1608, 0x160c,
* 0x168f, 0x2000, 0x2600, 0x3000, 0x810a, 0x810b.
*
* Currently, device IDs 0x2000 and 0x2600 are used by the Comedi "me_daq"
* driver.
*/
DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2000, quirk_plx_pci9050);
DECLARE_PCI_FIXUP_HEADER(0x1402, 0x2600, quirk_plx_pci9050);
static void quirk_netmos(struct pci_dev *dev)
{
unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4;
+36
View File
@@ -111,3 +111,39 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)
pci_remove_bus_device(dev);
}
EXPORT_SYMBOL(pci_stop_and_remove_bus_device);
void pci_stop_root_bus(struct pci_bus *bus)
{
struct pci_dev *child, *tmp;
struct pci_host_bridge *host_bridge;
if (!pci_is_root_bus(bus))
return;
host_bridge = to_pci_host_bridge(bus->bridge);
list_for_each_entry_safe_reverse(child, tmp,
&bus->devices, bus_list)
pci_stop_bus_device(child);
/* stop the host bridge */
device_del(&host_bridge->dev);
}
void pci_remove_root_bus(struct pci_bus *bus)
{
struct pci_dev *child, *tmp;
struct pci_host_bridge *host_bridge;
if (!pci_is_root_bus(bus))
return;
host_bridge = to_pci_host_bridge(bus->bridge);
list_for_each_entry_safe(child, tmp,
&bus->devices, bus_list)
pci_remove_bus_device(child);
pci_remove_bus(bus);
host_bridge->bus = NULL;
/* remove the host bridge */
put_device(&host_bridge->dev);
}
+9 -2
View File
@@ -117,12 +117,18 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
loff_t start;
void __iomem *rom;
/*
* Some devices may provide ROMs via a source other than the BAR
*/
if (pdev->rom && pdev->romlen) {
*size = pdev->romlen;
return phys_to_virt(pdev->rom);
/*
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
* memory map if the VGA enable bit of the Bridge Control register is
* set for embedded VGA.
*/
if (res->flags & IORESOURCE_ROM_SHADOW) {
} else if (res->flags & IORESOURCE_ROM_SHADOW) {
/* primary video rom always starts here */
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
@@ -181,7 +187,8 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;
iounmap(rom);
if (!pdev->rom || !pdev->romlen)
iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
+1 -21
View File
@@ -1550,25 +1550,12 @@ enable_all:
}
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
#ifdef CONFIG_HOTPLUG
/**
* pci_rescan_bus - scan a PCI bus for devices.
* @bus: PCI bus to scan
*
* Scan a PCI bus and child buses for new devices, adds them,
* and enables them.
*
* Returns the max number of subordinate bus discovered.
*/
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
void pci_assign_unassigned_bus_resources(struct pci_bus *bus)
{
unsigned int max;
struct pci_dev *dev;
LIST_HEAD(add_list); /* list of resources that
want additional resources */
max = pci_scan_child_bus(bus);
down_read(&pci_bus_sem);
list_for_each_entry(dev, &bus->devices, bus_list)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
@@ -1579,11 +1566,4 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
up_read(&pci_bus_sem);
__pci_bus_assign_resources(bus, &add_list, NULL);
BUG_ON(!list_empty(&add_list));
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
return max;
}
EXPORT_SYMBOL_GPL(pci_rescan_bus);
#endif
+4 -1
View File
@@ -1068,13 +1068,16 @@ static void __init_refok pcifront_backend_changed(struct xenbus_device *xdev,
case XenbusStateInitialising:
case XenbusStateInitWait:
case XenbusStateInitialised:
case XenbusStateClosed:
break;
case XenbusStateConnected:
pcifront_try_connect(pdev);
break;
case XenbusStateClosed:
if (xdev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
dev_warn(&xdev->dev, "backend going away!\n");
pcifront_try_disconnect(pdev);