scsi: lpfc: Add bsg support for retrieving adapter cmf data
authorJames Smart <jsmart2021@gmail.com>
Mon, 16 Aug 2021 16:28:59 +0000 (09:28 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Wed, 25 Aug 2021 02:56:34 +0000 (22:56 -0400)
Add a bsg ioctl to allow user applications to retrieve the adapter
congestion management framework buffer.

Link: https://lore.kernel.org/r/20210816162901.121235-15-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_bsg.h

index 38cfe1b..fdf08cb 100644 (file)
@@ -5751,6 +5751,92 @@ job_error:
 
 }
 
+static int
+lpfc_get_cgnbuf_info(struct bsg_job *job)
+{
+       struct lpfc_vport *vport = shost_priv(fc_bsg_to_shost(job));
+       struct lpfc_hba *phba = vport->phba;
+       struct fc_bsg_request *bsg_request = job->request;
+       struct fc_bsg_reply *bsg_reply = job->reply;
+       struct get_cgnbuf_info_req *cgnbuf_req;
+       struct lpfc_cgn_info *cp;
+       uint8_t *cgn_buff;
+       int size, cinfosz;
+       int  rc = 0;
+
+       if (job->request_len < sizeof(struct fc_bsg_request) +
+           sizeof(struct get_cgnbuf_info_req)) {
+               rc = -ENOMEM;
+               goto job_exit;
+       }
+
+       if (!phba->sli4_hba.pc_sli4_params.cmf) {
+               rc = -ENOENT;
+               goto job_exit;
+       }
+
+       if (!phba->cgn_i || !phba->cgn_i->virt) {
+               rc = -ENOENT;
+               goto job_exit;
+       }
+
+       cp = phba->cgn_i->virt;
+       if (cp->cgn_info_version < LPFC_CGN_INFO_V3) {
+               rc = -EPERM;
+               goto job_exit;
+       }
+
+       cgnbuf_req = (struct get_cgnbuf_info_req *)
+               bsg_request->rqst_data.h_vendor.vendor_cmd;
+
+       /* For reset or size == 0 */
+       bsg_reply->reply_payload_rcv_len = 0;
+
+       if (cgnbuf_req->reset == LPFC_BSG_CGN_RESET_STAT) {
+               lpfc_init_congestion_stat(phba);
+               goto job_exit;
+       }
+
+       /* We don't want to include the CRC at the end */
+       cinfosz = sizeof(struct lpfc_cgn_info) - sizeof(uint32_t);
+
+       size = cgnbuf_req->read_size;
+       if (!size)
+               goto job_exit;
+
+       if (size < cinfosz) {
+               /* Just copy back what we can */
+               cinfosz = size;
+               rc = -E2BIG;
+       }
+
+       /* Allocate memory to read congestion info */
+       cgn_buff = vmalloc(cinfosz);
+       if (!cgn_buff) {
+               rc = -ENOMEM;
+               goto job_exit;
+       }
+
+       memcpy(cgn_buff, cp, cinfosz);
+
+       bsg_reply->reply_payload_rcv_len =
+               sg_copy_from_buffer(job->reply_payload.sg_list,
+                                   job->reply_payload.sg_cnt,
+                                   cgn_buff, cinfosz);
+
+       vfree(cgn_buff);
+
+job_exit:
+       bsg_reply->result = rc;
+       if (!rc)
+               bsg_job_done(job, bsg_reply->result,
+                            bsg_reply->reply_payload_rcv_len);
+       else
+               lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
+                               "2724 GET CGNBUF error: %d\n", rc);
+       return rc;
+}
+
 /**
  * lpfc_bsg_hst_vendor - process a vendor-specific fc_bsg_job
  * @job: fc_bsg_job to handle
@@ -5813,6 +5899,9 @@ lpfc_bsg_hst_vendor(struct bsg_job *job)
        case LPFC_BSG_VENDOR_GET_TRUNK_INFO:
                rc = lpfc_get_trunk_info(job);
                break;
+       case LPFC_BSG_VENDOR_GET_CGNBUF_INFO:
+               rc = lpfc_get_cgnbuf_info(job);
+               break;
        default:
                rc = -EINVAL;
                bsg_reply->reply_payload_rcv_len = 0;
index 2dc7124..17012bc 100644 (file)
@@ -43,6 +43,7 @@
 #define LPFC_BSG_VENDOR_RAS_GET_CONFIG         18
 #define LPFC_BSG_VENDOR_RAS_SET_CONFIG         19
 #define LPFC_BSG_VENDOR_GET_TRUNK_INFO         20
+#define LPFC_BSG_VENDOR_GET_CGNBUF_INFO                21
 
 struct set_ct_event {
        uint32_t command;
@@ -386,6 +387,13 @@ struct get_trunk_info_req {
        uint32_t command;
 };
 
+struct get_cgnbuf_info_req {
+       uint32_t command;
+       uint32_t read_size;
+       uint32_t reset;
+#define LPFC_BSG_CGN_RESET_STAT                1
+};
+
 /* driver only */
 #define SLI_CONFIG_NOT_HANDLED         0
 #define SLI_CONFIG_HANDLED             1