[PATCH] PCI: fix memory leak in MMCONFIG error path
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / pci / pci-sysfs.c
CommitLineData
1da177e4
LT
1/*
2 * drivers/pci/pci-sysfs.c
3 *
4 * (C) Copyright 2002-2004 Greg Kroah-Hartman <greg@kroah.com>
5 * (C) Copyright 2002-2004 IBM Corp.
6 * (C) Copyright 2003 Matthew Wilcox
7 * (C) Copyright 2003 Hewlett-Packard
8 * (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
9 * (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
10 *
11 * File attributes for PCI devices
12 *
13 * Modeled after usb's driverfs.c
14 *
15 */
16
17
18#include <linux/config.h>
19#include <linux/kernel.h>
20#include <linux/pci.h>
21#include <linux/stat.h>
22#include <linux/topology.h>
23#include <linux/mm.h>
24
25#include "pci.h"
26
27static int sysfs_initialized; /* = 0 */
28
29/* show configuration fields */
30#define pci_config_attr(field, format_string) \
31static ssize_t \
e404e274 32field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
1da177e4
LT
33{ \
34 struct pci_dev *pdev; \
35 \
36 pdev = to_pci_dev (dev); \
37 return sprintf (buf, format_string, pdev->field); \
38}
39
40pci_config_attr(vendor, "0x%04x\n");
41pci_config_attr(device, "0x%04x\n");
42pci_config_attr(subsystem_vendor, "0x%04x\n");
43pci_config_attr(subsystem_device, "0x%04x\n");
44pci_config_attr(class, "0x%06x\n");
45pci_config_attr(irq, "%u\n");
9f125d30 46pci_config_attr(is_enabled, "%u\n");
1da177e4 47
4327edf6
AC
48static ssize_t local_cpus_show(struct device *dev,
49 struct device_attribute *attr, char *buf)
1da177e4 50{
4327edf6
AC
51 cpumask_t mask;
52 int len;
53
54 mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
55 len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
1da177e4
LT
56 strcat(buf,"\n");
57 return 1+len;
58}
59
60/* show resources */
61static ssize_t
e404e274 62resource_show(struct device * dev, struct device_attribute *attr, char * buf)
1da177e4
LT
63{
64 struct pci_dev * pci_dev = to_pci_dev(dev);
65 char * str = buf;
66 int i;
67 int max = 7;
2311b1f2 68 u64 start, end;
1da177e4
LT
69
70 if (pci_dev->subordinate)
71 max = DEVICE_COUNT_RESOURCE;
72
73 for (i = 0; i < max; i++) {
2311b1f2
ME
74 struct resource *res = &pci_dev->resource[i];
75 pci_resource_to_user(pci_dev, i, res, &start, &end);
76 str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",
77 (unsigned long long)start,
78 (unsigned long long)end,
79 (unsigned long long)res->flags);
1da177e4
LT
80 }
81 return (str - buf);
82}
83
87c8a443 84static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
9888549e
GKH
85{
86 struct pci_dev *pci_dev = to_pci_dev(dev);
87
88 return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
89 pci_dev->vendor, pci_dev->device,
90 pci_dev->subsystem_vendor, pci_dev->subsystem_device,
91 (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
92 (u8)(pci_dev->class));
93}
9f125d30
AV
94static ssize_t
95is_enabled_store(struct device *dev, struct device_attribute *attr,
96 const char *buf, size_t count)
97{
98 struct pci_dev *pdev = to_pci_dev(dev);
99
100 /* this can crash the machine when done on the "wrong" device */
101 if (!capable(CAP_SYS_ADMIN))
102 return count;
103
104 if (*buf == '0')
105 pci_disable_device(pdev);
106
107 if (*buf == '1')
108 pci_enable_device(pdev);
109
110 return count;
111}
112
9888549e 113
1da177e4
LT
114struct device_attribute pci_dev_attrs[] = {
115 __ATTR_RO(resource),
116 __ATTR_RO(vendor),
117 __ATTR_RO(device),
118 __ATTR_RO(subsystem_vendor),
119 __ATTR_RO(subsystem_device),
120 __ATTR_RO(class),
121 __ATTR_RO(irq),
122 __ATTR_RO(local_cpus),
9888549e 123 __ATTR_RO(modalias),
9f125d30 124 __ATTR(enable, 0600, is_enabled_show, is_enabled_store),
1da177e4
LT
125 __ATTR_NULL,
126};
127
128static ssize_t
129pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
130{
131 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
132 unsigned int size = 64;
133 loff_t init_off = off;
4c0619ad 134 u8 *data = (u8*) buf;
1da177e4
LT
135
136 /* Several chips lock up trying to read undefined config space */
137 if (capable(CAP_SYS_ADMIN)) {
138 size = dev->cfg_size;
139 } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
140 size = 128;
141 }
142
143 if (off > size)
144 return 0;
145 if (off + count > size) {
146 size -= off;
147 count = size;
148 } else {
149 size = count;
150 }
151
4c0619ad
SS
152 if ((off & 1) && size) {
153 u8 val;
e04b0ea2 154 pci_user_read_config_byte(dev, off, &val);
4c0619ad 155 data[off - init_off] = val;
1da177e4 156 off++;
4c0619ad
SS
157 size--;
158 }
159
160 if ((off & 3) && size > 2) {
161 u16 val;
e04b0ea2 162 pci_user_read_config_word(dev, off, &val);
4c0619ad
SS
163 data[off - init_off] = val & 0xff;
164 data[off - init_off + 1] = (val >> 8) & 0xff;
165 off += 2;
166 size -= 2;
1da177e4
LT
167 }
168
169 while (size > 3) {
4c0619ad 170 u32 val;
e04b0ea2 171 pci_user_read_config_dword(dev, off, &val);
4c0619ad
SS
172 data[off - init_off] = val & 0xff;
173 data[off - init_off + 1] = (val >> 8) & 0xff;
174 data[off - init_off + 2] = (val >> 16) & 0xff;
175 data[off - init_off + 3] = (val >> 24) & 0xff;
1da177e4
LT
176 off += 4;
177 size -= 4;
178 }
179
4c0619ad
SS
180 if (size >= 2) {
181 u16 val;
e04b0ea2 182 pci_user_read_config_word(dev, off, &val);
4c0619ad
SS
183 data[off - init_off] = val & 0xff;
184 data[off - init_off + 1] = (val >> 8) & 0xff;
185 off += 2;
186 size -= 2;
187 }
188
189 if (size > 0) {
190 u8 val;
e04b0ea2 191 pci_user_read_config_byte(dev, off, &val);
4c0619ad 192 data[off - init_off] = val;
1da177e4
LT
193 off++;
194 --size;
195 }
196
197 return count;
198}
199
200static ssize_t
201pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
202{
203 struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
204 unsigned int size = count;
205 loff_t init_off = off;
4c0619ad 206 u8 *data = (u8*) buf;
1da177e4
LT
207
208 if (off > dev->cfg_size)
209 return 0;
210 if (off + count > dev->cfg_size) {
211 size = dev->cfg_size - off;
212 count = size;
213 }
4c0619ad
SS
214
215 if ((off & 1) && size) {
e04b0ea2 216 pci_user_write_config_byte(dev, off, data[off - init_off]);
1da177e4 217 off++;
4c0619ad 218 size--;
1da177e4 219 }
4c0619ad
SS
220
221 if ((off & 3) && size > 2) {
222 u16 val = data[off - init_off];
223 val |= (u16) data[off - init_off + 1] << 8;
e04b0ea2 224 pci_user_write_config_word(dev, off, val);
4c0619ad
SS
225 off += 2;
226 size -= 2;
227 }
1da177e4
LT
228
229 while (size > 3) {
4c0619ad
SS
230 u32 val = data[off - init_off];
231 val |= (u32) data[off - init_off + 1] << 8;
232 val |= (u32) data[off - init_off + 2] << 16;
233 val |= (u32) data[off - init_off + 3] << 24;
e04b0ea2 234 pci_user_write_config_dword(dev, off, val);
1da177e4
LT
235 off += 4;
236 size -= 4;
237 }
4c0619ad
SS
238
239 if (size >= 2) {
240 u16 val = data[off - init_off];
241 val |= (u16) data[off - init_off + 1] << 8;
e04b0ea2 242 pci_user_write_config_word(dev, off, val);
4c0619ad
SS
243 off += 2;
244 size -= 2;
245 }
1da177e4 246
4c0619ad 247 if (size) {
e04b0ea2 248 pci_user_write_config_byte(dev, off, data[off - init_off]);
1da177e4
LT
249 off++;
250 --size;
251 }
252
253 return count;
254}
255
256#ifdef HAVE_PCI_LEGACY
257/**
258 * pci_read_legacy_io - read byte(s) from legacy I/O port space
259 * @kobj: kobject corresponding to file to read from
260 * @buf: buffer to store results
261 * @off: offset into legacy I/O port space
262 * @count: number of bytes to read
263 *
264 * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
265 * callback routine (pci_legacy_read).
266 */
267ssize_t
268pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
269{
270 struct pci_bus *bus = to_pci_bus(container_of(kobj,
271 struct class_device,
272 kobj));
273
274 /* Only support 1, 2 or 4 byte accesses */
275 if (count != 1 && count != 2 && count != 4)
276 return -EINVAL;
277
278 return pci_legacy_read(bus, off, (u32 *)buf, count);
279}
280
281/**
282 * pci_write_legacy_io - write byte(s) to legacy I/O port space
283 * @kobj: kobject corresponding to file to read from
284 * @buf: buffer containing value to be written
285 * @off: offset into legacy I/O port space
286 * @count: number of bytes to write
287 *
288 * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
289 * callback routine (pci_legacy_write).
290 */
291ssize_t
292pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
293{
294 struct pci_bus *bus = to_pci_bus(container_of(kobj,
295 struct class_device,
296 kobj));
297 /* Only support 1, 2 or 4 byte accesses */
298 if (count != 1 && count != 2 && count != 4)
299 return -EINVAL;
300
301 return pci_legacy_write(bus, off, *(u32 *)buf, count);
302}
303
304/**
305 * pci_mmap_legacy_mem - map legacy PCI memory into user memory space
306 * @kobj: kobject corresponding to device to be mapped
307 * @attr: struct bin_attribute for this file
308 * @vma: struct vm_area_struct passed to mmap
309 *
310 * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap
311 * legacy memory space (first meg of bus space) into application virtual
312 * memory space.
313 */
314int
315pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
316 struct vm_area_struct *vma)
317{
318 struct pci_bus *bus = to_pci_bus(container_of(kobj,
319 struct class_device,
320 kobj));
321
322 return pci_mmap_legacy_page_range(bus, vma);
323}
324#endif /* HAVE_PCI_LEGACY */
325
326#ifdef HAVE_PCI_MMAP
327/**
328 * pci_mmap_resource - map a PCI resource into user memory space
329 * @kobj: kobject for mapping
330 * @attr: struct bin_attribute for the file being mapped
331 * @vma: struct vm_area_struct passed into the mmap
332 *
333 * Use the regular PCI mapping routines to map a PCI resource into userspace.
334 * FIXME: write combining? maybe automatic for prefetchable regions?
335 */
336static int
337pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
338 struct vm_area_struct *vma)
339{
340 struct pci_dev *pdev = to_pci_dev(container_of(kobj,
341 struct device, kobj));
342 struct resource *res = (struct resource *)attr->private;
343 enum pci_mmap_state mmap_type;
2311b1f2
ME
344 u64 start, end;
345 int i;
1da177e4 346
2311b1f2
ME
347 for (i = 0; i < PCI_ROM_RESOURCE; i++)
348 if (res == &pdev->resource[i])
349 break;
350 if (i >= PCI_ROM_RESOURCE)
351 return -ENODEV;
352
353 /* pci_mmap_page_range() expects the same kind of entry as coming
354 * from /proc/bus/pci/ which is a "user visible" value. If this is
355 * different from the resource itself, arch will do necessary fixup.
356 */
357 pci_resource_to_user(pdev, i, res, &start, &end);
358 vma->vm_pgoff += start >> PAGE_SHIFT;
1da177e4
LT
359 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
360
361 return pci_mmap_page_range(pdev, vma, mmap_type, 0);
362}
363
364/**
365 * pci_create_resource_files - create resource files in sysfs for @dev
366 * @dev: dev in question
367 *
368 * Walk the resources in @dev creating files for each resource available.
369 */
370static void
371pci_create_resource_files(struct pci_dev *pdev)
372{
373 int i;
374
375 /* Expose the PCI resources from this device as files */
376 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
377 struct bin_attribute *res_attr;
378
379 /* skip empty resources */
380 if (!pci_resource_len(pdev, i))
381 continue;
382
d48593bf 383 /* allocate attribute structure, piggyback attribute name */
656da9da 384 res_attr = kzalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
1da177e4 385 if (res_attr) {
d48593bf
DT
386 char *res_attr_name = (char *)(res_attr + 1);
387
1da177e4 388 pdev->res_attr[i] = res_attr;
d48593bf
DT
389 sprintf(res_attr_name, "resource%d", i);
390 res_attr->attr.name = res_attr_name;
1da177e4
LT
391 res_attr->attr.mode = S_IRUSR | S_IWUSR;
392 res_attr->attr.owner = THIS_MODULE;
d48593bf 393 res_attr->size = pci_resource_len(pdev, i);
1da177e4
LT
394 res_attr->mmap = pci_mmap_resource;
395 res_attr->private = &pdev->resource[i];
396 sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
397 }
398 }
399}
400
401/**
402 * pci_remove_resource_files - cleanup resource files
403 * @dev: dev to cleanup
404 *
405 * If we created resource files for @dev, remove them from sysfs and
406 * free their resources.
407 */
408static void
409pci_remove_resource_files(struct pci_dev *pdev)
410{
411 int i;
412
413 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
414 struct bin_attribute *res_attr;
415
416 res_attr = pdev->res_attr[i];
417 if (res_attr) {
418 sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
419 kfree(res_attr);
420 }
421 }
422}
423#else /* !HAVE_PCI_MMAP */
424static inline void pci_create_resource_files(struct pci_dev *dev) { return; }
425static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
426#endif /* HAVE_PCI_MMAP */
427
428/**
429 * pci_write_rom - used to enable access to the PCI ROM display
430 * @kobj: kernel object handle
431 * @buf: user input
432 * @off: file offset
433 * @count: number of byte in input
434 *
435 * writing anything except 0 enables it
436 */
437static ssize_t
438pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
439{
440 struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
441
442 if ((off == 0) && (*buf == '0') && (count == 2))
443 pdev->rom_attr_enabled = 0;
444 else
445 pdev->rom_attr_enabled = 1;
446
447 return count;
448}
449
450/**
451 * pci_read_rom - read a PCI ROM
452 * @kobj: kernel object handle
453 * @buf: where to put the data we read from the ROM
454 * @off: file offset
455 * @count: number of bytes to read
456 *
457 * Put @count bytes starting at @off into @buf from the ROM in the PCI
458 * device corresponding to @kobj.
459 */
460static ssize_t
461pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
462{
463 struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
464 void __iomem *rom;
465 size_t size;
466
467 if (!pdev->rom_attr_enabled)
468 return -EINVAL;
469
470 rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */
471 if (!rom)
472 return 0;
473
474 if (off >= size)
475 count = 0;
476 else {
477 if (off + count > size)
478 count = size - off;
479
480 memcpy_fromio(buf, rom + off, count);
481 }
482 pci_unmap_rom(pdev, rom);
483
484 return count;
485}
486
487static struct bin_attribute pci_config_attr = {
488 .attr = {
489 .name = "config",
490 .mode = S_IRUGO | S_IWUSR,
491 .owner = THIS_MODULE,
492 },
493 .size = 256,
494 .read = pci_read_config,
495 .write = pci_write_config,
496};
497
498static struct bin_attribute pcie_config_attr = {
499 .attr = {
500 .name = "config",
501 .mode = S_IRUGO | S_IWUSR,
502 .owner = THIS_MODULE,
503 },
504 .size = 4096,
505 .read = pci_read_config,
506 .write = pci_write_config,
507};
508
509int pci_create_sysfs_dev_files (struct pci_dev *pdev)
510{
511 if (!sysfs_initialized)
512 return -EACCES;
513
514 if (pdev->cfg_size < 4096)
515 sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
516 else
517 sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
518
519 pci_create_resource_files(pdev);
520
521 /* If the device has a ROM, try to expose it in sysfs. */
522 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
523 struct bin_attribute *rom_attr;
524
f5afe806 525 rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
1da177e4 526 if (rom_attr) {
1da177e4
LT
527 pdev->rom_attr = rom_attr;
528 rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
529 rom_attr->attr.name = "rom";
530 rom_attr->attr.mode = S_IRUSR;
531 rom_attr->attr.owner = THIS_MODULE;
532 rom_attr->read = pci_read_rom;
533 rom_attr->write = pci_write_rom;
534 sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
535 }
536 }
537 /* add platform-specific attributes */
538 pcibios_add_platform_entries(pdev);
539
540 return 0;
541}
542
543/**
544 * pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
545 * @pdev: device whose entries we should free
546 *
547 * Cleanup when @pdev is removed from sysfs.
548 */
549void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
550{
551 if (pdev->cfg_size < 4096)
552 sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
553 else
554 sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
555
556 pci_remove_resource_files(pdev);
557
558 if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
559 if (pdev->rom_attr) {
560 sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
561 kfree(pdev->rom_attr);
562 }
563 }
564}
565
566static int __init pci_sysfs_init(void)
567{
568 struct pci_dev *pdev = NULL;
569
570 sysfs_initialized = 1;
571 for_each_pci_dev(pdev)
572 pci_create_sysfs_dev_files(pdev);
573
574 return 0;
575}
576
577__initcall(pci_sysfs_init);