aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKashyap, Desai <kashyap.desai@lsi.com>2010-11-12 18:01:14 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:03 -0500
commitdd3741d30300f9cf1adc046773a4bb87252d96ac (patch)
tree948c762c9b1131ce0dd7d7eb8879d4c607908a58
parent363fa50fc35357b1361fb63b0726335de993374a (diff)
[SCSI] mpt2sas: Added sanity check for cb_idx and smid access.
Sometime it is seen that controller firmware returns an invalid system message id (smid). the oops is occurring becuase mpt_callbacks pointer is referenced to either null or invalid virtual address. this is due to cb_idx set incorrectly from routine _base_get_cb_idx. the cb_idx was set incorrectly becuase there is no check to make sure smid is less than maxiumum anticapted smid. to fix this issue, we add a check in _base_get_cb_idx to make sure smid is not greater than ioc->hba_queue_depth. in addition, a similar check was added to make sure the reply address was less than the largest anticapated address. Newer firmware has sovled this issue, however it good to have this sanity check. Signed-off-by: Kashyap Desai <kashyap.desai@lsi.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c8
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h2
2 files changed, 9 insertions, 1 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 12faf64f91b0..d1c53455c063 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -758,7 +758,7 @@ _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
758 if (smid < ioc->internal_smid) { 758 if (smid < ioc->internal_smid) {
759 i = smid - ioc->hi_priority_smid; 759 i = smid - ioc->hi_priority_smid;
760 cb_idx = ioc->hpr_lookup[i].cb_idx; 760 cb_idx = ioc->hpr_lookup[i].cb_idx;
761 } else { 761 } else if (smid <= ioc->hba_queue_depth) {
762 i = smid - ioc->internal_smid; 762 i = smid - ioc->internal_smid;
763 cb_idx = ioc->internal_lookup[i].cb_idx; 763 cb_idx = ioc->internal_lookup[i].cb_idx;
764 } 764 }
@@ -848,6 +848,7 @@ _base_interrupt(int irq, void *bus_id)
848 return IRQ_NONE; 848 return IRQ_NONE;
849 849
850 completed_cmds = 0; 850 completed_cmds = 0;
851 cb_idx = 0xFF;
851 do { 852 do {
852 rd.word = rpf->Words; 853 rd.word = rpf->Words;
853 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) 854 if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
@@ -860,6 +861,9 @@ _base_interrupt(int irq, void *bus_id)
860 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { 861 MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
861 reply = le32_to_cpu 862 reply = le32_to_cpu
862 (rpf->AddressReply.ReplyFrameAddress); 863 (rpf->AddressReply.ReplyFrameAddress);
864 if (reply > ioc->reply_dma_max_address ||
865 reply < ioc->reply_dma_min_address)
866 reply = 0;
863 } else if (request_desript_type == 867 } else if (request_desript_type ==
864 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER) 868 MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
865 goto next; 869 goto next;
@@ -2221,6 +2225,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
2221 ioc->name); 2225 ioc->name);
2222 goto out; 2226 goto out;
2223 } 2227 }
2228 ioc->reply_dma_min_address = (u32)(ioc->reply_dma);
2229 ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz;
2224 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth" 2230 dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
2225 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply, 2231 "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
2226 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); 2232 ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 0b15a8bdebfc..63f7a196f42d 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -737,6 +737,8 @@ struct MPT2SAS_ADAPTER {
737 u16 reply_sz; 737 u16 reply_sz;
738 u8 *reply; 738 u8 *reply;
739 dma_addr_t reply_dma; 739 dma_addr_t reply_dma;
740 u32 reply_dma_max_address;
741 u32 reply_dma_min_address;
740 struct dma_pool *reply_dma_pool; 742 struct dma_pool *reply_dma_pool;
741 743
742 /* reply free queue */ 744 /* reply free queue */