aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/pci-quirks.c117
1 files changed, 74 insertions, 43 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 1d586d4f7b5..9b166d70ae9 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); 148commit:
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}
147EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); 174EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
148 175
@@ -284,6 +311,7 @@ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
284 311
285void usb_amd_dev_put(void) 312void 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}
312EXPORT_SYMBOL_GPL(usb_amd_dev_put); 343EXPORT_SYMBOL_GPL(usb_amd_dev_put);
313 344