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