aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/quirks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 19:24:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-21 19:24:54 -0400
commit3bb07f1b73ea6313b843807063e183e168c9182a (patch)
treef0e2ab77b8bc993a843a0edede00668c589863cc /drivers/pci/quirks.c
parent6326c71fd2fb3bef5fa33951479298b683da35fe (diff)
parent5420e46d4d79bcd5d5952df98d022c8412385d32 (diff)
Merge tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas: - Host bridge cleanups from Yinghai - Disable Bus Master bit on PCI device shutdown (kexec-related) - Stratus ftServer fix - pci_dev_reset() locking fix - IvyBridge graphics erratum workaround * tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (21 commits) microblaze/PCI: fix "io_offset undeclared" error x86/PCI: only check for spinlock being held in SMP kernels resources: add resource_overlaps() PCI: fix uninitialized variable 'cap_mask' MAINTAINERS: update PCI git tree and patchwork PCI: disable Bus Master on PCI device shutdown PCI: work around IvyBridge internal graphics FLR erratum x86/PCI: fix unused variable warning in amd_bus.c PCI: move mutex locking out of pci_dev_reset function PCI: work around Stratus ftServer broken PCIe hierarchy x86/PCI: merge pcibios_scan_root() and pci_scan_bus_on_node() x86/PCI: dynamically allocate pci_root_info for native host bridge drivers x86/PCI: embed pci_sysdata into pci_root_info on ACPI path x86/PCI: embed name into pci_root_info struct x86/PCI: add host bridge resource release for _CRS path x86/PCI: refactor get_current_resources() PCI: add host bridge release support PCI: add generic device into pci_host_bridge struct PCI: rename pci_host_bridge() to find_pci_root_bridge() x86/PCI: fix memleak with get_current_resources() ...
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r--drivers/pci/quirks.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 953ec3f08470..2a7521677541 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3097,16 +3097,74 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
3097 return 0; 3097 return 0;
3098} 3098}
3099 3099
3100#include "../gpu/drm/i915/i915_reg.h"
3101#define MSG_CTL 0x45010
3102#define NSDE_PWR_STATE 0xd0100
3103#define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */
3104
3105static int reset_ivb_igd(struct pci_dev *dev, int probe)
3106{
3107 void __iomem *mmio_base;
3108 unsigned long timeout;
3109 u32 val;
3110
3111 if (probe)
3112 return 0;
3113
3114 mmio_base = pci_iomap(dev, 0, 0);
3115 if (!mmio_base)
3116 return -ENOMEM;
3117
3118 iowrite32(0x00000002, mmio_base + MSG_CTL);
3119
3120 /*
3121 * Clobbering SOUTH_CHICKEN2 register is fine only if the next
3122 * driver loaded sets the right bits. However, this's a reset and
3123 * the bits have been set by i915 previously, so we clobber
3124 * SOUTH_CHICKEN2 register directly here.
3125 */
3126 iowrite32(0x00000005, mmio_base + SOUTH_CHICKEN2);
3127
3128 val = ioread32(mmio_base + PCH_PP_CONTROL) & 0xfffffffe;
3129 iowrite32(val, mmio_base + PCH_PP_CONTROL);
3130
3131 timeout = jiffies + msecs_to_jiffies(IGD_OPERATION_TIMEOUT);
3132 do {
3133 val = ioread32(mmio_base + PCH_PP_STATUS);
3134 if ((val & 0xb0000000) == 0)
3135 goto reset_complete;
3136 msleep(10);
3137 } while (time_before(jiffies, timeout));
3138 dev_warn(&dev->dev, "timeout during reset\n");
3139
3140reset_complete:
3141 iowrite32(0x00000002, mmio_base + NSDE_PWR_STATE);
3142
3143 pci_iounmap(dev, mmio_base);
3144 return 0;
3145}
3146
3100#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed 3147#define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed
3148#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
3149#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
3101 3150
3102static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { 3151static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
3103 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, 3152 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
3104 reset_intel_82599_sfp_virtfn }, 3153 reset_intel_82599_sfp_virtfn },
3154 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA,
3155 reset_ivb_igd },
3156 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA,
3157 reset_ivb_igd },
3105 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, 3158 { PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
3106 reset_intel_generic_dev }, 3159 reset_intel_generic_dev },
3107 { 0 } 3160 { 0 }
3108}; 3161};
3109 3162
3163/*
3164 * These device-specific reset methods are here rather than in a driver
3165 * because when a host assigns a device to a guest VM, the host may need
3166 * to reset the device but probably doesn't have a driver for it.
3167 */
3110int pci_dev_specific_reset(struct pci_dev *dev, int probe) 3168int pci_dev_specific_reset(struct pci_dev *dev, int probe)
3111{ 3169{
3112 const struct pci_dev_reset_methods *i; 3170 const struct pci_dev_reset_methods *i;