scsi: qla2xxx: Add support for mailbox passthru
authorBikash Hazarika <bhazarika@marvell.com>
Wed, 8 Sep 2021 16:46:13 +0000 (09:46 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 15 Sep 2021 03:33:19 +0000 (23:33 -0400)
This interface will allow user space applications to send a mailbox command
to the firmware.

Link: https://lore.kernel.org/r/20210908164622.19240-2-njavali@marvell.com
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_bsg.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_mbx.c

index 4b5d28d89d6906462364f6c8207937dce43e66c2..0c33fb0de21a40a23a7c5bb1bf5c8e6a187e316c 100644 (file)
@@ -2877,6 +2877,9 @@ qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_j
        case QL_VND_MANAGE_HOST_PORT:
                return qla2x00_manage_host_port(bsg_job);
 
+       case QL_VND_MBX_PASSTHRU:
+               return qla2x00_mailbox_passthru(bsg_job);
+
        default:
                return -ENOSYS;
        }
@@ -3013,3 +3016,48 @@ done:
        sp->free(sp);
        return 0;
 }
+
+int qla2x00_mailbox_passthru(struct bsg_job *bsg_job)
+{
+       struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+       scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+       int ret = -EINVAL;
+       int ptsize = sizeof(struct qla_mbx_passthru);
+       struct qla_mbx_passthru *req_data = NULL;
+       uint32_t req_data_len;
+
+       req_data_len = bsg_job->request_payload.payload_len;
+       if (req_data_len != ptsize) {
+               ql_log(ql_log_warn, vha, 0xf0a3, "req_data_len invalid.\n");
+               return -EIO;
+       }
+       req_data = kzalloc(ptsize, GFP_KERNEL);
+       if (!req_data) {
+               ql_log(ql_log_warn, vha, 0xf0a4,
+                      "req_data memory allocation failure.\n");
+               return -ENOMEM;
+       }
+
+       /* Copy the request buffer in req_data */
+       sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+                         bsg_job->request_payload.sg_cnt, req_data, ptsize);
+       ret = qla_mailbox_passthru(vha, req_data->mbx_in, req_data->mbx_out);
+
+       /* Copy the req_data in  request buffer */
+       sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                           bsg_job->reply_payload.sg_cnt, req_data, ptsize);
+
+       bsg_reply->reply_payload_rcv_len = ptsize;
+       if (ret == QLA_SUCCESS)
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+       else
+               bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_ERR;
+
+       bsg_job->reply_len = sizeof(*bsg_job->reply);
+       bsg_reply->result = DID_OK << 16;
+       bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+       kfree(req_data);
+
+       return ret;
+}
index dd793cf8bc1e8704343effde5de68f72be150d8c..0f8a4c7e52a233b8a1c21da9fdefa0f406cf051f 100644 (file)
@@ -36,6 +36,7 @@
 #define QL_VND_GET_HOST_STATS          0x24
 #define QL_VND_GET_TGT_STATS           0x25
 #define QL_VND_MANAGE_HOST_PORT                0x26
+#define QL_VND_MBX_PASSTHRU            0x2B
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK                  0
@@ -187,6 +188,12 @@ struct qla_port_param {
        uint16_t speed;
 } __attribute__ ((packed));
 
+struct qla_mbx_passthru {
+       uint16_t reserved1[2];
+       uint16_t mbx_in[32];
+       uint16_t mbx_out[32];
+       uint32_t reserved2[16];
+} __packed;
 
 /* FRU VPD */
 
index 1c3f055d41b8e82b2aee1bcc16907bd4887f1b55..8aadcdeca6cb965f2f63042e382582204ee9ccf2 100644 (file)
@@ -662,9 +662,13 @@ extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
 
 extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *);
 extern int qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *);
+extern int qla2x00_mailbox_passthru(struct bsg_job *bsg_job);
 int __qla_copy_purex_to_buffer(struct scsi_qla_host *vha, void **pkt,
        struct rsp_que **rsp, u8 *buf, u32 buf_len);
 
+int qla_mailbox_passthru(scsi_qla_host_t *vha, uint16_t *mbx_in,
+                        uint16_t *mbx_out);
+
 /*
  * Global Function Prototypes in qla_dbg.c source file.
  */
index 7811c4952035b3d1151c504ebc3833e02f296e86..9eb41dd39043cc7ce79799b3a67619b1470fac7c 100644 (file)
@@ -7011,3 +7011,36 @@ void qla_no_op_mb(struct scsi_qla_host *vha)
                        "Failed %s %x\n", __func__, rval);
        }
 }
+
+int qla_mailbox_passthru(scsi_qla_host_t *vha,
+                        uint16_t *mbx_in, uint16_t *mbx_out)
+{
+       mbx_cmd_t mc;
+       mbx_cmd_t *mcp = &mc;
+       int rval = -EINVAL;
+
+       memset(&mc, 0, sizeof(mc));
+       /* Receiving all 32 register's contents */
+       memcpy(&mcp->mb, (char *)mbx_in, (32 * sizeof(uint16_t)));
+
+       mcp->out_mb = 0xFFFFFFFF;
+       mcp->in_mb = 0xFFFFFFFF;
+
+       mcp->tov = MBX_TOV_SECONDS;
+       mcp->flags = 0;
+       mcp->bufp = NULL;
+
+       rval = qla2x00_mailbox_command(vha, mcp);
+
+       if (rval != QLA_SUCCESS) {
+               ql_dbg(ql_dbg_mbx, vha, 0xf0a2,
+                       "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+       } else {
+               ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xf0a3, "Done %s.\n",
+                      __func__);
+               /* passing all 32 register's contents */
+               memcpy(mbx_out, &mcp->mb, 32 * sizeof(uint16_t));
+       }
+
+       return rval;
+}