Commit 4224489f authored by Kashyap, Desai's avatar Kashyap, Desai Committed by James Bottomley

[SCSI] mpt2sas: Kernel Panic during Large Topology discovery

There was a configuration page timing out during the initial port
enable at driver load time. The port enable would fail, and this would
result in the driver unloading itself, meanwhile the driver was accessing
freed memory in another context resulting in the panic.  The fix is to
prevent access to freed memory once the driver had issued the diag reset
which woke up the sleeping port enable process.  The routine
_base_reset_handler was reorganized so the last sleeping process woken up was
the port_enable.
Signed-off-by: default avatarKashyap Desai <kashyap.desai@lsi.com>
Cc: stable@kernel.org
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent ec07a053
...@@ -3941,6 +3941,8 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) ...@@ -3941,6 +3941,8 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
static void static void
_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
{ {
mpt2sas_scsih_reset_handler(ioc, reset_phase);
mpt2sas_ctl_reset_handler(ioc, reset_phase);
switch (reset_phase) { switch (reset_phase) {
case MPT2_IOC_PRE_RESET: case MPT2_IOC_PRE_RESET:
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: " dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
...@@ -3971,8 +3973,6 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) ...@@ -3971,8 +3973,6 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
"MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
break; break;
} }
mpt2sas_scsih_reset_handler(ioc, reset_phase);
mpt2sas_ctl_reset_handler(ioc, reset_phase);
} }
/** /**
...@@ -4026,6 +4026,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, ...@@ -4026,6 +4026,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
{ {
int r; int r;
unsigned long flags; unsigned long flags;
u8 pe_complete = ioc->wait_for_port_enable_to_complete;
dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name, dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
__func__)); __func__));
...@@ -4068,6 +4069,14 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, ...@@ -4068,6 +4069,14 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
if (r) if (r)
goto out; goto out;
_base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
/* If this hard reset is called while port enable is active, then
* there is no reason to call make_ioc_operational
*/
if (pe_complete) {
r = -EFAULT;
goto out;
}
r = _base_make_ioc_operational(ioc, sleep_flag); r = _base_make_ioc_operational(ioc, sleep_flag);
if (!r) if (!r)
_base_reset_handler(ioc, MPT2_IOC_DONE_RESET); _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment