mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-27 21:14:44 +08:00
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 <chenxiang66@hisilicon.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b4241f0fa3
commit
13cd5ed612
@ -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_SRC3, 0xffffffff);
|
||||||
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe);
|
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_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_PHYUPDOWN_INT_MSK, 0x0);
|
||||||
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
|
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
|
||||||
hisi_sas_write32(hisi_hba, HGC_COM_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,
|
static void free_device_v3_hw(struct hisi_hba *hisi_hba,
|
||||||
struct hisi_sas_device *sas_dev)
|
struct hisi_sas_device *sas_dev)
|
||||||
{
|
{
|
||||||
|
DECLARE_COMPLETION_ONSTACK(completion);
|
||||||
u64 dev_id = sas_dev->device_id;
|
u64 dev_id = sas_dev->device_id;
|
||||||
struct device *dev = hisi_hba->dev;
|
|
||||||
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
|
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
|
||||||
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
|
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
|
||||||
|
|
||||||
|
sas_dev->completion = &completion;
|
||||||
|
|
||||||
/* clear the itct interrupt state */
|
/* clear the itct interrupt state */
|
||||||
if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
|
if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
|
||||||
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
|
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
|
||||||
ENT_INT_SRC3_ITC_INT_MSK);
|
ENT_INT_SRC3_ITC_INT_MSK);
|
||||||
|
|
||||||
/* clear the itct table*/
|
/* 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);
|
hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
|
||||||
|
|
||||||
udelay(10);
|
wait_for_completion(sas_dev->completion);
|
||||||
reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
|
memset(itct, 0, sizeof(struct hisi_sas_itct));
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
|
static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
|
||||||
|
Loading…
Reference in New Issue
Block a user