aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorPrarit Bhargava <prarit@sgi.com>2005-08-12 10:13:34 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-09-08 17:57:25 -0400
commit1d2450a4a6eb656798c6282b5ffc8e5f9f52ac14 (patch)
tree4537680974632dc626368d4fe53e932243d13ac1 /drivers/pci/hotplug
parentc9d8073fd2a0bcb5df973654e988282b523cf553 (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>
Diffstat (limited to 'drivers/pci/hotplug')
-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__);