Re: broken pcmcia_bus_match for dynids

2010-01-16 Thread Dominik Brodowski
Hey,

On Wed, Jan 13, 2010 at 01:42:05PM +0100, Jiri Slaby wrote:
 stanse found that when PCMCIA_DEV_ID_MATCH_FAKE_CIS is set in
 match_flags for a dynid, the pcmcia layer may deadlock.
 
 pcmcia_load_firmware in such case calls non-atomic operations
 (request_firmware, kzalloc(GFP_KERNEL)), while dynids.lock spinlock is held.
 
 Any ideas how to solve this? Any idea, why p_drv-dynids.lock is not a
 mutex instead?

Well, as dynid-id.cisfile is never set, it is still NULL, which means
pcmcia_load_firmware is left immediately, without calling the (blocking)
request_firmare(). So this actually isn't a problem, AFAICS.

Nonetheless, I'll prepare a patch to replace it with a mutex for 2.6.34.

Best,
Dominik

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


Re: broken pcmcia_bus_match for dynids

2010-01-16 Thread Jiri Slaby
On 01/16/2010 01:04 PM, Dominik Brodowski wrote:
 Well, as dynid-id.cisfile is never set, it is still NULL

Ah, I overlooked that. Thanks for pointing out.

-- 
js

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


[PATCH 02/12] pcmcia: also lock fake and cache CIS by ops_mutex

2010-01-16 Thread Dominik Brodowski
Specifically,

struct list_headcis_cache;
size_t  fake_cis_len;
u8  *fake_cis;

are protected.

Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 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 
event, int priority)
dev_dbg(skt-dev, cis mismatch - 

[PATCH 09/12] pcmcia: add locking documentation

2010-01-16 Thread Dominik Brodowski
Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 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..a3c43a7
--- /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 04/12] pcmcia: lock ops-set_socket

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

Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 drivers/pcmcia/cs.c  |   21 +
 drivers/pcmcia/pcmcia_resource.c |   15 +--
 2 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 91aa1f2..07673d9 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,31 +546,34 @@ 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);
 
-   if (skt-resume_status) {
+   if (skt-resume_status)
socket_shutdown(skt);
return 0;
-   }
 
if (skt-suspended_state != skt-state) {
dev_dbg(skt-dev,
@@ -795,7 +805,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 

[PATCH 10/12] pcmcia: assert locking to struct pcmcia_device

2010-01-16 Thread Dominik Brodowski
Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 Documentation/pcmcia/locking.txt |   25 +
 drivers/pcmcia/ds.c  |   38 +
 drivers/pcmcia/pcmcia_resource.c |  108 --
 3 files changed, 120 insertions(+), 51 deletions(-)

diff --git a/Documentation/pcmcia/locking.txt b/Documentation/pcmcia/locking.txt
index a3c43a7..eaadba7 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:
-   if (!ret)
-   p_dev-suspended = 0;
return ret;
 }
 

[PATCH 08/12] pcmcia: simplify locking

2010-01-16 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.

Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 drivers/pcmcia/cs.c   |2 -
 drivers/pcmcia/ds.c   |   69 -
 drivers/pcmcia/pcmcia_ioctl.c |   11 +++---
 drivers/pcmcia/rsrc_mgr.c |6 +--
 drivers/pcmcia/socket_sysfs.c |5 +--
 include/pcmcia/ss.h   |7 ++--
 6 files changed, 40 insertions(+), 60 deletions(-)

diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 07673d9..4cca8ca 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/ds.c b/drivers/pcmcia/ds.c
index d1d7a0c..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 *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
goto err_free;
dev_dbg(p_dev-dev, devname is %s\n, p_dev-devname);
 
-   spin_lock_irqsave(pcmcia_dev_list_lock, flags);
+   mutex_lock(s-ops_mutex);
 
/*
 * p_dev-function_config must be the same for all card functions.
@@ -564,7 +559,7 @@ struct pcmcia_device *pcmcia_device_add(struct 
pcmcia_socket *s, unsigned int fu
/* Add to the list in pcmcia_bus_socket */
list_add(p_dev-socket_device_list, s-devices_list);
 
-   spin_unlock_irqrestore(pcmcia_dev_list_lock, flags);
+   

[PATCH 07/12] pcmcia: add locking to struct pcmcia_socket-pcmcia_state()

2010-01-16 Thread Dominik Brodowski
Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 drivers/pcmcia/ds.c |   32 +---
 1 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index bcb9ef1..d1d7a0c 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;
 }
@@ -1387,7 +1410,10 @@ static void pcmcia_bus_remove_socket(struct device *dev,
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 03/12] pcmcia: lock ops-set_io_map()

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

Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net
---
 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


Re: [PATCH] ide/ide-cs: fix order of releasing resources

2010-01-16 Thread Wolfram Sang
  bzolnier:
  - release resources in ide_release() to fix ordering of events
  - remove stale FIXME note while at it
 
 Ok this does look better, Wolfram can you test this?

Works as expected.

-- 
Pengutronix e.K.   | Wolfram Sang|
Industrial Linux Solutions | http://www.pengutronix.de/  |


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


Re: [RFC] PCMCIA locking updates for 2.6.34

2010-01-16 Thread Wolfram Sang
Hi Dominik,

On Sat, Jan 16, 2010 at 01:41:43PM +0100, Dominik Brodowski wrote:

 
 on top of what had already been discussed for 2.6.34, here are 12 patches
 trying to fix the locking mess the PCMCIA subsystem used to be. As a
 side-effect, the PCMCIA ioctl will be disabled for all except the ARM
 architecture, and even there you need !SMP and !PREEMPT. Hopefully, we'll be
 able to remove the ioctl from ARM too.
 
 Everything is available in the git repository at:
 
   git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git#locking

I pulled and tested this branch. Sadly, it doesn't work for me. If I insert a
(previously working) network card, io-resources get allocated, but the driver
does not even print its success-string. Luckily, I had hung-task detection
enabled:

[   54.276728] pcmcia_socket pcmcia_socket0: pccard: PCMCIA card inserted into 
slot 0
[   54.276747] pcmcia_socket pcmcia_socket0: cs: memory probe 
0x0d4000-0x0d: clean.
[   54.288227] pcmcia_socket pcmcia_socket0: cs: memory probe 
0x6000-0x60ff: clean.
[   54.318694] pcmcia_socket pcmcia_socket0: cs: memory probe 
0xa000-0xa0ff: clean.
[   54.349945] pcmcia_socket pcmcia_socket0: cs: memory probe 
0xffd1-0xffde: clean.
[   54.381320] pcmcia 0.0: pcmcia: registering new device pcmcia0.0
[  240.110047] INFO: task modprobe:2669 blocked for more than 120 seconds.
[  240.110056] echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this 
message.
[  240.110065] modprobe  D bf05c428 0  2669  1 0x
[  240.110078]  bd823c40 0086 c1d6637d bf05c428 bf800140 bf87d890 bf05c534 
bf87d890
[  240.110096]  bf05c538 bd823c64 8050eac3 bf05c538 bf05c538 bf87d890  
bf05c534
[  240.110112]  bf03d020 bf05c428 bd823c74 8050ed2e bf03d020 bf03d000 bd823cac 
c1d66e58
[  240.110128] Call Trace:
[  240.110155]  [c1d6637d] ? alloc_io_space+0x32d/0x3a0 [pcmcia]
[  240.110170]  [8050eac3] __mutex_lock_slowpath+0x53/0x90
[  240.110181]  [8050ed2e] mutex_lock+0x1e/0x30
[  240.110195]  [c1d66e58] pcmcia_request_io+0x28/0x420 [pcmcia]
[  240.110204]  [8050ed23] ? mutex_lock+0x13/0x30
[  240.110218]  [c1d69b23] ? read_cis_cache+0xa3/0x200 [pcmcia]
[  240.110239]  [c1b60f30] pcnet_confcheck+0x110/0x174 [pcnet_cs]
[  240.110253]  [c1d65f49] pcmcia_do_loop_config+0x69/0x80 [pcmcia]
[  240.110267]  [c1d6a47d] pccard_loop_tuple+0xed/0x150 [pcmcia]
[  240.110282]  [c1d65ee0] ? pcmcia_do_loop_config+0x0/0x80 [pcmcia]
[  240.110296]  [c1d666a9] pcmcia_loop_config+0xb9/0xd0 [pcmcia]
[  240.110310]  [c1d65ee0] ? pcmcia_do_loop_config+0x0/0x80 [pcmcia]
[  240.110327]  [c1b60e20] ? pcnet_confcheck+0x0/0x174 [pcnet_cs]
[  240.110344]  [c1b6016d] pcnet_probe+0x9d/0xbf0 [pcnet_cs]
[  240.110358]  [c1d69b23] ? read_cis_cache+0xa3/0x200 [pcmcia]
[  240.110373]  [c1d6a31f] ? pccard_read_tuple+0xaf/0x120 [pcmcia]
[  240.110388]  [80292491] ? ida_get_new_above+0x81/0x1f0
[  240.110402]  [c1d63de8] pcmcia_device_probe+0xf8/0x2b0 [pcmcia]
[  240.110412]  [8050ed23] ? mutex_lock+0x13/0x30
[  240.110425]  [803bae00] ? driver_sysfs_add+0x50/0x70
[  240.110435]  [803baf73] driver_probe_device+0x93/0x280
[  240.110445]  [802934d9] ? kobject_add_internal+0xb9/0x240
[  240.110456]  [803bb1e9] __driver_attach+0x89/0x90
[  240.110466]  [803ba683] bus_for_each_dev+0x53/0x80
[  240.110476]  [803bad4e] driver_attach+0x1e/0x20
[  240.110486]  [803bb160] ? __driver_attach+0x0/0x90
[  240.110495]  [803b9f17] bus_add_driver+0x207/0x300
[  240.110510]  [c1d63a40] ? pcmcia_device_remove+0x0/0x1e0 [pcmcia]
[  240.110520]  [803bb4ca] driver_register+0x7a/0x170
[  240.110535]  [c1d65bd4] pcmcia_register_driver+0xb4/0x170 [pcmcia]
[  240.110549]  [8016d1c5] ? tracepoint_module_notify+0x25/0x30
[  240.110561]  [8014c64d] ? notifier_call_chain+0x3d/0x80
[  240.110578]  [c1b6f000] ? init_pcnet_cs+0x0/0xf [pcnet_cs]
[  240.110596]  [c1b6f00d] init_pcnet_cs+0xd/0xf [pcnet_cs]
[  240.110606]  [80101118] do_one_initcall+0x28/0x180
[  240.110617]  [8014cb4f] ? blocking_notifier_call_chain+0x1f/0x30
[  240.110630]  [8015f00f] sys_init_module+0xaf/0x210
[  240.110640]  [80102bd0] sysenter_do_call+0x12/0x26

A deadlock? At this stage, the pcmcia-host is stuck. Card removal is detected,
but the resources don't get freed. Let me know if I can provide more info or
can do more testing.

Regards,

   Wolfram

-- 
Pengutronix e.K.   | Wolfram Sang|
Industrial Linux Solutions | http://www.pengutronix.de/  |


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


Re: [RFC] PCMCIA locking updates for 2.6.34

2010-01-16 Thread Dominik Brodowski
Hey Wolfram,

On Sat, Jan 16, 2010 at 08:41:21PM +0100, Wolfram Sang wrote:
 On Sat, Jan 16, 2010 at 01:41:43PM +0100, Dominik Brodowski wrote:
 
  
  on top of what had already been discussed for 2.6.34, here are 12 patches
  trying to fix the locking mess the PCMCIA subsystem used to be. As a
  side-effect, the PCMCIA ioctl will be disabled for all except the ARM
  architecture, and even there you need !SMP and !PREEMPT. Hopefully, we'll be
  able to remove the ioctl from ARM too.
  
  Everything is available in the git repository at:
  
git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git#locking
 
 I pulled and tested this branch. Sadly, it doesn't work for me. If I insert a
 (previously working) network card, io-resources get allocated, but the driver
 does not even print its success-string. Luckily, I had hung-task detection
 enabled:

Thanks for testing -- might it be the following one-liner?

 A deadlock? At this stage, the pcmcia-host is stuck. Card removal is detected,
 but the resources don't get freed. Let me know if I can provide more info or
 can do more testing.

If it doesn't help, could you enable lockdep, please, and check with

echo d  /proc/sysrq-trigger

which lock is held where by which task?

Best,
Dominik

From: Dominik Brodowski li...@dominikbrodowski.net
Date: Sat, 16 Jan 2010 21:19:57 +0100
Subject: [PATCH] pcmcia: fix pcmcia_request_io locking

Signed-off-by: Dominik Brodowski li...@dominikbrodowski.net

diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
index 052b6ca..44cb7fa 100644
--- a/drivers/pcmcia/pcmcia_resource.c
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -689,9 +689,10 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, 
io_req_t *req)
c-io = *req;
c-state |= CONFIG_IO_REQ;
p_dev-_io = 1;
-   mutex_unlock(s-ops_mutex);
 
 out:
+   mutex_unlock(s-ops_mutex);
+
return ret;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);

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


Re: [RFC] PCMCIA locking updates for 2.6.34

2010-01-16 Thread Komuro
Hi,

Same result as Wolfram.

 
 echo d  /proc/sysrq-trigger

No output from sysrq-trigger.



pcmcia 0.0: pcmcia: registering new device pcmcia0.0
pcmcia 0.1: pcmcia: registering new device pcmcia0.1
INFO: task modprobe:2191 blocked for more than 120 seconds.
echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this message.
modprobe  D 001c 0  2191   2187 0x0080
 f45f1dd8 0086 36e648c7 001c f518c2f4 c0922ec0 c091e394 c0922ec0
 f518c2f4 c0922ec0 c0922ec0 f45f fffd451a c3a84394 0001 
 001c f518c060 00d8    f6a1f178 f6a1f170
Call Trace:
 [c06c880c] __mutex_lock_common+0x109/0x158
 [c06644bf] ? alloc_netdev_mq+0x19e/0x1bf
 [c06c8872] __mutex_lock_slowpath+0x17/0x1a
 [c06c8961] ? mutex_lock+0x30/0x3e
 [c06c8961] mutex_lock+0x30/0x3e
 [f88b8f9d] pcmcia_request_io+0x23/0xc9 [pcmcia]
 [fb62d879] tc589_probe+0xfb/0x2eb [3c589_cs]
 [f88b78b3] pcmcia_device_probe+0x121/0x1a9 [pcmcia]
 [c05d5100] ? device_release_driver+0xd/0x28
 [c05d526a] driver_probe_device+0x7e/0xf2
 [c05d5326] __driver_attach+0x48/0x64
 [c05d4a62] bus_for_each_dev+0x42/0x6c
 [c05d5134] driver_attach+0x19/0x1b
 [c05d52de] ? __driver_attach+0x0/0x64
 [c05d4e34] bus_add_driver+0x94/0x1c4
 [c054f8e4] ? kset_find_obj+0x12/0x4f
 [c05d557b] driver_register+0x7e/0xe5
 [f88b8172] pcmcia_register_driver+0xc2/0xf2 [pcmcia]
 [f80a7000] ? init_tc589+0x0/0xf [3c589_cs]
 [f80a700d] init_tc589+0xd/0xf [3c589_cs]
 [c040305b] do_one_initcall+0x51/0x144
 [c0469d6b] sys_init_module+0xac/0x1e0
 [c0408058] sysenter_do_call+0x12/0x2d
INFO: task modprobe:2192 blocked for more than 120 seconds.
echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this message.
modprobe  D 001c 0  2192   2188 0x0080
 f45f3e64 0086 3840b4f3 001c f5378f74 26c0 c091e394 c0922ec0
 f5378f74 c0922ec0 c0922ec0 f45f3e5c fffd457c c3a04394  
 001c f5378ce0 f45f3e94    f712fc9c f712fc94
Call Trace:
 [c06c8382] schedule_timeout+0x1b/0x95
 [f88b7e95] ? pcmcia_devmatch+0x2a3/0x2b4 [pcmcia]
 [c050c09e] ? __sysfs_add_one+0x2b/0x7a
 [c050c437] ? sysfs_addrm_finish+0x1b/0x93
 [c050c5f4] ? sysfs_add_one+0x18/0xc2
 [c06c8c3b] __down_common+0x82/0xb9
 [c06c8cd1] __down+0x17/0x19
 [c045a16c] down+0x27/0x37
 [c05d530d] __driver_attach+0x2f/0x64
 [c05d4a62] bus_for_each_dev+0x42/0x6c
 [c05d5134] driver_attach+0x19/0x1b
 [c05d52de] ? __driver_attach+0x0/0x64
 [c05d4e34] bus_add_driver+0x94/0x1c4
 [c054f8f5] ? kset_find_obj+0x23/0x4f
 [c05d557b] driver_register+0x7e/0xe5
 [f88b8172] pcmcia_register_driver+0xc2/0xf2 [pcmcia]
 [fb66d000] ? init_serial_cs+0x0/0xf [serial_cs]
 [fb66d00d] init_serial_cs+0xd/0xf [serial_cs]
 [c040305b] do_one_initcall+0x51/0x144
 [c0469d6b] sys_init_module+0xac/0x1e0
 [c0408058] sysenter_do_call+0x12/0x2d
SysRq : HELP : loglevel(0-9) reBoot Crash terminate-all-tasks(E) 
memory-full-oom-kill(F) kill-all-tasks(I) thaw-filesystems(J) saK 
show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) 
powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) 
Unmount force-fb(V) show-blocked-tasks(W) dump-ftrace-buffer(Z) 
INFO: task modprobe:2191 blocked for more than 120 seconds.
echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this message.
modprobe  D 001c 0  2191  1 0x0080
 f45f1dd8 0086 36e648c7 001c f518c2f4 c0922ec0 c091e394 c0922ec0
 f518c2f4 c0922ec0 c0922ec0 f45f fffd451a c3a84394 0001 
 001c f518c060 00d8    f6a1f178 f6a1f170
Call Trace:
 [c06c880c] __mutex_lock_common+0x109/0x158
 [c06644bf] ? alloc_netdev_mq+0x19e/0x1bf
 [c06c8872] __mutex_lock_slowpath+0x17/0x1a
 [c06c8961] ? mutex_lock+0x30/0x3e
 [c06c8961] mutex_lock+0x30/0x3e
 [f88b8f9d] pcmcia_request_io+0x23/0xc9 [pcmcia]
 [fb62d879] tc589_probe+0xfb/0x2eb [3c589_cs]
 [f88b78b3] pcmcia_device_probe+0x121/0x1a9 [pcmcia]
 [c05d5100] ? device_release_driver+0xd/0x28
 [c05d526a] driver_probe_device+0x7e/0xf2
 [c05d5326] __driver_attach+0x48/0x64
 [c05d4a62] bus_for_each_dev+0x42/0x6c
 [c05d5134] driver_attach+0x19/0x1b
 [c05d52de] ? __driver_attach+0x0/0x64
 [c05d4e34] bus_add_driver+0x94/0x1c4
 [c054f8e4] ? kset_find_obj+0x12/0x4f
 [c05d557b] driver_register+0x7e/0xe5
 [f88b8172] pcmcia_register_driver+0xc2/0xf2 [pcmcia]
 [f80a7000] ? init_tc589+0x0/0xf [3c589_cs]
 [f80a700d] init_tc589+0xd/0xf [3c589_cs]
 [c040305b] do_one_initcall+0x51/0x144
 [c0469d6b] sys_init_module+0xac/0x1e0
 [c0408058] sysenter_do_call+0x12/0x2d
INFO: task modprobe:2192 blocked for more than 120 seconds.
echo 0  /proc/sys/kernel/hung_task_timeout_secs disables this message.
modprobe  D 001c 0  2192  1 0x0080
 f45f3e64 0086 3840b4f3 001c f5378f74 26c0 c091e394 c0922ec0
 f5378f74 c0922ec0 c0922ec0 f45f3e5c fffd457c c3a04394  
 001c f5378ce0 f45f3e94    f712fc9c f712fc94
Call Trace:
 [c06c8382]