aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c195
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");
32MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); 32MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
33MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); 33MODULE_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 */
45static struct list_head sn_hp_list; 46static 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
56struct pcibr_slot_enable_resp { 58struct pcibr_slot_enable_resp {
@@ -70,7 +72,7 @@ enum sn_pci_req_e {
70 72
71static int enable_slot(struct hotplug_slot *slot); 73static int enable_slot(struct hotplug_slot *slot);
72static int disable_slot(struct hotplug_slot *slot); 74static int disable_slot(struct hotplug_slot *slot);
73static int get_power_status(struct hotplug_slot *slot, u8 *value); 75static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
74 76
75static struct hotplug_slot_ops sn_hotplug_slot_ops = { 77static 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
82static DECLARE_MUTEX(sn_hotplug_sem); 84static DECLARE_MUTEX(sn_hotplug_sem);
83 85
86static 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
99static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
100
84static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) 101static 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,
175static struct hotplug_slot * sn_hp_destroy(void) 191static 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
191static void sn_bus_alloc_data(struct pci_dev *dev) 207static 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
209static void sn_bus_free_data(struct pci_dev *dev) 222static 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
226static 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
238static 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
248static 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
258static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, 236static 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,
298static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, 277static 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
352static int enable_slot(struct hotplug_slot *bss_hotplug_slot) 332static 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
432static int disable_slot(struct hotplug_slot *bss_hotplug_slot) 410static 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
480static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value) 458static 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__);