aboutsummaryrefslogtreecommitdiff
path: root/drivers/pcmcia
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Kconfig25
-rw-r--r--drivers/pcmcia/Makefile10
-rw-r--r--drivers/pcmcia/at91_cf.c3
-rw-r--r--drivers/pcmcia/au1000_generic.c14
-rw-r--r--drivers/pcmcia/bcm63xx_pcmcia.c1
-rw-r--r--drivers/pcmcia/bfin_cf_pcmcia.c15
-rw-r--r--drivers/pcmcia/cardbus.c1
-rw-r--r--drivers/pcmcia/cistpl.c130
-rw-r--r--drivers/pcmcia/cs.c141
-rw-r--r--drivers/pcmcia/cs_internal.h22
-rw-r--r--drivers/pcmcia/db1xxx_ss.c40
-rw-r--r--drivers/pcmcia/ds.c128
-rw-r--r--drivers/pcmcia/electra_cf.c1
-rw-r--r--drivers/pcmcia/i82092.c17
-rw-r--r--drivers/pcmcia/i82365.c12
-rw-r--r--drivers/pcmcia/i82365.h1
-rw-r--r--drivers/pcmcia/m32r_cfc.c12
-rw-r--r--drivers/pcmcia/m32r_pcc.c13
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c18
-rw-r--r--drivers/pcmcia/omap_cf.c15
-rw-r--r--drivers/pcmcia/pcmcia_cis.c356
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c31
-rw-r--r--drivers/pcmcia/pcmcia_resource.c675
-rw-r--r--drivers/pcmcia/pd6729.c82
-rw-r--r--drivers/pcmcia/pxa2xx_base.c9
-rw-r--r--drivers/pcmcia/pxa2xx_vpac270.c229
-rw-r--r--drivers/pcmcia/rsrc_iodyn.c172
-rw-r--r--drivers/pcmcia/rsrc_mgr.c113
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c230
-rw-r--r--drivers/pcmcia/sa1100_generic.c14
-rw-r--r--drivers/pcmcia/sa1111_generic.c38
-rw-r--r--drivers/pcmcia/sa11xx_base.c1
-rw-r--r--drivers/pcmcia/socket_sysfs.c1
-rw-r--r--drivers/pcmcia/tcic.c13
-rw-r--r--drivers/pcmcia/ti113x.h37
-rw-r--r--drivers/pcmcia/vrc4171_card.c18
-rw-r--r--drivers/pcmcia/xxs1500_ss.c1
-rw-r--r--drivers/pcmcia/yenta_socket.c71
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
-