1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * PCI Hot Plug Controller Driver for System z 4 * 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 ": " fmt 13 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 10 22 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 is 83 * currently undergoing a transition and we bail out - just 84 * 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 exits 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