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