144 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * PCI Hot Plug Controller Driver for System z4 *5 * Copyright 2012 IBM Corp.6 *7 * Author(s):8 * Jan Glauber <jang@linux.vnet.ibm.com>9 */10 11#define KMSG_COMPONENT "zpci"12#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt13 14#include <linux/kernel.h>15#include <linux/slab.h>16#include <linux/pci.h>17#include <linux/pci_hotplug.h>18#include <asm/pci_debug.h>19#include <asm/sclp.h>20 21#define SLOT_NAME_SIZE 1022 23static int enable_slot(struct hotplug_slot *hotplug_slot)24{25 struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,26 hotplug_slot);27 int rc;28 29 mutex_lock(&zdev->state_lock);30 if (zdev->state != ZPCI_FN_STATE_STANDBY) {31 rc = -EIO;32 goto out;33 }34 35 rc = sclp_pci_configure(zdev->fid);36 zpci_dbg(3, "conf fid:%x, rc:%d\n", zdev->fid, rc);37 if (rc)38 goto out;39 zdev->state = ZPCI_FN_STATE_CONFIGURED;40 41 rc = zpci_scan_configured_device(zdev, zdev->fh);42out:43 mutex_unlock(&zdev->state_lock);44 return rc;45}46 47static int disable_slot(struct hotplug_slot *hotplug_slot)48{49 struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,50 hotplug_slot);51 struct pci_dev *pdev = NULL;52 int rc;53 54 mutex_lock(&zdev->state_lock);55 if (zdev->state != ZPCI_FN_STATE_CONFIGURED) {56 rc = -EIO;57 goto out;58 }59 60 pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);61 if (pdev && pci_num_vf(pdev)) {62 pci_dev_put(pdev);63 rc = -EBUSY;64 goto out;65 }66 67 rc = zpci_deconfigure_device(zdev);68out:69 mutex_unlock(&zdev->state_lock);70 if (pdev)71 pci_dev_put(pdev);72 return rc;73}74 75static int reset_slot(struct hotplug_slot *hotplug_slot, bool probe)76{77 struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,78 hotplug_slot);79 int rc = -EIO;80 81 /*82 * If we can't get the zdev->state_lock the device state is83 * currently undergoing a transition and we bail out - just84 * the same as if the device's state is not configured at all.85 */86 if (!mutex_trylock(&zdev->state_lock))87 return rc;88 89 /* We can reset only if the function is configured */90 if (zdev->state != ZPCI_FN_STATE_CONFIGURED)91 goto out;92 93 if (probe) {94 rc = 0;95 goto out;96 }97 98 rc = zpci_hot_reset_device(zdev);99out:100 mutex_unlock(&zdev->state_lock);101 return rc;102}103 104static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)105{106 struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,107 hotplug_slot);108 109 *value = zpci_is_device_configured(zdev) ? 1 : 0;110 return 0;111}112 113static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)114{115 /* if the slot exists it always contains a function */116 *value = 1;117 return 0;118}119 120static const struct hotplug_slot_ops s390_hotplug_slot_ops = {121 .enable_slot = enable_slot,122 .disable_slot = disable_slot,123 .reset_slot = reset_slot,124 .get_power_status = get_power_status,125 .get_adapter_status = get_adapter_status,126};127 128int zpci_init_slot(struct zpci_dev *zdev)129{130 char name[SLOT_NAME_SIZE];131 struct zpci_bus *zbus = zdev->zbus;132 133 zdev->hotplug_slot.ops = &s390_hotplug_slot_ops;134 135 snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);136 return pci_hp_register(&zdev->hotplug_slot, zbus->bus,137 zdev->devfn, name);138}139 140void zpci_exit_slot(struct zpci_dev *zdev)141{142 pci_hp_deregister(&zdev->hotplug_slot);143}144