linux/drivers/pci/hotplug/rpaphp_slot.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * RPA Virtual I/O device functions
   4 * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
   5 *
   6 * All rights reserved.
   7 *
   8 * Send feedback to <lxie@us.ibm.com>
   9 *
  10 */
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/sysfs.h>
  14#include <linux/pci.h>
  15#include <linux/string.h>
  16#include <linux/slab.h>
  17
  18#include <asm/rtas.h>
  19#include "rpaphp.h"
  20
  21/* free up the memory used by a slot */
  22void dealloc_slot_struct(struct slot *slot)
  23{
  24        kfree(slot->name);
  25        kfree(slot);
  26}
  27
  28struct slot *alloc_slot_struct(struct device_node *dn,
  29                int drc_index, char *drc_name, int power_domain)
  30{
  31        struct slot *slot;
  32
  33        slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
  34        if (!slot)
  35                goto error_nomem;
  36        slot->name = kstrdup(drc_name, GFP_KERNEL);
  37        if (!slot->name)
  38                goto error_slot;
  39        slot->dn = dn;
  40        slot->index = drc_index;
  41        slot->power_domain = power_domain;
  42        slot->hotplug_slot.ops = &rpaphp_hotplug_slot_ops;
  43
  44        return (slot);
  45
  46error_slot:
  47        kfree(slot);
  48error_nomem:
  49        return NULL;
  50}
  51
  52static int is_registered(struct slot *slot)
  53{
  54        struct slot *tmp_slot;
  55
  56        list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
  57                if (!strcmp(tmp_slot->name, slot->name))
  58                        return 1;
  59        }
  60        return 0;
  61}
  62
  63int rpaphp_deregister_slot(struct slot *slot)
  64{
  65        int retval = 0;
  66        struct hotplug_slot *php_slot = &slot->hotplug_slot;
  67
  68         dbg("%s - Entry: deregistering slot=%s\n",
  69                __func__, slot->name);
  70
  71        list_del(&slot->rpaphp_slot_list);
  72        pci_hp_deregister(php_slot);
  73        dealloc_slot_struct(slot);
  74
  75        dbg("%s - Exit: rc[%d]\n", __func__, retval);
  76        return retval;
  77}
  78EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
  79
  80int rpaphp_register_slot(struct slot *slot)
  81{
  82        struct hotplug_slot *php_slot = &slot->hotplug_slot;
  83        struct device_node *child;
  84        u32 my_index;
  85        int retval;
  86        int slotno = -1;
  87
  88        dbg("%s registering slot:path[%pOF] index[%x], name[%s] pdomain[%x] type[%d]\n",
  89                __func__, slot->dn, slot->index, slot->name,
  90                slot->power_domain, slot->type);
  91
  92        /* should not try to register the same slot twice */
  93        if (is_registered(slot)) {
  94                err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
  95                return -EAGAIN;
  96        }
  97
  98        for_each_child_of_node(slot->dn, child) {
  99                retval = of_property_read_u32(child, "ibm,my-drc-index", &my_index);
 100                if (my_index == slot->index) {
 101                        slotno = PCI_SLOT(PCI_DN(child)->devfn);
 102                        of_node_put(child);
 103                        break;
 104                }
 105        }
 106
 107        retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
 108        if (retval) {
 109                err("pci_hp_register failed with error %d\n", retval);
 110                return retval;
 111        }
 112
 113        /* add slot to our internal list */
 114        list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
 115        info("Slot [%s] registered\n", slot->name);
 116        return 0;
 117}
 118