[PATCH v6 1/6] fc_els: use 'union fc_tlv_desc'

John Meneghini jmeneghi at redhat.com
Mon Jun 23 08:59:41 PDT 2025


Reviewed-by: John Meneghini <jmeneghi at redhat.com>

On 6/20/25 1:55 PM, Bryan Gurney wrote:
> From: Hannes Reinecke <hare at kernel.org>
> 
> Introduce 'union fc_tlv_desc' to have a common structure for all FC
> ELS TLV structures and avoid type casts.
> 
> [bgurney: The cast inside the union fc_tlv_next_desc() has "u8",
> which causes a failure to build.  Use "__u8" instead.]
> 
> Signed-off-by: Hannes Reinecke <hare at kernel.org>
> Reviewed-by: Justin Tee <justin.tee at broadcom.com>
> Tested-by: Bryan Gurney <bgurney at redhat.com>
> ---
>   drivers/scsi/lpfc/lpfc_els.c     |  75 +++++++-------
>   drivers/scsi/scsi_transport_fc.c |  27 +++--
>   include/uapi/scsi/fc/fc_els.h    | 165 +++++++++++++++++--------------
>   3 files changed, 135 insertions(+), 132 deletions(-)
> 
> diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
> index 375a879c31f1..959603ab939a 100644
> --- a/drivers/scsi/lpfc/lpfc_els.c
> +++ b/drivers/scsi/lpfc/lpfc_els.c
> @@ -3937,7 +3937,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
>   {
>   	IOCB_t *irsp_iocb;
>   	struct fc_els_edc_resp *edc_rsp;
> -	struct fc_tlv_desc *tlv;
> +	union fc_tlv_desc *tlv;
>   	struct fc_diag_cg_sig_desc *pcgd;
>   	struct fc_diag_lnkflt_desc *plnkflt;
>   	struct lpfc_dmabuf *pcmd, *prsp;
> @@ -4028,7 +4028,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
>   			goto out;
>   		}
>   
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);
>   		switch (dtag) {
>   		case ELS_DTAG_LNK_FAULT_CAP:
>   			if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
> @@ -4043,7 +4043,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
>   					sizeof(struct fc_diag_lnkflt_desc));
>   				goto out;
>   			}
> -			plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
> +			plnkflt = &tlv->lnkflt;
>   			lpfc_printf_log(phba, KERN_INFO,
>   				LOG_ELS | LOG_LDS_EVENT,
>   				"4617 Link Fault Desc Data: 0x%08x 0x%08x "
> @@ -4070,7 +4070,7 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
>   				goto out;
>   			}
>   
> -			pcgd = (struct fc_diag_cg_sig_desc *)tlv;
> +			pcgd = &tlv->cg_sig;
>   			lpfc_printf_log(
>   				phba, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
>   				"4616 CGN Desc Data: 0x%08x 0x%08x "
> @@ -4125,10 +4125,8 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
>   }
>   
>   static void
> -lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_diag_lnkflt_desc *lft)
>   {
> -	struct fc_diag_lnkflt_desc *lft = (struct fc_diag_lnkflt_desc *)tlv;
> -
>   	lft->desc_tag = cpu_to_be32(ELS_DTAG_LNK_FAULT_CAP);
>   	lft->desc_len = cpu_to_be32(
>   		FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_diag_lnkflt_desc));
> @@ -4141,10 +4139,8 @@ lpfc_format_edc_lft_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
>   }
>   
>   static void
> -lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_format_edc_cgn_desc(struct lpfc_hba *phba, struct fc_diag_cg_sig_desc *cgd)
>   {
> -	struct fc_diag_cg_sig_desc *cgd = (struct fc_diag_cg_sig_desc *)tlv;
> -
>   	/* We are assuming cgd was zero'ed before calling this routine */
>   
>   	/* Configure the congestion detection capability */
> @@ -4233,7 +4229,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
>   	struct lpfc_hba  *phba = vport->phba;
>   	struct lpfc_iocbq *elsiocb;
>   	struct fc_els_edc *edc_req;
> -	struct fc_tlv_desc *tlv;
> +	union fc_tlv_desc *tlv;
>   	u16 cmdsize;
>   	struct lpfc_nodelist *ndlp;
>   	u8 *pcmd = NULL;
> @@ -4272,13 +4268,13 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
>   	tlv = edc_req->desc;
>   
>   	if (cgn_desc_size) {
> -		lpfc_format_edc_cgn_desc(phba, tlv);
> +		lpfc_format_edc_cgn_desc(phba, &tlv->cg_sig);
>   		phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
>   		tlv = fc_tlv_next_desc(tlv);
>   	}
>   
>   	if (lft_desc_size)
> -		lpfc_format_edc_lft_desc(phba, tlv);
> +		lpfc_format_edc_lft_desc(phba, &tlv->lnkflt);
>   
>   	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
>   			 "4623 Xmit EDC to remote "
> @@ -5823,7 +5819,7 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   {
>   	struct lpfc_hba  *phba = vport->phba;
>   	struct fc_els_edc_resp *edc_rsp;
> -	struct fc_tlv_desc *tlv;
> +	union fc_tlv_desc *tlv;
>   	struct lpfc_iocbq *elsiocb;
>   	IOCB_t *icmd, *cmd;
>   	union lpfc_wqe128 *wqe;
> @@ -5867,10 +5863,10 @@ lpfc_issue_els_edc_rsp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   		FC_TLV_DESC_LENGTH_FROM_SZ(struct fc_els_lsri_desc));
>   	edc_rsp->lsri.rqst_w0.cmd = ELS_EDC;
>   	tlv = edc_rsp->desc;
> -	lpfc_format_edc_cgn_desc(phba, tlv);
> +	lpfc_format_edc_cgn_desc(phba, &tlv->cg_sig);
>   	tlv = fc_tlv_next_desc(tlv);
>   	if (lft_desc_size)
> -		lpfc_format_edc_lft_desc(phba, tlv);
> +		lpfc_format_edc_lft_desc(phba, &tlv->lnkflt);
>   
>   	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
>   			      "Issue EDC ACC:      did:x%x flg:x%lx refcnt %d",
> @@ -9255,7 +9251,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   {
>   	struct lpfc_hba  *phba = vport->phba;
>   	struct fc_els_edc *edc_req;
> -	struct fc_tlv_desc *tlv;
> +	union fc_tlv_desc *tlv;
>   	uint8_t *payload;
>   	uint32_t *ptr, dtag;
>   	const char *dtag_nm;
> @@ -9298,7 +9294,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   			goto out;
>   		}
>   
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);
>   		switch (dtag) {
>   		case ELS_DTAG_LNK_FAULT_CAP:
>   			if (bytes_remain < FC_TLV_DESC_SZ_FROM_LENGTH(tlv) ||
> @@ -9313,7 +9309,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   					sizeof(struct fc_diag_lnkflt_desc));
>   				goto out;
>   			}
> -			plnkflt = (struct fc_diag_lnkflt_desc *)tlv;
> +			plnkflt = &tlv->lnkflt;
>   			lpfc_printf_log(phba, KERN_INFO,
>   				LOG_ELS | LOG_LDS_EVENT,
>   				"4626 Link Fault Desc Data: x%08x len x%x "
> @@ -9350,7 +9346,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>   			phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
>   
>   			lpfc_least_capable_settings(
> -				phba, (struct fc_diag_cg_sig_desc *)tlv);
> +				phba, &tlv->cg_sig);
>   			break;
>   		default:
>   			dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
> @@ -9941,14 +9937,13 @@ lpfc_display_fpin_wwpn(struct lpfc_hba *phba, __be64 *wwnlist, u32 cnt)
>   /**
>    * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event.
>    * @phba: Pointer to phba object.
> - * @tlv:  Pointer to the Link Integrity Notification Descriptor.
> + * @li:  Pointer to the Link Integrity Notification Descriptor.
>    *
>    * This function processes a Link Integrity FPIN event by logging a message.
>    **/
>   static void
> -lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_fn_li_desc *li)
>   {
> -	struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv;
>   	const char *li_evt_str;
>   	u32 li_evt, cnt;
>   
> @@ -9972,14 +9967,13 @@ lpfc_els_rcv_fpin_li(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
>   /**
>    * lpfc_els_rcv_fpin_del - Process an FPIN Delivery Event.
>    * @phba: Pointer to hba object.
> - * @tlv:  Pointer to the Delivery Notification Descriptor TLV
> + * @del:  Pointer to the Delivery Notification Descriptor TLV
>    *
>    * This function processes a Delivery FPIN event by logging a message.
>    **/
>   static void
> -lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_fn_deli_desc *del)
>   {
> -	struct fc_fn_deli_desc *del = (struct fc_fn_deli_desc *)tlv;
>   	const char *del_rsn_str;
>   	u32 del_rsn;
>   	__be32 *frame;
> @@ -10010,14 +10004,14 @@ lpfc_els_rcv_fpin_del(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
>   /**
>    * lpfc_els_rcv_fpin_peer_cgn - Process a FPIN Peer Congestion Event.
>    * @phba: Pointer to hba object.
> - * @tlv:  Pointer to the Peer Congestion Notification Descriptor TLV
> + * @pc:  Pointer to the Peer Congestion Notification Descriptor TLV
>    *
>    * This function processes a Peer Congestion FPIN event by logging a message.
>    **/
>   static void
> -lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba,
> +			   struct fc_fn_peer_congn_desc *pc)
>   {
> -	struct fc_fn_peer_congn_desc *pc = (struct fc_fn_peer_congn_desc *)tlv;
>   	const char *pc_evt_str;
>   	u32 pc_evt, cnt;
>   
> @@ -10045,7 +10039,7 @@ lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
>   /**
>    * lpfc_els_rcv_fpin_cgn - Process an FPIN Congestion notification
>    * @phba: Pointer to hba object.
> - * @tlv:  Pointer to the Congestion Notification Descriptor TLV
> + * @cgn:  Pointer to the Congestion Notification Descriptor TLV
>    *
>    * This function processes an FPIN Congestion Notifiction.  The notification
>    * could be an Alarm or Warning.  This routine feeds that data into driver's
> @@ -10054,10 +10048,9 @@ lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
>    * to the upper layer or 0 to indicate don't deliver it.
>    **/
>   static int
> -lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
> +lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_fn_congn_desc *cgn)
>   {
>   	struct lpfc_cgn_info *cp;
> -	struct fc_fn_congn_desc *cgn = (struct fc_fn_congn_desc *)tlv;
>   	const char *cgn_evt_str;
>   	u32 cgn_evt;
>   	const char *cgn_sev_str;
> @@ -10160,7 +10153,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
>   {
>   	struct lpfc_hba *phba = vport->phba;
>   	struct fc_els_fpin *fpin = (struct fc_els_fpin *)p;
> -	struct fc_tlv_desc *tlv, *first_tlv, *current_tlv;
> +	union fc_tlv_desc *tlv, *first_tlv, *current_tlv;
>   	const char *dtag_nm;
>   	int desc_cnt = 0, bytes_remain, cnt;
>   	u32 dtag, deliver = 0;
> @@ -10185,7 +10178,7 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
>   		return;
>   	}
>   
> -	tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
> +	tlv = &fpin->fpin_desc[0];
>   	first_tlv = tlv;
>   	bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc);
>   	bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
> @@ -10193,22 +10186,22 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
>   	/* process each descriptor separately */
>   	while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
>   	       bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);
>   		switch (dtag) {
>   		case ELS_DTAG_LNK_INTEGRITY:
> -			lpfc_els_rcv_fpin_li(phba, tlv);
> +			lpfc_els_rcv_fpin_li(phba, &tlv->li);
>   			deliver = 1;
>   			break;
>   		case ELS_DTAG_DELIVERY:
> -			lpfc_els_rcv_fpin_del(phba, tlv);
> +			lpfc_els_rcv_fpin_del(phba, &tlv->deli);
>   			deliver = 1;
>   			break;
>   		case ELS_DTAG_PEER_CONGEST:
> -			lpfc_els_rcv_fpin_peer_cgn(phba, tlv);
> +			lpfc_els_rcv_fpin_peer_cgn(phba, &tlv->peer_congn);
>   			deliver = 1;
>   			break;
>   		case ELS_DTAG_CONGESTION:
> -			deliver = lpfc_els_rcv_fpin_cgn(phba, tlv);
> +			deliver = lpfc_els_rcv_fpin_cgn(phba, &tlv->congn);
>   			break;
>   		default:
>   			dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
> @@ -10221,12 +10214,12 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
>   			return;
>   		}
>   		lpfc_cgn_update_stat(phba, dtag);
> -		cnt = be32_to_cpu(tlv->desc_len);
> +		cnt = be32_to_cpu(tlv->hdr.desc_len);
>   
>   		/* Sanity check descriptor length. The desc_len value does not
>   		 * include space for the desc_tag and the desc_len fields.
>   		 */
> -		len -= (cnt + sizeof(struct fc_tlv_desc));
> +		len -= (cnt + sizeof(struct fc_tlv_desc_hdr));
>   		if (len < 0) {
>   			dtag_nm = lpfc_get_tlv_dtag_nm(dtag);
>   			lpfc_printf_log(phba, KERN_WARNING, LOG_CGN_MGMT,
> diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
> index 082f76e76721..a62636c6f708 100644
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -750,13 +750,12 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats)
>    *
>    */
>   static void
> -fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
> +fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_fn_li_desc *li_desc)
>   {
>   	u8 i;
>   	struct fc_rport *rport = NULL;
>   	struct fc_rport *attach_rport = NULL;
>   	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
> -	struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
>   	u16 event_type = be16_to_cpu(li_desc->event_type);
>   	u64 wwpn;
>   
> @@ -799,12 +798,11 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
>    */
>   static void
>   fc_fpin_delivery_stats_update(struct Scsi_Host *shost,
> -			      struct fc_tlv_desc *tlv)
> +			      struct fc_fn_deli_desc *dn_desc)
>   {
>   	struct fc_rport *rport = NULL;
>   	struct fc_rport *attach_rport = NULL;
>   	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
> -	struct fc_fn_deli_desc *dn_desc = (struct fc_fn_deli_desc *)tlv;
>   	u32 reason_code = be32_to_cpu(dn_desc->deli_reason_code);
>   
>   	rport = fc_find_rport_by_wwpn(shost,
> @@ -830,13 +828,11 @@ fc_fpin_delivery_stats_update(struct Scsi_Host *shost,
>    */
>   static void
>   fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
> -				struct fc_tlv_desc *tlv)
> +				struct fc_fn_peer_congn_desc *pc_desc)
>   {
>   	u8 i;
>   	struct fc_rport *rport = NULL;
>   	struct fc_rport *attach_rport = NULL;
> -	struct fc_fn_peer_congn_desc *pc_desc =
> -	    (struct fc_fn_peer_congn_desc *)tlv;
>   	u16 event_type = be16_to_cpu(pc_desc->event_type);
>   	u64 wwpn;
>   
> @@ -876,10 +872,9 @@ fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
>    */
>   static void
>   fc_fpin_congn_stats_update(struct Scsi_Host *shost,
> -			   struct fc_tlv_desc *tlv)
> +			   struct fc_fn_congn_desc *congn)
>   {
>   	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
> -	struct fc_fn_congn_desc *congn = (struct fc_fn_congn_desc *)tlv;
>   
>   	fc_cn_stats_update(be16_to_cpu(congn->event_type),
>   			   &fc_host->fpin_stats);
> @@ -899,32 +894,32 @@ fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf,
>   		u8 event_acknowledge)
>   {
>   	struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf;
> -	struct fc_tlv_desc *tlv;
> +	union fc_tlv_desc *tlv;
>   	u32 bytes_remain;
>   	u32 dtag;
>   	enum fc_host_event_code event_code =
>   		event_acknowledge ? FCH_EVT_LINK_FPIN_ACK : FCH_EVT_LINK_FPIN;
>   
>   	/* Update Statistics */
> -	tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0];
> +	tlv = &fpin->fpin_desc[0];
>   	bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc);
>   	bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len));
>   
>   	while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
>   	       bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);
>   		switch (dtag) {
>   		case ELS_DTAG_LNK_INTEGRITY:
> -			fc_fpin_li_stats_update(shost, tlv);
> +			fc_fpin_li_stats_update(shost, &tlv->li);
>   			break;
>   		case ELS_DTAG_DELIVERY:
> -			fc_fpin_delivery_stats_update(shost, tlv);
> +			fc_fpin_delivery_stats_update(shost, &tlv->deli);
>   			break;
>   		case ELS_DTAG_PEER_CONGEST:
> -			fc_fpin_peer_congn_stats_update(shost, tlv);
> +			fc_fpin_peer_congn_stats_update(shost, &tlv->peer_congn);
>   			break;
>   		case ELS_DTAG_CONGESTION:
> -			fc_fpin_congn_stats_update(shost, tlv);
> +			fc_fpin_congn_stats_update(shost, &tlv->congn);
>   		}
>   
>   		bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
> diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h
> index 16782c360de3..3598dc553f4d 100644
> --- a/include/uapi/scsi/fc/fc_els.h
> +++ b/include/uapi/scsi/fc/fc_els.h
> @@ -253,12 +253,12 @@ enum fc_ls_tlv_dtag {
>   
>   
>   /*
> - * Generic Link Service TLV Descriptor format
> + * Generic Link Service TLV Descriptor header
>    *
>    * This structure, as it defines no payload, will also be referred to
>    * as the "tlv header" - which contains the tag and len fields.
>    */
> -struct fc_tlv_desc {
> +struct fc_tlv_desc_hdr {
>   	__be32		desc_tag;	/* Notification Descriptor Tag */
>   	__be32		desc_len;	/* Length of Descriptor (in bytes).
>   					 * Size of descriptor excluding
> @@ -267,36 +267,6 @@ struct fc_tlv_desc {
>   	__u8		desc_value[];  /* Descriptor Value */
>   };
>   
> -/* Descriptor tag and len fields are considered the mandatory header
> - * for a descriptor
> - */
> -#define FC_TLV_DESC_HDR_SZ	sizeof(struct fc_tlv_desc)
> -
> -/*
> - * Macro, used when initializing payloads, to return the descriptor length.
> - * Length is size of descriptor minus the tag and len fields.
> - */
> -#define FC_TLV_DESC_LENGTH_FROM_SZ(desc)	\
> -		(sizeof(desc) - FC_TLV_DESC_HDR_SZ)
> -
> -/* Macro, used on received payloads, to return the descriptor length */
> -#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv)		\
> -		(__be32_to_cpu((tlv)->desc_len) + FC_TLV_DESC_HDR_SZ)
> -
> -/*
> - * This helper is used to walk descriptors in a descriptor list.
> - * Given the address of the current descriptor, which minimally contains a
> - * tag and len field, calculate the address of the next descriptor based
> - * on the len field.
> - */
> -static inline void *fc_tlv_next_desc(void *desc)
> -{
> -	struct fc_tlv_desc *tlv = desc;
> -
> -	return (desc + FC_TLV_DESC_SZ_FROM_LENGTH(tlv));
> -}
> -
> -
>   /*
>    * Link Service Request Information Descriptor
>    */
> @@ -1094,19 +1064,6 @@ struct fc_fn_congn_desc {
>   	__u8		resv[3];	/* reserved - must be zero */
>   };
>   
> -/*
> - * ELS_FPIN - Fabric Performance Impact Notification
> - */
> -struct fc_els_fpin {
> -	__u8		fpin_cmd;	/* command (0x16) */
> -	__u8		fpin_zero[3];	/* specified as zero - part of cmd */
> -	__be32		desc_len;	/* Length of Descriptor List (in bytes).
> -					 * Size of ELS excluding fpin_cmd,
> -					 * fpin_zero and desc_len fields.
> -					 */
> -	struct fc_tlv_desc	fpin_desc[];	/* Descriptor list */
> -};
> -
>   /* Diagnostic Function Descriptor - FPIN Registration */
>   struct fc_df_desc_fpin_reg {
>   	__be32		desc_tag;	/* FPIN Registration (0x00030001) */
> @@ -1125,33 +1082,6 @@ struct fc_df_desc_fpin_reg {
>   					 */
>   };
>   
> -/*
> - * ELS_RDF - Register Diagnostic Functions
> - */
> -struct fc_els_rdf {
> -	__u8		fpin_cmd;	/* command (0x19) */
> -	__u8		fpin_zero[3];	/* specified as zero - part of cmd */
> -	__be32		desc_len;	/* Length of Descriptor List (in bytes).
> -					 * Size of ELS excluding fpin_cmd,
> -					 * fpin_zero and desc_len fields.
> -					 */
> -	struct fc_tlv_desc	desc[];	/* Descriptor list */
> -};
> -
> -/*
> - * ELS RDF LS_ACC Response.
> - */
> -struct fc_els_rdf_resp {
> -	struct fc_els_ls_acc	acc_hdr;
> -	__be32			desc_list_len;	/* Length of response (in
> -						 * bytes). Excludes acc_hdr
> -						 * and desc_list_len fields.
> -						 */
> -	struct fc_els_lsri_desc	lsri;
> -	struct fc_tlv_desc	desc[];	/* Supported Descriptor list */
> -};
> -
> -
>   /*
>    * Diagnostic Capability Descriptors for EDC ELS
>    */
> @@ -1221,6 +1151,65 @@ struct fc_diag_cg_sig_desc {
>   	struct fc_diag_cg_sig_freq	rcv_signal_frequency;
>   };
>   
> +/*
> + * Generic Link Service TLV Descriptor format
> + *
> + * This structure, as it defines no payload, will also be referred to
> + * as the "tlv header" - which contains the tag and len fields.
> + */
> +union fc_tlv_desc {
> +	struct fc_tlv_desc_hdr hdr;
> +	struct fc_els_lsri_desc lsri;
> +	struct fc_fn_li_desc li;
> +	struct fc_fn_deli_desc deli;
> +	struct fc_fn_peer_congn_desc peer_congn;
> +	struct fc_fn_congn_desc congn;
> +	struct fc_df_desc_fpin_reg fpin_reg;
> +	struct fc_diag_lnkflt_desc lnkflt;
> +	struct fc_diag_cg_sig_desc cg_sig;
> +};
> +
> +/* Descriptor tag and len fields are considered the mandatory header
> + * for a descriptor
> + */
> +#define FC_TLV_DESC_HDR_SZ	sizeof(struct fc_tlv_desc_hdr)
> +
> +/*
> + * Macro, used when initializing payloads, to return the descriptor length.
> + * Length is size of descriptor minus the tag and len fields.
> + */
> +#define FC_TLV_DESC_LENGTH_FROM_SZ(desc)	\
> +		(sizeof(desc) - FC_TLV_DESC_HDR_SZ)
> +
> +/* Macro, used on received payloads, to return the descriptor length */
> +#define FC_TLV_DESC_SZ_FROM_LENGTH(tlv)		\
> +		(__be32_to_cpu((tlv)->hdr.desc_len) + FC_TLV_DESC_HDR_SZ)
> +
> +/*
> + * This helper is used to walk descriptors in a descriptor list.
> + * Given the address of the current descriptor, which minimally contains a
> + * tag and len field, calculate the address of the next descriptor based
> + * on the len field.
> + */
> +static inline union fc_tlv_desc *fc_tlv_next_desc(union fc_tlv_desc *desc)
> +{
> +	return (union fc_tlv_desc *)((__u8 *)desc + FC_TLV_DESC_SZ_FROM_LENGTH(desc));
> +}
> +
> +
> +/*
> + * ELS_FPIN - Fabric Performance Impact Notification
> + */
> +struct fc_els_fpin {
> +	__u8		fpin_cmd;	/* command (0x16) */
> +	__u8		fpin_zero[3];	/* specified as zero - part of cmd */
> +	__be32		desc_len;	/* Length of Descriptor List (in bytes).
> +					 * Size of ELS excluding fpin_cmd,
> +					 * fpin_zero and desc_len fields.
> +					 */
> +	union fc_tlv_desc	fpin_desc[];	/* Descriptor list */
> +};
> +
>   /*
>    * ELS_EDC - Exchange Diagnostic Capabilities
>    */
> @@ -1231,10 +1220,37 @@ struct fc_els_edc {
>   					 * Size of ELS excluding edc_cmd,
>   					 * edc_zero and desc_len fields.
>   					 */
> -	struct fc_tlv_desc	desc[];
> +	union fc_tlv_desc	desc[];
>   					/* Diagnostic Descriptor list */
>   };
>   
> +/*
> + * ELS_RDF - Register Diagnostic Functions
> + */
> +struct fc_els_rdf {
> +	__u8		fpin_cmd;	/* command (0x19) */
> +	__u8		fpin_zero[3];	/* specified as zero - part of cmd */
> +	__be32		desc_len;	/* Length of Descriptor List (in bytes).
> +					 * Size of ELS excluding fpin_cmd,
> +					 * fpin_zero and desc_len fields.
> +					 */
> +	union fc_tlv_desc	desc[];	/* Descriptor list */
> +};
> +
> +/*
> + * ELS RDF LS_ACC Response.
> + */
> +struct fc_els_rdf_resp {
> +	struct fc_els_ls_acc	acc_hdr;
> +	__be32			desc_list_len;	/* Length of response (in
> +						 * bytes). Excludes acc_hdr
> +						 * and desc_list_len fields.
> +						 */
> +	struct fc_els_lsri_desc	lsri;
> +	union fc_tlv_desc	desc[];	/* Supported Descriptor list */
> +};
> +
> +
>   /*
>    * ELS EDC LS_ACC Response.
>    */
> @@ -1245,9 +1261,8 @@ struct fc_els_edc_resp {
>   						 * and desc_list_len fields.
>   						 */
>   	struct fc_els_lsri_desc	lsri;
> -	struct fc_tlv_desc	desc[];
> +	union fc_tlv_desc	desc[];
>   				    /* Supported Diagnostic Descriptor list */
>   };
>   
> -
>   #endif /* _FC_ELS_H_ */




More information about the Linux-nvme mailing list