From: Wang Chao wangchao342@hisilicon.com
driver inclusion category: bugfix bugzilla: NA CVE: NA
We find that when set HISI_SAS_MAX_ITCT_ENTRIES as 1, we don't evenallocate one device. This does not comply with the code logic designed by us.
The log is as follows:
[ 3.565847] hsi_sas_v3_hw 0000:74:02.0: Adding to iommu group 0 [ 3.582037] scsi host0: hisi_sas_v3_hw [ 4.794270] hisi_sas_v3_hw 0000:74:02.0: Enable MSI auo-affinity [ 4.872986] hisi_sas_v3_hw 0000:74:02.0: phyup: phy5 link_rate=11 [ 4.879057] hisi_sas_v3_hw 0000:74:02.0: phyup: phy0 link_rate=11 [ 4.879117] sas: phy-0:5 added to port-0:0, phy_mask:0x20 (500e004aaaaaaa1f) [ 4.885131] hisi_sas_v3_hw 0000:74:02.0: phyup: phy1 link_rate=11 [ 4.885145] sas: DOING DISCOVERY on port 0, pid:910 [ 4.891199] hisi_sas_v3_hw 0000:74:02.0: phyup: phy2 link_rate=11 [ 4.891203] hisi_sas_v3_hw 0000:74:02.0: phyup: phy3 link_rate=11 [ 4.891209] hisi_sas_v3_hw 0000:74:02.0: phyup: phy4 link_rate=11 [ 4.897510] hisi_sas_v3_hw 0000:74:02.0: fail alloc dev: max support 1 devices [ 4.903335] hisi_sas_v3_hw 0000:74:02.0: phyup: phy6 link_rate=11 [ 4.903340] hisi_sas_v3_hw 0000:74:02.0: phyup: phy7 link_rate=11 [ 4.909402] sas: driver on host 0000:74:02.0 cannot handle device 500e004aaaaaaa1f, error:-22 [ 4.937404] sas: DONE DISCOVERY on port 0, pid:910, result:-22 [ 4.937409] sas: broadcast received: 0 [ 4.937410] sas: phy0 matched wide port0 [ 4.937414] sas: phy-0:0 added to port-0:0, phy_mask:0x21 (500e004aaaaaaa1f) [ 4.937431] sas: DOING DISCOVERY on port 0, pid:910 [ 4.937581] hisi_sas_v3_hw 0000:74:02.0: fail alloc dev: max support 1 devices [ 4.944774] sas: driver on host 0000:74:02.0 cannot handle device 500e004aaaaaaa1f, error:-22 [ 4.953395] sas: DONE DISCOVERY on port 0, pid:910, result:-22
We find that this extreme case is not considered when implementing hisi_sas_alloc_dev(). Actually, the device ID is allocated from 1 instead of 0. As a result, if the value of HISI_SAS_MAX_ITCT_ENTRIES is 1, the driver considers that the number of devices has reached the upper limit and return sas_dev with NULL.
Signed-off-by: Wang Chao wangchao342@hisilicon.com Reviewed-by: Zhu Xiongxiong zhuxiongxiong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/hisi_sas/hisi_sas_main.c | 19 ++++++++++--------- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 + 2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 3df5d590aab8..124aa26fa4b8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -685,30 +685,31 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device) struct hisi_hba *hisi_hba = dev_to_hisi_hba(device); struct hisi_sas_device *sas_dev = NULL; unsigned long flags; - int last = hisi_hba->last_dev_id; int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES; + int dev_id; int i;
spin_lock_irqsave(&hisi_hba->lock, flags); - for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) { - if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) { - int queue = i % hisi_hba->queue_count; + for (i = first; i < first + HISI_SAS_MAX_DEVICES; i++) { + dev_id = i % HISI_SAS_MAX_DEVICES; + if (hisi_hba->devices[dev_id].dev_type == SAS_PHY_UNUSED) { + int queue = dev_id % hisi_hba->queue_count; struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
- hisi_hba->devices[i].device_id = i; - sas_dev = &hisi_hba->devices[i]; + hisi_hba->devices[dev_id].device_id = dev_id; + sas_dev = &hisi_hba->devices[dev_id]; sas_dev->dev_status = HISI_SAS_DEV_INIT; sas_dev->dev_type = device->dev_type; sas_dev->hisi_hba = hisi_hba; sas_dev->sas_device = device; sas_dev->dq = dq; spin_lock_init(&sas_dev->lock); - INIT_LIST_HEAD(&hisi_hba->devices[i].list); + INIT_LIST_HEAD(&hisi_hba->devices[dev_id].list); break; } - i++; } - hisi_hba->last_dev_id = i; + if (sas_dev) + hisi_hba->last_dev_id = i; spin_unlock_irqrestore(&hisi_hba->lock, flags);
return sas_dev; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 791194cd120e..3cf0255dccf1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3399,6 +3399,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_out_ha; }
+ hisi_hba->last_dev_id = -1; phy_nr = port_nr = hisi_hba->n_phy;
arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);