diff options
author | peter chang <dpf@google.com> | 2019-11-14 15:39:05 +0530 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-11-19 21:37:33 -0500 |
commit | 91a43fa61f102e045d9bac07a4b7739a4bbe623a (patch) | |
tree | 6f582c88a6b802a043ffb285f05c6627e2a987bd /drivers/scsi/pm8001/pm80xx_hwi.c | |
parent | scsi: pm80xx: Fix dereferencing dangling pointer (diff) | |
download | linux-dev-91a43fa61f102e045d9bac07a4b7739a4bbe623a.tar.xz linux-dev-91a43fa61f102e045d9bac07a4b7739a4bbe623a.zip |
scsi: pm80xx: Fix command issue sizing
The commands to the controller are sent in fixed sized chunks which are set
per-chip-generation and stashed in iomb_size. The driver fills in structs
matching the register layout and memcpy this to memory shared with the
controller. However, there are two problem cases:
1) Things like phy_start_req are too large because they share the
sas_identify_frame definition with libsas, and it includes the crc
word. This means that it's overwriting the start of the next
command block, that's ok except if it happens at the end of the
shared memory area.
2) Things like set_nvm_data_req which are shared between the HAL
layers. This means that it's sending 'random' data for things that
are in the reserved area. So far we haven't found a case where the
controller FW cares, but sending possible gibberish (for most of
the structures this is in the reserved area so previously zeroed)
is not recommended.
Link: https://lore.kernel.org/r/20191114100910.6153-9-deepak.ukey@microchip.com
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Deepak Ukey <deepak.ukey@microchip.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm80xx_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9d04e5cfffb4..09008db2efdc 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -955,7 +955,8 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n", payload.cfg_pg[0], payload.cfg_pg[1])); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); return rc; @@ -1037,7 +1038,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) memcpy(&payload.cfg_pg, &SASConfigPage, sizeof(SASProtocolTimerConfig_t)); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -1164,7 +1166,8 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) "Saving Encryption info to flash. payload 0x%x\n", payload.new_curidx_ksop)); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -1517,7 +1520,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); task_abort.tag = cpu_to_le32(ccb_tag); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, + sizeof(task_abort), 0); + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("Executing abort task end\n")); if (ret) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1593,7 +1599,9 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9)); memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); - res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); + res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, + sizeof(sata_cmd), 0); + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Executing read log end\n")); if (res) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -2962,7 +2970,8 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, ((phyId & 0xFF) << 24) | (port_id & 0xFF)); payload.param0 = cpu_to_le32(param0); payload.param1 = cpu_to_le32(param1); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); } static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, @@ -4082,8 +4091,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, + sizeof(smp_cmd), 0); if (rc) goto err_out_2; return 0; @@ -4291,7 +4300,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, } q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - &ssp_cmd, q_index); + &ssp_cmd, sizeof(ssp_cmd), q_index); return ret; } @@ -4532,7 +4541,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - &sata_cmd, q_index); + &sata_cmd, sizeof(sata_cmd), q_index); return ret; } @@ -4587,7 +4596,8 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) memcpy(payload.sas_identify.sas_addr, &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE); payload.sas_identify.phy_id = phy_id; - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4609,7 +4619,8 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, memset(&payload, 0, sizeof(payload)); payload.tag = cpu_to_le32(tag); payload.phy_id = cpu_to_le32(phy_id); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4675,7 +4686,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, SAS_ADDR_SIZE); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -4705,7 +4717,8 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(tag); payload.phyop_phyid = cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF)); - return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); } static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha) @@ -4763,7 +4776,8 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); j++; } - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); } @@ -4805,7 +4819,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, for (i = 0; i < length; i++) payload.reserved[i] = cpu_to_le32(*(buf + i)); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); |