Commit acbaa8c8 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Add bsg support for retrieving adapter cmf data

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.comCo-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 74a7baa2
......@@ -5751,6 +5751,92 @@ lpfc_get_trunk_info(struct bsg_job *job)
}
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;
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment