scsi: hisi_sas: Add firmware information check

For security purposes, after information is obtained through the FW,
check information to ensure data correctness.

 - In v1 and v2 hw, the maximum number of PHYs is 9, while in v3 it is 8.

 - In v2 and v3 hw, the maximum number of hardware queues is 16, while
   in v1 it is 32.

Also add some debug logs for failure.

Signed-off-by: Yihang Li <liyihang9@huawei.com>
Link: https://lore.kernel.org/r/20241008021822.2617339-4-liyihang9@huawei.com
Reviewed-by: Xiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Yihang Li
2024-10-08 10:18:12 +08:00
committed by Martin K. Petersen
parent 436a97c5d2
commit 2c335fa7e6
5 changed files with 62 additions and 0 deletions

View File

@@ -307,6 +307,7 @@ enum {
struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
int (*fw_info_check)(struct hisi_hba *hisi_hba);
int (*interrupt_preinit)(struct hisi_hba *hisi_hba);
void (*setup_itct)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *device);

View File

@@ -2450,6 +2450,11 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
if (hisi_sas_get_fw_info(hisi_hba) < 0)
goto err_out;
if (hisi_hba->hw->fw_info_check) {
if (hisi_hba->hw->fw_info_check(hisi_hba))
goto err_out;
}
error = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
if (error) {
dev_err(dev, "No usable DMA addressing method\n");

View File

@@ -1734,6 +1734,23 @@ static struct attribute *host_v1_hw_attrs[] = {
ATTRIBUTE_GROUPS(host_v1_hw);
static int check_fw_info_v1_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 32) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static const struct scsi_host_template sht_v1_hw = {
LIBSAS_SHT_BASE_NO_SLAVE_INIT
.device_configure = hisi_sas_device_configure,
@@ -1747,6 +1764,7 @@ static const struct scsi_host_template sht_v1_hw = {
static const struct hisi_sas_hw hisi_sas_v1_hw = {
.hw_init = hisi_sas_v1_init,
.fw_info_check = check_fw_info_v1_hw,
.setup_itct = setup_itct_v1_hw,
.sl_notify_ssp = sl_notify_ssp_v1_hw,
.clear_itct = clear_itct_v1_hw,

View File

@@ -3566,6 +3566,23 @@ static void map_queues_v2_hw(struct Scsi_Host *shost)
}
}
static int check_fw_info_v2_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 9) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static const struct scsi_host_template sht_v2_hw = {
LIBSAS_SHT_BASE_NO_SLAVE_INIT
.device_configure = hisi_sas_device_configure,
@@ -3582,6 +3599,7 @@ static const struct scsi_host_template sht_v2_hw = {
static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.fw_info_check = check_fw_info_v2_hw,
.interrupt_preinit = hisi_sas_v2_interrupt_preinit,
.setup_itct = setup_itct_v2_hw,
.slot_index_alloc = slot_index_alloc_quirk_v2_hw,

View File

@@ -3371,6 +3371,23 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.debugfs_snapshot_regs = debugfs_snapshot_regs_v3_hw,
};
static int check_fw_info_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
if (hisi_hba->n_phy < 0 || hisi_hba->n_phy > 8) {
dev_err(dev, "invalid phy number from FW\n");
return -EINVAL;
}
if (hisi_hba->queue_count < 0 || hisi_hba->queue_count > 16) {
dev_err(dev, "invalid queue count from FW\n");
return -EINVAL;
}
return 0;
}
static struct Scsi_Host *
hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
{
@@ -3401,6 +3418,9 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
if (hisi_sas_get_fw_info(hisi_hba) < 0)
goto err_out;
if (check_fw_info_v3_hw(hisi_hba) < 0)
goto err_out;
if (experimental_iopoll_q_cnt < 0 ||
experimental_iopoll_q_cnt >= hisi_hba->queue_count)
dev_err(dev, "iopoll queue count %d cannot exceed or equal 16, using default 0\n",