Commit a7c561f2 authored by Thomas Klein's avatar Thomas Klein Committed by David S. Miller
Browse files

ehea: fix possible DLPAR/mem deadlock



Force serialization of userspace-triggered DLPAR/mem operations

Signed-off-by: default avatarThomas Klein <tklein@de.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ea96ceac
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
#include <asm/io.h>

#define DRV_NAME	"ehea"
#define DRV_VERSION	"EHEA_0102"
#define DRV_VERSION	"EHEA_0103"

/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
+14 −5
Original line number Diff line number Diff line
@@ -2889,7 +2889,6 @@ static void ehea_rereg_mrs(struct work_struct *work)
	int ret, i;
	struct ehea_adapter *adapter;

	mutex_lock(&dlpar_mem_lock);
	ehea_info("LPAR memory changed - re-initializing driver");

	list_for_each_entry(adapter, &adapter_list, list)
@@ -2959,7 +2958,6 @@ static void ehea_rereg_mrs(struct work_struct *work)
		}
	ehea_info("re-initializing driver complete");
out:
	mutex_unlock(&dlpar_mem_lock);
	return;
}

@@ -3542,7 +3540,14 @@ void ehea_crash_handler(void)
static int ehea_mem_notifier(struct notifier_block *nb,
                             unsigned long action, void *data)
{
	int ret = NOTIFY_BAD;
	struct memory_notify *arg = data;

	if (!mutex_trylock(&dlpar_mem_lock)) {
		ehea_info("ehea_mem_notifier must not be called parallelized");
		goto out;
	}

	switch (action) {
	case MEM_CANCEL_OFFLINE:
		ehea_info("memory offlining canceled");
@@ -3551,14 +3556,14 @@ static int ehea_mem_notifier(struct notifier_block *nb,
		ehea_info("memory is going online");
		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
		if (ehea_add_sect_bmap(arg->start_pfn, arg->nr_pages))
			return NOTIFY_BAD;
			goto out_unlock;
		ehea_rereg_mrs(NULL);
		break;
	case MEM_GOING_OFFLINE:
		ehea_info("memory is going offline");
		set_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
		if (ehea_rem_sect_bmap(arg->start_pfn, arg->nr_pages))
			return NOTIFY_BAD;
			goto out_unlock;
		ehea_rereg_mrs(NULL);
		break;
	default:
@@ -3566,8 +3571,12 @@ static int ehea_mem_notifier(struct notifier_block *nb,
	}

	ehea_update_firmware_handles();
	ret = NOTIFY_OK;

	return NOTIFY_OK;
out_unlock:
	mutex_unlock(&dlpar_mem_lock);
out:
	return ret;
}

static struct notifier_block ehea_mem_nb = {