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
6 * Copyright (C) 2005 Silicon Graphics, Inc. All rights reserved.
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.
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>
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>
29 #include "pci_hotplug.h"
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");
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 */
44 /* internal list head */
45 static struct list_head sn_hp_list;
47 /* hotplug_slot struct's private pointer */
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;
56 struct pcibr_slot_enable_resp {
58 char resp_l1_msg[PCI_L1_QSIZE + 1];
61 struct pcibr_slot_disable_resp {
63 char resp_l1_msg[PCI_L1_QSIZE + 1];
67 PCI_REQ_SLOT_ELIGIBLE,
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);
75 static struct hotplug_slot_ops sn_hotplug_slot_ops = {
77 .enable_slot = enable_slot,
78 .disable_slot = disable_slot,
79 .get_power_status = get_power_status,
82 static DECLARE_MUTEX(sn_hotplug_sem);
84 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
86 struct pcibus_info *pcibus_info;
90 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
92 /* Check to see if this is a valid slot on 'pci_bus' */
93 if (!(pcibus_info->pbi_valid_devices & (1 << device)))
96 bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
97 bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
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))
107 static int sn_pci_bus_valid(struct pci_bus *pci_bus)
109 struct pcibus_info *pcibus_info;
113 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
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)
120 /* Only register slots in I/O Bricks that support hotplug */
121 bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
123 case L1_BRICKTYPE_IX:
124 case L1_BRICKTYPE_PX:
125 case L1_BRICKTYPE_IA:
126 case L1_BRICKTYPE_PA:
137 static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,
138 struct pci_bus *pci_bus, int device)
140 struct pcibus_info *pcibus_info;
143 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
145 bss_hotplug_slot->private = kcalloc(1, sizeof(struct slot),
147 if (!bss_hotplug_slot->private)
149 slot = (struct slot *)bss_hotplug_slot->private;
151 bss_hotplug_slot->name = kmalloc(33, GFP_KERNEL);
152 if (!bss_hotplug_slot->name) {
153 kfree(bss_hotplug_slot->private);
157 slot->device_num = device;
158 slot->pci_bus = pci_bus;
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,
169 slot->hotplug_slot = bss_hotplug_slot;
170 list_add(&slot->hp_list, &sn_hp_list);
175 static struct hotplug_slot * sn_hp_destroy(void)
178 struct list_head *list;
179 struct hotplug_slot *bss_hotplug_slot = NULL;
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)->
188 return bss_hotplug_slot;
191 static void sn_bus_alloc_data(struct pci_dev *dev)
193 struct list_head *node;
194 struct pci_bus *subordinate_bus;
195 struct pci_dev *child;
197 sn_pci_fixup_slot(dev);
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);
209 static void sn_bus_free_data(struct pci_dev *dev)
211 struct list_head *node;
212 struct pci_bus *subordinate_bus;
213 struct pci_dev *child;
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);
223 sn_pci_unfixup_slot(dev);
226 static u8 sn_power_status_get(struct hotplug_slot *bss_hotplug_slot)
228 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
229 struct pcibus_info *pcibus_info;
232 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
233 retval = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
235 return retval ? 1 : 0;
238 static void sn_slot_mark_enable(struct hotplug_slot *bss_hotplug_slot,
241 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
242 struct pcibus_info *pcibus_info;
244 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
245 pcibus_info->pbi_enabled_devices |= (1 << device_num);
248 static void sn_slot_mark_disable(struct hotplug_slot *bss_hotplug_slot,
251 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
252 struct pcibus_info *pcibus_info;
254 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
255 pcibus_info->pbi_enabled_devices &= ~(1 << device_num);
258 static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
261 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
262 struct pcibus_info *pcibus_info;
263 struct pcibr_slot_enable_resp resp;
266 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
269 * Power-on and initialize the slot in the SN
270 * PCI infrastructure.
272 rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
274 if (rc == PCI_SLOT_ALREADY_UP) {
275 dev_dbg(slot->pci_bus->self, "is already active\n");
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);
287 dev_dbg(slot->pci_bus->self,
288 "insert failed with error %d sub-error %d\n",
289 rc, resp.resp_sub_errno);
293 sn_slot_mark_enable(bss_hotplug_slot, device_num);
298 static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,
299 int device_num, int action)
301 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
302 struct pcibus_info *pcibus_info;
303 struct pcibr_slot_disable_resp resp;
306 pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
308 rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp);
310 if (action == PCI_REQ_SLOT_ELIGIBLE && rc == PCI_SLOT_ALREADY_DOWN) {
311 dev_dbg(slot->pci_bus->self, "Slot %s already inactive\n");
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");
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);
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);
335 if (action == PCI_REQ_SLOT_ELIGIBLE && !rc)
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");
344 if (action == PCI_REQ_SLOT_DISABLE && rc) {
345 dev_dbg(slot->pci_bus->self,"remove failed rc = %d\n", rc);
352 static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
354 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
355 struct pci_bus *new_bus = NULL;
361 /* Serialize the Linux PCI infrastructure */
362 down(&sn_hotplug_sem);
365 * Power-on and initialize the slot in the SN
366 * PCI infrastructure.
368 rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
374 num_funcs = pci_scan_slot(slot->pci_bus, PCI_DEVFN(slot->device_num+1,
377 dev_dbg(slot->pci_bus->self, "no device in slot\n");
382 sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
383 slot->pci_bus->number,
386 * Map SN resources for all functions on the card
387 * to the Linux PCI interface and tell the drivers
390 for (func = 0; func < num_funcs; func++) {
391 dev = pci_get_slot(slot->pci_bus,
392 PCI_DEVFN(slot->device_num + 1,
397 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
398 unsigned char sec_bus;
399 pci_read_config_byte(dev, PCI_SECONDARY_BUS,
401 new_bus = pci_add_new_bus(dev->bus, dev,
403 pci_scan_child_bus(new_bus);
404 sn_pci_controller_fixup(pci_domain_nr(new_bus),
409 sn_bus_alloc_data(dev);
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 */
418 pci_bus_add_devices(new_bus);
423 dev_dbg(slot->pci_bus->self,
424 "insert operation successful\n");
426 dev_dbg(slot->pci_bus->self,
427 "insert operation failed rc = %d\n", rc);
432 static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
434 struct slot *slot = (struct slot *)bss_hotplug_slot->private;
439 /* Acquire update access to the bus */
440 down(&sn_hotplug_sem);
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);
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,
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
460 sn_bus_store_sysdata(dev);
461 sn_bus_free_data(dev);
462 pci_remove_bus_device(dev);
467 /* free the collected sysdata pointers */
468 sn_bus_free_sysdata();
470 /* Deactivate slot */
471 rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
472 PCI_REQ_SLOT_DISABLE);
474 /* Release the bus lock */
480 static int get_power_status(struct hotplug_slot *bss_hotplug_slot, u8 *value)
482 down(&sn_hotplug_sem);
483 *value = sn_power_status_get(bss_hotplug_slot);
488 static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot)
490 kfree(bss_hotplug_slot->info);
491 kfree(bss_hotplug_slot->name);
492 kfree(bss_hotplug_slot->private);
493 kfree(bss_hotplug_slot);
496 static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
499 struct hotplug_slot *bss_hotplug_slot;
503 * Currently only four devices are supported,
504 * in the future there maybe more -- up to 32.
507 for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {
508 if (sn_pci_slot_valid(pci_bus, device) != 1)
511 bss_hotplug_slot = kcalloc(1,sizeof(struct hotplug_slot),
513 if (!bss_hotplug_slot) {
518 bss_hotplug_slot->info =
519 kcalloc(1,sizeof(struct hotplug_slot_info),
521 if (!bss_hotplug_slot->info) {
526 if (sn_hp_slot_private_alloc(bss_hotplug_slot,
532 bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
533 bss_hotplug_slot->release = &sn_release_slot;
535 rc = pci_hp_register(bss_hotplug_slot);
539 dev_dbg(pci_bus->self, "Registered bus with hotplug\n");
543 dev_dbg(pci_bus->self, "bus failed to register with err = %d\n",
548 dev_dbg(pci_bus->self, "Memory allocation error\n");
550 /* destroy THIS element */
551 if (bss_hotplug_slot)
552 sn_release_slot(bss_hotplug_slot);
554 /* destroy anything else on the list */
555 while ((bss_hotplug_slot = sn_hp_destroy()))
556 pci_hp_deregister(bss_hotplug_slot);
561 static int sn_pci_hotplug_init(void)
563 struct pci_bus *pci_bus = NULL;
567 INIT_LIST_HEAD(&sn_hp_list);
569 if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
570 printk(KERN_ERR "%s: PROM version must be greater than 4.05\n",
575 while ((pci_bus = pci_find_next_bus(pci_bus))) {
576 if (!pci_bus->sysdata)
579 rc = sn_pci_bus_valid(pci_bus);
581 dev_dbg(pci_bus->self, "not a valid hotplug bus\n");
584 dev_dbg(pci_bus->self, "valid hotplug bus\n");
586 rc = sn_hotplug_slot_register(pci_bus);
595 return registered == 1 ? 0 : -ENODEV;
598 static void sn_pci_hotplug_exit(void)
600 struct hotplug_slot *bss_hotplug_slot;
602 while ((bss_hotplug_slot = sn_hp_destroy())) {
603 pci_hp_deregister(bss_hotplug_slot);
606 if (!list_empty(&sn_hp_list))
607 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
610 module_init(sn_pci_hotplug_init);
611 module_exit(sn_pci_hotplug_exit);