scsi: megaraid_sas: Incorrect processing of IOCTL frames for SMP/STP commands
authorShivasharan S <shivasharan.srikanteshwara@broadcom.com>
Thu, 19 Oct 2017 09:49:02 +0000 (02:49 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 25 Oct 2017 08:55:30 +0000 (04:55 -0400)
cmd->frame->dcmd.opcode will be valid only for MFI_CMD_DCMD
IOCTL frames. Currently driver check for cmd->frame->dcmd.opcode without
checking cmd type. Ensure we check dcmd opcode only for MFI_CMD_DCMD
commands. Separate handling of MFI_CMD_SMP/STP commands from
MFI_CMD_DCMD in completion path.

Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: Shivasharan S <shivasharan.srikanteshwara@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c

index 83427b5..85ef841 100644 (file)
 /*
  * MFI command opcodes
  */
-#define MFI_CMD_INIT                           0x00
-#define MFI_CMD_LD_READ                                0x01
-#define MFI_CMD_LD_WRITE                       0x02
-#define MFI_CMD_LD_SCSI_IO                     0x03
-#define MFI_CMD_PD_SCSI_IO                     0x04
-#define MFI_CMD_DCMD                           0x05
-#define MFI_CMD_ABORT                          0x06
-#define MFI_CMD_SMP                            0x07
-#define MFI_CMD_STP                            0x08
-#define MFI_CMD_INVALID                                0xff
+enum MFI_CMD_OP {
+       MFI_CMD_INIT            = 0x0,
+       MFI_CMD_LD_READ         = 0x1,
+       MFI_CMD_LD_WRITE        = 0x2,
+       MFI_CMD_LD_SCSI_IO      = 0x3,
+       MFI_CMD_PD_SCSI_IO      = 0x4,
+       MFI_CMD_DCMD            = 0x5,
+       MFI_CMD_ABORT           = 0x6,
+       MFI_CMD_SMP             = 0x7,
+       MFI_CMD_STP             = 0x8,
+       MFI_CMD_OP_COUNT,
+       MFI_CMD_INVALID         = 0xff
+};
 
 #define MR_DCMD_CTRL_GET_INFO                  0x01010000
 #define MR_DCMD_LD_GET_LIST                    0x03010000
index 79e3e23..7e40ff6 100644 (file)
@@ -3298,6 +3298,9 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 
        case MFI_CMD_SMP:
        case MFI_CMD_STP:
+               megasas_complete_int_cmd(instance, cmd);
+               break;
+
        case MFI_CMD_DCMD:
                opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
                /* Check for LD map update */
@@ -3384,6 +3387,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
        default:
                dev_info(&instance->pdev->dev, "Unknown command completed! [0x%X]\n",
                       hdr->cmd);
+               megasas_complete_int_cmd(instance, cmd);
                break;
        }
 }
@@ -7017,7 +7021,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        void *sense = NULL;
        dma_addr_t sense_handle;
        unsigned long *sense_ptr;
-       u32 opcode;
+       u32 opcode = 0;
 
        memset(kbuff_arr, 0, sizeof(kbuff_arr));
 
@@ -7027,6 +7031,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
                return -EINVAL;
        }
 
+       if (ioc->frame.hdr.cmd >= MFI_CMD_OP_COUNT) {
+               dev_err(&instance->pdev->dev,
+                       "Received invalid ioctl command 0x%x\n",
+                       ioc->frame.hdr.cmd);
+               return -ENOTSUPP;
+       }
+
        cmd = megasas_get_cmd(instance);
        if (!cmd) {
                dev_printk(KERN_DEBUG, &instance->pdev->dev, "Failed to get a cmd packet\n");
@@ -7045,7 +7056,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        cmd->frame->hdr.flags &= cpu_to_le16(~(MFI_FRAME_IEEE |
                                               MFI_FRAME_SGL64 |
                                               MFI_FRAME_SENSE64));
-       opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
+
+       if (cmd->frame->hdr.cmd == MFI_CMD_DCMD)
+               opcode = le32_to_cpu(cmd->frame->dcmd.opcode);
 
        if (opcode == MR_DCMD_CTRL_SHUTDOWN) {
                if (megasas_get_ctrl_info(instance) != DCMD_SUCCESS) {
@@ -7127,8 +7140,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
        if (megasas_issue_blocked_cmd(instance, cmd, 0) == DCMD_NOT_FIRED) {
                cmd->sync_cmd = 0;
                dev_err(&instance->pdev->dev,
-                       "return -EBUSY from %s %d opcode 0x%x cmd->cmd_status_drv 0x%x\n",
-                       __func__, __LINE__, opcode,     cmd->cmd_status_drv);
+                       "return -EBUSY from %s %d cmd 0x%x opcode 0x%x cmd->cmd_status_drv 0x%x\n",
+                       __func__, __LINE__, cmd->frame->hdr.cmd, opcode,
+                       cmd->cmd_status_drv);
                return -EBUSY;
        }