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