Message ID | 20210531070545.32072-3-njavali@marvell.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | qla2xxx: Add EDIF support | expand |
On 5/31/21 9:05 AM, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > Latest FC adapter from Marvell has the ability to encrypt > data in flight (EDIF) feature. This feature require an > application (ex: ipsec, etc) to act as an authenticator. > > This patch add 2 new BSG calls: > QL_VND_SC_GET_FCINFO: Application from time to time can request > for a list of all FC ports or a single device that support > secure connection. If driver sees a new or old device has > came onto the switch, this call is used to check for the WWPN. > > QL_VND_SC_GET_STATS: Application request for various statistic > count of each FC port. > > Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com> > Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com> > Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com> > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_def.h | 2 + > drivers/scsi/qla2xxx/qla_edif.c | 182 ++++++++++++++++++++++++++++++++ > 2 files changed, 184 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index ac3b9b39d741..9c921381d020 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -2574,6 +2574,8 @@ typedef struct fc_port { > uint16_t app_started:1; > uint16_t secured_login:1; > uint16_t app_sess_online:1; > + uint16_t rekey_cnt; // num of times rekeyed > + uint8_t auth_state; /* cureent auth state */ > uint32_t tx_rekey_cnt; > uint32_t rx_rekey_cnt; > // delayed rx delete data structure list Please check structure alignment. > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c > index 38d79ef2e700..fd39232fa68d 100644 > --- a/drivers/scsi/qla2xxx/qla_edif.c > +++ b/drivers/scsi/qla2xxx/qla_edif.c > @@ -258,6 +258,182 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > return rval; > } > > +/* > + * event that the app needs fc port info (either all or individual d_id) > + */ > +static int > +qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > +{ > + int32_t rval = 0; > + int32_t num_cnt = 1; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + struct app_pinfo_req app_req; > + struct app_pinfo_reply *app_reply; > + port_id_t tdid; > + > + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app get fcinfo\n", __func__); > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + 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); > + 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)) > + continue; > + > + tdid = app_req.remote_pid; > + > + ql_dbg(ql_dbg_edif, vha, 0x2058, > + "APP request entry - portid=%02x%02x%02x.\n", > + tdid.b.domain, tdid.b.area, tdid.b.al_pa); > + > + /* Ran out of space */ > + if (pcnt > app_req.num_ports) > + break; > + > + if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24) > + continue; > + > + app_reply->ports[pcnt].remote_type = > + VND_CMD_RTYPE_UNKNOWN; > + if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET)) > + app_reply->ports[pcnt].remote_type |= > + VND_CMD_RTYPE_TARGET; > + if (fcport->port_type & (FCT_NVME_INITIATOR | FCT_INITIATOR)) > + app_reply->ports[pcnt].remote_type |= > + VND_CMD_RTYPE_INITIATOR; > + > + app_reply->ports[pcnt].remote_pid = fcport->d_id; > + > + ql_dbg(ql_dbg_edif, vha, 0x2058, > + "Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%02x%02x%02x.\n", Indentation. > + fcport->node_name, fcport->port_name, pcnt, > + fcport->d_id.b.domain, fcport->d_id.b.area, > + fcport->d_id.b.al_pa); > + > + switch (fcport->edif.auth_state) { > + case VND_CMD_AUTH_STATE_ELS_RCVD: > + if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) { > + fcport->edif.auth_state = VND_CMD_AUTH_STATE_NEEDED; > + app_reply->ports[pcnt].auth_state = > + VND_CMD_AUTH_STATE_NEEDED; > + } else { > + app_reply->ports[pcnt].auth_state = > + VND_CMD_AUTH_STATE_ELS_RCVD; > + } > + break; > + default: > + app_reply->ports[pcnt].auth_state = fcport->edif.auth_state; > + break; > + } > + > + memcpy(app_reply->ports[pcnt].remote_wwpn, > + fcport->port_name, 8); > + > + app_reply->ports[pcnt].remote_state = > + (atomic_read(&fcport->state) == > + FCS_ONLINE ? 1 : 0); > + > + pcnt++; > + > + if (tdid.b24 != 0) > + break; /* found the one req'd */ > + } > + app_reply->port_count = pcnt; > + 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); > + > + kfree(app_reply); > + > + return rval; > +} > + > +/* > + * return edif stats (TBD) to app > + */ > +static int32_t > +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; > + > + struct app_sinfo_req app_req; > + struct app_stats_reply *app_reply; > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + bsg_job->request_payload.sg_cnt, &app_req, > + sizeof(struct app_sinfo_req)); > + if (app_req.num_ports == 0) { > + ql_dbg(ql_dbg_async, vha, 0x911d, > + "%s app did not indicate number of ports to return\n", > + __func__); > + SET_DID_STATUS(bsg_reply->result, DID_ERROR); > + rval = -1; > + } > + > + 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) { > + if (pcnt > app_req.num_ports) > + break; > + > + app_reply->elem[pcnt].rekey_count = > + fcport->edif.rekey_cnt; > + app_reply->elem[pcnt].tx_bytes = > + fcport->edif.tx_bytes; > + app_reply->elem[pcnt].rx_bytes = > + fcport->edif.rx_bytes; > + > + memcpy(app_reply->elem[pcnt].remote_wwpn, > + fcport->port_name, 8); > + > + pcnt++; > + } > + } > + app_reply->elem_count = pcnt; > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + } > + > + 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); > + > + kfree(app_reply); > + > + return rval; > +} > + > int32_t > qla_edif_app_mgmt(struct bsg_job *bsg_job) > { > @@ -304,6 +480,12 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) > case QL_VND_SC_APP_STOP: > rval = qla_edif_app_stop(vha, bsg_job); > break; > + case QL_VND_SC_GET_FCINFO: > + rval = qla_edif_app_getfcinfo(vha, bsg_job); > + break; > + case QL_VND_SC_GET_STATS: > + rval = qla_edif_app_getstats(vha, bsg_job); > + break; > default: > ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n", > __func__, > Other than that: Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes
On 5/31/21 2:05 AM, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > Latest FC adapter from Marvell has the ability to encrypt > data in flight (EDIF) feature. This feature require an > application (ex: ipsec, etc) to act as an authenticator. > > This patch add 2 new BSG calls: > QL_VND_SC_GET_FCINFO: Application from time to time can request > for a list of all FC ports or a single device that support > secure connection. If driver sees a new or old device has > came onto the switch, this call is used to check for the WWPN. > > QL_VND_SC_GET_STATS: Application request for various statistic > count of each FC port. > > Signed-off-by: Larry Wisneski <Larry.Wisneski@marvell.com> > Signed-off-by: Duane Grigsby <duane.grigsby@marvell.com> > Signed-off-by: Rick Hicksted Jr <rhicksted@marvell.com> > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_def.h | 2 + > drivers/scsi/qla2xxx/qla_edif.c | 182 ++++++++++++++++++++++++++++++++ > 2 files changed, 184 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index ac3b9b39d741..9c921381d020 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -2574,6 +2574,8 @@ typedef struct fc_port { > uint16_t app_started:1; > uint16_t secured_login:1; > uint16_t app_sess_online:1; > + uint16_t rekey_cnt; // num of times rekeyed > + uint8_t auth_state; /* cureent auth state */ > uint32_t tx_rekey_cnt; > uint32_t rx_rekey_cnt; > // delayed rx delete data structure list seems like widespread issue during this patch series.. please fix comments > diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c > index 38d79ef2e700..fd39232fa68d 100644 > --- a/drivers/scsi/qla2xxx/qla_edif.c > +++ b/drivers/scsi/qla2xxx/qla_edif.c > @@ -258,6 +258,182 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > return rval; > } > > +/* > + * event that the app needs fc port info (either all or individual d_id) > + */ > +static int > +qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) > +{ > + int32_t rval = 0; > + int32_t num_cnt = 1; > + struct fc_bsg_reply *bsg_reply = bsg_job->reply; > + struct app_pinfo_req app_req; > + struct app_pinfo_reply *app_reply; > + port_id_t tdid; > + > + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app get fcinfo\n", __func__); > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + 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 */ extra space after "=" > + app_reply = kzalloc((sizeof(struct app_pinfo_reply) + > + sizeof(struct app_pinfo) * num_cnt), 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)) > + continue; > + > + tdid = app_req.remote_pid; > + > + ql_dbg(ql_dbg_edif, vha, 0x2058, > + "APP request entry - portid=%02x%02x%02x.\n", > + tdid.b.domain, tdid.b.area, tdid.b.al_pa); port id can be printed as %06x and tdid.b24 > + > + /* Ran out of space */ > + if (pcnt > app_req.num_ports) > + break; > + > + if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24) > + continue; > + > + app_reply->ports[pcnt].remote_type = > + VND_CMD_RTYPE_UNKNOWN; > + if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET)) > + app_reply->ports[pcnt].remote_type |= > + VND_CMD_RTYPE_TARGET; > + if (fcport->port_type & (FCT_NVME_INITIATOR | FCT_INITIATOR)) > + app_reply->ports[pcnt].remote_type |= > + VND_CMD_RTYPE_INITIATOR; > + > + app_reply->ports[pcnt].remote_pid = fcport->d_id; > + > + ql_dbg(ql_dbg_edif, vha, 0x2058, > + "Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%02x%02x%02x.\n", fix indentation and port id can be printed as "%06x" with fcport->d_id.b24 > + fcport->node_name, fcport->port_name, pcnt, > + fcport->d_id.b.domain, fcport->d_id.b.area, > + fcport->d_id.b.al_pa); > + > + switch (fcport->edif.auth_state) { > + case VND_CMD_AUTH_STATE_ELS_RCVD: > + if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) { > + fcport->edif.auth_state = VND_CMD_AUTH_STATE_NEEDED; > + app_reply->ports[pcnt].auth_state = > + VND_CMD_AUTH_STATE_NEEDED; > + } else { > + app_reply->ports[pcnt].auth_state = > + VND_CMD_AUTH_STATE_ELS_RCVD; > + } > + break; > + default: > + app_reply->ports[pcnt].auth_state = fcport->edif.auth_state; > + break; > + } > + > + memcpy(app_reply->ports[pcnt].remote_wwpn, > + fcport->port_name, 8); > + > + app_reply->ports[pcnt].remote_state = > + (atomic_read(&fcport->state) == > + FCS_ONLINE ? 1 : 0); > + > + pcnt++; > + > + if (tdid.b24 != 0) > + break; /* found the one req'd */ > + } > + app_reply->port_count = pcnt; > + 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); > + > + kfree(app_reply); > + > + return rval; > +} > + > +/* > + * return edif stats (TBD) to app > + */ > +static int32_t > +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; > + > + struct app_sinfo_req app_req; > + struct app_stats_reply *app_reply; > + > + sg_copy_to_buffer(bsg_job->request_payload.sg_list, > + bsg_job->request_payload.sg_cnt, &app_req, > + sizeof(struct app_sinfo_req)); > + if (app_req.num_ports == 0) { > + ql_dbg(ql_dbg_async, vha, 0x911d, > + "%s app did not indicate number of ports to return\n", > + __func__); > + SET_DID_STATUS(bsg_reply->result, DID_ERROR); > + rval = -1; > + } > + > + 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) { > + if (pcnt > app_req.num_ports) > + break; > + > + app_reply->elem[pcnt].rekey_count = > + fcport->edif.rekey_cnt; > + app_reply->elem[pcnt].tx_bytes = > + fcport->edif.tx_bytes; > + app_reply->elem[pcnt].rx_bytes = > + fcport->edif.rx_bytes; > + > + memcpy(app_reply->elem[pcnt].remote_wwpn, > + fcport->port_name, 8); > + > + pcnt++; > + } > + } > + app_reply->elem_count = pcnt; > + SET_DID_STATUS(bsg_reply->result, DID_OK); > + } > + > + 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); > + > + kfree(app_reply); > + > + return rval; > +} > + > int32_t > qla_edif_app_mgmt(struct bsg_job *bsg_job) > { > @@ -304,6 +480,12 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) > case QL_VND_SC_APP_STOP: > rval = qla_edif_app_stop(vha, bsg_job); > break; > + case QL_VND_SC_GET_FCINFO: > + rval = qla_edif_app_getfcinfo(vha, bsg_job); > + break; > + case QL_VND_SC_GET_STATS: > + rval = qla_edif_app_getstats(vha, bsg_job); > + break; > default: > ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n", > __func__, >
> // delayed rx delete data structure list
seems like widespread issue during this patch series.. please fix comments
QT: Ack to all various style issue. Will fix in v3.
Regards,
Quinn Tran
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ac3b9b39d741..9c921381d020 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2574,6 +2574,8 @@ typedef struct fc_port { uint16_t app_started:1; uint16_t secured_login:1; uint16_t app_sess_online:1; + uint16_t rekey_cnt; // num of times rekeyed + uint8_t auth_state; /* cureent auth state */ uint32_t tx_rekey_cnt; uint32_t rx_rekey_cnt; // delayed rx delete data structure list diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index 38d79ef2e700..fd39232fa68d 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -258,6 +258,182 @@ qla_edif_app_stop(scsi_qla_host_t *vha, struct bsg_job *bsg_job) return rval; } +/* + * event that the app needs fc port info (either all or individual d_id) + */ +static int +qla_edif_app_getfcinfo(scsi_qla_host_t *vha, struct bsg_job *bsg_job) +{ + int32_t rval = 0; + int32_t num_cnt = 1; + struct fc_bsg_reply *bsg_reply = bsg_job->reply; + struct app_pinfo_req app_req; + struct app_pinfo_reply *app_reply; + port_id_t tdid; + + ql_dbg(ql_dbg_edif, vha, 0x911d, "%s app get fcinfo\n", __func__); + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + 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); + 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)) + continue; + + tdid = app_req.remote_pid; + + ql_dbg(ql_dbg_edif, vha, 0x2058, + "APP request entry - portid=%02x%02x%02x.\n", + tdid.b.domain, tdid.b.area, tdid.b.al_pa); + + /* Ran out of space */ + if (pcnt > app_req.num_ports) + break; + + if (tdid.b24 != 0 && tdid.b24 != fcport->d_id.b24) + continue; + + app_reply->ports[pcnt].remote_type = + VND_CMD_RTYPE_UNKNOWN; + if (fcport->port_type & (FCT_NVME_TARGET | FCT_TARGET)) + app_reply->ports[pcnt].remote_type |= + VND_CMD_RTYPE_TARGET; + if (fcport->port_type & (FCT_NVME_INITIATOR | FCT_INITIATOR)) + app_reply->ports[pcnt].remote_type |= + VND_CMD_RTYPE_INITIATOR; + + app_reply->ports[pcnt].remote_pid = fcport->d_id; + + ql_dbg(ql_dbg_edif, vha, 0x2058, + "Found FC_SP fcport - nn %8phN pn %8phN pcnt %d portid=%02x%02x%02x.\n", + fcport->node_name, fcport->port_name, pcnt, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa); + + switch (fcport->edif.auth_state) { + case VND_CMD_AUTH_STATE_ELS_RCVD: + if (fcport->disc_state == DSC_LOGIN_AUTH_PEND) { + fcport->edif.auth_state = VND_CMD_AUTH_STATE_NEEDED; + app_reply->ports[pcnt].auth_state = + VND_CMD_AUTH_STATE_NEEDED; + } else { + app_reply->ports[pcnt].auth_state = + VND_CMD_AUTH_STATE_ELS_RCVD; + } + break; + default: + app_reply->ports[pcnt].auth_state = fcport->edif.auth_state; + break; + } + + memcpy(app_reply->ports[pcnt].remote_wwpn, + fcport->port_name, 8); + + app_reply->ports[pcnt].remote_state = + (atomic_read(&fcport->state) == + FCS_ONLINE ? 1 : 0); + + pcnt++; + + if (tdid.b24 != 0) + break; /* found the one req'd */ + } + app_reply->port_count = pcnt; + 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); + + kfree(app_reply); + + return rval; +} + +/* + * return edif stats (TBD) to app + */ +static int32_t +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; + + struct app_sinfo_req app_req; + struct app_stats_reply *app_reply; + + sg_copy_to_buffer(bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, &app_req, + sizeof(struct app_sinfo_req)); + if (app_req.num_ports == 0) { + ql_dbg(ql_dbg_async, vha, 0x911d, + "%s app did not indicate number of ports to return\n", + __func__); + SET_DID_STATUS(bsg_reply->result, DID_ERROR); + rval = -1; + } + + 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) { + if (pcnt > app_req.num_ports) + break; + + app_reply->elem[pcnt].rekey_count = + fcport->edif.rekey_cnt; + app_reply->elem[pcnt].tx_bytes = + fcport->edif.tx_bytes; + app_reply->elem[pcnt].rx_bytes = + fcport->edif.rx_bytes; + + memcpy(app_reply->elem[pcnt].remote_wwpn, + fcport->port_name, 8); + + pcnt++; + } + } + app_reply->elem_count = pcnt; + SET_DID_STATUS(bsg_reply->result, DID_OK); + } + + 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); + + kfree(app_reply); + + return rval; +} + int32_t qla_edif_app_mgmt(struct bsg_job *bsg_job) { @@ -304,6 +480,12 @@ qla_edif_app_mgmt(struct bsg_job *bsg_job) case QL_VND_SC_APP_STOP: rval = qla_edif_app_stop(vha, bsg_job); break; + case QL_VND_SC_GET_FCINFO: + rval = qla_edif_app_getfcinfo(vha, bsg_job); + break; + case QL_VND_SC_GET_STATS: + rval = qla_edif_app_getstats(vha, bsg_job); + break; default: ql_dbg(ql_dbg_edif, vha, 0x911d, "%s unknown cmd=%x\n", __func__,