[PATCH kernel 2.6.33] pd6729: remove irq_list parameter

2010-02-27 Thread Komuro

pd6729: 
 remove irq_list parameter.
 it should be set by /etc/pcmcia/config.opts.


Signed-off-by: Komuro 

---

--- linux-2.6.33/drivers/pcmcia/pd6729.c.orig   2010-02-28 08:36:55.0 
+0900
+++ linux-2.6.33/drivers/pcmcia/pd6729.c2010-02-28 08:41:55.0 
+0900
@@ -48,23 +48,13 @@ MODULE_AUTHOR("Jun Komuro http://lists.infradead.org/mailman/listinfo/linux-pcmcia


Re: [PATCH 20/49] cm4000_cs.c: Remove unnecessary cast

2010-02-27 Thread Harald Welte
On Sat, Feb 27, 2010 at 11:42:15AM +0100, Dominik Brodowski wrote:
> From: H Hartley Sweeten 
> 
> The struct file 'private_data' member is a void *, the cast is not needed.
> 
> Signed-off-by: H Hartley Sweeten 
> Cc: Harald Welte 

Acked-by: Harald Welte 

> Signed-off-by: Dominik Brodowski 
> ---
>  drivers/char/pcmcia/cm4000_cs.c |2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
> index 2db4c0a..c9bc896 100644
> --- a/drivers/char/pcmcia/cm4000_cs.c
> +++ b/drivers/char/pcmcia/cm4000_cs.c
> @@ -1047,7 +1047,7 @@ release_io:
>  static ssize_t cmm_write(struct file *filp, const char __user *buf,
>size_t count, loff_t *ppos)
>  {
> - struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
> + struct cm4000_dev *dev = filp->private_data;
>   unsigned int iobase = dev->p_dev->io.BasePort1;
>   unsigned short s;
>   unsigned char tmp;
> -- 
> 1.6.3.3
> 

-- 
- Harald Weltehttp://laforge.gnumonks.org/

"Privacy in residential applications is a desirable marketing option."
  (ETSI EN 300 175-7 Ch. A6)

___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 39/49] pcmcia: use pccardd to handle eject, insert, suspend and resume requests

2010-02-27 Thread Dominik Brodowski
This avoids any sysfs-related deadlock (or lockdep warning), such
as reported at http://lkml.org/lkml/2010/1/17/88 .

Reported-by: Ming Lei 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c   |  177 +---
 drivers/pcmcia/cs_internal.h  |   10 +-
 drivers/pcmcia/pcmcia_ioctl.c |8 +-
 drivers/pcmcia/socket_sysfs.c |   26 +++---
 include/pcmcia/ss.h   |3 +-
 5 files changed, 83 insertions(+), 141 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 7ba45b0..823ecda 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -505,7 +505,10 @@ static int socket_insert(struct pcmcia_socket *skt)
dev_dbg(&skt->dev, "insert\n");
 
mutex_lock(&skt->ops_mutex);
-   WARN_ON(skt->state & SOCKET_INUSE);
+   if (skt->state & SOCKET_INUSE) {
+   mutex_unlock(&skt->ops_mutex);
+   return -EINVAL;
+   }
skt->state |= SOCKET_INUSE;
 
ret = socket_setup(skt, setup_delay);
@@ -682,16 +685,19 @@ static int pccardd(void *__skt)
for (;;) {
unsigned long flags;
unsigned int events;
+   unsigned int sysfs_events;
 
set_current_state(TASK_INTERRUPTIBLE);
 
spin_lock_irqsave(&skt->thread_lock, flags);
events = skt->thread_events;
skt->thread_events = 0;
+   sysfs_events = skt->sysfs_events;
+   skt->sysfs_events = 0;
spin_unlock_irqrestore(&skt->thread_lock, flags);
 
+   mutex_lock(&skt->skt_mutex);
if (events) {
-   mutex_lock(&skt->skt_mutex);
if (events & SS_DETECT)
socket_detect_change(skt);
if (events & SS_BATDEAD)
@@ -700,10 +706,34 @@ static int pccardd(void *__skt)
send_event(skt, CS_EVENT_BATTERY_LOW, 
CS_EVENT_PRI_LOW);
if (events & SS_READY)
send_event(skt, CS_EVENT_READY_CHANGE, 
CS_EVENT_PRI_LOW);
-   mutex_unlock(&skt->skt_mutex);
-   continue;
}
 
+   if (sysfs_events) {
+   if (sysfs_events & PCMCIA_UEVENT_EJECT)
+   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)
+   socket_suspend(skt);
+   }
+   }
+   mutex_unlock(&skt->skt_mutex);
+
+   if (events || sysfs_events)
+   continue;
+
if (kthread_should_stop())
break;
 
@@ -745,6 +775,30 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int 
events)
 } /* pcmcia_parse_events */
 EXPORT_SYMBOL(pcmcia_parse_events);
 
+/**
+ * pcmcia_parse_uevents() - tell pccardd to issue manual commands
+ * @s: the PCMCIA socket we wan't to command
+ * @events:events to pass to pccardd
+ *
+ * userspace-issued insert, eject, suspend and resume commands must be
+ * handled by pccardd to avoid any sysfs-related deadlocks. Valid events
+ * are PCMCIA_UEVENT_EJECT (for eject), PCMCIA_UEVENT__INSERT (for insert),
+ * PCMCIA_UEVENT_RESUME (for resume) and PCMCIA_UEVENT_SUSPEND (for suspend).
+ */
+void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events)
+{
+   unsigned long flags;
+   dev_dbg(&s->dev, "parse_uevents: events %08x\n", events);
+   if (s->thread) {
+   spin_lock_irqsave(&s->thread_lock, flags);
+   s->sysfs_events |= events;
+   spin_unlock_irqrestore(&s->thread_lock, flags);
+
+   wake_up_process(s->thread);
+   }
+}
+EXPORT_SYMBOL(pcmcia_parse_uevents);
+
 
 /* register pcmcia_callback */
 int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
@@ -828,121 +882,6 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
 EXPORT_SYMBOL(pcmcia_reset_card);
 
 
-/* These shut down or wake up a socket.  They are sort of user
- * initiated versions of the 

[PATCH 34/49] pcmcia: simplify locking

2010-02-27 Thread Dominik Brodowski
replace pcmcia_socket->lock and pcmcia_dev_list_lock by using the
per-socket "ops_mutex", as we do neither need different locks
nor a spinlock here.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c   |2 -
 drivers/pcmcia/cs_internal.h  |2 -
 drivers/pcmcia/ds.c   |   70 -
 drivers/pcmcia/pcmcia_ioctl.c |   36 +
 drivers/pcmcia/rsrc_mgr.c |6 +--
 drivers/pcmcia/socket_sysfs.c |5 +--
 include/pcmcia/ss.h   |7 ++--
 7 files changed, 51 insertions(+), 77 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index cc0ba8a..13277ee 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -175,8 +175,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
 
dev_dbg(&socket->dev, "pcmcia_register_socket(0x%p)\n", socket->ops);
 
-   spin_lock_init(&socket->lock);
-
/* try to obtain a socket number [yes, it gets ugly if we
 * register more than 2^sizeof(unsigned int) pcmcia
 * sockets... but the socket number is deprecated
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 76ac444..bd386d7 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -182,8 +182,6 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t 
*tuple);
 
 #ifdef CONFIG_PCMCIA_IOCTL
 /* ds.c */
-extern spinlock_t pcmcia_dev_list_lock;
-
 extern struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev);
 extern void pcmcia_put_dev(struct pcmcia_device *p_dev);
 
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0eb242c..4c40db8 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -42,8 +42,6 @@ MODULE_DESCRIPTION("PCMCIA Driver Services");
 MODULE_LICENSE("GPL");
 
 
-spinlock_t pcmcia_dev_list_lock;
-
 /**/
 
 static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
@@ -265,7 +263,6 @@ static int pcmcia_device_probe(struct device *dev)
struct pcmcia_device_id *did;
struct pcmcia_socket *s;
cistpl_config_t cis_config;
-   unsigned long flags;
int ret = 0;
 
dev = get_device(dev);
@@ -316,11 +313,11 @@ static int pcmcia_device_probe(struct device *dev)
goto put_module;
}
 
-   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   mutex_lock(&s->ops_mutex);
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0);
-   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+   mutex_unlock(&s->ops_mutex);
 
 put_module:
if (ret)
@@ -339,28 +336,27 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, 
struct pcmcia_device *le
 {
struct pcmcia_device*p_dev;
struct pcmcia_device*tmp;
-   unsigned long   flags;
 
dev_dbg(leftover ? &leftover->dev : &s->dev,
   "pcmcia_card_remove(%d) %s\n", s->sock,
   leftover ? leftover->devname : "");
 
-   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   mutex_lock(&s->ops_mutex);
if (!leftover)
s->device_count = 0;
else
s->device_count = 1;
-   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+   mutex_unlock(&s->ops_mutex);
 
/* unregister all pcmcia_devices registered with this socket, except 
leftover */
list_for_each_entry_safe(p_dev, tmp, &s->devices_list, 
socket_device_list) {
if (p_dev == leftover)
continue;
 
-   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   mutex_lock(&s->ops_mutex);
list_del(&p_dev->socket_device_list);
p_dev->_removed = 1;
-   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+   mutex_unlock(&s->ops_mutex);
 
dev_dbg(&p_dev->dev, "unregistering device\n");
device_unregister(&p_dev->dev);
@@ -507,7 +503,6 @@ static DEFINE_MUTEX(device_add_lock);
 struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int 
function)
 {
struct pcmcia_device *p_dev, *tmp_dev;
-   unsigned long flags;
 
s = pcmcia_get_socket(s);
if (!s)
@@ -521,9 +516,9 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
if (!p_dev)
goto err_put;
 
-   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   mutex_lock(&s->ops_mutex);
p_dev->device_no = (s->device_count++);
-   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+   mutex_unlock(&s->ops_mutex);
 
/* max of 4 devices per card */
if (p_dev->device_no >= 4)
@@ -546,7 +541,7 @@ struct pcmcia_device *pcm

[PATCH 26/49] pcmcia/i82365: fix typos in comments

2010-02-27 Thread Dominik Brodowski
From: Wolfram Sang 

Signed-off-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/i82365.h |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/i82365.h b/drivers/pcmcia/i82365.h
index 622860c..849ef1b 100644
--- a/drivers/pcmcia/i82365.h
+++ b/drivers/pcmcia/i82365.h
@@ -77,8 +77,8 @@
 #define I365_VPP2_5V   0x04/* Vpp2 = 5.0v */
 #define I365_VPP2_12V  0x08/* Vpp2 = 12.0v */
 #define I365_VPP1_MASK 0x03/* Mask for turning off Vpp1 */
-#define I365_VPP1_5V   0x01/* Vpp2 = 5.0v */
-#define I365_VPP1_12V  0x02/* Vpp2 = 12.0v */
+#define I365_VPP1_5V   0x01/* Vpp1 = 5.0v */
+#define I365_VPP1_12V  0x02/* Vpp1 = 12.0v */
 
 /* Flags for I365_INTCTL */
 #define I365_RING_ENA  0x80
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 17/49] pcmcia: remove remaining rsrc_mgr indirections

2010-02-27 Thread Dominik Brodowski
Move rsrc_mgr indirections only used by the pcmcia module to the
pcmcia module.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs_internal.h |   15 +++
 drivers/pcmcia/pcmcia_resource.c |   16 
 drivers/pcmcia/rsrc_mgr.c|   20 
 3 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 3f438af..76ac444 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -133,14 +133,6 @@ int pcmcia_insert_card(struct pcmcia_socket *skt);
 struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
 void pcmcia_put_socket(struct pcmcia_socket *skt);
 
-/* rsrc_mgr.c */
-int pcmcia_validate_mem(struct pcmcia_socket *s);
-struct resource *pcmcia_find_mem_region(u_long base,
-   u_long num,
-   u_long align,
-   int low,
-   struct pcmcia_socket *s);
-
 /*
  * Stuff internal to module "pcmcia".
  */
@@ -149,6 +141,13 @@ extern struct bus_type pcmcia_bus_type;
 
 /* pcmcia_resource.c */
 extern int pcmcia_release_configuration(struct pcmcia_device *p_dev);
+extern int pcmcia_validate_mem(struct pcmcia_socket *s);
+extern struct resource *pcmcia_find_mem_region(u_long base,
+  u_long num,
+  u_long align,
+  int low,
+  struct pcmcia_socket *s);
+
 
 /* cistpl.c */
 extern struct bin_attribute pccard_cis_attr;
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 880b0b6..8ceb7ab 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -60,6 +60,22 @@ static struct resource *pcmcia_find_io_region(unsigned long 
base, int num,
return NULL;
 }
 
+int pcmcia_validate_mem(struct pcmcia_socket *s)
+{
+   if (s->resource_ops->validate_mem)
+   return s->resource_ops->validate_mem(s);
+   /* if there is no callback, we can assume that everything is OK */
+   return 0;
+}
+
+struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
+int low, struct pcmcia_socket *s)
+{
+   if (s->resource_ops->find_mem)
+   return s->resource_ops->find_mem(base, num, align, low, s);
+   return NULL;
+}
+
 
 /** alloc_io_space
  *
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 81540c4..cdd30c1 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -21,26 +21,6 @@
 #include 
 #include "cs_internal.h"
 
-
-int pcmcia_validate_mem(struct pcmcia_socket *s)
-{
-   if (s->resource_ops->validate_mem)
-   return s->resource_ops->validate_mem(s);
-   /* if there is no callback, we can assume that everything is OK */
-   return 0;
-}
-EXPORT_SYMBOL(pcmcia_validate_mem);
-
-struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
-int low, struct pcmcia_socket *s)
-{
-   if (s->resource_ops->find_mem)
-   return s->resource_ops->find_mem(base, num, align, low, s);
-   return NULL;
-}
-EXPORT_SYMBOL(pcmcia_find_mem_region);
-
-
 static int static_init(struct pcmcia_socket *s)
 {
unsigned long flags;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 08/49] pcmcia: call CIS cleanup from ds.c

2010-02-27 Thread Dominik Brodowski
As ds.c is the only real user of CIS access functions, call the
cleanup functions from ds.c, too.

Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c |3 ---
 drivers/pcmcia/ds.c |3 +++
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 8c51493..9d8b9c1 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -283,8 +283,6 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
if (socket->thread)
kthread_stop(socket->thread);
 
-   release_cis_mem(socket);
-
/* remove from our own list */
down_write(&pcmcia_socket_list_rwsem);
list_del(&socket->socket_list);
@@ -399,7 +397,6 @@ static void socket_shutdown(struct pcmcia_socket *s)
s->ops->set_socket(s, &s->socket);
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
-   destroy_cis_cache(s);
kfree(s->fake_cis);
s->fake_cis = NULL;
 #ifdef CONFIG_CARDBUS
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 87e0639..7bb52b0 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1241,10 +1241,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t 
event, int priority)
s->pcmcia_state.present = 0;
pcmcia_card_remove(skt, NULL);
handle_event(skt, event);
+   destroy_cis_cache(s);
break;
 
case CS_EVENT_CARD_INSERTION:
s->pcmcia_state.present = 1;
+   destroy_cis_cache(s); /* to be on the safe side... */
pcmcia_card_add(skt);
handle_event(skt, event);
break;
@@ -1366,6 +1368,7 @@ static void pcmcia_bus_remove_socket(struct device *dev,
/* unregister any unbound devices */
mutex_lock(&socket->skt_mutex);
pcmcia_card_remove(socket, NULL);
+   release_cis_mem(socket);
mutex_unlock(&socket->skt_mutex);
 
pcmcia_put_socket(socket);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 27/49] pcmcia: add locking to set_mem_map()

2010-02-27 Thread Dominik Brodowski
Protect the pccard_operations callback "set_mem_map" by a new
mutex ops_mutex. This mutex also protects the following values
in struct pcmcia_socket:

pccard_mem_map  win[]
pccard_mem_map  cis_mem
void __iomem*cis_virt

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c  |6 ++
 drivers/pcmcia/cs.c  |1 +
 drivers/pcmcia/pcmcia_resource.c |   20 +++-
 drivers/pcmcia/rsrc_nonstatic.c  |8 
 include/pcmcia/ss.h  |2 ++
 5 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 936417c..9ad66c9 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -64,6 +64,7 @@ module_param(cis_width, int, 0444);
 
 void release_cis_mem(struct pcmcia_socket *s)
 {
+mutex_lock(&s->ops_mutex);
 if (s->cis_mem.flags & MAP_ACTIVE) {
s->cis_mem.flags &= ~MAP_ACTIVE;
s->ops->set_mem_map(s, &s->cis_mem);
@@ -75,6 +76,7 @@ void release_cis_mem(struct pcmcia_socket *s)
iounmap(s->cis_virt);
s->cis_virt = NULL;
 }
+mutex_unlock(&s->ops_mutex);
 }
 
 /*
@@ -88,11 +90,13 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
pccard_mem_map *mem = &s->cis_mem;
int ret;
 
+   mutex_lock(&s->ops_mutex);
if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 
0, s);
if (mem->res == NULL) {
dev_printk(KERN_NOTICE, &s->dev,
   "cs: unable to map card memory!\n");
+   mutex_unlock(&s->ops_mutex);
return NULL;
}
s->cis_virt = NULL;
@@ -108,6 +112,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
if (ret) {
iounmap(s->cis_virt);
s->cis_virt = NULL;
+   mutex_unlock(&s->ops_mutex);
return NULL;
}
 
@@ -117,6 +122,7 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
s->cis_virt = ioremap(mem->static_start, s->map_size);
}
 
+   mutex_unlock(&s->ops_mutex);
return s->cis_virt;
 }
 
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 43c90f6..91aa1f2 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -222,6 +222,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
init_completion(&socket->socket_released);
init_completion(&socket->thread_done);
mutex_init(&socket->skt_mutex);
+   mutex_init(&socket->ops_mutex);
spin_lock_init(&socket->thread_lock);
 
if (socket->resource_ops->init) {
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 8ceb7ab..f31ba89 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -223,6 +223,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, 
window_handle_t wh,
memreq_t *req)
 {
struct pcmcia_socket *s = p_dev->socket;
+   int ret;
 
wh--;
if (wh >= MAX_WIN)
@@ -231,12 +232,13 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, 
window_handle_t wh,
dev_dbg(&s->dev, "failure: requested page is zero\n");
return -EINVAL;
}
+   mutex_lock(&s->ops_mutex);
s->win[wh].card_start = req->CardOffset;
-   if (s->ops->set_mem_map(s, &s->win[wh]) != 0) {
-   dev_dbg(&s->dev, "failed to set_mem_map\n");
-   return -EIO;
-   }
-   return 0;
+   ret = s->ops->set_mem_map(s, &s->win[wh]);
+   if (ret)
+   dev_warn(&s->dev, "failed to set_mem_map\n");
+   mutex_unlock(&s->ops_mutex);
+   return ret;
 } /* pcmcia_map_mem_page */
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
@@ -437,10 +439,12 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, 
window_handle_t wh)
if (wh >= MAX_WIN)
return -EINVAL;
 
+   mutex_lock(&s->ops_mutex);
win = &s->win[wh];
 
if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
dev_dbg(&s->dev, "not releasing unknown window\n");
+   mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
 
@@ -456,6 +460,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, 
window_handle_t wh)
win->res = NULL;
}
p_dev->_win &= ~CLIENT_WIN_REQ(wh);
+   mutex_unlock(&s->ops_mutex);
 
return 0;
 } /* pcmcia_release_window */
@@ -829,6 +834,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, 
win_req_t *req, window_ha
return -EINVAL;
}
 
+   mutex_lock(&s->ops_mutex);
win = &s->win[w];
 
if (!(s->f

[PATCH 16/49] pcmcia: move cistpl.c into pcmcia module

2010-02-27 Thread Dominik Brodowski
As PCMCIA is the only real user of CIS access functions, include
cistpl.c in the PCMCIA module, not in the PCMCIA & CardBus core
module.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/Makefile |4 +-
 drivers/pcmcia/cistpl.c |  158 ---
 drivers/pcmcia/cs_internal.h|   44 +--
 drivers/pcmcia/ds.c |   10 +++
 drivers/pcmcia/rsrc_nonstatic.c |4 +-
 drivers/pcmcia/socket_sysfs.c   |  150 +
 6 files changed, 183 insertions(+), 187 deletions(-)

diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 83ff802..3c83f68 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -2,11 +2,11 @@
 # Makefile for the kernel pcmcia subsystem (c/o David Hinds)
 #
 
-pcmcia_core-y  += cs.o cistpl.o rsrc_mgr.o 
socket_sysfs.o
+pcmcia_core-y  += cs.o rsrc_mgr.o 
socket_sysfs.o
 pcmcia_core-$(CONFIG_CARDBUS)  += cardbus.o
 obj-$(CONFIG_PCCARD)   += pcmcia_core.o
 
-pcmcia-y   += ds.o pcmcia_resource.o
+pcmcia-y   += ds.o pcmcia_resource.o 
cistpl.o
 pcmcia-$(CONFIG_PCMCIA_IOCTL)  += pcmcia_ioctl.o
 obj-$(CONFIG_PCMCIA)   += pcmcia.o
 
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 368367c..936417c 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -76,7 +76,6 @@ void release_cis_mem(struct pcmcia_socket *s)
s->cis_virt = NULL;
 }
 }
-EXPORT_SYMBOL(release_cis_mem);
 
 /*
  * Map the card memory at "card_offset" into virtual space.
@@ -195,7 +194,6 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, 
u_int addr,
  *(u_char *)(ptr+2), *(u_char *)(ptr+3));
 return 0;
 }
-EXPORT_SYMBOL(pcmcia_read_cis_mem);
 
 
 void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
@@ -254,7 +252,6 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int 
attr, u_int addr,
}
 }
 }
-EXPORT_SYMBOL(pcmcia_write_cis_mem);
 
 
 /*==
@@ -335,7 +332,6 @@ void destroy_cis_cache(struct pcmcia_socket *s)
kfree(cis);
}
 }
-EXPORT_SYMBOL(destroy_cis_cache);
 
 /*==
 
@@ -374,7 +370,6 @@ int verify_cis_cache(struct pcmcia_socket *s)
kfree(buf);
return 0;
 }
-EXPORT_SYMBOL(verify_cis_cache);
 
 /*==
 
@@ -400,7 +395,6 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
memcpy(s->fake_cis, data, len);
return 0;
 }
-EXPORT_SYMBOL(pcmcia_replace_cis);
 
 /*==
 
@@ -446,7 +440,6 @@ int pccard_get_first_tuple(struct pcmcia_socket *s, 
unsigned int function, tuple
 }
 return pccard_get_next_tuple(s, function, tuple);
 }
-EXPORT_SYMBOL(pccard_get_first_tuple);
 
 static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
 {
@@ -582,7 +575,6 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned 
int function, tuple_
 tuple->CISOffset = ofs + 2;
 return 0;
 }
-EXPORT_SYMBOL(pccard_get_next_tuple);
 
 /**/
 
@@ -606,7 +598,6 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t 
*tuple)
   _MIN(len, tuple->TupleDataMax), tuple->TupleData);
 return 0;
 }
-EXPORT_SYMBOL(pccard_get_tuple_data);
 
 
 /*==
@@ -1379,7 +1370,6 @@ done:
 kfree(buf);
 return ret;
 }
-EXPORT_SYMBOL(pccard_read_tuple);
 
 
 /**
@@ -1439,7 +1429,6 @@ next_entry:
kfree(buf);
return ret;
 }
-EXPORT_SYMBOL(pccard_loop_tuple);
 
 
 /**
@@ -1533,4 +1522,149 @@ done:
kfree(p);
return ret;
 }
-EXPORT_SYMBOL(pccard_validate_cis);
+
+
+#define to_socket(_dev) container_of(_dev, struct pcmcia_socket, dev)
+
+static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf,
+ loff_t off, size_t count)
+{
+   tuple_t tuple;
+   int status, i;
+   loff_t pointer = 0;
+   ssize_t ret = 0;
+   u_char *tuplebuffer;
+   u_char *tempbuffer;
+
+   tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL);
+   if (!tuplebuffer)
+   return -ENOMEM;
+
+   tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL);
+   if (!tempbuffer) {
+   ret = -ENOMEM;
+   goto free_tuple;
+   }
+
+   memset(&tuple, 0, sizeof(tuple_t));
+
+   tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
+   tuple.DesiredTuple = RETURN_FIRST_TUPLE;
+   tuple.TupleOffset = 0

[PATCH 46/49] pcmcia: use read_cis_mem return value

2010-02-27 Thread Dominik Brodowski
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |   63 --
 1 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 602f574..2f3622d 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -283,30 +283,32 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int 
attr, u_int addr,
 
 ==*/
 
-static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
-  size_t len, void *ptr)
+static int read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
+   size_t len, void *ptr)
 {
struct cis_cache_entry *cis;
-   int ret;
+   int ret = 0;
 
if (s->state & SOCKET_CARDBUS)
-   return;
+   return -EINVAL;
 
mutex_lock(&s->ops_mutex);
if (s->fake_cis) {
if (s->fake_cis_len >= addr+len)
memcpy(ptr, s->fake_cis+addr, len);
-   else
+   else {
memset(ptr, 0xff, len);
+   ret = -EINVAL;
+   }
mutex_unlock(&s->ops_mutex);
-   return;
+   return ret;
}
 
list_for_each_entry(cis, &s->cis_cache, node) {
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
memcpy(ptr, cis->cache, len);
mutex_unlock(&s->ops_mutex);
-   return;
+   return 0;
}
}
mutex_unlock(&s->ops_mutex);
@@ -326,6 +328,7 @@ static void read_cis_cache(struct pcmcia_socket *s, int 
attr, u_int addr,
mutex_unlock(&s->ops_mutex);
}
}
+   return ret;
 }
 
 static void
@@ -374,6 +377,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
 {
struct cis_cache_entry *cis;
char *buf;
+   int ret;
 
if (s->state & SOCKET_CARDBUS)
return -EINVAL;
@@ -390,9 +394,8 @@ int verify_cis_cache(struct pcmcia_socket *s)
if (len > 256)
len = 256;
 
-   pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
-
-   if (memcmp(buf, cis->cache, len) != 0) {
+   ret = pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
+   if (ret || memcmp(buf, cis->cache, len) != 0) {
kfree(buf);
return -1;
}
@@ -425,6 +428,7 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
}
s->fake_cis_len = len;
memcpy(s->fake_cis, data, len);
+   dev_info(&s->dev, "Using replacement CIS\n");
mutex_unlock(&s->ops_mutex);
return 0;
 }
@@ -478,11 +482,14 @@ static int follow_link(struct pcmcia_socket *s, tuple_t 
*tuple)
 {
 u_char link[5];
 u_int ofs;
+int ret;
 
 if (MFC_FN(tuple->Flags)) {
/* Get indirect link from the MFC tuple */
-   read_cis_cache(s, LINK_SPACE(tuple->Flags),
+   ret = read_cis_cache(s, LINK_SPACE(tuple->Flags),
   tuple->LinkOffset, 5, link);
+   if (ret)
+   return -1;
ofs = get_unaligned_le32(link + 1);
SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
/* Move to the next indirect link */
@@ -498,7 +505,9 @@ static int follow_link(struct pcmcia_socket *s, tuple_t 
*tuple)
 if (SPACE(tuple->Flags)) {
/* This is ugly, but a common CIS error is to code the long
   link offset incorrectly, so we check the right spot... */
-   read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+   ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+   if (ret)
+   return -1;
if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) == 0))
return ofs;
@@ -506,7 +515,9 @@ static int follow_link(struct pcmcia_socket *s, tuple_t 
*tuple)
/* Then, we try the wrong spot... */
ofs = ofs >> 1;
 }
-read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+ret = read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
+if (ret)
+   return -1;
 if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
(strncmp(link+2, "CIS", 3) == 0))
return ofs;
@@ -518,6 +529,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned 
int function, tuple_
 {
 u_char link[2], tmp;
 int ofs, i, attr;
+int ret;
 
 if (!s)
return -EINVAL;
@@ -532,7 +544,9 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned 
int function, tuple_
if (link[1] == 0xff) {
link[0] = CISTPL_END;
} else {
-   read_cis_cache(s, attr, ofs, 2, link);
+   ret = read_cis_cache(s, attr, ofs, 2, link);
+

[PATCH 25/49] pcmcia/omap_cf: don't redefine SZ_2K

2010-02-27 Thread Dominik Brodowski
From: Uwe Kleine-König 

This fixes:

drivers/pcmcia/omap_cf.c:74:1: warning: "SZ_2K" redefined

Since

c1191b0 ([ARM] Kirkwood: create a mapping for the Security Accelerator 
SRAM)

SZ_2K is defined in arch/arm/include/asm/sizes.h.

Signed-off-by: Uwe Kleine-König 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/omap_cf.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 663781d..3ef9915 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -71,8 +71,6 @@ struct omap_cf_socket {
 
 #definePOLL_INTERVAL   (2 * HZ)
 
-#defineSZ_2K   (2 * SZ_1K)
-
 /*--*/
 
 static int omap_cf_ss_init(struct pcmcia_socket *s)
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 07/49] pcmcia: CardBus doesn't need CIS access

2010-02-27 Thread Dominik Brodowski
At least no in-kernel CardBus-capable PCI driver makes use of the CIS
access functions. Therefore, it seems sensible to remove this unused
code, and cleanup cardbus.c a lot.

CC: Jesse Barnes 
CC: Linus Torvalds 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cardbus.c |  175 +++-
 drivers/pcmcia/cistpl.c  |  200 --
 include/pcmcia/ss.h  |6 --
 3 files changed, 46 insertions(+), 335 deletions(-)

diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index d99f846..ac0686e 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -20,170 +20,12 @@
  */
 
 
-#include 
 #include 
-#include 
-#include 
-#include 
+#include 
 #include 
-#include 
-#include 
-#include 
 
-#include 
 #include 
-#include 
-#include 
-#include "cs_internal.h"
-
-/**/
-
-/* Offsets in the Expansion ROM Image Header */
-#define ROM_SIGNATURE  0x  /* 2 bytes */
-#define ROM_DATA_PTR   0x0018  /* 2 bytes */
-
-/* Offsets in the CardBus PC Card Data Structure */
-#define PCDATA_SIGNATURE   0x  /* 4 bytes */
-#define PCDATA_VPD_PTR 0x0008  /* 2 bytes */
-#define PCDATA_LENGTH  0x000a  /* 2 bytes */
-#define PCDATA_REVISION0x000c
-#define PCDATA_IMAGE_SZ0x0010  /* 2 bytes */
-#define PCDATA_ROM_LEVEL   0x0012  /* 2 bytes */
-#define PCDATA_CODE_TYPE   0x0014
-#define PCDATA_INDICATOR   0x0015
-
-/*=
-
-Expansion ROM's have a special layout, and pointers specify an
-image number and an offset within that image.  xlate_rom_addr()
-converts an image/offset address to an absolute offset from the
-ROM's base address.
-
-=*/
-
-static u_int xlate_rom_addr(void __iomem *b, u_int addr)
-{
-   u_int img = 0, ofs = 0, sz;
-   u_short data;
-   while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
-   if (img == (addr >> 28))
-   return (addr & 0x0fff) + ofs;
-   data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) 
<< 8);
-   sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
-   (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
-   if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
-   break;
-   b += sz;
-   ofs += sz;
-   img++;
-   }
-   return 0;
-}
-
-/*=
-
-These are similar to setup_cis_mem and release_cis_mem for 16-bit
-cards.  The "result" that is used externally is the cb_cis_virt
-pointer in the struct pcmcia_socket structure.
-
-=*/
-
-static void cb_release_cis_mem(struct pcmcia_socket *s)
-{
-   if (s->cb_cis_virt) {
-   dev_dbg(&s->dev, "cb_release_cis_mem()\n");
-   iounmap(s->cb_cis_virt);
-   s->cb_cis_virt = NULL;
-   s->cb_cis_res = NULL;
-   }
-}
-
-static int cb_setup_cis_mem(struct pcmcia_socket *s, struct resource *res)
-{
-   unsigned int start, size;
-
-   if (res == s->cb_cis_res)
-   return 0;
-
-   if (s->cb_cis_res)
-   cb_release_cis_mem(s);
-
-   start = res->start;
-   size = res->end - start + 1;
-   s->cb_cis_virt = ioremap(start, size);
-
-   if (!s->cb_cis_virt)
-   return -1;
-
-   s->cb_cis_res = res;
-
-   return 0;
-}
-
-/*=
-
-This is used by the CIS processing code to read CIS information
-from a CardBus device.
-
-=*/
-
-int read_cb_mem(struct pcmcia_socket *s, int space, u_int addr, u_int len,
-   void *ptr)
-{
-   struct pci_dev *dev;
-   struct resource *res;
-
-   dev_dbg(&s->dev, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);
 
-   dev = pci_get_slot(s->cb_dev->subordinate, 0);
-   if (!dev)
-   goto fail;
-
-   /* Config space? */
-   if (space == 0) {
-   if (addr + len > 0x100)
-   goto failput;
-   for (; len; addr++, ptr++, len--)
-   pci_read_config_byte(dev, addr, ptr);
-   return 0;
-   }
-
-   res = dev->resource + space - 1;
-
-   pci_dev_put(dev);
-
-   if (!res->flags)
-   goto fail;
-
-   if (cb_setup_cis_mem(s, res) != 0)
-   goto fail;
-
-   if (space == 7) {
-   addr = xlate_rom_addr(s->cb_cis_virt, addr);
-   if (addr == 0)
-   

[PATCH 37/49] pcmcia: use mutex for dynid lock

2010-02-27 Thread Dominik Brodowski
Even though we weren't calling a blocking function within the dynid
spinlock, we do not need a spinlock here but can and should be using
a mutex.

Reported-by: Jiri Slaby 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |   16 
 include/pcmcia/ds.h |2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 83b51dd..253d9ac 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -124,9 +124,9 @@ pcmcia_store_new_id(struct device_driver *driver, const 
char *buf, size_t count)
dynid->id.device_no = device_no;
memcpy(dynid->id.prod_id_hash, prod_id_hash, sizeof(__u32) * 4);
 
-   spin_lock(&pdrv->dynids.lock);
+   mutex_lock(&pdrv->dynids.lock);
list_add_tail(&dynid->node, &pdrv->dynids.list);
-   spin_unlock(&pdrv->dynids.lock);
+   mutex_unlock(&pdrv->dynids.lock);
 
if (get_driver(&pdrv->drv)) {
retval = driver_attach(&pdrv->drv);
@@ -144,12 +144,12 @@ pcmcia_free_dynids(struct pcmcia_driver *drv)
 {
struct pcmcia_dynid *dynid, *n;
 
-   spin_lock(&drv->dynids.lock);
+   mutex_lock(&drv->dynids.lock);
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
-   spin_unlock(&drv->dynids.lock);
+   mutex_unlock(&drv->dynids.lock);
 }
 
 static int
@@ -180,7 +180,7 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
/* initialize common fields */
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
-   spin_lock_init(&driver->dynids.lock);
+   mutex_init(&driver->dynids.lock);
INIT_LIST_HEAD(&driver->dynids.list);
 
pr_debug("registering driver %s\n", driver->drv.name);
@@ -894,16 +894,16 @@ static int pcmcia_bus_match(struct device *dev, struct 
device_driver *drv)
struct pcmcia_dynid *dynid;
 
/* match dynamic devices first */
-   spin_lock(&p_drv->dynids.lock);
+   mutex_lock(&p_drv->dynids.lock);
list_for_each_entry(dynid, &p_drv->dynids.list, node) {
dev_dbg(dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, &dynid->id)) {
dev_dbg(dev, "matched to %s\n", drv->name);
-   spin_unlock(&p_drv->dynids.lock);
+   mutex_unlock(&p_drv->dynids.lock);
return 1;
}
}
-   spin_unlock(&p_drv->dynids.lock);
+   mutex_unlock(&p_drv->dynids.lock);
 
 #ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h
index ee14857..d57847f 100644
--- a/include/pcmcia/ds.h
+++ b/include/pcmcia/ds.h
@@ -40,7 +40,7 @@ struct net_device;
  * Documentation/pcmcia/driver.txt for details.
 */
 struct pcmcia_dynids {
-   spinlock_t  lock;
+   struct mutexlock;
struct list_headlist;
 };
 
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 10/49] pcmcia: do not lock socket driver module in pcmcia_get_socket()

2010-02-27 Thread Dominik Brodowski
Do not lock the socket driver module in pcmcia_get_socket(), as
the PCMCIA core can handle a socket module removal: In
pcmcia_unregister_socket(), we explicitely wait for the last
put_device() to succeed.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c |8 +---
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 9d8b9c1..f0630a6 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -140,19 +140,13 @@ struct pcmcia_socket *pcmcia_get_socket(struct 
pcmcia_socket *skt)
struct device *dev = get_device(&skt->dev);
if (!dev)
return NULL;
-   skt = dev_get_drvdata(dev);
-   if (!try_module_get(skt->owner)) {
-   put_device(&skt->dev);
-   return NULL;
-   }
-   return skt;
+   return dev_get_drvdata(dev);
 }
 EXPORT_SYMBOL(pcmcia_get_socket);
 
 
 void pcmcia_put_socket(struct pcmcia_socket *skt)
 {
-   module_put(skt->owner);
put_device(&skt->dev);
 }
 EXPORT_SYMBOL(pcmcia_put_socket);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 47/49] pcmcia: remove useless msleep in ds.c

2010-02-27 Thread Dominik Brodowski
As this is the socket thread (pccardd) starting up, we do not have
anything to wait for in ds.c. Instead, wait the same amount of time
in pccardd to allow userspace to catch up and - possibly - execute
pcmcia-socket-startup.

Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c |3 +++
 drivers/pcmcia/ds.c |6 --
 2 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 9a49c39..e679e70 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -689,6 +689,9 @@ static int pccardd(void *__skt)
 
complete(&skt->thread_done);
 
+   /* wait for userspace to catch up */
+   msleep(250);
+
set_freezable();
for (;;) {
unsigned long flags;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 93925f5..0f98be4 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1356,12 +1356,6 @@ static int __devinit pcmcia_bus_add_socket(struct device 
*dev,
return -ENODEV;
}
 
-   /*
-* Ugly. But we want to wait for the socket threads to have started up.
-* We really should let the drivers themselves drive some of this..
-*/
-   msleep(250);
-
ret = sysfs_create_bin_file(&dev->kobj, &pccard_cis_attr);
if (ret) {
dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n");
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 23/49] pcmcia/bfin_cf: don't check platform_get_irq's return value against zero

2010-02-27 Thread Dominik Brodowski
From: Uwe Kleine-König 

platform_get_irq returns -ENXIO on failure, so !irq was probably
always true.  Better use irq <= 0.  Note that a return value of
zero is still handled as error even though this could mean irq0.

This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that
changed the return value of platform_get_irq from 0 to -ENXIO on error.

Signed-off-by: Uwe Kleine-König 
Cc: David Vrabel 
Cc: Greg Kroah-Hartman 
Cc: Rafael J. Wysocki 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/bfin_cf_pcmcia.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c
index 300b368..2482ce7 100644
--- a/drivers/pcmcia/bfin_cf_pcmcia.c
+++ b/drivers/pcmcia/bfin_cf_pcmcia.c
@@ -205,7 +205,7 @@ static int __devinit bfin_cf_probe(struct platform_device 
*pdev)
dev_info(&pdev->dev, "Blackfin CompactFlash/PCMCIA Socket Driver\n");
 
irq = platform_get_irq(pdev, 0);
-   if (!irq)
+   if (irq <= 0)
return -EINVAL;
 
cd_pfx = platform_get_irq(pdev, 1); /*Card Detect GPIO PIN */
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 36/49] pcmcia: assert locking to struct pcmcia_device

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 Documentation/pcmcia/locking.txt |   25 
 drivers/pcmcia/ds.c  |   38 
 drivers/pcmcia/pcmcia_resource.c |  122 --
 3 files changed, 129 insertions(+), 56 deletions(-)

diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt
index 5f25de4..d625105 100644
--- a/Documentation/pcmcia/locking.txt
+++ b/Documentation/pcmcia/locking.txt
@@ -90,3 +90,28 @@ or single-use fields not mentioned):
struct list_headdevices_list;
u8  device_count;
struct  pcmcia_state;
+
+
+3. Per PCMCIA-device Data:
+--
+
+The "main" struct pcmcia_devie is protected as follows (read-only fields
+or single-use fields not mentioned):
+
+
+- by pcmcia_socket->ops_mutex:
+   struct list_headsocket_device_list;
+   struct config_t *function_config;
+   u16 _irq:1;
+   u16 _io:1;
+   u16 _win:4;
+   u16 _locked:1;
+   u16 allow_func_id_match:1;
+   u16 suspended:1;
+   u16 _removed:1;
+
+- by the PCMCIA driver:
+   io_req_tio;
+   irq_req_t   irq;
+   config_req_tconf;
+   window_handle_t win;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 4c40db8..83b51dd 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -835,6 +835,8 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
}
 
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID) {
+   int ret;
+
if ((!dev->has_func_id) || (dev->func_id != did->func_id))
return 0;
 
@@ -849,10 +851,15 @@ static inline int pcmcia_devmatch(struct pcmcia_device 
*dev,
 * after it has re-checked that there is no possible module
 * with a prod_id/manf_id/card_id match.
 */
-   dev_dbg(&dev->dev,
-   "skipping FUNC_ID match until userspace interaction\n");
-   if (!dev->allow_func_id_match)
+   mutex_lock(&dev->socket->ops_mutex);
+   ret = dev->allow_func_id_match;
+   mutex_unlock(&dev->socket->ops_mutex);
+
+   if (!ret) {
+   dev_dbg(&dev->dev,
+   "skipping FUNC_ID match until userspace ACK\n");
return 0;
+   }
}
 
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
@@ -1079,9 +1086,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct 
device *dev,
if (!count)
return -EINVAL;
 
-   mutex_lock(&p_dev->socket->skt_mutex);
+   mutex_lock(&p_dev->socket->ops_mutex);
p_dev->allow_func_id_match = 1;
-   mutex_unlock(&p_dev->socket->skt_mutex);
+   mutex_unlock(&p_dev->socket->ops_mutex);
 
ret = bus_rescan_devices(&pcmcia_bus_type);
if (ret)
@@ -1114,8 +1121,13 @@ static int pcmcia_dev_suspend(struct device *dev, 
pm_message_t state)
struct pcmcia_driver *p_drv = NULL;
int ret = 0;
 
-   if (p_dev->suspended)
+   mutex_lock(&p_dev->socket->ops_mutex);
+   if (p_dev->suspended) {
+   mutex_unlock(&p_dev->socket->ops_mutex);
return 0;
+   }
+   p_dev->suspended = 1;
+   mutex_unlock(&p_dev->socket->ops_mutex);
 
dev_dbg(dev, "suspending\n");
 
@@ -1132,6 +1144,9 @@ static int pcmcia_dev_suspend(struct device *dev, 
pm_message_t state)
   "pcmcia: device %s (driver %s) did "
   "not want to go to sleep (%d)\n",
   p_dev->devname, p_drv->drv.name, ret);
+   mutex_lock(&p_dev->socket->ops_mutex);
+   p_dev->suspended = 0;
+   mutex_unlock(&p_dev->socket->ops_mutex);
goto out;
}
}
@@ -1142,8 +1157,6 @@ static int pcmcia_dev_suspend(struct device *dev, 
pm_message_t state)
}
 
  out:
-   if (!ret)
-   p_dev->suspended = 1;
return ret;
 }
 
@@ -1154,8 +1167,13 @@ static int pcmcia_dev_resume(struct device *dev)
struct pcmcia_driver *p_drv = NULL;
int ret = 0;
 
-   if (!p_dev->suspended)
+   mutex_lock(&p_dev->socket->ops_mutex);
+   if (!p_dev->suspended) {
+   mutex_unlock(&p_dev->socket->ops_mutex);
return 0;
+   }
+   p_dev->suspended = 0;
+   mutex_unlock(&p_dev->socket->ops_mutex);
 
dev_dbg(dev, "resuming\n");
 
@@ -1176,8 +1194,6 @@ static int pcmcia_dev_resume(struct device *dev)
ret = p_drv->resume(p_dev);
 
  out:

[PATCH 43/49] pcmcia: avoid prod_id memleak

2010-02-27 Thread Dominik Brodowski
Reported-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |   19 ++-
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 9968c0d..93925f5 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -237,8 +237,11 @@ static void pcmcia_release_function(struct kref *ref)
 static void pcmcia_release_dev(struct device *dev)
 {
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
+   int i;
dev_dbg(dev, "releasing device\n");
pcmcia_put_socket(p_dev->socket);
+   for (i = 0; i < 4; i++)
+   kfree(p_dev->prod_id[i]);
kfree(p_dev->devname);
kref_put(&p_dev->function_config->ref, pcmcia_release_function);
kfree(p_dev);
@@ -450,6 +453,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
char *tmp;
unsigned int length;
+   char *new;
 
tmp = vers1->str + vers1->ofs[i];
 
@@ -457,13 +461,15 @@ static int pcmcia_device_query(struct pcmcia_device 
*p_dev)
if ((length < 2) || (length > 255))
continue;
 
-   p_dev->prod_id[i] = kmalloc(sizeof(char) * length,
-   GFP_KERNEL);
-   if (!p_dev->prod_id[i])
+   new = kmalloc(sizeof(char) * length, GFP_KERNEL);
+   if (!new)
continue;
 
-   p_dev->prod_id[i] = strncpy(p_dev->prod_id[i],
-   tmp, length);
+   new = strncpy(new, tmp, length);
+
+   tmp = p_dev->prod_id[i];
+   p_dev->prod_id[i] = new;
+   kfree(tmp);
}
mutex_unlock(&p_dev->socket->ops_mutex);
}
@@ -485,6 +491,7 @@ static DEFINE_MUTEX(device_add_lock);
 struct pcmcia_device *pcmcia_device_add(struct pcmcia_socket *s, unsigned int 
function)
 {
struct pcmcia_device *p_dev, *tmp_dev;
+   int i;
 
s = pcmcia_get_socket(s);
if (!s)
@@ -575,6 +582,8 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
s->device_count--;
mutex_unlock(&s->ops_mutex);
 
+   for (i = 0; i < 4; i++)
+   kfree(p_dev->prod_id[i]);
kfree(p_dev->devname);
kfree(p_dev);
  err_put:
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 33/49] pcmcia: add locking to struct pcmcia_socket->pcmcia_state()

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |   33 ++---
 1 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bcb9ef1..0eb242c 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -649,10 +649,17 @@ static void pcmcia_delayed_add_device(struct work_struct 
*work)
 {
struct pcmcia_socket *s =
container_of(work, struct pcmcia_socket, device_add);
-   dev_dbg(&s->dev, "adding additional device to %d\n", s->sock);
-   pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
+   u8 mfc_pfc;
+   unsigned long flags;
+
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   mfc_pfc = s->pcmcia_state.mfc_pfc;
s->pcmcia_state.device_add_pending = 0;
s->pcmcia_state.mfc_pfc = 0;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+   dev_dbg(&s->dev, "adding additional device to %d\n", s->sock);
+   pcmcia_device_add(s, mfc_pfc);
 }
 
 static int pcmcia_requery(struct device *dev, void * _data)
@@ -761,8 +768,13 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, 
char * filename)
 
if (old_funcs > no_funcs)
pcmcia_card_remove(s, dev);
-   else if (no_funcs > old_funcs)
+   else if (no_funcs > old_funcs) {
+   unsigned long flags;
+
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
pcmcia_add_device_later(s, 1);
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+   }
}
  release:
release_firmware(fw);
@@ -1236,6 +1248,7 @@ static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
 static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
 {
struct pcmcia_socket *s = pcmcia_get_socket(skt);
+   unsigned long flags;
 
if (!s) {
dev_printk(KERN_ERR, &skt->dev,
@@ -1249,7 +1262,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t 
event, int priority)
 
switch (event) {
case CS_EVENT_CARD_REMOVAL:
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
s->pcmcia_state.present = 0;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
pcmcia_card_remove(skt, NULL);
handle_event(skt, event);
mutex_lock(&s->ops_mutex);
@@ -1258,7 +1273,9 @@ static int ds_event(struct pcmcia_socket *skt, event_t 
event, int priority)
break;
 
case CS_EVENT_CARD_INSERTION:
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
s->pcmcia_state.present = 1;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
mutex_lock(&s->ops_mutex);
destroy_cis_cache(s); /* to be on the safe side... */
mutex_unlock(&s->ops_mutex);
@@ -1304,14 +1321,19 @@ struct pcmcia_device *pcmcia_dev_present(struct 
pcmcia_device *_p_dev)
 {
struct pcmcia_device *p_dev;
struct pcmcia_device *ret = NULL;
+   unsigned long flags;
 
p_dev = pcmcia_get_dev(_p_dev);
if (!p_dev)
return NULL;
 
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (!p_dev->socket->pcmcia_state.present)
goto out;
 
+   if (p_dev->socket->pcmcia_state.dead)
+   goto out;
+
if (p_dev->_removed)
goto out;
 
@@ -1320,6 +1342,7 @@ struct pcmcia_device *pcmcia_dev_present(struct 
pcmcia_device *_p_dev)
 
ret = p_dev;
  out:
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
pcmcia_put_dev(p_dev);
return ret;
 }
@@ -1383,11 +1406,15 @@ static void pcmcia_bus_remove_socket(struct device *dev,
 struct class_interface *class_intf)
 {
struct pcmcia_socket *socket = dev_get_drvdata(dev);
+   unsigned long flags;
 
if (!socket)
return;
 
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
socket->pcmcia_state.dead = 1;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
pccard_register_pcmcia(socket, NULL);
 
/* unregister any unbound devices */
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 05/49] pcmcia: cleanup pccard_validate_cis()

2010-02-27 Thread Dominik Brodowski
Cleanup pccard_validate_cis() and make it return an error code on
all failures, not merely on some failures.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |  155 --
 1 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 41ec772..04bf1ba 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1577,88 +1577,95 @@ next_entry:
 EXPORT_SYMBOL(pccard_loop_tuple);
 
 
-/*==
-
-This tries to determine if a card has a sensible CIS.  It returns
-the number of tuples in the CIS, or 0 if the CIS looks bad.  The
-checks include making sure several critical tuples are present and
-valid; seeing if the total number of tuples is reasonable; and
-looking for tuples that use reserved codes.
-
-==*/
-
+/**
+ * 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
+ *
+ * This tries to determine if a card has a sensible CIS.  In @info, it
+ * returns the number of tuples in the CIS, or 0 if the CIS looks bad. The
+ * checks include making sure several critical tuples are present and
+ * valid; seeing if the total number of tuples is reasonable; and
+ * looking for tuples that use reserved codes.
+ *
+ * The function returns 0 on success.
+ */
 int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
 {
-tuple_t *tuple;
-cisparse_t *p;
-unsigned int count = 0;
-int ret, reserved, dev_ok = 0, ident_ok = 0;
+   tuple_t *tuple;
+   cisparse_t *p;
+   unsigned int count = 0;
+   int ret, reserved, dev_ok = 0, ident_ok = 0;
 
-if (!s)
-   return -EINVAL;
+   if (!s)
+   return -EINVAL;
 
-/* We do not want to validate the CIS cache... */
-destroy_cis_cache(s);
+   /* We do not want to validate the CIS cache... */
+   destroy_cis_cache(s);
 
-tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
-if (tuple == NULL) {
-   dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
-   return -ENOMEM;
-}
-p = kmalloc(sizeof(*p), GFP_KERNEL);
-if (p == NULL) {
-   kfree(tuple);
-   dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
-   return -ENOMEM;
-}
+   tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
+   if (tuple == NULL) {
+   dev_warn(&s->dev, "no memory to validate CIS\n");
+   return -ENOMEM;
+   }
+   p = kmalloc(sizeof(*p), GFP_KERNEL);
+   if (p == NULL) {
+   kfree(tuple);
+   dev_warn(&s->dev, "no memory to validate CIS\n");
+   return -ENOMEM;
+   }
 
-count = reserved = 0;
-tuple->DesiredTuple = RETURN_FIRST_TUPLE;
-tuple->Attributes = TUPLE_RETURN_COMMON;
-ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
-if (ret != 0)
-   goto done;
-
-/* First tuple should be DEVICE; we should really have either that
-   or a CFTABLE_ENTRY of some sort */
-if ((tuple->TupleCode == CISTPL_DEVICE) ||
-   (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) ||
-   (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
-   dev_ok++;
-
-/* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
-   tuple, for card identification.  Certain old D-Link and Linksys
-   cards have only a broken VERS_2 tuple; hence the bogus test. */
-if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
-   (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
-   (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
-   ident_ok++;
-
-if (!dev_ok && !ident_ok)
-   goto done;
-
-for (count = 1; count < MAX_TUPLES; count++) {
-   ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
+   count = reserved = 0;
+   tuple->DesiredTuple = RETURN_FIRST_TUPLE;
+   tuple->Attributes = TUPLE_RETURN_COMMON;
+   ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
-   break;
-   if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
-   ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
-   ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
-   reserved++;
-}
-if ((count == MAX_TUPLES) || (reserved > 5) ||
-   ((!dev_ok || !ident_ok) && (count > 10)))
-   count = 0;
+   goto done;
+
+   /* First tuple should be DEVICE; we should really have either that
+  or a CFTABLE_ENTRY of some sort */
+   if ((tuple->TupleCode == CISTPL_DEVICE) ||
+   (!pccard_read_tuple(s, BIND_FN_AL

[PATCH 49/49] pcmcia: validate late-added resources

2010-02-27 Thread Dominik Brodowski
Currently, only those mem resources are validated which are already
registered at the time the first PCMCIA card is inserted. As we can
only validate resources immediately after card insert, store
"registered" mem resources in mem_db, and only upon validation move
them to mem_db_valid. When allocationg mem resources, mem_db_valid is
then preferred to mem_db.

Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/rsrc_nonstatic.c |   67 ---
 1 files changed, 48 insertions(+), 19 deletions(-)

diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index a06881c..a69eed6 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -55,8 +55,8 @@ struct resource_map {
 
 struct socket_data {
struct resource_map mem_db;
+   struct resource_map mem_db_valid;
struct resource_map io_db;
-   unsigned intrsrc_mem_probe;
 };
 
 #define MEM_PROBE_LOW  (1 << 0)
@@ -357,6 +357,7 @@ static int do_validate_mem(struct pcmcia_socket *s,
 struct resource *res,
 unsigned int *value))
 {
+   struct socket_data *s_data = s->resource_data;
struct resource *res1, *res2;
unsigned int info1 = 1, info2 = 1;
int ret = -EINVAL;
@@ -382,6 +383,12 @@ static int do_validate_mem(struct pcmcia_socket *s,
if ((ret) || (info1 != info2) || (info1 == 0))
return -EINVAL;
 
+   if (validate && !s->fake_cis) {
+   /* move it to the validated data set */
+   add_interval(&s_data->mem_db_valid, base, size);
+   sub_interval(&s_data->mem_db, base, size);
+   }
+
return 0;
 }
 
@@ -491,6 +498,8 @@ static int validate_mem(struct pcmcia_socket *s, unsigned 
int probe_mask)
if (probe_mask & MEM_PROBE_HIGH) {
if (inv_probe(s_data->mem_db.next, s) > 0)
return 0;
+   if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
+   return 0;
dev_printk(KERN_NOTICE, &s->dev,
   "cs: warning: no high memory space available!\n");
return -ENODEV;
@@ -565,21 +574,18 @@ static int pcmcia_nonstatic_validate_mem(struct 
pcmcia_socket *s)
 {
struct socket_data *s_data = s->resource_data;
unsigned int probe_mask = MEM_PROBE_LOW;
-   int ret = 0;
+   int ret;
 
-   if (!probe_mem)
+   if (!probe_mem || !(s->state & SOCKET_PRESENT))
return 0;
 
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
 
-   if (probe_mask & ~s_data->rsrc_mem_probe) {
-   if (s->state & SOCKET_PRESENT) {
-   ret = validate_mem(s, probe_mask);
-   if (!ret)
-   s_data->rsrc_mem_probe |= probe_mask;
-   }
-   }
+   ret = validate_mem(s, probe_mask);
+
+   if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
+   return 0;
 
return ret;
 }
@@ -723,15 +729,15 @@ static struct resource *nonstatic_find_mem_region(u_long 
base, u_long num,
struct socket_data *s_data = s->resource_data;
struct pcmcia_align_data data;
unsigned long min, max;
-   int ret, i;
+   int ret, i, j;
 
low = low || !(s->features & SS_CAP_PAGE_REGS);
 
data.mask = align - 1;
data.offset = base & data.mask;
-   data.map = &s_data->mem_db;
 
for (i = 0; i < 2; i++) {
+   data.map = &s_data->mem_db_valid;
if (low) {
max = 0x10UL;
min = base < max ? base : 0;
@@ -740,15 +746,23 @@ static struct resource *nonstatic_find_mem_region(u_long 
base, u_long num,
min = 0x10UL + base;
}
 
+   for (j = 0; j < 2; j++) {
 #ifdef CONFIG_PCI
-   if (s->cb_dev) {
-   ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
-1, min, 0,
-pcmcia_align, &data);
-   } else
+   if (s->cb_dev) {
+   ret = pci_bus_alloc_resource(s->cb_dev->bus,
+   res, num, 1, min, 0,
+   pcmcia_align, &data);
+   } else
 #endif
-   ret = allocate_resource(&iomem_resource, res, num, min,
-   max, 1, pcmcia_align, &data);
+   {
+   ret = allocate_resource(&iomem_resource,
+   res, num, min, max, 1,
+

[PATCH 02/49] pcmcia: remove remaining unused IRQ_FIRST_SHARED parameter

2010-02-27 Thread Dominik Brodowski
Komuro pointed out correctly that I missed one IRQ_FIRST_SHARED
parameter in smc91c92_cs.c, and that another line could be writter
more beautifully.

CC: net...@vger.kernel.org
CC: Komuro 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/net/pcmcia/smc91c92_cs.c |6 ++
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 6dd486d..aa57cfd 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -453,8 +453,7 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 
 link->conf.Attributes |= CONF_ENABLE_SPKR;
 link->conf.Status = CCSR_AUDIO_ENA;
-link->irq.Attributes =
-   IRQ_TYPE_DYNAMIC_SHARING;
+link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 link->io.IOAddrLines = 16;
 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
 link->io.NumPorts2 = 8;
@@ -652,8 +651,7 @@ static int osi_config(struct pcmcia_device *link)
 
 link->conf.Attributes |= CONF_ENABLE_SPKR;
 link->conf.Status = CCSR_AUDIO_ENA;
-link->irq.Attributes =
-   IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
+link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
 link->io.NumPorts1 = 64;
 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
 link->io.NumPorts2 = 8;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 44/49] pcmcia: add locking to pcmcia_{read,write}_cis_mem

2010-02-27 Thread Dominik Brodowski
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |   27 +--
 drivers/pcmcia/rsrc_nonstatic.c |5 +
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 17a5da3..602f574 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -83,6 +83,8 @@ void release_cis_mem(struct pcmcia_socket *s)
  * Map the card memory at "card_offset" into virtual space.
  * If flags & MAP_ATTRIB, map the attribute space, otherwise
  * map the memory space.
+ *
+ * Must be called with ops_mutex held.
  */
 static void __iomem *
 set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int 
flags)
@@ -90,13 +92,11 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
pccard_mem_map *mem = &s->cis_mem;
int ret;
 
-   mutex_lock(&s->ops_mutex);
if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 
0, s);
if (mem->res == NULL) {
dev_printk(KERN_NOTICE, &s->dev,
   "cs: unable to map card memory!\n");
-   mutex_unlock(&s->ops_mutex);
return NULL;
}
s->cis_virt = NULL;
@@ -112,7 +112,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
if (ret) {
iounmap(s->cis_virt);
s->cis_virt = NULL;
-   mutex_unlock(&s->ops_mutex);
return NULL;
}
 
@@ -122,7 +121,6 @@ set_cis_map(struct pcmcia_socket *s, unsigned int 
card_offset, unsigned int flag
s->cis_virt = ioremap(mem->static_start, s->map_size);
}
 
-   mutex_unlock(&s->ops_mutex);
return s->cis_virt;
 }
 
@@ -145,6 +143,7 @@ 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 */
@@ -156,7 +155,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, 
u_int addr,
 
sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
if (!sys) {
+   dev_dbg(&s->dev, "could not map memory\n");
memset(ptr, 0xff, len);
+   mutex_unlock(&s->ops_mutex);
return -1;
}
 
@@ -170,6 +171,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, 
u_int addr,
 } else {
u_int inc = 1, card_offset, flags;
 
+   if (addr > CISTPL_MAX_CIS_SIZE)
+   dev_dbg(&s->dev, "attempt to read CIS mem at addr %#x", addr);
+
flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
if (attr) {
flags |= MAP_ATTRIB;
@@ -181,7 +185,9 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, 
u_int addr,
while (len) {
sys = set_cis_map(s, card_offset, flags);
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;
@@ -195,6 +201,7 @@ 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));
@@ -210,6 +217,7 @@ 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 */
@@ -220,8 +228,11 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int 
attr, u_int addr,
}
 
sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
-   if (!sys)
+   if (!sys) {
+   dev_dbg(&s->dev, "could not map memory\n");
+   mutex_unlock(&s->ops_mutex);
return; /* FIXME: Error */
+   }
 
writeb(flags, sys+CISREG_ICTRL0);
writeb(addr & 0xff, sys+CISREG_IADDR0);
@@ -243,8 +254,11 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int 
attr, u_int addr,
card_offset = addr & ~(s->map_size-1);
while (len) {
sys = set_cis_map(s, card_offset, flags);
-   if (!sys)
+   if (!sys) {
+   dev_dbg(&s->dev, "could not map memory\n");
+   mutex_unlock(&s->ops_mutex);
return; /* FIXME: err

[PATCH 19/49] pcmcia: fix yenta dependency on PCCARD_NONSTATIC

2010-02-27 Thread Dominik Brodowski
From: Michal Marek 

With CONFIG_PCMCIA=m and CONFIG_YENTA=y, we get

drivers/built-in.o: In function `yenta_probe':
yenta_socket.c:(.devinit.text+0x1e582): undefined reference to
`pccard_nonstatic_ops'

This is because

select PCCARD_NONSTATIC if PCMCIA

sets PCCARD_NONSTATIC = min(YENTA, PCMCIA). Change it to 'if PCMCIA!=n'
to remove the upper limit.

[li...@dominikbrodowski.net: propagate change to PCMICA_M8XX]
Reported-by: Randy Dunlap 
Signed-off-by: Michal Marek 
Acked-by: Randy Dunlap 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/Kconfig |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index efc51b9..e8f35da 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -84,7 +84,7 @@ config YENTA
tristate "CardBus yenta-compatible bridge support"
depends on PCI
select CARDBUS if !EMBEDDED
-   select PCCARD_NONSTATIC if PCMCIA
+   select PCCARD_NONSTATIC if PCMCIA != n
---help---
  This option enables support for CardBus host bridges.  Virtually
  all modern PCMCIA bridges are CardBus compatible.  A "bridge" is
@@ -161,8 +161,8 @@ config TCIC
 
 config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support"
-   depends on PCMCIA && PPC && 8xx
-   select PCCARD_IODYN if PCMCIA
+   depends on PCCARD && PPC && 8xx
+   select PCCARD_IODYN if PCMCIA != n
help
  Say Y here to include support for PowerPC 8xx series PCMCIA
  controller.
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 31/49] pcmcia: properly lock skt->irq, skt->irq_mask

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/pcmcia_resource.c |3 +++
 drivers/pcmcia/socket_sysfs.c|2 ++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index f365ecb..f0de7b8 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -419,7 +419,9 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, 
irq_req_t *req)
dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n");
return -EINVAL;
}
+   mutex_lock(&s->ops_mutex);
if (s->irq.AssignedIRQ != req->AssignedIRQ) {
+   mutex_unlock(&s->ops_mutex);
dev_dbg(&s->dev, "IRQ must match assigned one\n");
return -EINVAL;
}
@@ -434,6 +436,7 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, 
irq_req_t *req)
 #ifdef CONFIG_PCMCIA_PROBE
pcmcia_used_irq[req->AssignedIRQ]--;
 #endif
+   mutex_unlock(&s->ops_mutex);
 
return 0;
 } /* pcmcia_release_irq */
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index 537d793..1cba9d3 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -167,7 +167,9 @@ static ssize_t pccard_store_irq_mask(struct device *dev,
ret = sscanf(buf, "0x%x\n", &mask);
 
if (ret == 1) {
+   mutex_lock(&s->ops_mutex);
s->irq_mask &= mask;
+   mutex_unlock(&s->ops_mutex);
ret = 0;
}
 
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 14/49] pcmcia: m32r uses static socket resources

2010-02-27 Thread Dominik Brodowski
m32r_cfc sets the socket capabilities to SS_CAP_STATIC_MAP and
also sets io_offset != 0. This means no calls to
&pccard_nonstatic_ops went through. Therfore, replace it with
&pccard_static_ops which is exactly for this case.

CC: Mamoru Sakugawa 
CC: Hirokazu Takata 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/Kconfig|2 --
 drivers/pcmcia/m32r_cfc.c |2 +-
 2 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 9f3adbd..7e9fd38 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -238,14 +238,12 @@ config PCMCIA_PROBE
 config M32R_PCC
bool "M32R PCMCIA I/F"
depends on M32R && CHIP_M32700 && PCMCIA
-   select PCCARD_NONSTATIC
help
  Say Y here to use the M32R PCMCIA controller.
 
 config M32R_CFC
bool "M32R CF I/F Controller"
depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || 
PLAT_MAPPI3 || PLAT_OPSPUT)
-   select PCCARD_NONSTATIC
help
  Say Y here to use the M32R CompactFlash controller.
 
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 26a621c..0ece2cd 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -764,7 +764,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.parent = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
-   socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+   socket[i].socket.resource_ops = &pccard_static_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 24/49] pcmcia/at91_cf: don't redefine SZ_2K

2010-02-27 Thread Dominik Brodowski
From: Uwe Kleine-König 

This fixes:

drivers/pcmcia/at91_cf.c:55:1: warning: "SZ_2K" redefined

Since

c1191b0 ([ARM] Kirkwood: create a mapping for the Security Accelerator 
SRAM)

SZ_2K is defined in arch/arm/include/asm/sizes.h.

Signed-off-by: Uwe Kleine-König 
Acked-by: Andrew Victor 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/at91_cf.c |2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
index e1dcced..5d22807 100644
--- a/drivers/pcmcia/at91_cf.c
+++ b/drivers/pcmcia/at91_cf.c
@@ -52,8 +52,6 @@ struct at91_cf_socket {
unsigned long   phys_baseaddr;
 };
 
-#defineSZ_2K   (2 * SZ_1K)
-
 static inline int at91_cf_present(struct at91_cf_socket *cf)
 {
return !gpio_get_value(cf->board->det_pin);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 41/49] pcmcia: use state machine for extended requery

2010-02-27 Thread Dominik Brodowski
The requery callback now also handles the addition of a second pseudo
multifunction device. Avoids messing with dev_{g,s}et_drvdata(), and
fixes any workqueue <-> skt_mutex deadlock.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |   92 --
 include/pcmcia/ss.h |   11 ++
 2 files changed, 25 insertions(+), 78 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 5400e20..9968c0d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -244,23 +244,11 @@ static void pcmcia_release_dev(struct device *dev)
kfree(p_dev);
 }
 
-static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)
-{
-   if (!s->pcmcia_state.device_add_pending) {
-   dev_dbg(&s->dev, "scheduling to add %s secondary"
-  " device to %d\n", mfc ? "mfc" : "pfc", s->sock);
-   s->pcmcia_state.device_add_pending = 1;
-   s->pcmcia_state.mfc_pfc = mfc;
-   schedule_work(&s->device_add);
-   }
-   return;
-}
 
 static int pcmcia_device_probe(struct device *dev)
 {
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
-   struct pcmcia_device_id *did;
struct pcmcia_socket *s;
cistpl_config_t cis_config;
int ret = 0;
@@ -273,18 +261,6 @@ static int pcmcia_device_probe(struct device *dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
 
-   /* The PCMCIA code passes the match data in via dev_set_drvdata(dev)
-* which is an ugly hack. Once the driver probe is called it may
-* and often will overwrite the match data so we must save it first
-*
-* handle pseudo multifunction devices:
-* there are at most two pseudo multifunction devices.
-* if we're matching against the first, schedule a
-* call which will then check whether there are two
-* pseudo devices, and if not, add the second one.
-*/
-   did = dev_get_drvdata(&p_dev->dev);
-
dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);
 
if ((!p_drv->probe) || (!p_dev->function_config) ||
@@ -314,9 +290,9 @@ static int pcmcia_device_probe(struct device *dev)
}
 
mutex_lock(&s->ops_mutex);
-   if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+   if ((s->pcmcia_state.has_pfc) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
-   pcmcia_add_device_later(p_dev->socket, 0);
+   pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
mutex_unlock(&s->ops_mutex);
 
 put_module:
@@ -369,7 +345,6 @@ static int pcmcia_device_remove(struct device *dev)
 {
struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv;
-   struct pcmcia_device_id *did;
int i;
 
p_dev = to_pcmcia_dev(dev);
@@ -381,8 +356,7 @@ static int pcmcia_device_remove(struct device *dev)
 * pseudo multi-function card, we need to unbind
 * all devices
 */
-   did = dev_get_drvdata(&p_dev->dev);
-   if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
+   if ((p_dev->socket->pcmcia_state.has_pfc) &&
(p_dev->socket->device_count > 0) &&
(p_dev->device_no == 0))
pcmcia_card_remove(p_dev->socket, p_dev);
@@ -528,8 +502,8 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
p_dev->device_no = (s->device_count++);
mutex_unlock(&s->ops_mutex);
 
-   /* max of 4 devices per card */
-   if (p_dev->device_no >= 4)
+   /* max of 2 devices per card */
+   if (p_dev->device_no >= 2)
goto err_free;
 
p_dev->socket = s;
@@ -652,22 +626,6 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
 }
 
 
-static void pcmcia_delayed_add_device(struct work_struct *work)
-{
-   struct pcmcia_socket *s =
-   container_of(work, struct pcmcia_socket, device_add);
-   u8 mfc_pfc;
-
-   mutex_lock(&s->ops_mutex);
-   mfc_pfc = s->pcmcia_state.mfc_pfc;
-   s->pcmcia_state.device_add_pending = 0;
-   s->pcmcia_state.mfc_pfc = 0;
-   mutex_unlock(&s->ops_mutex);
-
-   dev_dbg(&s->dev, "adding additional device to %d\n", s->sock);
-   pcmcia_device_add(s, mfc_pfc);
-}
-
 static int pcmcia_requery_callback(struct device *dev, void * _data)
 {
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
@@ -679,9 +637,10 @@ static int pcmcia_requery_callback(struct device *dev, 
void * _data)
return 0;
 }
 
+
 static void pcmcia_requery(struct pcmcia_socket *s)
 {
-   int present;
+   int present, has_pfc;
 
mutex_lock(&s->ops_mutex);
present = s->pcmcia_state.present;
@@ -723,6 +682,15 @@ static void pcmcia_requery(struct pcmcia_socket *s)
}
}
 
+   /* If the PCMCIA device consists of two pseudo devices,

[PATCH 06/49] pcmcia: improve check for same card in slot after resume

2010-02-27 Thread Dominik Brodowski
During a suspend/resume cycle, an user may change the card in the
PCMCIA/CardBus slot. The pcmcia_core can at least look at the
socket state to check whether it is the same.

For PCMCIA devices, move the detection and handling of such a
change to ds.c.

For CardBus devices, the PCI hotplug interface doesn't offer a "rescan"
facility which also _removes_ devices no longer to be found behind a
bridge. Therefore, remove and re-add all devices unconditionally.

CC: Jesse Barnes 
CC: Linus Torvalds 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |1 +
 drivers/pcmcia/cs.c |   65 +-
 drivers/pcmcia/ds.c |   16 +++-
 include/pcmcia/ss.h |1 +
 4 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 04bf1ba..a8323cb 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -377,6 +377,7 @@ int verify_cis_cache(struct pcmcia_socket *s)
kfree(buf);
return 0;
 }
+EXPORT_SYMBOL(verify_cis_cache);
 
 /*==
 
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 96d8d25..8c51493 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -328,7 +328,7 @@ static int send_event(struct pcmcia_socket *s, event_t 
event, int priority)
 {
int ret;
 
-   if (s->state & SOCKET_CARDBUS)
+   if ((s->state & SOCKET_CARDBUS) && (event != CS_EVENT_CARD_REMOVAL))
return 0;
 
dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",
@@ -346,13 +346,6 @@ static int send_event(struct pcmcia_socket *s, event_t 
event, int priority)
return ret;
 }
 
-static void socket_remove_drivers(struct pcmcia_socket *skt)
-{
-   dev_dbg(&skt->dev, "remove_drivers\n");
-
-   send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
-}
-
 static int socket_reset(struct pcmcia_socket *skt)
 {
int status, i;
@@ -395,7 +388,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
 
dev_dbg(&s->dev, "shutdown\n");
 
-   socket_remove_drivers(s);
+   send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
msleep(shutdown_delay * 10);
s->state &= SOCKET_INUSE;
@@ -462,7 +455,8 @@ static int socket_setup(struct pcmcia_socket *skt, int 
initial_delay)
return -EINVAL;
}
skt->state |= SOCKET_CARDBUS;
-   }
+   } else
+   skt->state &= ~SOCKET_CARDBUS;
 
/*
 * Decode the card voltage requirements, and apply power to the card.
@@ -544,6 +538,8 @@ static int socket_suspend(struct pcmcia_socket *skt)
if (skt->state & SOCKET_SUSPEND)
return -EBUSY;
 
+   skt->suspended_state = skt->state;
+
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
skt->socket = dead_socket;
skt->ops->set_socket(skt, &skt->socket);
@@ -566,38 +562,37 @@ static int socket_early_resume(struct pcmcia_socket *skt)
 
 static int socket_late_resume(struct pcmcia_socket *skt)
 {
-   if (!(skt->state & SOCKET_PRESENT)) {
-   skt->state &= ~SOCKET_SUSPEND;
+   skt->state &= ~SOCKET_SUSPEND;
+
+   if (!(skt->state & SOCKET_PRESENT))
return socket_insert(skt);
+
+   if (skt->resume_status) {
+   socket_shutdown(skt);
+   return 0;
}
 
-   if (skt->resume_status == 0) {
-   /*
-* FIXME: need a better check here for cardbus cards.
-*/
-   if (verify_cis_cache(skt) != 0) {
-   dev_dbg(&skt->dev, "cis mismatch - different card\n");
-   socket_remove_drivers(skt);
-   destroy_cis_cache(skt);
-   kfree(skt->fake_cis);
-   skt->fake_cis = NULL;
-   /*
-* Workaround: give DS time to schedule removal.
-* Remove me once the 100ms delay is eliminated
-* in ds.c
-*/
-   msleep(200);
-   send_event(skt, CS_EVENT_CARD_INSERTION, 
CS_EVENT_PRI_LOW);
-   } else {
-   dev_dbg(&skt->dev, "cis matches cache\n");
-   send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);
-   }
-   } else {
+   if (skt->suspended_state != skt->state) {
+   dev_dbg(&skt->dev,
+   "suspend state 0x%x != resume state 0x%x\n",
+   skt->suspended_state, skt->state);
+
socket_shutdown(skt);
+   return socket_insert(skt);
}
 
-   skt->state &= ~SOCKET_SUSPEND;
+#ifdef CONFIG_CARDBUS
+   if (skt->state & SOCKET_CARDBUS) {

[PATCH 11/49] pcmcia: do not lock socket driver module on card insert

2010-02-27 Thread Dominik Brodowski
Do not lock the socket driver module on card insert, as
the PCMCIA core can handle a socket module removal, at least
if we add a call to socket_remove() on pccardd()'s shutdown.

Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c  |   13 ++---
 drivers/pcmcia/cs_internal.h |   20 
 2 files changed, 10 insertions(+), 23 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index f0630a6..137a5db 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -407,7 +407,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
   "*** DANGER *** unable to remove socket power\n");
}
 
-   cs_socket_put(s);
+   s->state &= ~SOCKET_INUSE;
 }
 
 static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
@@ -496,8 +496,8 @@ static int socket_insert(struct pcmcia_socket *skt)
 
dev_dbg(&skt->dev, "insert\n");
 
-   if (!cs_socket_get(skt))
-   return -ENODEV;
+   WARN_ON(skt->state & SOCKET_INUSE);
+   skt->state |= SOCKET_INUSE;
 
ret = socket_setup(skt, setup_delay);
if (ret == 0) {
@@ -697,6 +697,13 @@ static int pccardd(void *__skt)
/* make sure we are running before we exit */
set_current_state(TASK_RUNNING);
 
+   /* shut down socket, if a device is still present */
+   if (skt->state & SOCKET_PRESENT) {
+   mutex_lock(&skt->skt_mutex);
+   socket_remove(skt);
+   mutex_unlock(&skt->skt_mutex);
+   }
+
/* remove from the device core */
pccard_sysfs_remove_socket(&skt->dev);
device_unregister(&skt->dev);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 3bc02d5..9a3bbad 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -87,26 +87,6 @@ struct pccard_resource_ops {
 #define SOCKET_CARDBUS 0x8000
 #define SOCKET_CARDBUS_CONFIG  0x1
 
-static inline int cs_socket_get(struct pcmcia_socket *skt)
-{
-   int ret;
-
-   WARN_ON(skt->state & SOCKET_INUSE);
-
-   ret = try_module_get(skt->owner);
-   if (ret)
-   skt->state |= SOCKET_INUSE;
-   return ret;
-}
-
-static inline void cs_socket_put(struct pcmcia_socket *skt)
-{
-   if (skt->state & SOCKET_INUSE) {
-   skt->state &= ~SOCKET_INUSE;
-   module_put(skt->owner);
-   }
-}
-
 
 /*
  * Stuff internal to module "pcmcia_core":
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 28/49] pcmcia: also lock fake and cache CIS by ops_mutex

2010-02-27 Thread Dominik Brodowski
Specifically,

struct list_headcis_cache;
size_t  fake_cis_len;
u8  *fake_cis;

are protected.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |   18 +-
 drivers/pcmcia/ds.c |6 ++
 2 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 9ad66c9..14de287 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -277,20 +277,24 @@ static void read_cis_cache(struct pcmcia_socket *s, int 
attr, u_int addr,
if (s->state & SOCKET_CARDBUS)
return;
 
+   mutex_lock(&s->ops_mutex);
if (s->fake_cis) {
if (s->fake_cis_len >= addr+len)
memcpy(ptr, s->fake_cis+addr, len);
else
memset(ptr, 0xff, len);
+   mutex_unlock(&s->ops_mutex);
return;
}
 
list_for_each_entry(cis, &s->cis_cache, node) {
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
memcpy(ptr, cis->cache, len);
+   mutex_unlock(&s->ops_mutex);
return;
}
}
+   mutex_unlock(&s->ops_mutex);
 
ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
 
@@ -302,7 +306,9 @@ static void 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);
}
}
 }
@@ -312,19 +318,22 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int 
addr, u_int len)
 {
struct cis_cache_entry *cis;
 
+   mutex_lock(&s->ops_mutex);
list_for_each_entry(cis, &s->cis_cache, node)
if (cis->addr == addr && cis->len == len && cis->attr == attr) {
list_del(&cis->node);
kfree(cis);
break;
}
+   mutex_unlock(&s->ops_mutex);
 }
 
 /**
  * destroy_cis_cache() - destroy the CIS cache
  * @s: pcmcia_socket for which CIS cache shall be destroyed
  *
- * This destroys the CIS cache but keeps any fake CIS alive.
+ * This destroys the CIS cache but keeps any fake CIS alive. Must be
+ * called with ops_mutex held.
  */
 
 void destroy_cis_cache(struct pcmcia_socket *s)
@@ -391,14 +400,17 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,
dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n");
return -EINVAL;
}
+   mutex_lock(&s->ops_mutex);
kfree(s->fake_cis);
s->fake_cis = kmalloc(len, GFP_KERNEL);
if (s->fake_cis == NULL) {
dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n");
+   mutex_unlock(&s->ops_mutex);
return -ENOMEM;
}
s->fake_cis_len = len;
memcpy(s->fake_cis, data, len);
+   mutex_unlock(&s->ops_mutex);
return 0;
 }
 
@@ -1461,7 +1473,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned 
int *info)
return -EINVAL;
 
/* We do not want to validate the CIS cache... */
+   mutex_lock(&s->ops_mutex);
destroy_cis_cache(s);
+   mutex_unlock(&s->ops_mutex);
 
tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
if (tuple == NULL) {
@@ -1518,7 +1532,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned 
int *info)
 done:
/* invalidate CIS cache on failure */
if (!dev_ok || !ident_ok || !count) {
+   mutex_lock(&s->ops_mutex);
destroy_cis_cache(s);
+   mutex_unlock(&s->ops_mutex);
ret = -EIO;
}
 
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0ab4fe0..4f7308d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1241,12 +1241,16 @@ static int ds_event(struct pcmcia_socket *skt, event_t 
event, int priority)
s->pcmcia_state.present = 0;
pcmcia_card_remove(skt, NULL);
handle_event(skt, event);
+   mutex_lock(&s->ops_mutex);
destroy_cis_cache(s);
+   mutex_unlock(&s->ops_mutex);
break;
 
case CS_EVENT_CARD_INSERTION:
s->pcmcia_state.present = 1;
+   mutex_lock(&s->ops_mutex);
destroy_cis_cache(s); /* to be on the safe side... */
+   mutex_unlock(&s->ops_mutex);
pcmcia_card_add(skt);
handle_event(skt, event);
break;
@@ -1259,9 +1263,11 @@ static int ds_event(struct pcmcia_socket *skt, event_t 

[PATCH 15/49] pcmcia: m8xx_pcmcia.c should use iodyn resource manager

2010-02-27 Thread Dominik Brodowski
The socket driver m8xx_pcmcia.c uses a static memory assignment,
but io_offset is set to 0. Therefore, it seems proper to use the
iodyn resource manager for this driver, as was previously the
case (before commit 80128ff79d282cf71b1819dbca9b8dd47d8ed3e8).

CC: Vitaly Bordug 
CC: Arnd Bergmann 
CC: Olof Johansson 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/Kconfig   |1 -
 drivers/pcmcia/m8xx_pcmcia.c |2 +-
 include/pcmcia/ss.h  |2 ++
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 7e9fd38..44b324b 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -163,7 +163,6 @@ config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support"
depends on PCMCIA && PPC && 8xx
select PCCARD_IODYN
-   select PCCARD_NONSTATIC
help
  Say Y here to include support for PowerPC 8xx series PCMCIA
  controller.
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 7f79c4e..3a1fe3a 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1233,7 +1233,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
socket[i].socket.io_offset = 0;
socket[i].socket.pci_irq = pcmcia_schlvl;
socket[i].socket.ops = &m8xx_services;
-   socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+   socket[i].socket.resource_ops = &pccard_iodyn_ops;
socket[i].socket.cb_dev = NULL;
socket[i].socket.dev.parent = &ofdev->dev;
socket[i].pcmcia = pcmcia;
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index b4e5cfd..1a47379 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -258,6 +258,8 @@ struct pcmcia_socket {
  * - pccard_static_ops iomem and ioport areas are assigned statically
  * - pccard_iodyn_ops  iomem areas is assigned statically, ioport
  * areas dynamically
+ * If this option is selected, use
+ * "select PCCARD_IODYN" in Kconfig.
  * - pccard_nonstatic_ops  iomem and ioport areas are assigned dynamically.
  * If this option is selected, use
  * "select PCCARD_NONSTATIC" in Kconfig.
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 38/49] pcmcia: use ops_mutex for rsrc_{mgr,nonstatic} locking

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 Documentation/pcmcia/locking.txt |5 +++--
 drivers/pcmcia/cs.c  |7 ++-
 drivers/pcmcia/ds.c  |6 +-
 drivers/pcmcia/pcmcia_ioctl.c|4 +---
 drivers/pcmcia/rsrc_mgr.c|2 --
 drivers/pcmcia/rsrc_nonstatic.c  |   35 ---
 6 files changed, 23 insertions(+), 36 deletions(-)

diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt
index d625105..68f622b 100644
--- a/Documentation/pcmcia/locking.txt
+++ b/Documentation/pcmcia/locking.txt
@@ -36,7 +36,8 @@ be called with "ops_mutex" held:
socket_reset()
socket_setup()
 
-   struct pccard_operations *ops
+   struct pccard_operations*ops
+   struct pccard_resource_ops  *resource_ops;
 
 Note that send_event() and struct pcmcia_callback *callback must not be
 called with "ops_mutex" held.
@@ -54,7 +55,7 @@ protected by pcmcia_socket_list_rwsem;
 
 2. Per-Socket Data:
 ---
-The resource_ops are on their own to provide proper locking.
+The resource_ops and their data are protected by ops_mutex.
 
 The "main" struct pcmcia_socket is protected as follows (read-only fields
 or single-use fields not mentioned):
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 13277ee..7ba45b0 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -224,7 +224,9 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)
spin_lock_init(&socket->thread_lock);
 
if (socket->resource_ops->init) {
+   mutex_lock(&socket->ops_mutex);
ret = socket->resource_ops->init(socket);
+   mutex_unlock(&socket->ops_mutex);
if (ret)
goto err;
}
@@ -282,8 +284,11 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
up_write(&pcmcia_socket_list_rwsem);
 
/* wait for sysfs to drop all references */
-   if (socket->resource_ops->exit)
+   if (socket->resource_ops->exit) {
+   mutex_lock(&socket->ops_mutex);
socket->resource_ops->exit(socket);
+   mutex_unlock(&socket->ops_mutex);
+   }
wait_for_completion(&socket->socket_released);
 } /* pcmcia_unregister_socket */
 EXPORT_SYMBOL(pcmcia_unregister_socket);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 253d9ac..76a2163 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -607,19 +607,23 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
 {
cistpl_longlink_mfc_t mfc;
unsigned int no_funcs, i, no_chains;
-   int ret = 0;
+   int ret = -EAGAIN;
 
+   mutex_lock(&s->ops_mutex);
if (!(s->resource_setup_done)) {
dev_dbg(&s->dev,
   "no resources available, delaying card_add\n");
+   mutex_unlock(&s->ops_mutex);
return -EAGAIN; /* try again, but later... */
}
 
if (pcmcia_validate_mem(s)) {
dev_dbg(&s->dev, "validating mem resources failed, "
   "delaying card_add\n");
+   mutex_unlock(&s->ops_mutex);
return -EAGAIN; /* try again, but later... */
}
+   mutex_unlock(&s->ops_mutex);
 
ret = pccard_validate_cis(s, &no_chains);
if (ret || !no_chains) {
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index db2e3db..96fd236 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -187,7 +187,6 @@ static int pcmcia_adjust_resource_info(adjust_t *adj)
continue;
} else if (!(s->resource_setup_old))
s->resource_setup_old = 1;
-   mutex_unlock(&s->ops_mutex);
 
switch (adj->Resource) {
case RES_MEMORY_RANGE:
@@ -206,10 +205,9 @@ static int pcmcia_adjust_resource_info(adjust_t *adj)
 * last call to adjust_resource_info, we
 * always need to assume this is the latest
 * one... */
-   mutex_lock(&s->ops_mutex);
s->resource_setup_done = 1;
-   mutex_unlock(&s->ops_mutex);
}
+   mutex_unlock(&s->ops_mutex);
}
}
up_read(&pcmcia_socket_list_rwsem);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index b815866..aca2cfd 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -26,9 +26,7 @@ static int static_init(struct pcmcia_socket *s)
/* the good thing about SS_CAP_STATIC_MAP sockets is
 * that they don't need a resource database */
 
-   mutex_lock(&s->ops_mutex);
s->resource_setup_done = 1;

[PATCH 01/49] pcmcia: make use of pcmcia_dev_resume() return value

2010-02-27 Thread Dominik Brodowski
In runtime_resume(), do not throw away the return value of
pcmcia_dev_resume(), for we can use it (at least) in
pcmcia_store_pm_state(). This also fixes the pointless assignment
previosly seen there, as noted by Dan Carpenter.

CC: Dan Carpenter 
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 1a4a3c4..defa44c 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -970,13 +970,14 @@ static int runtime_suspend(struct device *dev)
return rc;
 }
 
-static void runtime_resume(struct device *dev)
+static int runtime_resume(struct device *dev)
 {
int rc;
 
down(&dev->sem);
rc = pcmcia_dev_resume(dev);
up(&dev->sem);
+   return rc;
 }
 
 / per-device sysfs output ***/
@@ -1027,7 +1028,7 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, 
struct device_attribute
if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
ret = runtime_suspend(dev);
else if (p_dev->suspended && !strncmp(buf, "on", 2))
-   runtime_resume(dev);
+   ret = runtime_resume(dev);
 
return ret ? ret : count;
 }
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 03/49] pcmcia: do not meddle with already assigned resources

2010-02-27 Thread Dominik Brodowski
Do not release any iomem resources already in use.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/rsrc_nonstatic.c |7 ---
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 9b0dc43..4f93889 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -727,13 +727,6 @@ static int adjust_memory(struct pcmcia_socket *s, unsigned 
int action, unsigned
break;
case REMOVE_MANAGED_RESOURCE:
ret = sub_interval(&data->mem_db, start, size);
-   if (!ret) {
-   struct pcmcia_socket *socket;
-   down_read(&pcmcia_socket_list_rwsem);
-   list_for_each_entry(socket, &pcmcia_socket_list, 
socket_list)
-   release_cis_mem(socket);
-   up_read(&pcmcia_socket_list_rwsem);
-   }
break;
default:
ret = -EINVAL;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 48/49] pcmcia: allow for extension of resource interval

2010-02-27 Thread Dominik Brodowski
If a new interval overlaps or extends an existing interval in
add_interval(), do not fail, but extend the existing interval.

Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/rsrc_nonstatic.c |6 --
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 19cecb5..a06881c 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -124,8 +124,10 @@ static int add_interval(struct resource_map *map, u_long 
base, u_long num)
struct resource_map *p, *q;
 
for (p = map; ; p = p->next) {
-   if ((p != map) && (p->base+p->num-1 >= base))
-   return -1;
+   if ((p != map) && (p->base+p->num >= base)) {
+   p->num = max(num + base - p->base, p->num);
+   return 0;
+   }
if ((p->next == map) || (p->next->base > base+num-1))
break;
}
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[git pull] PCMCIA updates for 2.6.34

2010-02-27 Thread Dominik Brodowski
Linus,

several PCMCIA updates for 2.6.33 are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git master

Please pull from that location. The diffstat and list of changes is below,
the individual diffs are sent (at least) to the linux-pcmcia list.

Thanks,
Dominik

Dominik Brodowski (41):
  pcmcia: make use of pcmcia_dev_resume() return value
  pcmcia: remove remaining unused IRQ_FIRST_SHARED parameter
  pcmcia: do not meddle with already assigned resources
  pcmcia: validate CIS, not CIS cache.
  pcmcia: cleanup pccard_validate_cis()
  pcmcia: improve check for same card in slot after resume
  pcmcia: CardBus doesn't need CIS access
  pcmcia: call CIS cleanup from ds.c
  pcmcia: rsrc_nonstatic io memory probe improvements
  pcmcia: do not lock socket driver module in pcmcia_get_socket()
  pcmcia: do not lock socket driver module on card insert
  pcmcia: remove useless indirection
  pcmcia: remove some rsrc_mgr indirections
  pcmcia: m32r uses static socket resources
  pcmcia: m8xx_pcmcia.c should use iodyn resource manager
  pcmcia: move cistpl.c into pcmcia module
  pcmcia: remove remaining rsrc_mgr indirections
  pcmcia: do not use resource manager on !PCMCIA
  pcmcia: add locking to set_mem_map()
  pcmcia: also lock fake and cache CIS by ops_mutex
  pcmcia: lock ops->set_io_map()
  pcmcia: lock ops->set_socket
  pcmcia: properly lock skt->irq, skt->irq_mask
  pcmcia: protect s->device_count
  pcmcia: add locking to struct pcmcia_socket->pcmcia_state()
  pcmcia: simplify locking
  pcmcia: add locking documentation
  pcmcia: assert locking to struct pcmcia_device
  pcmcia: use mutex for dynid lock
  pcmcia: use ops_mutex for rsrc_{mgr,nonstatic} locking
  pcmcia: use pccardd to handle eject, insert, suspend and resume requests
  pcmcia: delay re-scanning and re-querying of PCMCIA bus
  pcmcia: use state machine for extended requery
  pcmcia: avoid sysfs-related lockup for cardbus
  pcmcia: avoid prod_id memleak
  pcmcia: add locking to pcmcia_{read,write}_cis_mem
  pcmcia: handle error in serial_cs config calls
  pcmcia: use read_cis_mem return value
  pcmcia: remove useless msleep in ds.c
  pcmcia: allow for extension of resource interval
  pcmcia: validate late-added resources

H Hartley Sweeten (1):
  cm4000_cs.c: Remove unnecessary cast

Michal Marek (1):
  pcmcia: fix yenta dependency on PCCARD_NONSTATIC

Márton Németh (1):
  pcmcia: make Open Firmware device id constant

Uwe Kleine-König (3):
  pcmcia/bfin_cf: don't check platform_get_irq's return value against zero
  pcmcia/at91_cf: don't redefine SZ_2K
  pcmcia/omap_cf: don't redefine SZ_2K

Wolfram Sang (2):
  pcmcia/yenta: add module parameter for O2 speedups
  pcmcia/i82365: fix typos in comments

 Documentation/pcmcia/locking.txt |  118 
 drivers/char/pcmcia/cm4000_cs.c  |2 +-
 drivers/net/pcmcia/smc91c92_cs.c |6 +-
 drivers/pcmcia/Kconfig   |9 +-
 drivers/pcmcia/Makefile  |4 +-
 drivers/pcmcia/at91_cf.c |2 -
 drivers/pcmcia/bfin_cf_pcmcia.c  |2 +-
 drivers/pcmcia/cardbus.c |  175 +--
 drivers/pcmcia/cistpl.c  |  606 +-
 drivers/pcmcia/cs.c  |  312 +---
 drivers/pcmcia/cs_internal.h |   89 ++
 drivers/pcmcia/ds.c  |  333 -
 drivers/pcmcia/electra_cf.c  |2 +-
 drivers/pcmcia/i82365.h  |4 +-
 drivers/pcmcia/m32r_cfc.c|2 +-
 drivers/pcmcia/m8xx_pcmcia.c |4 +-
 drivers/pcmcia/o2micro.h |   45 ++-
 drivers/pcmcia/omap_cf.c |2 -
 drivers/pcmcia/pcmcia_ioctl.c|   42 ++--
 drivers/pcmcia/pcmcia_resource.c |  169 +---
 drivers/pcmcia/rsrc_mgr.c|   48 ---
 drivers/pcmcia/rsrc_nonstatic.c  |  285 +++---
 drivers/pcmcia/socket_sysfs.c|  196 ++---
 drivers/pcmcia/yenta_socket.c|5 +
 drivers/serial/serial_cs.c   |7 +-
 include/pcmcia/ds.h  |2 +-
 include/pcmcia/ss.h  |   40 ++-
 27 files changed, 1257 insertions(+), 1254 deletions(-)
 create mode 100644 Documentation/pcmcia/locking.txt

___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 29/49] pcmcia: lock ops->set_io_map()

2010-02-27 Thread Dominik Brodowski
As a side effect,
io_window_t io[MAX_IO_WIN];
is explicitely protected now.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/pcmcia_resource.c |   10 ++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index f31ba89..4e0aaec 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -306,6 +306,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
int i;
 
io_on.speed = io_speed;
+   mutex_lock(&s->ops_mutex);
for (i = 0; i < MAX_IO_WIN; i++) {
if (!s->io[i].res)
continue;
@@ -320,6 +321,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
mdelay(40);
s->ops->set_io_map(s, &io_on);
}
+   mutex_unlock(&s->ops_mutex);
}
 
return 0;
@@ -345,6 +347,7 @@ int pcmcia_release_configuration(struct pcmcia_device 
*p_dev)
}
if (c->state & CONFIG_LOCKED) {
c->state &= ~CONFIG_LOCKED;
+   mutex_lock(&s->ops_mutex);
if (c->state & CONFIG_IO_REQ)
for (i = 0; i < MAX_IO_WIN; i++) {
if (!s->io[i].res)
@@ -355,6 +358,7 @@ int pcmcia_release_configuration(struct pcmcia_device 
*p_dev)
io.map = i;
s->ops->set_io_map(s, &io);
}
+   mutex_unlock(&s->ops_mutex);
}
 
return 0;
@@ -562,6 +566,7 @@ int pcmcia_request_configuration(struct pcmcia_device 
*p_dev,
 
/* Configure I/O windows */
if (c->state & CONFIG_IO_REQ) {
+   mutex_lock(&s->ops_mutex);
iomap.speed = io_speed;
for (i = 0; i < MAX_IO_WIN; i++)
if (s->io[i].res) {
@@ -580,6 +585,7 @@ int pcmcia_request_configuration(struct pcmcia_device 
*p_dev,
s->ops->set_io_map(s, &iomap);
s->io[i].Config++;
}
+   mutex_unlock(&s->ops_mutex);
}
 
c->state |= CONFIG_LOCKED;
@@ -625,10 +631,12 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, 
io_req_t *req)
return -EINVAL;
}
 
+   mutex_lock(&s->ops_mutex);
dev_dbg(&s->dev, "trying to allocate resource 1\n");
if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
   req->NumPorts1, req->IOAddrLines)) {
dev_dbg(&s->dev, "allocation of resource 1 failed\n");
+   mutex_unlock(&s->ops_mutex);
return -EBUSY;
}
 
@@ -638,9 +646,11 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, 
io_req_t *req)
   req->NumPorts2, req->IOAddrLines)) {
dev_dbg(&s->dev, "allocation of resource 2 failed\n");
release_io_space(s, req->BasePort1, req->NumPorts1);
+   mutex_unlock(&s->ops_mutex);
return -EBUSY;
}
}
+   mutex_unlock(&s->ops_mutex);
 
c->io = *req;
c->state |= CONFIG_IO_REQ;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 30/49] pcmcia: lock ops->set_socket

2010-02-27 Thread Dominik Brodowski
As a side effect,
socket_state_t  socket;
u_int   state;
u_int   suspended_state;
are properly protected now.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c  |   18 --
 drivers/pcmcia/pcmcia_resource.c |   15 +--
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 91aa1f2..cc0ba8a 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -383,6 +383,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
dev_dbg(&s->dev, "shutdown\n");
 
send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
+
+   mutex_lock(&s->ops_mutex);
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
msleep(shutdown_delay * 10);
s->state &= SOCKET_INUSE;
@@ -410,6 +412,7 @@ static void socket_shutdown(struct pcmcia_socket *s)
}
 
s->state &= ~SOCKET_INUSE;
+   mutex_unlock(&s->ops_mutex);
 }
 
 static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
@@ -498,6 +501,7 @@ static int socket_insert(struct pcmcia_socket *skt)
 
dev_dbg(&skt->dev, "insert\n");
 
+   mutex_lock(&skt->ops_mutex);
WARN_ON(skt->state & SOCKET_INUSE);
skt->state |= SOCKET_INUSE;
 
@@ -517,9 +521,11 @@ static int socket_insert(struct pcmcia_socket *skt)
}
 #endif
dev_dbg(&skt->dev, "insert done\n");
+   mutex_unlock(&skt->ops_mutex);
 
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else {
+   mutex_unlock(&skt->ops_mutex);
socket_shutdown(skt);
}
 
@@ -531,6 +537,7 @@ static int socket_suspend(struct pcmcia_socket *skt)
if (skt->state & SOCKET_SUSPEND)
return -EBUSY;
 
+   mutex_lock(&skt->ops_mutex);
skt->suspended_state = skt->state;
 
send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
@@ -539,23 +546,27 @@ static int socket_suspend(struct pcmcia_socket *skt)
if (skt->ops->suspend)
skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND;
-
+   mutex_unlock(&skt->ops_mutex);
return 0;
 }
 
 static int socket_early_resume(struct pcmcia_socket *skt)
 {
+   mutex_lock(&skt->ops_mutex);
skt->socket = dead_socket;
skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket);
if (skt->state & SOCKET_PRESENT)
skt->resume_status = socket_setup(skt, resume_delay);
+   mutex_unlock(&skt->ops_mutex);
return 0;
 }
 
 static int socket_late_resume(struct pcmcia_socket *skt)
 {
+   mutex_lock(&skt->ops_mutex);
skt->state &= ~SOCKET_SUSPEND;
+   mutex_unlock(&skt->ops_mutex);
 
if (!(skt->state & SOCKET_PRESENT))
return socket_insert(skt);
@@ -795,7 +806,10 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_RESET_PHYSICAL, 
CS_EVENT_PRI_LOW);
if (skt->callback)
skt->callback->suspend(skt);
-   if (socket_reset(skt) == 0) {
+   mutex_lock(&skt->ops_mutex);
+   ret = socket_reset(skt);
+   mutex_unlock(&skt->ops_mutex);
+   if (ret == 0) {
send_event(skt, CS_EVENT_CARD_RESET, 
CS_EVENT_PRI_LOW);
if (skt->callback)
skt->callback->resume(skt);
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 4e0aaec..f365ecb 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -266,6 +266,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
}
 
if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
+   mutex_lock(&s->ops_mutex);
if (mod->Attributes & CONF_ENABLE_IRQ) {
c->Attributes |= CONF_ENABLE_IRQ;
s->socket.io_irq = s->irq.AssignedIRQ;
@@ -274,6 +275,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
s->socket.io_irq = 0;
}
s->ops->set_socket(s, &s->socket);
+   mutex_unlock(&s->ops_mutex);
}
 
if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
@@ -288,12 +290,15 @@ int pcmcia_modify_configuration(struct pcmcia_device 
*p_dev,
dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
return -EINVAL;
}
+   mutex_lock(&s->ops_mutex);
s->socket.Vpp = mod->Vpp1;
if (s->ops->set_socket(s, &s->socket)) {
+   mutex_unlock(&s->ops_mutex);
dev_printk(KERN_WA

[PATCH 20/49] cm4000_cs.c: Remove unnecessary cast

2010-02-27 Thread Dominik Brodowski
From: H Hartley Sweeten 

The struct file 'private_data' member is a void *, the cast is not needed.

Signed-off-by: H Hartley Sweeten 
Cc: Harald Welte 
Signed-off-by: Dominik Brodowski 
---
 drivers/char/pcmcia/cm4000_cs.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index 2db4c0a..c9bc896 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -1047,7 +1047,7 @@ release_io:
 static ssize_t cmm_write(struct file *filp, const char __user *buf,
 size_t count, loff_t *ppos)
 {
-   struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
+   struct cm4000_dev *dev = filp->private_data;
unsigned int iobase = dev->p_dev->io.BasePort1;
unsigned short s;
unsigned char tmp;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 04/49] pcmcia: validate CIS, not CIS cache.

2010-02-27 Thread Dominik Brodowski
In pccard_validate_cis(), validate the card CIS, not the CIS cache.
Also, destroy the CIS cache if pccard_validate_cis fails.

Furthermore, do not remove the fake CIS in destroy_cis_cache() but
do so explicitely in the code paths where it makes sense.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c |   24 
 drivers/pcmcia/cs.c |4 
 drivers/pcmcia/rsrc_nonstatic.c |3 +--
 3 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 25b1cd2..41ec772 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -319,22 +319,23 @@ remove_cis_cache(struct pcmcia_socket *s, int attr, u_int 
addr, u_int len)
}
 }
 
+/**
+ * destroy_cis_cache() - destroy the CIS cache
+ * @s: pcmcia_socket for which CIS cache shall be destroyed
+ *
+ * This destroys the CIS cache but keeps any fake CIS alive.
+ */
+
 void destroy_cis_cache(struct pcmcia_socket *s)
 {
struct list_head *l, *n;
+   struct cis_cache_entry *cis;
 
list_for_each_safe(l, n, &s->cis_cache) {
-   struct cis_cache_entry *cis = list_entry(l, struct 
cis_cache_entry, node);
-
+   cis = list_entry(l, struct cis_cache_entry, node);
list_del(&cis->node);
kfree(cis);
}
-
-   /*
-* If there was a fake CIS, destroy that as well.
-*/
-   kfree(s->fake_cis);
-   s->fake_cis = NULL;
 }
 EXPORT_SYMBOL(destroy_cis_cache);
 
@@ -1596,6 +1597,9 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned 
int *info)
 if (!s)
return -EINVAL;
 
+/* We do not want to validate the CIS cache... */
+destroy_cis_cache(s);
+
 tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
 if (tuple == NULL) {
dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
@@ -1647,6 +1651,10 @@ int pccard_validate_cis(struct pcmcia_socket *s, 
unsigned int *info)
count = 0;
 
 done:
+/* invalidate CIS cache on failure */
+if (!dev_ok || !ident_ok || !count)
+   destroy_cis_cache(s);
+
 if (info)
*info = count;
 kfree(tuple);
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 6d6f82b..96d8d25 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -407,6 +407,8 @@ static void socket_shutdown(struct pcmcia_socket *s)
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
destroy_cis_cache(s);
+   kfree(s->fake_cis);
+   s->fake_cis = NULL;
 #ifdef CONFIG_CARDBUS
cb_free(s);
 #endif
@@ -577,6 +579,8 @@ static int socket_late_resume(struct pcmcia_socket *skt)
dev_dbg(&skt->dev, "cis mismatch - different card\n");
socket_remove_drivers(skt);
destroy_cis_cache(skt);
+   kfree(skt->fake_cis);
+   skt->fake_cis = NULL;
/*
 * Workaround: give DS time to schedule removal.
 * Remove me once the 100ms delay is eliminated
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 4f93889..b886385 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -281,10 +281,9 @@ static int readable(struct pcmcia_socket *s, struct 
resource *res,
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
ret = pccard_validate_cis(s, count);
-   /* invalidate mapping and CIS cache */
+   /* invalidate mapping */
iounmap(s->cis_virt);
s->cis_virt = NULL;
-   destroy_cis_cache(s);
}
s->cis_mem.res = NULL;
if ((ret != 0) || (*count == 0))
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 40/49] pcmcia: delay re-scanning and re-querying of PCMCIA bus

2010-02-27 Thread Dominik Brodowski
After a CIS update -- or the finalization of the resource database --,
proceed with the re-scanning or re-querying of PCMCIA cards only in
a separate thread to avoid deadlocks.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cistpl.c   |   10 +-
 drivers/pcmcia/cs.c   |8 -
 drivers/pcmcia/cs_internal.h  |3 +-
 drivers/pcmcia/ds.c   |   80 
 drivers/pcmcia/socket_sysfs.c |   11 +-
 5 files changed, 59 insertions(+), 53 deletions(-)

diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 14de287..17a5da3 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1670,15 +1670,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj,
if (error)
return -EIO;
 
-   mutex_lock(&s->skt_mutex);
-   if ((s->callback) && (s->state & SOCKET_PRESENT) &&
-   !(s->state & SOCKET_CARDBUS)) {
-   if (try_module_get(s->callback->owner)) {
-   s->callback->requery(s, 1);
-   module_put(s->callback->owner);
-   }
-   }
-   mutex_unlock(&s->skt_mutex);
+   pcmcia_parse_uevents(s, PCMCIA_UEVENT_REQUERY);
 
return count;
 }
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 823ecda..d529e02 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -728,6 +728,11 @@ static int pccardd(void *__skt)
if (!ret)
socket_suspend(skt);
}
+   if ((sysfs_events & PCMCIA_UEVENT_REQUERY) &&
+   !(skt->state & SOCKET_CARDBUS)) {
+   if (!ret && skt->callback)
+   skt->callback->requery(skt);
+   }
}
mutex_unlock(&skt->skt_mutex);
 
@@ -783,7 +788,8 @@ EXPORT_SYMBOL(pcmcia_parse_events);
  * userspace-issued insert, eject, suspend and resume commands must be
  * handled by pccardd to avoid any sysfs-related deadlocks. Valid events
  * are PCMCIA_UEVENT_EJECT (for eject), PCMCIA_UEVENT__INSERT (for insert),
- * PCMCIA_UEVENT_RESUME (for resume) and PCMCIA_UEVENT_SUSPEND (for suspend).
+ * PCMCIA_UEVENT_RESUME (for resume), PCMCIA_UEVENT_SUSPEND (for suspend)
+ * and PCMCIA_UEVENT_REQUERY (for re-querying the PCMCIA card).
  */
 void pcmcia_parse_uevents(struct pcmcia_socket *s, u_int events)
 {
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 127c97a..f95864c 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -110,7 +110,7 @@ struct pcmcia_callback{
struct module   *owner;
int (*event) (struct pcmcia_socket *s,
  event_t event, int priority);
-   void(*requery) (struct pcmcia_socket *s, int new_cis);
+   void(*requery) (struct pcmcia_socket *s);
int (*validate) (struct pcmcia_socket *s, unsigned int *i);
int (*suspend) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
@@ -129,6 +129,7 @@ void pcmcia_parse_uevents(struct pcmcia_socket *socket, 
unsigned int events);
 #define PCMCIA_UEVENT_INSERT   0x0002
 #define PCMCIA_UEVENT_SUSPEND  0x0004
 #define PCMCIA_UEVENT_RESUME   0x0008
+#define PCMCIA_UEVENT_REQUERY  0x0010
 
 struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt);
 void pcmcia_put_socket(struct pcmcia_socket *skt);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 76a2163..5400e20 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -432,16 +432,20 @@ static int pcmcia_device_query(struct pcmcia_device 
*p_dev)
 
if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
   CISTPL_MANFID, &manf_id)) {
+   mutex_lock(&p_dev->socket->ops_mutex);
p_dev->manf_id = manf_id.manf;
p_dev->card_id = manf_id.card;
p_dev->has_manf_id = 1;
p_dev->has_card_id = 1;
+   mutex_unlock(&p_dev->socket->ops_mutex);
}
 
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
   CISTPL_FUNCID, &func_id)) {
+   mutex_lock(&p_dev->socket->ops_mutex);
p_dev->func_id = func_id.func;
p_dev->has_func_id = 1;
+   mutex_unlock(&p_dev->socket->ops_mutex);
} else {
/* rule of thumb: cards with no FUNCID, but with
 * common memory device geometry information, are
@@ -458,14 +462,17 @@ static int pcmcia_device_query(struct pcmcia_device 
*p_dev)
dev_dbg(&p_dev->dev,
   "mem device geometry probably means "
   "FUNCID_MEMORY\n");
+

[PATCH 22/49] pcmcia/yenta: add module parameter for O2 speedups

2010-02-27 Thread Dominik Brodowski
From: Wolfram Sang 

O2-bridges can do read prefetch and write burst. However, for some combinations
of older bridges and cards, this causes problems, so it is disabled for those
bridges. Now, as some users know their setup works with the speedups enabled, a
new parameter is introduced to the driver. Now, a user can specifically enable
or disable these features, while the default is what we have today: detect the
bridge and decide accordingly. Fixes Bugzilla entry 15014.

Simplify and unify the printouts, fix a whitespace issue while we are here.

Signed-off-by: Wolfram Sang 
Tested-by: frod...@gmail.com
[li...@dominikbrodowski.net: whitespace fixes]
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/o2micro.h  |   45 ++--
 drivers/pcmcia/yenta_socket.c |5 
 2 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h
index 624442f..e74beba 100644
--- a/drivers/pcmcia/o2micro.h
+++ b/drivers/pcmcia/o2micro.h
@@ -116,13 +116,12 @@ static int o2micro_override(struct yenta_socket *socket)
 * from Eric Still, 02Micro.
 */
u8 a, b;
+   bool use_speedup;
 
if (PCI_FUNC(socket->dev->devfn) == 0) {
a = config_readb(socket, O2_RESERVED1);
b = config_readb(socket, O2_RESERVED2);
-
-   dev_printk(KERN_INFO, &socket->dev->dev,
-  "O2: res at 0x94/0xD4: %02x/%02x\n", a, b);
+   dev_dbg(&socket->dev->dev, "O2: 0x94/0xD4: %02x/%02x\n", a, b);
 
switch (socket->dev->device) {
/*
@@ -135,23 +134,37 @@ static int o2micro_override(struct yenta_socket *socket)
case PCI_DEVICE_ID_O2_6812:
case PCI_DEVICE_ID_O2_6832:
case PCI_DEVICE_ID_O2_6836:
-   case PCI_DEVICE_ID_O2_6933:
-   dev_printk(KERN_INFO, &socket->dev->dev,
-  "Yenta O2: old bridge, disabling read "
-  "prefetch/write burst\n");
-   config_writeb(socket, O2_RESERVED1,
- a & ~(O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST));
-   config_writeb(socket, O2_RESERVED2,
- b & ~(O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST));
+   case PCI_DEVICE_ID_O2_6933:
+   use_speedup = false;
break;
-
default:
-   dev_printk(KERN_INFO , &socket->dev->dev,
-  "O2: enabling read prefetch/write burst\n");
+   use_speedup = true;
+   break;
+   }
+
+   /* the user may override our decision */
+   if (strcasecmp(o2_speedup, "on") == 0)
+   use_speedup = true;
+   else if (strcasecmp(o2_speedup, "off") == 0)
+   use_speedup = false;
+   else if (strcasecmp(o2_speedup, "default") != 0)
+   dev_warn(&socket->dev->dev,
+   "O2: Unknown parameter, using 'default'");
+
+   if (use_speedup) {
+   dev_info(&socket->dev->dev,
+   "O2: enabling read prefetch/write burst\n");
+   config_writeb(socket, O2_RESERVED1,
+ a | O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST);
+   config_writeb(socket, O2_RESERVED2,
+ b | O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST);
+   } else {
+   dev_info(&socket->dev->dev,
+   "O2: disabling read prefetch/write burst\n");
config_writeb(socket, O2_RESERVED1,
- a | O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST);
+ a & ~(O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST));
config_writeb(socket, O2_RESERVED2,
- b | O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST);
+ b & ~(O2_RES_READ_PREFETCH | 
O2_RES_WRITE_BURST));
}
}
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index e4d12ac..041a75a 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -37,6 +37,11 @@ static int pwr_irqs_off;
 module_param(pwr_irqs_off, bool, 0644);
 MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use 
only when seeing IRQ storms!");
 
+static char o2_speedup[] = "default";
+module_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444);
+MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' "
+   "or 'default' (uses recommended behaviour for the detected bridge)"

[PATCH 35/49] pcmcia: add locking documentation

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 Documentation/pcmcia/locking.txt |   92 ++
 1 files changed, 92 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/pcmcia/locking.txt

diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt
new file mode 100644
index 000..5f25de4
--- /dev/null
+++ b/Documentation/pcmcia/locking.txt
@@ -0,0 +1,92 @@
+This file explains the locking and exclusion scheme used in the PCCARD
+and PCMCIA subsystems.
+
+
+A) Overview, Locking Hierarchy:
+===
+
+pcmcia_socket_list_rwsem   - protects only the list of sockets
+- skt_mutex- serializes card insert / ejection
+  - ops_mutex  - serializes socket operation
+
+
+B) Exclusion
+
+
+The following functions and callbacks to struct pcmcia_socket must
+be called with "skt_mutex" held:
+
+   socket_detect_change()
+   send_event()
+   socket_reset()
+   socket_shutdown()
+   socket_setup()
+   socket_remove()
+   socket_insert()
+   socket_early_resume()
+   socket_late_resume()
+   socket_resume()
+   socket_suspend()
+
+   struct pcmcia_callback  *callback
+
+The following functions and callbacks to struct pcmcia_socket must
+be called with "ops_mutex" held:
+
+   socket_reset()
+   socket_setup()
+
+   struct pccard_operations *ops
+
+Note that send_event() and struct pcmcia_callback *callback must not be
+called with "ops_mutex" held.
+
+
+C) Protection
+=
+
+1. Global Data:
+---
+struct list_head   pcmcia_socket_list;
+
+protected by pcmcia_socket_list_rwsem;
+
+
+2. Per-Socket Data:
+---
+The resource_ops are on their own to provide proper locking.
+
+The "main" struct pcmcia_socket is protected as follows (read-only fields
+or single-use fields not mentioned):
+
+- by pcmcia_socket_list_rwsem:
+   struct list_headsocket_list;
+
+- by thread_lock:
+   unsigned intthread_events;
+
+- by skt_mutex:
+   u_int   suspended_state;
+   void(*tune_bridge);
+   struct pcmcia_callback  *callback;
+   int resume_status;
+
+- by ops_mutex:
+   socket_state_t  socket;
+   u_int   state;
+   u_short lock_count;
+   pccard_mem_map  cis_mem;
+   void __iomem*cis_virt;
+   struct { }  irq;
+   io_window_t io[];
+   pccard_mem_map  win[];
+   struct list_headcis_cache;
+   size_t  fake_cis_len;
+   u8  *fake_cis;
+   u_int   irq_mask;
+   void(*zoom_video);
+   int (*power_hook);
+   u8  resource...;
+   struct list_headdevices_list;
+   u8  device_count;
+   struct  pcmcia_state;
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 12/49] pcmcia: remove useless indirection

2010-02-27 Thread Dominik Brodowski
As release_resoure_db() used to be called only from one place, and
it's a two-line function, remove it.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c  |3 ++-
 drivers/pcmcia/cs_internal.h |3 ---
 drivers/pcmcia/rsrc_mgr.c|6 --
 3 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 137a5db..43c90f6 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -283,7 +283,8 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)
up_write(&pcmcia_socket_list_rwsem);
 
/* wait for sysfs to drop all references */
-   release_resource_db(socket);
+   if (socket->resource_ops->exit)
+   socket->resource_ops->exit(socket);
wait_for_completion(&socket->socket_released);
 } /* pcmcia_unregister_socket */
 EXPORT_SYMBOL(pcmcia_unregister_socket);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 9a3bbad..7f86d09 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -95,9 +95,6 @@ struct pccard_resource_ops {
 /* cistpl.c */
 int verify_cis_cache(struct pcmcia_socket *s);
 
-/* rsrc_mgr.c */
-void release_resource_db(struct pcmcia_socket *s);
-
 /* socket_sysfs.c */
 extern int pccard_sysfs_add_socket(struct device *dev);
 extern void pccard_sysfs_remove_socket(struct device *dev);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 52db172..66c7800 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -58,12 +58,6 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long 
num, u_long align,
 }
 EXPORT_SYMBOL(pcmcia_find_mem_region);
 
-void release_resource_db(struct pcmcia_socket *s)
-{
-   if (s->resource_ops->exit)
-   s->resource_ops->exit(s);
-}
-
 
 static int static_init(struct pcmcia_socket *s)
 {
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 32/49] pcmcia: protect s->device_count

2010-02-27 Thread Dominik Brodowski
Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/ds.c |   25 ++---
 1 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 4f7308d..bcb9ef1 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -265,6 +265,7 @@ static int pcmcia_device_probe(struct device *dev)
struct pcmcia_device_id *did;
struct pcmcia_socket *s;
cistpl_config_t cis_config;
+   unsigned long flags;
int ret = 0;
 
dev = get_device(dev);
@@ -315,9 +316,11 @@ static int pcmcia_device_probe(struct device *dev)
goto put_module;
}
 
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0);
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
 put_module:
if (ret)
@@ -342,10 +345,12 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, 
struct pcmcia_device *le
   "pcmcia_card_remove(%d) %s\n", s->sock,
   leftover ? leftover->devname : "");
 
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (!leftover)
s->device_count = 0;
else
s->device_count = 1;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
/* unregister all pcmcia_devices registered with this socket, except 
leftover */
list_for_each_entry_safe(p_dev, tmp, &s->devices_list, 
socket_device_list) {
@@ -382,7 +387,7 @@ static int pcmcia_device_remove(struct device *dev)
 */
did = dev_get_drvdata(&p_dev->dev);
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
-   (p_dev->socket->device_count != 0) &&
+   (p_dev->socket->device_count > 0) &&
(p_dev->device_no == 0))
pcmcia_card_remove(p_dev->socket, p_dev);
 
@@ -512,16 +517,19 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
 
pr_debug("adding device to %d, function %d\n", s->sock, function);
 
-   /* max of 4 devices per card */
-   if (s->device_count == 4)
-   goto err_put;
-
p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
if (!p_dev)
goto err_put;
 
-   p_dev->socket = s;
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
p_dev->device_no = (s->device_count++);
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+   /* max of 4 devices per card */
+   if (p_dev->device_no >= 4)
+   goto err_free;
+
+   p_dev->socket = s;
p_dev->func   = function;
 
p_dev->dev.bus = &pcmcia_bus_type;
@@ -586,9 +594,12 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
 
  err_free:
+   spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+   s->device_count--;
+   spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
kfree(p_dev->devname);
kfree(p_dev);
-   s->device_count--;
  err_put:
mutex_unlock(&device_add_lock);
pcmcia_put_socket(s);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 21/49] pcmcia: make Open Firmware device id constant

2010-02-27 Thread Dominik Brodowski
From: Márton Németh 

The match_table field of the struct of_device_id is constant in 

so it is worth to make the initialization data also constant.

The semantic match that finds this kind of pattern is as follows:
(http://coccinelle.lip6.fr/)

// 
@r@
disable decl_init,const_decl_init;
identifier I1, I2, x;
@@
struct I1 {
  ...
  const struct I2 *x;
  ...
};
@s@
identifier r.I1, y;
identifier r.x, E;
@@
struct I1 y = {
  .x = E,
};
@c@
identifier r.I2;
identifier s.E;
@@
const struct I2 E[] = ... ;
@depends on !c@
identifier r.I2;
identifier s.E;
@@
+   const
struct I2 E[] = ...;
// 

Signed-off-by: Márton Németh 
Cc: Julia Lawall 
Cc: co...@diku.dk
Acked-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/electra_cf.c  |2 +-
 drivers/pcmcia/m8xx_pcmcia.c |2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index d187ba4..89cfddc 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -347,7 +347,7 @@ static int __devexit electra_cf_remove(struct of_device 
*ofdev)
return 0;
 }
 
-static struct of_device_id electra_cf_match[] = {
+static const struct of_device_id electra_cf_match[] = {
{
.compatible   = "electra-cf",
},
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 3a1fe3a..61c2159 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1303,7 +1303,7 @@ static int m8xx_resume(struct platform_device *pdev)
 #define m8xx_resume NULL
 #endif
 
-static struct of_device_id m8xx_pcmcia_match[] = {
+static const struct of_device_id m8xx_pcmcia_match[] = {
{
 .type = "pcmcia",
 .compatible = "fsl,pq-pcmcia",
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 42/49] pcmcia: avoid sysfs-related lockup for cardbus

2010-02-27 Thread Dominik Brodowski
In cb_free(), we remove some sysfs files -- other sysfs files might
grab ops_mutex, so we cannot hold it while removing sysfs files. This
fixes http://lkml.org/lkml/2010/1/17/88 .

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs.c |   12 ++--
 1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index d529e02..9a49c39 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -400,10 +400,19 @@ static void socket_shutdown(struct pcmcia_socket *s)
s->lock_count = 0;
kfree(s->fake_cis);
s->fake_cis = NULL;
+   s->functions = 0;
+
+   /* From here on we can be sure that only we (that is, the
+* pccardd thread) accesses this socket, and all (16-bit)
+* PCMCIA interactions are gone. Therefore, release
+* ops_mutex so that we don't get a sysfs-related lockdep
+* warning.
+*/
+   mutex_unlock(&s->ops_mutex);
+
 #ifdef CONFIG_CARDBUS
cb_free(s);
 #endif
-   s->functions = 0;
 
/* give socket some time to power down */
msleep(100);
@@ -415,7 +424,6 @@ static void socket_shutdown(struct pcmcia_socket *s)
}
 
s->state &= ~SOCKET_INUSE;
-   mutex_unlock(&s->ops_mutex);
 }
 
 static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 09/49] pcmcia: rsrc_nonstatic io memory probe improvements

2010-02-27 Thread Dominik Brodowski
Add a lot of documentation to the rsrc_nonstatic io memory probe
functions. Also, add a first memory probe call -- just checking
whether request_resource() succeeds -- upon adding of resources.

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/rsrc_nonstatic.c |  174 +-
 1 files changed, 114 insertions(+), 60 deletions(-)

diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index b886385..120d5ad 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -264,18 +264,15 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned 
int base,
 }
 #endif
 
-/*==
-
-This is tricky... when we set up CIS memory, we try to validate
-the memory window space allocations.
-
-==*/
+/*==*/
 
-/* Validation function for cards with a valid CIS */
+/**
+ * readable() - iomem validation function for cards with a valid CIS
+ */
 static int readable(struct pcmcia_socket *s, struct resource *res,
unsigned int *count)
 {
-   int ret = -1;
+   int ret = -EINVAL;
 
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
@@ -286,13 +283,16 @@ static int readable(struct pcmcia_socket *s, struct 
resource *res,
s->cis_virt = NULL;
}
s->cis_mem.res = NULL;
-   if ((ret != 0) || (*count == 0))
-   return 0;
-   return 1;
+   if ((ret) || (*count == 0))
+   return -EINVAL;
+   return 0;
 }
 
-/* Validation function for simple memory cards */
-static int checksum(struct pcmcia_socket *s, struct resource *res)
+/**
+ * checksum() - iomem validation function for simple memory cards
+ */
+static int checksum(struct pcmcia_socket *s, struct resource *res,
+   unsigned int *value)
 {
pccard_mem_map map;
int i, a = 0, b = -1, d;
@@ -320,61 +320,83 @@ static int checksum(struct pcmcia_socket *s, struct 
resource *res)
iounmap(virt);
}
 
-   return (b == -1) ? -1 : (a>>1);
-}
-
-static int
-cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
-{
-   struct resource *res1, *res2;
-   unsigned int info1, info2;
-   int ret = 0;
-
-   res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
-   res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
-   "PCMCIA memprobe");
-
-   if (res1 && res2) {
-   ret = readable(s, res1, &info1);
-   ret += readable(s, res2, &info2);
-   }
+   if (b == -1)
+   return -EINVAL;
 
-   free_region(res2);
-   free_region(res1);
+   *value = a;
 
-   return (ret == 2) && (info1 == info2);
+   return 0;
 }
 
-static int
-checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
+/**
+ * do_validate_mem() - low level validate a memory region for PCMCIA use
+ * @s: PCMCIA socket to validate
+ * @base:  start address of resource to check
+ * @size:  size of resource to check
+ * @validate:  validation function to use
+ *
+ * do_validate_mem() splits up the memory region which is to be checked
+ * into two parts. Both are passed to the @validate() function. If
+ * @validate() returns non-zero, or the value parameter to @validate()
+ * is zero, or the value parameter is different between both calls,
+ * the check fails, and -EINVAL is returned. Else, 0 is returned.
+ */
+static int do_validate_mem(struct pcmcia_socket *s,
+  unsigned long base, unsigned long size,
+  int validate (struct pcmcia_socket *s,
+struct resource *res,
+unsigned int *value))
 {
struct resource *res1, *res2;
-   int a = -1, b = -1;
+   unsigned int info1 = 1, info2 = 1;
+   int ret = -EINVAL;
 
res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
"PCMCIA memprobe");
 
if (res1 && res2) {
-   a = checksum(s, res1);
-   b = checksum(s, res2);
+   ret = 0;
+   if (validate) {
+   ret = validate(s, res1, &info1);
+   ret += validate(s, res2, &info2);
+   }
}
 
free_region(res2);
free_region(res1);
 
-   return (a == b) && (a >= 0);
-}
+   dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u",
+   base, base+size-1, res1, res2, ret, info1, info2);
 
-/*=

[PATCH 45/49] pcmcia: handle error in serial_cs config calls

2010-02-27 Thread Dominik Brodowski
Do not ignore the error returned by simple_config() / multi_config().

CC: linux-ser...@vger.kernel.org
Signed-off-by: Dominik Brodowski 
---
 drivers/serial/serial_cs.c |7 ---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 0ee7239..8d38eab 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -695,11 +695,11 @@ static int serial_config(struct pcmcia_device * link)
info->multi = info->quirk->multi;
 
if (info->multi > 1)
-   multi_config(link);
+   i = multi_config(link);
else
-   simple_config(link);
+   i = simple_config(link);
 
-   if (info->ndev == 0)
+   if (i || info->ndev == 0)
goto failed;
 
/*
@@ -714,6 +714,7 @@ static int serial_config(struct pcmcia_device * link)
return 0;
 
 failed:
+   dev_warn(&link->dev, "serial_cs: failed to initialize\n");
serial_remove(link);
return -ENODEV;
 }
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 18/49] pcmcia: do not use resource manager on !PCMCIA

2010-02-27 Thread Dominik Brodowski
If only CardBus cards are used, but not PCMCIA cards, we do not need
the extensive resource management functions provided for by
rsrc_nonstatic.c (~240K).

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/Kconfig |4 ++--
 include/pcmcia/ss.h|   10 ++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 44b324b..efc51b9 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -84,7 +84,7 @@ config YENTA
tristate "CardBus yenta-compatible bridge support"
depends on PCI
select CARDBUS if !EMBEDDED
-   select PCCARD_NONSTATIC
+   select PCCARD_NONSTATIC if PCMCIA
---help---
  This option enables support for CardBus host bridges.  Virtually
  all modern PCMCIA bridges are CardBus compatible.  A "bridge" is
@@ -162,7 +162,7 @@ config TCIC
 config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support"
depends on PCMCIA && PPC && 8xx
-   select PCCARD_IODYN
+   select PCCARD_IODYN if PCMCIA
help
  Say Y here to include support for PowerPC 8xx series PCMCIA
  controller.
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 1a47379..9ab53d8 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -263,10 +263,20 @@ struct pcmcia_socket {
  * - pccard_nonstatic_ops  iomem and ioport areas are assigned dynamically.
  * If this option is selected, use
  * "select PCCARD_NONSTATIC" in Kconfig.
+ *
  */
 extern struct pccard_resource_ops pccard_static_ops;
+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
 extern struct pccard_resource_ops pccard_iodyn_ops;
 extern struct pccard_resource_ops pccard_nonstatic_ops;
+#else
+/* If PCMCIA is not used, but only CARDBUS, these functions are not used
+ * at all. Therefore, do not use the large (240K!) rsrc_nonstatic module
+ */
+#define pccard_iodyn_ops pccard_static_ops
+#define pccard_nonstatic_ops pccard_static_ops
+#endif
+
 
 /* socket drivers are expected to use these callbacks in their .drv struct */
 extern int pcmcia_socket_dev_suspend(struct device *dev);
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia


[PATCH 13/49] pcmcia: remove some rsrc_mgr indirections

2010-02-27 Thread Dominik Brodowski
Remove rsrc_mgr indirections only used by pcmcia_resource.c

Tested-by: Wolfram Sang 
Signed-off-by: Dominik Brodowski 
---
 drivers/pcmcia/cs_internal.h |8 
 drivers/pcmcia/pcmcia_resource.c |   17 +
 drivers/pcmcia/rsrc_mgr.c|   18 --
 3 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 7f86d09..ad05e3b 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -168,14 +168,6 @@ int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t 
*tuple);
 
 /* rsrc_mgr.c */
 int pcmcia_validate_mem(struct pcmcia_socket *s);
-struct resource *pcmcia_find_io_region(unsigned long base,
-  int num,
-  unsigned long align,
-  struct pcmcia_socket *s);
-int pcmcia_adjust_io_region(struct resource *res,
-   unsigned long r_start,
-   unsigned long r_end,
-   struct pcmcia_socket *s);
 struct resource *pcmcia_find_mem_region(u_long base,
u_long num,
u_long align,
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index d5db956..880b0b6 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -43,6 +43,23 @@ module_param(io_speed, int, 0444);
 static u8 pcmcia_used_irq[NR_IRQS];
 #endif
 
+static int pcmcia_adjust_io_region(struct resource *res, unsigned long start,
+  unsigned long end, struct pcmcia_socket *s)
+{
+   if (s->resource_ops->adjust_io_region)
+   return s->resource_ops->adjust_io_region(res, start, end, s);
+   return -ENOMEM;
+}
+
+static struct resource *pcmcia_find_io_region(unsigned long base, int num,
+ unsigned long align,
+ struct pcmcia_socket *s)
+{
+   if (s->resource_ops->find_io)
+   return s->resource_ops->find_io(base, num, align, s);
+   return NULL;
+}
+
 
 /** alloc_io_space
  *
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 66c7800..81540c4 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -31,24 +31,6 @@ int pcmcia_validate_mem(struct pcmcia_socket *s)
 }
 EXPORT_SYMBOL(pcmcia_validate_mem);
 
-int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
-unsigned long r_end, struct pcmcia_socket *s)
-{
-   if (s->resource_ops->adjust_io_region)
-   return s->resource_ops->adjust_io_region(res, r_start, r_end, 
s);
-   return -ENOMEM;
-}
-EXPORT_SYMBOL(pcmcia_adjust_io_region);
-
-struct resource *pcmcia_find_io_region(unsigned long base, int num,
-  unsigned long align, struct pcmcia_socket *s)
-{
-   if (s->resource_ops->find_io)
-   return s->resource_ops->find_io(base, num, align, s);
-   return NULL;
-}
-EXPORT_SYMBOL(pcmcia_find_io_region);
-
 struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
 int low, struct pcmcia_socket *s)
 {
-- 
1.6.3.3


___
Linux PCMCIA reimplementation list
http://lists.infradead.org/mailman/listinfo/linux-pcmcia