xref: /linux/arch/s390/pci/pci_sysfs.c (revision b346953ddac0d57d4852ddc2b5cd9e16c84ddd59)
11e8da956SJan Glauber /*
21e8da956SJan Glauber  * Copyright IBM Corp. 2012
31e8da956SJan Glauber  *
41e8da956SJan Glauber  * Author(s):
51e8da956SJan Glauber  *   Jan Glauber <jang@linux.vnet.ibm.com>
61e8da956SJan Glauber  */
71e8da956SJan Glauber 
81e8da956SJan Glauber #define COMPONENT "zPCI"
91e8da956SJan Glauber #define pr_fmt(fmt) COMPONENT ": " fmt
101e8da956SJan Glauber 
111e8da956SJan Glauber #include <linux/kernel.h>
121e8da956SJan Glauber #include <linux/stat.h>
131e8da956SJan Glauber #include <linux/pci.h>
141e8da956SJan Glauber 
15*b346953dSSebastian Ott #define zpci_attr(name, fmt, member)					\
16*b346953dSSebastian Ott static ssize_t name##_show(struct device *dev,				\
17*b346953dSSebastian Ott 			   struct device_attribute *attr, char *buf)	\
18*b346953dSSebastian Ott {									\
19*b346953dSSebastian Ott 	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));		\
20*b346953dSSebastian Ott 									\
21*b346953dSSebastian Ott 	return sprintf(buf, fmt, zdev->member);				\
22*b346953dSSebastian Ott }									\
23*b346953dSSebastian Ott static DEVICE_ATTR_RO(name)
241e8da956SJan Glauber 
25*b346953dSSebastian Ott zpci_attr(function_id, "0x%08x\n", fid);
26*b346953dSSebastian Ott zpci_attr(function_handle, "0x%08x\n", fh);
27*b346953dSSebastian Ott zpci_attr(pchid, "0x%04x\n", pchid);
28*b346953dSSebastian Ott zpci_attr(pfgid, "0x%02x\n", pfgid);
291e8da956SJan Glauber 
30*b346953dSSebastian Ott static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
310b60f9eaSTejun Heo 			     const char *buf, size_t count)
320ff70ec8SSebastian Ott {
330ff70ec8SSebastian Ott 	struct pci_dev *pdev = to_pci_dev(dev);
340ff70ec8SSebastian Ott 	struct zpci_dev *zdev = get_zdev(pdev);
350ff70ec8SSebastian Ott 	int ret;
360ff70ec8SSebastian Ott 
370b60f9eaSTejun Heo 	if (!device_remove_file_self(dev, attr))
380b60f9eaSTejun Heo 		return count;
390b60f9eaSTejun Heo 
400ff70ec8SSebastian Ott 	pci_stop_and_remove_bus_device(pdev);
410ff70ec8SSebastian Ott 	ret = zpci_disable_device(zdev);
420ff70ec8SSebastian Ott 	if (ret)
430b60f9eaSTejun Heo 		return ret;
440ff70ec8SSebastian Ott 
450ff70ec8SSebastian Ott 	ret = zpci_enable_device(zdev);
460ff70ec8SSebastian Ott 	if (ret)
470b60f9eaSTejun Heo 		return ret;
480ff70ec8SSebastian Ott 
490ff70ec8SSebastian Ott 	pci_rescan_bus(zdev->bus);
500b60f9eaSTejun Heo 	return count;
510ff70ec8SSebastian Ott }
52*b346953dSSebastian Ott static DEVICE_ATTR_WO(recover);
530ff70ec8SSebastian Ott 
541e8da956SJan Glauber static struct device_attribute *zpci_dev_attrs[] = {
551e8da956SJan Glauber 	&dev_attr_function_id,
561e8da956SJan Glauber 	&dev_attr_function_handle,
571e8da956SJan Glauber 	&dev_attr_pchid,
581e8da956SJan Glauber 	&dev_attr_pfgid,
590ff70ec8SSebastian Ott 	&dev_attr_recover,
601e8da956SJan Glauber 	NULL,
611e8da956SJan Glauber };
621e8da956SJan Glauber 
631e8da956SJan Glauber int zpci_sysfs_add_device(struct device *dev)
641e8da956SJan Glauber {
651e8da956SJan Glauber 	int i, rc = 0;
661e8da956SJan Glauber 
671e8da956SJan Glauber 	for (i = 0; zpci_dev_attrs[i]; i++) {
681e8da956SJan Glauber 		rc = device_create_file(dev, zpci_dev_attrs[i]);
691e8da956SJan Glauber 		if (rc)
701e8da956SJan Glauber 			goto error;
711e8da956SJan Glauber 	}
721e8da956SJan Glauber 	return 0;
731e8da956SJan Glauber 
741e8da956SJan Glauber error:
751e8da956SJan Glauber 	while (--i >= 0)
761e8da956SJan Glauber 		device_remove_file(dev, zpci_dev_attrs[i]);
771e8da956SJan Glauber 	return rc;
781e8da956SJan Glauber }
791e8da956SJan Glauber 
801e8da956SJan Glauber void zpci_sysfs_remove_device(struct device *dev)
811e8da956SJan Glauber {
821e8da956SJan Glauber 	int i;
831e8da956SJan Glauber 
841e8da956SJan Glauber 	for (i = 0; zpci_dev_attrs[i]; i++)
851e8da956SJan Glauber 		device_remove_file(dev, zpci_dev_attrs[i]);
861e8da956SJan Glauber }
87