Commit 1d2450a4a6eb656798c6282b5ffc8e5f9f52ac14

Authored by Prarit Bhargava
Committed by Greg Kroah-Hartman
1 parent c9d8073fd2

[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>

Showing 1 changed file with 91 additions and 104 deletions Side-by-side Diff

drivers/pci/hotplug/sgi_hotplug.c
... ... @@ -32,14 +32,15 @@
32 32 MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
33 33 MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
34 34  
35   -#define PCIIO_ASIC_TYPE_TIOCA 4
36   -#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
37   -#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
38   -#define PCI_L1_ERR 7 /* L1 console command error */
39   -#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
40   -#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
41   -#define SN_MAX_HP_SLOTS 32 /* max number of hotplug slots */
42   -#define SGI_HOTPLUG_PROM_REV 0x0420 /* Min. required PROM version */
  35 +#define PCIIO_ASIC_TYPE_TIOCA 4
  36 +#define PCI_SLOT_ALREADY_UP 2 /* slot already up */
  37 +#define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */
  38 +#define PCI_L1_ERR 7 /* L1 console command error */
  39 +#define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */
  40 +#define PCI_L1_QSIZE 128 /* our L1 message buffer size */
  41 +#define SN_MAX_HP_SLOTS 32 /* max hotplug slots */
  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 45 /* internal list head */
45 46 static struct list_head sn_hp_list;
... ... @@ -51,6 +52,7 @@
51 52 /* this struct for glue internal only */
52 53 struct hotplug_slot *hotplug_slot;
53 54 struct list_head hp_list;
  55 + char physical_path[SN_SLOT_NAME_SIZE];
54 56 };
55 57  
56 58 struct pcibr_slot_enable_resp {
... ... @@ -70,7 +72,7 @@
70 72  
71 73 static int enable_slot(struct hotplug_slot *slot);
72 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 77 static struct hotplug_slot_ops sn_hotplug_slot_ops = {
76 78 .owner = THIS_MODULE,
... ... @@ -81,6 +83,21 @@
81 83  
82 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 101 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
85 102 {
86 103 struct pcibus_info *pcibus_info;
... ... @@ -120,15 +137,15 @@
120 137 /* Only register slots in I/O Bricks that support hotplug */
121 138 bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
122 139 switch (bricktype) {
123   - case L1_BRICKTYPE_IX:
124   - case L1_BRICKTYPE_PX:
125   - case L1_BRICKTYPE_IA:
126   - case L1_BRICKTYPE_PA:
127   - return 1;
128   - break;
129   - default:
130   - return -EPERM;
131   - break;
  140 + case L1_BRICKTYPE_IX:
  141 + case L1_BRICKTYPE_PX:
  142 + case L1_BRICKTYPE_IA:
  143 + case L1_BRICKTYPE_PA:
  144 + return 1;
  145 + break;
  146 + default:
  147 + return -EPERM;
  148 + break;
132 149 }
133 150  
134 151 return -EIO;
135 152  
136 153  
... ... @@ -142,13 +159,12 @@
142 159  
143 160 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
144 161  
145   - bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
146   - GFP_KERNEL);
147   - if (!bss_hotplug_slot->private)
  162 + slot = kcalloc(1, sizeof(*slot), GFP_KERNEL);
  163 + if (!slot)
148 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 168 if (!bss_hotplug_slot->name) {
153 169 kfree(bss_hotplug_slot->private);
154 170 return -ENOMEM;
155 171  
... ... @@ -156,16 +172,16 @@
156 172  
157 173 slot->device_num = device;
158 174 slot->pci_bus = pci_bus;
159   -
160   - sprintf(bss_hotplug_slot->name, "module_%c%c%c%c%.2d_b_%d_s_%d",
  175 + sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
  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 180 '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
162 181 '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
163 182 '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
164 183 MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
165   - MODULE_GET_BPOS(pcibus_info->pbi_moduleid),
166   - ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
167   - device + 1);
168   -
  184 + MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
169 185 slot->hotplug_slot = bss_hotplug_slot;
170 186 list_add(&slot->hp_list, &sn_hp_list);
171 187  
172 188  
173 189  
... ... @@ -175,14 +191,14 @@
175 191 static struct hotplug_slot * sn_hp_destroy(void)
176 192 {
177 193 struct slot *slot;
178   - struct list_head *list;
179 194 struct hotplug_slot *bss_hotplug_slot = NULL;
180 195  
181   - list_for_each(list, &sn_hp_list) {
182   - slot = list_entry(list, struct slot, hp_list);
  196 + list_for_each_entry(slot, &sn_hp_list, hp_list) {
183 197 bss_hotplug_slot = slot->hotplug_slot;
184 198 list_del(&((struct slot *)bss_hotplug_slot->private)->
185 199 hp_list);
  200 + sysfs_remove_file(&bss_hotplug_slot->kobj,
  201 + &sn_slot_path_attr.attr);
186 202 break;
187 203 }
188 204 return bss_hotplug_slot;
... ... @@ -190,7 +206,6 @@
190 206  
191 207 static void sn_bus_alloc_data(struct pci_dev *dev)
192 208 {
193   - struct list_head *node;
194 209 struct pci_bus *subordinate_bus;
195 210 struct pci_dev *child;
196 211  
197 212  
198 213  
199 214  
200 215  
201 216  
202 217  
... ... @@ -199,66 +214,29 @@
199 214 /* Recursively sets up the sn_irq_info structs */
200 215 if (dev->subordinate) {
201 216 subordinate_bus = dev->subordinate;
202   - list_for_each(node, &subordinate_bus->devices) {
203   - child = list_entry(node, struct pci_dev, bus_list);
  217 + list_for_each_entry(child, &subordinate_bus->devices, bus_list)
204 218 sn_bus_alloc_data(child);
205   - }
206 219 }
207 220 }
208 221  
209 222 static void sn_bus_free_data(struct pci_dev *dev)
210 223 {
211   - struct list_head *node;
212 224 struct pci_bus *subordinate_bus;
213 225 struct pci_dev *child;
214 226  
215 227 /* Recursively clean up sn_irq_info structs */
216 228 if (dev->subordinate) {
217 229 subordinate_bus = dev->subordinate;
218   - list_for_each(node, &subordinate_bus->devices) {
219   - child = list_entry(node, struct pci_dev, bus_list);
  230 + list_for_each_entry(child, &subordinate_bus->devices, bus_list)
220 231 sn_bus_free_data(child);
221   - }
222 232 }
223 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 236 static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
259 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 240 struct pcibus_info *pcibus_info;
263 241 struct pcibr_slot_enable_resp resp;
264 242 int rc;
... ... @@ -273,7 +251,7 @@
273 251  
274 252 if (rc == PCI_SLOT_ALREADY_UP) {
275 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 257 if (rc == PCI_L1_ERR) {
... ... @@ -290,7 +268,8 @@
290 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 274 return 0;
296 275 }
... ... @@ -298,7 +277,7 @@
298 277 static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
299 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 281 struct pcibus_info *pcibus_info;
303 282 struct pcibr_slot_disable_resp resp;
304 283 int rc;
305 284  
306 285  
307 286  
308 287  
309 288  
310 289  
311 290  
312 291  
... ... @@ -307,43 +286,44 @@
307 286  
308 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 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 296 dev_dbg(slot->pci_bus->self,
317 297 "Cannot remove last 33MHz card\n");
318 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 302 dev_dbg(slot->pci_bus->self,
323 303 "L1 failure %d with message \n%s\n",
324 304 resp.resp_sub_errno, resp.resp_l1_msg);
325 305 return -EPERM;
326 306 }
327 307  
328   - if (action == PCI_REQ_SLOT_ELIGIBLE && rc) {
  308 + if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) {
329 309 dev_dbg(slot->pci_bus->self,
330 310 "remove failed with error %d sub-error %d\n",
331 311 rc, resp.resp_sub_errno);
332 312 return -EIO;
333 313 }
334 314  
335   - if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
  315 + if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc)
336 316 return 0;
337 317  
338   - if (action == PCI_REQ_SLOT_DISABLE && !rc) {
339   - sn_slot_mark_disable(bss_hotplug_slot, device_num);
  318 + if ((action == PCI_REQ_SLOT_DISABLE) && !rc) {
  319 + pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
  320 + pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
340 321 dev_dbg(slot->pci_bus->self, "remove successful\n");
341 322 return 0;
342 323 }
343 324  
344   - if (action == PCI_REQ_SLOT_DISABLE && rc) {
  325 + if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
345 326 dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
346   - return rc;
347 327 }
348 328  
349 329 return rc;
... ... @@ -351,7 +331,7 @@
351 331  
352 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 335 struct pci_bus *new_bus = NULL;
356 336 struct pci_dev *dev;
357 337 int func, num_funcs;
... ... @@ -371,8 +351,8 @@
371 351 return rc;
372 352 }
373 353  
374   - num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
375   - PCI_FUNC(0)));
  354 + num_funcs = pci_scan_slot(slot->pci_bus,
  355 + PCI_DEVFN(slot->device_num + 1, 0));
376 356 if (!num_funcs) {
377 357 dev_dbg(slot->pci_bus->self, "no device in slot\n");
378 358 up(&sn_hotplug_sem);
... ... @@ -391,8 +371,6 @@
391 371 dev = pci_get_slot(slot->pci_bus,
392 372 PCI_DEVFN(slot->device_num + 1,
393 373 PCI_FUNC(func)));
394   -
395   -
396 374 if (dev) {
397 375 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
398 376 unsigned char sec_bus;
... ... @@ -431,7 +409,7 @@
431 409  
432 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 413 struct pci_dev *dev;
436 414 int func;
437 415 int rc;
... ... @@ -448,7 +426,7 @@
448 426 /* Free the SN resources assigned to the Linux device.*/
449 427 for (func = 0; func < 8; func++) {
450 428 dev = pci_get_slot(slot->pci_bus,
451   - PCI_DEVFN(slot->device_num+1,
  429 + PCI_DEVFN(slot->device_num + 1,
452 430 PCI_FUNC(func)));
453 431 if (dev) {
454 432 /*
455 433  
456 434  
... ... @@ -477,10 +455,15 @@
477 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 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 467 up(&sn_hotplug_sem);
485 468 return 0;
486 469 }
... ... @@ -508,7 +491,7 @@
508 491 if (sn_pci_slot_valid(pci_bus, device) != 1)
509 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 495 GFP_KERNEL);
513 496 if (!bss_hotplug_slot) {
514 497 rc = -ENOMEM;
... ... @@ -516,7 +499,7 @@
516 499 }
517 500  
518 501 bss_hotplug_slot->info =
519   - kcalloc(1,sizeof(struct hotplug_slot_info),
  502 + kcalloc(1, sizeof(struct hotplug_slot_info),
520 503 GFP_KERNEL);
521 504 if (!bss_hotplug_slot->info) {
522 505 rc = -ENOMEM;
... ... @@ -535,6 +518,11 @@
535 518 rc = pci_hp_register(bss_hotplug_slot);
536 519 if (rc)
537 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 527 dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
540 528 return rc;
541 529  
542 530  
... ... @@ -564,14 +552,14 @@
564 552 int rc;
565 553 int registered = 0;
566 554  
567   - INIT_LIST_HEAD(&sn_hp_list);
568   -
569 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 557 __FUNCTION__);
572 558 return -EPERM;
573 559 }
574 560  
  561 + INIT_LIST_HEAD(&sn_hp_list);
  562 +
575 563 while ((pci_bus = pci_find_next_bus(pci_bus))) {
576 564 if (!pci_bus->sysdata)
577 565 continue;
578 566  
... ... @@ -584,9 +572,9 @@
584 572 dev_dbg(pci_bus->self, "valid hotplug bus\n");
585 573  
586 574 rc = sn_hotplug_slot_register(pci_bus);
587   - if (!rc)
  575 + if (!rc) {
588 576 registered = 1;
589   - else {
  577 + } else {
590 578 registered = 0;
591 579 break;
592 580 }
593 581  
... ... @@ -599,9 +587,8 @@
599 587 {
600 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 591 pci_hp_deregister(bss_hotplug_slot);
604   - }
605 592  
606 593 if (!list_empty(&sn_hp_list))
607 594 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);