mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 02:01:29 +00:00
[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: Kashyap Desai <kashyap.desai@lsi.com> Cc: stable@kernel.org Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
ec07a05359
commit
4224489f45
@ -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)
|
|||||||
"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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user