Message ID | 20200514101026.10040-4-njavali@marvell.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | qla2xxx SAN Congestion Management (SCM) support | expand |
On 5/14/20 5:10 AM, Nilesh Javali wrote: > From: Shyam Sundar <ssundar@marvell.com> > > Implement 3 functions to pass on SAN congestion management > related counters tracked by the driver, up to the Marvell > application using the BSG interface. > > Signed-off-by: Shyam Sundar <ssundar@marvell.com> > Signed-off-by: Arun Easi <aeasi@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_bsg.c | 114 +++++++++++++++++++++++++++++++++ > drivers/scsi/qla2xxx/qla_bsg.h | 3 + > 2 files changed, 117 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c > index 97b51c477972..bd898bbdd44d 100644 > --- a/drivers/scsi/qla2xxx/qla_bsg.c > +++ b/drivers/scsi/qla2xxx/qla_bsg.c > @@ -2446,6 +2446,111 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) > return 0; > } > > +static int > +qla2x00_get_drv_attr(struct bsg_job *bsg_job) > +{ > + struct qla_drv_attr drv_attr; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + > + memset(&drv_attr, 0, sizeof(struct qla_drv_attr)); > + /* Additional check should be added if SCM is not enabled > + * by default for a given driver version. > + */ > + drv_attr.attributes |= QLA_DRV_ATTR_SCM_SUPPORTED; > + > + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, > + bsg_job->reply_payload.sg_cnt, &drv_attr, > + sizeof(struct qla_drv_attr)); > + > + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr); > + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; > + > + 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); > + > + return 0; > +} > + > +static int > +qla2x00_get_port_scm(struct bsg_job *bsg_job) > +{ > + struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job); > + scsi_qla_host_t *vha = shost_priv(shost); > + struct qla_hw_data *ha = vha->hw; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + > + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) > + return -EPERM; > + > + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, > + bsg_job->reply_payload.sg_cnt, &vha->scm_stats, > + sizeof(struct qla_scm_port)); > + > + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_port); > + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; > + > + 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); > + > + return 0; > +} > + > +static int > +qla2x00_get_target_scm(struct bsg_job *bsg_job) > +{ > + struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job); > + scsi_qla_host_t *vha = shost_priv(shost); > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + struct qla_hw_data *ha = vha->hw; > + fc_port_t *fcport = NULL; > + int rval; > + struct qla_scm_target *scm_stats = NULL; > + > + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) > + return -EPERM; > + > + scm_stats = kzalloc(sizeof(*scm_stats), GFP_KERNEL); > + if (!scm_stats) { > + ql_log(ql_log_warn, vha, 0x7024, > + "Failed to allocate memory for target scm stats.\n"); > + return -ENOMEM; > + } > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + bsg_job->request_payload.sg_cnt, scm_stats, > + sizeof(struct qla_scm_target)); > + > + fcport = qla2x00_find_fcport_by_wwpn(vha, scm_stats->wwpn, 0); > + if (fcport) { > + /* Copy SCM Target data to local struct, keep WWPN from user */ > + memcpy(&scm_stats->current_events, > + &fcport->scm_stats.current_events, > + (sizeof(struct qla_scm_target) - > + sizeof(scm_stats->wwpn))); > + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, > + bsg_job->reply_payload.sg_cnt, scm_stats, > + sizeof(struct qla_scm_target)); > + rval = EXT_STATUS_OK; > + } else { > + rval = EXT_STATUS_ERR; > + } > + > + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_target); > + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; > + > + 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(scm_stats); > + return 0; > +} > + > static int > qla2x00_process_vendor_specific(struct bsg_job *bsg_job) > { > @@ -2522,6 +2627,15 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job) > case QL_VND_SS_GET_FLASH_IMAGE_STATUS: > return qla2x00_get_flash_image_status(bsg_job); > > + case QL_VND_GET_PORT_SCM: > + return qla2x00_get_port_scm(bsg_job); > + > + case QL_VND_GET_TARGET_SCM: > + return qla2x00_get_target_scm(bsg_job); > + > + case QL_VND_GET_DRV_ATTR: > + return qla2x00_get_drv_attr(bsg_job); > + > default: > return -ENOSYS; > } > diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h > index 0b308859047c..c7cf5f772ad3 100644 > --- a/drivers/scsi/qla2xxx/qla_bsg.h > +++ b/drivers/scsi/qla2xxx/qla_bsg.h > @@ -32,6 +32,9 @@ > #define QL_VND_DPORT_DIAGNOSTICS 0x19 > #define QL_VND_GET_PRIV_STATS_EX 0x1A > #define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E > +#define QL_VND_GET_PORT_SCM 0x20 > +#define QL_VND_GET_TARGET_SCM 0x21 > +#define QL_VND_GET_DRV_ATTR 0x22 > > /* BSG Vendor specific subcode returns */ > #define EXT_STATUS_OK 0 > Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 97b51c477972..bd898bbdd44d 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -2446,6 +2446,111 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job) return 0; } +static int +qla2x00_get_drv_attr(struct bsg_job *bsg_job) +{ + struct qla_drv_attr drv_attr; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + + memset(&drv_attr, 0, sizeof(struct qla_drv_attr)); + /* Additional check should be added if SCM is not enabled + * by default for a given driver version. + */ + drv_attr.attributes |= QLA_DRV_ATTR_SCM_SUPPORTED; + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, &drv_attr, + sizeof(struct qla_drv_attr)); + + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr); + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + + 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); + + return 0; +} + +static int +qla2x00_get_port_scm(struct bsg_job *bsg_job) +{ + struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job); + scsi_qla_host_t *vha = shost_priv(shost); + struct qla_hw_data *ha = vha->hw; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, &vha->scm_stats, + sizeof(struct qla_scm_port)); + + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_port); + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; + + 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); + + return 0; +} + +static int +qla2x00_get_target_scm(struct bsg_job *bsg_job) +{ + struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job); + scsi_qla_host_t *vha = shost_priv(shost); + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + struct qla_hw_data *ha = vha->hw; + fc_port_t *fcport = NULL; + int rval; + struct qla_scm_target *scm_stats = NULL; + + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) + return -EPERM; + + scm_stats = kzalloc(sizeof(*scm_stats), GFP_KERNEL); + if (!scm_stats) { + ql_log(ql_log_warn, vha, 0x7024, + "Failed to allocate memory for target scm stats.\n"); + return -ENOMEM; + } + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, scm_stats, + sizeof(struct qla_scm_target)); + + fcport = qla2x00_find_fcport_by_wwpn(vha, scm_stats->wwpn, 0); + if (fcport) { + /* Copy SCM Target data to local struct, keep WWPN from user */ + memcpy(&scm_stats->current_events, + &fcport->scm_stats.current_events, + (sizeof(struct qla_scm_target) - + sizeof(scm_stats->wwpn))); + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, scm_stats, + sizeof(struct qla_scm_target)); + rval = EXT_STATUS_OK; + } else { + rval = EXT_STATUS_ERR; + } + + bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_target); + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval; + + 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(scm_stats); + return 0; +} + static int qla2x00_process_vendor_specific(struct bsg_job *bsg_job) { @@ -2522,6 +2627,15 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job) case QL_VND_SS_GET_FLASH_IMAGE_STATUS: return qla2x00_get_flash_image_status(bsg_job); + case QL_VND_GET_PORT_SCM: + return qla2x00_get_port_scm(bsg_job); + + case QL_VND_GET_TARGET_SCM: + return qla2x00_get_target_scm(bsg_job); + + case QL_VND_GET_DRV_ATTR: + return qla2x00_get_drv_attr(bsg_job); + default: return -ENOSYS; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h index 0b308859047c..c7cf5f772ad3 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.h +++ b/drivers/scsi/qla2xxx/qla_bsg.h @@ -32,6 +32,9 @@ #define QL_VND_DPORT_DIAGNOSTICS 0x19 #define QL_VND_GET_PRIV_STATS_EX 0x1A #define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E +#define QL_VND_GET_PORT_SCM 0x20 +#define QL_VND_GET_TARGET_SCM 0x21 +#define QL_VND_GET_DRV_ATTR 0x22 /* BSG Vendor specific subcode returns */ #define EXT_STATUS_OK 0