>Yi Zou wrote:
>> Upon receiving ELS_RLS, send the Link Error Status Block (LESB) back.
>>
>> Signed-off-by: Yi Zou <[email protected]>
>> ---
>>
>> drivers/scsi/libfc/fc_lport.c | 124
>+++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 124 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
>> index bbf4152..48b8aae 100644
>> --- a/drivers/scsi/libfc/fc_lport.c
>> +++ b/drivers/scsi/libfc/fc_lport.c
>> @@ -526,6 +526,127 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp,
>struct fc_frame *fp,
>> }
>>
>> /**
>> + * fc_lport_get_lesb() - Fill the Link Error Status Block
>> + * @lport: The local port recieving the RLS
>> + * @lesb: The FC-BB-5 Link Error Status Block to be filled in
>> + *
>> + * Fill the LESB with from the per-cpu fcoe statistics, return 0
>> + * when stats are successfully retrieved.
>> + */
>> +static int fc_lport_get_lesb(struct fc_lport *lport,
>> + struct fc_els_lesb_bb5 *lesb)
>> +{
>> + unsigned int cpu;
>> + u32 lfc, vlfc, mdac;
>> + struct fcoe_dev_stats *devst;
>> + struct fcoe_lld_stats *lldst;
>> +
>> + lfc = 0;
>> + vlfc = 0;
>> + mdac = 0;
>> + memset(lesb, 0, sizeof(*lesb));
>> + for_each_possible_cpu(cpu) {
>> + devst = per_cpu_ptr(lport->dev_stats, cpu);
>> + lfc += devst->LinkFailureCount;
>> + vlfc += devst->VLinkFailureCount;
>> + mdac += devst->MissDiscAdvCount;
>> + }
>> + lesb->lesb_link_fail = __cpu_to_be32(lfc);
>> + lesb->lesb_vlink_fail = __cpu_to_be32(vlfc);
>> + lesb->lesb_miss_fip = __cpu_to_be32(mdac);
>> +
>> + lldst = &lport->lld_stats;
>> + if (lport->tt.lld_stats) {
>> + lport->tt.lld_stats(lport, lldst);
>> + lesb->lesb_symb_err = __cpu_to_be32(lldst->SymbolErrorCount);
>> + lesb->lesb_err_block = __cpu_to_be32(lldst->ErroredBlockCount);
>> + lesb->lesb_fcs_error = __cpu_to_be32(lldst->FCSErrorCount);
>> + }
>> + return 0;
>> +}
>> +
>> +/**
>> + * fc_lport_recv_rls_req() - Handle received Request Node ID data request
>> + * @sp: The sequence in the RLS exchange
>> + * @fp: The RLS request frame
>> + * @lport: The local port recieving the RLS
>> + *
>> + * Locking Note: The lport lock is expected to be held before calling
>> + * this function.
>> + *
>> + * FIXME: how to check/indicate if we want support RLS for LESB?
>
>If the LLD supports it?
I don't know how the LLD will indicate to FCoE stack this is supported,
possibly by netdev flags as well? I wanted call it out as I did not
find any way to query if this feature is supported.
>
>> + *
>> + */
>> +static void fc_lport_recv_rls_req(struct fc_seq *sp, struct fc_frame
>*in_fp,
>> + struct fc_lport *lport)
>> +{
>> + struct fc_frame *fp;
>> + struct fc_exch *ep = fc_seq_exch(sp);
>> + struct fc_els_rls *rls;
>> + struct fc_els_rls_resp *rsp;
>> + struct fc_seq_els_data rjt_data;
>> + struct fc_els_lesb_bb5 *lesb;
>> + struct fc_rport_priv *rdata;
>> + struct fc_frame_header *fh;
>> + size_t len;
>> + u32 f_ctl;
>> + u32 sid;
>> +
>> + FC_LPORT_DBG(lport, "Received RLS request while in state %s\n",
>> + fc_lport_state(lport));
>> +
>> + /* check if this port is logged in */
>> + fh = fc_frame_header_get(in_fp);
>> + sid = ntoh24(fh->fh_s_id);
>> + mutex_lock(&lport->disc.disc_mutex);
>> + rdata = lport->tt.rport_lookup(lport, sid);
>> + mutex_unlock(&lport->disc.disc_mutex);
>
>This should be done in fc_rport_recv_els_req(). The rport lookup is
>already done for you and the PLOGI needed error check is also done by then.
>
Good point, I missed that, plus your comment below. I initially started this
by sending ELS_NOLOGIN handled by lport. This should really be in rport.
Thanks.
yi
>> + if (!rdata) {
>> + FC_LPORT_DBG(lport, "LS_RJT %x:PLOGI needed\n", sid);
>> + rjt_data.reason = ELS_RJT_UNAB;
>> + rjt_data.explan = ELS_EXPL_PLOGI_REQD;
>> + goto out_rjt;
>> + }
>> + /* no rls payload */
>> + rls = fc_frame_payload_get(in_fp, sizeof(*rls));
>> + if (!rls) {
>> + rjt_data.reason = ELS_RJT_LOGIC;
>> + rjt_data.explan = ELS_EXPL_NONE;
>> + goto out_rjt;
>> + }
>> +
>> + len = sizeof(*rsp);
>> + fp = fc_frame_alloc(lport, len);
>> + if (!fp) {
>> + rjt_data.reason = ELS_RJT_UNAB;
>> + rjt_data.explan = ELS_EXPL_INSUF_RES;
>> + goto out_rjt;
>> + }
>> + rsp = fc_frame_payload_get(fp, len);
>> + memset(rsp, 0, len);
>> + rsp->rls_cmd = ELS_LS_ACC;
>> + lesb = (struct fc_els_lesb_bb5 *)&rsp->rls_lesb;
>> + if (fc_lport_get_lesb(lport, lesb)) {
>> + FC_LPORT_DBG(lport, "LS_RJT %x:failed to get lesb\n", sid);
>> + rjt_data.reason = ELS_RJT_UNAB;
>> + rjt_data.explan = ELS_EXPL_INSUF_RES;
>> + goto out_rjt;
>> + }
>> + /* send response */
>> + sp = lport->tt.seq_start_next(sp);
>> + f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ;
>> + fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
>> + FC_TYPE_ELS, f_ctl, 0);
>> + lport->tt.seq_send(lport, sp, fp);
>> + goto out;
>> +out_rjt:
>> + rjt_data.fp = NULL;
>> + lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
>> +out:
>> + fc_frame_free(in_fp);
>> +}
>> +
>> +/**
>> * fc_fabric_login() - Start the lport state machine
>> * @lport: The local port that should log into the fabric
>> *
>> @@ -898,6 +1019,9 @@ static void fc_lport_recv_req(struct fc_lport *lport,
>struct fc_seq *sp,
>> case ELS_RNID:
>> recv = fc_lport_recv_rnid_req;
>> break;
>> + case ELS_RLS:
>> + recv = fc_lport_recv_rls_req;
>> + break;
>
>This case should be added to fc_rport_recv_req() instead.
>
>> }
>>
>> recv(sp, fp, lport);
>>
>> _______________________________________________
>> devel mailing list
>> [email protected]
>> http://www.open-fcoe.org/mailman/listinfo/devel
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel