scsi: qla2xxx: edif: Fix EDIF bsg
authorQuinn Tran <qutran@marvell.com>
Tue, 26 Oct 2021 11:54:11 +0000 (04:54 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:17:04 +0000 (19:17 +0100)
[ Upstream commit 9fd26c633e8ab5a291c0241533efff161bbe5570 ]

Various EDIF bsgs did not properly fill out the reply_payload_rcv_len
field. This causes app to parse empty data in the return payload.

Link: https://lore.kernel.org/r/20211026115412.27691-13-njavali@marvell.com
Fixes: 7ebb336e45ef ("scsi: qla2xxx: edif: Add start + stop bsgs")
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/scsi/qla2xxx/qla_edif.c

index 98235df..9240e78 100644 (file)
@@ -544,14 +544,14 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
        appreply.edif_enode_active = vha->pur_cinfo.enode_flags;
        appreply.edif_edb_active = vha->e_dbell.db_flags;
 
-       bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
-           sizeof(struct app_start_reply);
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply);
 
        SET_DID_STATUS(bsg_reply->result, DID_OK);
 
-       sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
-           bsg_job->reply_payload.sg_cnt, &appreply,
-           sizeof(struct app_start_reply));
+       bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                                                              bsg_job->reply_payload.sg_cnt,
+                                                              &appreply,
+                                                              sizeof(struct app_start_reply));
 
        ql_dbg(ql_dbg_edif, vha, 0x911d,
            "%s app start completed with 0x%x\n",
@@ -748,9 +748,10 @@ qla_edif_app_authok(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 
 errstate_exit:
        bsg_job->reply_len = sizeof(struct fc_bsg_reply);
-       sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
-           bsg_job->reply_payload.sg_cnt, &appplogireply,
-           sizeof(struct app_plogi_reply));
+       bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                                                              bsg_job->reply_payload.sg_cnt,
+                                                              &appplogireply,
+                                                              sizeof(struct app_plogi_reply));
 
        return rval;
 }
@@ -833,7 +834,7 @@ static int
 qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 {
        int32_t                 rval = 0;
-       int32_t                 num_cnt;
+       int32_t                 pcnt = 0;
        struct fc_bsg_reply     *bsg_reply = bsg_job->reply;
        struct app_pinfo_req    app_req;
        struct app_pinfo_reply  *app_reply;
@@ -845,16 +846,14 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
            bsg_job->request_payload.sg_cnt, &app_req,
            sizeof(struct app_pinfo_req));
 
-       num_cnt = app_req.num_ports;    /* num of ports alloc'd by app */
-
        app_reply = kzalloc((sizeof(struct app_pinfo_reply) +
-           sizeof(struct app_pinfo) * num_cnt), GFP_KERNEL);
+           sizeof(struct app_pinfo) * app_req.num_ports), GFP_KERNEL);
+
        if (!app_reply) {
                SET_DID_STATUS(bsg_reply->result, DID_ERROR);
                rval = -1;
        } else {
                struct fc_port  *fcport = NULL, *tf;
-               uint32_t        pcnt = 0;
 
                list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
                        if (!(fcport->flags & FCF_FCSP_DEVICE))
@@ -923,9 +922,11 @@ qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
                SET_DID_STATUS(bsg_reply->result, DID_OK);
        }
 
-       sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
-           bsg_job->reply_payload.sg_cnt, app_reply,
-           sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * num_cnt);
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+       bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+                                                              bsg_job->reply_payload.sg_cnt,
+                                                              app_reply,
+                                                              sizeof(struct app_pinfo_reply) + sizeof(struct app_pinfo) * pcnt);
 
        kfree(app_reply);
 
@@ -942,10 +943,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
 {
        int32_t                 rval = 0;
        struct fc_bsg_reply     *bsg_reply = bsg_job->reply;
-       uint32_t ret_size, size;
+       uint32_t size;
 
        struct app_sinfo_req    app_req;
        struct app_stats_reply  *app_reply;
+       uint32_t pcnt = 0;
 
        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
            bsg_job->request_payload.sg_cnt, &app_req,
@@ -961,18 +963,12 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
        size = sizeof(struct app_stats_reply) +
            (sizeof(struct app_sinfo) * app_req.num_ports);
 
-       if (size > bsg_job->reply_payload.payload_len)
-               ret_size = bsg_job->reply_payload.payload_len;
-       else
-               ret_size = size;
-
        app_reply = kzalloc(size, GFP_KERNEL);
        if (!app_reply) {
                SET_DID_STATUS(bsg_reply->result, DID_ERROR);
                rval = -1;
        } else {
                struct fc_port  *fcport = NULL, *tf;
-               uint32_t        pcnt = 0;
 
                list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
                        if (fcport->edif.enable) {
@@ -996,9 +992,11 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
                SET_DID_STATUS(bsg_reply->result, DID_OK);
        }
 
+       bsg_job->reply_len = sizeof(struct fc_bsg_reply);
        bsg_reply->reply_payload_rcv_len =
            sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
-              bsg_job->reply_payload.sg_cnt, app_reply, ret_size);
+              bsg_job->reply_payload.sg_cnt, app_reply,
+              sizeof(struct app_stats_reply) + (sizeof(struct app_sinfo) * pcnt));
 
        kfree(app_reply);
 
@@ -1072,8 +1070,7 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job)
                    __func__,
                    bsg_request->rqst_data.h_vendor.vendor_cmd[1]);
                rval = EXT_STATUS_INVALID_PARAM;
-               bsg_job->reply_len = sizeof(struct fc_bsg_reply);
-               SET_DID_STATUS(bsg_reply->result, DID_ERROR);
+               done = false;
                break;
        }