diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-02 15:49:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-04-02 15:49:59 -0400 |
commit | 86dca4f8e6ab1fd8a3fb5838163fc9d7990f416e (patch) | |
tree | 3d32116afc3be0d323ef93f260592bcea11db329 /drivers/pcmcia | |
parent | 9c8680e2cfbb60d5075f8caaf9d98276120bcc78 (diff) | |
parent | 553ee5dc1a7a1fb04a6286b0c779481f7035bbd1 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6: (33 commits)
[PATCH] pcmcia: declare pccard_iodyn_ops (fix m8xx_pcmcia.c compilation error)
[PATCH] pcmcia: fix pcmcia_device_remove oops
[PATCH] pcmcia: Add support for Possio GCC AKA PCMCIA Siemens MC45
[PATCH] pcmcia: pseudo device handling update
[PATCH] pcmcia: convert DEV_OK to pcmcia_dev_present
[PATCH] pcmcia: use bitfield instead of p_state and state
[PATCH] pcmcia: remove unused p_dev->state flags
[PATCH] pcmcia: make pcmcia_release_{io,irq} static
[PATCH] pcmcia: add return value to _config() functions
[PATCH] pcmcia: remove dev_link_t and client_handle_t indirection
[PATCH] pcmcia: embed dev_link_t into struct pcmcia_device
[PATCH] pcmcia: rename pcmcia_device.state
[PATCH] pcmcia: remove unneeded Vcc pseudo setting
[PATCH] pcmcia: remove export of pcmcia_release_configuration
[PATCH] pcmcia: default suspend and resume handling
[PATCH] pcmcia: convert remaining users of pcmcia_release_io and _irq
[PATCH] pcmcia: add pcmcia_disable_device
[PATCH] serial_cs: add Merlin U630 IDs
[PATCH] pcmcia: AT91RM9200 Compact Flash driver
[PATCH] pcmcia: socket.functions starts with 1
...
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/Kconfig | 7 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 3 | ||||
-rw-r--r-- | drivers/pcmcia/at91_cf.c | 365 | ||||
-rw-r--r-- | drivers/pcmcia/cistpl.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 43 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 19 | ||||
-rw-r--r-- | drivers/pcmcia/ds.c | 249 | ||||
-rw-r--r-- | drivers/pcmcia/ds_internal.h | 4 | ||||
-rw-r--r-- | drivers/pcmcia/i82092.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/i82365.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_compat.c | 65 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_ioctl.c | 81 | ||||
-rw-r--r-- | drivers/pcmcia/pcmcia_resource.c | 228 | ||||
-rw-r--r-- | drivers/pcmcia/pd6729.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_mgr.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/rsrc_nonstatic.c | 41 | ||||
-rw-r--r-- | drivers/pcmcia/sa1100_cerf.c | 1 | ||||
-rw-r--r-- | drivers/pcmcia/socket_sysfs.c | 10 | ||||
-rw-r--r-- | drivers/pcmcia/ti113x.h | 1 |
19 files changed, 767 insertions, 359 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 1f4ad0e7836e..cba6c9eef28e 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
@@ -263,6 +263,13 @@ config OMAP_CF | |||
263 | Say Y here to support the CompactFlash controller on OMAP. | 263 | Say Y here to support the CompactFlash controller on OMAP. |
264 | Note that this doesn't support "True IDE" mode. | 264 | Note that this doesn't support "True IDE" mode. |
265 | 265 | ||
266 | config AT91_CF | ||
267 | tristate "AT91 CompactFlash Controller" | ||
268 | depends on PCMCIA && ARCH_AT91RM9200 | ||
269 | help | ||
270 | Say Y here to support the CompactFlash controller on AT91 chips. | ||
271 | Or choose M to compile the driver as a module named "at91_cf". | ||
272 | |||
266 | config PCCARD_NONSTATIC | 273 | config PCCARD_NONSTATIC |
267 | tristate | 274 | tristate |
268 | 275 | ||
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index bcecf5133b7e..4276965517f2 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
@@ -10,7 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o | |||
10 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o | 10 | pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o |
11 | obj-$(CONFIG_PCCARD) += pcmcia_core.o | 11 | obj-$(CONFIG_PCCARD) += pcmcia_core.o |
12 | 12 | ||
13 | pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o | 13 | pcmcia-y += ds.o pcmcia_resource.o |
14 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o | 14 | pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o |
15 | obj-$(CONFIG_PCMCIA) += pcmcia.o | 15 | obj-$(CONFIG_PCMCIA) += pcmcia.o |
16 | 16 | ||
@@ -36,6 +36,7 @@ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o | |||
36 | obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o | 36 | obj-$(CONFIG_PCMCIA_VRC4171) += vrc4171_card.o |
37 | obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o | 37 | obj-$(CONFIG_PCMCIA_VRC4173) += vrc4173_cardu.o |
38 | obj-$(CONFIG_OMAP_CF) += omap_cf.o | 38 | obj-$(CONFIG_OMAP_CF) += omap_cf.o |
39 | obj-$(CONFIG_AT91_CF) += at91_cf.o | ||
39 | 40 | ||
40 | sa11xx_core-y += soc_common.o sa11xx_base.o | 41 | sa11xx_core-y += soc_common.o sa11xx_base.o |
41 | pxa2xx_core-y += soc_common.o pxa2xx_base.o | 42 | pxa2xx_core-y += soc_common.o pxa2xx_base.o |
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c new file mode 100644 index 000000000000..67cc5f7d0c90 --- /dev/null +++ b/drivers/pcmcia/at91_cf.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * at91_cf.c -- AT91 CompactFlash controller driver | ||
3 | * | ||
4 | * Copyright (C) 2005 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <pcmcia/ss.h> | ||
21 | |||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/sizes.h> | ||
25 | |||
26 | #include <asm/arch/at91rm9200.h> | ||
27 | #include <asm/arch/board.h> | ||
28 | #include <asm/arch/gpio.h> | ||
29 | |||
30 | |||
31 | #define CF_SIZE 0x30000000 /* CS5+CS6: unavailable */ | ||
32 | |||
33 | /* | ||
34 | * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; | ||
35 | * some other bit in {A24,A22..A11} is nREG to flag memory access | ||
36 | * (vs attributes). So more than 2KB/region would just be waste. | ||
37 | */ | ||
38 | #define CF_ATTR_PHYS (AT91_CF_BASE) | ||
39 | #define CF_IO_PHYS (AT91_CF_BASE + (1 << 23)) | ||
40 | #define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800) | ||
41 | |||
42 | /*--------------------------------------------------------------------------*/ | ||
43 | |||
44 | static const char driver_name[] = "at91_cf"; | ||
45 | |||
46 | struct at91_cf_socket { | ||
47 | struct pcmcia_socket socket; | ||
48 | |||
49 | unsigned present:1; | ||
50 | |||
51 | struct platform_device *pdev; | ||
52 | struct at91_cf_data *board; | ||
53 | }; | ||
54 | |||
55 | #define SZ_2K (2 * SZ_1K) | ||
56 | |||
57 | static inline int at91_cf_present(struct at91_cf_socket *cf) | ||
58 | { | ||
59 | return !at91_get_gpio_value(cf->board->det_pin); | ||
60 | } | ||
61 | |||
62 | /*--------------------------------------------------------------------------*/ | ||
63 | |||
64 | static int at91_cf_ss_init(struct pcmcia_socket *s) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r) | ||
70 | { | ||
71 | struct at91_cf_socket *cf = (struct at91_cf_socket *) _cf; | ||
72 | |||
73 | if (irq == cf->board->det_pin) { | ||
74 | unsigned present = at91_cf_present(cf); | ||
75 | |||
76 | /* kick pccard as needed */ | ||
77 | if (present != cf->present) { | ||
78 | cf->present = present; | ||
79 | pr_debug("%s: card %s\n", driver_name, present ? "present" : "gone"); | ||
80 | pcmcia_parse_events(&cf->socket, SS_DETECT); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | return IRQ_HANDLED; | ||
85 | } | ||
86 | |||
87 | static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp) | ||
88 | { | ||
89 | struct at91_cf_socket *cf; | ||
90 | |||
91 | if (!sp) | ||
92 | return -EINVAL; | ||
93 | |||
94 | cf = container_of(s, struct at91_cf_socket, socket); | ||
95 | |||
96 | /* NOTE: we assume 3VCARD, not XVCARD... */ | ||
97 | if (at91_cf_present(cf)) { | ||
98 | int rdy = cf->board->irq_pin; /* RDY/nIRQ */ | ||
99 | int vcc = cf->board->vcc_pin; | ||
100 | |||
101 | *sp = SS_DETECT | SS_3VCARD; | ||
102 | if (!rdy || at91_get_gpio_value(rdy)) | ||
103 | *sp |= SS_READY; | ||
104 | if (!vcc || at91_get_gpio_value(vcc)) | ||
105 | *sp |= SS_POWERON; | ||
106 | } else | ||
107 | *sp = 0; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s) | ||
113 | { | ||
114 | struct at91_cf_socket *cf; | ||
115 | |||
116 | cf = container_of(sock, struct at91_cf_socket, socket); | ||
117 | |||
118 | /* switch Vcc if needed and possible */ | ||
119 | if (cf->board->vcc_pin) { | ||
120 | switch (s->Vcc) { | ||
121 | case 0: | ||
122 | at91_set_gpio_value(cf->board->vcc_pin, 0); | ||
123 | break; | ||
124 | case 33: | ||
125 | at91_set_gpio_value(cf->board->vcc_pin, 1); | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* toggle reset if needed */ | ||
133 | at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET); | ||
134 | |||
135 | pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n", | ||
136 | driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int at91_cf_ss_suspend(struct pcmcia_socket *s) | ||
142 | { | ||
143 | return at91_cf_set_socket(s, &dead_socket); | ||
144 | } | ||
145 | |||
146 | /* we already mapped the I/O region */ | ||
147 | static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) | ||
148 | { | ||
149 | struct at91_cf_socket *cf; | ||
150 | u32 csr; | ||
151 | |||
152 | cf = container_of(s, struct at91_cf_socket, socket); | ||
153 | io->flags &= (MAP_ACTIVE | MAP_16BIT | MAP_AUTOSZ); | ||
154 | |||
155 | /* | ||
156 | * Use 16 bit accesses unless/until we need 8-bit i/o space. | ||
157 | * Always set CSR4 ... PCMCIA won't always unmap things. | ||
158 | */ | ||
159 | csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW; | ||
160 | |||
161 | /* | ||
162 | * NOTE: this CF controller ignores IOIS16, so we can't really do | ||
163 | * MAP_AUTOSZ. The 16bit mode allows single byte access on either | ||
164 | * D0-D7 (even addr) or D8-D15 (odd), so it's close enough for many | ||
165 | * purposes (and handles ide-cs). | ||
166 | * | ||
167 | * The 8bit mode is needed for odd byte access on D0-D7. It seems | ||
168 | * some cards only like that way to get at the odd byte, despite | ||
169 | * CF 3.0 spec table 35 also giving the D8-D15 option. | ||
170 | */ | ||
171 | if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) { | ||
172 | csr |= AT91_SMC_DBW_8; | ||
173 | pr_debug("%s: 8bit i/o bus\n", driver_name); | ||
174 | } else { | ||
175 | csr |= AT91_SMC_DBW_16; | ||
176 | pr_debug("%s: 16bit i/o bus\n", driver_name); | ||
177 | } | ||
178 | at91_sys_write(AT91_SMC_CSR(4), csr); | ||
179 | |||
180 | io->start = cf->socket.io_offset; | ||
181 | io->stop = io->start + SZ_2K - 1; | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | /* pcmcia layer maps/unmaps mem regions */ | ||
187 | static int at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map) | ||
188 | { | ||
189 | struct at91_cf_socket *cf; | ||
190 | |||
191 | if (map->card_start) | ||
192 | return -EINVAL; | ||
193 | |||
194 | cf = container_of(s, struct at91_cf_socket, socket); | ||
195 | |||
196 | map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT; | ||
197 | if (map->flags & MAP_ATTRIB) | ||
198 | map->static_start = CF_ATTR_PHYS; | ||
199 | else | ||
200 | map->static_start = CF_MEM_PHYS; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static struct pccard_operations at91_cf_ops = { | ||
206 | .init = at91_cf_ss_init, | ||
207 | .suspend = at91_cf_ss_suspend, | ||
208 | .get_status = at91_cf_get_status, | ||
209 | .set_socket = at91_cf_set_socket, | ||
210 | .set_io_map = at91_cf_set_io_map, | ||
211 | .set_mem_map = at91_cf_set_mem_map, | ||
212 | }; | ||
213 | |||
214 | /*--------------------------------------------------------------------------*/ | ||
215 | |||
216 | static int __init at91_cf_probe(struct device *dev) | ||
217 | { | ||
218 | struct at91_cf_socket *cf; | ||
219 | struct at91_cf_data *board = dev->platform_data; | ||
220 | struct platform_device *pdev = to_platform_device(dev); | ||
221 | unsigned int csa; | ||
222 | int status; | ||
223 | |||
224 | if (!board || !board->det_pin || !board->rst_pin) | ||
225 | return -ENODEV; | ||
226 | |||
227 | cf = kcalloc(1, sizeof *cf, GFP_KERNEL); | ||
228 | if (!cf) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | cf->board = board; | ||
232 | cf->pdev = pdev; | ||
233 | dev_set_drvdata(dev, cf); | ||
234 | |||
235 | /* CF takes over CS4, CS5, CS6 */ | ||
236 | csa = at91_sys_read(AT91_EBI_CSA); | ||
237 | at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); | ||
238 | |||
239 | /* force poweron defaults for these pins ... */ | ||
240 | (void) at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ | ||
241 | (void) at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ | ||
242 | (void) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ | ||
243 | (void) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ | ||
244 | |||
245 | /* nWAIT is _not_ a default setting */ | ||
246 | (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ | ||
247 | |||
248 | /* | ||
249 | * Static memory controller timing adjustments. | ||
250 | * REVISIT: these timings are in terms of MCK cycles, so | ||
251 | * when MCK changes (cpufreq etc) so must these values... | ||
252 | */ | ||
253 | at91_sys_write(AT91_SMC_CSR(4), AT91_SMC_ACSS_STD | AT91_SMC_DBW_16 | AT91_SMC_BAT | AT91_SMC_WSEN | ||
254 | | AT91_SMC_NWS_(32) /* wait states */ | ||
255 | | AT91_SMC_RWSETUP_(6) /* setup time */ | ||
256 | | AT91_SMC_RWHOLD_(4) /* hold time */ | ||
257 | ); | ||
258 | |||
259 | /* must be a GPIO; ergo must trigger on both edges */ | ||
260 | status = request_irq(board->det_pin, at91_cf_irq, | ||
261 | SA_SAMPLE_RANDOM, driver_name, cf); | ||
262 | if (status < 0) | ||
263 | goto fail0; | ||
264 | |||
265 | /* | ||
266 | * The card driver will request this irq later as needed. | ||
267 | * but it causes lots of "irqNN: nobody cared" messages | ||
268 | * unless we report that we handle everything (sigh). | ||
269 | * (Note: DK board doesn't wire the IRQ pin...) | ||
270 | */ | ||
271 | if (board->irq_pin) { | ||
272 | status = request_irq(board->irq_pin, at91_cf_irq, | ||
273 | SA_SHIRQ, driver_name, cf); | ||
274 | if (status < 0) | ||
275 | goto fail0a; | ||
276 | cf->socket.pci_irq = board->irq_pin; | ||
277 | } | ||
278 | else | ||
279 | cf->socket.pci_irq = NR_IRQS + 1; | ||
280 | |||
281 | /* pcmcia layer only remaps "real" memory not iospace */ | ||
282 | cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K); | ||
283 | if (!cf->socket.io_offset) | ||
284 | goto fail1; | ||
285 | |||
286 | /* reserve CS4, CS5, and CS6 regions; but use just CS4 */ | ||
287 | if (!request_mem_region(AT91_CF_BASE, CF_SIZE, driver_name)) | ||
288 | goto fail1; | ||
289 | |||
290 | pr_info("%s: irqs det #%d, io #%d\n", driver_name, | ||
291 | board->det_pin, board->irq_pin); | ||
292 | |||
293 | cf->socket.owner = THIS_MODULE; | ||
294 | cf->socket.dev.dev = dev; | ||
295 | cf->socket.ops = &at91_cf_ops; | ||
296 | cf->socket.resource_ops = &pccard_static_ops; | ||
297 | cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP | ||
298 | | SS_CAP_MEM_ALIGN; | ||
299 | cf->socket.map_size = SZ_2K; | ||
300 | cf->socket.io[0].NumPorts = SZ_2K; | ||
301 | |||
302 | status = pcmcia_register_socket(&cf->socket); | ||
303 | if (status < 0) | ||
304 | goto fail2; | ||
305 | |||
306 | return 0; | ||
307 | |||
308 | fail2: | ||
309 | iounmap((void __iomem *) cf->socket.io_offset); | ||
310 | release_mem_region(AT91_CF_BASE, CF_SIZE); | ||
311 | fail1: | ||
312 | if (board->irq_pin) | ||
313 | free_irq(board->irq_pin, cf); | ||
314 | fail0a: | ||
315 | free_irq(board->det_pin, cf); | ||
316 | fail0: | ||
317 | at91_sys_write(AT91_EBI_CSA, csa); | ||
318 | kfree(cf); | ||
319 | return status; | ||
320 | } | ||
321 | |||
322 | static int __exit at91_cf_remove(struct device *dev) | ||
323 | { | ||
324 | struct at91_cf_socket *cf = dev_get_drvdata(dev); | ||
325 | unsigned int csa; | ||
326 | |||
327 | pcmcia_unregister_socket(&cf->socket); | ||
328 | free_irq(cf->board->irq_pin, cf); | ||
329 | free_irq(cf->board->det_pin, cf); | ||
330 | iounmap((void __iomem *) cf->socket.io_offset); | ||
331 | release_mem_region(AT91_CF_BASE, CF_SIZE); | ||
332 | |||
333 | csa = at91_sys_read(AT91_EBI_CSA); | ||
334 | at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A); | ||
335 | |||
336 | kfree(cf); | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct device_driver at91_cf_driver = { | ||
341 | .name = (char *) driver_name, | ||
342 | .bus = &platform_bus_type, | ||
343 | .probe = at91_cf_probe, | ||
344 | .remove = __exit_p(at91_cf_remove), | ||
345 | .suspend = pcmcia_socket_dev_suspend, | ||
346 | .resume = pcmcia_socket_dev_resume, | ||
347 | }; | ||
348 | |||
349 | /*--------------------------------------------------------------------------*/ | ||
350 | |||
351 | static int __init at91_cf_init(void) | ||
352 | { | ||
353 | return driver_register(&at91_cf_driver); | ||
354 | } | ||
355 | module_init(at91_cf_init); | ||
356 | |||
357 | static void __exit at91_cf_exit(void) | ||
358 | { | ||
359 | driver_unregister(&at91_cf_driver); | ||
360 | } | ||
361 | module_exit(at91_cf_exit); | ||
362 | |||
363 | MODULE_DESCRIPTION("AT91 Compact Flash Driver"); | ||
364 | MODULE_AUTHOR("David Brownell"); | ||
365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 120fa8da6392..912c03e5eb0a 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
18 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 613f2f1fbfdd..3162998579c1 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/config.h> | ||
20 | #include <linux/string.h> | 19 | #include <linux/string.h> |
21 | #include <linux/major.h> | 20 | #include <linux/major.h> |
22 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
@@ -111,9 +110,9 @@ int pcmcia_socket_dev_suspend(struct device *dev, pm_message_t state) | |||
111 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { | 110 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { |
112 | if (socket->dev.dev != dev) | 111 | if (socket->dev.dev != dev) |
113 | continue; | 112 | continue; |
114 | down(&socket->skt_sem); | 113 | mutex_lock(&socket->skt_mutex); |
115 | socket_suspend(socket); | 114 | socket_suspend(socket); |
116 | up(&socket->skt_sem); | 115 | mutex_unlock(&socket->skt_mutex); |
117 | } | 116 | } |
118 | up_read(&pcmcia_socket_list_rwsem); | 117 | up_read(&pcmcia_socket_list_rwsem); |
119 | 118 | ||
@@ -129,9 +128,9 @@ int pcmcia_socket_dev_resume(struct device *dev) | |||
129 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { | 128 | list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { |
130 | if (socket->dev.dev != dev) | 129 | if (socket->dev.dev != dev) |
131 | continue; | 130 | continue; |
132 | down(&socket->skt_sem); | 131 | mutex_lock(&socket->skt_mutex); |
133 | socket_resume(socket); | 132 | socket_resume(socket); |
134 | up(&socket->skt_sem); | 133 | mutex_unlock(&socket->skt_mutex); |
135 | } | 134 | } |
136 | up_read(&pcmcia_socket_list_rwsem); | 135 | up_read(&pcmcia_socket_list_rwsem); |
137 | 136 | ||
@@ -237,7 +236,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
237 | init_completion(&socket->socket_released); | 236 | init_completion(&socket->socket_released); |
238 | init_completion(&socket->thread_done); | 237 | init_completion(&socket->thread_done); |
239 | init_waitqueue_head(&socket->thread_wait); | 238 | init_waitqueue_head(&socket->thread_wait); |
240 | init_MUTEX(&socket->skt_sem); | 239 | mutex_init(&socket->skt_mutex); |
241 | spin_lock_init(&socket->thread_lock); | 240 | spin_lock_init(&socket->thread_lock); |
242 | 241 | ||
243 | ret = kernel_thread(pccardd, socket, CLONE_KERNEL); | 242 | ret = kernel_thread(pccardd, socket, CLONE_KERNEL); |
@@ -406,8 +405,6 @@ static void socket_shutdown(struct pcmcia_socket *s) | |||
406 | cb_free(s); | 405 | cb_free(s); |
407 | #endif | 406 | #endif |
408 | s->functions = 0; | 407 | s->functions = 0; |
409 | kfree(s->config); | ||
410 | s->config = NULL; | ||
411 | 408 | ||
412 | s->ops->get_status(s, &status); | 409 | s->ops->get_status(s, &status); |
413 | if (status & SS_POWERON) { | 410 | if (status & SS_POWERON) { |
@@ -664,7 +661,7 @@ static int pccardd(void *__skt) | |||
664 | spin_unlock_irqrestore(&skt->thread_lock, flags); | 661 | spin_unlock_irqrestore(&skt->thread_lock, flags); |
665 | 662 | ||
666 | if (events) { | 663 | if (events) { |
667 | down(&skt->skt_sem); | 664 | mutex_lock(&skt->skt_mutex); |
668 | if (events & SS_DETECT) | 665 | if (events & SS_DETECT) |
669 | socket_detect_change(skt); | 666 | socket_detect_change(skt); |
670 | if (events & SS_BATDEAD) | 667 | if (events & SS_BATDEAD) |
@@ -673,7 +670,7 @@ static int pccardd(void *__skt) | |||
673 | send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); | 670 | send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); |
674 | if (events & SS_READY) | 671 | if (events & SS_READY) |
675 | send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); | 672 | send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); |
676 | up(&skt->skt_sem); | 673 | mutex_unlock(&skt->skt_mutex); |
677 | continue; | 674 | continue; |
678 | } | 675 | } |
679 | 676 | ||
@@ -717,8 +714,8 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) | |||
717 | { | 714 | { |
718 | int ret = 0; | 715 | int ret = 0; |
719 | 716 | ||
720 | /* s->skt_sem also protects s->callback */ | 717 | /* s->skt_mutex also protects s->callback */ |
721 | down(&s->skt_sem); | 718 | mutex_lock(&s->skt_mutex); |
722 | 719 | ||
723 | if (c) { | 720 | if (c) { |
724 | /* registration */ | 721 | /* registration */ |
@@ -734,7 +731,7 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) | |||
734 | } else | 731 | } else |
735 | s->callback = NULL; | 732 | s->callback = NULL; |
736 | err: | 733 | err: |
737 | up(&s->skt_sem); | 734 | mutex_unlock(&s->skt_mutex); |
738 | 735 | ||
739 | return ret; | 736 | return ret; |
740 | } | 737 | } |
@@ -752,7 +749,7 @@ int pccard_reset_card(struct pcmcia_socket *skt) | |||
752 | 749 | ||
753 | cs_dbg(skt, 1, "resetting socket\n"); | 750 | cs_dbg(skt, 1, "resetting socket\n"); |
754 | 751 | ||
755 | down(&skt->skt_sem); | 752 | mutex_lock(&skt->skt_mutex); |
756 | do { | 753 | do { |
757 | if (!(skt->state & SOCKET_PRESENT)) { | 754 | if (!(skt->state & SOCKET_PRESENT)) { |
758 | ret = CS_NO_CARD; | 755 | ret = CS_NO_CARD; |
@@ -781,7 +778,7 @@ int pccard_reset_card(struct pcmcia_socket *skt) | |||
781 | 778 | ||
782 | ret = CS_SUCCESS; | 779 | ret = CS_SUCCESS; |
783 | } while (0); | 780 | } while (0); |
784 | up(&skt->skt_sem); | 781 | mutex_unlock(&skt->skt_mutex); |
785 | 782 | ||
786 | return ret; | 783 | return ret; |
787 | } /* reset_card */ | 784 | } /* reset_card */ |
@@ -797,7 +794,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) | |||
797 | 794 | ||
798 | cs_dbg(skt, 1, "suspending socket\n"); | 795 | cs_dbg(skt, 1, "suspending socket\n"); |
799 | 796 | ||
800 | down(&skt->skt_sem); | 797 | mutex_lock(&skt->skt_mutex); |
801 | do { | 798 | do { |
802 | if (!(skt->state & SOCKET_PRESENT)) { | 799 | if (!(skt->state & SOCKET_PRESENT)) { |
803 | ret = CS_NO_CARD; | 800 | ret = CS_NO_CARD; |
@@ -814,7 +811,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt) | |||
814 | } | 811 | } |
815 | ret = socket_suspend(skt); | 812 | ret = socket_suspend(skt); |
816 | } while (0); | 813 | } while (0); |
817 | up(&skt->skt_sem); | 814 | mutex_unlock(&skt->skt_mutex); |
818 | 815 | ||
819 | return ret; | 816 | return ret; |
820 | } /* suspend_card */ | 817 | } /* suspend_card */ |
@@ -827,7 +824,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) | |||
827 | 824 | ||
828 | cs_dbg(skt, 1, "waking up socket\n"); | 825 | cs_dbg(skt, 1, "waking up socket\n"); |
829 | 826 | ||
830 | down(&skt->skt_sem); | 827 | mutex_lock(&skt->skt_mutex); |
831 | do { | 828 | do { |
832 | if (!(skt->state & SOCKET_PRESENT)) { | 829 | if (!(skt->state & SOCKET_PRESENT)) { |
833 | ret = CS_NO_CARD; | 830 | ret = CS_NO_CARD; |
@@ -841,7 +838,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt) | |||
841 | if (!ret && skt->callback) | 838 | if (!ret && skt->callback) |
842 | skt->callback->resume(skt); | 839 | skt->callback->resume(skt); |
843 | } while (0); | 840 | } while (0); |
844 | up(&skt->skt_sem); | 841 | mutex_unlock(&skt->skt_mutex); |
845 | 842 | ||
846 | return ret; | 843 | return ret; |
847 | } /* resume_card */ | 844 | } /* resume_card */ |
@@ -855,7 +852,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) | |||
855 | 852 | ||
856 | cs_dbg(skt, 1, "user eject request\n"); | 853 | cs_dbg(skt, 1, "user eject request\n"); |
857 | 854 | ||
858 | down(&skt->skt_sem); | 855 | mutex_lock(&skt->skt_mutex); |
859 | do { | 856 | do { |
860 | if (!(skt->state & SOCKET_PRESENT)) { | 857 | if (!(skt->state & SOCKET_PRESENT)) { |
861 | ret = -ENODEV; | 858 | ret = -ENODEV; |
@@ -871,7 +868,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt) | |||
871 | socket_remove(skt); | 868 | socket_remove(skt); |
872 | ret = 0; | 869 | ret = 0; |
873 | } while (0); | 870 | } while (0); |
874 | up(&skt->skt_sem); | 871 | mutex_unlock(&skt->skt_mutex); |
875 | 872 | ||
876 | return ret; | 873 | return ret; |
877 | } /* eject_card */ | 874 | } /* eject_card */ |
@@ -884,7 +881,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) | |||
884 | 881 | ||
885 | cs_dbg(skt, 1, "user insert request\n"); | 882 | cs_dbg(skt, 1, "user insert request\n"); |
886 | 883 | ||
887 | down(&skt->skt_sem); | 884 | mutex_lock(&skt->skt_mutex); |
888 | do { | 885 | do { |
889 | if (skt->state & SOCKET_PRESENT) { | 886 | if (skt->state & SOCKET_PRESENT) { |
890 | ret = -EBUSY; | 887 | ret = -EBUSY; |
@@ -896,7 +893,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt) | |||
896 | } | 893 | } |
897 | ret = 0; | 894 | ret = 0; |
898 | } while (0); | 895 | } while (0); |
899 | up(&skt->skt_sem); | 896 | mutex_unlock(&skt->skt_mutex); |
900 | 897 | ||
901 | return ret; | 898 | return ret; |
902 | } /* insert_card */ | 899 | } /* insert_card */ |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 7b37eba35bf1..d6164cd583fd 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #ifndef _LINUX_CS_INTERNAL_H | 15 | #ifndef _LINUX_CS_INTERNAL_H |
16 | #define _LINUX_CS_INTERNAL_H | 16 | #define _LINUX_CS_INTERNAL_H |
17 | 17 | ||
18 | #include <linux/config.h> | 18 | #include <linux/kref.h> |
19 | 19 | ||
20 | /* Flags in client state */ | 20 | /* Flags in client state */ |
21 | #define CLIENT_CONFIG_LOCKED 0x0001 | 21 | #define CLIENT_CONFIG_LOCKED 0x0001 |
@@ -23,7 +23,7 @@ | |||
23 | #define CLIENT_IO_REQ 0x0004 | 23 | #define CLIENT_IO_REQ 0x0004 |
24 | #define CLIENT_UNBOUND 0x0008 | 24 | #define CLIENT_UNBOUND 0x0008 |
25 | #define CLIENT_STALE 0x0010 | 25 | #define CLIENT_STALE 0x0010 |
26 | #define CLIENT_WIN_REQ(i) (0x20<<(i)) | 26 | #define CLIENT_WIN_REQ(i) (0x1<<(i)) |
27 | #define CLIENT_CARDBUS 0x8000 | 27 | #define CLIENT_CARDBUS 0x8000 |
28 | 28 | ||
29 | #define REGION_MAGIC 0xE3C9 | 29 | #define REGION_MAGIC 0xE3C9 |
@@ -31,7 +31,7 @@ typedef struct region_t { | |||
31 | u_short region_magic; | 31 | u_short region_magic; |
32 | u_short state; | 32 | u_short state; |
33 | dev_info_t dev_info; | 33 | dev_info_t dev_info; |
34 | client_handle_t mtd; | 34 | struct pcmcia_device *mtd; |
35 | u_int MediaID; | 35 | u_int MediaID; |
36 | region_info_t info; | 36 | region_info_t info; |
37 | } region_t; | 37 | } region_t; |
@@ -40,12 +40,12 @@ typedef struct region_t { | |||
40 | 40 | ||
41 | /* Each card function gets one of these guys */ | 41 | /* Each card function gets one of these guys */ |
42 | typedef struct config_t { | 42 | typedef struct config_t { |
43 | struct kref ref; | ||
43 | u_int state; | 44 | u_int state; |
44 | u_int Attributes; | 45 | u_int Attributes; |
45 | u_int IntType; | 46 | u_int IntType; |
46 | u_int ConfigBase; | 47 | u_int ConfigBase; |
47 | u_char Status, Pin, Copy, Option, ExtStatus; | 48 | u_char Status, Pin, Copy, Option, ExtStatus; |
48 | u_int Present; | ||
49 | u_int CardValues; | 49 | u_int CardValues; |
50 | io_req_t io; | 50 | io_req_t io; |
51 | struct { | 51 | struct { |
@@ -95,12 +95,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt) | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | #define CHECK_SOCKET(s) \ | ||
99 | (((s) >= sockets) || (socket_table[s]->ops == NULL)) | ||
100 | |||
101 | #define SOCKET(h) (h->socket) | ||
102 | #define CONFIG(h) (&SOCKET(h)->config[(h)->func]) | ||
103 | |||
104 | /* In cardbus.c */ | 98 | /* In cardbus.c */ |
105 | int cb_alloc(struct pcmcia_socket *s); | 99 | int cb_alloc(struct pcmcia_socket *s); |
106 | void cb_free(struct pcmcia_socket *s); | 100 | void cb_free(struct pcmcia_socket *s); |
@@ -133,10 +127,9 @@ extern struct class_interface pccard_sysfs_interface; | |||
133 | extern struct rw_semaphore pcmcia_socket_list_rwsem; | 127 | extern struct rw_semaphore pcmcia_socket_list_rwsem; |
134 | extern struct list_head pcmcia_socket_list; | 128 | extern struct list_head pcmcia_socket_list; |
135 | int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); | 129 | int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req); |
136 | int pccard_get_configuration_info(struct pcmcia_socket *s, unsigned int function, config_info_t *config); | 130 | int pccard_get_configuration_info(struct pcmcia_socket *s, struct pcmcia_device *p_dev, config_info_t *config); |
137 | int pccard_reset_card(struct pcmcia_socket *skt); | 131 | int pccard_reset_card(struct pcmcia_socket *skt); |
138 | int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status); | 132 | int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_status_t *status); |
139 | int pccard_access_configuration_register(struct pcmcia_socket *s, unsigned int function, conf_reg_t *reg); | ||
140 | 133 | ||
141 | 134 | ||
142 | struct pcmcia_callback{ | 135 | struct pcmcia_callback{ |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index bb96ce1db08c..ae10d1eed65e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -10,10 +10,9 @@ | |||
10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | 10 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. |
11 | * | 11 | * |
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | * (C) 2003 - 2005 Dominik Brodowski | 13 | * (C) 2003 - 2006 Dominik Brodowski |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/init.h> | 18 | #include <linux/init.h> |
@@ -23,6 +22,7 @@ | |||
23 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
24 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
25 | #include <linux/firmware.h> | 24 | #include <linux/firmware.h> |
25 | #include <linux/kref.h> | ||
26 | 26 | ||
27 | #define IN_CARD_SERVICES | 27 | #define IN_CARD_SERVICES |
28 | #include <pcmcia/cs_types.h> | 28 | #include <pcmcia/cs_types.h> |
@@ -343,12 +343,19 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev) | |||
343 | put_device(&p_dev->dev); | 343 | put_device(&p_dev->dev); |
344 | } | 344 | } |
345 | 345 | ||
346 | static void pcmcia_release_function(struct kref *ref) | ||
347 | { | ||
348 | struct config_t *c = container_of(ref, struct config_t, ref); | ||
349 | kfree(c); | ||
350 | } | ||
351 | |||
346 | static void pcmcia_release_dev(struct device *dev) | 352 | static void pcmcia_release_dev(struct device *dev) |
347 | { | 353 | { |
348 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 354 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
349 | ds_dbg(1, "releasing dev %p\n", p_dev); | 355 | ds_dbg(1, "releasing dev %p\n", p_dev); |
350 | pcmcia_put_socket(p_dev->socket); | 356 | pcmcia_put_socket(p_dev->socket); |
351 | kfree(p_dev->devname); | 357 | kfree(p_dev->devname); |
358 | kref_put(&p_dev->function_config->ref, pcmcia_release_function); | ||
352 | kfree(p_dev); | 359 | kfree(p_dev); |
353 | } | 360 | } |
354 | 361 | ||
@@ -377,29 +384,12 @@ static int pcmcia_device_probe(struct device * dev) | |||
377 | p_drv = to_pcmcia_drv(dev->driver); | 384 | p_drv = to_pcmcia_drv(dev->driver); |
378 | s = p_dev->socket; | 385 | s = p_dev->socket; |
379 | 386 | ||
380 | if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) { | 387 | if ((!p_drv->probe) || (!p_dev->function_config) || |
388 | (!try_module_get(p_drv->owner))) { | ||
381 | ret = -EINVAL; | 389 | ret = -EINVAL; |
382 | goto put_dev; | 390 | goto put_dev; |
383 | } | 391 | } |
384 | 392 | ||
385 | p_dev->state &= ~CLIENT_UNBOUND; | ||
386 | |||
387 | /* set up the device configuration, if it hasn't been done before */ | ||
388 | if (!s->functions) { | ||
389 | cistpl_longlink_mfc_t mfc; | ||
390 | if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, | ||
391 | &mfc) == CS_SUCCESS) | ||
392 | s->functions = mfc.nfn; | ||
393 | else | ||
394 | s->functions = 1; | ||
395 | s->config = kzalloc(sizeof(config_t) * s->functions, | ||
396 | GFP_KERNEL); | ||
397 | if (!s->config) { | ||
398 | ret = -ENOMEM; | ||
399 | goto put_module; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | ret = p_drv->probe(p_dev); | 393 | ret = p_drv->probe(p_dev); |
404 | if (ret) | 394 | if (ret) |
405 | goto put_module; | 395 | goto put_module; |
@@ -425,15 +415,61 @@ static int pcmcia_device_probe(struct device * dev) | |||
425 | } | 415 | } |
426 | 416 | ||
427 | 417 | ||
418 | /* | ||
419 | * Removes a PCMCIA card from the device tree and socket list. | ||
420 | */ | ||
421 | static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *leftover) | ||
422 | { | ||
423 | struct pcmcia_device *p_dev; | ||
424 | struct pcmcia_device *tmp; | ||
425 | unsigned long flags; | ||
426 | |||
427 | ds_dbg(2, "unbind_request(%d)\n", s->sock); | ||
428 | |||
429 | |||
430 | if (!leftover) | ||
431 | s->device_count = 0; | ||
432 | else | ||
433 | s->device_count = 1; | ||
434 | |||
435 | /* unregister all pcmcia_devices registered with this socket, except leftover */ | ||
436 | list_for_each_entry_safe(p_dev, tmp, &s->devices_list, socket_device_list) { | ||
437 | if (p_dev == leftover) | ||
438 | continue; | ||
439 | |||
440 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
441 | list_del(&p_dev->socket_device_list); | ||
442 | p_dev->_removed=1; | ||
443 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
444 | |||
445 | device_unregister(&p_dev->dev); | ||
446 | } | ||
447 | |||
448 | return; | ||
449 | } | ||
450 | |||
451 | |||
428 | static int pcmcia_device_remove(struct device * dev) | 452 | static int pcmcia_device_remove(struct device * dev) |
429 | { | 453 | { |
430 | struct pcmcia_device *p_dev; | 454 | struct pcmcia_device *p_dev; |
431 | struct pcmcia_driver *p_drv; | 455 | struct pcmcia_driver *p_drv; |
456 | struct pcmcia_device_id *did; | ||
432 | int i; | 457 | int i; |
433 | 458 | ||
434 | /* detach the "instance" */ | ||
435 | p_dev = to_pcmcia_dev(dev); | 459 | p_dev = to_pcmcia_dev(dev); |
436 | p_drv = to_pcmcia_drv(dev->driver); | 460 | p_drv = to_pcmcia_drv(dev->driver); |
461 | |||
462 | /* If we're removing the primary module driving a | ||
463 | * pseudo multi-function card, we need to unbind | ||
464 | * all devices | ||
465 | */ | ||
466 | did = (struct pcmcia_device_id *) p_dev->dev.driver_data; | ||
467 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && | ||
468 | (p_dev->socket->device_count != 0) && | ||
469 | (p_dev->device_no == 0)) | ||
470 | pcmcia_card_remove(p_dev->socket, p_dev); | ||
471 | |||
472 | /* detach the "instance" */ | ||
437 | if (!p_drv) | 473 | if (!p_drv) |
438 | return 0; | 474 | return 0; |
439 | 475 | ||
@@ -441,17 +477,16 @@ static int pcmcia_device_remove(struct device * dev) | |||
441 | p_drv->remove(p_dev); | 477 | p_drv->remove(p_dev); |
442 | 478 | ||
443 | /* check for proper unloading */ | 479 | /* check for proper unloading */ |
444 | if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) | 480 | if (p_dev->_irq || p_dev->_io || p_dev->_locked) |
445 | printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", | 481 | printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", |
446 | p_drv->drv.name); | 482 | p_drv->drv.name); |
447 | 483 | ||
448 | for (i = 0; i < MAX_WIN; i++) | 484 | for (i = 0; i < MAX_WIN; i++) |
449 | if (p_dev->state & CLIENT_WIN_REQ(i)) | 485 | if (p_dev->_win & CLIENT_WIN_REQ(i)) |
450 | printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", | 486 | printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", |
451 | p_drv->drv.name); | 487 | p_drv->drv.name); |
452 | 488 | ||
453 | /* references from pcmcia_probe_device */ | 489 | /* references from pcmcia_probe_device */ |
454 | p_dev->state = CLIENT_UNBOUND; | ||
455 | pcmcia_put_dev(p_dev); | 490 | pcmcia_put_dev(p_dev); |
456 | module_put(p_drv->owner); | 491 | module_put(p_drv->owner); |
457 | 492 | ||
@@ -460,37 +495,6 @@ static int pcmcia_device_remove(struct device * dev) | |||
460 | 495 | ||
461 | 496 | ||
462 | /* | 497 | /* |
463 | * Removes a PCMCIA card from the device tree and socket list. | ||
464 | */ | ||
465 | static void pcmcia_card_remove(struct pcmcia_socket *s) | ||
466 | { | ||
467 | struct pcmcia_device *p_dev; | ||
468 | unsigned long flags; | ||
469 | |||
470 | ds_dbg(2, "unbind_request(%d)\n", s->sock); | ||
471 | |||
472 | s->device_count = 0; | ||
473 | |||
474 | for (;;) { | ||
475 | /* unregister all pcmcia_devices registered with this socket*/ | ||
476 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
477 | if (list_empty(&s->devices_list)) { | ||
478 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
479 | return; | ||
480 | } | ||
481 | p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list); | ||
482 | list_del(&p_dev->socket_device_list); | ||
483 | p_dev->state |= CLIENT_STALE; | ||
484 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
485 | |||
486 | device_unregister(&p_dev->dev); | ||
487 | } | ||
488 | |||
489 | return; | ||
490 | } /* unbind_request */ | ||
491 | |||
492 | |||
493 | /* | ||
494 | * pcmcia_device_query -- determine information about a pcmcia device | 498 | * pcmcia_device_query -- determine information about a pcmcia device |
495 | */ | 499 | */ |
496 | static int pcmcia_device_query(struct pcmcia_device *p_dev) | 500 | static int pcmcia_device_query(struct pcmcia_device *p_dev) |
@@ -546,7 +550,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
546 | tmp = vers1->str + vers1->ofs[i]; | 550 | tmp = vers1->str + vers1->ofs[i]; |
547 | 551 | ||
548 | length = strlen(tmp) + 1; | 552 | length = strlen(tmp) + 1; |
549 | if ((length < 3) || (length > 255)) | 553 | if ((length < 2) || (length > 255)) |
550 | continue; | 554 | continue; |
551 | 555 | ||
552 | p_dev->prod_id[i] = kmalloc(sizeof(char) * length, | 556 | p_dev->prod_id[i] = kmalloc(sizeof(char) * length, |
@@ -571,11 +575,11 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev) | |||
571 | * won't work, this doesn't matter much at the moment: the driver core doesn't | 575 | * won't work, this doesn't matter much at the moment: the driver core doesn't |
572 | * support it either. | 576 | * support it either. |
573 | */ | 577 | */ |
574 | static DECLARE_MUTEX(device_add_lock); | 578 | static DEFINE_MUTEX(device_add_lock); |
575 | 579 | ||
576 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) | 580 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function) |
577 | { | 581 | { |
578 | struct pcmcia_device *p_dev; | 582 | struct pcmcia_device *p_dev, *tmp_dev; |
579 | unsigned long flags; | 583 | unsigned long flags; |
580 | int bus_id_len; | 584 | int bus_id_len; |
581 | 585 | ||
@@ -583,7 +587,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
583 | if (!s) | 587 | if (!s) |
584 | return NULL; | 588 | return NULL; |
585 | 589 | ||
586 | down(&device_add_lock); | 590 | mutex_lock(&device_add_lock); |
587 | 591 | ||
588 | /* max of 2 devices per card */ | 592 | /* max of 2 devices per card */ |
589 | if (s->device_count == 2) | 593 | if (s->device_count == 2) |
@@ -596,6 +600,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
596 | p_dev->socket = s; | 600 | p_dev->socket = s; |
597 | p_dev->device_no = (s->device_count++); | 601 | p_dev->device_no = (s->device_count++); |
598 | p_dev->func = function; | 602 | p_dev->func = function; |
603 | if (s->functions <= function) | ||
604 | s->functions = function + 1; | ||
599 | 605 | ||
600 | p_dev->dev.bus = &pcmcia_bus_type; | 606 | p_dev->dev.bus = &pcmcia_bus_type; |
601 | p_dev->dev.parent = s->dev.dev; | 607 | p_dev->dev.parent = s->dev.dev; |
@@ -608,36 +614,55 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
608 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); | 614 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); |
609 | 615 | ||
610 | /* compat */ | 616 | /* compat */ |
611 | p_dev->state = CLIENT_UNBOUND; | 617 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
618 | |||
619 | /* | ||
620 | * p_dev->function_config must be the same for all card functions. | ||
621 | * Note that this is serialized by the device_add_lock, so that | ||
622 | * only one such struct will be created. | ||
623 | */ | ||
624 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) | ||
625 | if (p_dev->func == tmp_dev->func) { | ||
626 | p_dev->function_config = tmp_dev->function_config; | ||
627 | kref_get(&p_dev->function_config->ref); | ||
628 | } | ||
612 | 629 | ||
613 | /* Add to the list in pcmcia_bus_socket */ | 630 | /* Add to the list in pcmcia_bus_socket */ |
614 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
615 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); | 631 | list_add_tail(&p_dev->socket_device_list, &s->devices_list); |
632 | |||
616 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 633 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
617 | 634 | ||
635 | if (!p_dev->function_config) { | ||
636 | p_dev->function_config = kzalloc(sizeof(struct config_t), | ||
637 | GFP_KERNEL); | ||
638 | if (!p_dev->function_config) | ||
639 | goto err_unreg; | ||
640 | kref_init(&p_dev->function_config->ref); | ||
641 | } | ||
642 | |||
618 | printk(KERN_NOTICE "pcmcia: registering new device %s\n", | 643 | printk(KERN_NOTICE "pcmcia: registering new device %s\n", |
619 | p_dev->devname); | 644 | p_dev->devname); |
620 | 645 | ||
621 | pcmcia_device_query(p_dev); | 646 | pcmcia_device_query(p_dev); |
622 | 647 | ||
623 | if (device_register(&p_dev->dev)) { | 648 | if (device_register(&p_dev->dev)) |
624 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 649 | goto err_unreg; |
625 | list_del(&p_dev->socket_device_list); | ||
626 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
627 | |||
628 | goto err_free; | ||
629 | } | ||
630 | 650 | ||
631 | up(&device_add_lock); | 651 | mutex_unlock(&device_add_lock); |
632 | 652 | ||
633 | return p_dev; | 653 | return p_dev; |
634 | 654 | ||
655 | err_unreg: | ||
656 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
657 | list_del(&p_dev->socket_device_list); | ||
658 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
659 | |||
635 | err_free: | 660 | err_free: |
636 | kfree(p_dev->devname); | 661 | kfree(p_dev->devname); |
637 | kfree(p_dev); | 662 | kfree(p_dev); |
638 | s->device_count--; | 663 | s->device_count--; |
639 | err_put: | 664 | err_put: |
640 | up(&device_add_lock); | 665 | mutex_unlock(&device_add_lock); |
641 | pcmcia_put_socket(s); | 666 | pcmcia_put_socket(s); |
642 | 667 | ||
643 | return NULL; | 668 | return NULL; |
@@ -696,7 +721,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) | |||
696 | int no_devices=0; | 721 | int no_devices=0; |
697 | unsigned long flags; | 722 | unsigned long flags; |
698 | 723 | ||
699 | /* must be called with skt_sem held */ | 724 | /* must be called with skt_mutex held */ |
700 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 725 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
701 | if (list_empty(&skt->devices_list)) | 726 | if (list_empty(&skt->devices_list)) |
702 | no_devices=1; | 727 | no_devices=1; |
@@ -819,9 +844,11 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { | |||
819 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); | 844 | struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); |
820 | struct pcmcia_device_id *did = p_drv->id_table; | 845 | struct pcmcia_device_id *did = p_drv->id_table; |
821 | 846 | ||
847 | #ifdef CONFIG_PCMCIA_IOCTL | ||
822 | /* matching by cardmgr */ | 848 | /* matching by cardmgr */ |
823 | if (p_dev->cardmgr == p_drv) | 849 | if (p_dev->cardmgr == p_drv) |
824 | return 1; | 850 | return 1; |
851 | #endif | ||
825 | 852 | ||
826 | while (did && did->match_flags) { | 853 | while (did && did->match_flags) { |
827 | if (pcmcia_devmatch(p_dev, did)) | 854 | if (pcmcia_devmatch(p_dev, did)) |
@@ -927,7 +954,7 @@ static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute | |||
927 | { | 954 | { |
928 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 955 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
929 | 956 | ||
930 | if (p_dev->dev.power.power_state.event != PM_EVENT_ON) | 957 | if (p_dev->suspended) |
931 | return sprintf(buf, "off\n"); | 958 | return sprintf(buf, "off\n"); |
932 | else | 959 | else |
933 | return sprintf(buf, "on\n"); | 960 | return sprintf(buf, "on\n"); |
@@ -942,11 +969,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute | |||
942 | if (!count) | 969 | if (!count) |
943 | return -EINVAL; | 970 | return -EINVAL; |
944 | 971 | ||
945 | if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) && | 972 | if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) |
946 | (!strncmp(buf, "off", 3))) | ||
947 | ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); | 973 | ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); |
948 | else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) && | 974 | else if (p_dev->suspended && !strncmp(buf, "on", 2)) |
949 | (!strncmp(buf, "on", 2))) | ||
950 | dpm_runtime_resume(dev); | 975 | dpm_runtime_resume(dev); |
951 | 976 | ||
952 | return ret ? ret : count; | 977 | return ret ? ret : count; |
@@ -982,9 +1007,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
982 | if (!count) | 1007 | if (!count) |
983 | return -EINVAL; | 1008 | return -EINVAL; |
984 | 1009 | ||
985 | down(&p_dev->socket->skt_sem); | 1010 | mutex_lock(&p_dev->socket->skt_mutex); |
986 | p_dev->allow_func_id_match = 1; | 1011 | p_dev->allow_func_id_match = 1; |
987 | up(&p_dev->socket->skt_sem); | 1012 | mutex_unlock(&p_dev->socket->skt_mutex); |
988 | 1013 | ||
989 | bus_rescan_devices(&pcmcia_bus_type); | 1014 | bus_rescan_devices(&pcmcia_bus_type); |
990 | 1015 | ||
@@ -1012,14 +1037,27 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) | |||
1012 | { | 1037 | { |
1013 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 1038 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
1014 | struct pcmcia_driver *p_drv = NULL; | 1039 | struct pcmcia_driver *p_drv = NULL; |
1040 | int ret = 0; | ||
1015 | 1041 | ||
1016 | if (dev->driver) | 1042 | if (dev->driver) |
1017 | p_drv = to_pcmcia_drv(dev->driver); | 1043 | p_drv = to_pcmcia_drv(dev->driver); |
1018 | 1044 | ||
1019 | if (p_drv && p_drv->suspend) | 1045 | if (!p_drv) |
1020 | return p_drv->suspend(p_dev); | 1046 | goto out; |
1021 | 1047 | ||
1022 | return 0; | 1048 | if (p_drv->suspend) { |
1049 | ret = p_drv->suspend(p_dev); | ||
1050 | if (ret) | ||
1051 | goto out; | ||
1052 | } | ||
1053 | |||
1054 | if (p_dev->device_no == p_dev->func) | ||
1055 | pcmcia_release_configuration(p_dev); | ||
1056 | |||
1057 | out: | ||
1058 | if (!ret) | ||
1059 | p_dev->suspended = 1; | ||
1060 | return ret; | ||
1023 | } | 1061 | } |
1024 | 1062 | ||
1025 | 1063 | ||
@@ -1027,14 +1065,27 @@ static int pcmcia_dev_resume(struct device * dev) | |||
1027 | { | 1065 | { |
1028 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 1066 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
1029 | struct pcmcia_driver *p_drv = NULL; | 1067 | struct pcmcia_driver *p_drv = NULL; |
1068 | int ret = 0; | ||
1030 | 1069 | ||
1031 | if (dev->driver) | 1070 | if (dev->driver) |
1032 | p_drv = to_pcmcia_drv(dev->driver); | 1071 | p_drv = to_pcmcia_drv(dev->driver); |
1033 | 1072 | ||
1034 | if (p_drv && p_drv->resume) | 1073 | if (!p_drv) |
1035 | return p_drv->resume(p_dev); | 1074 | goto out; |
1036 | 1075 | ||
1037 | return 0; | 1076 | if (p_dev->device_no == p_dev->func) { |
1077 | ret = pcmcia_request_configuration(p_dev, &p_dev->conf); | ||
1078 | if (ret) | ||
1079 | goto out; | ||
1080 | } | ||
1081 | |||
1082 | if (p_drv->resume) | ||
1083 | ret = p_drv->resume(p_dev); | ||
1084 | |||
1085 | out: | ||
1086 | if (!ret) | ||
1087 | p_dev->suspended = 0; | ||
1088 | return ret; | ||
1038 | } | 1089 | } |
1039 | 1090 | ||
1040 | 1091 | ||
@@ -1100,7 +1151,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1100 | switch (event) { | 1151 | switch (event) { |
1101 | case CS_EVENT_CARD_REMOVAL: | 1152 | case CS_EVENT_CARD_REMOVAL: |
1102 | s->pcmcia_state.present = 0; | 1153 | s->pcmcia_state.present = 0; |
1103 | pcmcia_card_remove(skt); | 1154 | pcmcia_card_remove(skt, NULL); |
1104 | handle_event(skt, event); | 1155 | handle_event(skt, event); |
1105 | break; | 1156 | break; |
1106 | 1157 | ||
@@ -1128,6 +1179,32 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
1128 | } /* ds_event */ | 1179 | } /* ds_event */ |
1129 | 1180 | ||
1130 | 1181 | ||
1182 | struct pcmcia_device * pcmcia_dev_present(struct pcmcia_device *_p_dev) | ||
1183 | { | ||
1184 | struct pcmcia_device *p_dev; | ||
1185 | struct pcmcia_device *ret = NULL; | ||
1186 | |||
1187 | p_dev = pcmcia_get_dev(_p_dev); | ||
1188 | if (!p_dev) | ||
1189 | return NULL; | ||
1190 | |||
1191 | if (!p_dev->socket->pcmcia_state.present) | ||
1192 | goto out; | ||
1193 | |||
1194 | if (p_dev->_removed) | ||
1195 | goto out; | ||
1196 | |||
1197 | if (p_dev->suspended) | ||
1198 | goto out; | ||
1199 | |||
1200 | ret = p_dev; | ||
1201 | out: | ||
1202 | pcmcia_put_dev(p_dev); | ||
1203 | return ret; | ||
1204 | } | ||
1205 | EXPORT_SYMBOL(pcmcia_dev_present); | ||
1206 | |||
1207 | |||
1131 | static struct pcmcia_callback pcmcia_bus_callback = { | 1208 | static struct pcmcia_callback pcmcia_bus_callback = { |
1132 | .owner = THIS_MODULE, | 1209 | .owner = THIS_MODULE, |
1133 | .event = ds_event, | 1210 | .event = ds_event, |
diff --git a/drivers/pcmcia/ds_internal.h b/drivers/pcmcia/ds_internal.h index d359bd25a51c..3a2b25e6ed73 100644 --- a/drivers/pcmcia/ds_internal.h +++ b/drivers/pcmcia/ds_internal.h | |||
@@ -8,6 +8,8 @@ extern void pcmcia_put_dev(struct pcmcia_device *p_dev); | |||
8 | 8 | ||
9 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function); | 9 | struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int function); |
10 | 10 | ||
11 | extern int pcmcia_release_configuration(struct pcmcia_device *p_dev); | ||
12 | |||
11 | #ifdef CONFIG_PCMCIA_IOCTL | 13 | #ifdef CONFIG_PCMCIA_IOCTL |
12 | extern void __init pcmcia_setup_ioctl(void); | 14 | extern void __init pcmcia_setup_ioctl(void); |
13 | extern void __exit pcmcia_cleanup_ioctl(void); | 15 | extern void __exit pcmcia_cleanup_ioctl(void); |
@@ -15,7 +17,7 @@ extern void handle_event(struct pcmcia_socket *s, event_t event); | |||
15 | extern int handle_request(struct pcmcia_socket *s, event_t event); | 17 | extern int handle_request(struct pcmcia_socket *s, event_t event); |
16 | #else | 18 | #else |
17 | static inline void __init pcmcia_setup_ioctl(void) { return; } | 19 | static inline void __init pcmcia_setup_ioctl(void) { return; } |
18 | static inline void __init pcmcia_cleanup_ioctl(void) { return; } | 20 | static inline void __exit pcmcia_cleanup_ioctl(void) { return; } |
19 | static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; } | 21 | static inline void handle_event(struct pcmcia_socket *s, event_t event) { return; } |
20 | static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; } | 22 | static inline int handle_request(struct pcmcia_socket *s, event_t event) { return CS_SUCCESS; } |
21 | #endif | 23 | #endif |
diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 7979c85df3dc..d5f03a338c6c 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c | |||
@@ -10,7 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/config.h> | ||
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
16 | #include <linux/init.h> | 15 | #include <linux/init.h> |
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 35a92d1e4945..bd0308e89815 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/config.h> | ||
38 | #include <linux/types.h> | 37 | #include <linux/types.h> |
39 | #include <linux/fcntl.h> | 38 | #include <linux/fcntl.h> |
40 | #include <linux/string.h> | 39 | #include <linux/string.h> |
diff --git a/drivers/pcmcia/pcmcia_compat.c b/drivers/pcmcia/pcmcia_compat.c deleted file mode 100644 index ebb161c4f819..000000000000 --- a/drivers/pcmcia/pcmcia_compat.c +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /* | ||
2 | * PCMCIA 16-bit compatibility functions | ||
3 | * | ||
4 | * The initial developer of the original code is David A. Hinds | ||
5 | * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds | ||
6 | * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. | ||
7 | * | ||
8 | * Copyright (C) 2004 Dominik Brodowski | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #define IN_CARD_SERVICES | ||
21 | #include <pcmcia/cs_types.h> | ||
22 | #include <pcmcia/cs.h> | ||
23 | #include <pcmcia/bulkmem.h> | ||
24 | #include <pcmcia/cistpl.h> | ||
25 | #include <pcmcia/ds.h> | ||
26 | #include <pcmcia/ss.h> | ||
27 | |||
28 | #include "cs_internal.h" | ||
29 | |||
30 | int pcmcia_get_first_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) | ||
31 | { | ||
32 | return pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple); | ||
33 | } | ||
34 | EXPORT_SYMBOL(pcmcia_get_first_tuple); | ||
35 | |||
36 | int pcmcia_get_next_tuple(struct pcmcia_device *p_dev, tuple_t *tuple) | ||
37 | { | ||
38 | return pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple); | ||
39 | } | ||
40 | EXPORT_SYMBOL(pcmcia_get_next_tuple); | ||
41 | |||
42 | int pcmcia_get_tuple_data(struct pcmcia_device *p_dev, tuple_t *tuple) | ||
43 | { | ||
44 | return pccard_get_tuple_data(p_dev->socket, tuple); | ||
45 | } | ||
46 | EXPORT_SYMBOL(pcmcia_get_tuple_data); | ||
47 | |||
48 | int pcmcia_parse_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, cisparse_t *parse) | ||
49 | { | ||
50 | return pccard_parse_tuple(tuple, parse); | ||
51 | } | ||
52 | EXPORT_SYMBOL(pcmcia_parse_tuple); | ||
53 | |||
54 | int pcmcia_validate_cis(struct pcmcia_device *p_dev, cisinfo_t *info) | ||
55 | { | ||
56 | return pccard_validate_cis(p_dev->socket, p_dev->func, info); | ||
57 | } | ||
58 | EXPORT_SYMBOL(pcmcia_validate_cis); | ||
59 | |||
60 | |||
61 | int pcmcia_reset_card(struct pcmcia_device *p_dev, client_req_t *req) | ||
62 | { | ||
63 | return pccard_reset_card(p_dev->socket); | ||
64 | } | ||
65 | EXPORT_SYMBOL(pcmcia_reset_card); | ||
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 80969f7e7a0b..c53db7ceda5e 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -18,7 +18,6 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | 20 | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
24 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -70,10 +69,26 @@ extern int ds_pc_debug; | |||
70 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) | 69 | #define ds_dbg(lvl, fmt, arg...) do { } while (0) |
71 | #endif | 70 | #endif |
72 | 71 | ||
72 | static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s, | ||
73 | unsigned int function) | ||
74 | { | ||
75 | struct pcmcia_device *p_dev = NULL; | ||
76 | unsigned long flags; | ||
77 | |||
78 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | ||
79 | list_for_each_entry(p_dev, &s->devices_list, socket_device_list) { | ||
80 | if (p_dev->func == function) { | ||
81 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
82 | return pcmcia_get_dev(p_dev); | ||
83 | } | ||
84 | } | ||
85 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | ||
86 | return NULL; | ||
87 | } | ||
73 | 88 | ||
74 | /* backwards-compatible accessing of driver --- by name! */ | 89 | /* backwards-compatible accessing of driver --- by name! */ |
75 | 90 | ||
76 | static struct pcmcia_driver * get_pcmcia_driver (dev_info_t *dev_info) | 91 | static struct pcmcia_driver *get_pcmcia_driver(dev_info_t *dev_info) |
77 | { | 92 | { |
78 | struct device_driver *drv; | 93 | struct device_driver *drv; |
79 | struct pcmcia_driver *p_drv; | 94 | struct pcmcia_driver *p_drv; |
@@ -214,7 +229,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info) | |||
214 | * by userspace before, we need to | 229 | * by userspace before, we need to |
215 | * return the "instance". */ | 230 | * return the "instance". */ |
216 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 231 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
217 | bind_info->instance = p_dev->instance; | 232 | bind_info->instance = p_dev; |
218 | ret = -EBUSY; | 233 | ret = -EBUSY; |
219 | goto err_put_module; | 234 | goto err_put_module; |
220 | } else { | 235 | } else { |
@@ -253,9 +268,9 @@ rescan: | |||
253 | /* | 268 | /* |
254 | * Prevent this racing with a card insertion. | 269 | * Prevent this racing with a card insertion. |
255 | */ | 270 | */ |
256 | down(&s->skt_sem); | 271 | mutex_lock(&s->skt_mutex); |
257 | bus_rescan_devices(&pcmcia_bus_type); | 272 | bus_rescan_devices(&pcmcia_bus_type); |
258 | up(&s->skt_sem); | 273 | mutex_unlock(&s->skt_mutex); |
259 | 274 | ||
260 | /* check whether the driver indeed matched. I don't care if this | 275 | /* check whether the driver indeed matched. I don't care if this |
261 | * is racy or not, because it can only happen on cardmgr access | 276 | * is racy or not, because it can only happen on cardmgr access |
@@ -289,6 +304,7 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int | |||
289 | { | 304 | { |
290 | dev_node_t *node; | 305 | dev_node_t *node; |
291 | struct pcmcia_device *p_dev; | 306 | struct pcmcia_device *p_dev; |
307 | struct pcmcia_driver *p_drv; | ||
292 | unsigned long flags; | 308 | unsigned long flags; |
293 | int ret = 0; | 309 | int ret = 0; |
294 | 310 | ||
@@ -343,16 +359,16 @@ static int get_device_info(struct pcmcia_socket *s, bind_info_t *bind_info, int | |||
343 | found: | 359 | found: |
344 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 360 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
345 | 361 | ||
346 | if ((!p_dev->instance) || | 362 | p_drv = to_pcmcia_drv(p_dev->dev.driver); |
347 | (p_dev->instance->state & DEV_CONFIG_PENDING)) { | 363 | if (p_drv && !p_dev->_locked) { |
348 | ret = -EAGAIN; | 364 | ret = -EAGAIN; |
349 | goto err_put; | 365 | goto err_put; |
350 | } | 366 | } |
351 | 367 | ||
352 | if (first) | 368 | if (first) |
353 | node = p_dev->instance->dev; | 369 | node = p_dev->dev_node; |
354 | else | 370 | else |
355 | for (node = p_dev->instance->dev; node; node = node->next) | 371 | for (node = p_dev->dev_node; node; node = node->next) |
356 | if (node == bind_info->next) | 372 | if (node == bind_info->next) |
357 | break; | 373 | break; |
358 | if (!node) { | 374 | if (!node) { |
@@ -583,14 +599,16 @@ static int ds_ioctl(struct inode * inode, struct file * file, | |||
583 | if (buf->config.Function && | 599 | if (buf->config.Function && |
584 | (buf->config.Function >= s->functions)) | 600 | (buf->config.Function >= s->functions)) |
585 | ret = CS_BAD_ARGS; | 601 | ret = CS_BAD_ARGS; |
586 | else | 602 | else { |
587 | ret = pccard_get_configuration_info(s, | 603 | struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function); |
588 | buf->config.Function, &buf->config); | 604 | ret = pccard_get_configuration_info(s, p_dev, &buf->config); |
605 | pcmcia_put_dev(p_dev); | ||
606 | } | ||
589 | break; | 607 | break; |
590 | case DS_GET_FIRST_TUPLE: | 608 | case DS_GET_FIRST_TUPLE: |
591 | down(&s->skt_sem); | 609 | mutex_lock(&s->skt_mutex); |
592 | pcmcia_validate_mem(s); | 610 | pcmcia_validate_mem(s); |
593 | up(&s->skt_sem); | 611 | mutex_unlock(&s->skt_mutex); |
594 | ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple); | 612 | ret = pccard_get_first_tuple(s, BIND_FN_ALL, &buf->tuple); |
595 | break; | 613 | break; |
596 | case DS_GET_NEXT_TUPLE: | 614 | case DS_GET_NEXT_TUPLE: |
@@ -609,16 +627,19 @@ static int ds_ioctl(struct inode * inode, struct file * file, | |||
609 | ret = pccard_reset_card(s); | 627 | ret = pccard_reset_card(s); |
610 | break; | 628 | break; |
611 | case DS_GET_STATUS: | 629 | case DS_GET_STATUS: |
612 | if (buf->status.Function && | 630 | if (buf->status.Function && |
613 | (buf->status.Function >= s->functions)) | 631 | (buf->status.Function >= s->functions)) |
614 | ret = CS_BAD_ARGS; | 632 | ret = CS_BAD_ARGS; |
615 | else | 633 | else { |
616 | ret = pccard_get_status(s, buf->status.Function, &buf->status); | 634 | struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function); |
617 | break; | 635 | ret = pccard_get_status(s, p_dev, &buf->status); |
636 | pcmcia_put_dev(p_dev); | ||
637 | } | ||
638 | break; | ||
618 | case DS_VALIDATE_CIS: | 639 | case DS_VALIDATE_CIS: |
619 | down(&s->skt_sem); | 640 | mutex_lock(&s->skt_mutex); |
620 | pcmcia_validate_mem(s); | 641 | pcmcia_validate_mem(s); |
621 | up(&s->skt_sem); | 642 | mutex_unlock(&s->skt_mutex); |
622 | ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); | 643 | ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo); |
623 | break; | 644 | break; |
624 | case DS_SUSPEND_CARD: | 645 | case DS_SUSPEND_CARD: |
@@ -638,12 +659,16 @@ static int ds_ioctl(struct inode * inode, struct file * file, | |||
638 | err = -EPERM; | 659 | err = -EPERM; |
639 | goto free_out; | 660 | goto free_out; |
640 | } | 661 | } |
641 | if (buf->conf_reg.Function && | 662 | |
642 | (buf->conf_reg.Function >= s->functions)) | 663 | ret = CS_BAD_ARGS; |
643 | ret = CS_BAD_ARGS; | 664 | |
644 | else | 665 | if (!(buf->conf_reg.Function && |
645 | ret = pccard_access_configuration_register(s, | 666 | (buf->conf_reg.Function >= s->functions))) { |
646 | buf->conf_reg.Function, &buf->conf_reg); | 667 | struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->conf_reg.Function); |
668 | if (p_dev) | ||
669 | ret = pcmcia_access_configuration_register(p_dev, &buf->conf_reg); | ||
670 | pcmcia_put_dev(p_dev); | ||
671 | } | ||
647 | break; | 672 | break; |
648 | case DS_GET_FIRST_REGION: | 673 | case DS_GET_FIRST_REGION: |
649 | case DS_GET_NEXT_REGION: | 674 | case DS_GET_NEXT_REGION: |
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 89022ad5b520..45063b4e5b78 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
@@ -14,7 +14,6 @@ | |||
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/config.h> | ||
18 | #include <linux/module.h> | 17 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
@@ -89,7 +88,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, | |||
89 | } | 88 | } |
90 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { | 89 | if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) { |
91 | *base = s->io_offset | (*base & 0x0fff); | 90 | *base = s->io_offset | (*base & 0x0fff); |
92 | s->io[0].Attributes = attr; | 91 | s->io[0].res->flags = (s->io[0].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); |
93 | return 0; | 92 | return 0; |
94 | } | 93 | } |
95 | /* Check for an already-allocated window that must conflict with | 94 | /* Check for an already-allocated window that must conflict with |
@@ -97,38 +96,36 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, | |||
97 | * potential conflicts, just the most obvious ones. | 96 | * potential conflicts, just the most obvious ones. |
98 | */ | 97 | */ |
99 | for (i = 0; i < MAX_IO_WIN; i++) | 98 | for (i = 0; i < MAX_IO_WIN; i++) |
100 | if ((s->io[i].NumPorts != 0) && | 99 | if ((s->io[i].res) && |
101 | ((s->io[i].BasePort & (align-1)) == *base)) | 100 | ((s->io[i].res->start & (align-1)) == *base)) |
102 | return 1; | 101 | return 1; |
103 | for (i = 0; i < MAX_IO_WIN; i++) { | 102 | for (i = 0; i < MAX_IO_WIN; i++) { |
104 | if (s->io[i].NumPorts == 0) { | 103 | if (!s->io[i].res) { |
105 | s->io[i].res = pcmcia_find_io_region(*base, num, align, s); | 104 | s->io[i].res = pcmcia_find_io_region(*base, num, align, s); |
106 | if (s->io[i].res) { | 105 | if (s->io[i].res) { |
107 | s->io[i].Attributes = attr; | 106 | *base = s->io[i].res->start; |
108 | s->io[i].BasePort = *base = s->io[i].res->start; | 107 | s->io[i].res->flags = (s->io[i].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS); |
109 | s->io[i].NumPorts = s->io[i].InUse = num; | 108 | s->io[i].InUse = num; |
110 | break; | 109 | break; |
111 | } else | 110 | } else |
112 | return 1; | 111 | return 1; |
113 | } else if (s->io[i].Attributes != attr) | 112 | } else if ((s->io[i].res->flags & IORESOURCE_BITS) != (attr & IORESOURCE_BITS)) |
114 | continue; | 113 | continue; |
115 | /* Try to extend top of window */ | 114 | /* Try to extend top of window */ |
116 | try = s->io[i].BasePort + s->io[i].NumPorts; | 115 | try = s->io[i].res->end + 1; |
117 | if ((*base == 0) || (*base == try)) | 116 | if ((*base == 0) || (*base == try)) |
118 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, | 117 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start, |
119 | s->io[i].res->end + num, s) == 0) { | 118 | s->io[i].res->end + num, s) == 0) { |
120 | *base = try; | 119 | *base = try; |
121 | s->io[i].NumPorts += num; | ||
122 | s->io[i].InUse += num; | 120 | s->io[i].InUse += num; |
123 | break; | 121 | break; |
124 | } | 122 | } |
125 | /* Try to extend bottom of window */ | 123 | /* Try to extend bottom of window */ |
126 | try = s->io[i].BasePort - num; | 124 | try = s->io[i].res->start - num; |
127 | if ((*base == 0) || (*base == try)) | 125 | if ((*base == 0) || (*base == try)) |
128 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, | 126 | if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num, |
129 | s->io[i].res->end, s) == 0) { | 127 | s->io[i].res->end, s) == 0) { |
130 | s->io[i].BasePort = *base = try; | 128 | *base = try; |
131 | s->io[i].NumPorts += num; | ||
132 | s->io[i].InUse += num; | 129 | s->io[i].InUse += num; |
133 | break; | 130 | break; |
134 | } | 131 | } |
@@ -143,12 +140,13 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, | |||
143 | int i; | 140 | int i; |
144 | 141 | ||
145 | for (i = 0; i < MAX_IO_WIN; i++) { | 142 | for (i = 0; i < MAX_IO_WIN; i++) { |
146 | if ((s->io[i].BasePort <= base) && | 143 | if (!s->io[i].res) |
147 | (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) { | 144 | continue; |
145 | if ((s->io[i].res->start <= base) && | ||
146 | (s->io[i].res->end >= base+num-1)) { | ||
148 | s->io[i].InUse -= num; | 147 | s->io[i].InUse -= num; |
149 | /* Free the window if no one else is using it */ | 148 | /* Free the window if no one else is using it */ |
150 | if (s->io[i].InUse == 0) { | 149 | if (s->io[i].InUse == 0) { |
151 | s->io[i].NumPorts = 0; | ||
152 | release_resource(s->io[i].res); | 150 | release_resource(s->io[i].res); |
153 | kfree(s->io[i].res); | 151 | kfree(s->io[i].res); |
154 | s->io[i].res = NULL; | 152 | s->io[i].res = NULL; |
@@ -165,21 +163,19 @@ static void release_io_space(struct pcmcia_socket *s, ioaddr_t base, | |||
165 | * this and the tuple reading services. | 163 | * this and the tuple reading services. |
166 | */ | 164 | */ |
167 | 165 | ||
168 | int pccard_access_configuration_register(struct pcmcia_socket *s, | 166 | int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, |
169 | unsigned int function, | ||
170 | conf_reg_t *reg) | 167 | conf_reg_t *reg) |
171 | { | 168 | { |
169 | struct pcmcia_socket *s; | ||
172 | config_t *c; | 170 | config_t *c; |
173 | int addr; | 171 | int addr; |
174 | u_char val; | 172 | u_char val; |
175 | 173 | ||
176 | if (!s || !s->config) | 174 | if (!p_dev || !p_dev->function_config) |
177 | return CS_NO_CARD; | 175 | return CS_NO_CARD; |
178 | 176 | ||
179 | c = &s->config[function]; | 177 | s = p_dev->socket; |
180 | 178 | c = p_dev->function_config; | |
181 | if (c == NULL) | ||
182 | return CS_NO_CARD; | ||
183 | 179 | ||
184 | if (!(c->state & CONFIG_LOCKED)) | 180 | if (!(c->state & CONFIG_LOCKED)) |
185 | return CS_CONFIGURATION_LOCKED; | 181 | return CS_CONFIGURATION_LOCKED; |
@@ -200,20 +196,12 @@ int pccard_access_configuration_register(struct pcmcia_socket *s, | |||
200 | break; | 196 | break; |
201 | } | 197 | } |
202 | return CS_SUCCESS; | 198 | return CS_SUCCESS; |
203 | } /* pccard_access_configuration_register */ | 199 | } /* pcmcia_access_configuration_register */ |
204 | |||
205 | int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, | ||
206 | conf_reg_t *reg) | ||
207 | { | ||
208 | return pccard_access_configuration_register(p_dev->socket, | ||
209 | p_dev->func, reg); | ||
210 | } | ||
211 | EXPORT_SYMBOL(pcmcia_access_configuration_register); | 200 | EXPORT_SYMBOL(pcmcia_access_configuration_register); |
212 | 201 | ||
213 | 202 | ||
214 | |||
215 | int pccard_get_configuration_info(struct pcmcia_socket *s, | 203 | int pccard_get_configuration_info(struct pcmcia_socket *s, |
216 | unsigned int function, | 204 | struct pcmcia_device *p_dev, |
217 | config_info_t *config) | 205 | config_info_t *config) |
218 | { | 206 | { |
219 | config_t *c; | 207 | config_t *c; |
@@ -221,7 +209,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
221 | if (!(s->state & SOCKET_PRESENT)) | 209 | if (!(s->state & SOCKET_PRESENT)) |
222 | return CS_NO_CARD; | 210 | return CS_NO_CARD; |
223 | 211 | ||
224 | config->Function = function; | 212 | config->Function = p_dev->func; |
225 | 213 | ||
226 | #ifdef CONFIG_CARDBUS | 214 | #ifdef CONFIG_CARDBUS |
227 | if (s->state & SOCKET_CARDBUS) { | 215 | if (s->state & SOCKET_CARDBUS) { |
@@ -235,14 +223,14 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
235 | config->AssignedIRQ = s->irq.AssignedIRQ; | 223 | config->AssignedIRQ = s->irq.AssignedIRQ; |
236 | if (config->AssignedIRQ) | 224 | if (config->AssignedIRQ) |
237 | config->Attributes |= CONF_ENABLE_IRQ; | 225 | config->Attributes |= CONF_ENABLE_IRQ; |
238 | config->BasePort1 = s->io[0].BasePort; | 226 | config->BasePort1 = s->io[0].res->start; |
239 | config->NumPorts1 = s->io[0].NumPorts; | 227 | config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1; |
240 | } | 228 | } |
241 | return CS_SUCCESS; | 229 | return CS_SUCCESS; |
242 | } | 230 | } |
243 | #endif | 231 | #endif |
244 | 232 | ||
245 | c = (s->config != NULL) ? &s->config[function] : NULL; | 233 | c = (p_dev) ? p_dev->function_config : NULL; |
246 | 234 | ||
247 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { | 235 | if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { |
248 | config->Attributes = 0; | 236 | config->Attributes = 0; |
@@ -271,7 +259,7 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, | |||
271 | int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, | 259 | int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, |
272 | config_info_t *config) | 260 | config_info_t *config) |
273 | { | 261 | { |
274 | return pccard_get_configuration_info(p_dev->socket, p_dev->func, | 262 | return pccard_get_configuration_info(p_dev->socket, p_dev, |
275 | config); | 263 | config); |
276 | } | 264 | } |
277 | EXPORT_SYMBOL(pcmcia_get_configuration_info); | 265 | EXPORT_SYMBOL(pcmcia_get_configuration_info); |
@@ -317,7 +305,7 @@ EXPORT_SYMBOL(pcmcia_get_window); | |||
317 | * SocketState yet: I haven't seen any point for it. | 305 | * SocketState yet: I haven't seen any point for it. |
318 | */ | 306 | */ |
319 | 307 | ||
320 | int pccard_get_status(struct pcmcia_socket *s, unsigned int function, | 308 | int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, |
321 | cs_status_t *status) | 309 | cs_status_t *status) |
322 | { | 310 | { |
323 | config_t *c; | 311 | config_t *c; |
@@ -334,11 +322,12 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, | |||
334 | if (!(s->state & SOCKET_PRESENT)) | 322 | if (!(s->state & SOCKET_PRESENT)) |
335 | return CS_NO_CARD; | 323 | return CS_NO_CARD; |
336 | 324 | ||
337 | c = (s->config != NULL) ? &s->config[function] : NULL; | 325 | c = (p_dev) ? p_dev->function_config : NULL; |
326 | |||
338 | if ((c != NULL) && (c->state & CONFIG_LOCKED) && | 327 | if ((c != NULL) && (c->state & CONFIG_LOCKED) && |
339 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { | 328 | (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) { |
340 | u_char reg; | 329 | u_char reg; |
341 | if (c->Present & PRESENT_PIN_REPLACE) { | 330 | if (c->CardValues & PRESENT_PIN_REPLACE) { |
342 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); | 331 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); |
343 | status->CardState |= | 332 | status->CardState |= |
344 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; | 333 | (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; |
@@ -352,7 +341,7 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, | |||
352 | /* No PRR? Then assume we're always ready */ | 341 | /* No PRR? Then assume we're always ready */ |
353 | status->CardState |= CS_EVENT_READY_CHANGE; | 342 | status->CardState |= CS_EVENT_READY_CHANGE; |
354 | } | 343 | } |
355 | if (c->Present & PRESENT_EXT_STATUS) { | 344 | if (c->CardValues & PRESENT_EXT_STATUS) { |
356 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); | 345 | pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); |
357 | status->CardState |= | 346 | status->CardState |= |
358 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; | 347 | (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; |
@@ -370,11 +359,9 @@ int pccard_get_status(struct pcmcia_socket *s, unsigned int function, | |||
370 | return CS_SUCCESS; | 359 | return CS_SUCCESS; |
371 | } /* pccard_get_status */ | 360 | } /* pccard_get_status */ |
372 | 361 | ||
373 | int pcmcia_get_status(client_handle_t handle, cs_status_t *status) | 362 | int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status) |
374 | { | 363 | { |
375 | struct pcmcia_socket *s; | 364 | return pccard_get_status(p_dev->socket, p_dev, status); |
376 | s = SOCKET(handle); | ||
377 | return pccard_get_status(s, handle->func, status); | ||
378 | } | 365 | } |
379 | EXPORT_SYMBOL(pcmcia_get_status); | 366 | EXPORT_SYMBOL(pcmcia_get_status); |
380 | 367 | ||
@@ -422,7 +409,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
422 | config_t *c; | 409 | config_t *c; |
423 | 410 | ||
424 | s = p_dev->socket; | 411 | s = p_dev->socket; |
425 | c = CONFIG(p_dev); | 412 | c = p_dev->function_config; |
413 | |||
426 | if (!(s->state & SOCKET_PRESENT)) | 414 | if (!(s->state & SOCKET_PRESENT)) |
427 | return CS_NO_CARD; | 415 | return CS_NO_CARD; |
428 | if (!(c->state & CONFIG_LOCKED)) | 416 | if (!(c->state & CONFIG_LOCKED)) |
@@ -454,6 +442,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
454 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) | 442 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) |
455 | return CS_BAD_VPP; | 443 | return CS_BAD_VPP; |
456 | 444 | ||
445 | if (mod->Attributes & CONF_IO_CHANGE_WIDTH) { | ||
446 | pccard_io_map io_off = { 0, 0, 0, 0, 1 }; | ||
447 | pccard_io_map io_on; | ||
448 | int i; | ||
449 | |||
450 | io_on.speed = io_speed; | ||
451 | for (i = 0; i < MAX_IO_WIN; i++) { | ||
452 | if (!s->io[i].res) | ||
453 | continue; | ||
454 | io_off.map = i; | ||
455 | io_on.map = i; | ||
456 | |||
457 | io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8; | ||
458 | io_on.start = s->io[i].res->start; | ||
459 | io_on.stop = s->io[i].res->end; | ||
460 | |||
461 | s->ops->set_io_map(s, &io_off); | ||
462 | mdelay(40); | ||
463 | s->ops->set_io_map(s, &io_on); | ||
464 | } | ||
465 | } | ||
466 | |||
457 | return CS_SUCCESS; | 467 | return CS_SUCCESS; |
458 | } /* modify_configuration */ | 468 | } /* modify_configuration */ |
459 | EXPORT_SYMBOL(pcmcia_modify_configuration); | 469 | EXPORT_SYMBOL(pcmcia_modify_configuration); |
@@ -463,23 +473,23 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
463 | { | 473 | { |
464 | pccard_io_map io = { 0, 0, 0, 0, 1 }; | 474 | pccard_io_map io = { 0, 0, 0, 0, 1 }; |
465 | struct pcmcia_socket *s = p_dev->socket; | 475 | struct pcmcia_socket *s = p_dev->socket; |
476 | config_t *c = p_dev->function_config; | ||
466 | int i; | 477 | int i; |
467 | 478 | ||
468 | if (!(p_dev->state & CLIENT_CONFIG_LOCKED)) | 479 | if (p_dev->_locked) { |
469 | return CS_BAD_HANDLE; | 480 | p_dev->_locked = 0; |
470 | p_dev->state &= ~CLIENT_CONFIG_LOCKED; | ||
471 | |||
472 | if (!(p_dev->state & CLIENT_STALE)) { | ||
473 | config_t *c = CONFIG(p_dev); | ||
474 | if (--(s->lock_count) == 0) { | 481 | if (--(s->lock_count) == 0) { |
475 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ | 482 | s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ |
476 | s->socket.Vpp = 0; | 483 | s->socket.Vpp = 0; |
477 | s->socket.io_irq = 0; | 484 | s->socket.io_irq = 0; |
478 | s->ops->set_socket(s, &s->socket); | 485 | s->ops->set_socket(s, &s->socket); |
479 | } | 486 | } |
487 | } | ||
488 | if (c->state & CONFIG_LOCKED) { | ||
489 | c->state &= ~CONFIG_LOCKED; | ||
480 | if (c->state & CONFIG_IO_REQ) | 490 | if (c->state & CONFIG_IO_REQ) |
481 | for (i = 0; i < MAX_IO_WIN; i++) { | 491 | for (i = 0; i < MAX_IO_WIN; i++) { |
482 | if (s->io[i].NumPorts == 0) | 492 | if (!s->io[i].res) |
483 | continue; | 493 | continue; |
484 | s->io[i].Config--; | 494 | s->io[i].Config--; |
485 | if (s->io[i].Config != 0) | 495 | if (s->io[i].Config != 0) |
@@ -487,12 +497,10 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev) | |||
487 | io.map = i; | 497 | io.map = i; |
488 | s->ops->set_io_map(s, &io); | 498 | s->ops->set_io_map(s, &io); |
489 | } | 499 | } |
490 | c->state &= ~CONFIG_LOCKED; | ||
491 | } | 500 | } |
492 | 501 | ||
493 | return CS_SUCCESS; | 502 | return CS_SUCCESS; |
494 | } /* pcmcia_release_configuration */ | 503 | } /* pcmcia_release_configuration */ |
495 | EXPORT_SYMBOL(pcmcia_release_configuration); | ||
496 | 504 | ||
497 | 505 | ||
498 | /** pcmcia_release_io | 506 | /** pcmcia_release_io |
@@ -503,25 +511,23 @@ EXPORT_SYMBOL(pcmcia_release_configuration); | |||
503 | * don't bother checking the port ranges against the current socket | 511 | * don't bother checking the port ranges against the current socket |
504 | * values. | 512 | * values. |
505 | */ | 513 | */ |
506 | int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | 514 | static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) |
507 | { | 515 | { |
508 | struct pcmcia_socket *s = p_dev->socket; | 516 | struct pcmcia_socket *s = p_dev->socket; |
517 | config_t *c = p_dev->function_config; | ||
509 | 518 | ||
510 | if (!(p_dev->state & CLIENT_IO_REQ)) | 519 | if (!p_dev->_io ) |
511 | return CS_BAD_HANDLE; | 520 | return CS_BAD_HANDLE; |
512 | p_dev->state &= ~CLIENT_IO_REQ; | 521 | |
513 | 522 | p_dev->_io = 0; | |
514 | if (!(p_dev->state & CLIENT_STALE)) { | 523 | |
515 | config_t *c = CONFIG(p_dev); | 524 | if ((c->io.BasePort1 != req->BasePort1) || |
516 | if (c->state & CONFIG_LOCKED) | 525 | (c->io.NumPorts1 != req->NumPorts1) || |
517 | return CS_CONFIGURATION_LOCKED; | 526 | (c->io.BasePort2 != req->BasePort2) || |
518 | if ((c->io.BasePort1 != req->BasePort1) || | 527 | (c->io.NumPorts2 != req->NumPorts2)) |
519 | (c->io.NumPorts1 != req->NumPorts1) || | 528 | return CS_BAD_ARGS; |
520 | (c->io.BasePort2 != req->BasePort2) || | 529 | |
521 | (c->io.NumPorts2 != req->NumPorts2)) | 530 | c->state &= ~CONFIG_IO_REQ; |
522 | return CS_BAD_ARGS; | ||
523 | c->state &= ~CONFIG_IO_REQ; | ||
524 | } | ||
525 | 531 | ||
526 | release_io_space(s, req->BasePort1, req->NumPorts1); | 532 | release_io_space(s, req->BasePort1, req->NumPorts1); |
527 | if (req->NumPorts2) | 533 | if (req->NumPorts2) |
@@ -529,28 +535,26 @@ int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
529 | 535 | ||
530 | return CS_SUCCESS; | 536 | return CS_SUCCESS; |
531 | } /* pcmcia_release_io */ | 537 | } /* pcmcia_release_io */ |
532 | EXPORT_SYMBOL(pcmcia_release_io); | ||
533 | 538 | ||
534 | 539 | ||
535 | int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | 540 | static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) |
536 | { | 541 | { |
537 | struct pcmcia_socket *s = p_dev->socket; | 542 | struct pcmcia_socket *s = p_dev->socket; |
538 | if (!(p_dev->state & CLIENT_IRQ_REQ)) | 543 | config_t *c= p_dev->function_config; |
544 | |||
545 | if (!p_dev->_irq) | ||
539 | return CS_BAD_HANDLE; | 546 | return CS_BAD_HANDLE; |
540 | p_dev->state &= ~CLIENT_IRQ_REQ; | 547 | p_dev->_irq = 0; |
541 | 548 | ||
542 | if (!(p_dev->state & CLIENT_STALE)) { | 549 | if (c->state & CONFIG_LOCKED) |
543 | config_t *c = CONFIG(p_dev); | 550 | return CS_CONFIGURATION_LOCKED; |
544 | if (c->state & CONFIG_LOCKED) | 551 | if (c->irq.Attributes != req->Attributes) |
545 | return CS_CONFIGURATION_LOCKED; | 552 | return CS_BAD_ATTRIBUTE; |
546 | if (c->irq.Attributes != req->Attributes) | 553 | if (s->irq.AssignedIRQ != req->AssignedIRQ) |
547 | return CS_BAD_ATTRIBUTE; | 554 | return CS_BAD_IRQ; |
548 | if (s->irq.AssignedIRQ != req->AssignedIRQ) | 555 | if (--s->irq.Config == 0) { |
549 | return CS_BAD_IRQ; | 556 | c->state &= ~CONFIG_IRQ_REQ; |
550 | if (--s->irq.Config == 0) { | 557 | s->irq.AssignedIRQ = 0; |
551 | c->state &= ~CONFIG_IRQ_REQ; | ||
552 | s->irq.AssignedIRQ = 0; | ||
553 | } | ||
554 | } | 558 | } |
555 | 559 | ||
556 | if (req->Attributes & IRQ_HANDLE_PRESENT) { | 560 | if (req->Attributes & IRQ_HANDLE_PRESENT) { |
@@ -563,7 +567,6 @@ int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
563 | 567 | ||
564 | return CS_SUCCESS; | 568 | return CS_SUCCESS; |
565 | } /* pcmcia_release_irq */ | 569 | } /* pcmcia_release_irq */ |
566 | EXPORT_SYMBOL(pcmcia_release_irq); | ||
567 | 570 | ||
568 | 571 | ||
569 | int pcmcia_release_window(window_handle_t win) | 572 | int pcmcia_release_window(window_handle_t win) |
@@ -573,7 +576,7 @@ int pcmcia_release_window(window_handle_t win) | |||
573 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) | 576 | if ((win == NULL) || (win->magic != WINDOW_MAGIC)) |
574 | return CS_BAD_HANDLE; | 577 | return CS_BAD_HANDLE; |
575 | s = win->sock; | 578 | s = win->sock; |
576 | if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) | 579 | if (!(win->handle->_win & CLIENT_WIN_REQ(win->index))) |
577 | return CS_BAD_HANDLE; | 580 | return CS_BAD_HANDLE; |
578 | 581 | ||
579 | /* Shut down memory window */ | 582 | /* Shut down memory window */ |
@@ -587,7 +590,7 @@ int pcmcia_release_window(window_handle_t win) | |||
587 | kfree(win->ctl.res); | 590 | kfree(win->ctl.res); |
588 | win->ctl.res = NULL; | 591 | win->ctl.res = NULL; |
589 | } | 592 | } |
590 | win->handle->state &= ~CLIENT_WIN_REQ(win->index); | 593 | win->handle->_win &= ~CLIENT_WIN_REQ(win->index); |
591 | 594 | ||
592 | win->magic = 0; | 595 | win->magic = 0; |
593 | 596 | ||
@@ -610,16 +613,12 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
610 | 613 | ||
611 | if (req->IntType & INT_CARDBUS) | 614 | if (req->IntType & INT_CARDBUS) |
612 | return CS_UNSUPPORTED_MODE; | 615 | return CS_UNSUPPORTED_MODE; |
613 | c = CONFIG(p_dev); | 616 | c = p_dev->function_config; |
614 | if (c->state & CONFIG_LOCKED) | 617 | if (c->state & CONFIG_LOCKED) |
615 | return CS_CONFIGURATION_LOCKED; | 618 | return CS_CONFIGURATION_LOCKED; |
616 | 619 | ||
617 | /* Do power control. We don't allow changes in Vcc. */ | 620 | /* Do power control. We don't allow changes in Vcc. */ |
618 | if (s->socket.Vcc != req->Vcc) | 621 | s->socket.Vpp = req->Vpp; |
619 | return CS_BAD_VCC; | ||
620 | if (req->Vpp1 != req->Vpp2) | ||
621 | return CS_BAD_VPP; | ||
622 | s->socket.Vpp = req->Vpp1; | ||
623 | if (s->ops->set_socket(s, &s->socket)) | 622 | if (s->ops->set_socket(s, &s->socket)) |
624 | return CS_BAD_VPP; | 623 | return CS_BAD_VPP; |
625 | 624 | ||
@@ -643,7 +642,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
643 | 642 | ||
644 | /* Set up CIS configuration registers */ | 643 | /* Set up CIS configuration registers */ |
645 | base = c->ConfigBase = req->ConfigBase; | 644 | base = c->ConfigBase = req->ConfigBase; |
646 | c->Present = c->CardValues = req->Present; | 645 | c->CardValues = req->Present; |
647 | if (req->Present & PRESENT_COPY) { | 646 | if (req->Present & PRESENT_COPY) { |
648 | c->Copy = req->Copy; | 647 | c->Copy = req->Copy; |
649 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); | 648 | pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); |
@@ -690,10 +689,10 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
690 | if (c->state & CONFIG_IO_REQ) { | 689 | if (c->state & CONFIG_IO_REQ) { |
691 | iomap.speed = io_speed; | 690 | iomap.speed = io_speed; |
692 | for (i = 0; i < MAX_IO_WIN; i++) | 691 | for (i = 0; i < MAX_IO_WIN; i++) |
693 | if (s->io[i].NumPorts != 0) { | 692 | if (s->io[i].res) { |
694 | iomap.map = i; | 693 | iomap.map = i; |
695 | iomap.flags = MAP_ACTIVE; | 694 | iomap.flags = MAP_ACTIVE; |
696 | switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { | 695 | switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) { |
697 | case IO_DATA_PATH_WIDTH_16: | 696 | case IO_DATA_PATH_WIDTH_16: |
698 | iomap.flags |= MAP_16BIT; break; | 697 | iomap.flags |= MAP_16BIT; break; |
699 | case IO_DATA_PATH_WIDTH_AUTO: | 698 | case IO_DATA_PATH_WIDTH_AUTO: |
@@ -701,15 +700,15 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev, | |||
701 | default: | 700 | default: |
702 | break; | 701 | break; |
703 | } | 702 | } |
704 | iomap.start = s->io[i].BasePort; | 703 | iomap.start = s->io[i].res->start; |
705 | iomap.stop = iomap.start + s->io[i].NumPorts - 1; | 704 | iomap.stop = s->io[i].res->end; |
706 | s->ops->set_io_map(s, &iomap); | 705 | s->ops->set_io_map(s, &iomap); |
707 | s->io[i].Config++; | 706 | s->io[i].Config++; |
708 | } | 707 | } |
709 | } | 708 | } |
710 | 709 | ||
711 | c->state |= CONFIG_LOCKED; | 710 | c->state |= CONFIG_LOCKED; |
712 | p_dev->state |= CLIENT_CONFIG_LOCKED; | 711 | p_dev->_locked = 1; |
713 | return CS_SUCCESS; | 712 | return CS_SUCCESS; |
714 | } /* pcmcia_request_configuration */ | 713 | } /* pcmcia_request_configuration */ |
715 | EXPORT_SYMBOL(pcmcia_request_configuration); | 714 | EXPORT_SYMBOL(pcmcia_request_configuration); |
@@ -730,7 +729,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
730 | 729 | ||
731 | if (!req) | 730 | if (!req) |
732 | return CS_UNSUPPORTED_MODE; | 731 | return CS_UNSUPPORTED_MODE; |
733 | c = CONFIG(p_dev); | 732 | c = p_dev->function_config; |
734 | if (c->state & CONFIG_LOCKED) | 733 | if (c->state & CONFIG_LOCKED) |
735 | return CS_CONFIGURATION_LOCKED; | 734 | return CS_CONFIGURATION_LOCKED; |
736 | if (c->state & CONFIG_IO_REQ) | 735 | if (c->state & CONFIG_IO_REQ) |
@@ -755,7 +754,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req) | |||
755 | 754 | ||
756 | c->io = *req; | 755 | c->io = *req; |
757 | c->state |= CONFIG_IO_REQ; | 756 | c->state |= CONFIG_IO_REQ; |
758 | p_dev->state |= CLIENT_IO_REQ; | 757 | p_dev->_io = 1; |
759 | return CS_SUCCESS; | 758 | return CS_SUCCESS; |
760 | } /* pcmcia_request_io */ | 759 | } /* pcmcia_request_io */ |
761 | EXPORT_SYMBOL(pcmcia_request_io); | 760 | EXPORT_SYMBOL(pcmcia_request_io); |
@@ -786,7 +785,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
786 | 785 | ||
787 | if (!(s->state & SOCKET_PRESENT)) | 786 | if (!(s->state & SOCKET_PRESENT)) |
788 | return CS_NO_CARD; | 787 | return CS_NO_CARD; |
789 | c = CONFIG(p_dev); | 788 | c = p_dev->function_config; |
790 | if (c->state & CONFIG_LOCKED) | 789 | if (c->state & CONFIG_LOCKED) |
791 | return CS_CONFIGURATION_LOCKED; | 790 | return CS_CONFIGURATION_LOCKED; |
792 | if (c->state & CONFIG_IRQ_REQ) | 791 | if (c->state & CONFIG_IRQ_REQ) |
@@ -851,7 +850,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) | |||
851 | s->irq.Config++; | 850 | s->irq.Config++; |
852 | 851 | ||
853 | c->state |= CONFIG_IRQ_REQ; | 852 | c->state |= CONFIG_IRQ_REQ; |
854 | p_dev->state |= CLIENT_IRQ_REQ; | 853 | p_dev->_irq = 1; |
855 | 854 | ||
856 | #ifdef CONFIG_PCMCIA_PROBE | 855 | #ifdef CONFIG_PCMCIA_PROBE |
857 | pcmcia_used_irq[irq]++; | 856 | pcmcia_used_irq[irq]++; |
@@ -911,7 +910,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h | |||
911 | if (!win->ctl.res) | 910 | if (!win->ctl.res) |
912 | return CS_IN_USE; | 911 | return CS_IN_USE; |
913 | } | 912 | } |
914 | (*p_dev)->state |= CLIENT_WIN_REQ(w); | 913 | (*p_dev)->_win |= CLIENT_WIN_REQ(w); |
915 | 914 | ||
916 | /* Configure the socket controller */ | 915 | /* Configure the socket controller */ |
917 | win->ctl.map = w+1; | 916 | win->ctl.map = w+1; |
@@ -941,3 +940,14 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h | |||
941 | return CS_SUCCESS; | 940 | return CS_SUCCESS; |
942 | } /* pcmcia_request_window */ | 941 | } /* pcmcia_request_window */ |
943 | EXPORT_SYMBOL(pcmcia_request_window); | 942 | EXPORT_SYMBOL(pcmcia_request_window); |
943 | |||
944 | void pcmcia_disable_device(struct pcmcia_device *p_dev) { | ||
945 | pcmcia_release_configuration(p_dev); | ||
946 | pcmcia_release_io(p_dev, &p_dev->io); | ||
947 | pcmcia_release_irq(p_dev, &p_dev->irq); | ||
948 | if (&p_dev->win) | ||
949 | pcmcia_release_window(p_dev->win); | ||
950 | |||
951 | p_dev->dev_node = NULL; | ||
952 | } | ||
953 | EXPORT_SYMBOL(pcmcia_disable_device); | ||
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index f2789afb22b2..16d1ea7b0a18 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c | |||
@@ -8,7 +8,6 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/config.h> | ||
12 | #include <linux/module.h> | 11 | #include <linux/module.h> |
13 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 514609369836..81dfc2cac2b4 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | 17 | ||
@@ -22,6 +21,8 @@ | |||
22 | #include "cs_internal.h" | 21 | #include "cs_internal.h" |
23 | 22 | ||
24 | 23 | ||
24 | #ifdef CONFIG_PCMCIA_IOCTL | ||
25 | |||
25 | #ifdef CONFIG_PCMCIA_PROBE | 26 | #ifdef CONFIG_PCMCIA_PROBE |
26 | 27 | ||
27 | static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) | 28 | static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) |
@@ -98,6 +99,8 @@ int pcmcia_adjust_resource_info(adjust_t *adj) | |||
98 | } | 99 | } |
99 | EXPORT_SYMBOL(pcmcia_adjust_resource_info); | 100 | EXPORT_SYMBOL(pcmcia_adjust_resource_info); |
100 | 101 | ||
102 | #endif | ||
103 | |||
101 | int pcmcia_validate_mem(struct pcmcia_socket *s) | 104 | int pcmcia_validate_mem(struct pcmcia_socket *s) |
102 | { | 105 | { |
103 | if (s->resource_ops->validate_mem) | 106 | if (s->resource_ops->validate_mem) |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 5301ac60358f..0f8b157c9717 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
@@ -12,7 +12,6 @@ | |||
12 | * (C) 1999 David A. Hinds | 12 | * (C) 1999 David A. Hinds |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/config.h> | ||
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/moduleparam.h> | 16 | #include <linux/moduleparam.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
@@ -61,7 +60,7 @@ struct socket_data { | |||
61 | unsigned int rsrc_mem_probe; | 60 | unsigned int rsrc_mem_probe; |
62 | }; | 61 | }; |
63 | 62 | ||
64 | static DECLARE_MUTEX(rsrc_sem); | 63 | static DEFINE_MUTEX(rsrc_mutex); |
65 | #define MEM_PROBE_LOW (1 << 0) | 64 | #define MEM_PROBE_LOW (1 << 0) |
66 | #define MEM_PROBE_HIGH (1 << 1) | 65 | #define MEM_PROBE_HIGH (1 << 1) |
67 | 66 | ||
@@ -484,7 +483,7 @@ static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) | |||
484 | 483 | ||
485 | 484 | ||
486 | /* | 485 | /* |
487 | * Locking note: Must be called with skt_sem held! | 486 | * Locking note: Must be called with skt_mutex held! |
488 | */ | 487 | */ |
489 | static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) | 488 | static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) |
490 | { | 489 | { |
@@ -495,7 +494,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) | |||
495 | if (!probe_mem) | 494 | if (!probe_mem) |
496 | return 0; | 495 | return 0; |
497 | 496 | ||
498 | down(&rsrc_sem); | 497 | mutex_lock(&rsrc_mutex); |
499 | 498 | ||
500 | if (s->features & SS_CAP_PAGE_REGS) | 499 | if (s->features & SS_CAP_PAGE_REGS) |
501 | probe_mask = MEM_PROBE_HIGH; | 500 | probe_mask = MEM_PROBE_HIGH; |
@@ -507,7 +506,7 @@ static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) | |||
507 | s_data->rsrc_mem_probe |= probe_mask; | 506 | s_data->rsrc_mem_probe |= probe_mask; |
508 | } | 507 | } |
509 | 508 | ||
510 | up(&rsrc_sem); | 509 | mutex_unlock(&rsrc_mutex); |
511 | 510 | ||
512 | return ret; | 511 | return ret; |
513 | } | 512 | } |
@@ -585,7 +584,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
585 | struct socket_data *s_data = s->resource_data; | 584 | struct socket_data *s_data = s->resource_data; |
586 | int ret = -ENOMEM; | 585 | int ret = -ENOMEM; |
587 | 586 | ||
588 | down(&rsrc_sem); | 587 | mutex_lock(&rsrc_mutex); |
589 | for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) { | 588 | for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) { |
590 | unsigned long start = m->base; | 589 | unsigned long start = m->base; |
591 | unsigned long end = m->base + m->num - 1; | 590 | unsigned long end = m->base + m->num - 1; |
@@ -596,7 +595,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
596 | ret = adjust_resource(res, r_start, r_end - r_start + 1); | 595 | ret = adjust_resource(res, r_start, r_end - r_start + 1); |
597 | break; | 596 | break; |
598 | } | 597 | } |
599 | up(&rsrc_sem); | 598 | mutex_unlock(&rsrc_mutex); |
600 | 599 | ||
601 | return ret; | 600 | return ret; |
602 | } | 601 | } |
@@ -630,7 +629,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
630 | data.offset = base & data.mask; | 629 | data.offset = base & data.mask; |
631 | data.map = &s_data->io_db; | 630 | data.map = &s_data->io_db; |
632 | 631 | ||
633 | down(&rsrc_sem); | 632 | mutex_lock(&rsrc_mutex); |
634 | #ifdef CONFIG_PCI | 633 | #ifdef CONFIG_PCI |
635 | if (s->cb_dev) { | 634 | if (s->cb_dev) { |
636 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, | 635 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1, |
@@ -639,7 +638,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
639 | #endif | 638 | #endif |
640 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, | 639 | ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, |
641 | 1, pcmcia_align, &data); | 640 | 1, pcmcia_align, &data); |
642 | up(&rsrc_sem); | 641 | mutex_unlock(&rsrc_mutex); |
643 | 642 | ||
644 | if (ret != 0) { | 643 | if (ret != 0) { |
645 | kfree(res); | 644 | kfree(res); |
@@ -672,7 +671,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, | |||
672 | min = 0x100000UL + base; | 671 | min = 0x100000UL + base; |
673 | } | 672 | } |
674 | 673 | ||
675 | down(&rsrc_sem); | 674 | mutex_lock(&rsrc_mutex); |
676 | #ifdef CONFIG_PCI | 675 | #ifdef CONFIG_PCI |
677 | if (s->cb_dev) { | 676 | if (s->cb_dev) { |
678 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, | 677 | ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, |
@@ -682,7 +681,7 @@ static struct resource * nonstatic_find_mem_region(u_long base, u_long num, | |||
682 | #endif | 681 | #endif |
683 | ret = allocate_resource(&iomem_resource, res, num, min, | 682 | ret = allocate_resource(&iomem_resource, res, num, min, |
684 | max, 1, pcmcia_align, &data); | 683 | max, 1, pcmcia_align, &data); |
685 | up(&rsrc_sem); | 684 | mutex_unlock(&rsrc_mutex); |
686 | if (ret == 0 || low) | 685 | if (ret == 0 || low) |
687 | break; | 686 | break; |
688 | low = 1; | 687 | low = 1; |
@@ -705,7 +704,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned | |||
705 | if (end < start) | 704 | if (end < start) |
706 | return -EINVAL; | 705 | return -EINVAL; |
707 | 706 | ||
708 | down(&rsrc_sem); | 707 | mutex_lock(&rsrc_mutex); |
709 | switch (action) { | 708 | switch (action) { |
710 | case ADD_MANAGED_RESOURCE: | 709 | case ADD_MANAGED_RESOURCE: |
711 | ret = add_interval(&data->mem_db, start, size); | 710 | ret = add_interval(&data->mem_db, start, size); |
@@ -723,7 +722,7 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned | |||
723 | default: | 722 | default: |
724 | ret = -EINVAL; | 723 | ret = -EINVAL; |
725 | } | 724 | } |
726 | up(&rsrc_sem); | 725 | mutex_unlock(&rsrc_mutex); |
727 | 726 | ||
728 | return ret; | 727 | return ret; |
729 | } | 728 | } |
@@ -741,7 +740,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long | |||
741 | if (end > IO_SPACE_LIMIT) | 740 | if (end > IO_SPACE_LIMIT) |
742 | return -EINVAL; | 741 | return -EINVAL; |
743 | 742 | ||
744 | down(&rsrc_sem); | 743 | mutex_lock(&rsrc_mutex); |
745 | switch (action) { | 744 | switch (action) { |
746 | case ADD_MANAGED_RESOURCE: | 745 | case ADD_MANAGED_RESOURCE: |
747 | if (add_interval(&data->io_db, start, size) != 0) { | 746 | if (add_interval(&data->io_db, start, size) != 0) { |
@@ -760,7 +759,7 @@ static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long | |||
760 | ret = -EINVAL; | 759 | ret = -EINVAL; |
761 | break; | 760 | break; |
762 | } | 761 | } |
763 | up(&rsrc_sem); | 762 | mutex_unlock(&rsrc_mutex); |
764 | 763 | ||
765 | return ret; | 764 | return ret; |
766 | } | 765 | } |
@@ -867,7 +866,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) | |||
867 | struct socket_data *data = s->resource_data; | 866 | struct socket_data *data = s->resource_data; |
868 | struct resource_map *p, *q; | 867 | struct resource_map *p, *q; |
869 | 868 | ||
870 | down(&rsrc_sem); | 869 | mutex_lock(&rsrc_mutex); |
871 | for (p = data->mem_db.next; p != &data->mem_db; p = q) { | 870 | for (p = data->mem_db.next; p != &data->mem_db; p = q) { |
872 | q = p->next; | 871 | q = p->next; |
873 | kfree(p); | 872 | kfree(p); |
@@ -876,7 +875,7 @@ static void nonstatic_release_resource_db(struct pcmcia_socket *s) | |||
876 | q = p->next; | 875 | q = p->next; |
877 | kfree(p); | 876 | kfree(p); |
878 | } | 877 | } |
879 | up(&rsrc_sem); | 878 | mutex_unlock(&rsrc_mutex); |
880 | } | 879 | } |
881 | 880 | ||
882 | 881 | ||
@@ -901,7 +900,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf) | |||
901 | struct resource_map *p; | 900 | struct resource_map *p; |
902 | ssize_t ret = 0; | 901 | ssize_t ret = 0; |
903 | 902 | ||
904 | down(&rsrc_sem); | 903 | mutex_lock(&rsrc_mutex); |
905 | data = s->resource_data; | 904 | data = s->resource_data; |
906 | 905 | ||
907 | for (p = data->io_db.next; p != &data->io_db; p = p->next) { | 906 | for (p = data->io_db.next; p != &data->io_db; p = p->next) { |
@@ -913,7 +912,7 @@ static ssize_t show_io_db(struct class_device *class_dev, char *buf) | |||
913 | ((unsigned long) p->base + p->num - 1)); | 912 | ((unsigned long) p->base + p->num - 1)); |
914 | } | 913 | } |
915 | 914 | ||
916 | up(&rsrc_sem); | 915 | mutex_unlock(&rsrc_mutex); |
917 | return (ret); | 916 | return (ret); |
918 | } | 917 | } |
919 | 918 | ||
@@ -953,7 +952,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf) | |||
953 | struct resource_map *p; | 952 | struct resource_map *p; |
954 | ssize_t ret = 0; | 953 | ssize_t ret = 0; |
955 | 954 | ||
956 | down(&rsrc_sem); | 955 | mutex_lock(&rsrc_mutex); |
957 | data = s->resource_data; | 956 | data = s->resource_data; |
958 | 957 | ||
959 | for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { | 958 | for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { |
@@ -965,7 +964,7 @@ static ssize_t show_mem_db(struct class_device *class_dev, char *buf) | |||
965 | ((unsigned long) p->base + p->num - 1)); | 964 | ((unsigned long) p->base + p->num - 1)); |
966 | } | 965 | } |
967 | 966 | ||
968 | up(&rsrc_sem); | 967 | mutex_unlock(&rsrc_mutex); |
969 | return (ret); | 968 | return (ret); |
970 | } | 969 | } |
971 | 970 | ||
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index 2b3c2895b43d..eb89928f2338 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c | |||
@@ -5,7 +5,6 @@ | |||
5 | * Based off the Assabet. | 5 | * Based off the Assabet. |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | #include <linux/config.h> | ||
9 | #include <linux/module.h> | 8 | #include <linux/module.h> |
10 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
11 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 5ab1cdef7c48..c5d7476da471 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/moduleparam.h> | 12 | #include <linux/moduleparam.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/config.h> | ||
16 | #include <linux/string.h> | 15 | #include <linux/string.h> |
17 | #include <linux/major.h> | 16 | #include <linux/major.h> |
18 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
@@ -25,6 +24,7 @@ | |||
25 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
26 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
27 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/mutex.h> | ||
28 | #include <asm/system.h> | 28 | #include <asm/system.h> |
29 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
30 | 30 | ||
@@ -183,7 +183,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, | |||
183 | s->resource_setup_done = 1; | 183 | s->resource_setup_done = 1; |
184 | spin_unlock_irqrestore(&s->lock, flags); | 184 | spin_unlock_irqrestore(&s->lock, flags); |
185 | 185 | ||
186 | down(&s->skt_sem); | 186 | mutex_lock(&s->skt_mutex); |
187 | if ((s->callback) && | 187 | if ((s->callback) && |
188 | (s->state & SOCKET_PRESENT) && | 188 | (s->state & SOCKET_PRESENT) && |
189 | !(s->state & SOCKET_CARDBUS)) { | 189 | !(s->state & SOCKET_CARDBUS)) { |
@@ -192,7 +192,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, | |||
192 | module_put(s->callback->owner); | 192 | module_put(s->callback->owner); |
193 | } | 193 | } |
194 | } | 194 | } |
195 | up(&s->skt_sem); | 195 | mutex_unlock(&s->skt_mutex); |
196 | 196 | ||
197 | return count; | 197 | return count; |
198 | } | 198 | } |
@@ -322,7 +322,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz | |||
322 | kfree(cis); | 322 | kfree(cis); |
323 | 323 | ||
324 | if (!ret) { | 324 | if (!ret) { |
325 | down(&s->skt_sem); | 325 | mutex_lock(&s->skt_mutex); |
326 | if ((s->callback) && (s->state & SOCKET_PRESENT) && | 326 | if ((s->callback) && (s->state & SOCKET_PRESENT) && |
327 | !(s->state & SOCKET_CARDBUS)) { | 327 | !(s->state & SOCKET_CARDBUS)) { |
328 | if (try_module_get(s->callback->owner)) { | 328 | if (try_module_get(s->callback->owner)) { |
@@ -330,7 +330,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz | |||
330 | module_put(s->callback->owner); | 330 | module_put(s->callback->owner); |
331 | } | 331 | } |
332 | } | 332 | } |
333 | up(&s->skt_sem); | 333 | mutex_unlock(&s->skt_mutex); |
334 | } | 334 | } |
335 | 335 | ||
336 | 336 | ||
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index d5b4ff74462e..7a3d1b8e16b9 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h | |||
@@ -30,7 +30,6 @@ | |||
30 | #ifndef _LINUX_TI113X_H | 30 | #ifndef _LINUX_TI113X_H |
31 | #define _LINUX_TI113X_H | 31 | #define _LINUX_TI113X_H |
32 | 32 | ||
33 | #include <linux/config.h> | ||
34 | 33 | ||
35 | /* Register definitions for TI 113X PCI-to-CardBus bridges */ | 34 | /* Register definitions for TI 113X PCI-to-CardBus bridges */ |
36 | 35 | ||