Message ID | 20210908072846.10011-2-njavali@marvell.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | qla2xxx driver bug fixes | expand |
> On Sep 8, 2021, at 2:28 AM, Nilesh Javali <njavali@marvell.com> wrote: > > From: Bikash Hazarika <bhazarika@marvell.com> > > This interface will allow user space application(s) to send a mailbox > command to the FW. > > Signed-off-by: Bikash Hazarika <bhazarika@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_bsg.c | 48 ++++++++++++++++++++++++++++++++++ > drivers/scsi/qla2xxx/qla_bsg.h | 7 +++++ > drivers/scsi/qla2xxx/qla_gbl.h | 4 +++ > drivers/scsi/qla2xxx/qla_mbx.c | 33 +++++++++++++++++++++++ > 4 files changed, 92 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c > index 4b5d28d89d69..0c33fb0de21a 100644 > --- a/drivers/scsi/qla2xxx/qla_bsg.c > +++ b/drivers/scsi/qla2xxx/qla_bsg.c > @@ -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 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) > 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; > +} > diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h > index dd793cf8bc1e..0f8a4c7e52a2 100644 > --- a/drivers/scsi/qla2xxx/qla_bsg.h > +++ b/drivers/scsi/qla2xxx/qla_bsg.h > @@ -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 */ > > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h > index 1c3f055d41b8..8aadcdeca6cb 100644 > --- a/drivers/scsi/qla2xxx/qla_gbl.h > +++ b/drivers/scsi/qla2xxx/qla_gbl.h > @@ -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. > */ > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c > index 7811c4952035..9eb41dd39043 100644 > --- a/drivers/scsi/qla2xxx/qla_mbx.c > +++ b/drivers/scsi/qla2xxx/qla_mbx.c > @@ -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; > +} > -- > 2.19.0.rc0 > Looks Good. Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> -- Himanshu Madhani Oracle Linux Engineering
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 4b5d28d89d69..0c33fb0de21a 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -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 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job) 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; +} diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index dd793cf8bc1e..0f8a4c7e52a2 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -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 */ diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 1c3f055d41b8..8aadcdeca6cb 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -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. */ diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 7811c4952035..9eb41dd39043 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -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; +}