From 13cd5ed612dad10f998e341e0ab1e0019aeb4217 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 24 Oct 2017 23:51:46 +0800 Subject: [PATCH] scsi: hisi_sas: fix a bug when free device for v3 hw Use completion to wait on ITCT CLR interrupt finishing before processing other things when freeing a device. This is safer than the pre-existing process of polling the register. Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 1f8995bfdb8e..243fa1d5772e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -393,7 +393,7 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe); hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe); - hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffffffff); + hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff); hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0); hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0); hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0); @@ -582,35 +582,24 @@ static void setup_itct_v3_hw(struct hisi_hba *hisi_hba, static void free_device_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_device *sas_dev) { + DECLARE_COMPLETION_ONSTACK(completion); u64 dev_id = sas_dev->device_id; - struct device *dev = hisi_hba->dev; struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id]; u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3); + sas_dev->completion = &completion; + /* clear the itct interrupt state */ if (ENT_INT_SRC3_ITC_INT_MSK & reg_val) hisi_sas_write32(hisi_hba, ENT_INT_SRC3, ENT_INT_SRC3_ITC_INT_MSK); /* clear the itct table*/ - reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR); - reg_val |= ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK); + reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK); hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val); - udelay(10); - reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3); - if (ENT_INT_SRC3_ITC_INT_MSK & reg_val) { - dev_dbg(dev, "got clear ITCT done interrupt\n"); - - /* invalid the itct state*/ - memset(itct, 0, sizeof(struct hisi_sas_itct)); - hisi_sas_write32(hisi_hba, ENT_INT_SRC3, - ENT_INT_SRC3_ITC_INT_MSK); - - /* clear the itct */ - hisi_sas_write32(hisi_hba, ITCT_CLR, 0); - dev_dbg(dev, "clear ITCT ok\n"); - } + wait_for_completion(sas_dev->completion); + memset(itct, 0, sizeof(struct hisi_sas_itct)); } static void dereg_device_v3_hw(struct hisi_hba *hisi_hba, -- 2.45.2