Commit 03ea1115 authored by Eric Moore's avatar Eric Moore Committed by James Bottomley

[SCSI] mpt2sas : the sanity check in base_interrupt needs to be on dword boundary

The poison sanity check on the reply_post_free register needs to be by 32bit,
not 64bit. The poison check is there because its possible that the driver read
the 1st 32bit before the 2nd 32bit has been written to by firmware.  In other
words, this handles race between driver reading the 64 bit register, and it
being dma'd across pci memory from controller firmware as two 32bit pci writes.
Signed-off-by: default avatarEric Moore <eric.moore@lsi.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent fd01825c
...@@ -636,6 +636,14 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) ...@@ -636,6 +636,14 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
static irqreturn_t static irqreturn_t
_base_interrupt(int irq, void *bus_id) _base_interrupt(int irq, void *bus_id)
{ {
union reply_descriptor {
u64 word;
struct {
u32 low;
u32 high;
} u;
};
union reply_descriptor rd;
u32 post_index, post_index_next, completed_cmds; u32 post_index, post_index_next, completed_cmds;
u8 request_desript_type; u8 request_desript_type;
u16 smid; u16 smid;
...@@ -656,7 +664,8 @@ _base_interrupt(int irq, void *bus_id) ...@@ -656,7 +664,8 @@ _base_interrupt(int irq, void *bus_id)
completed_cmds = 0; completed_cmds = 0;
do { do {
if (ioc->reply_post_free[post_index].Words == ~0ULL) rd.word = ioc->reply_post_free[post_index].Words;
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out; goto out;
reply = 0; reply = 0;
cb_idx = 0xFF; cb_idx = 0xFF;
...@@ -721,7 +730,7 @@ _base_interrupt(int irq, void *bus_id) ...@@ -721,7 +730,7 @@ _base_interrupt(int irq, void *bus_id)
for (i = 0 ; i < completed_cmds; i++) { for (i = 0 ; i < completed_cmds; i++) {
post_index = post_index_next; post_index = post_index_next;
/* poison the reply post descriptor */ /* poison the reply post descriptor */
ioc->reply_post_free[post_index_next].Words = ~0ULL; ioc->reply_post_free[post_index_next].Words = ULLONG_MAX;
post_index_next = (post_index == post_index_next = (post_index ==
(ioc->reply_post_queue_depth - 1)) (ioc->reply_post_queue_depth - 1))
? 0 : post_index + 1; ? 0 : post_index + 1;
...@@ -3068,7 +3077,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, ...@@ -3068,7 +3077,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
/* initialize Reply Post Free Queue */ /* initialize Reply Post Free Queue */
for (i = 0; i < ioc->reply_post_queue_depth; i++) for (i = 0; i < ioc->reply_post_queue_depth; i++)
ioc->reply_post_free[i].Words = ~0ULL; ioc->reply_post_free[i].Words = ULLONG_MAX;
r = _base_send_ioc_init(ioc, VF_ID, sleep_flag); r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
if (r) if (r)
......
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