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        of_node_put(slot->dn);
  25        kfree(slot->name);
  26        kfree(slot);
  27}
  28
  29struct slot *alloc_slot_struct(struct device_node *dn,
  30                int drc_index, char *drc_name, int power_domain)
  31{
  32        struct slot *slot;
  33
  34        slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
  35        if (!slot)
  36                goto error_nomem;
  37        slot->name = kstrdup(drc_name, GFP_KERNEL);
  38        if (!slot->name)
  39                goto error_slot;
  40        slot->dn = of_node_get(dn);
  41        slot->index = drc_index;
  42        slot->power_domain = power_domain;
  43        slot->hotplug_slot.ops = &rpaphp_hotplug_slot_ops;
  44
  45        return (slot);
  46
  47error_slot:
  48        kfree(slot);
  49error_nomem:
  50        return NULL;
  51}
  52
  53static int is_registered(struct slot *slot)
  54{
  55        struct slot *tmp_slot;
  56
  57        list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
  58                if (!strcmp(tmp_slot->name, slot->name))
  59                        return 1;
  60        }
  61        return 0;
  62}
  63
  64int rpaphp_deregister_slot(struct slot *slot)
  65{
  66        int retval = 0;
  67        struct hotplug_slot *php_slot = &slot->hotplug_slot;
  68
  69         dbg("%s - Entry: deregistering slot=%s\n",
  70                __func__, slot->name);
  71
  72        list_del(&slot->rpaphp_slot_list);
  73        pci_hp_deregister(php_slot);
  74        dealloc_slot_struct(slot);
  75
  76        dbg("%s - Exit: rc[%d]\n", __func__, retval);
  77        return retval;
  78}
  79EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
  80
  81int rpaphp_register_slot(struct slot *slot)
  82{
  83        struct hotplug_slot *php_slot = &slot->hotplug_slot;
  84        struct device_node *child;
  85        u32 my_index;
  86        int retval;
  87        int slotno = -1;
  88
  89        dbg("%s registering slot:path[%pOF] index[%x], name[%s] pdomain[%x] type[%d]\n",
  90                __func__, slot->dn, slot->index, slot->name,
  91                slot->power_domain, slot->type);
  92
  93        /* should not try to register the same slot twice */
  94        if (is_registered(slot)) {
  95                err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);
  96                return -EAGAIN;
  97        }
  98
  99        for_each_child_of_node(slot->dn, child) {
 100                retval = of_property_read_u32(child, "ibm,my-drc-index", &my_index);
 101                if (my_index == slot->index) {
 102                        slotno = PCI_SLOT(PCI_DN(child)->devfn);
 103                        of_node_put(child);
 104                        break;
 105                }
 106        }
 107
 108        retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
 109        if (retval) {
 110                err("pci_hp_register failed with error %d\n", retval);
 111                return retval;
 112        }
 113
 114        /* add slot to our internal list */
 115        list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
 116        info("Slot [%s] registered\n", slot->name);
 117        return 0;
 118}
 119