diff options
Diffstat (limited to 'drivers/pcmcia')
38 files changed, 1455 insertions, 1255 deletions
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d189e4743e6..d0f5ad30607 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -49,26 +49,6 @@ config PCMCIA_LOAD_CIS If unsure, say Y. -config PCMCIA_IOCTL - bool "PCMCIA control ioctl (obsolete)" - depends on PCMCIA && ARM && !SMP && !PREEMPT - default y - help - If you say Y here, the deprecated ioctl interface to the PCMCIA - subsystem will be built. It is needed by the deprecated pcmcia-cs - tools (cardmgr, cardctl) to function properly. - - You should use the new pcmciautils package instead (see - <file:Documentation/Changes> for location and details). - - This config option will most likely be removed from kernel 2.6.35, - the associated code from kernel 2.6.36. - - As the PCMCIA ioctl is not locking safe, it depends on !SMP and - !PREEMPT. - - If unsure, say N. - config CARDBUS bool "32-bit CardBus support" depends on PCI @@ -234,7 +214,8 @@ config PCMCIA_PXA2XX depends on ARM && ARCH_PXA && PCMCIA depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ - || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2) + || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ + || MACH_VPAC270) select PCMCIA_SOC_COMMON help Say Y here to include support for the PXA2xx PCMCIA controller @@ -317,7 +298,7 @@ config ELECTRA_CF PA Semi Electra eval board. config PCCARD_NONSTATIC - tristate + bool config PCCARD_IODYN bool diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 381b031d9d7..d006e8beab9 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -2,15 +2,18 @@ # Makefile for the kernel pcmcia subsystem (c/o David Hinds) # -pcmcia_core-y += cs.o rsrc_mgr.o socket_sysfs.o +pcmcia_core-y += cs.o socket_sysfs.o pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o obj-$(CONFIG_PCCARD) += pcmcia_core.o -pcmcia-y += ds.o pcmcia_resource.o cistpl.o +pcmcia-y += ds.o pcmcia_resource.o cistpl.o pcmcia_cis.o pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o obj-$(CONFIG_PCMCIA) += pcmcia.o -obj-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o +pcmcia_rsrc-y += rsrc_mgr.o +pcmcia_rsrc-$(CONFIG_PCCARD_NONSTATIC) += rsrc_nonstatic.o +pcmcia_rsrc-$(CONFIG_PCCARD_IODYN) += rsrc_iodyn.o +obj-$(CONFIG_PCCARD) += pcmcia_rsrc.o # socket drivers @@ -66,6 +69,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o +pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 5d228071ec6..fb33fa42d24 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -15,6 +15,7 @@ #include <linux/errno.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <pcmcia/ss.h> @@ -361,7 +362,6 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg) struct at91_cf_socket *cf = platform_get_drvdata(pdev); struct at91_cf_data *board = cf->board; - pcmcia_socket_dev_suspend(&pdev->dev); if (device_may_wakeup(&pdev->dev)) { enable_irq_wake(board->det_pin); if (board->irq_pin) @@ -381,7 +381,6 @@ static int at91_cf_resume(struct platform_device *pdev) disable_irq_wake(board->irq_pin); } - pcmcia_socket_dev_resume(&pdev->dev); return 0; } diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 171c8a65488..88c4c409878 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -43,6 +43,7 @@ #include <linux/spinlock.h> #include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/irq.h> @@ -510,17 +511,6 @@ static int au1x00_drv_pcmcia_probe(struct platform_device *dev) return ret; } -static int au1x00_drv_pcmcia_suspend(struct platform_device *dev, - pm_message_t state) -{ - return pcmcia_socket_dev_suspend(&dev->dev); -} - -static int au1x00_drv_pcmcia_resume(struct platform_device *dev) -{ - return pcmcia_socket_dev_resume(&dev->dev); -} - static struct platform_driver au1x00_pcmcia_driver = { .driver = { .name = "au1x00-pcmcia", @@ -528,8 +518,6 @@ static struct platform_driver au1x00_pcmcia_driver = { }, .probe = au1x00_drv_pcmcia_probe, .remove = au1x00_drv_pcmcia_remove, - .suspend = au1x00_drv_pcmcia_suspend, - .resume = au1x00_drv_pcmcia_resume, }; diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c index bc88a3b19bb..693577e0fef 100644 --- a/drivers/pcmcia/bcm63xx_pcmcia.c +++ b/drivers/pcmcia/bcm63xx_pcmcia.c @@ -11,6 +11,7 @@ #include <linux/ioport.h> #include <linux/timer.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/pci.h> #include <linux/gpio.h> diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index 2482ce7ac6d..eae9cbe37a3 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c @@ -31,6 +31,7 @@ #include <linux/platform_device.h> #include <linux/errno.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/irq.h> @@ -112,7 +113,7 @@ static int bfin_cf_get_status(struct pcmcia_socket *s, u_int *sp) if (bfin_cf_present(cf->cd_pfx)) { *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD; - s->irq.AssignedIRQ = 0; + s->pcmcia_irq = 0; s->pci_irq = cf->irq; } else @@ -300,16 +301,6 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev) return 0; } -static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return pcmcia_socket_dev_suspend(&pdev->dev); -} - -static int bfin_cf_resume(struct platform_device *pdev) -{ - return pcmcia_socket_dev_resume(&pdev->dev); -} - static struct platform_driver bfin_cf_driver = { .driver = { .name = (char *)driver_name, @@ -317,8 +308,6 @@ static struct platform_driver bfin_cf_driver = { }, .probe = bfin_cf_probe, .remove = __devexit_p(bfin_cf_remove), - .suspend = bfin_cf_suspend, - .resume = bfin_cf_resume, }; static int __init bfin_cf_init(void) diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index e6ab2a47d8c..9a58862f140 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -94,7 +94,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) pci_enable_bridges(bus); pci_bus_add_devices(bus); - s->irq.AssignedIRQ = s->pci_irq; return 0; } diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index f230f6543bf..60d428be0b0 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -129,6 +129,8 @@ static void __iomem *set_cis_map(struct pcmcia_socket *s, /** * pcmcia_read_cis_mem() - low-level function to read CIS memory + * + * must be called with ops_mutex held */ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) @@ -138,7 +140,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); - mutex_lock(&s->ops_mutex); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ @@ -153,7 +154,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, if (!sys) { dev_dbg(&s->dev, "could not map memory\n"); memset(ptr, 0xff, len); - mutex_unlock(&s->ops_mutex); return -1; } @@ -184,7 +184,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, if (!sys) { dev_dbg(&s->dev, "could not map memory\n"); memset(ptr, 0xff, len); - mutex_unlock(&s->ops_mutex); return -1; } end = sys + s->map_size; @@ -198,7 +197,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, addr = 0; } } - mutex_unlock(&s->ops_mutex); dev_dbg(&s->dev, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n", *(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+2), *(u_char *)(ptr+3)); @@ -209,7 +207,8 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, /** * pcmcia_write_cis_mem() - low-level function to write CIS memory * - * Probably only useful for writing one-byte registers. + * Probably only useful for writing one-byte registers. Must be called + * with ops_mutex held. */ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, u_int len, void *ptr) @@ -220,7 +219,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); - mutex_lock(&s->ops_mutex); if (attr & IS_INDIRECT) { /* Indirect accesses use a bunch of special registers at fixed locations in common memory */ @@ -234,7 +232,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, ((cis_width) ? MAP_16BIT : 0)); if (!sys) { dev_dbg(&s->dev, "could not map memory\n"); - mutex_unlock(&s->ops_mutex); return; /* FIXME: Error */ } @@ -260,7 +257,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, sys = set_cis_map(s, card_offset, flags); if (!sys) { dev_dbg(&s->dev, "could not map memory\n"); - mutex_unlock(&s->ops_mutex); return; /* FIXME: error */ } @@ -275,7 +271,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, addr = 0; } } - mutex_unlock(&s->ops_mutex); } @@ -314,7 +309,6 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, return 0; } } - mutex_unlock(&s->ops_mutex); ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr); @@ -326,11 +320,11 @@ static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, cis->len = len; cis->attr = attr; memcpy(cis->cache, ptr, len); - mutex_lock(&s->ops_mutex); list_add(&cis->node, &s->cis_cache); - mutex_unlock(&s->ops_mutex); } } + mutex_unlock(&s->ops_mutex); + return ret; } @@ -386,6 +380,7 @@ int verify_cis_cache(struct pcmcia_socket *s) "no memory for verifying CIS\n"); return -ENOMEM; } + mutex_lock(&s->ops_mutex); list_for_each_entry(cis, &s->cis_cache, node) { int len = cis->len; @@ -395,10 +390,12 @@ int verify_cis_cache(struct pcmcia_socket *s) ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf); if (ret || memcmp(buf, cis->cache, len) != 0) { kfree(buf); + mutex_unlock(&s->ops_mutex); return -1; } } kfree(buf); + mutex_unlock(&s->ops_mutex); return 0; } @@ -1362,106 +1359,6 @@ EXPORT_SYMBOL(pcmcia_parse_tuple); /** - * pccard_read_tuple() - internal CIS tuple access - * @s: the struct pcmcia_socket where the card is inserted - * @function: the device function we loop for - * @code: which CIS code shall we look for? - * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) - * - * pccard_read_tuple() reads out one tuple and attempts to parse it - */ -int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, - cisdata_t code, void *parse) -{ - tuple_t tuple; - cisdata_t *buf; - int ret; - - buf = kmalloc(256, GFP_KERNEL); - if (buf == NULL) { - dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); - return -ENOMEM; - } - tuple.DesiredTuple = code; - tuple.Attributes = 0; - if (function == BIND_FN_ALL) - tuple.Attributes = TUPLE_RETURN_COMMON; - ret = pccard_get_first_tuple(s, function, &tuple); - if (ret != 0) - goto done; - tuple.TupleData = buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - ret = pccard_get_tuple_data(s, &tuple); - if (ret != 0) - goto done; - ret = pcmcia_parse_tuple(&tuple, parse); -done: - kfree(buf); - return ret; -} - - -/** - * pccard_loop_tuple() - loop over tuples in the CIS - * @s: the struct pcmcia_socket where the card is inserted - * @function: the device function we loop for - * @code: which CIS code shall we look for? - * @parse: buffer where the tuple shall be parsed (or NULL, if no parse) - * @priv_data: private data to be passed to the loop_tuple function. - * @loop_tuple: function to call for each CIS entry of type @function. IT - * gets passed the raw tuple, the paresed tuple (if @parse is - * set) and @priv_data. - * - * pccard_loop_tuple() loops over all CIS entries of type @function, and - * calls the @loop_tuple function for each entry. If the call to @loop_tuple - * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. - */ -int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, - cisdata_t code, cisparse_t *parse, void *priv_data, - int (*loop_tuple) (tuple_t *tuple, - cisparse_t *parse, - void *priv_data)) -{ - tuple_t tuple; - cisdata_t *buf; - int ret; - - buf = kzalloc(256, GFP_KERNEL); - if (buf == NULL) { - dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); - return -ENOMEM; - } - - tuple.TupleData = buf; - tuple.TupleDataMax = 255; - tuple.TupleOffset = 0; - tuple.DesiredTuple = code; - tuple.Attributes = 0; - - ret = pccard_get_first_tuple(s, function, &tuple); - while (!ret) { - if (pccard_get_tuple_data(s, &tuple)) - goto next_entry; - - if (parse) - if (pcmcia_parse_tuple(&tuple, parse)) - goto next_entry; - - ret = loop_tuple(&tuple, parse, priv_data); - if (!ret) - break; - -next_entry: - ret = pccard_get_next_tuple(s, function, &tuple); - } - - kfree(buf); - return ret; -} - - -/** * pccard_validate_cis() - check whether card has a sensible CIS * @s: the struct pcmcia_socket we are to check * @info: returns the number of tuples in the (valid) CIS, or 0 @@ -1484,6 +1381,11 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info) if (!s) return -EINVAL; + if (s->functions) { + WARN_ON(1); + return -EINVAL; + } + /* We do not want to validate the CIS cache... */ mutex_lock(&s->ops_mutex); destroy_cis_cache(s); @@ -1639,7 +1541,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, count = 0; else { struct pcmcia_socket *s; - unsigned int chains; + unsigned int chains = 1; if (off + count > size) count = size - off; @@ -1648,7 +1550,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, if (!(s->state & SOCKET_PRESENT)) return -ENODEV; - if (pccard_validate_cis(s, &chains)) + if (!s->functions && pccard_validate_cis(s, &chains)) return -EIO; if (!chains) return -ENODATA; diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index e679e708db6..976d80706ea 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -76,65 +76,6 @@ DECLARE_RWSEM(pcmcia_socket_list_rwsem); EXPORT_SYMBOL(pcmcia_socket_list_rwsem); -/* - * Low-level PCMCIA socket drivers need to register with the PCCard - * core using pcmcia_register_socket. - * - * socket drivers are expected to use the following callbacks in their - * .drv struct: - * - pcmcia_socket_dev_suspend - * - pcmcia_socket_dev_resume - * These functions check for the appropriate struct pcmcia_soket arrays, - * and pass them to the low-level functions pcmcia_{suspend,resume}_socket - */ -static int socket_early_resume(struct pcmcia_socket *skt); -static int socket_late_resume(struct pcmcia_socket *skt); -static int socket_resume(struct pcmcia_socket *skt); -static int socket_suspend(struct pcmcia_socket *skt); - -static void pcmcia_socket_dev_run(struct device *dev, - int (*cb)(struct pcmcia_socket *)) -{ - struct pcmcia_socket *socket; - - down_read(&pcmcia_socket_list_rwsem); - list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { - if (socket->dev.parent != dev) - continue; - mutex_lock(&socket->skt_mutex); - cb(socket); - mutex_unlock(&socket->skt_mutex); - } - up_read(&pcmcia_socket_list_rwsem); -} - -int pcmcia_socket_dev_suspend(struct device *dev) -{ - pcmcia_socket_dev_run(dev, socket_suspend); - return 0; -} -EXPORT_SYMBOL(pcmcia_socket_dev_suspend); - -void pcmcia_socket_dev_early_resume(struct device *dev) -{ - pcmcia_socket_dev_run(dev, socket_early_resume); -} -EXPORT_SYMBOL(pcmcia_socket_dev_early_resume); - -void pcmcia_socket_dev_late_resume(struct device *dev) -{ - pcmcia_socket_dev_run(dev, socket_late_resume); -} -EXPORT_SYMBOL(pcmcia_socket_dev_late_resume); - -int pcmcia_socket_dev_resume(struct device *dev) -{ - pcmcia_socket_dev_run(dev, socket_resume); - return 0; -} -EXPORT_SYMBOL(pcmcia_socket_dev_resume); - - struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt) { struct device *dev = get_device(&skt->dev); @@ -396,7 +337,6 @@ static void socket_shutdown(struct pcmcia_socket *s) s->socket = dead_socket; s->ops->init(s); s->ops->set_socket(s, &s->socket); - s->irq.AssignedIRQ = s->irq.Config = 0; s->lock_count = 0; kfree(s->fake_cis); s->fake_cis = NULL; @@ -578,12 +518,18 @@ static int socket_early_resume(struct pcmcia_socket *skt) static int socket_late_resume(struct pcmcia_socket *skt) { + int ret; + mutex_lock(&skt->ops_mutex); skt->state &= ~SOCKET_SUSPEND; mutex_unlock(&skt->ops_mutex); - if (!(skt->state & SOCKET_PRESENT)) - return socket_insert(skt); + if (!(skt->state & SOCKET_PRESENT)) { + ret = socket_insert(skt); + if (ret == -ENODEV) + ret = 0; + return ret; + } if (skt->resume_status) { socket_shutdown(skt); @@ -724,20 +670,22 @@ static int pccardd(void *__skt) socket_remove(skt); if (sysfs_events & PCMCIA_UEVENT_INSERT) socket_insert(skt); - if ((sysfs_events & PCMCIA_UEVENT_RESUME) && - !(skt->state & SOCKET_CARDBUS)) { - ret = socket_resume(skt); - if (!ret && skt->callback) - skt->callback->resume(skt); - } if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) && !(skt->state & SOCKET_CARDBUS)) { if (skt->callback) ret = skt->callback->suspend(skt); else ret = 0; - if (!ret) + if (!ret) { socket_suspend(skt); + msleep(100); + } + } + if ((sysfs_events & PCMCIA_UEVENT_RESUME) && + !(skt->state & SOCKET_CARDBUS)) { + ret = socket_resume(skt); + if (!ret && skt->callback) + skt->callback->resume(skt); } if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && !(skt->state & SOCKET_CARDBUS)) { @@ -919,11 +867,66 @@ static void pcmcia_release_socket_class(struct class *data) } +#ifdef CONFIG_PM + +static int __pcmcia_pm_op(struct device *dev, + int (*callback) (struct pcmcia_socket *skt)) +{ + struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev); + int ret; + + mutex_lock(&s->skt_mutex); + ret = callback(s); + mutex_unlock(&s->skt_mutex); + + return ret; +} + +static int pcmcia_socket_dev_suspend_noirq(struct device *dev) +{ + return __pcmcia_pm_op(dev, socket_suspend); +} + +static int pcmcia_socket_dev_resume_noirq(struct device *dev) +{ + return __pcmcia_pm_op(dev, socket_early_resume); +} + +static int pcmcia_socket_dev_resume(struct device *dev) +{ + return __pcmcia_pm_op(dev, socket_late_resume); +} + +static const struct dev_pm_ops pcmcia_socket_pm_ops = { + /* dev_resume may be called with IRQs enabled */ + SET_SYSTEM_SLEEP_PM_OPS(NULL, + pcmcia_socket_dev_resume) + + /* late suspend must be called with IRQs disabled */ + .suspend_noirq = pcmcia_socket_dev_suspend_noirq, + .freeze_noirq = pcmcia_socket_dev_suspend_noirq, + .poweroff_noirq = pcmcia_socket_dev_suspend_noirq, + + /* early resume must be called with IRQs disabled */ + .resume_noirq = pcmcia_socket_dev_resume_noirq, + .thaw_noirq = pcmcia_socket_dev_resume_noirq, + .restore_noirq = pcmcia_socket_dev_resume_noirq, +}; + +#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops) + +#else /* CONFIG_PM */ + +#define PCMCIA_SOCKET_CLASS_PM_OPS NULL + +#endif /* CONFIG_PM */ + struct class pcmcia_socket_class = { .name = "pcmcia_socket", .dev_uevent = pcmcia_socket_uevent, .dev_release = pcmcia_release_socket, .class_release = pcmcia_release_socket_class, + .pm = PCMCIA_SOCKET_CLASS_PM_OPS, }; EXPORT_SYMBOL(pcmcia_socket_class); diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index f95864c2191..4126a75445e 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -52,13 +52,11 @@ struct cis_cache_entry { struct pccard_resource_ops { int (*validate_mem) (struct pcmcia_socket *s); - int (*adjust_io_region) (struct resource *res, - unsigned long r_start, - unsigned long r_end, - struct pcmcia_socket *s); - struct resource* (*find_io) (unsigned long base, int num, - unsigned long align, - struct pcmcia_socket *s); + int (*find_io) (struct pcmcia_socket *s, + unsigned int attr, + unsigned int *base, + unsigned int num, + unsigned int align); struct resource* (*find_mem) (unsigned long base, unsigned long num, unsigned long align, int low, struct pcmcia_socket *s); @@ -89,6 +87,14 @@ struct pccard_resource_ops { /* + * Stuff internal to module "pcmcia_rsrc": + */ +extern int static_init(struct pcmcia_socket *s); +extern struct resource *pcmcia_make_resource(unsigned long start, + unsigned long end, + int flags, const char *name); + +/* * Stuff internal to module "pcmcia_core": */ @@ -149,6 +155,8 @@ extern struct resource *pcmcia_find_mem_region(u_long base, int low, struct pcmcia_socket *s); +void pcmcia_cleanup_irq(struct pcmcia_socket *s); +int pcmcia_setup_irq(struct pcmcia_device *p_dev); /* cistpl.c */ extern struct bin_attribute pccard_cis_attr; diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 9254ab0b29b..0f4cc3f0002 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c @@ -26,6 +26,7 @@ #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/resource.h> +#include <linux/slab.h> #include <linux/spinlock.h> #include <pcmcia/cs_types.h> @@ -145,7 +146,6 @@ static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data) static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) { int ret; - unsigned long flags; if (sock->stschg_irq != -1) { ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq, @@ -161,8 +161,6 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) * active one disabled. */ if (sock->board_type == BOARD_TYPE_DB1200) { - local_irq_save(flags); - ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq, IRQF_DISABLED, "pcmcia_insert", sock); if (ret) @@ -172,17 +170,14 @@ static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock) IRQF_DISABLED, "pcmcia_eject", sock); if (ret) { free_irq(sock->insert_irq, sock); - local_irq_restore(flags); goto out1; } - /* disable the currently active one */ + /* enable the currently silent one */ if (db1200_card_inserted(sock)) - disable_irq_nosync(sock->insert_irq); + enable_irq(sock->eject_irq); else - disable_irq_nosync(sock->eject_irq); - - local_irq_restore(flags); + enable_irq(sock->insert_irq); } else { /* all other (older) Db1x00 boards use a GPIO to show * card detection status: use both-edge triggers. @@ -558,37 +553,10 @@ static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int db1x_pcmcia_suspend(struct device *dev) -{ - return pcmcia_socket_dev_suspend(dev); -} - -static int db1x_pcmcia_resume(struct device *dev) -{ - return pcmcia_socket_dev_resume(dev); -} - -static struct dev_pm_ops db1x_pcmcia_pmops = { - .resume = db1x_pcmcia_resume, - .suspend = db1x_pcmcia_suspend, - .thaw = db1x_pcmcia_resume, - .freeze = db1x_pcmcia_suspend, -}; - -#define DB1XXX_SS_PMOPS &db1x_pcmcia_pmops - -#else - -#define DB1XXX_SS_PMOPS NULL - -#endif - |