Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: PCI: pci_slot: grab refcount on slot's bus PCI Hotplug: acpiphp: grab refcount on p2p subordinate bus PCI: allow PCI core hotplug to remove PCI root bus PCI: Fix oops in pci_vpd_truncate PCI: don't corrupt enable_cnt when doing manual resource alignment PCI: annotate pci_rescan_bus as __ref, not __devinit PCI-IOV: fix missing kernel-doc PCI: Setup disabled bridges even if buses are added PCI: SR-IOV quirk for Intel 82576 NIC
This commit is contained in:
commit
8e2c4f2844
|
@ -164,6 +164,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||||
list_add(&slot->list, &slot_list);
|
list_add(&slot->list, &slot_list);
|
||||||
mutex_unlock(&slot_list_lock);
|
mutex_unlock(&slot_list_lock);
|
||||||
|
|
||||||
|
get_device(&pci_bus->dev);
|
||||||
|
|
||||||
dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
|
dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
|
||||||
pci_slot, pci_bus->number, device, name);
|
pci_slot, pci_bus->number, device, name);
|
||||||
|
|
||||||
|
@ -310,12 +312,15 @@ static void
|
||||||
acpi_pci_slot_remove(acpi_handle handle)
|
acpi_pci_slot_remove(acpi_handle handle)
|
||||||
{
|
{
|
||||||
struct acpi_pci_slot *slot, *tmp;
|
struct acpi_pci_slot *slot, *tmp;
|
||||||
|
struct pci_bus *pbus;
|
||||||
|
|
||||||
mutex_lock(&slot_list_lock);
|
mutex_lock(&slot_list_lock);
|
||||||
list_for_each_entry_safe(slot, tmp, &slot_list, list) {
|
list_for_each_entry_safe(slot, tmp, &slot_list, list) {
|
||||||
if (slot->root_handle == handle) {
|
if (slot->root_handle == handle) {
|
||||||
list_del(&slot->list);
|
list_del(&slot->list);
|
||||||
|
pbus = slot->pci_slot->bus;
|
||||||
pci_destroy_slot(slot->pci_slot);
|
pci_destroy_slot(slot->pci_slot);
|
||||||
|
put_device(&pbus->dev);
|
||||||
kfree(slot);
|
kfree(slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
|
||||||
|
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||||
if (dev->subordinate) {
|
if (dev->subordinate) {
|
||||||
if (atomic_read(&dev->enable_cnt) == 0) {
|
if (!pci_is_enabled(dev)) {
|
||||||
retval = pci_enable_device(dev);
|
retval = pci_enable_device(dev);
|
||||||
pci_set_master(dev);
|
pci_set_master(dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
* - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
|
* - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()
|
||||||
* when the bridge is scanned and it loses a refcount when the bridge
|
* when the bridge is scanned and it loses a refcount when the bridge
|
||||||
* is removed.
|
* is removed.
|
||||||
|
* - When a P2P bridge is present, we elevate the refcount on the subordinate
|
||||||
|
* bus. It loses the refcount when the the driver unloads.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
@ -440,6 +442,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grab a ref to the subordinate PCI bus in case the bus is
|
||||||
|
* removed via PCI core logical hotplug. The ref pins the bus
|
||||||
|
* (which we access during module unload).
|
||||||
|
*/
|
||||||
|
get_device(&bridge->pci_bus->dev);
|
||||||
spin_lock_init(&bridge->res_lock);
|
spin_lock_init(&bridge->res_lock);
|
||||||
|
|
||||||
init_bridge_misc(bridge);
|
init_bridge_misc(bridge);
|
||||||
|
@ -619,6 +627,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
|
||||||
slot = next;
|
slot = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only P2P bridges have a pci_dev
|
||||||
|
*/
|
||||||
|
if (bridge->pci_dev)
|
||||||
|
put_device(&bridge->pci_bus->dev);
|
||||||
|
|
||||||
pci_dev_put(bridge->pci_dev);
|
pci_dev_put(bridge->pci_dev);
|
||||||
list_del(&bridge->list);
|
list_del(&bridge->list);
|
||||||
kfree(bridge);
|
kfree(bridge);
|
||||||
|
|
|
@ -631,6 +631,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
|
||||||
/**
|
/**
|
||||||
* pci_enable_sriov - enable the SR-IOV capability
|
* pci_enable_sriov - enable the SR-IOV capability
|
||||||
* @dev: the PCI device
|
* @dev: the PCI device
|
||||||
|
* @nr_virtfn: number of virtual functions to enable
|
||||||
*
|
*
|
||||||
* Returns 0 on success, or negative on failure.
|
* Returns 0 on success, or negative on failure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (!val) {
|
if (!val) {
|
||||||
if (atomic_read(&pdev->enable_cnt) != 0)
|
if (pci_is_enabled(pdev))
|
||||||
pci_disable_device(pdev);
|
pci_disable_device(pdev);
|
||||||
else
|
else
|
||||||
result = -EIO;
|
result = -EIO;
|
||||||
|
@ -277,14 +277,10 @@ remove_store(struct device *dev, struct device_attribute *dummy,
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
|
||||||
|
|
||||||
if (strict_strtoul(buf, 0, &val) < 0)
|
if (strict_strtoul(buf, 0, &val) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (pci_is_root_bus(pdev->bus))
|
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
/* An attribute cannot be unregistered by one of its own methods,
|
/* An attribute cannot be unregistered by one of its own methods,
|
||||||
* so we have to use this roundabout approach.
|
* so we have to use this roundabout approach.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -844,7 +844,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
|
||||||
*/
|
*/
|
||||||
int pci_reenable_device(struct pci_dev *dev)
|
int pci_reenable_device(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
if (atomic_read(&dev->enable_cnt))
|
if (pci_is_enabled(dev))
|
||||||
return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1042,7 +1042,7 @@ static void do_pci_disable_device(struct pci_dev *dev)
|
||||||
*/
|
*/
|
||||||
void pci_disable_enabled_device(struct pci_dev *dev)
|
void pci_disable_enabled_device(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
if (atomic_read(&dev->enable_cnt))
|
if (pci_is_enabled(dev))
|
||||||
do_pci_disable_device(dev);
|
do_pci_disable_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1220,7 +1220,7 @@ EXPORT_SYMBOL(pci_scan_bus_parented);
|
||||||
*
|
*
|
||||||
* Returns the max number of subordinate bus discovered.
|
* Returns the max number of subordinate bus discovered.
|
||||||
*/
|
*/
|
||||||
unsigned int __devinit pci_rescan_bus(struct pci_bus *bus)
|
unsigned int __ref pci_rescan_bus(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
|
|
|
@ -36,17 +36,18 @@ EXPORT_SYMBOL(pcie_mch_quirk);
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_QUIRKS
|
#ifdef CONFIG_PCI_QUIRKS
|
||||||
/*
|
/*
|
||||||
* This quirk function disables the device and releases resources
|
* This quirk function disables memory decoding and releases memory resources
|
||||||
* which is specified by kernel's boot parameter 'pci=resource_alignment='.
|
* of the device specified by kernel's boot parameter 'pci=resource_alignment='.
|
||||||
* It also rounds up size to specified alignment.
|
* It also rounds up size to specified alignment.
|
||||||
* Later on, the kernel will assign page-aligned memory resource back
|
* Later on, the kernel will assign page-aligned memory resource back
|
||||||
* to that device.
|
* to the device.
|
||||||
*/
|
*/
|
||||||
static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct resource *r;
|
struct resource *r;
|
||||||
resource_size_t align, size;
|
resource_size_t align, size;
|
||||||
|
u16 command;
|
||||||
|
|
||||||
if (!pci_is_reassigndev(dev))
|
if (!pci_is_reassigndev(dev))
|
||||||
return;
|
return;
|
||||||
|
@ -58,8 +59,11 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(&dev->dev, "Disabling device and release resources.\n");
|
dev_info(&dev->dev,
|
||||||
pci_disable_device(dev);
|
"Disabling memory decoding and releasing memory resources.\n");
|
||||||
|
pci_read_config_word(dev, PCI_COMMAND, &command);
|
||||||
|
command &= ~PCI_COMMAND_MEMORY;
|
||||||
|
pci_write_config_word(dev, PCI_COMMAND, command);
|
||||||
|
|
||||||
align = pci_specified_resource_alignment(dev);
|
align = pci_specified_resource_alignment(dev);
|
||||||
for (i=0; i < PCI_BRIDGE_RESOURCES; i++) {
|
for (i=0; i < PCI_BRIDGE_RESOURCES; i++) {
|
||||||
|
@ -2411,6 +2415,54 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
|
||||||
|
|
||||||
#endif /* CONFIG_PCI_MSI */
|
#endif /* CONFIG_PCI_MSI */
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI_IOV
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
|
||||||
|
* SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
|
||||||
|
* old Flash Memory Space.
|
||||||
|
*/
|
||||||
|
static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
int pos, flags;
|
||||||
|
u32 bar, start, size;
|
||||||
|
|
||||||
|
if (PAGE_SIZE > 0x10000)
|
||||||
|
return;
|
||||||
|
|
||||||
|
flags = pci_resource_flags(dev, 0);
|
||||||
|
if ((flags & PCI_BASE_ADDRESS_SPACE) !=
|
||||||
|
PCI_BASE_ADDRESS_SPACE_MEMORY ||
|
||||||
|
(flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
|
||||||
|
PCI_BASE_ADDRESS_MEM_TYPE_32)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
|
||||||
|
if (!pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
|
||||||
|
if (bar & PCI_BASE_ADDRESS_MEM_MASK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
start = pci_resource_start(dev, 1);
|
||||||
|
size = pci_resource_len(dev, 1);
|
||||||
|
if (!start || size != 0x400000 || start & (size - 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_resource_flags(dev, 1) = 0;
|
||||||
|
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
|
||||||
|
pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
|
||||||
|
pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
|
||||||
|
|
||||||
|
dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
|
||||||
|
}
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
|
||||||
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
|
||||||
|
|
||||||
|
#endif /* CONFIG_PCI_IOV */
|
||||||
|
|
||||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||||||
struct pci_fixup *end)
|
struct pci_fixup *end)
|
||||||
{
|
{
|
||||||
|
|
|
@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
|
||||||
struct pci_bus_region region;
|
struct pci_bus_region region;
|
||||||
u32 l, bu, lu, io_upper16;
|
u32 l, bu, lu, io_upper16;
|
||||||
|
|
||||||
if (!pci_is_root_bus(bus) && bus->is_added)
|
if (pci_is_enabled(bridge))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
|
dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
|
||||||
|
|
|
@ -674,6 +674,11 @@ int __must_check pci_reenable_device(struct pci_dev *);
|
||||||
int __must_check pcim_enable_device(struct pci_dev *pdev);
|
int __must_check pcim_enable_device(struct pci_dev *pdev);
|
||||||
void pcim_pin_device(struct pci_dev *pdev);
|
void pcim_pin_device(struct pci_dev *pdev);
|
||||||
|
|
||||||
|
static inline int pci_is_enabled(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
return (atomic_read(&pdev->enable_cnt) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pci_is_managed(struct pci_dev *pdev)
|
static inline int pci_is_managed(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
return pdev->is_managed;
|
return pdev->is_managed;
|
||||||
|
|
Loading…
Reference in a new issue