diff options
author | Prarit Bhargava <prarit@sgi.com> | 2005-08-12 10:13:34 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-09-08 17:57:25 -0400 |
commit | 1d2450a4a6eb656798c6282b5ffc8e5f9f52ac14 (patch) | |
tree | 4537680974632dc626368d4fe53e932243d13ac1 | |
parent | c9d8073fd2a0bcb5df973654e988282b523cf553 (diff) |
[PATCH] PCI Hotplug: SGI hotplug driver fixes
These fixes were suggested by pcihpd-discuss, but were dropped in the
initial checkin of the code. These fixes include cleaning up the
hotplug driver sysfs filename, and some minor code cleanups. The driver
also requires at least PROM 4.30, not 4.20.
Signed-off-by: Prarit Bhargava <prarit@sgi.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/pci/hotplug/sgi_hotplug.c | 195 |
1 files changed, 91 insertions, 104 deletions
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 323041fd41dc..b1409441c1cd 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
@@ -32,14 +32,15 @@ MODULE_LICENSE("GPL"); | |||
32 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); | 32 | MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); |
33 | MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); | 33 | MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); |
34 | 34 | ||
35 | #define PCIIO_ASIC_TYPE_TIOCA 4 | 35 | #define PCIIO_ASIC_TYPE_TIOCA 4 |
36 | #define PCI_SLOT_ALREADY_UP 2 /* slot already up */ | 36 | #define PCI_SLOT_ALREADY_UP 2 /* slot already up */ |
37 | #define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ | 37 | #define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ |
38 | #define PCI_L1_ERR 7 /* L1 console command error */ | 38 | #define PCI_L1_ERR 7 /* L1 console command error */ |
39 | #define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ | 39 | #define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ |
40 | #define PCI_L1_QSIZE 128 /* our L1 message buffer size */ | 40 | #define PCI_L1_QSIZE 128 /* our L1 message buffer size */ |
41 | #define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */ | 41 | #define SN_MAX_HP_SLOTS 32 /* max hotplug slots */ |
42 | #define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */ | 42 | #define SGI_HOTPLUG_PROM_REV 0x0430 /* Min. required PROM version */ |
43 | #define SN_SLOT_NAME_SIZE 33 /* size of name string */ | ||
43 | 44 | ||
44 | /* internal list head */ | 45 | /* internal list head */ |
45 | static struct list_head sn_hp_list; | 46 | static struct list_head sn_hp_list; |
@@ -51,6 +52,7 @@ struct slot { | |||
51 | /* this struct for glue internal only */ | 52 | /* this struct for glue internal only */ |
52 | struct hotplug_slot *hotplug_slot; | 53 | struct hotplug_slot *hotplug_slot; |
53 | struct list_head hp_list; | 54 | struct list_head hp_list; |
55 | char physical_path[SN_SLOT_NAME_SIZE]; | ||
54 | }; | 56 | }; |
55 | 57 | ||
56 | struct pcibr_slot_enable_resp { | 58 | struct pcibr_slot_enable_resp { |
@@ -70,7 +72,7 @@ enum sn_pci_req_e { | |||
70 | 72 | ||
71 | static int enable_slot(struct hotplug_slot *slot); | 73 | static int enable_slot(struct hotplug_slot *slot); |
72 | static int disable_slot(struct hotplug_slot *slot); | 74 | static int disable_slot(struct hotplug_slot *slot); |
73 | static int get_power_status(struct hotplug_slot *slot, u8 *value); | 75 | static inline int get_power_status(struct hotplug_slot *slot, u8 *value); |
74 | 76 | ||
75 | static struct hotplug_slot_ops sn_hotplug_slot_ops = { | 77 | static struct hotplug_slot_ops sn_hotplug_slot_ops = { |
76 | .owner = THIS_MODULE, | 78 | .owner = THIS_MODULE, |
@@ -81,6 +83,21 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = { | |||
81 | 83 | ||
82 | static DECLARE_MUTEX(sn_hotplug_sem); | 84 | static DECLARE_MUTEX(sn_hotplug_sem); |
83 | 85 | ||
86 | static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot, | ||
87 | char *buf) | ||
88 | { | ||
89 | int retval = -ENOENT; | ||
90 | struct slot *slot = bss_hotplug_slot->private; | ||
91 | |||
92 | if (!slot) | ||
93 | return retval; | ||
94 | |||
95 | retval = sprintf (buf, "%s\n", slot->physical_path); | ||
96 | return retval; | ||
97 | } | ||
98 | |||
99 | static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path); | ||
100 | |||
84 | static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) | 101 | static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) |
85 | { | 102 | { |
86 | struct pcibus_info *pcibus_info; | 103 | struct pcibus_info *pcibus_info; |
@@ -120,15 +137,15 @@ static int sn_pci_bus_valid(struct pci_bus *pci_bus) | |||
120 | /* Only register slots in I/O Bricks that support hotplug */ | 137 | /* Only register slots in I/O Bricks that support hotplug */ |
121 | bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); | 138 | bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid); |
122 | switch (bricktype) { | 139 | switch (bricktype) { |
123 | case L1_BRICKTYPE_IX: | 140 | case L1_BRICKTYPE_IX: |
124 | case L1_BRICKTYPE_PX: | 141 | case L1_BRICKTYPE_PX: |
125 | case L1_BRICKTYPE_IA: | 142 | case L1_BRICKTYPE_IA: |
126 | case L1_BRICKTYPE_PA: | 143 | case L1_BRICKTYPE_PA: |
127 | return 1; | 144 | return 1; |
128 | break; | 145 | break; |
129 | default: | 146 | default: |
130 | return -EPERM; | 147 | return -EPERM; |
131 | break; | 148 | break; |
132 | } | 149 | } |
133 | 150 | ||
134 | return -EIO; | 151 | return -EIO; |
@@ -142,13 +159,12 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, | |||
142 | 159 | ||
143 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); | 160 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); |
144 | 161 | ||
145 | bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot), | 162 | slot = kcalloc(1, sizeof(*slot), GFP_KERNEL); |
146 | GFP_KERNEL); | 163 | if (!slot) |
147 | if (!bss_hotplug_slot->private) | ||
148 | return -ENOMEM; | 164 | return -ENOMEM; |
149 | slot = (struct slot *)bss_hotplug_slot->private; | 165 | bss_hotplug_slot->private = slot; |
150 | 166 | ||
151 | bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL); | 167 | bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL); |
152 | if (!bss_hotplug_slot->name) { | 168 | if (!bss_hotplug_slot->name) { |
153 | kfree(bss_hotplug_slot->private); | 169 | kfree(bss_hotplug_slot->private); |
154 | return -ENOMEM; | 170 | return -ENOMEM; |
@@ -156,16 +172,16 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, | |||
156 | 172 | ||
157 | slot->device_num = device; | 173 | slot->device_num = device; |
158 | slot->pci_bus = pci_bus; | 174 | slot->pci_bus = pci_bus; |
159 | 175 | sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x", | |
160 | sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d", | 176 | pci_domain_nr(pci_bus), |
177 | ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, | ||
178 | device + 1); | ||
179 | sprintf(slot->physical_path, "module_%c%c%c%c%.2d", | ||
161 | '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), | 180 | '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), |
162 | '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), | 181 | '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), |
163 | '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), | 182 | '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)), |
164 | MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), | 183 | MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid), |
165 | MODULE_GET_BPOS(pcibus_info->pbi_moduleid), | 184 | MODULE_GET_BPOS(pcibus_info->pbi_moduleid)); |
166 | ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf, | ||
167 | device + 1); | ||
168 | |||
169 | slot->hotplug_slot = bss_hotplug_slot; | 185 | slot->hotplug_slot = bss_hotplug_slot; |
170 | list_add(&slot->hp_list, &sn_hp_list); | 186 | list_add(&slot->hp_list, &sn_hp_list); |
171 | 187 | ||
@@ -175,14 +191,14 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot, | |||
175 | static struct hotplug_slot * sn_hp_destroy(void) | 191 | static struct hotplug_slot * sn_hp_destroy(void) |
176 | { | 192 | { |
177 | struct slot *slot; | 193 | struct slot *slot; |
178 | struct list_head *list; | ||
179 | struct hotplug_slot *bss_hotplug_slot = NULL; | 194 | struct hotplug_slot *bss_hotplug_slot = NULL; |
180 | 195 | ||
181 | list_for_each(list, &sn_hp_list) { | 196 | list_for_each_entry(slot, &sn_hp_list, hp_list) { |
182 | slot = list_entry(list, struct slot, hp_list); | ||
183 | bss_hotplug_slot = slot->hotplug_slot; | 197 | bss_hotplug_slot = slot->hotplug_slot; |
184 | list_del(&((struct slot *)bss_hotplug_slot->private)-> | 198 | list_del(&((struct slot *)bss_hotplug_slot->private)-> |
185 | hp_list); | 199 | hp_list); |
200 | sysfs_remove_file(&bss_hotplug_slot->kobj, | ||
201 | &sn_slot_path_attr.attr); | ||
186 | break; | 202 | break; |
187 | } | 203 | } |
188 | return bss_hotplug_slot; | 204 | return bss_hotplug_slot; |
@@ -190,7 +206,6 @@ static struct hotplug_slot * sn_hp_destroy(void) | |||
190 | 206 | ||
191 | static void sn_bus_alloc_data(struct pci_dev *dev) | 207 | static void sn_bus_alloc_data(struct pci_dev *dev) |
192 | { | 208 | { |
193 | struct list_head *node; | ||
194 | struct pci_bus *subordinate_bus; | 209 | struct pci_bus *subordinate_bus; |
195 | struct pci_dev *child; | 210 | struct pci_dev *child; |
196 | 211 | ||
@@ -199,66 +214,29 @@ static void sn_bus_alloc_data(struct pci_dev *dev) | |||
199 | /* Recursively sets up the sn_irq_info structs */ | 214 | /* Recursively sets up the sn_irq_info structs */ |
200 | if (dev->subordinate) { | 215 | if (dev->subordinate) { |
201 | subordinate_bus = dev->subordinate; | 216 | subordinate_bus = dev->subordinate; |
202 | list_for_each(node, &subordinate_bus->devices) { | 217 | list_for_each_entry(child, &subordinate_bus->devices, bus_list) |
203 | child = list_entry(node, struct pci_dev, bus_list); | ||
204 | sn_bus_alloc_data(child); | 218 | sn_bus_alloc_data(child); |
205 | } | ||
206 | } | 219 | } |
207 | } | 220 | } |
208 | 221 | ||
209 | static void sn_bus_free_data(struct pci_dev *dev) | 222 | static void sn_bus_free_data(struct pci_dev *dev) |
210 | { | 223 | { |
211 | struct list_head *node; | ||
212 | struct pci_bus *subordinate_bus; | 224 | struct pci_bus *subordinate_bus; |
213 | struct pci_dev *child; | 225 | struct pci_dev *child; |
214 | 226 | ||
215 | /* Recursively clean up sn_irq_info structs */ | 227 | /* Recursively clean up sn_irq_info structs */ |
216 | if (dev->subordinate) { | 228 | if (dev->subordinate) { |
217 | subordinate_bus = dev->subordinate; | 229 | subordinate_bus = dev->subordinate; |
218 | list_for_each(node, &subordinate_bus->devices) { | 230 | list_for_each_entry(child, &subordinate_bus->devices, bus_list) |
219 | child = list_entry(node, struct pci_dev, bus_list); | ||
220 | sn_bus_free_data(child); | 231 | sn_bus_free_data(child); |
221 | } | ||
222 | } | 232 | } |
223 | sn_pci_unfixup_slot(dev); | 233 | sn_pci_unfixup_slot(dev); |
224 | } | 234 | } |
225 | 235 | ||
226 | static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot) | ||
227 | { | ||
228 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | ||
229 | struct pcibus_info *pcibus_info; | ||
230 | u8 retval; | ||
231 | |||
232 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); | ||
233 | retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); | ||
234 | |||
235 | return retval ? 1 : 0; | ||
236 | } | ||
237 | |||
238 | static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot, | ||
239 | int device_num) | ||
240 | { | ||
241 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | ||
242 | struct pcibus_info *pcibus_info; | ||
243 | |||
244 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); | ||
245 | pcibus_info->pbi_enabled_devices |= (1 << device_num); | ||
246 | } | ||
247 | |||
248 | static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot, | ||
249 | int device_num) | ||
250 | { | ||
251 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | ||
252 | struct pcibus_info *pcibus_info; | ||
253 | |||
254 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); | ||
255 | pcibus_info->pbi_enabled_devices &= ~(1 << device_num); | ||
256 | } | ||
257 | |||
258 | static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, | 236 | static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, |
259 | int device_num) | 237 | int device_num) |
260 | { | 238 | { |
261 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | 239 | struct slot *slot = bss_hotplug_slot->private; |
262 | struct pcibus_info *pcibus_info; | 240 | struct pcibus_info *pcibus_info; |
263 | struct pcibr_slot_enable_resp resp; | 241 | struct pcibr_slot_enable_resp resp; |
264 | int rc; | 242 | int rc; |
@@ -273,7 +251,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, | |||
273 | 251 | ||
274 | if (rc == PCI_SLOT_ALREADY_UP) { | 252 | if (rc == PCI_SLOT_ALREADY_UP) { |
275 | dev_dbg(slot->pci_bus->self, "is already active\n"); | 253 | dev_dbg(slot->pci_bus->self, "is already active\n"); |
276 | return -EPERM; | 254 | return 1; /* return 1 to user */ |
277 | } | 255 | } |
278 | 256 | ||
279 | if (rc == PCI_L1_ERR) { | 257 | if (rc == PCI_L1_ERR) { |
@@ -290,7 +268,8 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, | |||
290 | return -EIO; | 268 | return -EIO; |
291 | } | 269 | } |
292 | 270 | ||
293 | sn_slot_mark_enable(bss_hotplug_slot, device_num); | 271 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); |
272 | pcibus_info->pbi_enabled_devices |= (1 << device_num); | ||
294 | 273 | ||
295 | return 0; | 274 | return 0; |
296 | } | 275 | } |
@@ -298,7 +277,7 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, | |||
298 | static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, | 277 | static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, |
299 | int device_num, int action) | 278 | int device_num, int action) |
300 | { | 279 | { |
301 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | 280 | struct slot *slot = bss_hotplug_slot->private; |
302 | struct pcibus_info *pcibus_info; | 281 | struct pcibus_info *pcibus_info; |
303 | struct pcibr_slot_disable_resp resp; | 282 | struct pcibr_slot_disable_resp resp; |
304 | int rc; | 283 | int rc; |
@@ -307,43 +286,44 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, | |||
307 | 286 | ||
308 | rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp); | 287 | rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp); |
309 | 288 | ||
310 | if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) { | 289 | if ((action == PCI_REQ_SLOT_ELIGIBLE) && |
290 | (rc == PCI_SLOT_ALREADY_DOWN)) { | ||
311 | dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n"); | 291 | dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n"); |
312 | return -ENODEV; | 292 | return 1; /* return 1 to user */ |
313 | } | 293 | } |
314 | 294 | ||
315 | if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_EMPTY_33MHZ) { | 295 | if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) { |
316 | dev_dbg(slot->pci_bus->self, | 296 | dev_dbg(slot->pci_bus->self, |
317 | "Cannot remove last 33MHz card\n"); | 297 | "Cannot remove last 33MHz card\n"); |
318 | return -EPERM; | 298 | return -EPERM; |
319 | } | 299 | } |
320 | 300 | ||
321 | if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_L1_ERR) { | 301 | if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) { |
322 | dev_dbg(slot->pci_bus->self, | 302 | dev_dbg(slot->pci_bus->self, |
323 | "L1 failure %d with message \n%s\n", | 303 | "L1 failure %d with message \n%s\n", |
324 | resp.resp_sub_errno, resp.resp_l1_msg); | 304 | resp.resp_sub_errno, resp.resp_l1_msg); |
325 | return -EPERM; | 305 | return -EPERM; |
326 | } | 306 | } |
327 | 307 | ||
328 | if (action == PCI_REQ_SLOT_ELIGIBLE && rc) { | 308 | if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) { |
329 | dev_dbg(slot->pci_bus->self, | 309 | dev_dbg(slot->pci_bus->self, |
330 | "remove failed with error %d sub-error %d\n", | 310 | "remove failed with error %d sub-error %d\n", |
331 | rc, resp.resp_sub_errno); | 311 | rc, resp.resp_sub_errno); |
332 | return -EIO; | 312 | return -EIO; |
333 | } | 313 | } |
334 | 314 | ||
335 | if (action == PCI_REQ_SLOT_ELIGIBLE && !rc) | 315 | if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc) |
336 | return 0; | 316 | return 0; |
337 | 317 | ||
338 | if (action == PCI_REQ_SLOT_DISABLE && !rc) { | 318 | if ((action == PCI_REQ_SLOT_DISABLE) && !rc) { |
339 | sn_slot_mark_disable(bss_hotplug_slot, device_num); | 319 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); |
320 | pcibus_info->pbi_enabled_devices &= ~(1 << device_num); | ||
340 | dev_dbg(slot->pci_bus->self, "remove successful\n"); | 321 | dev_dbg(slot->pci_bus->self, "remove successful\n"); |
341 | return 0; | 322 | return 0; |
342 | } | 323 | } |
343 | 324 | ||
344 | if (action == PCI_REQ_SLOT_DISABLE && rc) { | 325 | if ((action == PCI_REQ_SLOT_DISABLE) && rc) { |
345 | dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc); | 326 | dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc); |
346 | return rc; | ||
347 | } | 327 | } |
348 | 328 | ||
349 | return rc; | 329 | return rc; |
@@ -351,7 +331,7 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, | |||
351 | 331 | ||
352 | static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | 332 | static int enable_slot(struct hotplug_slot *bss_hotplug_slot) |
353 | { | 333 | { |
354 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | 334 | struct slot *slot = bss_hotplug_slot->private; |
355 | struct pci_bus *new_bus = NULL; | 335 | struct pci_bus *new_bus = NULL; |
356 | struct pci_dev *dev; | 336 | struct pci_dev *dev; |
357 | int func, num_funcs; | 337 | int func, num_funcs; |
@@ -371,8 +351,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
371 | return rc; | 351 | return rc; |
372 | } | 352 | } |
373 | 353 | ||
374 | num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1, | 354 | num_funcs = pci_scan_slot(slot->pci_bus, |
375 | PCI_FUNC(0))); | 355 | PCI_DEVFN(slot->device_num + 1, 0)); |
376 | if (!num_funcs) { | 356 | if (!num_funcs) { |
377 | dev_dbg(slot->pci_bus->self, "no device in slot\n"); | 357 | dev_dbg(slot->pci_bus->self, "no device in slot\n"); |
378 | up(&sn_hotplug_sem); | 358 | up(&sn_hotplug_sem); |
@@ -391,8 +371,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
391 | dev = pci_get_slot(slot->pci_bus, | 371 | dev = pci_get_slot(slot->pci_bus, |
392 | PCI_DEVFN(slot->device_num + 1, | 372 | PCI_DEVFN(slot->device_num + 1, |
393 | PCI_FUNC(func))); | 373 | PCI_FUNC(func))); |
394 | |||
395 | |||
396 | if (dev) { | 374 | if (dev) { |
397 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { | 375 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { |
398 | unsigned char sec_bus; | 376 | unsigned char sec_bus; |
@@ -431,7 +409,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
431 | 409 | ||
432 | static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | 410 | static int disable_slot(struct hotplug_slot *bss_hotplug_slot) |
433 | { | 411 | { |
434 | struct slot *slot = (struct slot *)bss_hotplug_slot->private; | 412 | struct slot *slot = bss_hotplug_slot->private; |
435 | struct pci_dev *dev; | 413 | struct pci_dev *dev; |
436 | int func; | 414 | int func; |
437 | int rc; | 415 | int rc; |
@@ -448,7 +426,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
448 | /* Free the SN resources assigned to the Linux device.*/ | 426 | /* Free the SN resources assigned to the Linux device.*/ |
449 | for (func = 0; func < 8; func++) { | 427 | for (func = 0; func < 8; func++) { |
450 | dev = pci_get_slot(slot->pci_bus, | 428 | dev = pci_get_slot(slot->pci_bus, |
451 | PCI_DEVFN(slot->device_num+1, | 429 | PCI_DEVFN(slot->device_num + 1, |
452 | PCI_FUNC(func))); | 430 | PCI_FUNC(func))); |
453 | if (dev) { | 431 | if (dev) { |
454 | /* | 432 | /* |
@@ -477,10 +455,15 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
477 | return rc; | 455 | return rc; |
478 | } | 456 | } |
479 | 457 | ||
480 | static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value) | 458 | static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, |
459 | u8 *value) | ||
481 | { | 460 | { |
461 | struct slot *slot = bss_hotplug_slot->private; | ||
462 | struct pcibus_info *pcibus_info; | ||
463 | |||
464 | pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); | ||
482 | down(&sn_hotplug_sem); | 465 | down(&sn_hotplug_sem); |
483 | *value = sn_power_status_get(bss_hotplug_slot); | 466 | *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); |
484 | up(&sn_hotplug_sem); | 467 | up(&sn_hotplug_sem); |
485 | return 0; | 468 | return 0; |
486 | } | 469 | } |
@@ -508,7 +491,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) | |||
508 | if (sn_pci_slot_valid(pci_bus, device) != 1) | 491 | if (sn_pci_slot_valid(pci_bus, device) != 1) |
509 | continue; | 492 | continue; |
510 | 493 | ||
511 | bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot), | 494 | bss_hotplug_slot = kcalloc(1, sizeof(*bss_hotplug_slot), |
512 | GFP_KERNEL); | 495 | GFP_KERNEL); |
513 | if (!bss_hotplug_slot) { | 496 | if (!bss_hotplug_slot) { |
514 | rc = -ENOMEM; | 497 | rc = -ENOMEM; |
@@ -516,7 +499,7 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) | |||
516 | } | 499 | } |
517 | 500 | ||
518 | bss_hotplug_slot->info = | 501 | bss_hotplug_slot->info = |
519 | kcalloc(1,sizeof(struct hotplug_slot_info), | 502 | kcalloc(1, sizeof(struct hotplug_slot_info), |
520 | GFP_KERNEL); | 503 | GFP_KERNEL); |
521 | if (!bss_hotplug_slot->info) { | 504 | if (!bss_hotplug_slot->info) { |
522 | rc = -ENOMEM; | 505 | rc = -ENOMEM; |
@@ -535,6 +518,11 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus) | |||
535 | rc = pci_hp_register(bss_hotplug_slot); | 518 | rc = pci_hp_register(bss_hotplug_slot); |
536 | if (rc) | 519 | if (rc) |
537 | goto register_err; | 520 | goto register_err; |
521 | |||
522 | rc = sysfs_create_file(&bss_hotplug_slot->kobj, | ||
523 | &sn_slot_path_attr.attr); | ||
524 | if (rc) | ||
525 | goto register_err; | ||
538 | } | 526 | } |
539 | dev_dbg(pci_bus->self, "Registered bus with hotplug\n"); | 527 | dev_dbg(pci_bus->self, "Registered bus with hotplug\n"); |
540 | return rc; | 528 | return rc; |
@@ -564,14 +552,14 @@ static int sn_pci_hotplug_init(void) | |||
564 | int rc; | 552 | int rc; |
565 | int registered = 0; | 553 | int registered = 0; |
566 | 554 | ||
567 | INIT_LIST_HEAD(&sn_hp_list); | ||
568 | |||
569 | if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { | 555 | if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) { |
570 | printk(KERN_ERR "%s: PROM version must be greater than 4.05\n", | 556 | printk(KERN_ERR "%s: PROM version must be greater than 4.30\n", |
571 | __FUNCTION__); | 557 | __FUNCTION__); |
572 | return -EPERM; | 558 | return -EPERM; |
573 | } | 559 | } |
574 | 560 | ||
561 | INIT_LIST_HEAD(&sn_hp_list); | ||
562 | |||
575 | while ((pci_bus = pci_find_next_bus(pci_bus))) { | 563 | while ((pci_bus = pci_find_next_bus(pci_bus))) { |
576 | if (!pci_bus->sysdata) | 564 | if (!pci_bus->sysdata) |
577 | continue; | 565 | continue; |
@@ -584,9 +572,9 @@ static int sn_pci_hotplug_init(void) | |||
584 | dev_dbg(pci_bus->self, "valid hotplug bus\n"); | 572 | dev_dbg(pci_bus->self, "valid hotplug bus\n"); |
585 | 573 | ||
586 | rc = sn_hotplug_slot_register(pci_bus); | 574 | rc = sn_hotplug_slot_register(pci_bus); |
587 | if (!rc) | 575 | if (!rc) { |
588 | registered = 1; | 576 | registered = 1; |
589 | else { | 577 | } else { |
590 | registered = 0; | 578 | registered = 0; |
591 | break; | 579 | break; |
592 | } | 580 | } |
@@ -599,9 +587,8 @@ static void sn_pci_hotplug_exit(void) | |||
599 | { | 587 | { |
600 | struct hotplug_slot *bss_hotplug_slot; | 588 | struct hotplug_slot *bss_hotplug_slot; |
601 | 589 | ||
602 | while ((bss_hotplug_slot = sn_hp_destroy())) { | 590 | while ((bss_hotplug_slot = sn_hp_destroy())) |
603 | pci_hp_deregister(bss_hotplug_slot); | 591 | pci_hp_deregister(bss_hotplug_slot); |
604 | } | ||
605 | 592 | ||
606 | if (!list_empty(&sn_hp_list)) | 593 | if (!list_empty(&sn_hp_list)) |
607 | printk(KERN_ERR "%s: internal list is not empty\n", __FILE__); | 594 | printk(KERN_ERR "%s: internal list is not empty\n", __FILE__); |