aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2014-12-10 10:07:36 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-01-12 08:04:13 -0500
commit02b03846bb2befc558bfd0665749d6bb26f4c2f1 (patch)
tree055074b8ad2677ea38eefe967923b6bd85c10f94
parent1c6c9b1d9d2530c346910329751e7fd1a02dc2bd (diff)
pcmcia: add a new resource manager for non ISA systems
On a pure PCI platform we don't actually need all the complexity of the rsrc_nonstatic manager, in fact we can just work directly with the pci allocators and avoid all the complexity (and code bloat). Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/pcmcia/Kconfig12
-rw-r--r--drivers/pcmcia/Makefile1
-rw-r--r--drivers/pcmcia/rsrc_pci.c172
3 files changed, 182 insertions, 3 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 910e90bf16c6..8843a678f200 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -69,7 +69,8 @@ config YENTA
69 tristate "CardBus yenta-compatible bridge support" 69 tristate "CardBus yenta-compatible bridge support"
70 depends on PCI 70 depends on PCI
71 select CARDBUS if !EXPERT 71 select CARDBUS if !EXPERT
72 select PCCARD_NONSTATIC if PCMCIA != n 72 select PCCARD_NONSTATIC if PCMCIA != n && ISA
73 select PCCARD_PCI if PCMCIA !=n && !ISA
73 ---help--- 74 ---help---
74 This option enables support for CardBus host bridges. Virtually 75 This option enables support for CardBus host bridges. Virtually
75 all modern PCMCIA bridges are CardBus compatible. A "bridge" is 76 all modern PCMCIA bridges are CardBus compatible. A "bridge" is
@@ -109,7 +110,8 @@ config YENTA_TOSHIBA
109config PD6729 110config PD6729
110 tristate "Cirrus PD6729 compatible bridge support" 111 tristate "Cirrus PD6729 compatible bridge support"
111 depends on PCMCIA && PCI 112 depends on PCMCIA && PCI
112 select PCCARD_NONSTATIC 113 select PCCARD_NONSTATIC if PCMCIA != n && ISA
114 select PCCARD_PCI if PCMCIA !=n && !ISA
113 help 115 help
114 This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge 116 This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
115 device, found in some older laptops and PCMCIA card readers. 117 device, found in some older laptops and PCMCIA card readers.
@@ -117,7 +119,8 @@ config PD6729
117config I82092 119config I82092
118 tristate "i82092 compatible bridge support" 120 tristate "i82092 compatible bridge support"
119 depends on PCMCIA && PCI 121 depends on PCMCIA && PCI
120 select PCCARD_NONSTATIC 122 select PCCARD_NONSTATIC if PCMCIA != n && ISA
123 select PCCARD_PCI if PCMCIA !=n && !ISA
121 help 124 help
122 This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device, 125 This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
123 found in some older laptops and more commonly in evaluation boards for the 126 found in some older laptops and more commonly in evaluation boards for the
@@ -287,6 +290,9 @@ config ELECTRA_CF
287 Say Y here to support the CompactFlash controller on the 290 Say Y here to support the CompactFlash controller on the
288 PA Semi Electra eval board. 291 PA Semi Electra eval board.
289 292
293config PCCARD_PCI
294 bool
295
290config PCCARD_NONSTATIC 296config PCCARD_NONSTATIC
291 bool 297 bool
292 298
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 27e94b30cf96..f1a7ca04d89e 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_PCMCIA) += pcmcia.o
12pcmcia_rsrc-y += rsrc_mgr.o 12pcmcia_rsrc-y += rsrc_mgr.o
13pcmcia_rsrc-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o 13pcmcia_rsrc-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o
14pcmcia_rsrc-$(CONFIG_PCCARD_IODYN) += rsrc_iodyn.o 14pcmcia_rsrc-$(CONFIG_PCCARD_IODYN) += rsrc_iodyn.o
15pcmcia_rsrc-$(CONFIG_PCCARD_PCI) += rsrc_pci.o
15obj-$(CONFIG_PCCARD) += pcmcia_rsrc.o 16obj-$(CONFIG_PCCARD) += pcmcia_rsrc.o
16 17
17 18
diff --git a/drivers/pcmcia/rsrc_pci.c b/drivers/pcmcia/rsrc_pci.c
new file mode 100644
index 000000000000..8934d3c01f80
--- /dev/null
+++ b/drivers/pcmcia/rsrc_pci.c
@@ -0,0 +1,172 @@
1#include <linux/slab.h>
2#include <linux/module.h>
3#include <linux/kernel.h>
4
5#include <pcmcia/ss.h>
6#include <pcmcia/cistpl.h>
7#include "cs_internal.h"
8
9
10struct pcmcia_align_data {
11 unsigned long mask;
12 unsigned long offset;
13};
14
15static resource_size_t pcmcia_align(void *align_data,
16 const struct resource *res,
17 resource_size_t size, resource_size_t align)
18{
19 struct pcmcia_align_data *data = align_data;
20 resource_size_t start;
21
22 start = (res->start & ~data->mask) + data->offset;
23 if (start < res->start)
24 start += data->mask + 1;
25 return start;
26}
27
28static struct resource *find_io_region(struct pcmcia_socket *s,
29 unsigned long base, int num,
30 unsigned long align)
31{
32 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
33 dev_name(&s->dev));
34 struct pcmcia_align_data data;
35 int ret;
36
37 data.mask = align - 1;
38 data.offset = base & data.mask;
39
40 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
41 base, 0, pcmcia_align, &data);
42 if (ret != 0) {
43 kfree(res);
44 res = NULL;
45 }
46 return res;
47}
48
49static int res_pci_find_io(struct pcmcia_socket *s, unsigned int attr,
50 unsigned int *base, unsigned int num,
51 unsigned int align, struct resource **parent)
52{
53 int i, ret = 0;
54
55 /* Check for an already-allocated window that must conflict with
56 * what was asked for. It is a hack because it does not catch all
57 * potential conflicts, just the most obvious ones.
58 */
59 for (i = 0; i < MAX_IO_WIN; i++) {
60 if (!s->io[i].res)
61 continue;
62
63 if (!*base)
64 continue;
65
66 if ((s->io[i].res->start & (align-1)) == *base)
67 return -EBUSY;
68 }
69
70 for (i = 0; i < MAX_IO_WIN; i++) {
71 struct resource *res = s->io[i].res;
72 unsigned int try;
73
74 if (res && (res->flags & IORESOURCE_BITS) !=
75 (attr & IORESOURCE_BITS))
76 continue;
77
78 if (!res) {
79 if (align == 0)
80 align = 0x10000;
81
82 res = s->io[i].res = find_io_region(s, *base, num,
83 align);
84 if (!res)
85 return -EINVAL;
86
87 *base = res->start;
88 s->io[i].res->flags =
89 ((res->flags & ~IORESOURCE_BITS) |
90 (attr & IORESOURCE_BITS));
91 s->io[i].InUse = num;
92 *parent = res;
93 return 0;
94 }
95
96 /* Try to extend top of window */
97 try = res->end + 1;
98 if ((*base == 0) || (*base == try)) {
99 ret = adjust_resource(s->io[i].res, res->start,
100 resource_size(res) + num);
101 if (ret)
102 continue;
103 *base = try;
104 s->io[i].InUse += num;
105 *parent = res;
106 return 0;
107 }
108
109 /* Try to extend bottom of window */
110 try = res->start - num;
111 if ((*base == 0) || (*base == try)) {
112 ret = adjust_resource(s->io[i].res,
113 res->start - num,
114 resource_size(res) + num);
115 if (ret)
116 continue;
117 *base = try;
118 s->io[i].InUse += num;
119 *parent = res;
120 return 0;
121 }
122 }
123 return -EINVAL;
124}
125
126static struct resource *res_pci_find_mem(u_long base, u_long num,
127 u_long align, int low, struct pcmcia_socket *s)
128{
129 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
130 dev_name(&s->dev));
131 struct pcmcia_align_data data;
132 unsigned long min;
133 int ret;
134
135 if (align < 0x20000)
136 align = 0x20000;
137 data.mask = align - 1;
138 data.offset = base & data.mask;
139
140 min = 0;
141 if (!low)
142 min = 0x100000UL;
143
144 ret = pci_bus_alloc_resource(s->cb_dev->bus,
145 res, num, 1, min, 0,
146 pcmcia_align, &data);
147
148 if (ret != 0) {
149 kfree(res);
150 res = NULL;
151 }
152 return res;
153}
154
155
156static int res_pci_init(struct pcmcia_socket *s)
157{
158 if (!s->cb_dev || (!s->features & SS_CAP_PAGE_REGS)) {
159 dev_err(&s->dev, "not supported by res_pci\n");
160 return -EOPNOTSUPP;
161 }
162 return 0;
163}
164
165struct pccard_resource_ops pccard_nonstatic_ops = {
166 .validate_mem = NULL,
167 .find_io = res_pci_find_io,
168 .find_mem = res_pci_find_mem,
169 .init = res_pci_init,
170 .exit = NULL,
171};
172EXPORT_SYMBOL(pccard_nonstatic_ops);