diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 3d3cdfe07089..0dd38ccc9470 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1120,7 +1120,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct Comma static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) { int i = 0; - uint32_t flag_ccb; + uint32_t flag_ccb, ccb_cdb_phy; struct ARCMSR_CDB *pARCMSR_CDB; bool error; struct CommandControlBlock *pCCB; @@ -1164,10 +1164,6 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_C: { struct MessageUnit_C __iomem *reg = acb->pmuC; - struct ARCMSR_CDB *pARCMSR_CDB; - uint32_t flag_ccb, ccb_cdb_phy; - bool error; - struct CommandControlBlock *pCCB; while ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { /*need to do*/ flag_ccb = readl(®->outbound_queueport_low); @@ -1181,35 +1177,25 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) break; case ACB_ADAPTER_TYPE_D: { struct MessageUnit_D *pmu = acb->pmuD; - uint32_t ccb_cdb_phy, outbound_write_pointer; - uint32_t doneq_index, index_stripped, addressLow, residual; - bool error; - struct CommandControlBlock *pCCB; + uint32_t outbound_write_pointer; + uint32_t doneq_index, index_stripped, addressLow, residual, toggle; + unsigned long flags; - outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; - doneq_index = pmu->doneq_index; residual = atomic_read(&acb->ccboutstandingcount); for (i = 0; i < residual; i++) { - while ((doneq_index & 0xFFF) != + spin_lock_irqsave(&acb->doneq_lock, flags); + outbound_write_pointer = + pmu->done_qbuffer[0].addressLow + 1; + doneq_index = pmu->doneq_index; + if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) { - if (doneq_index & 0x4000) { - index_stripped = doneq_index & 0xFFF; - index_stripped += 1; - index_stripped %= - ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped ? - (index_stripped | 0x4000) : - (index_stripped + 1); - } else { - index_stripped = doneq_index; - index_stripped += 1; - index_stripped %= - ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped ? - index_stripped : - ((index_stripped | 0x4000) + 1); - } + toggle = doneq_index & 0x4000; + index_stripped = (doneq_index & 0xFFF) + 1; + index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; + pmu->doneq_index = index_stripped ? (index_stripped | toggle) : + ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; + spin_unlock_irqrestore(&acb->doneq_lock, flags); addressLow = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ccb_cdb_phy = (addressLow & 0xFFFFFFF0); @@ -1223,11 +1209,10 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) arcmsr_drain_donequeue(acb, pCCB, error); writel(doneq_index, pmu->outboundlist_read_pointer); + } else { + spin_unlock_irqrestore(&acb->doneq_lock, flags); + mdelay(10); } - mdelay(10); - outbound_write_pointer = - pmu->done_qbuffer[0].addressLow + 1; - doneq_index = pmu->doneq_index; } pmu->postq_index = 0; pmu->doneq_index = 0x40FF; @@ -1460,7 +1445,7 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr case ACB_ADAPTER_TYPE_D: { struct MessageUnit_D *pmu = acb->pmuD; u16 index_stripped; - u16 postq_index; + u16 postq_index, toggle; unsigned long flags; struct InBound_SRB *pinbound_srb; @@ -1471,19 +1456,11 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr pinbound_srb->addressLow = dma_addr_lo32(cdb_phyaddr); pinbound_srb->length = ccb->arc_cdb_size >> 2; arcmsr_cdb->msgContext = dma_addr_lo32(cdb_phyaddr); - if (postq_index & 0x4000) { - index_stripped = postq_index & 0xFF; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; - pmu->postq_index = index_stripped ? - (index_stripped | 0x4000) : index_stripped; - } else { - index_stripped = postq_index; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_POSTQUEUE; - pmu->postq_index = index_stripped ? index_stripped : - (index_stripped | 0x4000); - } + toggle = postq_index & 0x4000; + index_stripped = postq_index + 1; + index_stripped &= (ARCMSR_MAX_ARC1214_POSTQUEUE - 1); + pmu->postq_index = index_stripped ? (index_stripped | toggle) : + (toggle ^ 0x4000); writel(postq_index, pmu->inboundlist_write_pointer); spin_unlock_irqrestore(&acb->postq_lock, flags); break; @@ -1999,7 +1976,7 @@ static void arcmsr_hbaC_postqueue_isr(struct AdapterControlBlock *acb) static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) { - u32 outbound_write_pointer, doneq_index, index_stripped; + u32 outbound_write_pointer, doneq_index, index_stripped, toggle; uint32_t addressLow, ccb_cdb_phy; int error; struct MessageUnit_D *pmu; @@ -2013,21 +1990,11 @@ static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb) doneq_index = pmu->doneq_index; if ((doneq_index & 0xFFF) != (outbound_write_pointer & 0xFFF)) { do { - if (doneq_index & 0x4000) { - index_stripped = doneq_index & 0xFFF; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped - ? (index_stripped | 0x4000) : - (index_stripped + 1); - } else { - index_stripped = doneq_index; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped - ? index_stripped : - ((index_stripped | 0x4000) + 1); - } + toggle = doneq_index & 0x4000; + index_stripped = (doneq_index & 0xFFF) + 1; + index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; + pmu->doneq_index = index_stripped ? (index_stripped | toggle) : + ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; addressLow = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; @@ -2890,7 +2857,7 @@ static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb) char __iomem *iop_firm_version; char __iomem *iop_device_map; u32 count; - struct MessageUnit_D *reg ; + struct MessageUnit_D *reg; void *dma_coherent2; dma_addr_t dma_coherent_handle2; struct pci_dev *pdev = acb->pdev; @@ -3223,7 +3190,7 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, { bool error; uint32_t poll_ccb_done = 0, poll_count = 0, flag_ccb, ccb_cdb_phy; - int rtn, doneq_index, index_stripped, outbound_write_pointer; + int rtn, doneq_index, index_stripped, outbound_write_pointer, toggle; unsigned long flags; struct ARCMSR_CDB *arcmsr_cdb; struct CommandControlBlock *pCCB; @@ -3232,9 +3199,11 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, polling_hbaD_ccb_retry: poll_count++; while (1) { + spin_lock_irqsave(&acb->doneq_lock, flags); outbound_write_pointer = pmu->done_qbuffer[0].addressLow + 1; doneq_index = pmu->doneq_index; if ((outbound_write_pointer & 0xFFF) == (doneq_index & 0xFFF)) { + spin_unlock_irqrestore(&acb->doneq_lock, flags); if (poll_ccb_done) { rtn = SUCCESS; break; @@ -3247,23 +3216,13 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb, goto polling_hbaD_ccb_retry; } } - spin_lock_irqsave(&acb->doneq_lock, flags); - if (doneq_index & 0x4000) { - index_stripped = doneq_index & 0xFFF; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped ? - (index_stripped | 0x4000) : - (index_stripped + 1); - } else { - index_stripped = doneq_index; - index_stripped += 1; - index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; - pmu->doneq_index = index_stripped ? index_stripped : - ((index_stripped | 0x4000) + 1); - } - spin_unlock_irqrestore(&acb->doneq_lock, flags); + toggle = doneq_index & 0x4000; + index_stripped = (doneq_index & 0xFFF) + 1; + index_stripped %= ARCMSR_MAX_ARC1214_DONEQUEUE; + pmu->doneq_index = index_stripped ? (index_stripped | toggle) : + ((toggle ^ 0x4000) + 1); doneq_index = pmu->doneq_index; + spin_unlock_irqrestore(&acb->doneq_lock, flags); flag_ccb = pmu->done_qbuffer[doneq_index & 0xFFF].addressLow; ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0); arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset +