You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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;
|
||||
|
||||
@@ -125,3 +125,5 @@ static void __exit ioapic_exit(void)
|
||||
|
||||
module_init(ioapic_init);
|
||||
module_exit(ioapic_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
+67
-20
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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, ®32);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, ®16);
|
||||
pcie_capability_read_word(dev, PCI_EXP_FLAGS, ®16);
|
||||
entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
|
||||
if (entry >= nr_entries)
|
||||
goto Error;
|
||||
|
||||
+34
-8
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user