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