Merge branches 'pci/enumeration', 'pci/hotplug', 'pci/resource' and 'pci/virtualization' into next
* pci/enumeration: PCI: Generate uppercase hex for modalias var in uevent * pci/hotplug: PCI: pciehp: Handle surprise add even if surprise removal isn't supported * pci/resource: PCI: Fix infinite loop with ROM image of size 0 * pci/virtualization: PCI: Add Wellsburg (X99) to Intel PCH root port ACS quirk PCI: Add DMA alias quirk for Adaptec 3405 PCI: Add ACS quirk for Emulex NICs PCI: Mark AMD/ATI VGA devices that don't reset on D3hot->D0 transition PCI: Add flag for devices that don't reset on D3hot->D0 transition PCI: Mark Atheros AR93xx to avoid bus reset PCI: Add flag for devices where we can't use bus reset
This commit is contained in:
Коммит
341f3a2bcf
|
@ -532,8 +532,6 @@ static void interrupt_event_handler(struct work_struct *work)
|
|||
pciehp_green_led_off(p_slot);
|
||||
break;
|
||||
case INT_PRESENCE_ON:
|
||||
if (!HP_SUPR_RM(ctrl))
|
||||
break;
|
||||
ctrl_dbg(ctrl, "Surprise Insertion\n");
|
||||
handle_surprise_event(p_slot);
|
||||
break;
|
||||
|
|
|
@ -1383,7 +1383,7 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||
if (add_uevent_var(env, "PCI_SLOT_NAME=%s", pci_name(pdev)))
|
||||
return -ENOMEM;
|
||||
|
||||
if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
|
||||
if (add_uevent_var(env, "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X",
|
||||
pdev->vendor, pdev->device,
|
||||
pdev->subsystem_vendor, pdev->subsystem_device,
|
||||
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
|
||||
|
|
|
@ -3199,7 +3199,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)
|
|||
{
|
||||
u16 csr;
|
||||
|
||||
if (!dev->pm_cap)
|
||||
if (!dev->pm_cap || dev->dev_flags & PCI_DEV_FLAGS_NO_PM_RESET)
|
||||
return -ENOTTY;
|
||||
|
||||
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &csr);
|
||||
|
@ -3273,7 +3273,8 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
|
|||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self)
|
||||
if (pci_is_root_bus(dev->bus) || dev->subordinate ||
|
||||
!dev->bus->self || dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
|
||||
return -ENOTTY;
|
||||
|
||||
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
|
||||
|
@ -3307,7 +3308,8 @@ static int pci_dev_reset_slot_function(struct pci_dev *dev, int probe)
|
|||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
if (dev->subordinate || !dev->slot)
|
||||
if (dev->subordinate || !dev->slot ||
|
||||
dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET)
|
||||
return -ENOTTY;
|
||||
|
||||
list_for_each_entry(pdev, &dev->bus->devices, bus_list)
|
||||
|
@ -3559,6 +3561,20 @@ int pci_try_reset_function(struct pci_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_try_reset_function);
|
||||
|
||||
/* Do any devices on or below this bus prevent a bus reset? */
|
||||
static bool pci_bus_resetable(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
|
||||
(dev->subordinate && !pci_bus_resetable(dev->subordinate)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Lock devices from the top of the tree down */
|
||||
static void pci_bus_lock(struct pci_bus *bus)
|
||||
{
|
||||
|
@ -3609,6 +3625,22 @@ unlock:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Do any devices on or below this slot prevent a bus reset? */
|
||||
static bool pci_slot_resetable(struct pci_slot *slot)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &slot->bus->devices, bus_list) {
|
||||
if (!dev->slot || dev->slot != slot)
|
||||
continue;
|
||||
if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
|
||||
(dev->subordinate && !pci_bus_resetable(dev->subordinate)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Lock devices from the top of the tree down */
|
||||
static void pci_slot_lock(struct pci_slot *slot)
|
||||
{
|
||||
|
@ -3730,7 +3762,7 @@ static int pci_slot_reset(struct pci_slot *slot, int probe)
|
|||
{
|
||||
int rc;
|
||||
|
||||
if (!slot)
|
||||
if (!slot || !pci_slot_resetable(slot))
|
||||
return -ENOTTY;
|
||||
|
||||
if (!probe)
|
||||
|
@ -3822,7 +3854,7 @@ EXPORT_SYMBOL_GPL(pci_try_reset_slot);
|
|||
|
||||
static int pci_bus_reset(struct pci_bus *bus, int probe)
|
||||
{
|
||||
if (!bus->self)
|
||||
if (!bus->self || !pci_bus_resetable(bus))
|
||||
return -ENOTTY;
|
||||
|
||||
if (probe)
|
||||
|
|
|
@ -3028,6 +3028,41 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169,
|
|||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, PCI_ANY_ID,
|
||||
quirk_broken_intx_masking);
|
||||
|
||||
static void quirk_no_bus_reset(struct pci_dev *dev)
|
||||
{
|
||||
dev->dev_flags |= PCI_DEV_FLAGS_NO_BUS_RESET;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atheros AR93xx chips do not behave after a bus reset. The device will
|
||||
* throw a Link Down error on AER-capable systems and regardless of AER,
|
||||
* config space of the device is never accessible again and typically
|
||||
* causes the system to hang or reset when access is attempted.
|
||||
* http://www.spinics.net/lists/linux-pci/msg34797.html
|
||||
*/
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
|
||||
|
||||
static void quirk_no_pm_reset(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* We can't do a bus reset on root bus devices, but an ineffective
|
||||
* PM reset may be better than nothing.
|
||||
*/
|
||||
if (!pci_is_root_bus(dev->bus))
|
||||
dev->dev_flags |= PCI_DEV_FLAGS_NO_PM_RESET;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some AMD/ATI GPUS (HD8570 - Oland) report that a D3hot->D0 transition
|
||||
* causes a reset (i.e., they advertise NoSoftRst-). This transition seems
|
||||
* to have no effect on the device: it retains the framebuffer contents and
|
||||
* monitor sync. Advertising this support makes other layers, like VFIO,
|
||||
* assume pci_reset_function() is viable for this device. Mark it as
|
||||
* unavailable to skip it when testing reset methods.
|
||||
*/
|
||||
DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
|
||||
PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
* Apple: Shutdown Cactus Ridge Thunderbolt controller.
|
||||
|
@ -3527,6 +3562,44 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON,
|
|||
PCI_DEVICE_ID_JMICRON_JMB388_ESD,
|
||||
quirk_dma_func1_alias);
|
||||
|
||||
/*
|
||||
* Some devices DMA with the wrong devfn, not just the wrong function.
|
||||
* quirk_fixed_dma_alias() uses this table to create fixed aliases, where
|
||||
* the alias is "fixed" and independent of the device devfn.
|
||||
*
|
||||
* For example, the Adaptec 3405 is a PCIe card with an Intel 80333 I/O
|
||||
* processor. To software, this appears as a PCIe-to-PCI/X bridge with a
|
||||
* single device on the secondary bus. In reality, the single exposed
|
||||
* device at 0e.0 is the Address Translation Unit (ATU) of the controller
|
||||
* that provides a bridge to the internal bus of the I/O processor. The
|
||||
* controller supports private devices, which can be hidden from PCI config
|
||||
* space. In the case of the Adaptec 3405, a private device at 01.0
|
||||
* appears to be the DMA engine, which therefore needs to become a DMA
|
||||
* alias for the device.
|
||||
*/
|
||||
static const struct pci_device_id fixed_dma_alias_tbl[] = {
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x0285,
|
||||
PCI_VENDOR_ID_ADAPTEC2, 0x02bb), /* Adaptec 3405 */
|
||||
.driver_data = PCI_DEVFN(1, 0) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static void quirk_fixed_dma_alias(struct pci_dev *dev)
|
||||
{
|
||||
const struct pci_device_id *id;
|
||||
|
||||
id = pci_match_id(fixed_dma_alias_tbl, dev);
|
||||
if (id) {
|
||||
dev->dma_alias_devfn = id->driver_data;
|
||||
dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
|
||||
dev_info(&dev->dev, "Enabling fixed DMA alias to %02x.%d\n",
|
||||
PCI_SLOT(dev->dma_alias_devfn),
|
||||
PCI_FUNC(dev->dma_alias_devfn));
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADAPTEC2, 0x0285, quirk_fixed_dma_alias);
|
||||
|
||||
/*
|
||||
* A few PCIe-to-PCI bridges fail to expose a PCIe capability, resulting in
|
||||
* using the wrong DMA alias for the device. Some of these devices can be
|
||||
|
@ -3630,6 +3703,9 @@ static const u16 pci_quirk_intel_pch_acs_ids[] = {
|
|||
0x9c98, 0x9c99, 0x9c9a, 0x9c9b,
|
||||
/* Patsburg (X79) PCH */
|
||||
0x1d10, 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e,
|
||||
/* Wellsburg (X99) PCH */
|
||||
0x8d10, 0x8d11, 0x8d12, 0x8d13, 0x8d14, 0x8d15, 0x8d16, 0x8d17,
|
||||
0x8d18, 0x8d19, 0x8d1a, 0x8d1b, 0x8d1c, 0x8d1d, 0x8d1e,
|
||||
};
|
||||
|
||||
static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev)
|
||||
|
@ -3713,6 +3789,8 @@ static const struct pci_dev_acs_enabled {
|
|||
{ PCI_VENDOR_ID_INTEL, 0x1551, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_INTEL, 0x1558, pci_quirk_mf_endpoint_acs },
|
||||
{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
|
||||
{ 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
|
||||
{ 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
|
|||
{
|
||||
void __iomem *image;
|
||||
int last_image;
|
||||
unsigned length;
|
||||
|
||||
image = rom;
|
||||
do {
|
||||
|
@ -93,9 +94,9 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size)
|
|||
if (readb(pds + 3) != 'R')
|
||||
break;
|
||||
last_image = readb(pds + 21) & 0x80;
|
||||
/* this length is reliable */
|
||||
image += readw(pds + 16) * 512;
|
||||
} while (!last_image);
|
||||
length = readw(pds + 16);
|
||||
image += length * 512;
|
||||
} while (length && !last_image);
|
||||
|
||||
/* never return a size larger than the PCI resource window */
|
||||
/* there are known ROMs that get the size wrong */
|
||||
|
|
|
@ -175,6 +175,10 @@ enum pci_dev_flags {
|
|||
PCI_DEV_FLAGS_DMA_ALIAS_DEVFN = (__force pci_dev_flags_t) (1 << 4),
|
||||
/* Use a PCIe-to-PCI bridge alias even if !pci_is_pcie */
|
||||
PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS = (__force pci_dev_flags_t) (1 << 5),
|
||||
/* Do not use bus resets for device */
|
||||
PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6),
|
||||
/* Do not use PM reset even if device advertises NoSoftRst- */
|
||||
PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
|
||||
};
|
||||
|
||||
enum pci_irq_reroute_variant {
|
||||
|
|
Загрузка…
Ссылка в новой задаче