diff options
author | Jan-Bernd Themann <ossthema@de.ibm.com> | 2010-06-15 01:35:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-16 21:05:27 -0400 |
commit | 099473c16bac7b936994bc95b5fd96f36397e1ad (patch) | |
tree | 09acc87af2002c2f737b83613394959120aee2c0 /drivers/net/ehea | |
parent | a91fb143de61dce847e319ca79b9937a665ad622 (diff) |
ehea: Fix kernel deadlock in DLPAR-mem processing
Port reset operations and memory add/remove operations need to
be serialized to avoid a kernel deadlock. The deadlock is caused
by calling the napi_disable() function twice.
Therefore we have to employ the dlpar_mem_lock in the ehea_reset_port
function as well
Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ehea')
-rw-r--r-- | drivers/net/ehea/ehea.h | 2 | ||||
-rw-r--r-- | drivers/net/ehea/ehea_main.c | 8 |
2 files changed, 4 insertions, 6 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 0630980a2722..0060e422f171 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | 41 | ||
42 | #define DRV_NAME "ehea" | 42 | #define DRV_NAME "ehea" |
43 | #define DRV_VERSION "EHEA_0103" | 43 | #define DRV_VERSION "EHEA_0105" |
44 | 44 | ||
45 | /* eHEA capability flags */ | 45 | /* eHEA capability flags */ |
46 | #define DLPAR_PORT_ADD_REM 1 | 46 | #define DLPAR_PORT_ADD_REM 1 |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index fd890faf5174..8b92acb448c2 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -2860,6 +2860,7 @@ static void ehea_reset_port(struct work_struct *work) | |||
2860 | container_of(work, struct ehea_port, reset_task); | 2860 | container_of(work, struct ehea_port, reset_task); |
2861 | struct net_device *dev = port->netdev; | 2861 | struct net_device *dev = port->netdev; |
2862 | 2862 | ||
2863 | mutex_lock(&dlpar_mem_lock); | ||
2863 | port->resets++; | 2864 | port->resets++; |
2864 | mutex_lock(&port->port_lock); | 2865 | mutex_lock(&port->port_lock); |
2865 | netif_stop_queue(dev); | 2866 | netif_stop_queue(dev); |
@@ -2882,6 +2883,7 @@ static void ehea_reset_port(struct work_struct *work) | |||
2882 | netif_wake_queue(dev); | 2883 | netif_wake_queue(dev); |
2883 | out: | 2884 | out: |
2884 | mutex_unlock(&port->port_lock); | 2885 | mutex_unlock(&port->port_lock); |
2886 | mutex_unlock(&dlpar_mem_lock); | ||
2885 | } | 2887 | } |
2886 | 2888 | ||
2887 | static void ehea_rereg_mrs(struct work_struct *work) | 2889 | static void ehea_rereg_mrs(struct work_struct *work) |
@@ -3543,10 +3545,7 @@ static int ehea_mem_notifier(struct notifier_block *nb, | |||
3543 | int ret = NOTIFY_BAD; | 3545 | int ret = NOTIFY_BAD; |
3544 | struct memory_notify *arg = data; | 3546 | struct memory_notify *arg = data; |
3545 | 3547 | ||
3546 | if (!mutex_trylock(&dlpar_mem_lock)) { | 3548 | mutex_lock(&dlpar_mem_lock); |
3547 | ehea_info("ehea_mem_notifier must not be called parallelized"); | ||
3548 | goto out; | ||
3549 | } | ||
3550 | 3549 | ||
3551 | switch (action) { | 3550 | switch (action) { |
3552 | case MEM_CANCEL_OFFLINE: | 3551 | case MEM_CANCEL_OFFLINE: |
@@ -3575,7 +3574,6 @@ static int ehea_mem_notifier(struct notifier_block *nb, | |||
3575 | 3574 | ||
3576 | out_unlock: | 3575 | out_unlock: |
3577 | mutex_unlock(&dlpar_mem_lock); | 3576 | mutex_unlock(&dlpar_mem_lock); |
3578 | out: | ||
3579 | return ret; | 3577 | return ret; |
3580 | } | 3578 | } |
3581 | 3579 | ||