xref: /linux/arch/s390/pci/pci_sysfs.c (revision 0b60f9ead5d4816e7e3d6e28f4a0d22d4a1b2513)
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 
151e8da956SJan Glauber static ssize_t show_fid(struct device *dev, struct device_attribute *attr,
161e8da956SJan Glauber 			char *buf)
171e8da956SJan Glauber {
189294896eSSebastian Ott 	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
191e8da956SJan Glauber 
2080b054baSSebastian Ott 	return sprintf(buf, "0x%08x\n", zdev->fid);
211e8da956SJan Glauber }
221e8da956SJan Glauber static DEVICE_ATTR(function_id, S_IRUGO, show_fid, NULL);
231e8da956SJan Glauber 
241e8da956SJan Glauber static ssize_t show_fh(struct device *dev, struct device_attribute *attr,
251e8da956SJan Glauber 		       char *buf)
261e8da956SJan Glauber {
279294896eSSebastian Ott 	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
281e8da956SJan Glauber 
2980b054baSSebastian Ott 	return sprintf(buf, "0x%08x\n", zdev->fh);
301e8da956SJan Glauber }
311e8da956SJan Glauber static DEVICE_ATTR(function_handle, S_IRUGO, show_fh, NULL);
321e8da956SJan Glauber 
331e8da956SJan Glauber static ssize_t show_pchid(struct device *dev, struct device_attribute *attr,
341e8da956SJan Glauber 			  char *buf)
351e8da956SJan Glauber {
369294896eSSebastian Ott 	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
371e8da956SJan Glauber 
3880b054baSSebastian Ott 	return sprintf(buf, "0x%04x\n", zdev->pchid);
391e8da956SJan Glauber }
401e8da956SJan Glauber static DEVICE_ATTR(pchid, S_IRUGO, show_pchid, NULL);
411e8da956SJan Glauber 
421e8da956SJan Glauber static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
431e8da956SJan Glauber 			  char *buf)
441e8da956SJan Glauber {
459294896eSSebastian Ott 	struct zpci_dev *zdev = get_zdev(to_pci_dev(dev));
461e8da956SJan Glauber 
4780b054baSSebastian Ott 	return sprintf(buf, "0x%02x\n", zdev->pfgid);
481e8da956SJan Glauber }
491e8da956SJan Glauber static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);
501e8da956SJan Glauber 
51*0b60f9eaSTejun Heo static ssize_t store_recover(struct device *dev, struct device_attribute *attr,
52*0b60f9eaSTejun Heo 			     const char *buf, size_t count)
530ff70ec8SSebastian Ott {
540ff70ec8SSebastian Ott 	struct pci_dev *pdev = to_pci_dev(dev);
550ff70ec8SSebastian Ott 	struct zpci_dev *zdev = get_zdev(pdev);
560ff70ec8SSebastian Ott 	int ret;
570ff70ec8SSebastian Ott 
58*0b60f9eaSTejun Heo 	if (!device_remove_file_self(dev, attr))
59*0b60f9eaSTejun Heo 		return count;
60*0b60f9eaSTejun Heo 
610ff70ec8SSebastian Ott 	pci_stop_and_remove_bus_device(pdev);
620ff70ec8SSebastian Ott 	ret = zpci_disable_device(zdev);
630ff70ec8SSebastian Ott 	if (ret)
64*0b60f9eaSTejun Heo 		return ret;
650ff70ec8SSebastian Ott 
660ff70ec8SSebastian Ott 	ret = zpci_enable_device(zdev);
670ff70ec8SSebastian Ott 	if (ret)
68*0b60f9eaSTejun Heo 		return ret;
690ff70ec8SSebastian Ott 
700ff70ec8SSebastian Ott 	pci_rescan_bus(zdev->bus);
71*0b60f9eaSTejun Heo 	return count;
720ff70ec8SSebastian Ott }
730ff70ec8SSebastian Ott static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover);
740ff70ec8SSebastian Ott 
751e8da956SJan Glauber static struct device_attribute *zpci_dev_attrs[] = {
761e8da956SJan Glauber 	&dev_attr_function_id,
771e8da956SJan Glauber 	&dev_attr_function_handle,
781e8da956SJan Glauber 	&dev_attr_pchid,
791e8da956SJan Glauber 	&dev_attr_pfgid,
800ff70ec8SSebastian Ott 	&dev_attr_recover,
811e8da956SJan Glauber 	NULL,
821e8da956SJan Glauber };
831e8da956SJan Glauber 
841e8da956SJan Glauber int zpci_sysfs_add_device(struct device *dev)
851e8da956SJan Glauber {
861e8da956SJan Glauber 	int i, rc = 0;
871e8da956SJan Glauber 
881e8da956SJan Glauber 	for (i = 0; zpci_dev_attrs[i]; i++) {
891e8da956SJan Glauber 		rc = device_create_file(dev, zpci_dev_attrs[i]);
901e8da956SJan Glauber 		if (rc)
911e8da956SJan Glauber 			goto error;
921e8da956SJan Glauber 	}
931e8da956SJan Glauber 	return 0;
941e8da956SJan Glauber 
951e8da956SJan Glauber error:
961e8da956SJan Glauber 	while (--i >= 0)
971e8da956SJan Glauber 		device_remove_file(dev, zpci_dev_attrs[i]);
981e8da956SJan Glauber 	return rc;
991e8da956SJan Glauber }
1001e8da956SJan Glauber 
1011e8da956SJan Glauber void zpci_sysfs_remove_device(struct device *dev)
1021e8da956SJan Glauber {
1031e8da956SJan Glauber 	int i;
1041e8da956SJan Glauber 
1051e8da956SJan Glauber 	for (i = 0; zpci_dev_attrs[i]; i++)
1061e8da956SJan Glauber 		device_remove_file(dev, zpci_dev_attrs[i]);
1071e8da956SJan Glauber }
108