brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · 055518e Raw
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