Steve Ma wrote:
> This is an implementation of the FC pass-through support in FCoE
> via bsg interface according to the RFC published by James Smart
> on 11/18/2008 with the title "[RFC] FC pass thru - Rev IV"
> ---
>   
This is great!   Hopefully we can use this for fcping and fctraceroute 
eventually.
>  drivers/scsi/fcoe/fcoe_sw.c   |    2 
>  drivers/scsi/libfc/fc_rport.c |  232 
> +++++++++++++++++++++++++++++++++++++++++
>  include/scsi/libfc.h          |    2 
>  3 files changed, 236 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
> index 765a388..04f38af 100644
> --- a/drivers/scsi/fcoe/fcoe_sw.c
> +++ b/drivers/scsi/fcoe/fcoe_sw.c
> @@ -83,6 +83,8 @@ struct fc_function_template fcoe_sw_transport_function = {
>       .issue_fc_host_lip = fcoe_reset,
>  
>       .terminate_rport_io = fc_rport_terminate_io,
> +
> +     .bsg_request = fcoe_bsg_request,
>  };
>  
>  static struct scsi_host_template fcoe_sw_shost_template = {
> diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
> index dae6513..41d1519 100644
> --- a/drivers/scsi/libfc/fc_rport.c
> +++ b/drivers/scsi/libfc/fc_rport.c
> @@ -1314,3 +1314,235 @@ void fc_rport_terminate_io(struct fc_rport *rport)
>       lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
>  }
>  EXPORT_SYMBOL(fc_rport_terminate_io);
> +
> +struct fcoe_bsg_info {
> +     struct fc_bsg_job *job;
> +     struct fc_lport *lport;
> +};
> +
> +static void fc_bsg_els_resp(struct fc_seq *sp, struct fc_frame *fp,
> +                             void *rp_arg)
> +{
> +     struct fcoe_bsg_info *info = (struct fcoe_bsg_info *)rp_arg;
> +     struct fc_bsg_job *job = info->job;
> +     struct fc_lport *lport = info->lport;
> +     unsigned int len;
> +     void *pp;
> +
> +     mutex_lock(&lport->lp_mutex);
> +
> +     if (IS_ERR(fp))
> +             goto err;
> +
> +     len = fr_len(fp) - sizeof(struct fc_frame_header);
> +     pp = fc_frame_payload_get(fp, len);
> +
> +     sg_copy_from_buffer(job->reply_payload.sg_list,
> +                         job->reply_payload.sg_cnt,
> +                         pp, len);
> +     job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
> +
> +     if (fc_frame_payload_op(fp) == ELS_LS_ACC)
> +             job->reply->reply_data.ctels_reply.status
> +                     = FC_CTELS_STATUS_OK;
> +     else
> +             job->reply->reply_data.ctels_reply.status
> +                     = FC_CTELS_STATUS_REJECT;
> +err:
> +     fc_frame_free(fp);
> +     mutex_unlock(&lport->lp_mutex);
> +     kfree(info);
> +     job->state_flags = FC_RQST_STATE_DONE;
> +     job->job_done(job);
> +}
> +
> +static int fcoe_bsg_els_request(struct fc_bsg_job *job)
> +{
> +     struct fcoe_bsg_info *info;
> +     struct fc_rport *rport = job->rport;
> +     struct Scsi_Host *shost;
> +     struct fc_lport *lport;
> +     struct fc_frame *fp;
> +     struct fc_frame_header *fh;
> +     char *pp;
> +     int len;
> +     u32 did;
> +
> +     shost = rport ? rport_to_shost(rport) : job->shost;
> +     lport = shost_priv(shost);
> +
> +     if (!((lport->state == LPORT_ST_READY) &&
> +         lport->link_up && !lport->qfull))
> +             return -EINVAL;
> +
> +
> +     fp = fc_frame_alloc(lport, sizeof(struct fc_frame_header) +
> +                             job->request_payload.payload_len);
> +     if (!fp)
> +             return -EINVAL;
> +
> +     len = job->request_payload.payload_len;
> +     pp = fc_frame_payload_get(fp, len);
> +     memset(pp, 0, len);
> +
> +     sg_copy_to_buffer(job->request_payload.sg_list,
> +                       job->request_payload.sg_cnt,
> +                       pp, len);
> +
> +     switch (pp[0]) {
> +     case ELS_RNID:
> +     case ELS_RLS:
> +     case ELS_RCS:
> +             did = job->request->rqst_data.h_els.port_id[0]<<16 |
> +                   job->request->rqst_data.h_els.port_id[1]<<8  |
> +                   job->request->rqst_data.h_els.port_id[2];
>   

Use ntoh24().  This applies in a few other places.  Also, there should 
be spaces around the <<.
> +             break;
> +     default:
> +             if (!rport) {
> +                     fc_frame_free(fp);
> +                     return -EINVAL;
> +             }
> +             did = rport->port_id;
> +             break;
> +     }
> +
> +     fh = fc_frame_header_get(fp);
> +     fh->fh_r_ctl = FC_RCTL_ELS_REQ;
> +     hton24(fh->fh_d_id, did);
> +     hton24(fh->fh_s_id, fc_host_port_id(shost));
> +     fh->fh_type = FC_TYPE_ELS;
> +     hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
> +             FC_FC_END_SEQ | FC_FC_SEQ_INIT);
> +     fh->fh_cs_ctl = 0;
> +     fh->fh_df_ctl = 0;
> +     fh->fh_parm_offset = 0;
> +
> +     info = kzalloc(sizeof(struct fcoe_bsg_info), GFP_KERNEL);
> +     if (!info) {
> +             fc_frame_free(fp);
> +             return -EINVAL;
> +     }
> +
> +     info->job = job;
> +     info->lport = lport;
> +
> +     lport->tt.exch_seq_send(lport, fp, fc_bsg_els_resp,
> +                             NULL, (void *)info, lport->e_d_tov);
> +     return 0;
> +}
> +
> +static void fc_bsg_ct_resp(struct fc_seq *sp, struct fc_frame *fp,
> +                             void *rp_arg)
> +{
> +     struct fcoe_bsg_info *info = (struct fcoe_bsg_info *)rp_arg;
> +     struct fc_bsg_job *job = info->job;
> +     struct fc_lport *lport = info->lport;
> +     struct fc_ct_hdr *ct;
> +     unsigned int len;
> +     void *pp;
> +
> +     mutex_lock(&lport->lp_mutex);
> +
> +     if (IS_ERR(fp))
> +             goto err;
> +
> +     len = fr_len(fp) - sizeof(struct fc_frame_header);
> +     pp = fc_frame_payload_get(fp, len);
> +     sg_copy_from_buffer(job->reply_payload.sg_list,
> +                         job->reply_payload.sg_cnt,
> +                         pp, len);
> +     job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
> +
> +     ct = (struct fc_ct_hdr *)pp;
> +     if (ntohs(ct->ct_cmd) == FC_FS_ACC)
> +             job->reply->reply_data.ctels_reply.status
> +                     = FC_CTELS_STATUS_OK;
>   
Split this lines like this after the =.
> +     else
> +             job->reply->reply_data.ctels_reply.status
> +                     = FC_CTELS_STATUS_REJECT;
> +err:
> +     fc_frame_free(fp);
> +     mutex_unlock(&lport->lp_mutex);
> +     kfree(info);
> +     job->state_flags = FC_RQST_STATE_DONE;
> +     job->job_done(job);
> +}
> +
> +static int fcoe_bsg_ct_request(struct fc_bsg_job *job)
> +{
> +     struct fcoe_bsg_info *info;
> +     struct fc_rport *rport = job->rport;
> +     struct Scsi_Host *shost;
> +     struct fc_lport *lport;
> +     struct fc_frame *fp;
> +     struct fc_frame_header *fh;
> +     struct fc_ct_req *ct;
> +     struct fc_ct_hdr *ct_hdr;
> +     size_t len;
> +     u32 did;
> +
> +     shost = rport ? rport_to_shost(rport) : job->shost;
> +     lport = shost_priv(shost);
> +
> +     if (!((lport->state == LPORT_ST_READY) &&
> +         lport->link_up && !lport->qfull))
> +             return -EINVAL;
> +
> +     fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
> +                             job->request_payload.payload_len);
> +     if (!fp)
> +             return -EINVAL;
> +
> +     len = job->request_payload.payload_len;
> +     ct = fc_frame_payload_get(fp, len);
> +     memset(ct, 0, len);
> +
> +     sg_copy_to_buffer(job->request_payload.sg_list,
> +                       job->request_payload.sg_cnt,
> +                       ct, len);
> +     ct_hdr = &ct->hdr;
> +     ct_hdr->ct_cmd = htons((u16)ct_hdr->ct_cmd);
> +     ct_hdr->ct_mr_size = htons((u16)ct_hdr->ct_mr_size);
> +     did = ct->hdr.ct_in_id[0]<<16 |
> +           ct->hdr.ct_in_id[1]<<8  |
> +           ct->hdr.ct_in_id[2];
> +
> +     fh = fc_frame_header_get(fp);
> +     fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL;
> +     hton24(fh->fh_d_id, did);
> +     hton24(fh->fh_s_id, fc_host_port_id(shost));
> +     fh->fh_type = FC_TYPE_CT;
> +     hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
> +             FC_FC_END_SEQ | FC_FC_SEQ_INIT);
> +     fh->fh_cs_ctl = 0;
> +     fh->fh_df_ctl = 0;
> +     fh->fh_parm_offset = 0;
> +
> +     info = kzalloc(sizeof(struct fcoe_bsg_info), GFP_KERNEL);
> +     if (!info) {
> +             fc_frame_free(fp);
> +             return -EINVAL;
> +     }
> +
> +     info->job = job;
> +     info->lport = lport;
> +
> +     lport->tt.exch_seq_send(lport, fp, fc_bsg_ct_resp,
> +                             NULL, (void *)info, lport->e_d_tov);
> +     return 0;
> +}
> +
> +int fcoe_bsg_request(struct fc_bsg_job *job)
> +{
> +     switch (job->request->msgcode) {
> +     case FC_BSG_RPT_ELS:
> +     case FC_BSG_HST_ELS_NOLOGIN:
> +             return fcoe_bsg_els_request(job);
> +     case FC_BSG_RPT_CT:
> +             return fcoe_bsg_ct_request(job);
> +     default:
> +             return -EINVAL;
> +     }
> +}
> +EXPORT_SYMBOL(fcoe_bsg_request);
> +
> diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
> index a70eafa..221dff0 100644
> --- a/include/scsi/libfc.h
> +++ b/include/scsi/libfc.h
> @@ -25,6 +25,7 @@
>  
>  #include <scsi/scsi_transport.h>
>  #include <scsi/scsi_transport_fc.h>
> +#include <scsi/scsi_bsg_fc.h>
>  
>  #include <scsi/fc/fc_fcp.h>
>  #include <scsi/fc/fc_ns.h>
> @@ -778,6 +779,7 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs);
>   *****************************/
>  int fc_rport_init(struct fc_lport *lp);
>  void fc_rport_terminate_io(struct fc_rport *rp);
> +int fcoe_bsg_request(struct fc_bsg_job *job);
>  
>  /*
>   * DISCOVERY LAYER
>
> _______________________________________________
> 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