1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2012
6 * Jan Glauber <jang@linux.vnet.ibm.com>
9 #define KMSG_COMPONENT "zpci"
10 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12 #include <linux/kernel.h>
13 #include <linux/stat.h>
14 #include <linux/pci.h>
16 #include "../../../drivers/pci/pci.h"
20 #define zpci_attr(name, fmt, member) \
21 static ssize_t name##_show(struct device *dev, \
22 struct device_attribute *attr, char *buf) \
24 struct zpci_dev *zdev = to_zpci(to_pci_dev(dev)); \
26 return sprintf(buf, fmt, zdev->member); \
28 static DEVICE_ATTR_RO(name)
30 zpci_attr(function_id
, "0x%08x\n", fid
);
31 zpci_attr(function_handle
, "0x%08x\n", fh
);
32 zpci_attr(pchid
, "0x%04x\n", pchid
);
33 zpci_attr(pfgid
, "0x%02x\n", pfgid
);
34 zpci_attr(vfn
, "0x%04x\n", vfn
);
35 zpci_attr(pft
, "0x%02x\n", pft
);
36 zpci_attr(port
, "%d\n", port
);
37 zpci_attr(uid
, "0x%x\n", uid
);
38 zpci_attr(segment0
, "0x%02x\n", pfip
[0]);
39 zpci_attr(segment1
, "0x%02x\n", pfip
[1]);
40 zpci_attr(segment2
, "0x%02x\n", pfip
[2]);
41 zpci_attr(segment3
, "0x%02x\n", pfip
[3]);
43 static ssize_t
mio_enabled_show(struct device
*dev
,
44 struct device_attribute
*attr
, char *buf
)
46 struct zpci_dev
*zdev
= to_zpci(to_pci_dev(dev
));
48 return sprintf(buf
, zpci_use_mio(zdev
) ? "1\n" : "0\n");
50 static DEVICE_ATTR_RO(mio_enabled
);
52 static ssize_t
recover_store(struct device
*dev
, struct device_attribute
*attr
,
53 const char *buf
, size_t count
)
55 struct kernfs_node
*kn
;
56 struct pci_dev
*pdev
= to_pci_dev(dev
);
57 struct zpci_dev
*zdev
= to_zpci(pdev
);
60 /* Can't use device_remove_self() here as that would lead us to lock
61 * the pci_rescan_remove_lock while holding the device' kernfs lock.
62 * This would create a possible deadlock with disable_slot() which is
63 * not directly protected by the device' kernfs lock but takes it
64 * during the device removal which happens under
65 * pci_rescan_remove_lock.
67 * This is analogous to sdev_store_delete() in
68 * drivers/scsi/scsi_sysfs.c
70 kn
= sysfs_break_active_protection(&dev
->kobj
, &attr
->attr
);
72 /* device_remove_file() serializes concurrent calls ignoring all but
75 device_remove_file(dev
, attr
);
77 /* A concurrent call to recover_store() may slip between
78 * sysfs_break_active_protection() and the sysfs file removal.
79 * Once it unblocks from pci_lock_rescan_remove() the original pdev
80 * will already be removed.
82 pci_lock_rescan_remove();
83 if (pci_dev_is_added(pdev
)) {
84 pci_stop_and_remove_bus_device(pdev
);
85 ret
= zpci_disable_device(zdev
);
89 ret
= zpci_enable_device(zdev
);
92 pci_rescan_bus(zdev
->zbus
->bus
);
95 pci_unlock_rescan_remove();
97 sysfs_unbreak_active_protection(kn
);
98 return ret
? ret
: count
;
100 static DEVICE_ATTR_WO(recover
);
102 static ssize_t
util_string_read(struct file
*filp
, struct kobject
*kobj
,
103 struct bin_attribute
*attr
, char *buf
,
104 loff_t off
, size_t count
)
106 struct device
*dev
= kobj_to_dev(kobj
);
107 struct pci_dev
*pdev
= to_pci_dev(dev
);
108 struct zpci_dev
*zdev
= to_zpci(pdev
);
110 return memory_read_from_buffer(buf
, count
, &off
, zdev
->util_str
,
111 sizeof(zdev
->util_str
));
113 static BIN_ATTR_RO(util_string
, CLP_UTIL_STR_LEN
);
115 static ssize_t
report_error_write(struct file
*filp
, struct kobject
*kobj
,
116 struct bin_attribute
*attr
, char *buf
,
117 loff_t off
, size_t count
)
119 struct zpci_report_error_header
*report
= (void *) buf
;
120 struct device
*dev
= kobj_to_dev(kobj
);
121 struct pci_dev
*pdev
= to_pci_dev(dev
);
122 struct zpci_dev
*zdev
= to_zpci(pdev
);
125 if (off
|| (count
< sizeof(*report
)))
128 ret
= sclp_pci_report(report
, zdev
->fh
, zdev
->fid
);
130 return ret
? ret
: count
;
132 static BIN_ATTR(report_error
, S_IWUSR
, NULL
, report_error_write
, PAGE_SIZE
);
134 static struct bin_attribute
*zpci_bin_attrs
[] = {
135 &bin_attr_util_string
,
136 &bin_attr_report_error
,
140 static struct attribute
*zpci_dev_attrs
[] = {
141 &dev_attr_function_id
.attr
,
142 &dev_attr_function_handle
.attr
,
143 &dev_attr_pchid
.attr
,
144 &dev_attr_pfgid
.attr
,
149 &dev_attr_recover
.attr
,
150 &dev_attr_mio_enabled
.attr
,
153 static struct attribute_group zpci_attr_group
= {
154 .attrs
= zpci_dev_attrs
,
155 .bin_attrs
= zpci_bin_attrs
,
158 static struct attribute
*pfip_attrs
[] = {
159 &dev_attr_segment0
.attr
,
160 &dev_attr_segment1
.attr
,
161 &dev_attr_segment2
.attr
,
162 &dev_attr_segment3
.attr
,
165 static struct attribute_group pfip_attr_group
= {
170 const struct attribute_group
*zpci_attr_groups
[] = {