aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-03 05:49:32 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2008-10-20 14:01:46 -0400
commitf19aeb1f3638b7bb4ca21eb361f004fac2bfe259 (patch)
tree2990881affb22ba426149e8d4c317fe9df9992c7
parentf393d9b130423a7a47c751b26df07ceaa5dc76a9 (diff)
PCI: Add ability to mmap legacy_io on some platforms
This adds the ability to mmap legacy IO space to the legacy_io files in sysfs on platforms that support it. This will allow to clean up X to use this instead of /dev/mem for legacy IO accesses such as those performed by Int10. While at it I moved pci_create/remove_legacy_files() to pci-sysfs.c where I think they belong, thus making more things statis in there and cleaned up some spurrious prototypes in the ia64 pci.h file Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--arch/ia64/include/asm/pci.h12
-rw-r--r--arch/ia64/pci/pci.c7
-rw-r--r--drivers/pci/pci-sysfs.c93
-rw-r--r--drivers/pci/pci.h6
-rw-r--r--drivers/pci/probe.c66
5 files changed, 102 insertions, 82 deletions
diff --git a/arch/ia64/include/asm/pci.h b/arch/ia64/include/asm/pci.h
index 0149097b736d..ce342fb74246 100644
--- a/arch/ia64/include/asm/pci.h
+++ b/arch/ia64/include/asm/pci.h
@@ -95,16 +95,8 @@ extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
95 enum pci_mmap_state mmap_state, int write_combine); 95 enum pci_mmap_state mmap_state, int write_combine);
96#define HAVE_PCI_LEGACY 96#define HAVE_PCI_LEGACY
97extern int pci_mmap_legacy_page_range(struct pci_bus *bus, 97extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
98 struct vm_area_struct *vma); 98 struct vm_area_struct *vma,
99extern ssize_t pci_read_legacy_io(struct kobject *kobj, 99 enum pci_mmap_state mmap_state);
100 struct bin_attribute *bin_attr,
101 char *buf, loff_t off, size_t count);
102extern ssize_t pci_write_legacy_io(struct kobject *kobj,
103 struct bin_attribute *bin_attr,
104 char *buf, loff_t off, size_t count);
105extern int pci_mmap_legacy_mem(struct kobject *kobj,
106 struct bin_attribute *attr,
107 struct vm_area_struct *vma);
108 100
109#define pci_get_legacy_mem platform_pci_get_legacy_mem 101#define pci_get_legacy_mem platform_pci_get_legacy_mem
110#define pci_legacy_read platform_pci_legacy_read 102#define pci_legacy_read platform_pci_legacy_read
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 7545037a8625..211fcfd115f9 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -614,12 +614,17 @@ char *ia64_pci_get_legacy_mem(struct pci_bus *bus)
614 * vector to get the base address. 614 * vector to get the base address.
615 */ 615 */
616int 616int
617pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma) 617pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
618 enum pci_mmap_state mmap_state)
618{ 619{
619 unsigned long size = vma->vm_end - vma->vm_start; 620 unsigned long size = vma->vm_end - vma->vm_start;
620 pgprot_t prot; 621 pgprot_t prot;
621 char *addr; 622 char *addr;
622 623
624 /* We only support mmap'ing of legacy memory space */
625 if (mmap_state != pci_mmap_mem)
626 return -ENOSYS;
627
623 /* 628 /*
624 * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt 629 * Avoid attribute aliasing. See Documentation/ia64/aliasing.txt
625 * for more details. 630 * for more details.
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 2cad6da2e4aa..110022d78689 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -423,7 +423,7 @@ pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr,
423 * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific 423 * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
424 * callback routine (pci_legacy_read). 424 * callback routine (pci_legacy_read).
425 */ 425 */
426ssize_t 426static ssize_t
427pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, 427pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
428 char *buf, loff_t off, size_t count) 428 char *buf, loff_t off, size_t count)
429{ 429{
@@ -448,7 +448,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
448 * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific 448 * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
449 * callback routine (pci_legacy_write). 449 * callback routine (pci_legacy_write).
450 */ 450 */
451ssize_t 451static ssize_t
452pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, 452pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
453 char *buf, loff_t off, size_t count) 453 char *buf, loff_t off, size_t count)
454{ 454{
@@ -468,11 +468,11 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
468 * @attr: struct bin_attribute for this file 468 * @attr: struct bin_attribute for this file
469 * @vma: struct vm_area_struct passed to mmap 469 * @vma: struct vm_area_struct passed to mmap
470 * 470 *
471 * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap 471 * Uses an arch specific callback, pci_mmap_legacy_mem_page_range, to mmap
472 * legacy memory space (first meg of bus space) into application virtual 472 * legacy memory space (first meg of bus space) into application virtual
473 * memory space. 473 * memory space.
474 */ 474 */
475int 475static int
476pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, 476pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
477 struct vm_area_struct *vma) 477 struct vm_area_struct *vma)
478{ 478{
@@ -480,7 +480,90 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
480 struct device, 480 struct device,
481 kobj)); 481 kobj));
482 482
483 return pci_mmap_legacy_page_range(bus, vma); 483 return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);
484}
485
486/**
487 * pci_mmap_legacy_io - map legacy PCI IO into user memory space
488 * @kobj: kobject corresponding to device to be mapped
489 * @attr: struct bin_attribute for this file
490 * @vma: struct vm_area_struct passed to mmap
491 *
492 * Uses an arch specific callback, pci_mmap_legacy_io_page_range, to mmap
493 * legacy IO space (first meg of bus space) into application virtual
494 * memory space. Returns -ENOSYS if the operation isn't supported
495 */
496static int
497pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr,
498 struct vm_area_struct *vma)
499{
500 struct pci_bus *bus = to_pci_bus(container_of(kobj,
501 struct device,
502 kobj));
503
504 return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);
505}
506
507/**
508 * pci_create_legacy_files - create legacy I/O port and memory files
509 * @b: bus to create files under
510 *
511 * Some platforms allow access to legacy I/O port and ISA memory space on
512 * a per-bus basis. This routine creates the files and ties them into
513 * their associated read, write and mmap files from pci-sysfs.c
514 *
515 * On error unwind, but don't propogate the error to the caller
516 * as it is ok to set up the PCI bus without these files.
517 */
518void pci_create_legacy_files(struct pci_bus *b)
519{
520 int error;
521
522 b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
523 GFP_ATOMIC);
524 if (!b->legacy_io)
525 goto kzalloc_err;
526
527 b->legacy_io->attr.name = "legacy_io";
528 b->legacy_io->size = 0xffff;
529 b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
530 b->legacy_io->read = pci_read_legacy_io;
531 b->legacy_io->write = pci_write_legacy_io;
532 b->legacy_io->mmap = pci_mmap_legacy_io;
533 error = device_create_bin_file(&b->dev, b->legacy_io);
534 if (error)
535 goto legacy_io_err;
536
537 /* Allocated above after the legacy_io struct */
538 b->legacy_mem = b->legacy_io + 1;
539 b->legacy_mem->attr.name = "legacy_mem";
540 b->legacy_mem->size = 1024*1024;
541 b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
542 b->legacy_mem->mmap = pci_mmap_legacy_mem;
543 error = device_create_bin_file(&b->dev, b->legacy_mem);
544 if (error)
545 goto legacy_mem_err;
546
547 return;
548
549legacy_mem_err:
550 device_remove_bin_file(&b->dev, b->legacy_io);
551legacy_io_err:
552 kfree(b->legacy_io);
553 b->legacy_io = NULL;
554kzalloc_err:
555 printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
556 "and ISA memory resources to sysfs\n");
557 return;
558}
559
560void pci_remove_legacy_files(struct pci_bus *b)
561{
562 if (b->legacy_io) {
563 device_remove_bin_file(&b->dev, b->legacy_io);
564 device_remove_bin_file(&b->dev, b->legacy_mem);
565 kfree(b->legacy_io); /* both are allocated here */
566 }
484} 567}
485#endif /* HAVE_PCI_LEGACY */ 568#endif /* HAVE_PCI_LEGACY */
486 569
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 39684c1415c5..b205ab866a1d 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -82,7 +82,13 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
82/* Functions for PCI Hotplug drivers to use */ 82/* Functions for PCI Hotplug drivers to use */
83extern unsigned int pci_do_scan_bus(struct pci_bus *bus); 83extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
84 84
85#ifdef HAVE_PCI_LEGACY
86extern void pci_create_legacy_files(struct pci_bus *bus);
85extern void pci_remove_legacy_files(struct pci_bus *bus); 87extern void pci_remove_legacy_files(struct pci_bus *bus);
88#else
89static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
90static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
91#endif
86 92
87/* Lock for read/write access to pci device and bus lists */ 93/* Lock for read/write access to pci device and bus lists */
88extern struct rw_semaphore pci_bus_sem; 94extern struct rw_semaphore pci_bus_sem;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index afb9f1c0bc28..aaaf0a1fed22 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -42,72 +42,6 @@ int no_pci_devices(void)
42} 42}
43EXPORT_SYMBOL(no_pci_devices); 43EXPORT_SYMBOL(no_pci_devices);
44 44
45#ifdef HAVE_PCI_LEGACY
46/**
47 * pci_create_legacy_files - create legacy I/O port and memory files
48 * @b: bus to create files under
49 *
50 * Some platforms allow access to legacy I/O port and ISA memory space on
51 * a per-bus basis. This routine creates the files and ties them into
52 * their associated read, write and mmap files from pci-sysfs.c
53 *
54 * On error unwind, but don't propogate the error to the caller
55 * as it is ok to set up the PCI bus without these files.
56 */
57static void pci_create_legacy_files(struct pci_bus *b)
58{
59 int error;
60
61 b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
62 GFP_ATOMIC);
63 if (!b->legacy_io)
64 goto kzalloc_err;
65
66 b->legacy_io->attr.name = "legacy_io";
67 b->legacy_io->size = 0xffff;
68 b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
69 b->legacy_io->read = pci_read_legacy_io;
70 b->legacy_io->write = pci_write_legacy_io;
71 error = device_create_bin_file(&b->dev, b->legacy_io);
72 if (error)
73 goto legacy_io_err;
74
75 /* Allocated above after the legacy_io struct */
76 b->legacy_mem = b->legacy_io + 1;
77 b->legacy_mem->attr.name = "legacy_mem";
78 b->legacy_mem->size = 1024*1024;
79 b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
80 b->legacy_mem->mmap = pci_mmap_legacy_mem;
81 error = device_create_bin_file(&b->dev, b->legacy_mem);
82 if (error)
83 goto legacy_mem_err;
84
85 return;
86
87legacy_mem_err:
88 device_remove_bin_file(&b->dev, b->legacy_io);
89legacy_io_err:
90 kfree(b->legacy_io);
91 b->legacy_io = NULL;
92kzalloc_err:
93 printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
94 "and ISA memory resources to sysfs\n");
95 return;
96}
97
98void pci_remove_legacy_files(struct pci_bus *b)
99{
100 if (b->legacy_io) {
101 device_remove_bin_file(&b->dev, b->legacy_io);
102 device_remove_bin_file(&b->dev, b->legacy_mem);
103 kfree(b->legacy_io); /* both are allocated here */
104 }
105}
106#else /* !HAVE_PCI_LEGACY */
107static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
108void pci_remove_legacy_files(struct pci_bus *bus) { return; }
109#endif /* HAVE_PCI_LEGACY */
110
111/* 45/*
112 * PCI Bus Class Devices 46 * PCI Bus Class Devices
113 */ 47 */