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?

> + *
> + */
> +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.

> +     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

Reply via email to