| From 5d2aae3c41b0cae1e263a49ceb62b9d239fb703f Mon Sep 17 00:00:00 2001 |
| From: Kashyap, Desai <kashyap.desai@lsi.com> |
| Date: Tue, 4 Jan 2011 11:38:39 +0530 |
| Subject: [PATCH] mpt2sas: Kernel Panic during Large Topology discovery |
| |
| commit 4224489f45b503f0a1f1cf310f76dc108f45689a upstream. |
| |
| 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> |
| Signed-off-by: James Bottomley <James.Bottomley@suse.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c |
| index 21ddd36..d6f3ccf 100644 |
| --- a/drivers/scsi/mpt2sas/mpt2sas_base.c |
| +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c |
| @@ -3693,6 +3693,8 @@ mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc) |
| static void |
| _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) { |
| case MPT2_IOC_PRE_RESET: |
| dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: " |
| @@ -3723,8 +3725,6 @@ _base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) |
| "MPT2_IOC_DONE_RESET\n", ioc->name, __func__)); |
| break; |
| } |
| - mpt2sas_scsih_reset_handler(ioc, reset_phase); |
| - mpt2sas_ctl_reset_handler(ioc, reset_phase); |
| } |
| |
| /** |
| @@ -3778,6 +3778,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, |
| { |
| int r; |
| unsigned long flags; |
| + u8 pe_complete = ioc->wait_for_port_enable_to_complete; |
| |
| dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, |
| __func__)); |
| @@ -3802,6 +3803,14 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, |
| if (r) |
| goto out; |
| _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); |
| if (!r) |
| _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); |
| -- |
| 1.7.4.4 |
| |