mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-06 11:26:22 -04:00
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:
committed by
Martin K. Petersen
parent
436a97c5d2
commit
2c335fa7e6
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user