Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI/hotplug: remove the sgi_hotplug driver

The SGI SN2 support is about to be removed. Remove this driver that
depends on the SN2 support.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lkml.kernel.org/r/20190813072514.23299-6-hch@lst.de
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Christoph Hellwig and committed by
Tony Luck
c7532b60 0b43ba0d

-710
-9
drivers/pci/hotplug/Kconfig
··· 147 147 148 148 When in doubt, say N. 149 149 150 - config HOTPLUG_PCI_SGI 151 - tristate "SGI PCI Hotplug Support" 152 - depends on IA64_SGI_SN2 || IA64_GENERIC 153 - help 154 - Say Y here if you want to use the SGI Altix Hotplug 155 - Driver for PCI devices. 156 - 157 - When in doubt, say N. 158 - 159 150 config HOTPLUG_PCI_S390 160 151 bool "System z PCI Hotplug Support" 161 152 depends on S390 && 64BIT
-1
drivers/pci/hotplug/Makefile
··· 18 18 obj-$(CONFIG_HOTPLUG_PCI_POWERNV) += pnv-php.o 19 19 obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o 20 20 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o 21 - obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o 22 21 obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o 23 22 obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o 24 23
-700
drivers/pci/hotplug/sgi_hotplug.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Copyright (C) 2005-2006 Silicon Graphics, Inc. All rights reserved. 4 - * 5 - * This work was based on the 2.4/2.6 kernel development by Dick Reigner. 6 - * Work to add BIOS PROM support was completed by Mike Habeck. 7 - */ 8 - 9 - #include <linux/acpi.h> 10 - #include <linux/init.h> 11 - #include <linux/kernel.h> 12 - #include <linux/module.h> 13 - #include <linux/pci.h> 14 - #include <linux/pci_hotplug.h> 15 - #include <linux/proc_fs.h> 16 - #include <linux/slab.h> 17 - #include <linux/types.h> 18 - #include <linux/mutex.h> 19 - 20 - #include <asm/sn/addrs.h> 21 - #include <asm/sn/geo.h> 22 - #include <asm/sn/l1.h> 23 - #include <asm/sn/module.h> 24 - #include <asm/sn/pcibr_provider.h> 25 - #include <asm/sn/pcibus_provider_defs.h> 26 - #include <asm/sn/pcidev.h> 27 - #include <asm/sn/sn_feature_sets.h> 28 - #include <asm/sn/sn_sal.h> 29 - #include <asm/sn/types.h> 30 - #include <asm/sn/acpi.h> 31 - 32 - #include "../pci.h" 33 - 34 - MODULE_LICENSE("GPL"); 35 - MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); 36 - MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver"); 37 - 38 - 39 - /* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */ 40 - #define PCI_SLOT_ALREADY_UP 2 /* slot already up */ 41 - #define PCI_SLOT_ALREADY_DOWN 3 /* slot already down */ 42 - #define PCI_L1_ERR 7 /* L1 console command error */ 43 - #define PCI_EMPTY_33MHZ 15 /* empty 33 MHz bus */ 44 - 45 - 46 - #define PCIIO_ASIC_TYPE_TIOCA 4 47 - #define PCI_L1_QSIZE 128 /* our L1 message buffer size */ 48 - #define SN_MAX_HP_SLOTS 32 /* max hotplug slots */ 49 - #define SN_SLOT_NAME_SIZE 33 /* size of name string */ 50 - 51 - /* internal list head */ 52 - static struct list_head sn_hp_list; 53 - 54 - /* hotplug_slot struct's private pointer */ 55 - struct slot { 56 - int device_num; 57 - struct pci_bus *pci_bus; 58 - /* this struct for glue internal only */ 59 - struct hotplug_slot hotplug_slot; 60 - struct list_head hp_list; 61 - char physical_path[SN_SLOT_NAME_SIZE]; 62 - }; 63 - 64 - struct pcibr_slot_enable_resp { 65 - int resp_sub_errno; 66 - char resp_l1_msg[PCI_L1_QSIZE + 1]; 67 - }; 68 - 69 - struct pcibr_slot_disable_resp { 70 - int resp_sub_errno; 71 - char resp_l1_msg[PCI_L1_QSIZE + 1]; 72 - }; 73 - 74 - enum sn_pci_req_e { 75 - PCI_REQ_SLOT_ELIGIBLE, 76 - PCI_REQ_SLOT_DISABLE 77 - }; 78 - 79 - static int enable_slot(struct hotplug_slot *slot); 80 - static int disable_slot(struct hotplug_slot *slot); 81 - static inline int get_power_status(struct hotplug_slot *slot, u8 *value); 82 - 83 - static const struct hotplug_slot_ops sn_hotplug_slot_ops = { 84 - .enable_slot = enable_slot, 85 - .disable_slot = disable_slot, 86 - .get_power_status = get_power_status, 87 - }; 88 - 89 - static DEFINE_MUTEX(sn_hotplug_mutex); 90 - 91 - static struct slot *to_slot(struct hotplug_slot *bss_hotplug_slot) 92 - { 93 - return container_of(bss_hotplug_slot, struct slot, hotplug_slot); 94 - } 95 - 96 - static ssize_t path_show(struct pci_slot *pci_slot, char *buf) 97 - { 98 - int retval = -ENOENT; 99 - struct slot *slot = to_slot(pci_slot->hotplug); 100 - 101 - if (!slot) 102 - return retval; 103 - 104 - retval = sprintf(buf, "%s\n", slot->physical_path); 105 - return retval; 106 - } 107 - 108 - static struct pci_slot_attribute sn_slot_path_attr = __ATTR_RO(path); 109 - 110 - static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device) 111 - { 112 - struct pcibus_info *pcibus_info; 113 - u16 busnum, segment, ioboard_type; 114 - 115 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); 116 - 117 - /* Check to see if this is a valid slot on 'pci_bus' */ 118 - if (!(pcibus_info->pbi_valid_devices & (1 << device))) 119 - return -EPERM; 120 - 121 - ioboard_type = sn_ioboard_to_pci_bus(pci_bus); 122 - busnum = pcibus_info->pbi_buscommon.bs_persist_busnum; 123 - segment = pci_domain_nr(pci_bus) & 0xf; 124 - 125 - /* Do not allow hotplug operations on base I/O cards */ 126 - if ((ioboard_type == L1_BRICKTYPE_IX || 127 - ioboard_type == L1_BRICKTYPE_IA) && 128 - (segment == 1 && busnum == 0 && device != 1)) 129 - return -EPERM; 130 - 131 - return 1; 132 - } 133 - 134 - static int sn_pci_bus_valid(struct pci_bus *pci_bus) 135 - { 136 - struct pcibus_info *pcibus_info; 137 - u32 asic_type; 138 - u16 ioboard_type; 139 - 140 - /* Don't register slots hanging off the TIOCA bus */ 141 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); 142 - asic_type = pcibus_info->pbi_buscommon.bs_asic_type; 143 - if (asic_type == PCIIO_ASIC_TYPE_TIOCA) 144 - return -EPERM; 145 - 146 - /* Only register slots in I/O Bricks that support hotplug */ 147 - ioboard_type = sn_ioboard_to_pci_bus(pci_bus); 148 - switch (ioboard_type) { 149 - case L1_BRICKTYPE_IX: 150 - case L1_BRICKTYPE_PX: 151 - case L1_BRICKTYPE_IA: 152 - case L1_BRICKTYPE_PA: 153 - case L1_BOARDTYPE_PCIX3SLOT: 154 - return 1; 155 - break; 156 - default: 157 - return -EPERM; 158 - break; 159 - } 160 - 161 - return -EIO; 162 - } 163 - 164 - static int sn_hp_slot_private_alloc(struct hotplug_slot **bss_hotplug_slot, 165 - struct pci_bus *pci_bus, int device, 166 - char *name) 167 - { 168 - struct pcibus_info *pcibus_info; 169 - struct slot *slot; 170 - 171 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus); 172 - 173 - slot = kzalloc(sizeof(*slot), GFP_KERNEL); 174 - if (!slot) 175 - return -ENOMEM; 176 - 177 - slot->device_num = device; 178 - slot->pci_bus = pci_bus; 179 - sprintf(name, "%04x:%02x:%02x", 180 - pci_domain_nr(pci_bus), 181 - ((u16)pcibus_info->pbi_buscommon.bs_persist_busnum), 182 - device + 1); 183 - 184 - sn_generate_path(pci_bus, slot->physical_path); 185 - 186 - list_add(&slot->hp_list, &sn_hp_list); 187 - *bss_hotplug_slot = &slot->hotplug_slot; 188 - 189 - return 0; 190 - } 191 - 192 - static struct hotplug_slot *sn_hp_destroy(void) 193 - { 194 - struct slot *slot; 195 - struct pci_slot *pci_slot; 196 - struct hotplug_slot *bss_hotplug_slot = NULL; 197 - 198 - list_for_each_entry(slot, &sn_hp_list, hp_list) { 199 - bss_hotplug_slot = &slot->hotplug_slot; 200 - pci_slot = bss_hotplug_slot->pci_slot; 201 - list_del(&slot->hp_list); 202 - sysfs_remove_file(&pci_slot->kobj, 203 - &sn_slot_path_attr.attr); 204 - break; 205 - } 206 - return bss_hotplug_slot; 207 - } 208 - 209 - static void sn_bus_free_data(struct pci_dev *dev) 210 - { 211 - struct pci_bus *subordinate_bus; 212 - struct pci_dev *child; 213 - 214 - /* Recursively clean up sn_irq_info structs */ 215 - if (dev->subordinate) { 216 - subordinate_bus = dev->subordinate; 217 - list_for_each_entry(child, &subordinate_bus->devices, bus_list) 218 - sn_bus_free_data(child); 219 - } 220 - /* 221 - * Some drivers may use dma accesses during the 222 - * driver remove function. We release the sysdata 223 - * areas after the driver remove functions have 224 - * been called. 225 - */ 226 - sn_bus_store_sysdata(dev); 227 - sn_pci_unfixup_slot(dev); 228 - } 229 - 230 - static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot, 231 - int device_num, char **ssdt) 232 - { 233 - struct slot *slot = to_slot(bss_hotplug_slot); 234 - struct pcibus_info *pcibus_info; 235 - struct pcibr_slot_enable_resp resp; 236 - int rc; 237 - 238 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); 239 - 240 - /* 241 - * Power-on and initialize the slot in the SN 242 - * PCI infrastructure. 243 - */ 244 - rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp, ssdt); 245 - 246 - 247 - if (rc == PCI_SLOT_ALREADY_UP) { 248 - pci_dbg(slot->pci_bus->self, "is already active\n"); 249 - return 1; /* return 1 to user */ 250 - } 251 - 252 - if (rc == PCI_L1_ERR) { 253 - pci_dbg(slot->pci_bus->self, "L1 failure %d with message: %s", 254 - resp.resp_sub_errno, resp.resp_l1_msg); 255 - return -EPERM; 256 - } 257 - 258 - if (rc) { 259 - pci_dbg(slot->pci_bus->self, "insert failed with error %d sub-error %d\n", 260 - rc, resp.resp_sub_errno); 261 - return -EIO; 262 - } 263 - 264 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); 265 - pcibus_info->pbi_enabled_devices |= (1 << device_num); 266 - 267 - return 0; 268 - } 269 - 270 - static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, 271 - int device_num, int action) 272 - { 273 - struct slot *slot = to_slot(bss_hotplug_slot); 274 - struct pcibus_info *pcibus_info; 275 - struct pcibr_slot_disable_resp resp; 276 - int rc; 277 - 278 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); 279 - 280 - rc = sal_pcibr_slot_disable(pcibus_info, device_num, action, &resp); 281 - 282 - if ((action == PCI_REQ_SLOT_ELIGIBLE) && 283 - (rc == PCI_SLOT_ALREADY_DOWN)) { 284 - pci_dbg(slot->pci_bus->self, "Slot %s already inactive\n", slot->physical_path); 285 - return 1; /* return 1 to user */ 286 - } 287 - 288 - if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) { 289 - pci_dbg(slot->pci_bus->self, "Cannot remove last 33MHz card\n"); 290 - return -EPERM; 291 - } 292 - 293 - if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) { 294 - pci_dbg(slot->pci_bus->self, "L1 failure %d with message \n%s\n", 295 - resp.resp_sub_errno, resp.resp_l1_msg); 296 - return -EPERM; 297 - } 298 - 299 - if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) { 300 - pci_dbg(slot->pci_bus->self, "remove failed with error %d sub-error %d\n", 301 - rc, resp.resp_sub_errno); 302 - return -EIO; 303 - } 304 - 305 - if ((action == PCI_REQ_SLOT_ELIGIBLE) && !rc) 306 - return 0; 307 - 308 - if ((action == PCI_REQ_SLOT_DISABLE) && !rc) { 309 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); 310 - pcibus_info->pbi_enabled_devices &= ~(1 << device_num); 311 - pci_dbg(slot->pci_bus->self, "remove successful\n"); 312 - return 0; 313 - } 314 - 315 - if ((action == PCI_REQ_SLOT_DISABLE) && rc) { 316 - pci_dbg(slot->pci_bus->self, "remove failed rc = %d\n", rc); 317 - } 318 - 319 - return rc; 320 - } 321 - 322 - /* 323 - * Power up and configure the slot via a SAL call to PROM. 324 - * Scan slot (and any children), do any platform specific fixup, 325 - * and find device driver. 326 - */ 327 - static int enable_slot(struct hotplug_slot *bss_hotplug_slot) 328 - { 329 - struct slot *slot = to_slot(bss_hotplug_slot); 330 - struct pci_bus *new_bus = NULL; 331 - struct pci_dev *dev; 332 - int num_funcs; 333 - int new_ppb = 0; 334 - int rc; 335 - char *ssdt = NULL; 336 - void pcibios_fixup_device_resources(struct pci_dev *); 337 - 338 - /* Serialize the Linux PCI infrastructure */ 339 - mutex_lock(&sn_hotplug_mutex); 340 - 341 - /* 342 - * Power-on and initialize the slot in the SN 343 - * PCI infrastructure. Also, retrieve the ACPI SSDT 344 - * table for the slot (if ACPI capable PROM). 345 - */ 346 - rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt); 347 - if (rc) { 348 - mutex_unlock(&sn_hotplug_mutex); 349 - return rc; 350 - } 351 - 352 - if (ssdt) 353 - ssdt = __va(ssdt); 354 - /* Add the new SSDT for the slot to the ACPI namespace */ 355 - if (SN_ACPI_BASE_SUPPORT() && ssdt) { 356 - acpi_status ret; 357 - 358 - ret = acpi_load_table((struct acpi_table_header *)ssdt); 359 - if (ACPI_FAILURE(ret)) { 360 - printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n", 361 - __func__, ret); 362 - /* try to continue on */ 363 - } 364 - } 365 - 366 - num_funcs = pci_scan_slot(slot->pci_bus, 367 - PCI_DEVFN(slot->device_num + 1, 0)); 368 - if (!num_funcs) { 369 - pci_dbg(slot->pci_bus->self, "no device in slot\n"); 370 - mutex_unlock(&sn_hotplug_mutex); 371 - return -ENODEV; 372 - } 373 - 374 - /* 375 - * Map SN resources for all functions on the card 376 - * to the Linux PCI interface and tell the drivers 377 - * about them. 378 - */ 379 - list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) { 380 - if (PCI_SLOT(dev->devfn) != slot->device_num + 1) 381 - continue; 382 - 383 - /* Need to do slot fixup on PPB before fixup of children 384 - * (PPB's pcidev_info needs to be in pcidev_info list 385 - * before child's SN_PCIDEV_INFO() call to setup 386 - * pdi_host_pcidev_info). 387 - */ 388 - pcibios_fixup_device_resources(dev); 389 - if (SN_ACPI_BASE_SUPPORT()) 390 - sn_acpi_slot_fixup(dev); 391 - else 392 - sn_io_slot_fixup(dev); 393 - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { 394 - pci_hp_add_bridge(dev); 395 - if (dev->subordinate) { 396 - new_bus = dev->subordinate; 397 - new_ppb = 1; 398 - } 399 - } 400 - } 401 - 402 - /* 403 - * Add the slot's devices to the ACPI infrastructure */ 404 - if (SN_ACPI_BASE_SUPPORT() && ssdt) { 405 - unsigned long long adr; 406 - struct acpi_device *pdevice; 407 - acpi_handle phandle; 408 - acpi_handle chandle = NULL; 409 - acpi_handle rethandle; 410 - acpi_status ret; 411 - 412 - phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion); 413 - 414 - if (acpi_bus_get_device(phandle, &pdevice)) { 415 - pci_dbg(slot->pci_bus->self, "no parent device, assuming NULL\n"); 416 - pdevice = NULL; 417 - } 418 - 419 - acpi_scan_lock_acquire(); 420 - /* 421 - * Walk the rootbus node's immediate children looking for 422 - * the slot's device node(s). There can be more than 423 - * one for multifunction devices. 424 - */ 425 - for (;;) { 426 - rethandle = NULL; 427 - ret = acpi_get_next_object(ACPI_TYPE_DEVICE, 428 - phandle, chandle, 429 - &rethandle); 430 - 431 - if (ret == AE_NOT_FOUND || rethandle == NULL) 432 - break; 433 - 434 - chandle = rethandle; 435 - 436 - ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR, 437 - NULL, &adr); 438 - 439 - if (ACPI_SUCCESS(ret) && 440 - (adr>>16) == (slot->device_num + 1)) { 441 - 442 - ret = acpi_bus_scan(chandle); 443 - if (ACPI_FAILURE(ret)) { 444 - printk(KERN_ERR "%s: acpi_bus_scan failed (0x%x) for slot %d func %d\n", 445 - __func__, ret, (int)(adr>>16), 446 - (int)(adr&0xffff)); 447 - /* try to continue on */ 448 - } 449 - } 450 - } 451 - acpi_scan_lock_release(); 452 - } 453 - 454 - pci_lock_rescan_remove(); 455 - 456 - /* Call the driver for the new device */ 457 - pci_bus_add_devices(slot->pci_bus); 458 - /* Call the drivers for the new devices subordinate to PPB */ 459 - if (new_ppb) 460 - pci_bus_add_devices(new_bus); 461 - 462 - pci_unlock_rescan_remove(); 463 - mutex_unlock(&sn_hotplug_mutex); 464 - 465 - if (rc == 0) 466 - pci_dbg(slot->pci_bus->self, "insert operation successful\n"); 467 - else 468 - pci_dbg(slot->pci_bus->self, "insert operation failed rc = %d\n", rc); 469 - 470 - return rc; 471 - } 472 - 473 - static int disable_slot(struct hotplug_slot *bss_hotplug_slot) 474 - { 475 - struct slot *slot = to_slot(bss_hotplug_slot); 476 - struct pci_dev *dev, *temp; 477 - int rc; 478 - acpi_handle ssdt_hdl = NULL; 479 - 480 - /* Acquire update access to the bus */ 481 - mutex_lock(&sn_hotplug_mutex); 482 - 483 - /* is it okay to bring this slot down? */ 484 - rc = sn_slot_disable(bss_hotplug_slot, slot->device_num, 485 - PCI_REQ_SLOT_ELIGIBLE); 486 - if (rc) 487 - goto leaving; 488 - 489 - /* free the ACPI resources for the slot */ 490 - if (SN_ACPI_BASE_SUPPORT() && 491 - PCI_CONTROLLER(slot->pci_bus)->companion) { 492 - unsigned long long adr; 493 - struct acpi_device *device; 494 - acpi_handle phandle; 495 - acpi_handle chandle = NULL; 496 - acpi_handle rethandle; 497 - acpi_status ret; 498 - 499 - /* Get the rootbus node pointer */ 500 - phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion); 501 - 502 - acpi_scan_lock_acquire(); 503 - /* 504 - * Walk the rootbus node's immediate children looking for 505 - * the slot's device node(s). There can be more than 506 - * one for multifunction devices. 507 - */ 508 - for (;;) { 509 - rethandle = NULL; 510 - ret = acpi_get_next_object(ACPI_TYPE_DEVICE, 511 - phandle, chandle, 512 - &rethandle); 513 - 514 - if (ret == AE_NOT_FOUND || rethandle == NULL) 515 - break; 516 - 517 - chandle = rethandle; 518 - 519 - ret = acpi_evaluate_integer(chandle, 520 - METHOD_NAME__ADR, 521 - NULL, &adr); 522 - if (ACPI_SUCCESS(ret) && 523 - (adr>>16) == (slot->device_num + 1)) { 524 - /* retain the owner id */ 525 - ssdt_hdl = chandle; 526 - 527 - ret = acpi_bus_get_device(chandle, 528 - &device); 529 - if (ACPI_SUCCESS(ret)) 530 - acpi_bus_trim(device); 531 - } 532 - } 533 - acpi_scan_lock_release(); 534 - } 535 - 536 - pci_lock_rescan_remove(); 537 - /* Free the SN resources assigned to the Linux device.*/ 538 - list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { 539 - if (PCI_SLOT(dev->devfn) != slot->device_num + 1) 540 - continue; 541 - 542 - pci_dev_get(dev); 543 - sn_bus_free_data(dev); 544 - pci_stop_and_remove_bus_device(dev); 545 - pci_dev_put(dev); 546 - } 547 - pci_unlock_rescan_remove(); 548 - 549 - /* Remove the SSDT for the slot from the ACPI namespace */ 550 - if (SN_ACPI_BASE_SUPPORT() && ssdt_hdl) { 551 - acpi_status ret; 552 - ret = acpi_unload_parent_table(ssdt_hdl); 553 - if (ACPI_FAILURE(ret)) { 554 - acpi_handle_err(ssdt_hdl, 555 - "%s: acpi_unload_parent_table failed (0x%x)\n", 556 - __func__, ret); 557 - /* try to continue on */ 558 - } 559 - } 560 - 561 - /* free the collected sysdata pointers */ 562 - sn_bus_free_sysdata(); 563 - 564 - /* Deactivate slot */ 565 - rc = sn_slot_disable(bss_hotplug_slot, slot->device_num, 566 - PCI_REQ_SLOT_DISABLE); 567 - leaving: 568 - /* Release the bus lock */ 569 - mutex_unlock(&sn_hotplug_mutex); 570 - 571 - return rc; 572 - } 573 - 574 - static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot, 575 - u8 *value) 576 - { 577 - struct slot *slot = to_slot(bss_hotplug_slot); 578 - struct pcibus_info *pcibus_info; 579 - u32 power; 580 - 581 - pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus); 582 - mutex_lock(&sn_hotplug_mutex); 583 - power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); 584 - *value = power ? 1 : 0; 585 - mutex_unlock(&sn_hotplug_mutex); 586 - return 0; 587 - } 588 - 589 - static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot) 590 - { 591 - kfree(to_slot(bss_hotplug_slot)); 592 - } 593 - 594 - static int sn_hotplug_slot_register(struct pci_bus *pci_bus) 595 - { 596 - int device; 597 - struct pci_slot *pci_slot; 598 - struct hotplug_slot *bss_hotplug_slot; 599 - char name[SN_SLOT_NAME_SIZE]; 600 - int rc = 0; 601 - 602 - /* 603 - * Currently only four devices are supported, 604 - * in the future there maybe more -- up to 32. 605 - */ 606 - 607 - for (device = 0; device < SN_MAX_HP_SLOTS ; device++) { 608 - if (sn_pci_slot_valid(pci_bus, device) != 1) 609 - continue; 610 - 611 - if (sn_hp_slot_private_alloc(&bss_hotplug_slot, 612 - pci_bus, device, name)) { 613 - rc = -ENOMEM; 614 - goto alloc_err; 615 - } 616 - bss_hotplug_slot->ops = &sn_hotplug_slot_ops; 617 - 618 - rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name); 619 - if (rc) 620 - goto register_err; 621 - 622 - pci_slot = bss_hotplug_slot->pci_slot; 623 - rc = sysfs_create_file(&pci_slot->kobj, 624 - &sn_slot_path_attr.attr); 625 - if (rc) 626 - goto alloc_err; 627 - } 628 - pci_dbg(pci_bus->self, "Registered bus with hotplug\n"); 629 - return rc; 630 - 631 - register_err: 632 - pci_dbg(pci_bus->self, "bus failed to register with err = %d\n", 633 - rc); 634 - 635 - /* destroy THIS element */ 636 - sn_hp_destroy(); 637 - sn_release_slot(bss_hotplug_slot); 638 - 639 - alloc_err: 640 - /* destroy anything else on the list */ 641 - while ((bss_hotplug_slot = sn_hp_destroy())) { 642 - pci_hp_deregister(bss_hotplug_slot); 643 - sn_release_slot(bss_hotplug_slot); 644 - } 645 - 646 - return rc; 647 - } 648 - 649 - static int __init sn_pci_hotplug_init(void) 650 - { 651 - struct pci_bus *pci_bus = NULL; 652 - int rc; 653 - int registered = 0; 654 - 655 - if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) { 656 - printk(KERN_ERR "%s: PROM version does not support hotplug.\n", 657 - __func__); 658 - return -EPERM; 659 - } 660 - 661 - INIT_LIST_HEAD(&sn_hp_list); 662 - 663 - while ((pci_bus = pci_find_next_bus(pci_bus))) { 664 - if (!pci_bus->sysdata) 665 - continue; 666 - 667 - rc = sn_pci_bus_valid(pci_bus); 668 - if (rc != 1) { 669 - pci_dbg(pci_bus->self, "not a valid hotplug bus\n"); 670 - continue; 671 - } 672 - pci_dbg(pci_bus->self, "valid hotplug bus\n"); 673 - 674 - rc = sn_hotplug_slot_register(pci_bus); 675 - if (!rc) { 676 - registered = 1; 677 - } else { 678 - registered = 0; 679 - break; 680 - } 681 - } 682 - 683 - return registered == 1 ? 0 : -ENODEV; 684 - } 685 - 686 - static void __exit sn_pci_hotplug_exit(void) 687 - { 688 - struct hotplug_slot *bss_hotplug_slot; 689 - 690 - while ((bss_hotplug_slot = sn_hp_destroy())) { 691 - pci_hp_deregister(bss_hotplug_slot); 692 - sn_release_slot(bss_hotplug_slot); 693 - } 694 - 695 - if (!list_empty(&sn_hp_list)) 696 - printk(KERN_ERR "%s: internal list is not empty\n", __FILE__); 697 - } 698 - 699 - module_init(sn_pci_hotplug_init); 700 - module_exit(sn_pci_hotplug_exit);