aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/eeh_sysfs.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/eeh_sysfs.c b/arch/powerpc/kernel/eeh_sysfs.c
index e2595ba4b720..eb15be4d8849 100644
--- a/arch/powerpc/kernel/eeh_sysfs.c
+++ b/arch/powerpc/kernel/eeh_sysfs.c
@@ -54,6 +54,62 @@ EEH_SHOW_ATTR(eeh_mode, mode, "0x%x");
54EEH_SHOW_ATTR(eeh_config_addr, config_addr, "0x%x"); 54EEH_SHOW_ATTR(eeh_config_addr, config_addr, "0x%x");
55EEH_SHOW_ATTR(eeh_pe_config_addr, pe_config_addr, "0x%x"); 55EEH_SHOW_ATTR(eeh_pe_config_addr, pe_config_addr, "0x%x");
56 56
57static ssize_t eeh_pe_state_show(struct device *dev,
58 struct device_attribute *attr, char *buf)
59{
60 struct pci_dev *pdev = to_pci_dev(dev);
61 struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
62 int state;
63
64 if (!edev || !edev->pe)
65 return -ENODEV;
66
67 state = eeh_ops->get_state(edev->pe, NULL);
68 return sprintf(buf, "%08x %08x\n",
69 state, edev->pe->state);
70}
71
72static ssize_t eeh_pe_state_store(struct device *dev,
73 struct device_attribute *attr,
74 const char *buf, size_t count)
75{
76 struct pci_dev *pdev = to_pci_dev(dev);
77 struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
78 int ret;
79
80 if (!edev || !edev->pe)
81 return -ENODEV;
82
83 /* Nothing to do if it's not frozen */
84 if (!(edev->pe->state & EEH_PE_ISOLATED))
85 return count;
86
87 /* Enable MMIO */
88 ret = eeh_pci_enable(edev->pe, EEH_OPT_THAW_MMIO);
89 if (ret) {
90 pr_warn("%s: Failure %d enabling MMIO for PHB#%d-PE#%d\n",
91 __func__, ret, edev->pe->phb->global_number,
92 edev->pe->addr);
93 return -EIO;
94 }
95
96 /* Enable DMA */
97 ret = eeh_pci_enable(edev->pe, EEH_OPT_THAW_DMA);
98 if (ret) {
99 pr_warn("%s: Failure %d enabling DMA for PHB#%d-PE#%d\n",
100 __func__, ret, edev->pe->phb->global_number,
101 edev->pe->addr);
102 return -EIO;
103 }
104
105 /* Clear software state */
106 eeh_pe_state_clear(edev->pe, EEH_PE_ISOLATED);
107
108 return count;
109}
110
111static DEVICE_ATTR_RW(eeh_pe_state);
112
57void eeh_sysfs_add_device(struct pci_dev *pdev) 113void eeh_sysfs_add_device(struct pci_dev *pdev)
58{ 114{
59 struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev); 115 struct eeh_dev *edev = pci_dev_to_eeh_dev(pdev);
@@ -68,9 +124,10 @@ void eeh_sysfs_add_device(struct pci_dev *pdev)
68 rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); 124 rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
69 rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); 125 rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
70 rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); 126 rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
127 rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_state);
71 128
72 if (rc) 129 if (rc)
73 printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); 130 pr_warn("EEH: Unable to create sysfs entries\n");
74 else if (edev) 131 else if (edev)
75 edev->mode |= EEH_DEV_SYSFS; 132 edev->mode |= EEH_DEV_SYSFS;
76} 133}
@@ -92,6 +149,7 @@ void eeh_sysfs_remove_device(struct pci_dev *pdev)
92 device_remove_file(&pdev->dev, &dev_attr_eeh_mode); 149 device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
93 device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); 150 device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
94 device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); 151 device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
152 device_remove_file(&pdev->dev, &dev_attr_eeh_pe_state);
95 153
96 if (edev) 154 if (edev)
97 edev->mode &= ~EEH_DEV_SYSFS; 155 edev->mode &= ~EEH_DEV_SYSFS;