s390_pci_hpc.c 2.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2 3 4 5 6 7 8 9 10
/*
 * PCI Hot Plug Controller Driver for System z
 *
 * Copyright 2012 IBM Corp.
 *
 * Author(s):
 *   Jan Glauber <jang@linux.vnet.ibm.com>
 */

G
Gerald Schaefer 已提交
11 12
#define KMSG_COMPONENT "zpci"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 14 15 16 17

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
S
Sebastian Ott 已提交
18
#include <asm/pci_debug.h>
19 20 21 22 23 24
#include <asm/sclp.h>

#define SLOT_NAME_SIZE	10

static int enable_slot(struct hotplug_slot *hotplug_slot)
{
25 26
	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
					     hotplug_slot);
27

28
	if (zdev->state != ZPCI_FN_STATE_STANDBY)
29 30
		return -EIO;

31
	return zpci_configure_device(zdev, zdev->fh);
32 33 34 35
}

static int disable_slot(struct hotplug_slot *hotplug_slot)
{
36 37
	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
					     hotplug_slot);
38
	struct pci_dev *pdev;
39

40
	if (zdev->state != ZPCI_FN_STATE_CONFIGURED)
41 42
		return -EIO;

43 44
	pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
	if (pdev && pci_num_vf(pdev)) {
45
		pci_dev_put(pdev);
46
		return -EBUSY;
47
	}
48
	pci_dev_put(pdev);
49

50
	return zpci_deconfigure_device(zdev);
51 52 53 54
}

static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
55 56
	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
					     hotplug_slot);
57

58
	switch (zdev->state) {
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
	case ZPCI_FN_STATE_STANDBY:
		*value = 0;
		break;
	default:
		*value = 1;
		break;
	}
	return 0;
}

static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
	/* if the slot exits it always contains a function */
	*value = 1;
	return 0;
}

76
static const struct hotplug_slot_ops s390_hotplug_slot_ops = {
77 78 79 80 81 82
	.enable_slot =		enable_slot,
	.disable_slot =		disable_slot,
	.get_power_status =	get_power_status,
	.get_adapter_status =	get_adapter_status,
};

83
int zpci_init_slot(struct zpci_dev *zdev)
84 85
{
	char name[SLOT_NAME_SIZE];
P
Pierre Morel 已提交
86
	struct zpci_bus *zbus = zdev->zbus;
87

88
	zdev->hotplug_slot.ops = &s390_hotplug_slot_ops;
89 90

	snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);
P
Pierre Morel 已提交
91
	return pci_hp_register(&zdev->hotplug_slot, zbus->bus,
P
Pierre Morel 已提交
92
			       zdev->devfn, name);
93 94
}

95
void zpci_exit_slot(struct zpci_dev *zdev)
96
{
97
	pci_hp_deregister(&zdev->hotplug_slot);
98
}