aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/arcmsr
diff options
context:
space:
mode:
authorChing Huang <ching2048@areca.com.tw>2014-08-19 03:07:35 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 12:39:49 -0400
commit5eb6bfa02a9dfecbb1f644a0b13b16cd3d23770b (patch)
tree3516dad932f67cab22915afa074abe9519025ae4 /drivers/scsi/arcmsr
parenta2c89bbccac476d42a8526c0c59d081d9e56d0a8 (diff)
arcmsr: clear outbound doorbell buffer completely
Clear outbound doorbell buffer completely for adapter type C. This is to prevent getting bad data input from IOP before ioctl command processing starts. Signed-off-by: Ching Huang <ching2048@areca.com.tw> Reviewed-by: Tomas Henzl <thenzl@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/arcmsr')
-rw-r--r--drivers/scsi/arcmsr/arcmsr_hba.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 0707677c11a1..3363c31bb789 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -2870,11 +2870,23 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
2870 break; 2870 break;
2871 case ACB_ADAPTER_TYPE_C: { 2871 case ACB_ADAPTER_TYPE_C: {
2872 struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC; 2872 struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
2873 uint32_t outbound_doorbell; 2873 uint32_t outbound_doorbell, i;
2874 /* empty doorbell Qbuffer if door bell ringed */ 2874 /* empty doorbell Qbuffer if door bell ringed */
2875 outbound_doorbell = readl(&reg->outbound_doorbell); 2875 outbound_doorbell = readl(&reg->outbound_doorbell);
2876 writel(outbound_doorbell, &reg->outbound_doorbell_clear); 2876 writel(outbound_doorbell, &reg->outbound_doorbell_clear);
2877 writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, &reg->inbound_doorbell); 2877 writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, &reg->inbound_doorbell);
2878 for (i = 0; i < 200; i++) {
2879 msleep(20);
2880 outbound_doorbell = readl(&reg->outbound_doorbell);
2881 if (outbound_doorbell &
2882 ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
2883 writel(outbound_doorbell,
2884 &reg->outbound_doorbell_clear);
2885 writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK,
2886 &reg->inbound_doorbell);
2887 } else
2888 break;
2889 }
2878 } 2890 }
2879 } 2891 }
2880} 2892}
@@ -3102,9 +3114,7 @@ sleep:
3102 arcmsr_get_firmware_spec(acb); 3114 arcmsr_get_firmware_spec(acb);
3103 arcmsr_start_adapter_bgrb(acb); 3115 arcmsr_start_adapter_bgrb(acb);
3104 /* clear Qbuffer if door bell ringed */ 3116 /* clear Qbuffer if door bell ringed */
3105 outbound_doorbell = readl(&reg->outbound_doorbell); 3117 arcmsr_clear_doorbell_queue_buffer(acb);
3106 writel(outbound_doorbell, &reg->outbound_doorbell_clear); /*clear interrupt */
3107 writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, &reg->inbound_doorbell);
3108 /* enable outbound Post Queue,outbound doorbell Interrupt */ 3118 /* enable outbound Post Queue,outbound doorbell Interrupt */
3109 arcmsr_enable_outbound_ints(acb, intmask_org); 3119 arcmsr_enable_outbound_ints(acb, intmask_org);
3110 atomic_set(&acb->rq_map_token, 16); 3120 atomic_set(&acb->rq_map_token, 16);