mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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
10 changed files with 88 additions and 15 deletions
|
@ -164,6 +164,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
|||
list_add(&slot->list, &slot_list);
|
||||
mutex_unlock(&slot_list_lock);
|
||||
|
||||
get_device(&pci_bus->dev);
|
||||
|
||||
dbg("pci_slot: %p, pci_bus: %x, device: %d, name: %s\n",
|
||||
pci_slot, pci_bus->number, device, name);
|
||||
|
||||
|
@ -310,12 +312,15 @@ static void
|
|||
acpi_pci_slot_remove(acpi_handle handle)
|
||||
{
|
||||
struct acpi_pci_slot *slot, *tmp;
|
||||
struct pci_bus *pbus;
|
||||
|
||||
mutex_lock(&slot_list_lock);
|
||||
list_for_each_entry_safe(slot, tmp, &slot_list, list) {
|
||||
if (slot->root_handle == handle) {
|
||||
list_del(&slot->list);
|
||||
pbus = slot->pci_slot->bus;
|
||||
pci_destroy_slot(slot->pci_slot);
|
||||
put_device(&pbus->dev);
|
||||
kfree(slot);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ void pci_enable_bridges(struct pci_bus *bus)
|
|||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->subordinate) {
|
||||
if (atomic_read(&dev->enable_cnt) == 0) {
|
||||
if (!pci_is_enabled(dev)) {
|
||||
retval = pci_enable_device(dev);
|
||||
pci_set_master(dev);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
* - 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
|
||||
* 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>
|
||||
|
@ -440,6 +442,12 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)
|
|||
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);
|
||||
|
||||
init_bridge_misc(bridge);
|
||||
|
@ -619,6 +627,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
|
|||
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);
|
||||
list_del(&bridge->list);
|
||||
kfree(bridge);
|
||||
|
|
|
@ -631,6 +631,7 @@ int pci_iov_bus_range(struct pci_bus *bus)
|
|||
/**
|
||||
* pci_enable_sriov - enable the SR-IOV capability
|
||||
* @dev: the PCI device
|
||||
* @nr_virtfn: number of virtual functions to enable
|
||||
*
|
||||
* Returns 0 on success, or negative on failure.
|
||||
*/
|
||||
|
|
|
@ -148,7 +148,7 @@ static ssize_t is_enabled_store(struct device *dev,
|
|||
return -EPERM;
|
||||
|
||||
if (!val) {
|
||||
if (atomic_read(&pdev->enable_cnt) != 0)
|
||||
if (pci_is_enabled(pdev))
|
||||
pci_disable_device(pdev);
|
||||
else
|
||||
result = -EIO;
|
||||
|
@ -277,14 +277,10 @@ remove_store(struct device *dev, struct device_attribute *dummy,
|
|||
{
|
||||
int ret = 0;
|
||||
unsigned long val;
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
|
||||
if (strict_strtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (pci_is_root_bus(pdev->bus))
|
||||
return -EBUSY;
|
||||
|
||||
/* An attribute cannot be unregistered by one of its own methods,
|
||||
* 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)
|
||||
{
|
||||
if (atomic_read(&dev->enable_cnt))
|
||||
if (pci_is_enabled(dev))
|
||||
return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);
|
||||
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)
|
||||
{
|
||||
if (atomic_read(&dev->enable_cnt))
|
||||
if (pci_is_enabled(dev))
|
||||
do_pci_disable_device(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -1220,7 +1220,7 @@ EXPORT_SYMBOL(pci_scan_bus_parented);
|
|||
*
|
||||
* 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;
|
||||
struct pci_dev *dev;
|
||||
|
|
|
@ -36,17 +36,18 @@ EXPORT_SYMBOL(pcie_mch_quirk);
|
|||
|
||||
#ifdef CONFIG_PCI_QUIRKS
|
||||
/*
|
||||
* This quirk function disables the device and releases resources
|
||||
* which is specified by kernel's boot parameter 'pci=resource_alignment='.
|
||||
* This quirk function disables memory decoding and releases memory resources
|
||||
* of the device specified by kernel's boot parameter 'pci=resource_alignment='.
|
||||
* It also rounds up size to specified alignment.
|
||||
* 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)
|
||||
{
|
||||
int i;
|
||||
struct resource *r;
|
||||
resource_size_t align, size;
|
||||
u16 command;
|
||||
|
||||
if (!pci_is_reassigndev(dev))
|
||||
return;
|
||||
|
@ -58,8 +59,11 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
dev_info(&dev->dev, "Disabling device and release resources.\n");
|
||||
pci_disable_device(dev);
|
||||
dev_info(&dev->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);
|
||||
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 */
|
||||
|
||||
#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,
|
||||
struct pci_fixup *end)
|
||||
{
|
||||
|
|
|
@ -144,7 +144,7 @@ static void pci_setup_bridge(struct pci_bus *bus)
|
|||
struct pci_bus_region region;
|
||||
u32 l, bu, lu, io_upper16;
|
||||
|
||||
if (!pci_is_root_bus(bus) && bus->is_added)
|
||||
if (pci_is_enabled(bridge))
|
||||
return;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
return pdev->is_managed;
|
||||
|
|
Loading…
Reference in a new issue