diff options
author | Scott Murray <scottm@somanetworks.com> | 2005-05-27 16:48:52 -0400 |
---|---|---|
committer | Greg KH <gregkh@suse.de> | 2005-05-31 17:26:38 -0400 |
commit | bcc488ab02254a6e60d749187a632dc3d642d4f8 (patch) | |
tree | 4cd45b4d546cf85c14c442b27f611e048a4d9938 /drivers/pci/hotplug/cpci_hotplug_pci.c | |
parent | af00f9811e0ccbd3db84ddc4cffb0da942653393 (diff) |
[PATCH] PCI Hotplug: more CPCI updates
Here is my third attempt at a patch to further update the CompactPCI
hotplug driver infrastructure to address the pci_enable_device issue
discussed on the list as well as a few other issues I discovered during
some more testing. This version addresses a few more issues pointed out
by Prarit Bhargava. Changes include:
- cpci_enable_device and its recursive calling of pci_enable_device on
new devices removed.
- Use list_rwsem to avoid slot status change races between disable_slot
and check_slots.
- Fixed oopsing in cpci_hp_unregister_bus caused by calling list_del on
a slot after calling pci_hp_deregister.
- Removed kfree calls in cleanup_slots since release_slot will have
done it already.
- Reworked init_slots a bit to fix latch and adapter file updating on
subsequent calls to cpci_hp_start.
- Improved sanity checking in cpci_hp_register_controller.
- Now shut things down correctly in cpci_hotplug_exit.
- Switch to pci_get_slot instead of deprecated pci_find_slot.
- A bunch of CodingStyle fixes.
Signed-off-by: Scott Murray <scottm@somanetworks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/cpci_hotplug_pci.c')
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 144 |
1 files changed, 54 insertions, 90 deletions
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 69eb4fc54f2f..c878028ad215 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * CompactPCI Hot Plug Driver PCI functions | 2 | * CompactPCI Hot Plug Driver PCI functions |
3 | * | 3 | * |
4 | * Copyright (C) 2002 by SOMA Networks, Inc. | 4 | * Copyright (C) 2002,2005 by SOMA Networks, Inc. |
5 | * | 5 | * |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -38,10 +38,10 @@ extern int cpci_debug; | |||
38 | 38 | ||
39 | #define dbg(format, arg...) \ | 39 | #define dbg(format, arg...) \ |
40 | do { \ | 40 | do { \ |
41 | if(cpci_debug) \ | 41 | if (cpci_debug) \ |
42 | printk (KERN_DEBUG "%s: " format "\n", \ | 42 | printk (KERN_DEBUG "%s: " format "\n", \ |
43 | MY_NAME , ## arg); \ | 43 | MY_NAME , ## arg); \ |
44 | } while(0) | 44 | } while (0) |
45 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) | 45 | #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg) |
46 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) | 46 | #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) |
47 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) | 47 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) |
@@ -57,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot) | |||
57 | hs_cap = pci_bus_find_capability(slot->bus, | 57 | hs_cap = pci_bus_find_capability(slot->bus, |
58 | slot->devfn, | 58 | slot->devfn, |
59 | PCI_CAP_ID_CHSWP); | 59 | PCI_CAP_ID_CHSWP); |
60 | if(!hs_cap) { | 60 | if (!hs_cap) |
61 | return 0; | 61 | return 0; |
62 | } | ||
63 | 62 | ||
64 | if(pci_bus_read_config_word(slot->bus, | 63 | if (pci_bus_read_config_word(slot->bus, |
65 | slot->devfn, | 64 | slot->devfn, |
66 | hs_cap + 2, | 65 | hs_cap + 2, |
67 | &hs_csr)) { | 66 | &hs_csr)) |
68 | return 0; | 67 | return 0; |
69 | } | 68 | |
70 | return hs_csr & 0x0008 ? 1 : 0; | 69 | return hs_csr & 0x0008 ? 1 : 0; |
71 | } | 70 | } |
72 | 71 | ||
@@ -78,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status) | |||
78 | hs_cap = pci_bus_find_capability(slot->bus, | 77 | hs_cap = pci_bus_find_capability(slot->bus, |
79 | slot->devfn, | 78 | slot->devfn, |
80 | PCI_CAP_ID_CHSWP); | 79 | PCI_CAP_ID_CHSWP); |
81 | if(!hs_cap) { | 80 | if (!hs_cap) |
82 | return 0; | 81 | return 0; |
83 | } | 82 | if (pci_bus_read_config_word(slot->bus, |
84 | |||
85 | if(pci_bus_read_config_word(slot->bus, | ||
86 | slot->devfn, | 83 | slot->devfn, |
87 | hs_cap + 2, | 84 | hs_cap + 2, |
88 | &hs_csr)) { | 85 | &hs_csr)) |
89 | return 0; | 86 | return 0; |
90 | } | 87 | if (status) |
91 | if(status) { | ||
92 | hs_csr |= HS_CSR_LOO; | 88 | hs_csr |= HS_CSR_LOO; |
93 | } else { | 89 | else |
94 | hs_csr &= ~HS_CSR_LOO; | 90 | hs_csr &= ~HS_CSR_LOO; |
95 | } | 91 | if (pci_bus_write_config_word(slot->bus, |
96 | if(pci_bus_write_config_word(slot->bus, | ||
97 | slot->devfn, | 92 | slot->devfn, |
98 | hs_cap + 2, | 93 | hs_cap + 2, |
99 | hs_csr)) { | 94 | hs_csr)) |
100 | return 0; | 95 | return 0; |
101 | } | ||
102 | return 1; | 96 | return 1; |
103 | } | 97 | } |
104 | 98 | ||
@@ -110,16 +104,13 @@ u16 cpci_get_hs_csr(struct slot* slot) | |||
110 | hs_cap = pci_bus_find_capability(slot->bus, | 104 | hs_cap = pci_bus_find_capability(slot->bus, |
111 | slot->devfn, | 105 | slot->devfn, |
112 | PCI_CAP_ID_CHSWP); | 106 | PCI_CAP_ID_CHSWP); |
113 | if(!hs_cap) { | 107 | if (!hs_cap) |
114 | return 0xFFFF; | 108 | return 0xFFFF; |
115 | } | 109 | if (pci_bus_read_config_word(slot->bus, |
116 | |||
117 | if(pci_bus_read_config_word(slot->bus, | ||
118 | slot->devfn, | 110 | slot->devfn, |
119 | hs_cap + 2, | 111 | hs_cap + 2, |
120 | &hs_csr)) { | 112 | &hs_csr)) |
121 | return 0xFFFF; | 113 | return 0xFFFF; |
122 | } | ||
123 | return hs_csr; | 114 | return hs_csr; |
124 | } | 115 | } |
125 | 116 | ||
@@ -132,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot) | |||
132 | hs_cap = pci_bus_find_capability(slot->bus, | 123 | hs_cap = pci_bus_find_capability(slot->bus, |
133 | slot->devfn, | 124 | slot->devfn, |
134 | PCI_CAP_ID_CHSWP); | 125 | PCI_CAP_ID_CHSWP); |
135 | if(!hs_cap) { | 126 | if (!hs_cap) |
136 | return 0; | 127 | return 0; |
137 | } | 128 | if (pci_bus_read_config_word(slot->bus, |
138 | if(pci_bus_read_config_word(slot->bus, | ||
139 | slot->devfn, | 129 | slot->devfn, |
140 | hs_cap + 2, | 130 | hs_cap + 2, |
141 | &hs_csr)) { | 131 | &hs_csr)) |
142 | return 0; | 132 | return 0; |
143 | } | 133 | if (hs_csr & HS_CSR_INS) { |
144 | if(hs_csr & HS_CSR_INS) { | ||
145 | /* Clear INS (by setting it) */ | 134 | /* Clear INS (by setting it) */ |
146 | if(pci_bus_write_config_word(slot->bus, | 135 | if (pci_bus_write_config_word(slot->bus, |
147 | slot->devfn, | 136 | slot->devfn, |
148 | hs_cap + 2, | 137 | hs_cap + 2, |
149 | hs_csr)) { | 138 | hs_csr)) |
150 | ins = 0; | 139 | ins = 0; |
151 | } | 140 | else |
152 | ins = 1; | 141 | ins = 1; |
153 | } | 142 | } |
154 | return ins; | 143 | return ins; |
155 | } | 144 | } |
@@ -163,18 +152,15 @@ int cpci_check_ext(struct slot* slot) | |||
163 | hs_cap = pci_bus_find_capability(slot->bus, | 152 | hs_cap = pci_bus_find_capability(slot->bus, |
164 | slot->devfn, | 153 | slot->devfn, |
165 | PCI_CAP_ID_CHSWP); | 154 | PCI_CAP_ID_CHSWP); |
166 | if(!hs_cap) { | 155 | if (!hs_cap) |
167 | return 0; | 156 | return 0; |
168 | } | 157 | if (pci_bus_read_config_word(slot->bus, |
169 | if(pci_bus_read_config_word(slot->bus, | ||
170 | slot->devfn, | 158 | slot->devfn, |
171 | hs_cap + 2, | 159 | hs_cap + 2, |
172 | &hs_csr)) { | 160 | &hs_csr)) |
173 | return 0; | 161 | return 0; |
174 | } | 162 | if (hs_csr & HS_CSR_EXT) |
175 | if(hs_csr & HS_CSR_EXT) { | ||
176 | ext = 1; | 163 | ext = 1; |
177 | } | ||
178 | return ext; | 164 | return ext; |
179 | } | 165 | } |
180 | 166 | ||
@@ -186,23 +172,20 @@ int cpci_clear_ext(struct slot* slot) | |||
186 | hs_cap = pci_bus_find_capability(slot->bus, | 172 | hs_cap = pci_bus_find_capability(slot->bus, |
187 | slot->devfn, | 173 | slot->devfn, |
188 | PCI_CAP_ID_CHSWP); | 174 | PCI_CAP_ID_CHSWP); |
189 | if(!hs_cap) { | 175 | if (!hs_cap) |
190 | return -ENODEV; | 176 | return -ENODEV; |
191 | } | 177 | if (pci_bus_read_config_word(slot->bus, |
192 | if(pci_bus_read_config_word(slot->bus, | ||
193 | slot->devfn, | 178 | slot->devfn, |
194 | hs_cap + 2, | 179 | hs_cap + 2, |
195 | &hs_csr)) { | 180 | &hs_csr)) |
196 | return -ENODEV; | 181 | return -ENODEV; |
197 | } | 182 | if (hs_csr & HS_CSR_EXT) { |
198 | if(hs_csr & HS_CSR_EXT) { | ||
199 | /* Clear EXT (by setting it) */ | 183 | /* Clear EXT (by setting it) */ |
200 | if(pci_bus_write_config_word(slot->bus, | 184 | if (pci_bus_write_config_word(slot->bus, |
201 | slot->devfn, | 185 | slot->devfn, |
202 | hs_cap + 2, | 186 | hs_cap + 2, |
203 | hs_csr)) { | 187 | hs_csr)) |
204 | return -ENODEV; | 188 | return -ENODEV; |
205 | } | ||
206 | } | 189 | } |
207 | return 0; | 190 | return 0; |
208 | } | 191 | } |
@@ -215,18 +198,16 @@ int cpci_led_on(struct slot* slot) | |||
215 | hs_cap = pci_bus_find_capability(slot->bus, | 198 | hs_cap = pci_bus_find_capability(slot->bus, |
216 | slot->devfn, | 199 | slot->devfn, |
217 | PCI_CAP_ID_CHSWP); | 200 | PCI_CAP_ID_CHSWP); |
218 | if(!hs_cap) { | 201 | if (!hs_cap) |
219 | return -ENODEV; | 202 | return -ENODEV; |
220 | } | 203 | if (pci_bus_read_config_word(slot->bus, |
221 | if(pci_bus_read_config_word(slot->bus, | ||
222 | slot->devfn, | 204 | slot->devfn, |
223 | hs_cap + 2, | 205 | hs_cap + 2, |
224 | &hs_csr)) { | 206 | &hs_csr)) |
225 | return -ENODEV; | 207 | return -ENODEV; |
226 | } | 208 | if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { |
227 | if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) { | ||
228 | hs_csr |= HS_CSR_LOO; | 209 | hs_csr |= HS_CSR_LOO; |
229 | if(pci_bus_write_config_word(slot->bus, | 210 | if (pci_bus_write_config_word(slot->bus, |
230 | slot->devfn, | 211 | slot->devfn, |
231 | hs_cap + 2, | 212 | hs_cap + 2, |
232 | hs_csr)) { | 213 | hs_csr)) { |
@@ -246,18 +227,16 @@ int cpci_led_off(struct slot* slot) | |||
246 | hs_cap = pci_bus_find_capability(slot->bus, | 227 | hs_cap = pci_bus_find_capability(slot->bus, |
247 | slot->devfn, | 228 | slot->devfn, |
248 | PCI_CAP_ID_CHSWP); | 229 | PCI_CAP_ID_CHSWP); |
249 | if(!hs_cap) { | 230 | if (!hs_cap) |
250 | return -ENODEV; | 231 | return -ENODEV; |
251 | } | 232 | if (pci_bus_read_config_word(slot->bus, |
252 | if(pci_bus_read_config_word(slot->bus, | ||
253 | slot->devfn, | 233 | slot->devfn, |
254 | hs_cap + 2, | 234 | hs_cap + 2, |
255 | &hs_csr)) { | 235 | &hs_csr)) |
256 | return -ENODEV; | 236 | return -ENODEV; |
257 | } | 237 | if (hs_csr & HS_CSR_LOO) { |
258 | if(hs_csr & HS_CSR_LOO) { | ||
259 | hs_csr &= ~HS_CSR_LOO; | 238 | hs_csr &= ~HS_CSR_LOO; |
260 | if(pci_bus_write_config_word(slot->bus, | 239 | if (pci_bus_write_config_word(slot->bus, |
261 | slot->devfn, | 240 | slot->devfn, |
262 | hs_cap + 2, | 241 | hs_cap + 2, |
263 | hs_csr)) { | 242 | hs_csr)) { |
@@ -274,19 +253,6 @@ int cpci_led_off(struct slot* slot) | |||
274 | * Device configuration functions | 253 | * Device configuration functions |
275 | */ | 254 | */ |
276 | 255 | ||
277 | static void cpci_enable_device(struct pci_dev *dev) | ||
278 | { | ||
279 | struct pci_bus *bus; | ||
280 | |||
281 | pci_enable_device(dev); | ||
282 | if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | ||
283 | bus = dev->subordinate; | ||
284 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
285 | cpci_enable_device(dev); | ||
286 | } | ||
287 | } | ||
288 | } | ||
289 | |||
290 | int cpci_configure_slot(struct slot* slot) | 256 | int cpci_configure_slot(struct slot* slot) |
291 | { | 257 | { |
292 | unsigned char busnr; | 258 | unsigned char busnr; |
@@ -294,14 +260,14 @@ int cpci_configure_slot(struct slot* slot) | |||
294 | 260 | ||
295 | dbg("%s - enter", __FUNCTION__); | 261 | dbg("%s - enter", __FUNCTION__); |
296 | 262 | ||
297 | if(slot->dev == NULL) { | 263 | if (slot->dev == NULL) { |
298 | dbg("pci_dev null, finding %02x:%02x:%x", | 264 | dbg("pci_dev null, finding %02x:%02x:%x", |
299 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); | 265 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); |
300 | slot->dev = pci_find_slot(slot->bus->number, slot->devfn); | 266 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
301 | } | 267 | } |
302 | 268 | ||
303 | /* Still NULL? Well then scan for it! */ | 269 | /* Still NULL? Well then scan for it! */ |
304 | if(slot->dev == NULL) { | 270 | if (slot->dev == NULL) { |
305 | int n; | 271 | int n; |
306 | dbg("pci_dev still null"); | 272 | dbg("pci_dev still null"); |
307 | 273 | ||
@@ -311,10 +277,10 @@ int cpci_configure_slot(struct slot* slot) | |||
311 | */ | 277 | */ |
312 | n = pci_scan_slot(slot->bus, slot->devfn); | 278 | n = pci_scan_slot(slot->bus, slot->devfn); |
313 | dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); | 279 | dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); |
314 | if(n > 0) | 280 | if (n > 0) |
315 | pci_bus_add_devices(slot->bus); | 281 | pci_bus_add_devices(slot->bus); |
316 | slot->dev = pci_find_slot(slot->bus->number, slot->devfn); | 282 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
317 | if(slot->dev == NULL) { | 283 | if (slot->dev == NULL) { |
318 | err("Could not find PCI device for slot %02x", slot->number); | 284 | err("Could not find PCI device for slot %02x", slot->number); |
319 | return 1; | 285 | return 1; |
320 | } | 286 | } |
@@ -329,8 +295,6 @@ int cpci_configure_slot(struct slot* slot) | |||
329 | 295 | ||
330 | pci_bus_assign_resources(slot->dev->bus); | 296 | pci_bus_assign_resources(slot->dev->bus); |
331 | 297 | ||
332 | cpci_enable_device(slot->dev); | ||
333 | |||
334 | dbg("%s - exit", __FUNCTION__); | 298 | dbg("%s - exit", __FUNCTION__); |
335 | return 0; | 299 | return 0; |
336 | } | 300 | } |
@@ -341,15 +305,15 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
341 | struct pci_dev *dev; | 305 | struct pci_dev *dev; |
342 | 306 | ||
343 | dbg("%s - enter", __FUNCTION__); | 307 | dbg("%s - enter", __FUNCTION__); |
344 | if(!slot->dev) { | 308 | if (!slot->dev) { |
345 | err("No device for slot %02x\n", slot->number); | 309 | err("No device for slot %02x\n", slot->number); |
346 | return -ENODEV; | 310 | return -ENODEV; |
347 | } | 311 | } |
348 | 312 | ||
349 | for (i = 0; i < 8; i++) { | 313 | for (i = 0; i < 8; i++) { |
350 | dev = pci_find_slot(slot->bus->number, | 314 | dev = pci_get_slot(slot->bus, |
351 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); | 315 | PCI_DEVFN(PCI_SLOT(slot->devfn), i)); |
352 | if(dev) { | 316 | if (dev) { |
353 | pci_remove_bus_device(dev); | 317 | pci_remove_bus_device(dev); |
354 | slot->dev = NULL; | 318 | slot->dev = NULL; |
355 | } | 319 | } |