diff options
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4bf71028556b..6279d5b85993 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -3085,16 +3085,74 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe) | |||
3085 | return 0; | 3085 | return 0; |
3086 | } | 3086 | } |
3087 | 3087 | ||
3088 | #include "../gpu/drm/i915/i915_reg.h" | ||
3089 | #define MSG_CTL 0x45010 | ||
3090 | #define NSDE_PWR_STATE 0xd0100 | ||
3091 | #define IGD_OPERATION_TIMEOUT 10000 /* set timeout 10 seconds */ | ||
3092 | |||
3093 | static int reset_ivb_igd(struct pci_dev *dev, int probe) | ||
3094 | { | ||
3095 | void __iomem *mmio_base; | ||
3096 | unsigned long timeout; | ||
3097 | u32 val; | ||
3098 | |||
3099 | if (probe) | ||
3100 | return 0; | ||
3101 | |||
3102 | mmio_base = pci_iomap(dev, 0, 0); | ||
3103 | if (!mmio_base) | ||
3104 | return -ENOMEM; | ||
3105 | |||
3106 | iowrite32(0x00000002, mmio_base + MSG_CTL); | ||
3107 | |||
3108 | /* | ||
3109 | * Clobbering SOUTH_CHICKEN2 register is fine only if the next | ||
3110 | * driver loaded sets the right bits. However, this's a reset and | ||
3111 | * the bits have been set by i915 previously, so we clobber | ||
3112 | * SOUTH_CHICKEN2 register directly here. | ||
3113 | */ | ||
3114 | iowrite32(0x00000005, mmio_base + SOUTH_CHICKEN2); | ||
3115 | |||
3116 | val = ioread32(mmio_base + PCH_PP_CONTROL) & 0xfffffffe; | ||
3117 | iowrite32(val, mmio_base + PCH_PP_CONTROL); | ||
3118 | |||
3119 | timeout = jiffies + msecs_to_jiffies(IGD_OPERATION_TIMEOUT); | ||
3120 | do { | ||
3121 | val = ioread32(mmio_base + PCH_PP_STATUS); | ||
3122 | if ((val & 0xb0000000) == 0) | ||
3123 | goto reset_complete; | ||
3124 | msleep(10); | ||
3125 | } while (time_before(jiffies, timeout)); | ||
3126 | dev_warn(&dev->dev, "timeout during reset\n"); | ||
3127 | |||
3128 | reset_complete: | ||
3129 | iowrite32(0x00000002, mmio_base + NSDE_PWR_STATE); | ||
3130 | |||
3131 | pci_iounmap(dev, mmio_base); | ||
3132 | return 0; | ||
3133 | } | ||
3134 | |||
3088 | #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed | 3135 | #define PCI_DEVICE_ID_INTEL_82599_SFP_VF 0x10ed |
3136 | #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156 | ||
3137 | #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166 | ||
3089 | 3138 | ||
3090 | static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { | 3139 | static const struct pci_dev_reset_methods pci_dev_reset_methods[] = { |
3091 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, | 3140 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF, |
3092 | reset_intel_82599_sfp_virtfn }, | 3141 | reset_intel_82599_sfp_virtfn }, |
3142 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M_VGA, | ||
3143 | reset_ivb_igd }, | ||
3144 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IVB_M2_VGA, | ||
3145 | reset_ivb_igd }, | ||
3093 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, | 3146 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, |
3094 | reset_intel_generic_dev }, | 3147 | reset_intel_generic_dev }, |
3095 | { 0 } | 3148 | { 0 } |
3096 | }; | 3149 | }; |
3097 | 3150 | ||
3151 | /* | ||
3152 | * These device-specific reset methods are here rather than in a driver | ||
3153 | * because when a host assigns a device to a guest VM, the host may need | ||
3154 | * to reset the device but probably doesn't have a driver for it. | ||
3155 | */ | ||
3098 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) | 3156 | int pci_dev_specific_reset(struct pci_dev *dev, int probe) |
3099 | { | 3157 | { |
3100 | const struct pci_dev_reset_methods *i; | 3158 | const struct pci_dev_reset_methods *i; |