diff options
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
| -rw-r--r-- | drivers/usb/host/pci-quirks.c | 117 |
1 files changed, 74 insertions, 43 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 1d586d4f7b56..9b166d70ae91 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
| @@ -84,65 +84,92 @@ int usb_amd_find_chipset_info(void) | |||
| 84 | { | 84 | { |
| 85 | u8 rev = 0; | 85 | u8 rev = 0; |
| 86 | unsigned long flags; | 86 | unsigned long flags; |
| 87 | struct amd_chipset_info info; | ||
| 88 | int ret; | ||
| 87 | 89 | ||
| 88 | spin_lock_irqsave(&amd_lock, flags); | 90 | spin_lock_irqsave(&amd_lock, flags); |
| 89 | 91 | ||
| 90 | amd_chipset.probe_count++; | ||
| 91 | /* probe only once */ | 92 | /* probe only once */ |
| 92 | if (amd_chipset.probe_count > 1) { | 93 | if (amd_chipset.probe_count > 0) { |
| 94 | amd_chipset.probe_count++; | ||
| 93 | spin_unlock_irqrestore(&amd_lock, flags); | 95 | spin_unlock_irqrestore(&amd_lock, flags); |
| 94 | return amd_chipset.probe_result; | 96 | return amd_chipset.probe_result; |
| 95 | } | 97 | } |
| 98 | memset(&info, 0, sizeof(info)); | ||
| 99 | spin_unlock_irqrestore(&amd_lock, flags); | ||
| 96 | 100 | ||
| 97 | amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); | 101 | info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); |
| 98 | if (amd_chipset.smbus_dev) { | 102 | if (info.smbus_dev) { |
| 99 | rev = amd_chipset.smbus_dev->revision; | 103 | rev = info.smbus_dev->revision; |
| 100 | if (rev >= 0x40) | 104 | if (rev >= 0x40) |
| 101 | amd_chipset.sb_type = 1; | 105 | info.sb_type = 1; |
| 102 | else if (rev >= 0x30 && rev <= 0x3b) | 106 | else if (rev >= 0x30 && rev <= 0x3b) |
| 103 | amd_chipset.sb_type = 3; | 107 | info.sb_type = 3; |
| 104 | } else { | 108 | } else { |
| 105 | amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, | 109 | info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, |
| 106 | 0x780b, NULL); | 110 | 0x780b, NULL); |
| 107 | if (!amd_chipset.smbus_dev) { | 111 | if (!info.smbus_dev) { |
| 108 | spin_unlock_irqrestore(&amd_lock, flags); | 112 | ret = 0; |
| 109 | return 0; | 113 | goto commit; |
| 110 | } | 114 | } |
| 111 | rev = amd_chipset.smbus_dev->revision; | 115 | |
| 116 | rev = info.smbus_dev->revision; | ||
| 112 | if (rev >= 0x11 && rev <= 0x18) | 117 | if (rev >= 0x11 && rev <= 0x18) |
| 113 | amd_chipset.sb_type = 2; | 118 | info.sb_type = 2; |
| 114 | } | 119 | } |
| 115 | 120 | ||
| 116 | if (amd_chipset.sb_type == 0) { | 121 | if (info.sb_type == 0) { |
| 117 | if (amd_chipset.smbus_dev) { | 122 | if (info.smbus_dev) { |
| 118 | pci_dev_put(amd_chipset.smbus_dev); | 123 | pci_dev_put(info.smbus_dev); |
| 119 | amd_chipset.smbus_dev = NULL; | 124 | info.smbus_dev = NULL; |
| 120 | } | 125 | } |
| 121 | spin_unlock_irqrestore(&amd_lock, flags); | 126 | ret = 0; |
| 122 | return 0; | 127 | goto commit; |
| 123 | } | 128 | } |
| 124 | 129 | ||
| 125 | amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL); | 130 | info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL); |
| 126 | if (amd_chipset.nb_dev) { | 131 | if (info.nb_dev) { |
| 127 | amd_chipset.nb_type = 1; | 132 | info.nb_type = 1; |
| 128 | } else { | 133 | } else { |
| 129 | amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, | 134 | info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); |
| 130 | 0x1510, NULL); | 135 | if (info.nb_dev) { |
| 131 | if (amd_chipset.nb_dev) { | 136 | info.nb_type = 2; |
| 132 | amd_chipset.nb_type = 2; | 137 | } else { |
| 133 | } else { | 138 | info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, |
| 134 | amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, | 139 | 0x9600, NULL); |
| 135 | 0x9600, NULL); | 140 | if (info.nb_dev) |
| 136 | if (amd_chipset.nb_dev) | 141 | info.nb_type = 3; |
| 137 | amd_chipset.nb_type = 3; | ||
| 138 | } | 142 | } |
| 139 | } | 143 | } |
| 140 | 144 | ||
| 141 | amd_chipset.probe_result = 1; | 145 | ret = info.probe_result = 1; |
| 142 | printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n"); | 146 | printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n"); |
| 143 | 147 | ||
| 144 | spin_unlock_irqrestore(&amd_lock, flags); | 148 | commit: |
| 145 | return amd_chipset.probe_result; | 149 | |
| 150 | spin_lock_irqsave(&amd_lock, flags); | ||
| 151 | if (amd_chipset.probe_count > 0) { | ||
| 152 | /* race - someone else was faster - drop devices */ | ||
| 153 | |||
| 154 | /* Mark that we where here */ | ||
| 155 | amd_chipset.probe_count++; | ||
| 156 | ret = amd_chipset.probe_result; | ||
| 157 | |||
| 158 | spin_unlock_irqrestore(&amd_lock, flags); | ||
| 159 | |||
| 160 | if (info.nb_dev) | ||
| 161 | pci_dev_put(info.nb_dev); | ||
| 162 | if (info.smbus_dev) | ||
| 163 | pci_dev_put(info.smbus_dev); | ||
| 164 | |||
| 165 | } else { | ||
| 166 | /* no race - commit the result */ | ||
| 167 | info.probe_count++; | ||
| 168 | amd_chipset = info; | ||
| 169 | spin_unlock_irqrestore(&amd_lock, flags); | ||
| 170 | } | ||
| 171 | |||
| 172 | return ret; | ||
| 146 | } | 173 | } |
| 147 | EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); | 174 | EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); |
| 148 | 175 | ||
| @@ -284,6 +311,7 @@ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable); | |||
| 284 | 311 | ||
| 285 | void usb_amd_dev_put(void) | 312 | void usb_amd_dev_put(void) |
| 286 | { | 313 | { |
| 314 | struct pci_dev *nb, *smbus; | ||
| 287 | unsigned long flags; | 315 | unsigned long flags; |
| 288 | 316 | ||
| 289 | spin_lock_irqsave(&amd_lock, flags); | 317 | spin_lock_irqsave(&amd_lock, flags); |
| @@ -294,20 +322,23 @@ void usb_amd_dev_put(void) | |||
| 294 | return; | 322 | return; |
| 295 | } | 323 | } |
| 296 | 324 | ||
| 297 | if (amd_chipset.nb_dev) { | 325 | /* save them to pci_dev_put outside of spinlock */ |
| 298 | pci_dev_put(amd_chipset.nb_dev); | 326 | nb = amd_chipset.nb_dev; |
| 299 | amd_chipset.nb_dev = NULL; | 327 | smbus = amd_chipset.smbus_dev; |
| 300 | } | 328 | |
| 301 | if (amd_chipset.smbus_dev) { | 329 | amd_chipset.nb_dev = NULL; |
| 302 | pci_dev_put(amd_chipset.smbus_dev); | 330 | amd_chipset.smbus_dev = NULL; |
| 303 | amd_chipset.smbus_dev = NULL; | ||
| 304 | } | ||
| 305 | amd_chipset.nb_type = 0; | 331 | amd_chipset.nb_type = 0; |
| 306 | amd_chipset.sb_type = 0; | 332 | amd_chipset.sb_type = 0; |
| 307 | amd_chipset.isoc_reqs = 0; | 333 | amd_chipset.isoc_reqs = 0; |
| 308 | amd_chipset.probe_result = 0; | 334 | amd_chipset.probe_result = 0; |
| 309 | 335 | ||
| 310 | spin_unlock_irqrestore(&amd_lock, flags); | 336 | spin_unlock_irqrestore(&amd_lock, flags); |
| 337 | |||
| 338 | if (nb) | ||
| 339 | pci_dev_put(nb); | ||
| 340 | if (smbus) | ||
| 341 | pci_dev_put(smbus); | ||
| 311 | } | 342 | } |
| 312 | EXPORT_SYMBOL_GPL(usb_amd_dev_put); | 343 | EXPORT_SYMBOL_GPL(usb_amd_dev_put); |
| 313 | 344 | ||
