This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / pci / hotplug / sgi_hotplug.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved.
7  *
8  * This work was based on the 2.4/2.6 kernel development by Dick Reigner.
9  * Work to add BIOS PROM support was completed by Mike Habeck.
10  */
11
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/pci.h>
16 #include <linux/proc_fs.h>
17 #include <linux/types.h>
18 #include <linux/mutex.h>
19
20 #include <asm/sn/addrs.h>
21 #include <asm/sn/l1.h>
22 #include <asm/sn/module.h>
23 #include <asm/sn/pcibr_provider.h>
24 #include <asm/sn/pcibus_provider_defs.h>
25 #include <asm/sn/pcidev.h>
26 #include <asm/sn/sn_sal.h>
27 #include <asm/sn/types.h>
28
29 #include "../pci.h"
30 #include "pci_hotplug.h"
31
32 MODULE_LICENSE("GPL");
33 MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
34 MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
35
36 #define PCIIO_ASIC_TYPE_TIOCA           4
37 #define PCI_SLOT_ALREADY_UP             2       /* slot already up */
38 #define PCI_SLOT_ALREADY_DOWN           3       /* slot already down */
39 #define PCI_L1_ERR                      7       /* L1 console command error */
40 #define PCI_EMPTY_33MHZ                 15      /* empty 33 MHz bus */
41 #define PCI_L1_QSIZE                    128     /* our L1 message buffer size */
42 #define SN_MAX_HP_SLOTS                 32      /* max hotplug slots */
43 #define SGI_HOTPLUG_PROM_REV            0x0430  /* Min. required PROM version */
44 #define SN_SLOT_NAME_SIZE               33      /* size of name string */
45
46 /* internal list head */
47 static struct list_head sn_hp_list;
48
49 /* hotplug_slot struct's private pointer */
50 struct slot {
51         int device_num;
52         struct pci_bus *pci_bus;
53         /* this struct for glue internal only */
54         struct hotplug_slot *hotplug_slot;
55         struct list_head hp_list;
56         char physical_path[SN_SLOT_NAME_SIZE];
57 };
58
59 struct pcibr_slot_enable_resp {
60         int resp_sub_errno;
61         char resp_l1_msg[PCI_L1_QSIZE + 1];
62 };
63
64 struct pcibr_slot_disable_resp {
65         int resp_sub_errno;
66         char resp_l1_msg[PCI_L1_QSIZE + 1];
67 };
68
69 enum sn_pci_req_e {
70         PCI_REQ_SLOT_ELIGIBLE,
71         PCI_REQ_SLOT_DISABLE
72 };
73
74 static int enable_slot(struct hotplug_slot *slot);
75 static int disable_slot(struct hotplug_slot *slot);
76 static inline int get_power_status(struct hotplug_slot *slot, u8 *value);
77
78 static struct hotplug_slot_ops sn_hotplug_slot_ops = {
79         .owner                  = THIS_MODULE,
80         .enable_slot            = enable_slot,
81         .disable_slot           = disable_slot,
82         .get_power_status       = get_power_status,
83 };
84
85 static DEFINE_MUTEX(sn_hotplug_mutex);
86
87 static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
88                           char *buf)
89 {
90         int retval = -ENOENT;
91         struct slot *slot = bss_hotplug_slot->private;
92
93         if (!slot)
94                 return retval;
95
96         retval = sprintf (buf, "%s\n", slot->physical_path);
97         return retval;
98 }
99
100 static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
101
102 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
103 {
104         struct pcibus_info *pcibus_info;
105         int bricktype;
106         int bus_num;
107
108         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
109
110         /* Check to see if this is a valid slot on 'pci_bus' */
111         if (!(pcibus_info->pbi_valid_devices & (1 << device)))
112                 return -EPERM;
113
114         bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
115         bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
116
117         /* Do not allow hotplug operations on base I/O cards */
118         if ((bricktype == L1_BRICKTYPE_IX ||  bricktype == L1_BRICKTYPE_IA) &&
119             (bus_num == 1 && device != 1))
120                 return -EPERM;
121
122         return 1;
123 }
124
125 static int sn_pci_bus_valid(struct pci_bus *pci_bus)
126 {
127         struct pcibus_info *pcibus_info;
128         int asic_type;
129         int bricktype;
130
131         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
132
133         /* Don't register slots hanging off the TIOCA bus */
134         asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
135         if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
136                 return -EPERM;
137
138         /* Only register slots in I/O Bricks that support hotplug */
139         bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
140         switch (bricktype) {
141                 case L1_BRICKTYPE_IX:
142                 case L1_BRICKTYPE_PX:
143                 case L1_BRICKTYPE_IA:
144                 case L1_BRICKTYPE_PA:
145                         return 1;
146                         break;
147                 default:
148                         return -EPERM;
149                         break;
150         }
151
152         return -EIO;
153 }
154
155 static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
156                                     struct pci_bus *pci_bus, int device)
157 {
158         struct pcibus_info *pcibus_info;
159         struct slot *slot;
160
161         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
162
163         slot = kzalloc(sizeof(*slot), GFP_KERNEL);
164         if (!slot)
165                 return -ENOMEM;
166         bss_hotplug_slot->private = slot;
167
168         bss_hotplug_slot->name = kmalloc(SN_SLOT_NAME_SIZE, GFP_KERNEL);
169         if (!bss_hotplug_slot->name) {
170                 kfree(bss_hotplug_slot->private);
171                 return -ENOMEM;
172         }
173
174         slot->device_num = device;
175         slot->pci_bus = pci_bus;
176         sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
177                 pci_domain_nr(pci_bus),
178                 ((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
179                 device + 1);
180         sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
181                 '0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
182                 '0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
183                 '0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
184                 MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
185                 MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
186         slot->hotplug_slot = bss_hotplug_slot;
187         list_add(&slot->hp_list, &sn_hp_list);
188
189         return 0;
190 }
191
192 static struct hotplug_slot * sn_hp_destroy(void)
193 {
194         struct slot *slot;
195         struct hotplug_slot *bss_hotplug_slot = NULL;
196
197         list_for_each_entry(slot, &sn_hp_list, hp_list) {
198                 bss_hotplug_slot = slot->hotplug_slot;
199                 list_del(&((struct slot *)bss_hotplug_slot->private)->
200                          hp_list);
201                 sysfs_remove_file(&bss_hotplug_slot->kobj,
202                                   &sn_slot_path_attr.attr);
203                 break;
204         }
205         return bss_hotplug_slot;
206 }
207
208 static void sn_bus_alloc_data(struct pci_dev *dev)
209 {
210         struct pci_bus *subordinate_bus;
211         struct pci_dev *child;
212
213         sn_pci_fixup_slot(dev);
214
215         /* Recursively sets up the sn_irq_info structs */
216         if (dev->subordinate) {
217                 subordinate_bus = dev->subordinate;
218                 list_for_each_entry(child, &subordinate_bus->devices, bus_list)
219                         sn_bus_alloc_data(child);
220         }
221 }
222
223 static void sn_bus_free_data(struct pci_dev *dev)
224 {
225         struct pci_bus *subordinate_bus;
226         struct pci_dev *child;
227
228         /* Recursively clean up sn_irq_info structs */
229         if (dev->subordinate) {
230                 subordinate_bus = dev->subordinate;
231                 list_for_each_entry(child, &subordinate_bus->devices, bus_list)
232                         sn_bus_free_data(child);
233         }
234         /*
235          * Some drivers may use dma accesses during the
236          * driver remove function. We release the sysdata
237          * areas after the driver remove functions have
238          * been called.
239          */
240         sn_bus_store_sysdata(dev);
241         sn_pci_unfixup_slot(dev);
242 }
243
244 static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
245                           int device_num)
246 {
247         struct slot *slot = bss_hotplug_slot->private;
248         struct pcibus_info *pcibus_info;
249         struct pcibr_slot_enable_resp resp;
250         int rc;
251
252         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
253
254         /*
255          * Power-on and initialize the slot in the SN
256          * PCI infrastructure.
257          */
258         rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
259
260         if (rc == PCI_SLOT_ALREADY_UP) {
261                 dev_dbg(slot->pci_bus->self, "is already active\n");
262                 return 1; /* return 1 to user */
263         }
264
265         if (rc == PCI_L1_ERR) {
266                 dev_dbg(slot->pci_bus->self,
267                         "L1 failure %d with message: %s",
268                         resp.resp_sub_errno, resp.resp_l1_msg);
269                 return -EPERM;
270         }
271
272         if (rc) {
273                 dev_dbg(slot->pci_bus->self,
274                         "insert failed with error %d sub-error %d\n",
275                         rc, resp.resp_sub_errno);
276                 return -EIO;
277         }
278
279         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
280         pcibus_info->pbi_enabled_devices |= (1 << device_num);
281
282         return 0;
283 }
284
285 static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
286                            int device_num, int action)
287 {
288         struct slot *slot = bss_hotplug_slot->private;
289         struct pcibus_info *pcibus_info;
290         struct pcibr_slot_disable_resp resp;
291         int rc;
292
293         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
294
295         rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
296
297         if ((action == PCI_REQ_SLOT_ELIGIBLE) &&
298             (rc == PCI_SLOT_ALREADY_DOWN)) {
299                 dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
300                 return 1; /* return 1 to user */
301         }
302
303         if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) {
304                 dev_dbg(slot->pci_bus->self,
305                         "Cannot remove last 33MHz card\n");
306                 return -EPERM;
307         }
308
309         if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) {
310                 dev_dbg(slot->pci_bus->self,
311                         "L1 failure %d with message \n%s\n",
312                         resp.resp_sub_errno, resp.resp_l1_msg);
313                 return -EPERM;
314         }
315
316         if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) {
317                 dev_dbg(slot->pci_bus->self,
318                         "remove failed with error %d sub-error %d\n",
319                         rc, resp.resp_sub_errno);
320                 return -EIO;
321         }
322
323         if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc)
324                 return 0;
325
326         if ((action == PCI_REQ_SLOT_DISABLE) && !rc) {
327                 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
328                 pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
329                 dev_dbg(slot->pci_bus->self, "remove successful\n");
330                 return 0;
331         }
332
333         if ((action == PCI_REQ_SLOT_DISABLE) && rc) {
334                 dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
335         }
336
337         return rc;
338 }
339
340 static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
341 {
342         struct slot *slot = bss_hotplug_slot->private;
343         struct pci_bus *new_bus = NULL;
344         struct pci_dev *dev;
345         int func, num_funcs;
346         int new_ppb = 0;
347         int rc;
348
349         /* Serialize the Linux PCI infrastructure */
350         mutex_lock(&sn_hotplug_mutex);
351
352         /*
353          * Power-on and initialize the slot in the SN
354          * PCI infrastructure.
355          */
356         rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
357         if (rc) {
358                 mutex_unlock(&sn_hotplug_mutex);
359                 return rc;
360         }
361
362         num_funcs = pci_scan_slot(slot->pci_bus,
363                                   PCI_DEVFN(slot->device_num + 1, 0));
364         if (!num_funcs) {
365                 dev_dbg(slot->pci_bus->self, "no device in slot\n");
366                 mutex_unlock(&sn_hotplug_mutex);
367                 return -ENODEV;
368         }
369
370         sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
371                                 slot->pci_bus->number,
372                                 slot->pci_bus);
373         /*
374          * Map SN resources for all functions on the card
375          * to the Linux PCI interface and tell the drivers
376          * about them.
377          */
378         for (func = 0; func < num_funcs;  func++) {
379                 dev = pci_get_slot(slot->pci_bus,
380                                    PCI_DEVFN(slot->device_num + 1,
381                                              PCI_FUNC(func)));
382                 if (dev) {
383                         if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
384                                 unsigned char sec_bus;
385                                 pci_read_config_byte(dev, PCI_SECONDARY_BUS,
386                                                      &sec_bus);
387                                 new_bus = pci_add_new_bus(dev->bus, dev,
388                                                           sec_bus);
389                                 pci_scan_child_bus(new_bus);
390                                 sn_pci_controller_fixup(pci_domain_nr(new_bus),
391                                                         new_bus->number,
392                                                         new_bus);
393                                 new_ppb = 1;
394                         }
395                         sn_bus_alloc_data(dev);
396                         pci_dev_put(dev);
397                 }
398         }
399
400         /* Call the driver for the new device */
401         pci_bus_add_devices(slot->pci_bus);
402         /* Call the drivers for the new devices subordinate to PPB */
403         if (new_ppb)
404                 pci_bus_add_devices(new_bus);
405
406         mutex_unlock(&sn_hotplug_mutex);
407
408         if (rc == 0)
409                 dev_dbg(slot->pci_bus->self,
410                         "insert operation successful\n");
411         else
412                 dev_dbg(slot->pci_bus->self,
413                         "insert operation failed rc = %d\n", rc);
414
415         return rc;
416 }
417
418 static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
419 {
420         struct slot *slot = bss_hotplug_slot->private;
421         struct pci_dev *dev;
422         int func;
423         int rc;
424
425         /* Acquire update access to the bus */
426         mutex_lock(&sn_hotplug_mutex);
427
428         /* is it okay to bring this slot down? */
429         rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
430                              PCI_REQ_SLOT_ELIGIBLE);
431         if (rc)
432                 goto leaving;
433
434         /* Free the SN resources assigned to the Linux device.*/
435         for (func = 0; func < 8;  func++) {
436                 dev = pci_get_slot(slot->pci_bus,
437                                    PCI_DEVFN(slot->device_num + 1,
438                                              PCI_FUNC(func)));
439                 if (dev) {
440                         sn_bus_free_data(dev);
441                         pci_remove_bus_device(dev);
442                         pci_dev_put(dev);
443                 }
444         }
445
446         /* free the collected sysdata pointers */
447         sn_bus_free_sysdata();
448
449         /* Deactivate slot */
450         rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
451                              PCI_REQ_SLOT_DISABLE);
452  leaving:
453         /* Release the bus lock */
454         mutex_unlock(&sn_hotplug_mutex);
455
456         return rc;
457 }
458
459 static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,
460                                    u8 *value)
461 {
462         struct slot *slot = bss_hotplug_slot->private;
463         struct pcibus_info *pcibus_info;
464
465         pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
466         mutex_lock(&sn_hotplug_mutex);
467         *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
468         mutex_unlock(&sn_hotplug_mutex);
469         return 0;
470 }
471
472 static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
473 {
474         kfree(bss_hotplug_slot->info);
475         kfree(bss_hotplug_slot->name);
476         kfree(bss_hotplug_slot->private);
477         kfree(bss_hotplug_slot);
478 }
479
480 static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
481 {
482         int device;
483         struct hotplug_slot *bss_hotplug_slot;
484         int rc = 0;
485
486         /*
487          * Currently only four devices are supported,
488          * in the future there maybe more -- up to 32.
489          */
490
491         for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
492                 if (sn_pci_slot_valid(pci_bus, device) != 1)
493                         continue;
494
495                 bss_hotplug_slot = kzalloc(sizeof(*bss_hotplug_slot),
496                                            GFP_KERNEL);
497                 if (!bss_hotplug_slot) {
498                         rc = -ENOMEM;
499                         goto alloc_err;
500                 }
501
502                 bss_hotplug_slot->info =
503                         kzalloc(sizeof(struct hotplug_slot_info),
504                                 GFP_KERNEL);
505                 if (!bss_hotplug_slot->info) {
506                         rc = -ENOMEM;
507                         goto alloc_err;
508                 }
509
510                 if (sn_hp_slot_private_alloc(bss_hotplug_slot,
511                                              pci_bus, device)) {
512                         rc = -ENOMEM;
513                         goto alloc_err;
514                 }
515
516                 bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
517                 bss_hotplug_slot->release = &sn_release_slot;
518
519                 rc = pci_hp_register(bss_hotplug_slot);
520                 if (rc)
521                         goto register_err;
522
523                 rc = sysfs_create_file(&bss_hotplug_slot->kobj,
524                                        &sn_slot_path_attr.attr);
525                 if (rc)
526                         goto register_err;
527         }
528         dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
529         return rc;
530
531 register_err:
532         dev_dbg(pci_bus->self, "bus failed to register with err = %d\n",
533                 rc);
534
535 alloc_err:
536         if (rc == -ENOMEM)
537                 dev_dbg(pci_bus->self, "Memory allocation error\n");
538
539         /* destroy THIS element */
540         if (bss_hotplug_slot)
541                 sn_release_slot(bss_hotplug_slot);
542
543         /* destroy anything else on the list */
544         while ((bss_hotplug_slot = sn_hp_destroy()))
545                 pci_hp_deregister(bss_hotplug_slot);
546
547         return rc;
548 }
549
550 static int sn_pci_hotplug_init(void)
551 {
552         struct pci_bus *pci_bus = NULL;
553         int rc;
554         int registered = 0;
555
556         if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
557                 printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
558                        __FUNCTION__);
559                 return -EPERM;
560         }
561
562         INIT_LIST_HEAD(&sn_hp_list);
563
564         while ((pci_bus = pci_find_next_bus(pci_bus))) {
565                 if (!pci_bus->sysdata)
566                         continue;
567
568                 rc = sn_pci_bus_valid(pci_bus);
569                 if (rc != 1) {
570                         dev_dbg(pci_bus->self, "not a valid hotplug bus\n");
571                         continue;
572                 }
573                 dev_dbg(pci_bus->self, "valid hotplug bus\n");
574
575                 rc = sn_hotplug_slot_register(pci_bus);
576                 if (!rc) {
577                         registered = 1;
578                 } else {
579                         registered = 0;
580                         break;
581                 }
582         }
583
584         return registered == 1 ? 0 : -ENODEV;
585 }
586
587 static void sn_pci_hotplug_exit(void)
588 {
589         struct hotplug_slot *bss_hotplug_slot;
590
591         while ((bss_hotplug_slot = sn_hp_destroy()))
592                 pci_hp_deregister(bss_hotplug_slot);
593
594         if (!list_empty(&sn_hp_list))
595                 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
596 }
597
598 module_init(sn_pci_hotplug_init);
599 module_exit(sn_pci_hotplug_exit);