diff options
author | Thomas Klein <tklein@de.ibm.com> | 2010-04-20 19:11:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-22 01:32:44 -0400 |
commit | a7c561f2e32f98b477f5fe670b3f294be6b1eae2 (patch) | |
tree | 8ce32aacea816de1dbbd9e4bc9ce3460ba638c03 /drivers/net/ehea | |
parent | ea96ceac80cc82cb1c54a37bb8aaf4e695e87d0a (diff) |
ehea: fix possible DLPAR/mem deadlock
Force serialization of userspace-triggered DLPAR/mem operations
Signed-off-by: Thomas Klein <tklein@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 | 19 |
2 files changed, 15 insertions, 6 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index fa311a950996..0630980a2722 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_0102" | 43 | #define DRV_VERSION "EHEA_0103" |
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 c35d1e3631d1..39774817c3eb 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
@@ -2889,7 +2889,6 @@ static void ehea_rereg_mrs(struct work_struct *work) | |||
2889 | int ret, i; | 2889 | int ret, i; |
2890 | struct ehea_adapter *adapter; | 2890 | struct ehea_adapter *adapter; |
2891 | 2891 | ||
2892 | mutex_lock(&dlpar_mem_lock); | ||
2893 | ehea_info("LPAR memory changed - re-initializing driver"); | 2892 | ehea_info("LPAR memory changed - re-initializing driver"); |
2894 | 2893 | ||
2895 | list_for_each_entry(adapter, &adapter_list, list) | 2894 | list_for_each_entry(adapter, &adapter_list, list) |
@@ -2959,7 +2958,6 @@ static void ehea_rereg_mrs(struct work_struct *work) | |||
2959 | } | 2958 | } |
2960 | ehea_info("re-initializing driver complete"); | 2959 | ehea_info("re-initializing driver complete"); |
2961 | out: | 2960 | out: |
2962 | mutex_unlock(&dlpar_mem_lock); | ||
2963 | return; | 2961 | return; |
2964 | } | 2962 | } |
2965 | 2963 | ||
@@ -3542,7 +3540,14 @@ void ehea_crash_handler(void) | |||
3542 | static int ehea_mem_notifier(struct notifier_block *nb, | 3540 | static int ehea_mem_notifier(struct notifier_block *nb, |
3543 | unsigned long action, void *data) | 3541 | unsigned long action, void *data) |
3544 | { | 3542 | { |
3543 | int ret = NOTIFY_BAD; | ||
3545 | struct memory_notify *arg = data; | 3544 | struct memory_notify *arg = data; |
3545 | |||
3546 | if (!mutex_trylock(&dlpar_mem_lock)) { | ||
3547 | ehea_info("ehea_mem_notifier must not be called parallelized"); | ||
3548 | goto out; | ||
3549 | } | ||
3550 | |||
3546 | switch (action) { | 3551 | switch (action) { |
3547 | case MEM_CANCEL_OFFLINE: | 3552 | case MEM_CANCEL_OFFLINE: |
3548 | ehea_info("memory offlining canceled"); | 3553 | ehea_info("memory offlining canceled"); |
@@ -3551,14 +3556,14 @@ static int ehea_mem_notifier(struct notifier_block *nb, | |||
3551 | ehea_info("memory is going online"); | 3556 | ehea_info("memory is going online"); |
3552 | set_bit(__EHEA_STOP_XFER, &ehea_driver_flags); | 3557 | set_bit(__EHEA_STOP_XFER, &ehea_driver_flags); |
3553 | if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages)) | 3558 | if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages)) |
3554 | return NOTIFY_BAD; | 3559 | goto out_unlock; |
3555 | ehea_rereg_mrs(NULL); | 3560 | ehea_rereg_mrs(NULL); |
3556 | break; | 3561 | break; |
3557 | case MEM_GOING_OFFLINE: | 3562 | case MEM_GOING_OFFLINE: |
3558 | ehea_info("memory is going offline"); | 3563 | ehea_info("memory is going offline"); |
3559 | set_bit(__EHEA_STOP_XFER, &ehea_driver_flags); | 3564 | set_bit(__EHEA_STOP_XFER, &ehea_driver_flags); |
3560 | if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages)) | 3565 | if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages)) |
3561 | return NOTIFY_BAD; | 3566 | goto out_unlock; |
3562 | ehea_rereg_mrs(NULL); | 3567 | ehea_rereg_mrs(NULL); |
3563 | break; | 3568 | break; |
3564 | default: | 3569 | default: |
@@ -3566,8 +3571,12 @@ static int ehea_mem_notifier(struct notifier_block *nb, | |||
3566 | } | 3571 | } |
3567 | 3572 | ||
3568 | ehea_update_firmware_handles(); | 3573 | ehea_update_firmware_handles(); |
3574 | ret = NOTIFY_OK; | ||
3569 | 3575 | ||
3570 | return NOTIFY_OK; | 3576 | out_unlock: |
3577 | mutex_unlock(&dlpar_mem_lock); | ||
3578 | out: | ||
3579 | return ret; | ||
3571 | } | 3580 | } |
3572 | 3581 | ||
3573 | static struct notifier_block ehea_mem_nb = { | 3582 | static struct notifier_block ehea_mem_nb = { |