aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-sysfs.c
diff options
context:
space:
mode:
authorTrent Piepho <xyzzy@speakeasy.org>2008-11-30 20:10:12 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 14:12:58 -0500
commit92425a405ea482209b43093a5e35be7de02acf18 (patch)
tree0cf7d494d8a743350f29a827a272287a7d99b5d1 /drivers/pci/pci-sysfs.c
parent1684f5ddd4c0c754f52c78eaa2c5c69ad09fb18c (diff)
PCI: Make settable sysfs attributes more consistent
PCI devices have three settable boolean attributes, enable, broken_parity_status, and msi_bus. The store functions for these would silently interpret "0x01" as false, "1llogical" as true, and "true" would be (silently!) ignored and do nothing. This is inconsistent with typical sysfs handling of settable attributes, and just plain doesn't make much sense. So, use strict_strtoul(), which was created for this purpose. The store functions will treat a value of 0 as false, non-zero as true, and return -EINVAL for a parse failure. Additionally, is_enabled_store() and msi_bus_store() return -EPERM if CAP_SYS_ADMIN is lacking, rather than silently doing nothing. This is more typical behavior for sysfs attributes that need a capability. And msi_bus_store() will only print the "forced subordinate bus ..." warning if the MSI flag was actually forced to a different value. Signed-off-by: Trent Piepho <xyzzy@speakeasy.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r--drivers/pci/pci-sysfs.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d5cdccf27a69..d2f1354fd189 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -58,13 +58,14 @@ static ssize_t broken_parity_status_store(struct device *dev,
58 const char *buf, size_t count) 58 const char *buf, size_t count)
59{ 59{
60 struct pci_dev *pdev = to_pci_dev(dev); 60 struct pci_dev *pdev = to_pci_dev(dev);
61 ssize_t consumed = -EINVAL; 61 unsigned long val;
62 62
63 if ((count > 0) && (*buf == '0' || *buf == '1')) { 63 if (strict_strtoul(buf, 0, &val) < 0)
64 pdev->broken_parity_status = *buf == '1' ? 1 : 0; 64 return -EINVAL;
65 consumed = count; 65
66 } 66 pdev->broken_parity_status = !!val;
67 return consumed; 67
68 return count;
68} 69}
69 70
70static ssize_t local_cpus_show(struct device *dev, 71static ssize_t local_cpus_show(struct device *dev,
@@ -133,19 +134,23 @@ static ssize_t is_enabled_store(struct device *dev,
133 struct device_attribute *attr, const char *buf, 134 struct device_attribute *attr, const char *buf,
134 size_t count) 135 size_t count)
135{ 136{
136 ssize_t result = -EINVAL;
137 struct pci_dev *pdev = to_pci_dev(dev); 137 struct pci_dev *pdev = to_pci_dev(dev);
138 unsigned long val;
139 ssize_t result = strict_strtoul(buf, 0, &val);
140
141 if (result < 0)
142 return result;
138 143
139 /* this can crash the machine when done on the "wrong" device */ 144 /* this can crash the machine when done on the "wrong" device */
140 if (!capable(CAP_SYS_ADMIN)) 145 if (!capable(CAP_SYS_ADMIN))
141 return count; 146 return -EPERM;
142 147
143 if (*buf == '0') { 148 if (!val) {
144 if (atomic_read(&pdev->enable_cnt) != 0) 149 if (atomic_read(&pdev->enable_cnt) != 0)
145 pci_disable_device(pdev); 150 pci_disable_device(pdev);
146 else 151 else
147 result = -EIO; 152 result = -EIO;
148 } else if (*buf == '1') 153 } else
149 result = pci_enable_device(pdev); 154 result = pci_enable_device(pdev);
150 155
151 return result < 0 ? result : count; 156 return result < 0 ? result : count;
@@ -185,25 +190,28 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
185 const char *buf, size_t count) 190 const char *buf, size_t count)
186{ 191{
187 struct pci_dev *pdev = to_pci_dev(dev); 192 struct pci_dev *pdev = to_pci_dev(dev);
193 unsigned long val;
194
195 if (strict_strtoul(buf, 0, &val) < 0)
196 return -EINVAL;
188 197
189 /* bad things may happen if the no_msi flag is changed 198 /* bad things may happen if the no_msi flag is changed
190 * while some drivers are loaded */ 199 * while some drivers are loaded */
191 if (!capable(CAP_SYS_ADMIN)) 200 if (!capable(CAP_SYS_ADMIN))
192 return count; 201 return -EPERM;
193 202
203 /* Maybe pci devices without subordinate busses shouldn't even have this
204 * attribute in the first place? */
194 if (!pdev->subordinate) 205 if (!pdev->subordinate)
195 return count; 206 return count;
196 207
197 if (*buf == '0') { 208 /* Is the flag going to change, or keep the value it already had? */
198 pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; 209 if (!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI) ^
199 dev_warn(&pdev->dev, "forced subordinate bus to not support MSI," 210 !!val) {
200 " bad things could happen.\n"); 211 pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI;
201 }
202 212
203 if (*buf == '1') { 213 dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI,"
204 pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI; 214 " bad things could happen\n", val ? "" : " not");
205 dev_warn(&pdev->dev, "forced subordinate bus to support MSI,"
206 " bad things could happen.\n");
207 } 215 }
208 216
209 return count; 217 return count;