Blame view

drivers/pci/pci-sysfs.c 43.7 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * drivers/pci/pci-sysfs.c
   *
   * (C) Copyright 2002-2004 Greg Kroah-Hartman <greg@kroah.com>
   * (C) Copyright 2002-2004 IBM Corp.
   * (C) Copyright 2003 Matthew Wilcox
   * (C) Copyright 2003 Hewlett-Packard
   * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
   * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
   *
   * File attributes for PCI devices
   *
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
14
   * Modeled after usb's driverfs.c
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/kernel.h>
b5ff7df3d   Linus Torvalds   Check mapped rang...
18
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <linux/pci.h>
  #include <linux/stat.h>
363c75db1   Paul Gortmaker   pci: Fix files ne...
21
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  #include <linux/topology.h>
  #include <linux/mm.h>
de139a339   Chris Wright   pci: check caps f...
24
  #include <linux/fs.h>
aa0ac3651   Alexey Dobriyan   Remove capability...
25
  #include <linux/capability.h>
a628e7b87   Chris Wright   pci: use security...
26
  #include <linux/security.h>
7d715a6c1   Shaohua Li   PCI: add PCI Expr...
27
  #include <linux/pci-aspm.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
1a39b310e   Matthew Garrett   vgaarb: Add suppo...
29
  #include <linux/vgaarb.h>
448bd857d   Huang Ying   PCI/PM: add PCIe ...
30
  #include <linux/pm_runtime.h>
dfc73e7ac   Sebastian Ott   PCI: Move Open Fi...
31
  #include <linux/of.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
  #include "pci.h"
  
  static int sysfs_initialized;	/* = 0 */
  
  /* show configuration fields */
  #define pci_config_attr(field, format_string)				\
  static ssize_t								\
e404e274f   Yani Ioannou   [PATCH] Driver Co...
39
  field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
  {									\
  	struct pci_dev *pdev;						\
  									\
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
43
44
  	pdev = to_pci_dev(dev);						\
  	return sprintf(buf, format_string, pdev->field);		\
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
45
46
  }									\
  static DEVICE_ATTR_RO(field)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
  
  pci_config_attr(vendor, "0x%04x
  ");
  pci_config_attr(device, "0x%04x
  ");
  pci_config_attr(subsystem_vendor, "0x%04x
  ");
  pci_config_attr(subsystem_device, "0x%04x
  ");
702ed3be1   Emil Velikov   PCI: Create revis...
56
57
  pci_config_attr(revision, "0x%02x
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
  pci_config_attr(class, "0x%06x
  ");
  pci_config_attr(irq, "%u
  ");
bdee9d98d   Doug Thompson   [PATCH] PCI: Bus ...
62
63
64
65
66
  static ssize_t broken_parity_status_show(struct device *dev,
  					 struct device_attribute *attr,
  					 char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
67
68
  	return sprintf(buf, "%u
  ", pdev->broken_parity_status);
bdee9d98d   Doug Thompson   [PATCH] PCI: Bus ...
69
70
71
72
73
74
75
  }
  
  static ssize_t broken_parity_status_store(struct device *dev,
  					  struct device_attribute *attr,
  					  const char *buf, size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
92425a405   Trent Piepho   PCI: Make settabl...
76
  	unsigned long val;
bdee9d98d   Doug Thompson   [PATCH] PCI: Bus ...
77

9a994e8ec   Jingoo Han   PCI: Replace stri...
78
  	if (kstrtoul(buf, 0, &val) < 0)
92425a405   Trent Piepho   PCI: Make settabl...
79
80
81
82
83
  		return -EINVAL;
  
  	pdev->broken_parity_status = !!val;
  
  	return count;
bdee9d98d   Doug Thompson   [PATCH] PCI: Bus ...
84
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
85
  static DEVICE_ATTR_RW(broken_parity_status);
bdee9d98d   Doug Thompson   [PATCH] PCI: Bus ...
86

5aaba3631   Sudeep Holla   cpumask: factor o...
87
  static ssize_t pci_dev_show_local_cpu(struct device *dev, bool list,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
88
  				      struct device_attribute *attr, char *buf)
c489f5fbb   Yijing Wang   PCI: Add pci_dev_...
89
  {
3be83050d   Mike Travis   cpumask: update l...
90
  	const struct cpumask *mask;
4327edf6b   Alan Cox   [PATCH] Subject: ...
91

e0cd51603   Andreas Herrmann   PCI: derive nearb...
92
  #ifdef CONFIG_NUMA
6be954d1f   David John   PCI: Check the no...
93
94
  	mask = (dev_to_node(dev) == -1) ? cpu_online_mask :
  					  cpumask_of_node(dev_to_node(dev));
e0cd51603   Andreas Herrmann   PCI: derive nearb...
95
  #else
3be83050d   Mike Travis   cpumask: update l...
96
  	mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
e0cd51603   Andreas Herrmann   PCI: derive nearb...
97
  #endif
5aaba3631   Sudeep Holla   cpumask: factor o...
98
  	return cpumap_print_to_pagebuf(list, buf, mask);
39106dcf8   Mike Travis   cpumask: use new ...
99
  }
c489f5fbb   Yijing Wang   PCI: Add pci_dev_...
100
  static ssize_t local_cpus_show(struct device *dev,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
101
  			       struct device_attribute *attr, char *buf)
c489f5fbb   Yijing Wang   PCI: Add pci_dev_...
102
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
103
  	return pci_dev_show_local_cpu(dev, false, attr, buf);
c489f5fbb   Yijing Wang   PCI: Add pci_dev_...
104
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
105
  static DEVICE_ATTR_RO(local_cpus);
39106dcf8   Mike Travis   cpumask: use new ...
106
107
  
  static ssize_t local_cpulist_show(struct device *dev,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
108
  				  struct device_attribute *attr, char *buf)
39106dcf8   Mike Travis   cpumask: use new ...
109
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
110
  	return pci_dev_show_local_cpu(dev, true, attr, buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
112
  static DEVICE_ATTR_RO(local_cpulist);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113

dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
114
115
116
  /*
   * PCI Bus Class Devices
   */
56039e658   Greg Kroah-Hartman   PCI: Convert clas...
117
118
  static ssize_t cpuaffinity_show(struct device *dev,
  				struct device_attribute *attr, char *buf)
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
119
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
120
121
122
  	const struct cpumask *cpumask = cpumask_of_pcibus(to_pci_bus(dev));
  
  	return cpumap_print_to_pagebuf(false, buf, cpumask);
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
123
  }
56039e658   Greg Kroah-Hartman   PCI: Convert clas...
124
  static DEVICE_ATTR_RO(cpuaffinity);
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
125

56039e658   Greg Kroah-Hartman   PCI: Convert clas...
126
127
  static ssize_t cpulistaffinity_show(struct device *dev,
  				    struct device_attribute *attr, char *buf)
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
128
  {
5aaba3631   Sudeep Holla   cpumask: factor o...
129
130
131
  	const struct cpumask *cpumask = cpumask_of_pcibus(to_pci_bus(dev));
  
  	return cpumap_print_to_pagebuf(true, buf, cpumask);
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
132
  }
56039e658   Greg Kroah-Hartman   PCI: Convert clas...
133
  static DEVICE_ATTR_RO(cpulistaffinity);
dc2c2c9dd   Yinghai Lu   PCI/sysfs: move b...
134

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  /* show resources */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
136
137
  static ssize_t resource_show(struct device *dev, struct device_attribute *attr,
  			     char *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
  {
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
139
140
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	char *str = buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  	int i;
fde09c6d8   Yu Zhao   PCI: define PCI r...
142
  	int max;
e31dd6e45   Greg Kroah-Hartman   [PATCH] 64bit res...
143
  	resource_size_t start, end;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
  
  	if (pci_dev->subordinate)
  		max = DEVICE_COUNT_RESOURCE;
fde09c6d8   Yu Zhao   PCI: define PCI r...
147
148
  	else
  		max = PCI_BRIDGE_RESOURCES;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
  
  	for (i = 0; i < max; i++) {
2311b1f2b   Michael Ellerman   [PATCH] PCI: fix-...
151
152
  		struct resource *res =  &pci_dev->resource[i];
  		pci_resource_to_user(pci_dev, i, res, &start, &end);
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
153
154
  		str += sprintf(str, "0x%016llx 0x%016llx 0x%016llx
  ",
2311b1f2b   Michael Ellerman   [PATCH] PCI: fix-...
155
156
157
  			       (unsigned long long)start,
  			       (unsigned long long)end,
  			       (unsigned long long)res->flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
  	}
  	return (str - buf);
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
161
  static DEVICE_ATTR_RO(resource);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  static ssize_t max_link_speed_show(struct device *dev,
  				   struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u32 linkcap;
  	int err;
  	const char *speed;
  
  	err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap);
  	if (err)
  		return -EINVAL;
  
  	switch (linkcap & PCI_EXP_LNKCAP_SLS) {
  	case PCI_EXP_LNKCAP_SLS_8_0GB:
  		speed = "8 GT/s";
  		break;
  	case PCI_EXP_LNKCAP_SLS_5_0GB:
  		speed = "5 GT/s";
  		break;
  	case PCI_EXP_LNKCAP_SLS_2_5GB:
  		speed = "2.5 GT/s";
  		break;
  	default:
  		speed = "Unknown speed";
  	}
  
  	return sprintf(buf, "%s
  ", speed);
  }
  static DEVICE_ATTR_RO(max_link_speed);
  
  static ssize_t max_link_width_show(struct device *dev,
  				   struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u32 linkcap;
  	int err;
  
  	err = pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &linkcap);
  	if (err)
  		return -EINVAL;
  
  	return sprintf(buf, "%u
  ", (linkcap & PCI_EXP_LNKCAP_MLW) >> 4);
  }
  static DEVICE_ATTR_RO(max_link_width);
  
  static ssize_t current_link_speed_show(struct device *dev,
  				       struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u16 linkstat;
  	int err;
  	const char *speed;
  
  	err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat);
  	if (err)
  		return -EINVAL;
  
  	switch (linkstat & PCI_EXP_LNKSTA_CLS) {
  	case PCI_EXP_LNKSTA_CLS_8_0GB:
  		speed = "8 GT/s";
  		break;
  	case PCI_EXP_LNKSTA_CLS_5_0GB:
  		speed = "5 GT/s";
  		break;
  	case PCI_EXP_LNKSTA_CLS_2_5GB:
  		speed = "2.5 GT/s";
  		break;
  	default:
  		speed = "Unknown speed";
  	}
  
  	return sprintf(buf, "%s
  ", speed);
  }
  static DEVICE_ATTR_RO(current_link_speed);
  
  static ssize_t current_link_width_show(struct device *dev,
  				       struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u16 linkstat;
  	int err;
  
  	err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat);
  	if (err)
  		return -EINVAL;
  
  	return sprintf(buf, "%u
  ",
  		(linkstat & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT);
  }
  static DEVICE_ATTR_RO(current_link_width);
  
  static ssize_t secondary_bus_number_show(struct device *dev,
  					 struct device_attribute *attr,
  					 char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u8 sec_bus;
  	int err;
  
  	err = pci_read_config_byte(pci_dev, PCI_SECONDARY_BUS, &sec_bus);
  	if (err)
  		return -EINVAL;
  
  	return sprintf(buf, "%u
  ", sec_bus);
  }
  static DEVICE_ATTR_RO(secondary_bus_number);
  
  static ssize_t subordinate_bus_number_show(struct device *dev,
  					   struct device_attribute *attr,
  					   char *buf)
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
  	u8 sub_bus;
  	int err;
  
  	err = pci_read_config_byte(pci_dev, PCI_SUBORDINATE_BUS, &sub_bus);
  	if (err)
  		return -EINVAL;
  
  	return sprintf(buf, "%u
  ", sub_bus);
  }
  static DEVICE_ATTR_RO(subordinate_bus_number);
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
291
292
  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
  			     char *buf)
9888549e0   Greg Kroah-Hartman   [PATCH] PCI: add ...
293
294
  {
  	struct pci_dev *pci_dev = to_pci_dev(dev);
89ec3dcf1   Ricardo Ribalda Delgado   PCI: Generate upp...
295
296
  	return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02X
  ",
9888549e0   Greg Kroah-Hartman   [PATCH] PCI: add ...
297
298
299
300
301
  		       pci_dev->vendor, pci_dev->device,
  		       pci_dev->subsystem_vendor, pci_dev->subsystem_device,
  		       (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
  		       (u8)(pci_dev->class));
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
302
  static DEVICE_ATTR_RO(modalias);
bae94d023   Inaky Perez-Gonzalez   PCI: switch pci_{...
303

d8e7d53a2   Greg Kroah-Hartman   PCI: Rename sysfs...
304
  static ssize_t enable_store(struct device *dev, struct device_attribute *attr,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
305
  			     const char *buf, size_t count)
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
306
307
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
92425a405   Trent Piepho   PCI: Make settabl...
308
  	unsigned long val;
9a994e8ec   Jingoo Han   PCI: Replace stri...
309
  	ssize_t result = kstrtoul(buf, 0, &val);
92425a405   Trent Piepho   PCI: Make settabl...
310
311
312
  
  	if (result < 0)
  		return result;
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
313
314
315
  
  	/* this can crash the machine when done on the "wrong" device */
  	if (!capable(CAP_SYS_ADMIN))
92425a405   Trent Piepho   PCI: Make settabl...
316
  		return -EPERM;
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
317

2040b0d8c   Christoph Hellwig   PCI: Prevent sysf...
318
319
320
321
  	device_lock(dev);
  	if (dev->driver)
  		result = -EBUSY;
  	else if (val)
bae94d023   Inaky Perez-Gonzalez   PCI: switch pci_{...
322
  		result = pci_enable_device(pdev);
2040b0d8c   Christoph Hellwig   PCI: Prevent sysf...
323
324
325
326
327
  	else if (pci_is_enabled(pdev))
  		pci_disable_device(pdev);
  	else
  		result = -EIO;
  	device_unlock(dev);
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
328

bae94d023   Inaky Perez-Gonzalez   PCI: switch pci_{...
329
330
  	return result < 0 ? result : count;
  }
d8e7d53a2   Greg Kroah-Hartman   PCI: Rename sysfs...
331
  static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
332
  			    char *buf)
bae94d023   Inaky Perez-Gonzalez   PCI: switch pci_{...
333
334
  {
  	struct pci_dev *pdev;
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
335

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
336
337
338
  	pdev = to_pci_dev(dev);
  	return sprintf(buf, "%u
  ", atomic_read(&pdev->enable_cnt));
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
339
  }
d8e7d53a2   Greg Kroah-Hartman   PCI: Rename sysfs...
340
  static DEVICE_ATTR_RW(enable);
9f125d304   Arjan van de Ven   [PATCH] PCI: Add ...
341

81bb0e198   Brice Goglin   PCI: Make PCI dev...
342
  #ifdef CONFIG_NUMA
63692df10   Prarit Bhargava   PCI: Allow numa_n...
343
344
345
346
347
348
349
350
351
352
353
354
355
  static ssize_t numa_node_store(struct device *dev,
  			       struct device_attribute *attr, const char *buf,
  			       size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  	int node, ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	ret = kstrtoint(buf, 0, &node);
  	if (ret)
  		return ret;
3dcc8d39c   Mathias Krause   PCI: Prevent out ...
356
357
358
359
  	if ((node < 0 && node != NUMA_NO_NODE) || node >= MAX_NUMNODES)
  		return -EINVAL;
  
  	if (node != NUMA_NO_NODE && !node_online(node))
63692df10   Prarit Bhargava   PCI: Allow numa_n...
360
361
362
363
364
365
366
367
368
  		return -EINVAL;
  
  	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
  	dev_alert(&pdev->dev, FW_BUG "Overriding NUMA node to %d.  Contact your vendor for updates.",
  		  node);
  
  	dev->numa_node = node;
  	return count;
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
369
370
  static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr,
  			      char *buf)
81bb0e198   Brice Goglin   PCI: Make PCI dev...
371
  {
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
372
373
  	return sprintf(buf, "%d
  ", dev->numa_node);
81bb0e198   Brice Goglin   PCI: Make PCI dev...
374
  }
63692df10   Prarit Bhargava   PCI: Allow numa_n...
375
  static DEVICE_ATTR_RW(numa_node);
81bb0e198   Brice Goglin   PCI: Make PCI dev...
376
  #endif
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
377
378
  static ssize_t dma_mask_bits_show(struct device *dev,
  				  struct device_attribute *attr, char *buf)
bb965401f   Yinghai Lu   PCI: show dma_mas...
379
380
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
381
382
  	return sprintf(buf, "%d
  ", fls64(pdev->dma_mask));
bb965401f   Yinghai Lu   PCI: show dma_mas...
383
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
384
  static DEVICE_ATTR_RO(dma_mask_bits);
bb965401f   Yinghai Lu   PCI: show dma_mas...
385

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
386
387
388
  static ssize_t consistent_dma_mask_bits_show(struct device *dev,
  					     struct device_attribute *attr,
  					     char *buf)
bb965401f   Yinghai Lu   PCI: show dma_mas...
389
  {
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
390
391
  	return sprintf(buf, "%d
  ", fls64(dev->coherent_dma_mask));
bb965401f   Yinghai Lu   PCI: show dma_mas...
392
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
393
  static DEVICE_ATTR_RO(consistent_dma_mask_bits);
bb965401f   Yinghai Lu   PCI: show dma_mas...
394

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
395
396
  static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr,
  			    char *buf)
fe97064c2   Brice Goglin   MSI: Export the P...
397
398
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
399
  	struct pci_bus *subordinate = pdev->subordinate;
fe97064c2   Brice Goglin   MSI: Export the P...
400

468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
401
402
403
404
  	return sprintf(buf, "%u
  ", subordinate ?
  		       !(subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI)
  			   : !pdev->no_msi);
fe97064c2   Brice Goglin   MSI: Export the P...
405
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
406
407
  static ssize_t msi_bus_store(struct device *dev, struct device_attribute *attr,
  			     const char *buf, size_t count)
fe97064c2   Brice Goglin   MSI: Export the P...
408
409
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
410
  	struct pci_bus *subordinate = pdev->subordinate;
92425a405   Trent Piepho   PCI: Make settabl...
411
  	unsigned long val;
9a994e8ec   Jingoo Han   PCI: Replace stri...
412
  	if (kstrtoul(buf, 0, &val) < 0)
92425a405   Trent Piepho   PCI: Make settabl...
413
  		return -EINVAL;
fe97064c2   Brice Goglin   MSI: Export the P...
414

fe97064c2   Brice Goglin   MSI: Export the P...
415
  	if (!capable(CAP_SYS_ADMIN))
92425a405   Trent Piepho   PCI: Make settabl...
416
  		return -EPERM;
fe97064c2   Brice Goglin   MSI: Export the P...
417

f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
418
  	/*
468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
419
420
421
  	 * "no_msi" and "bus_flags" only affect what happens when a driver
  	 * requests MSI or MSI-X.  They don't affect any drivers that have
  	 * already requested MSI or MSI-X.
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
422
  	 */
468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
423
424
425
426
427
  	if (!subordinate) {
  		pdev->no_msi = !val;
  		dev_info(&pdev->dev, "MSI/MSI-X %s for future drivers
  ",
  			 val ? "allowed" : "disallowed");
fe97064c2   Brice Goglin   MSI: Export the P...
428
  		return count;
fe97064c2   Brice Goglin   MSI: Export the P...
429
  	}
468ff15a3   Yijing Wang   PCI/MSI: Add "msi...
430
431
432
433
434
435
436
437
  	if (val)
  		subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
  	else
  		subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
  
  	dev_info(&subordinate->dev, "MSI/MSI-X %s for future drivers of devices on this bus
  ",
  		 val ? "allowed" : "disallowed");
fe97064c2   Brice Goglin   MSI: Export the P...
438
439
  	return count;
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
440
  static DEVICE_ATTR_RW(msi_bus);
9888549e0   Greg Kroah-Hartman   [PATCH] PCI: add ...
441

705b1aaa8   Alex Chiang   PCI: Introduce /s...
442
443
444
445
446
  static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
  				size_t count)
  {
  	unsigned long val;
  	struct pci_bus *b = NULL;
9a994e8ec   Jingoo Han   PCI: Replace stri...
447
  	if (kstrtoul(buf, 0, &val) < 0)
705b1aaa8   Alex Chiang   PCI: Introduce /s...
448
449
450
  		return -EINVAL;
  
  	if (val) {
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
451
  		pci_lock_rescan_remove();
705b1aaa8   Alex Chiang   PCI: Introduce /s...
452
453
  		while ((b = pci_find_next_bus(b)) != NULL)
  			pci_rescan_bus(b);
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
454
  		pci_unlock_rescan_remove();
705b1aaa8   Alex Chiang   PCI: Introduce /s...
455
456
457
  	}
  	return count;
  }
0f49ba559   Greg Kroah-Hartman   PCI: convert bus ...
458
  static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store);
705b1aaa8   Alex Chiang   PCI: Introduce /s...
459

bf22c90fb   Sachin Kamat   PCI: Make pci_bus...
460
  static struct attribute *pci_bus_attrs[] = {
0f49ba559   Greg Kroah-Hartman   PCI: convert bus ...
461
462
463
464
465
466
467
468
469
470
471
  	&bus_attr_rescan.attr,
  	NULL,
  };
  
  static const struct attribute_group pci_bus_group = {
  	.attrs = pci_bus_attrs,
  };
  
  const struct attribute_group *pci_bus_groups[] = {
  	&pci_bus_group,
  	NULL,
705b1aaa8   Alex Chiang   PCI: Introduce /s...
472
  };
77c27c7b4   Alex Chiang   PCI: Introduce /s...
473

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
474
475
476
  static ssize_t dev_rescan_store(struct device *dev,
  				struct device_attribute *attr, const char *buf,
  				size_t count)
738a6396c   Alex Chiang   PCI: Introduce /s...
477
478
479
  {
  	unsigned long val;
  	struct pci_dev *pdev = to_pci_dev(dev);
9a994e8ec   Jingoo Han   PCI: Replace stri...
480
  	if (kstrtoul(buf, 0, &val) < 0)
738a6396c   Alex Chiang   PCI: Introduce /s...
481
482
483
  		return -EINVAL;
  
  	if (val) {
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
484
  		pci_lock_rescan_remove();
738a6396c   Alex Chiang   PCI: Introduce /s...
485
  		pci_rescan_bus(pdev->bus);
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
486
  		pci_unlock_rescan_remove();
738a6396c   Alex Chiang   PCI: Introduce /s...
487
488
489
  	}
  	return count;
  }
bf22c90fb   Sachin Kamat   PCI: Make pci_bus...
490
491
492
  static struct device_attribute dev_rescan_attr = __ATTR(rescan,
  							(S_IWUSR|S_IWGRP),
  							NULL, dev_rescan_store);
738a6396c   Alex Chiang   PCI: Introduce /s...
493

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
494
495
  static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
  			    const char *buf, size_t count)
77c27c7b4   Alex Chiang   PCI: Introduce /s...
496
  {
77c27c7b4   Alex Chiang   PCI: Introduce /s...
497
  	unsigned long val;
77c27c7b4   Alex Chiang   PCI: Introduce /s...
498

9a994e8ec   Jingoo Han   PCI: Replace stri...
499
  	if (kstrtoul(buf, 0, &val) < 0)
77c27c7b4   Alex Chiang   PCI: Introduce /s...
500
  		return -EINVAL;
bc6caf02c   Tejun Heo   pci: use device_r...
501
502
  	if (val && device_remove_file_self(dev, attr))
  		pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));
77c27c7b4   Alex Chiang   PCI: Introduce /s...
503
504
  	return count;
  }
bf22c90fb   Sachin Kamat   PCI: Make pci_bus...
505
506
507
  static struct device_attribute dev_remove_attr = __ATTR(remove,
  							(S_IWUSR|S_IWGRP),
  							NULL, remove_store);
b9d320fcb   Yinghai Lu   PCI: add rescan t...
508

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
509
510
511
  static ssize_t dev_bus_rescan_store(struct device *dev,
  				    struct device_attribute *attr,
  				    const char *buf, size_t count)
b9d320fcb   Yinghai Lu   PCI: add rescan t...
512
513
514
  {
  	unsigned long val;
  	struct pci_bus *bus = to_pci_bus(dev);
9a994e8ec   Jingoo Han   PCI: Replace stri...
515
  	if (kstrtoul(buf, 0, &val) < 0)
b9d320fcb   Yinghai Lu   PCI: add rescan t...
516
517
518
  		return -EINVAL;
  
  	if (val) {
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
519
  		pci_lock_rescan_remove();
2f320521a   Yinghai Lu   PCI: Make rescan ...
520
521
522
523
  		if (!pci_is_root_bus(bus) && list_empty(&bus->devices))
  			pci_rescan_bus_bridge_resize(bus->self);
  		else
  			pci_rescan_bus(bus);
9d16947b7   Rafael J. Wysocki   PCI: Add global p...
524
  		pci_unlock_rescan_remove();
b9d320fcb   Yinghai Lu   PCI: add rescan t...
525
526
527
  	}
  	return count;
  }
56039e658   Greg Kroah-Hartman   PCI: Convert clas...
528
  static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store);
b9d320fcb   Yinghai Lu   PCI: add rescan t...
529

fbb988be7   Rafael J. Wysocki   PCI / PM: Drop CO...
530
  #if defined(CONFIG_PM) && defined(CONFIG_ACPI)
448bd857d   Huang Ying   PCI/PM: add PCIe ...
531
532
533
534
535
536
  static ssize_t d3cold_allowed_store(struct device *dev,
  				    struct device_attribute *attr,
  				    const char *buf, size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  	unsigned long val;
9a994e8ec   Jingoo Han   PCI: Replace stri...
537
  	if (kstrtoul(buf, 0, &val) < 0)
448bd857d   Huang Ying   PCI/PM: add PCIe ...
538
539
540
  		return -EINVAL;
  
  	pdev->d3cold_allowed = !!val;
9d26d3a8f   Mika Westerberg   PCI: Put PCIe por...
541
542
543
544
  	if (pdev->d3cold_allowed)
  		pci_d3cold_enable(pdev);
  	else
  		pci_d3cold_disable(pdev);
448bd857d   Huang Ying   PCI/PM: add PCIe ...
545
546
547
548
549
550
551
552
553
  	pm_runtime_resume(dev);
  
  	return count;
  }
  
  static ssize_t d3cold_allowed_show(struct device *dev,
  				   struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
554
555
  	return sprintf(buf, "%u
  ", pdev->d3cold_allowed);
448bd857d   Huang Ying   PCI/PM: add PCIe ...
556
  }
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
557
  static DEVICE_ATTR_RW(d3cold_allowed);
448bd857d   Huang Ying   PCI/PM: add PCIe ...
558
  #endif
dfc73e7ac   Sebastian Ott   PCI: Move Open Fi...
559
560
561
562
563
564
  #ifdef CONFIG_OF
  static ssize_t devspec_show(struct device *dev,
  			    struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  	struct device_node *np = pci_device_to_OF_node(pdev);
b63773a80   Rob Herring   PCI: Convert to u...
565
  	if (np == NULL)
dfc73e7ac   Sebastian Ott   PCI: Move Open Fi...
566
  		return 0;
b63773a80   Rob Herring   PCI: Convert to u...
567
  	return sprintf(buf, "%pOF", np);
dfc73e7ac   Sebastian Ott   PCI: Move Open Fi...
568
569
570
  }
  static DEVICE_ATTR_RO(devspec);
  #endif
1789382a7   Donald Dutile   PCI: SRIOV contro...
571
572
573
574
575
576
  #ifdef CONFIG_PCI_IOV
  static ssize_t sriov_totalvfs_show(struct device *dev,
  				   struct device_attribute *attr,
  				   char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
bff73156d   Donald Dutile   PCI: Provide meth...
577
578
  	return sprintf(buf, "%u
  ", pci_sriov_get_totalvfs(pdev));
1789382a7   Donald Dutile   PCI: SRIOV contro...
579
580
581
582
583
584
585
586
  }
  
  
  static ssize_t sriov_numvfs_show(struct device *dev,
  				 struct device_attribute *attr,
  				 char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
6b1367246   Bjorn Helgaas   PCI: Use spec nam...
587
588
  	return sprintf(buf, "%u
  ", pdev->sriov->num_VFs);
1789382a7   Donald Dutile   PCI: SRIOV contro...
589
590
591
  }
  
  /*
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
592
593
   * num_vfs > 0; number of VFs to enable
   * num_vfs = 0; disable all VFs
1789382a7   Donald Dutile   PCI: SRIOV contro...
594
595
   *
   * Note: SRIOV spec doesn't allow partial VF
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
596
   *       disable, so it's all or none.
1789382a7   Donald Dutile   PCI: SRIOV contro...
597
598
599
600
601
602
   */
  static ssize_t sriov_numvfs_store(struct device *dev,
  				  struct device_attribute *attr,
  				  const char *buf, size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
603
604
  	int ret;
  	u16 num_vfs;
1789382a7   Donald Dutile   PCI: SRIOV contro...
605

faa48a507   Bjorn Helgaas   PCI: Remove spuri...
606
607
608
609
610
611
  	ret = kstrtou16(buf, 0, &num_vfs);
  	if (ret < 0)
  		return ret;
  
  	if (num_vfs > pci_sriov_get_totalvfs(pdev))
  		return -ERANGE;
17530e71e   Jakub Kicinski   PCI: Protect pci_...
612
  	device_lock(&pdev->dev);
5b0948dfe   Emil Tantilov   PCI: Lock each en...
613

faa48a507   Bjorn Helgaas   PCI: Remove spuri...
614
  	if (num_vfs == pdev->sriov->num_VFs)
5b0948dfe   Emil Tantilov   PCI: Lock each en...
615
  		goto exit;
1789382a7   Donald Dutile   PCI: SRIOV contro...
616
617
618
  
  	/* is PF driver loaded w/callback */
  	if (!pdev->driver || !pdev->driver->sriov_configure) {
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
619
620
  		dev_info(&pdev->dev, "Driver doesn't support SRIOV configuration via sysfs
  ");
5b0948dfe   Emil Tantilov   PCI: Lock each en...
621
622
  		ret = -ENOENT;
  		goto exit;
1789382a7   Donald Dutile   PCI: SRIOV contro...
623
  	}
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
624
625
626
  	if (num_vfs == 0) {
  		/* disable VFs */
  		ret = pdev->driver->sriov_configure(pdev, 0);
5b0948dfe   Emil Tantilov   PCI: Lock each en...
627
  		goto exit;
1789382a7   Donald Dutile   PCI: SRIOV contro...
628
  	}
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
629
630
631
632
633
  	/* enable VFs */
  	if (pdev->sriov->num_VFs) {
  		dev_warn(&pdev->dev, "%d VFs already enabled. Disable before enabling %d VFs
  ",
  			 pdev->sriov->num_VFs, num_vfs);
5b0948dfe   Emil Tantilov   PCI: Lock each en...
634
635
  		ret = -EBUSY;
  		goto exit;
1789382a7   Donald Dutile   PCI: SRIOV contro...
636
  	}
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
637
638
  	ret = pdev->driver->sriov_configure(pdev, num_vfs);
  	if (ret < 0)
5b0948dfe   Emil Tantilov   PCI: Lock each en...
639
  		goto exit;
1789382a7   Donald Dutile   PCI: SRIOV contro...
640

faa48a507   Bjorn Helgaas   PCI: Remove spuri...
641
642
643
644
  	if (ret != num_vfs)
  		dev_warn(&pdev->dev, "%d VFs requested; only %d enabled
  ",
  			 num_vfs, ret);
5b0948dfe   Emil Tantilov   PCI: Lock each en...
645
  exit:
17530e71e   Jakub Kicinski   PCI: Protect pci_...
646
  	device_unlock(&pdev->dev);
5b0948dfe   Emil Tantilov   PCI: Lock each en...
647
648
649
  
  	if (ret < 0)
  		return ret;
faa48a507   Bjorn Helgaas   PCI: Remove spuri...
650
  	return count;
1789382a7   Donald Dutile   PCI: SRIOV contro...
651
  }
0e7df2240   Bodong Wang   PCI: Add sysfs sr...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
  					    struct device_attribute *attr,
  					    char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  
  	return sprintf(buf, "%u
  ", pdev->sriov->drivers_autoprobe);
  }
  
  static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
  					     struct device_attribute *attr,
  					     const char *buf, size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  	bool drivers_autoprobe;
  
  	if (kstrtobool(buf, &drivers_autoprobe) < 0)
  		return -EINVAL;
  
  	pdev->sriov->drivers_autoprobe = drivers_autoprobe;
  
  	return count;
  }
1789382a7   Donald Dutile   PCI: SRIOV contro...
676
677
678
679
  static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
  static struct device_attribute sriov_numvfs_attr =
  		__ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
  		       sriov_numvfs_show, sriov_numvfs_store);
0e7df2240   Bodong Wang   PCI: Add sysfs sr...
680
681
682
  static struct device_attribute sriov_drivers_autoprobe_attr =
  		__ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP),
  		       sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store);
1789382a7   Donald Dutile   PCI: SRIOV contro...
683
  #endif /* CONFIG_PCI_IOV */
782a985d7   Alex Williamson   PCI: Introduce ne...
684
685
686
687
688
  static ssize_t driver_override_store(struct device *dev,
  				     struct device_attribute *attr,
  				     const char *buf, size_t count)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
9561475db   Nicolai Stange   PCI: Fix race con...
689
  	char *driver_override, *old, *cp;
782a985d7   Alex Williamson   PCI: Introduce ne...
690

4efe874aa   Sasha Levin   PCI: Don't read p...
691
692
  	/* We need to keep extra room for a newline */
  	if (count >= (PAGE_SIZE - 1))
782a985d7   Alex Williamson   PCI: Introduce ne...
693
694
695
696
697
698
699
700
701
702
  		return -EINVAL;
  
  	driver_override = kstrndup(buf, count, GFP_KERNEL);
  	if (!driver_override)
  		return -ENOMEM;
  
  	cp = strchr(driver_override, '
  ');
  	if (cp)
  		*cp = '\0';
9561475db   Nicolai Stange   PCI: Fix race con...
703
704
  	device_lock(dev);
  	old = pdev->driver_override;
782a985d7   Alex Williamson   PCI: Introduce ne...
705
706
707
708
709
710
  	if (strlen(driver_override)) {
  		pdev->driver_override = driver_override;
  	} else {
  		kfree(driver_override);
  		pdev->driver_override = NULL;
  	}
9561475db   Nicolai Stange   PCI: Fix race con...
711
  	device_unlock(dev);
782a985d7   Alex Williamson   PCI: Introduce ne...
712
713
714
715
716
717
718
719
720
721
  
  	kfree(old);
  
  	return count;
  }
  
  static ssize_t driver_override_show(struct device *dev,
  				    struct device_attribute *attr, char *buf)
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
9561475db   Nicolai Stange   PCI: Fix race con...
722
  	ssize_t len;
782a985d7   Alex Williamson   PCI: Introduce ne...
723

9561475db   Nicolai Stange   PCI: Fix race con...
724
725
726
727
728
  	device_lock(dev);
  	len = snprintf(buf, PAGE_SIZE, "%s
  ", pdev->driver_override);
  	device_unlock(dev);
  	return len;
782a985d7   Alex Williamson   PCI: Introduce ne...
729
730
  }
  static DEVICE_ATTR_RW(driver_override);
bf22c90fb   Sachin Kamat   PCI: Make pci_bus...
731
  static struct attribute *pci_dev_attrs[] = {
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
732
733
734
735
736
  	&dev_attr_resource.attr,
  	&dev_attr_vendor.attr,
  	&dev_attr_device.attr,
  	&dev_attr_subsystem_vendor.attr,
  	&dev_attr_subsystem_device.attr,
702ed3be1   Emil Velikov   PCI: Create revis...
737
  	&dev_attr_revision.attr,
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
738
739
740
741
742
  	&dev_attr_class.attr,
  	&dev_attr_irq.attr,
  	&dev_attr_local_cpus.attr,
  	&dev_attr_local_cpulist.attr,
  	&dev_attr_modalias.attr,
81bb0e198   Brice Goglin   PCI: Make PCI dev...
743
  #ifdef CONFIG_NUMA
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
744
  	&dev_attr_numa_node.attr,
81bb0e198   Brice Goglin   PCI: Make PCI dev...
745
  #endif
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
746
747
  	&dev_attr_dma_mask_bits.attr,
  	&dev_attr_consistent_dma_mask_bits.attr,
d8e7d53a2   Greg Kroah-Hartman   PCI: Rename sysfs...
748
  	&dev_attr_enable.attr,
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
749
750
  	&dev_attr_broken_parity_status.attr,
  	&dev_attr_msi_bus.attr,
fbb988be7   Rafael J. Wysocki   PCI / PM: Drop CO...
751
  #if defined(CONFIG_PM) && defined(CONFIG_ACPI)
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
752
  	&dev_attr_d3cold_allowed.attr,
448bd857d   Huang Ying   PCI/PM: add PCIe ...
753
  #endif
dfc73e7ac   Sebastian Ott   PCI: Move Open Fi...
754
755
756
  #ifdef CONFIG_OF
  	&dev_attr_devspec.attr,
  #endif
782a985d7   Alex Williamson   PCI: Introduce ne...
757
  	&dev_attr_driver_override.attr,
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
758
759
  	NULL,
  };
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
760
761
762
763
  static struct attribute *pci_bridge_attrs[] = {
  	&dev_attr_subordinate_bus_number.attr,
  	&dev_attr_secondary_bus_number.attr,
  	NULL,
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
764
  };
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
765
766
767
768
769
  static struct attribute *pcie_dev_attrs[] = {
  	&dev_attr_current_link_speed.attr,
  	&dev_attr_current_link_width.attr,
  	&dev_attr_max_link_width.attr,
  	&dev_attr_max_link_speed.attr,
5136b2da7   Greg Kroah-Hartman   PCI: convert bus ...
770
  	NULL,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
771
  };
56039e658   Greg Kroah-Hartman   PCI: Convert clas...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
  static struct attribute *pcibus_attrs[] = {
  	&dev_attr_rescan.attr,
  	&dev_attr_cpuaffinity.attr,
  	&dev_attr_cpulistaffinity.attr,
  	NULL,
  };
  
  static const struct attribute_group pcibus_group = {
  	.attrs = pcibus_attrs,
  };
  
  const struct attribute_group *pcibus_groups[] = {
  	&pcibus_group,
  	NULL,
b9d320fcb   Yinghai Lu   PCI: add rescan t...
786
  };
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
787
788
  static ssize_t boot_vga_show(struct device *dev, struct device_attribute *attr,
  			     char *buf)
217f45de3   Dave Airlie   PCI: expose boot ...
789
790
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
1a39b310e   Matthew Garrett   vgaarb: Add suppo...
791
792
793
794
795
  	struct pci_dev *vga_dev = vga_default_device();
  
  	if (vga_dev)
  		return sprintf(buf, "%u
  ", (pdev == vga_dev));
217f45de3   Dave Airlie   PCI: expose boot ...
796
797
798
799
800
801
  
  	return sprintf(buf, "%u
  ",
  		!!(pdev->resource[PCI_ROM_RESOURCE].flags &
  		   IORESOURCE_ROM_SHADOW));
  }
bf22c90fb   Sachin Kamat   PCI: Make pci_bus...
802
  static struct device_attribute vga_attr = __ATTR_RO(boot_vga);
217f45de3   Dave Airlie   PCI: expose boot ...
803

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
804
805
806
  static ssize_t pci_read_config(struct file *filp, struct kobject *kobj,
  			       struct bin_attribute *bin_attr, char *buf,
  			       loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
808
  	struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809
810
  	unsigned int size = 64;
  	loff_t init_off = off;
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
811
  	u8 *data = (u8 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
812
813
  
  	/* Several chips lock up trying to read undefined config space */
ab0fa82b2   Linus Torvalds   pci-sysfs: use pr...
814
  	if (file_ns_capable(filp, &init_user_ns, CAP_SYS_ADMIN))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  		size = dev->cfg_size;
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
816
  	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
  		size = 128;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
820
821
822
823
824
825
826
  
  	if (off > size)
  		return 0;
  	if (off + count > size) {
  		size -= off;
  		count = size;
  	} else {
  		size = count;
  	}
3d8387efe   Huang Ying   PCI/PM: Fix confi...
827
  	pci_config_pm_runtime_get(dev);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
828
829
  	if ((off & 1) && size) {
  		u8 val;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
830
  		pci_user_read_config_byte(dev, off, &val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
831
  		data[off - init_off] = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  		off++;
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
833
834
835
836
837
  		size--;
  	}
  
  	if ((off & 3) && size > 2) {
  		u16 val;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
838
  		pci_user_read_config_word(dev, off, &val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
839
840
841
842
  		data[off - init_off] = val & 0xff;
  		data[off - init_off + 1] = (val >> 8) & 0xff;
  		off += 2;
  		size -= 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
843
844
845
  	}
  
  	while (size > 3) {
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
846
  		u32 val;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
847
  		pci_user_read_config_dword(dev, off, &val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
848
849
850
851
  		data[off - init_off] = val & 0xff;
  		data[off - init_off + 1] = (val >> 8) & 0xff;
  		data[off - init_off + 2] = (val >> 16) & 0xff;
  		data[off - init_off + 3] = (val >> 24) & 0xff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
853
854
  		off += 4;
  		size -= 4;
  	}
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
855
856
  	if (size >= 2) {
  		u16 val;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
857
  		pci_user_read_config_word(dev, off, &val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
858
859
860
861
862
863
864
865
  		data[off - init_off] = val & 0xff;
  		data[off - init_off + 1] = (val >> 8) & 0xff;
  		off += 2;
  		size -= 2;
  	}
  
  	if (size > 0) {
  		u8 val;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
866
  		pci_user_read_config_byte(dev, off, &val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
867
  		data[off - init_off] = val;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
868
869
870
  		off++;
  		--size;
  	}
3d8387efe   Huang Ying   PCI/PM: Fix confi...
871
  	pci_config_pm_runtime_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
872
873
  	return count;
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
874
875
876
  static ssize_t pci_write_config(struct file *filp, struct kobject *kobj,
  				struct bin_attribute *bin_attr, char *buf,
  				loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
878
  	struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
880
  	unsigned int size = count;
  	loff_t init_off = off;
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
881
  	u8 *data = (u8 *) buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
882
883
884
885
886
887
888
  
  	if (off > dev->cfg_size)
  		return 0;
  	if (off + count > dev->cfg_size) {
  		size = dev->cfg_size - off;
  		count = size;
  	}
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
889

3d8387efe   Huang Ying   PCI/PM: Fix confi...
890
  	pci_config_pm_runtime_get(dev);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
891
  	if ((off & 1) && size) {
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
892
  		pci_user_write_config_byte(dev, off, data[off - init_off]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
  		off++;
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
894
  		size--;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
  	}
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
896

4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
897
898
899
  	if ((off & 3) && size > 2) {
  		u16 val = data[off - init_off];
  		val |= (u16) data[off - init_off + 1] << 8;
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
900
901
902
903
  		pci_user_write_config_word(dev, off, val);
  		off += 2;
  		size -= 2;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
  
  	while (size > 3) {
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
906
907
908
909
  		u32 val = data[off - init_off];
  		val |= (u32) data[off - init_off + 1] << 8;
  		val |= (u32) data[off - init_off + 2] << 16;
  		val |= (u32) data[off - init_off + 3] << 24;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
910
  		pci_user_write_config_dword(dev, off, val);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
913
  		off += 4;
  		size -= 4;
  	}
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
914

4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
915
916
917
  	if (size >= 2) {
  		u16 val = data[off - init_off];
  		val |= (u16) data[off - init_off + 1] << 8;
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
918
  		pci_user_write_config_word(dev, off, val);
4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
919
920
921
  		off += 2;
  		size -= 2;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
922

4c0619add   Sachin P Sant   [PATCH] PCI: fix ...
923
  	if (size) {
e04b0ea2e   Brian King   [PATCH] PCI: Bloc...
924
  		pci_user_write_config_byte(dev, off, data[off - init_off]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
927
  		off++;
  		--size;
  	}
3d8387efe   Huang Ying   PCI/PM: Fix confi...
928
  	pci_config_pm_runtime_put(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929
930
  	return count;
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
931
932
933
  static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj,
  			     struct bin_attribute *bin_attr, char *buf,
  			     loff_t off, size_t count)
94e610880   Ben Hutchings   PCI: Expose PCI V...
934
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
935
  	struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
94e610880   Ben Hutchings   PCI: Expose PCI V...
936

f52e5629f   Hannes Reinecke   PCI: Allow access...
937
938
939
940
941
942
  	if (bin_attr->size > 0) {
  		if (off > bin_attr->size)
  			count = 0;
  		else if (count > bin_attr->size - off)
  			count = bin_attr->size - off;
  	}
94e610880   Ben Hutchings   PCI: Expose PCI V...
943

287d19ce2   Stephen Hemminger   PCI: revise VPD a...
944
  	return pci_read_vpd(dev, off, count, buf);
94e610880   Ben Hutchings   PCI: Expose PCI V...
945
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
946
947
948
  static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj,
  			      struct bin_attribute *bin_attr, char *buf,
  			      loff_t off, size_t count)
94e610880   Ben Hutchings   PCI: Expose PCI V...
949
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
950
  	struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
94e610880   Ben Hutchings   PCI: Expose PCI V...
951

f52e5629f   Hannes Reinecke   PCI: Allow access...
952
953
954
955
956
957
  	if (bin_attr->size > 0) {
  		if (off > bin_attr->size)
  			count = 0;
  		else if (count > bin_attr->size - off)
  			count = bin_attr->size - off;
  	}
94e610880   Ben Hutchings   PCI: Expose PCI V...
958

287d19ce2   Stephen Hemminger   PCI: revise VPD a...
959
  	return pci_write_vpd(dev, off, count, buf);
94e610880   Ben Hutchings   PCI: Expose PCI V...
960
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
961
962
963
  #ifdef HAVE_PCI_LEGACY
  /**
   * pci_read_legacy_io - read byte(s) from legacy I/O port space
2c3c8bea6   Chris Wright   sysfs: add struct...
964
   * @filp: open sysfs file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
   * @kobj: kobject corresponding to file to read from
cffb2fafb   Randy Dunlap   docbooks: add/fix...
966
   * @bin_attr: struct bin_attribute for this file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
970
971
972
973
   * @buf: buffer to store results
   * @off: offset into legacy I/O port space
   * @count: number of bytes to read
   *
   * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
   * callback routine (pci_legacy_read).
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
974
975
976
  static ssize_t pci_read_legacy_io(struct file *filp, struct kobject *kobj,
  				  struct bin_attribute *bin_attr, char *buf,
  				  loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
977
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
978
  	struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
980
981
982
  	/* Only support 1, 2 or 4 byte accesses */
  	if (count != 1 && count != 2 && count != 4)
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
984
  	return pci_legacy_read(bus, off, (u32 *)buf, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
  }
  
  /**
   * pci_write_legacy_io - write byte(s) to legacy I/O port space
2c3c8bea6   Chris Wright   sysfs: add struct...
989
   * @filp: open sysfs file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
   * @kobj: kobject corresponding to file to read from
cffb2fafb   Randy Dunlap   docbooks: add/fix...
991
   * @bin_attr: struct bin_attribute for this file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
993
994
995
996
997
998
   * @buf: buffer containing value to be written
   * @off: offset into legacy I/O port space
   * @count: number of bytes to write
   *
   * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
   * callback routine (pci_legacy_write).
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
999
1000
1001
  static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj,
  				   struct bin_attribute *bin_attr, char *buf,
  				   loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1003
  	struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1005
1006
1007
1008
1009
  	/* Only support 1, 2 or 4 byte accesses */
  	if (count != 1 && count != 2 && count != 4)
  		return -EINVAL;
  
  	return pci_legacy_write(bus, off, *(u32 *)buf, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
1012
1013
  }
  
  /**
   * pci_mmap_legacy_mem - map legacy PCI memory into user memory space
2c3c8bea6   Chris Wright   sysfs: add struct...
1014
   * @filp: open sysfs file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
   * @kobj: kobject corresponding to device to be mapped
   * @attr: struct bin_attribute for this file
   * @vma: struct vm_area_struct passed to mmap
   *
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1019
   * Uses an arch specific callback, pci_mmap_legacy_mem_page_range, to mmap
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1020
1021
1022
   * legacy memory space (first meg of bus space) into application virtual
   * memory space.
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1023
1024
1025
  static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
  			       struct bin_attribute *attr,
  			       struct vm_area_struct *vma)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1026
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1027
  	struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1029
  	return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1030
1031
1032
1033
  }
  
  /**
   * pci_mmap_legacy_io - map legacy PCI IO into user memory space
2c3c8bea6   Chris Wright   sysfs: add struct...
1034
   * @filp: open sysfs file
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1035
1036
1037
1038
1039
1040
1041
1042
   * @kobj: kobject corresponding to device to be mapped
   * @attr: struct bin_attribute for this file
   * @vma: struct vm_area_struct passed to mmap
   *
   * Uses an arch specific callback, pci_mmap_legacy_io_page_range, to mmap
   * legacy IO space (first meg of bus space) into application virtual
   * memory space. Returns -ENOSYS if the operation isn't supported
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1043
1044
1045
  static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,
  			      struct bin_attribute *attr,
  			      struct vm_area_struct *vma)
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1046
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1047
  	struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1048

3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1049
  	return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1050
1051
1052
  }
  
  /**
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1053
1054
1055
1056
1057
1058
   * pci_adjust_legacy_attr - adjustment of legacy file attributes
   * @b: bus to create files under
   * @mmap_type: I/O port or memory
   *
   * Stub implementation. Can be overridden by arch if necessary.
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1059
1060
  void __weak pci_adjust_legacy_attr(struct pci_bus *b,
  				   enum pci_mmap_state mmap_type)
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1061
  {
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1062
1063
1064
  }
  
  /**
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1065
1066
1067
1068
1069
1070
1071
   * pci_create_legacy_files - create legacy I/O port and memory files
   * @b: bus to create files under
   *
   * Some platforms allow access to legacy I/O port and ISA memory space on
   * a per-bus basis.  This routine creates the files and ties them into
   * their associated read, write and mmap files from pci-sysfs.c
   *
25985edce   Lucas De Marchi   Fix common misspe...
1072
   * On error unwind, but don't propagate the error to the caller
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
   * as it is ok to set up the PCI bus without these files.
   */
  void pci_create_legacy_files(struct pci_bus *b)
  {
  	int error;
  
  	b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
  			       GFP_ATOMIC);
  	if (!b->legacy_io)
  		goto kzalloc_err;
62e877b89   Stephen Rothwell   sysfs: fix for th...
1083
  	sysfs_bin_attr_init(b->legacy_io);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1084
1085
1086
1087
1088
1089
  	b->legacy_io->attr.name = "legacy_io";
  	b->legacy_io->size = 0xffff;
  	b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
  	b->legacy_io->read = pci_read_legacy_io;
  	b->legacy_io->write = pci_write_legacy_io;
  	b->legacy_io->mmap = pci_mmap_legacy_io;
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1090
  	pci_adjust_legacy_attr(b, pci_mmap_io);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1091
1092
1093
1094
1095
1096
  	error = device_create_bin_file(&b->dev, b->legacy_io);
  	if (error)
  		goto legacy_io_err;
  
  	/* Allocated above after the legacy_io struct */
  	b->legacy_mem = b->legacy_io + 1;
6757eca34   Mel Gorman   sysfs: Initialise...
1097
  	sysfs_bin_attr_init(b->legacy_mem);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1098
1099
1100
1101
  	b->legacy_mem->attr.name = "legacy_mem";
  	b->legacy_mem->size = 1024*1024;
  	b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
  	b->legacy_mem->mmap = pci_mmap_legacy_mem;
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1102
  	pci_adjust_legacy_attr(b, pci_mmap_mem);
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
  	error = device_create_bin_file(&b->dev, b->legacy_mem);
  	if (error)
  		goto legacy_mem_err;
  
  	return;
  
  legacy_mem_err:
  	device_remove_bin_file(&b->dev, b->legacy_io);
  legacy_io_err:
  	kfree(b->legacy_io);
  	b->legacy_io = NULL;
  kzalloc_err:
227f06470   Ryan Desfosses   PCI: Merge multi-...
1115
1116
  	printk(KERN_WARNING "pci: warning: could not create legacy I/O port and ISA memory resources to sysfs
  ");
f19aeb1f3   Benjamin Herrenschmidt   PCI: Add ability ...
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  	return;
  }
  
  void pci_remove_legacy_files(struct pci_bus *b)
  {
  	if (b->legacy_io) {
  		device_remove_bin_file(&b->dev, b->legacy_io);
  		device_remove_bin_file(&b->dev, b->legacy_mem);
  		kfree(b->legacy_io); /* both are allocated here */
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1127
1128
  }
  #endif /* HAVE_PCI_LEGACY */
f71958243   David Woodhouse   PCI: Add pci_mmap...
1129
  #if defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)
b5ff7df3d   Linus Torvalds   Check mapped rang...
1130

3b519e4ea   Martin Wilck   PCI: fix size che...
1131
1132
  int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
  		  enum pci_mmap_api mmap_api)
b5ff7df3d   Linus Torvalds   Check mapped rang...
1133
  {
6bccc7f42   David Woodhouse   PCI: Fix pci_mmap...
1134
1135
  	unsigned long nr, start, size;
  	resource_size_t pci_start = 0, pci_end;
b5ff7df3d   Linus Torvalds   Check mapped rang...
1136

3b519e4ea   Martin Wilck   PCI: fix size che...
1137
1138
  	if (pci_resource_len(pdev, resno) == 0)
  		return 0;
64b001758   Libin   PCI: Use vma_page...
1139
  	nr = vma_pages(vma);
b5ff7df3d   Linus Torvalds   Check mapped rang...
1140
  	start = vma->vm_pgoff;
88e7df0b7   Ed Swierk   PCI: fix range ch...
1141
  	size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
6bccc7f42   David Woodhouse   PCI: Fix pci_mmap...
1142
1143
1144
1145
1146
  	if (mmap_api == PCI_MMAP_PROCFS) {
  		pci_resource_to_user(pdev, resno, &pdev->resource[resno],
  				     &pci_start, &pci_end);
  		pci_start >>= PAGE_SHIFT;
  	}
3b519e4ea   Martin Wilck   PCI: fix size che...
1147
1148
  	if (start >= pci_start && start < pci_start + size &&
  			start + nr <= pci_start + size)
b5ff7df3d   Linus Torvalds   Check mapped rang...
1149
  		return 1;
b5ff7df3d   Linus Torvalds   Check mapped rang...
1150
1151
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1152
1153
1154
1155
1156
  /**
   * pci_mmap_resource - map a PCI resource into user memory space
   * @kobj: kobject for mapping
   * @attr: struct bin_attribute for the file being mapped
   * @vma: struct vm_area_struct passed into the mmap
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1157
   * @write_combine: 1 for write_combine mapping
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
1159
   *
   * Use the regular PCI mapping routines to map a PCI resource into userspace.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1160
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1161
1162
  static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
  			     struct vm_area_struct *vma, int write_combine)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1164
  	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
dca40b186   David Woodhouse   PCI: Use BAR inde...
1165
  	int bar = (unsigned long)attr->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1166
  	enum pci_mmap_state mmap_type;
dca40b186   David Woodhouse   PCI: Use BAR inde...
1167
  	struct resource *res = &pdev->resource[bar];
2311b1f2b   Michael Ellerman   [PATCH] PCI: fix-...
1168

ca620723d   Bjorn Helgaas   PCI: Supply CPU p...
1169
1170
  	if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
  		return -EINVAL;
dca40b186   David Woodhouse   PCI: Use BAR inde...
1171
  	if (!pci_mmap_fits(pdev, bar, vma, PCI_MMAP_SYSFS)) {
227f06470   Ryan Desfosses   PCI: Merge multi-...
1172
1173
  		WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)
  ",
3b519e4ea   Martin Wilck   PCI: fix size che...
1174
  			current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
dca40b186   David Woodhouse   PCI: Use BAR inde...
1175
1176
1177
  			pci_name(pdev), bar,
  			(u64)pci_resource_start(pdev, bar),
  			(u64)pci_resource_len(pdev, bar));
b5ff7df3d   Linus Torvalds   Check mapped rang...
1178
  		return -EINVAL;
3b519e4ea   Martin Wilck   PCI: fix size che...
1179
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
  	mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
f71958243   David Woodhouse   PCI: Add pci_mmap...
1181
1182
  
  	return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1183
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1184
1185
1186
  static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
  				struct bin_attribute *attr,
  				struct vm_area_struct *vma)
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1187
1188
1189
  {
  	return pci_mmap_resource(kobj, attr, vma, 0);
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1190
1191
1192
  static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
  				struct bin_attribute *attr,
  				struct vm_area_struct *vma)
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1193
1194
  {
  	return pci_mmap_resource(kobj, attr, vma, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1196
1197
1198
  static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
  			       struct bin_attribute *attr, char *buf,
  			       loff_t off, size_t count, bool write)
8633328be   Alex Williamson   PCI: Allow read/w...
1199
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1200
  	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
dca40b186   David Woodhouse   PCI: Use BAR inde...
1201
  	int bar = (unsigned long)attr->private;
8633328be   Alex Williamson   PCI: Allow read/w...
1202
  	unsigned long port = off;
8633328be   Alex Williamson   PCI: Allow read/w...
1203

dca40b186   David Woodhouse   PCI: Use BAR inde...
1204
  	port += pci_resource_start(pdev, bar);
8633328be   Alex Williamson   PCI: Allow read/w...
1205

dca40b186   David Woodhouse   PCI: Use BAR inde...
1206
  	if (port > pci_resource_end(pdev, bar))
8633328be   Alex Williamson   PCI: Allow read/w...
1207
  		return 0;
dca40b186   David Woodhouse   PCI: Use BAR inde...
1208
  	if (port + count - 1 > pci_resource_end(pdev, bar))
8633328be   Alex Williamson   PCI: Allow read/w...
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
  		return -EINVAL;
  
  	switch (count) {
  	case 1:
  		if (write)
  			outb(*(u8 *)buf, port);
  		else
  			*(u8 *)buf = inb(port);
  		return 1;
  	case 2:
  		if (write)
  			outw(*(u16 *)buf, port);
  		else
  			*(u16 *)buf = inw(port);
  		return 2;
  	case 4:
  		if (write)
  			outl(*(u32 *)buf, port);
  		else
  			*(u32 *)buf = inl(port);
  		return 4;
  	}
  	return -EINVAL;
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1233
1234
1235
  static ssize_t pci_read_resource_io(struct file *filp, struct kobject *kobj,
  				    struct bin_attribute *attr, char *buf,
  				    loff_t off, size_t count)
8633328be   Alex Williamson   PCI: Allow read/w...
1236
1237
1238
  {
  	return pci_resource_io(filp, kobj, attr, buf, off, count, false);
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1239
1240
1241
  static ssize_t pci_write_resource_io(struct file *filp, struct kobject *kobj,
  				     struct bin_attribute *attr, char *buf,
  				     loff_t off, size_t count)
8633328be   Alex Williamson   PCI: Allow read/w...
1242
1243
1244
  {
  	return pci_resource_io(filp, kobj, attr, buf, off, count, true);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1245
  /**
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1246
   * pci_remove_resource_files - cleanup resource files
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1247
   * @pdev: dev to cleanup
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1248
   *
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1249
   * If we created resource files for @pdev, remove them from sysfs and
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1250
1251
   * free their resources.
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1252
  static void pci_remove_resource_files(struct pci_dev *pdev)
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
  {
  	int i;
  
  	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
  		struct bin_attribute *res_attr;
  
  		res_attr = pdev->res_attr[i];
  		if (res_attr) {
  			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
  			kfree(res_attr);
  		}
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1264
1265
1266
1267
1268
1269
  
  		res_attr = pdev->res_attr_wc[i];
  		if (res_attr) {
  			sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
  			kfree(res_attr);
  		}
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1270
1271
  	}
  }
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1272
1273
1274
1275
1276
  static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
  {
  	/* allocate attribute structure, piggyback attribute name */
  	int name_len = write_combine ? 13 : 10;
  	struct bin_attribute *res_attr;
bd5174dfb   Bjorn Helgaas   PCI: Simplify pci...
1277
  	char *res_attr_name;
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1278
1279
1280
  	int retval;
  
  	res_attr = kzalloc(sizeof(*res_attr) + name_len, GFP_ATOMIC);
bd5174dfb   Bjorn Helgaas   PCI: Simplify pci...
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
  	if (!res_attr)
  		return -ENOMEM;
  
  	res_attr_name = (char *)(res_attr + 1);
  
  	sysfs_bin_attr_init(res_attr);
  	if (write_combine) {
  		pdev->res_attr_wc[num] = res_attr;
  		sprintf(res_attr_name, "resource%d_wc", num);
  		res_attr->mmap = pci_mmap_resource_wc;
  	} else {
  		pdev->res_attr[num] = res_attr;
  		sprintf(res_attr_name, "resource%d", num);
e854d8b2a   David Woodhouse   PCI: Add arch_can...
1294
1295
1296
1297
1298
1299
1300
1301
  		if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
  			res_attr->read = pci_read_resource_io;
  			res_attr->write = pci_write_resource_io;
  			if (arch_can_pci_mmap_io())
  				res_attr->mmap = pci_mmap_resource_uc;
  		} else {
  			res_attr->mmap = pci_mmap_resource_uc;
  		}
bd5174dfb   Bjorn Helgaas   PCI: Simplify pci...
1302
1303
1304
1305
  	}
  	res_attr->attr.name = res_attr_name;
  	res_attr->attr.mode = S_IRUSR | S_IWUSR;
  	res_attr->size = pci_resource_len(pdev, num);
dca40b186   David Woodhouse   PCI: Use BAR inde...
1306
  	res_attr->private = (void *)(unsigned long)num;
bd5174dfb   Bjorn Helgaas   PCI: Simplify pci...
1307
1308
1309
  	retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
  	if (retval)
  		kfree(res_attr);
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1310
1311
1312
  
  	return retval;
  }
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1313
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1314
   * pci_create_resource_files - create resource files in sysfs for @dev
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1315
   * @pdev: dev in question
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
   *
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1317
   * Walk the resources in @pdev creating files for each resource available.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1318
   */
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1319
  static int pci_create_resource_files(struct pci_dev *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
  {
  	int i;
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1322
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323
1324
1325
  
  	/* Expose the PCI resources from this device as files */
  	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1326
1327
1328
1329
  
  		/* skip empty resources */
  		if (!pci_resource_len(pdev, i))
  			continue;
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1330
1331
  		retval = pci_create_attr(pdev, i, 0);
  		/* for prefetchable resources, create a WC mappable file */
ae749c7ab   David Woodhouse   PCI: Add arch_can...
1332
1333
  		if (!retval && arch_can_pci_mmap_wc() &&
  		    pdev->resource[i].flags & IORESOURCE_PREFETCH)
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1334
  			retval = pci_create_attr(pdev, i, 1);
45aec1ae7   venkatesh.pallipadi@intel.com   x86: PAT export r...
1335
1336
1337
  		if (retval) {
  			pci_remove_resource_files(pdev);
  			return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1338
1339
  		}
  	}
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1340
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
1342
  }
  #else /* !HAVE_PCI_MMAP */
10a0ef39f   Ivan Kokshaysky   PCI/alpha: pci sy...
1343
1344
  int __weak pci_create_resource_files(struct pci_dev *dev) { return 0; }
  void __weak pci_remove_resource_files(struct pci_dev *dev) { return; }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1345
1346
1347
1348
  #endif /* HAVE_PCI_MMAP */
  
  /**
   * pci_write_rom - used to enable access to the PCI ROM display
2c3c8bea6   Chris Wright   sysfs: add struct...
1349
   * @filp: sysfs file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350
   * @kobj: kernel object handle
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1351
   * @bin_attr: struct bin_attribute for this file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1352
1353
1354
1355
1356
1357
   * @buf: user input
   * @off: file offset
   * @count: number of byte in input
   *
   * writing anything except 0 enables it
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1358
1359
1360
  static ssize_t pci_write_rom(struct file *filp, struct kobject *kobj,
  			     struct bin_attribute *bin_attr, char *buf,
  			     loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1361
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1362
  	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
  
  	if ((off ==  0) && (*buf == '0') && (count == 2))
  		pdev->rom_attr_enabled = 0;
  	else
  		pdev->rom_attr_enabled = 1;
  
  	return count;
  }
  
  /**
   * pci_read_rom - read a PCI ROM
2c3c8bea6   Chris Wright   sysfs: add struct...
1374
   * @filp: sysfs file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
   * @kobj: kernel object handle
cffb2fafb   Randy Dunlap   docbooks: add/fix...
1376
   * @bin_attr: struct bin_attribute for this file
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
1379
1380
1381
1382
1383
   * @buf: where to put the data we read from the ROM
   * @off: file offset
   * @count: number of bytes to read
   *
   * Put @count bytes starting at @off into @buf from the ROM in the PCI
   * device corresponding to @kobj.
   */
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1384
1385
1386
  static ssize_t pci_read_rom(struct file *filp, struct kobject *kobj,
  			    struct bin_attribute *bin_attr, char *buf,
  			    loff_t off, size_t count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1388
  	struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
1391
1392
1393
  	void __iomem *rom;
  	size_t size;
  
  	if (!pdev->rom_attr_enabled)
  		return -EINVAL;
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
1394

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1395
  	rom = pci_map_rom(pdev, &size);	/* size starts out as PCI window size */
97c44836c   Timothy S. Nelson   PCI: return error...
1396
1397
  	if (!rom || !size)
  		return -EIO;
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
1398

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1399
1400
1401
1402
1403
  	if (off >= size)
  		count = 0;
  	else {
  		if (off + count > size)
  			count = size - off;
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
1404

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1405
1406
1407
  		memcpy_fromio(buf, rom + off, count);
  	}
  	pci_unmap_rom(pdev, rom);
f7625980f   Bjorn Helgaas   PCI: Fix whitespa...
1408

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1409
1410
  	return count;
  }
8bdc50ac5   Bhumika Goyal   PCI: Constify bin...
1411
  static const struct bin_attribute pci_config_attr = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
1413
1414
  	.attr =	{
  		.name = "config",
  		.mode = S_IRUGO | S_IWUSR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
  	},
557848c3c   Zhao, Yu   PCI: replace cfg ...
1416
  	.size = PCI_CFG_SPACE_SIZE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417
1418
1419
  	.read = pci_read_config,
  	.write = pci_write_config,
  };
8bdc50ac5   Bhumika Goyal   PCI: Constify bin...
1420
  static const struct bin_attribute pcie_config_attr = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1421
1422
1423
  	.attr =	{
  		.name = "config",
  		.mode = S_IRUGO | S_IWUSR,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
  	},
557848c3c   Zhao, Yu   PCI: replace cfg ...
1425
  	.size = PCI_CFG_SPACE_EXP_SIZE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1426
1427
1428
  	.read = pci_read_config,
  	.write = pci_write_config,
  };
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1429
1430
  static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
  			   const char *buf, size_t count)
711d57796   Michael S. Tsirkin   PCI: expose funct...
1431
1432
1433
  {
  	struct pci_dev *pdev = to_pci_dev(dev);
  	unsigned long val;
9a994e8ec   Jingoo Han   PCI: Replace stri...
1434
  	ssize_t result = kstrtoul(buf, 0, &val);
711d57796   Michael S. Tsirkin   PCI: expose funct...
1435
1436
1437
1438
1439
1440
  
  	if (result < 0)
  		return result;
  
  	if (val != 1)
  		return -EINVAL;
447c5dd73   Michal Schmidt   PCI: return corre...
1441
1442
1443
1444
1445
1446
  
  	result = pci_reset_function(pdev);
  	if (result < 0)
  		return result;
  
  	return count;
711d57796   Michael S. Tsirkin   PCI: expose funct...
1447
1448
1449
  }
  
  static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store);
280c73d36   Zhao, Yu   PCI: centralize t...
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
  static int pci_create_capabilities_sysfs(struct pci_dev *dev)
  {
  	int retval;
  	struct bin_attribute *attr;
  
  	/* If the device has VPD, try to expose it in sysfs. */
  	if (dev->vpd) {
  		attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
  		if (!attr)
  			return -ENOMEM;
a07e4156a   Eric W. Biederman   sysfs: Use sysfs_...
1460
  		sysfs_bin_attr_init(attr);
104daa71b   Hannes Reinecke   PCI: Determine ac...
1461
  		attr->size = 0;
280c73d36   Zhao, Yu   PCI: centralize t...
1462
1463
  		attr->attr.name = "vpd";
  		attr->attr.mode = S_IRUSR | S_IWUSR;
287d19ce2   Stephen Hemminger   PCI: revise VPD a...
1464
1465
  		attr->read = read_vpd_attr;
  		attr->write = write_vpd_attr;
280c73d36   Zhao, Yu   PCI: centralize t...
1466
1467
  		retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
  		if (retval) {
0f12a4e29   Ben Hutchings   PCI: sysfs: Fix f...
1468
  			kfree(attr);
280c73d36   Zhao, Yu   PCI: centralize t...
1469
1470
1471
1472
1473
1474
1475
  			return retval;
  		}
  		dev->vpd->attr = attr;
  	}
  
  	/* Active State Power Management */
  	pcie_aspm_create_sysfs_dev_files(dev);
711d57796   Michael S. Tsirkin   PCI: expose funct...
1476
1477
1478
1479
1480
1481
  	if (!pci_probe_reset_function(dev)) {
  		retval = device_create_file(&dev->dev, &reset_attr);
  		if (retval)
  			goto error;
  		dev->reset_fn = 1;
  	}
280c73d36   Zhao, Yu   PCI: centralize t...
1482
  	return 0;
711d57796   Michael S. Tsirkin   PCI: expose funct...
1483
1484
1485
1486
1487
1488
1489
1490
1491
  
  error:
  	pcie_aspm_remove_sysfs_dev_files(dev);
  	if (dev->vpd && dev->vpd->attr) {
  		sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
  		kfree(dev->vpd->attr);
  	}
  
  	return retval;
280c73d36   Zhao, Yu   PCI: centralize t...
1492
  }
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1493
  int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
  {
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1495
  	int retval;
ac0c302a9   Bjorn Helgaas   PCI: Remove arch-...
1496
  	int rom_size;
280c73d36   Zhao, Yu   PCI: centralize t...
1497
  	struct bin_attribute *attr;
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1498

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1499
1500
  	if (!sysfs_initialized)
  		return -EACCES;
c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1501
  	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1502
  		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1503
1504
  	else
  		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1505
1506
  	if (retval)
  		goto err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1507

b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1508
1509
  	retval = pci_create_resource_files(pdev);
  	if (retval)
280c73d36   Zhao, Yu   PCI: centralize t...
1510
  		goto err_config_file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1511
  	/* If the device has a ROM, try to expose it in sysfs. */
ac0c302a9   Bjorn Helgaas   PCI: Remove arch-...
1512
  	rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
280c73d36   Zhao, Yu   PCI: centralize t...
1513
  	if (rom_size) {
94e610880   Ben Hutchings   PCI: Expose PCI V...
1514
  		attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
280c73d36   Zhao, Yu   PCI: centralize t...
1515
  		if (!attr) {
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1516
  			retval = -ENOMEM;
9890b12a4   Michael Ellerman   PCI: Free resourc...
1517
  			goto err_resource_files;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1518
  		}
a07e4156a   Eric W. Biederman   sysfs: Use sysfs_...
1519
  		sysfs_bin_attr_init(attr);
280c73d36   Zhao, Yu   PCI: centralize t...
1520
1521
  		attr->size = rom_size;
  		attr->attr.name = "rom";
ff29530e6   Alex Williamson   PCI: sysfs: Updat...
1522
  		attr->attr.mode = S_IRUSR | S_IWUSR;
280c73d36   Zhao, Yu   PCI: centralize t...
1523
1524
1525
1526
1527
1528
1529
1530
  		attr->read = pci_read_rom;
  		attr->write = pci_write_rom;
  		retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);
  		if (retval) {
  			kfree(attr);
  			goto err_resource_files;
  		}
  		pdev->rom_attr = attr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1531
  	}
280c73d36   Zhao, Yu   PCI: centralize t...
1532

280c73d36   Zhao, Yu   PCI: centralize t...
1533
1534
1535
  	/* add sysfs entries for various capabilities */
  	retval = pci_create_capabilities_sysfs(pdev);
  	if (retval)
625e1d59a   Yinghai Lu   PCI: Use is_visib...
1536
  		goto err_rom_file;
7d715a6c1   Shaohua Li   PCI: add PCI Expr...
1537

911e1c9b0   Narendra K   PCI: export SMBIO...
1538
  	pci_create_firmware_label_files(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1539
  	return 0;
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1540

a2cd52ca9   Michael Ellerman   PCI: Make pcibios...
1541
  err_rom_file:
9d88b93be   Bjorn Helgaas   PCI: Simplify sys...
1542
  	if (pdev->rom_attr) {
94e610880   Ben Hutchings   PCI: Expose PCI V...
1543
  		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
280c73d36   Zhao, Yu   PCI: centralize t...
1544
1545
1546
  		kfree(pdev->rom_attr);
  		pdev->rom_attr = NULL;
  	}
9890b12a4   Michael Ellerman   PCI: Free resourc...
1547
1548
  err_resource_files:
  	pci_remove_resource_files(pdev);
94e610880   Ben Hutchings   PCI: Expose PCI V...
1549
  err_config_file:
c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1550
  	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1551
  		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1552
1553
  	else
  		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1554
1555
  err:
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
  }
280c73d36   Zhao, Yu   PCI: centralize t...
1557
1558
1559
1560
1561
1562
1563
1564
  static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
  {
  	if (dev->vpd && dev->vpd->attr) {
  		sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
  		kfree(dev->vpd->attr);
  	}
  
  	pcie_aspm_remove_sysfs_dev_files(dev);
711d57796   Michael S. Tsirkin   PCI: expose funct...
1565
1566
1567
1568
  	if (dev->reset_fn) {
  		device_remove_file(&dev->dev, &reset_attr);
  		dev->reset_fn = 0;
  	}
280c73d36   Zhao, Yu   PCI: centralize t...
1569
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1570
1571
1572
1573
1574
1575
1576
1577
  /**
   * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
   * @pdev: device whose entries we should free
   *
   * Cleanup when @pdev is removed from sysfs.
   */
  void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
  {
d67afe5ed   David Miller   [PATCH] pci: don'...
1578
1579
  	if (!sysfs_initialized)
  		return;
280c73d36   Zhao, Yu   PCI: centralize t...
1580
  	pci_remove_capabilities_sysfs(pdev);
7d715a6c1   Shaohua Li   PCI: add PCI Expr...
1581

c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1582
  	if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
  		sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
c20aecf69   Jason S. McMullan   PCI: Support PCIe...
1584
1585
  	else
  		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1586
1587
  
  	pci_remove_resource_files(pdev);
9d88b93be   Bjorn Helgaas   PCI: Simplify sys...
1588
  	if (pdev->rom_attr) {
280c73d36   Zhao, Yu   PCI: centralize t...
1589
1590
  		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
  		kfree(pdev->rom_attr);
9d88b93be   Bjorn Helgaas   PCI: Simplify sys...
1591
  		pdev->rom_attr = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1592
  	}
911e1c9b0   Narendra K   PCI: export SMBIO...
1593
1594
  
  	pci_remove_firmware_label_files(pdev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1595
1596
1597
1598
1599
  }
  
  static int __init pci_sysfs_init(void)
  {
  	struct pci_dev *pdev = NULL;
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1600
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1601
  	sysfs_initialized = 1;
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1602
1603
  	for_each_pci_dev(pdev) {
  		retval = pci_create_sysfs_dev_files(pdev);
151fc5dfc   Julia Lawall   PCI: drivers/pci/...
1604
1605
  		if (retval) {
  			pci_dev_put(pdev);
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1606
  			return retval;
151fc5dfc   Julia Lawall   PCI: drivers/pci/...
1607
  		}
b19441af1   Greg Kroah-Hartman   PCI: fix __must_c...
1608
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
1611
  
  	return 0;
  }
40ee9e9f8   Jesse Barnes   PCI: fix sysfs ro...
1612
  late_initcall(pci_sysfs_init);
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1613
1614
  
  static struct attribute *pci_dev_dev_attrs[] = {
625e1d59a   Yinghai Lu   PCI: Use is_visib...
1615
  	&vga_attr.attr,
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1616
1617
1618
1619
  	NULL,
  };
  
  static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1620
  					 struct attribute *a, int n)
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1621
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1622
  	struct device *dev = kobj_to_dev(kobj);
625e1d59a   Yinghai Lu   PCI: Use is_visib...
1623
1624
1625
1626
1627
  	struct pci_dev *pdev = to_pci_dev(dev);
  
  	if (a == &vga_attr.attr)
  		if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
  			return 0;
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1628
1629
  	return a->mode;
  }
dfab88bed   Jiang Liu   PCI: Hide remove ...
1630
1631
1632
1633
1634
1635
1636
  static struct attribute *pci_dev_hp_attrs[] = {
  	&dev_remove_attr.attr,
  	&dev_rescan_attr.attr,
  	NULL,
  };
  
  static umode_t pci_dev_hp_attrs_are_visible(struct kobject *kobj,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1637
  					    struct attribute *a, int n)
dfab88bed   Jiang Liu   PCI: Hide remove ...
1638
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1639
  	struct device *dev = kobj_to_dev(kobj);
dfab88bed   Jiang Liu   PCI: Hide remove ...
1640
1641
1642
1643
1644
1645
1646
  	struct pci_dev *pdev = to_pci_dev(dev);
  
  	if (pdev->is_virtfn)
  		return 0;
  
  	return a->mode;
  }
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
  static umode_t pci_bridge_attrs_are_visible(struct kobject *kobj,
  					    struct attribute *a, int n)
  {
  	struct device *dev = kobj_to_dev(kobj);
  	struct pci_dev *pdev = to_pci_dev(dev);
  
  	if (pci_is_bridge(pdev))
  		return a->mode;
  
  	return 0;
  }
  
  static umode_t pcie_dev_attrs_are_visible(struct kobject *kobj,
  					  struct attribute *a, int n)
  {
  	struct device *dev = kobj_to_dev(kobj);
  	struct pci_dev *pdev = to_pci_dev(dev);
  
  	if (pci_is_pcie(pdev))
  		return a->mode;
  
  	return 0;
  }
  
  static const struct attribute_group pci_dev_group = {
  	.attrs = pci_dev_attrs,
  };
  
  const struct attribute_group *pci_dev_groups[] = {
  	&pci_dev_group,
  	NULL,
  };
  
  static const struct attribute_group pci_bridge_group = {
  	.attrs = pci_bridge_attrs,
  };
  
  const struct attribute_group *pci_bridge_groups[] = {
  	&pci_bridge_group,
  	NULL,
  };
  
  static const struct attribute_group pcie_dev_group = {
  	.attrs = pcie_dev_attrs,
  };
  
  const struct attribute_group *pcie_dev_groups[] = {
  	&pcie_dev_group,
  	NULL,
  };
e7ea9825f   Arvind Yadav   PCI: Constify sys...
1697
  static const struct attribute_group pci_dev_hp_attr_group = {
dfab88bed   Jiang Liu   PCI: Hide remove ...
1698
1699
1700
  	.attrs = pci_dev_hp_attrs,
  	.is_visible = pci_dev_hp_attrs_are_visible,
  };
1789382a7   Donald Dutile   PCI: SRIOV contro...
1701
1702
1703
1704
  #ifdef CONFIG_PCI_IOV
  static struct attribute *sriov_dev_attrs[] = {
  	&sriov_totalvfs_attr.attr,
  	&sriov_numvfs_attr.attr,
0e7df2240   Bodong Wang   PCI: Add sysfs sr...
1705
  	&sriov_drivers_autoprobe_attr.attr,
1789382a7   Donald Dutile   PCI: SRIOV contro...
1706
1707
1708
1709
  	NULL,
  };
  
  static umode_t sriov_attrs_are_visible(struct kobject *kobj,
3c78bc61f   Ryan Desfosses   PCI: Whitespace c...
1710
  				       struct attribute *a, int n)
1789382a7   Donald Dutile   PCI: SRIOV contro...
1711
  {
554a60379   Geliang Tang   PCI: Use kobj_to_...
1712
  	struct device *dev = kobj_to_dev(kobj);
1789382a7   Donald Dutile   PCI: SRIOV contro...
1713
1714
1715
1716
1717
1718
  
  	if (!dev_is_pf(dev))
  		return 0;
  
  	return a->mode;
  }
e7ea9825f   Arvind Yadav   PCI: Constify sys...
1719
  static const struct attribute_group sriov_dev_attr_group = {
1789382a7   Donald Dutile   PCI: SRIOV contro...
1720
1721
1722
1723
  	.attrs = sriov_dev_attrs,
  	.is_visible = sriov_attrs_are_visible,
  };
  #endif /* CONFIG_PCI_IOV */
e7ea9825f   Arvind Yadav   PCI: Constify sys...
1724
  static const struct attribute_group pci_dev_attr_group = {
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1725
1726
1727
  	.attrs = pci_dev_dev_attrs,
  	.is_visible = pci_dev_attrs_are_visible,
  };
e7ea9825f   Arvind Yadav   PCI: Constify sys...
1728
  static const struct attribute_group pci_bridge_attr_group = {
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
1729
1730
1731
  	.attrs = pci_bridge_attrs,
  	.is_visible = pci_bridge_attrs_are_visible,
  };
e7ea9825f   Arvind Yadav   PCI: Constify sys...
1732
  static const struct attribute_group pcie_dev_attr_group = {
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
1733
1734
1735
  	.attrs = pcie_dev_attrs,
  	.is_visible = pcie_dev_attrs_are_visible,
  };
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1736
1737
  static const struct attribute_group *pci_dev_attr_groups[] = {
  	&pci_dev_attr_group,
dfab88bed   Jiang Liu   PCI: Hide remove ...
1738
  	&pci_dev_hp_attr_group,
1789382a7   Donald Dutile   PCI: SRIOV contro...
1739
1740
1741
  #ifdef CONFIG_PCI_IOV
  	&sriov_dev_attr_group,
  #endif
56c1af460   Wong Vee Khee   PCI: Add sysfs ma...
1742
1743
  	&pci_bridge_attr_group,
  	&pcie_dev_attr_group,
4e15c46bd   Yinghai Lu   PCI: Add pci_devi...
1744
1745
1746
1747
1748
1749
  	NULL,
  };
  
  struct device_type pci_dev_type = {
  	.groups = pci_dev_attr_groups,
  };