Re: [PATCH 1/2] scsi: fc: Update statistics for host and rport on FPIN reception.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> On Jul 30, 2020, at 1:11 AM, Nilesh Javali <njavali@xxxxxxxxxxx> wrote:
> 
> From: Shyam Sundar <ssundar@xxxxxxxxxxx>
> 
> Add Fabric Performance Impact Notification (FPIN) stats structure to
> fc_host_attr and the fc_rport structures to maintain FPIN statistics
> for the respective entities when the LLD notifies the transport of an
> FPIN ELS.
> 
> Add sysfs nodes to display FPIN statistics
> 
> Specifically, this patch:
> 
> - Adds the formal definition of FPIN descriptors
> 	* Delivery Notification Descriptor
> 	* Peer Congestion Notification Descriptor
> 	* Congestion Notification Descriptor
> 
> - Adds the formal definition of the event types associated with them
> 
> - Adds a structure for holding fpin stats for host & rport
> 
> - Adds functions to parse the FPIN ELS and update the stats
> 
> - Adds sysfs nodes to maintain FPIN stats:
> 	/sys/class/fc_host/hostXX/statistics/
> 	/sys/class/fc_remote_ports/rport-XX\:Y-Z/statistics/
> 
> - Add stats for Congestion Signals, that are delivered to the host as
> interrupt signals, under fc_host_statistics.
> 
> Signed-off-by: Shyam Sundar <ssundar@xxxxxxxxxxx>
> Signed-off-by: Nilesh Javali <njavali@xxxxxxxxxxx>
> ---
> drivers/scsi/lpfc/lpfc_attr.c    |   2 +
> drivers/scsi/qla2xxx/qla_attr.c  |   2 +
> drivers/scsi/scsi_transport_fc.c | 410 ++++++++++++++++++++++++++++++-
> include/scsi/scsi_transport_fc.h |  34 ++-
> include/uapi/scsi/fc/fc_els.h    | 114 +++++++++
> 5 files changed, 559 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
> index a62c60ca6477..9fd35b90cb53 100644
> --- a/drivers/scsi/lpfc/lpfc_attr.c
> +++ b/drivers/scsi/lpfc/lpfc_attr.c
> @@ -7158,6 +7158,8 @@ struct fc_function_template lpfc_transport_functions = {
> 	.set_rport_dev_loss_tmo = lpfc_set_rport_loss_tmo,
> 	.show_rport_dev_loss_tmo = 1,
> 
> +	.show_rport_statistics = 1,
> +
> 	.get_starget_port_id  = lpfc_get_starget_port_id,
> 	.show_starget_port_id = 1,
> 
> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> index 5d93ccc73153..e34623b7cb6f 100644
> --- a/drivers/scsi/qla2xxx/qla_attr.c
> +++ b/drivers/scsi/qla2xxx/qla_attr.c
> @@ -3143,6 +3143,8 @@ struct fc_function_template qla2xxx_transport_functions = {
> 	.set_rport_dev_loss_tmo = qla2x00_set_rport_loss_tmo,
> 	.show_rport_dev_loss_tmo = 1,
> 
> +	.show_rport_statistics = 1,
> +
> 	.issue_fc_host_lip = qla2x00_issue_lip,
> 	.dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
> 	.terminate_rport_io = qla2x00_terminate_rport_io,
> diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
> index 2732fa65119c..587b610e13a2 100644
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -22,6 +22,7 @@
> #include <net/netlink.h>
> #include <scsi/scsi_netlink_fc.h>
> #include <scsi/scsi_bsg_fc.h>
> +#include <uapi/scsi/fc/fc_els.h>
> #include "scsi_priv.h"
> 
> static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
> @@ -33,6 +34,10 @@ static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *);
> static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *);
> static void fc_bsg_remove(struct request_queue *);
> static void fc_bsg_goose_queue(struct fc_rport *);
> +static void fc_li_stats_update(struct fc_fn_li_desc *li_desc,
> +			       struct fpin_stats *stats);
> +static void fc_deli_stats_update(u32 reason_code, struct fpin_stats *stats);
> +static void fc_cn_stats_update(u16 event_type, struct fpin_stats *stats);
> 
> /*
>  * Module Parameters
> @@ -418,6 +423,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
> 	fc_host->fabric_name = -1;
> 	memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name));
> 	memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname));
> +	memset(&fc_host->stats, 0, sizeof(struct fpin_stats));
> 
> 	fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN;
> 
> @@ -627,6 +633,266 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
> }
> EXPORT_SYMBOL(fc_host_post_vendor_event);
> 
> +/**
> + * fc_find_rport_by_wwpn - find the fc_rport pointer for a given wwpn
> + * @shost:		host the fc_rport is associated with
> + * @wwpn:		wwpn of the fc_rport device
> + *
> + * Notes:
> + *	This routine assumes no locks are held on entry.
> + */
> +struct fc_rport *
> +fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn)
> +{
> +	struct fc_rport *rport, *found = NULL;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(shost->host_lock, flags);
> +
> +	list_for_each_entry(rport, &fc_host_rports(shost), peers) {
> +		if (rport->scsi_target_id == -1)
> +			continue;
> +
> +		if (rport->port_state != FC_PORTSTATE_ONLINE)
> +			continue;
> +
> +		if (rport->port_name == wwpn)
> +			found = rport;
> +	}
> +
> +	spin_unlock_irqrestore(shost->host_lock, flags);
> +	return found;
> +}
> +EXPORT_SYMBOL(fc_find_rport_by_wwpn);
> +
> +static void
> +fc_li_stats_update(struct fc_fn_li_desc *li_desc,
> +		   struct fpin_stats *stats)
> +{
> +	switch (be16_to_cpu(li_desc->event_type)) {
> +	case FPIN_LI_UNKNOWN:
> +		stats->li_failure_unknown +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_LINK_FAILURE:
> +		stats->li_link_failure_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_LOSS_OF_SYNC:
> +		stats->li_loss_of_sync_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_LOSS_OF_SIG:
> +		stats->li_loss_of_signals_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_PRIM_SEQ_ERR:
> +		stats->li_prim_seq_err_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_INVALID_TX_WD:
> +		stats->li_invalid_tx_word_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_INVALID_CRC:
> +		stats->li_invalid_crc_count +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	case FPIN_LI_DEVICE_SPEC:
> +		stats->li_device_specific +=
> +		    be32_to_cpu(li_desc->event_count);
> +		break;
> +	}
> +}
> +
> +static void
> +fc_deli_stats_update(u32 deli_reason_code, struct fpin_stats *stats)
> +{
> +	switch (deli_reason_code) {
> +	case FPIN_DELI_UNKNOWN:
> +		stats->dn_unknown++;
> +		break;
> +	case FPIN_DELI_TIMEOUT:
> +		stats->dn_timeout++;
> +		break;
> +	case FPIN_DELI_UNABLE_TO_ROUTE:
> +		stats->dn_unable_to_route++;
> +		break;
> +	case FPIN_DELI_DEVICE_SPEC:
> +		stats->dn_device_specific++;
> +		break;
> +	}
> +}
> +
> +static void
> +fc_cn_stats_update(u16 event_type, struct fpin_stats *stats)
> +{
> +	switch (event_type) {
> +	case FPIN_CONGN_CLEAR:
> +		stats->cn_clear++;
> +		break;
> +	case FPIN_CONGN_LOST_CREDIT:
> +		stats->cn_lost_credit++;
> +		break;
> +	case FPIN_CONGN_CREDIT_STALL:
> +		stats->cn_credit_stall++;
> +		break;
> +	case FPIN_CONGN_OVERSUBSCRIPTION:
> +		stats->cn_oversubscription++;
> +		break;
> +	case FPIN_CONGN_DEVICE_SPEC:
> +		stats->cn_device_specific++;
> +	}
> +}
> +
> +/*
> + * fc_fpin_li_stats_update - routine to update Link Integrity
> + * event statistics.
> + * @shost:		host the FPIN was received on
> + * @tlv:		pointer to link integrity descriptor
> + *
> + */
> +static void
> +fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
> +{
> +	u8 i;
> +	struct fc_rport *rport = NULL;
> +	struct fc_rport *det_rport = NULL, *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;
> +	u64 wwpn;
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(li_desc->detecting_wwpn));
> +	if (rport) {
> +		det_rport = rport;
> +		fc_li_stats_update(li_desc, &det_rport->stats);
> +	}
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(li_desc->attached_wwpn));
> +	if (rport) {
> +		attach_rport = rport;
> +		fc_li_stats_update(li_desc, &attach_rport->stats);
> +	}
> +
> +	if (be32_to_cpu(li_desc->pname_count) > 0) {
> +		for (i = 0;
> +		    i < be32_to_cpu(li_desc->pname_count);
> +		    i++) {
> +			wwpn = be64_to_cpu(li_desc->pname_list[i]);
> +			rport = fc_find_rport_by_wwpn(shost, wwpn);
> +			if (rport && rport != det_rport &&
> +			    rport != attach_rport) {
> +				fc_li_stats_update(li_desc, &rport->stats);
> +			}
> +		}
> +	}
> +
> +	if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn))
> +		fc_li_stats_update(li_desc, &fc_host->stats);
> +}
> +
> +/*
> + * fc_fpin_deli_stats_update - routine to update Delivery Notification
> + * event statistics.
> + * @shost:		host the FPIN was received on
> + * @tlv:		pointer to delivery descriptor
> + *
> + */
> +static void
> +fc_fpin_deli_stats_update(struct Scsi_Host *shost,
> +			  struct fc_tlv_desc *tlv)
> +{
> +	struct fc_rport *rport = NULL;
> +	struct fc_rport *det_rport = NULL, *attach_rport = NULL;
> +	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
> +	struct fc_fn_deli_desc *deli_desc = (struct fc_fn_deli_desc *)tlv;
> +	u32 reason_code = be32_to_cpu(deli_desc->deli_reason_code);
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(deli_desc->detecting_wwpn));
> +	if (rport) {
> +		det_rport = rport;
> +		fc_deli_stats_update(reason_code, &det_rport->stats);
> +	}
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(deli_desc->attached_wwpn));
> +	if (rport) {
> +		attach_rport = rport;
> +		fc_deli_stats_update(reason_code, &attach_rport->stats);
> +	}
> +
> +	if (fc_host->port_name == be64_to_cpu(deli_desc->attached_wwpn))
> +		fc_deli_stats_update(reason_code, &fc_host->stats);
> +}
> +
> +/*
> + * fc_fpin_peer_congn_stats_update - routine to update Peer Congestion
> + * event statistics.
> + * @shost:		host the FPIN was received on
> + * @tlv:		pointer to peer congestion descriptor
> + *
> + */
> +static void
> +fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost,
> +				struct fc_tlv_desc *tlv)
> +{
> +	u8 i;
> +	struct fc_rport *rport = NULL;
> +	struct fc_rport *det_rport = NULL, *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;
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(pc_desc->detecting_wwpn));
> +	if (rport) {
> +		det_rport = rport;
> +		fc_cn_stats_update(event_type, &det_rport->stats);
> +	}
> +
> +	rport = fc_find_rport_by_wwpn(shost,
> +				      be64_to_cpu(pc_desc->attached_wwpn));
> +	if (rport) {
> +		attach_rport = rport;
> +		fc_cn_stats_update(event_type, &attach_rport->stats);
> +	}
> +
> +	if (be32_to_cpu(pc_desc->pname_count) > 0) {
> +		for (i = 0;
> +		    i < be32_to_cpu(pc_desc->pname_count);
> +		    i++) {
> +			wwpn = be64_to_cpu(pc_desc->pname_list[i]);
> +			rport = fc_find_rport_by_wwpn(shost, wwpn);
> +			if (rport && rport != det_rport &&
> +			    rport != attach_rport) {
> +				fc_cn_stats_update(event_type,
> +						   &rport->stats);
> +			}
> +		}
> +	}
> +}
> +
> +/*
> + * fc_fpin_congn_stats_update - routine to update Congestion
> + * event statistics.
> + * @shost:		host the FPIN was received on
> + * @tlv:		pointer to congestion descriptor
> + *
> + */
> +static void
> +fc_fpin_congn_stats_update(struct Scsi_Host *shost,
> +			   struct fc_tlv_desc *tlv)
> +{
> +	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->stats);
> +}
> +
> /**
>  * fc_host_rcv_fpin - routine to process a received FPIN.
>  * @shost:		host the FPIN was received on
> @@ -639,8 +905,41 @@ EXPORT_SYMBOL(fc_host_post_vendor_event);
> void
> fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf)
> {
> +	struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf;
> +	struct fc_tlv_desc *tlv;
> +	u32 desc_cnt = 0, bytes_remain;
> +	u32 dtag;
> +
> +	/* Update Statistics */
> +	tlv = (struct fc_tlv_desc *)&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);
> +		switch (dtag) {
> +		case ELS_DTAG_LNK_INTEGRITY:
> +			fc_fpin_li_stats_update(shost, tlv);
> +			break;
> +		case ELS_DTAG_DELIVERY:
> +			fc_fpin_deli_stats_update(shost, tlv);
> +			break;
> +		case ELS_DTAG_PEER_CONGEST:
> +			fc_fpin_peer_congn_stats_update(shost, tlv);
> +			break;
> +		case ELS_DTAG_CONGESTION:
> +			fc_fpin_congn_stats_update(shost, tlv);
> +		}
> +
> +		desc_cnt++;
> +		bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv);
> +		tlv = fc_tlv_next_desc(tlv);
> +	}
> +
> 	fc_host_post_fc_event(shost, fc_get_event_number(),
> -				FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0);
> +			      FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0);
> +
> }
> EXPORT_SYMBOL(fc_host_fpin_rcv);
> 
> @@ -990,6 +1289,61 @@ store_fc_rport_fast_io_fail_tmo(struct device *dev,
> static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR,
> 	show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo);
> 
> +#define fc_rport_fpin_statistic(name)					\
> +static ssize_t fc_rport_fpinstat_##name(struct device *cd,		\
> +				  struct device_attribute *attr,	\
> +				  char *buf)				\
> +{									\
> +	struct fc_rport *rport = transport_class_to_rport(cd);		\
> +									\
> +	return snprintf(buf, 20, "0x%llx\n", rport->stats.name);	\
> +}									\
> +static FC_DEVICE_ATTR(rport, fpin_##name, 0444, fc_rport_fpinstat_##name, NULL)
> +
> +fc_rport_fpin_statistic(dn_unknown);
> +fc_rport_fpin_statistic(dn_timeout);
> +fc_rport_fpin_statistic(dn_unable_to_route);
> +fc_rport_fpin_statistic(dn_device_specific);
> +fc_rport_fpin_statistic(cn_clear);
> +fc_rport_fpin_statistic(cn_lost_credit);
> +fc_rport_fpin_statistic(cn_credit_stall);
> +fc_rport_fpin_statistic(cn_oversubscription);
> +fc_rport_fpin_statistic(cn_device_specific);
> +fc_rport_fpin_statistic(li_failure_unknown);
> +fc_rport_fpin_statistic(li_link_failure_count);
> +fc_rport_fpin_statistic(li_loss_of_sync_count);
> +fc_rport_fpin_statistic(li_loss_of_signals_count);
> +fc_rport_fpin_statistic(li_prim_seq_err_count);
> +fc_rport_fpin_statistic(li_invalid_tx_word_count);
> +fc_rport_fpin_statistic(li_invalid_crc_count);
> +fc_rport_fpin_statistic(li_device_specific);
> +
> +static struct attribute *fc_rport_statistics_attrs[] = {
> +	&device_attr_rport_fpin_dn_unknown.attr,
> +	&device_attr_rport_fpin_dn_timeout.attr,
> +	&device_attr_rport_fpin_dn_unable_to_route.attr,
> +	&device_attr_rport_fpin_dn_device_specific.attr,
> +	&device_attr_rport_fpin_li_failure_unknown.attr,
> +	&device_attr_rport_fpin_li_link_failure_count.attr,
> +	&device_attr_rport_fpin_li_loss_of_sync_count.attr,
> +	&device_attr_rport_fpin_li_loss_of_signals_count.attr,
> +	&device_attr_rport_fpin_li_prim_seq_err_count.attr,
> +	&device_attr_rport_fpin_li_invalid_tx_word_count.attr,
> +	&device_attr_rport_fpin_li_invalid_crc_count.attr,
> +	&device_attr_rport_fpin_li_device_specific.attr,
> +	&device_attr_rport_fpin_cn_clear.attr,
> +	&device_attr_rport_fpin_cn_lost_credit.attr,
> +	&device_attr_rport_fpin_cn_credit_stall.attr,
> +	&device_attr_rport_fpin_cn_oversubscription.attr,
> +	&device_attr_rport_fpin_cn_device_specific.attr,
> +	NULL
> +};
> +
> +static struct attribute_group fc_rport_statistics_group = {
> +	.name = "statistics",
> +	.attrs = fc_rport_statistics_attrs,
> +};
> +
> 
> /*
>  * FC SCSI Target Attribute Management
> @@ -1743,6 +2097,38 @@ fc_host_statistic(fc_xid_not_found);
> fc_host_statistic(fc_xid_busy);
> fc_host_statistic(fc_seq_not_found);
> fc_host_statistic(fc_non_bls_resp);
> +fc_host_statistic(cn_sig_warn);
> +fc_host_statistic(cn_sig_alarm);
> +
> +#define fc_host_fpin_statistic(name)					\
> +static ssize_t fc_host_fpinstat_##name(struct device *cd,		\
> +				  struct device_attribute *attr,	\
> +				  char *buf)				\
> +{									\
> +	struct Scsi_Host *shost = transport_class_to_shost(cd);		\
> +	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);	\
> +									\
> +	return snprintf(buf, 20, "0x%llx\n", fc_host->stats.name);	\
> +}									\
> +static FC_DEVICE_ATTR(host, fpin_##name, 0444, fc_host_fpinstat_##name, NULL)
> +
> +fc_host_fpin_statistic(dn_unknown);
> +fc_host_fpin_statistic(dn_timeout);
> +fc_host_fpin_statistic(dn_unable_to_route);
> +fc_host_fpin_statistic(dn_device_specific);
> +fc_host_fpin_statistic(cn_clear);
> +fc_host_fpin_statistic(cn_lost_credit);
> +fc_host_fpin_statistic(cn_credit_stall);
> +fc_host_fpin_statistic(cn_oversubscription);
> +fc_host_fpin_statistic(cn_device_specific);
> +fc_host_fpin_statistic(li_failure_unknown);
> +fc_host_fpin_statistic(li_link_failure_count);
> +fc_host_fpin_statistic(li_loss_of_sync_count);
> +fc_host_fpin_statistic(li_loss_of_signals_count);
> +fc_host_fpin_statistic(li_prim_seq_err_count);
> +fc_host_fpin_statistic(li_invalid_tx_word_count);
> +fc_host_fpin_statistic(li_invalid_crc_count);
> +fc_host_fpin_statistic(li_device_specific);
> 
> static ssize_t
> fc_reset_statistics(struct device *dev, struct device_attribute *attr,
> @@ -1792,7 +2178,26 @@ static struct attribute *fc_statistics_attrs[] = {
> 	&device_attr_host_fc_xid_busy.attr,
> 	&device_attr_host_fc_seq_not_found.attr,
> 	&device_attr_host_fc_non_bls_resp.attr,
> +	&device_attr_host_cn_sig_warn.attr,
> +	&device_attr_host_cn_sig_alarm.attr,
> 	&device_attr_host_reset_statistics.attr,
> +	&device_attr_host_fpin_dn_unknown.attr,
> +	&device_attr_host_fpin_dn_timeout.attr,
> +	&device_attr_host_fpin_dn_unable_to_route.attr,
> +	&device_attr_host_fpin_dn_device_specific.attr,
> +	&device_attr_host_fpin_li_failure_unknown.attr,
> +	&device_attr_host_fpin_li_link_failure_count.attr,
> +	&device_attr_host_fpin_li_loss_of_sync_count.attr,
> +	&device_attr_host_fpin_li_loss_of_signals_count.attr,
> +	&device_attr_host_fpin_li_prim_seq_err_count.attr,
> +	&device_attr_host_fpin_li_invalid_tx_word_count.attr,
> +	&device_attr_host_fpin_li_invalid_crc_count.attr,
> +	&device_attr_host_fpin_li_device_specific.attr,
> +	&device_attr_host_fpin_cn_clear.attr,
> +	&device_attr_host_fpin_cn_lost_credit.attr,
> +	&device_attr_host_fpin_cn_credit_stall.attr,
> +	&device_attr_host_fpin_cn_oversubscription.attr,
> +	&device_attr_host_fpin_cn_device_specific.attr,
> 	NULL
> };
> 
> @@ -1801,7 +2206,6 @@ static struct attribute_group fc_statistics_group = {
> 	.attrs = fc_statistics_attrs,
> };
> 
> -
> /* Host Vport Attributes */
> 
> static int
> @@ -2176,6 +2580,8 @@ fc_attach_transport(struct fc_function_template *ft)
> 	i->rport_attr_cont.ac.attrs = &i->rport_attrs[0];
> 	i->rport_attr_cont.ac.class = &fc_rport_class.class;
> 	i->rport_attr_cont.ac.match = fc_rport_match;
> +	if (ft->show_rport_statistics)
> +		i->rport_attr_cont.statistics = &fc_rport_statistics_group;
> 	transport_container_register(&i->rport_attr_cont);
> 
> 	i->vport_attr_cont.ac.attrs = &i->vport_attrs[0];
> diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
> index 7db2dd783834..be7392ea9f91 100644
> --- a/include/scsi/scsi_transport_fc.h
> +++ b/include/scsi/scsi_transport_fc.h
> @@ -284,6 +284,33 @@ struct fc_rport_identifiers {
> 	u32 roles;
> };
> 
> +/*
> + * Fabric Performance Impact Notification Statistics
> + */
> +struct fpin_stats {
> +	/* Delivery */
> +	u64 dn_unknown;
> +	u64 dn_timeout;
> +	u64 dn_unable_to_route;
> +	u64 dn_device_specific;
> +
> +	/* Link Integrity */
> +	u64 li_failure_unknown;
> +	u64 li_link_failure_count;
> +	u64 li_loss_of_sync_count;
> +	u64 li_loss_of_signals_count;
> +	u64 li_prim_seq_err_count;
> +	u64 li_invalid_tx_word_count;
> +	u64 li_invalid_crc_count;
> +	u64 li_device_specific;
> +
> +	/* Congestion/Peer Congestion */
> +	u64 cn_clear;
> +	u64 cn_lost_credit;
> +	u64 cn_credit_stall;
> +	u64 cn_oversubscription;
> +	u64 cn_device_specific;
> +};
> 
> /* Macro for use in defining Remote Port attributes */
> #define FC_RPORT_ATTR(_name,_mode,_show,_store)				\
> @@ -325,6 +352,7 @@ struct fc_rport {	/* aka fc_starget_attrs */
> 
> 	/* Dynamic Attributes */
> 	u32 dev_loss_tmo;	/* Remote Port loss timeout in seconds. */
> +	struct fpin_stats stats;
> 
> 	/* Private (Transport-managed) Attributes */
> 	u64 node_name;
> @@ -394,7 +422,6 @@ struct fc_starget_attrs {	/* aka fc_target_attrs */
> #define starget_to_rport(s)			\
> 	scsi_is_fc_rport(s->dev.parent) ? dev_to_rport(s->dev.parent) : NULL
> 
> -
> /*
>  * FC Local Port (Host) Statistics
>  */
> @@ -436,6 +463,9 @@ struct fc_host_statistics {
> 	u64 fc_seq_not_found;		/* seq is not found for exchange */
> 	u64 fc_non_bls_resp;		/* a non BLS response frame with
> 					   a sequence responder in new exch */
> +	/* Host Congestion Signals */
> +	u64 cn_sig_warn;
> +	u64 cn_sig_alarm;
> };
> 
> 
> @@ -515,6 +545,7 @@ struct fc_host_attrs {
> 	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
> 	char system_hostname[FC_SYMBOLIC_NAME_SIZE];
> 	u32 dev_loss_tmo;
> +	struct fpin_stats stats;
> 
> 	/* Private (Transport-managed) Attributes */
> 	enum fc_tgtid_binding_type  tgtid_bind_type;
> @@ -667,6 +698,7 @@ struct fc_function_template {
> 	unsigned long	show_rport_maxframe_size:1;
> 	unsigned long	show_rport_supported_classes:1;
> 	unsigned long   show_rport_dev_loss_tmo:1;
> +	unsigned long	show_rport_statistics:1;
> 
> 	/*
> 	 * target dynamic attributes
> diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h
> index 8c704e510e39..d630692a6346 100644
> --- a/include/uapi/scsi/fc/fc_els.h
> +++ b/include/uapi/scsi/fc/fc_els.h
> @@ -917,6 +917,9 @@ enum fc_els_clid_ic {
> };
> 
> 
> +/*
> + * Link Integrity event types
> + */
> enum fc_fpin_li_event_types {
> 	FPIN_LI_UNKNOWN =		0x0,
> 	FPIN_LI_LINK_FAILURE =		0x1,
> @@ -943,6 +946,55 @@ enum fc_fpin_li_event_types {
> 	{ FPIN_LI_DEVICE_SPEC,		"Device Specific" },		\
> }
> 
> +/*
> + * Delivery event types
> + */
> +enum fc_fpin_deli_event_types {
> +	FPIN_DELI_UNKNOWN =		0x0,
> +	FPIN_DELI_TIMEOUT =		0x1,
> +	FPIN_DELI_UNABLE_TO_ROUTE =	0x2,
> +	FPIN_DELI_DEVICE_SPEC =		0xF,
> +};
> +
> +/*
> + * Initializer useful for decoding table.
> + * Please keep this in sync with the above definitions.
> + */
> +#define FC_FPIN_DELI_EVT_TYPES_INIT {					\
> +	{ FPIN_DELI_UNKNOWN,		"Unknown" },			\
> +	{ FPIN_DELI_TIMEOUT,		"Timeout" },			\
> +	{ FPIN_DELI_UNABLE_TO_ROUTE,	"Unable to Route" },		\
> +	{ FPIN_DELI_DEVICE_SPEC,	"Device Specific" },		\
> +}
> +
> +/*
> + * Congestion event types
> + */
> +enum fc_fpin_congn_event_types {
> +	FPIN_CONGN_CLEAR =		0x0,
> +	FPIN_CONGN_LOST_CREDIT =	0x1,
> +	FPIN_CONGN_CREDIT_STALL =	0x2,
> +	FPIN_CONGN_OVERSUBSCRIPTION =	0x3,
> +	FPIN_CONGN_DEVICE_SPEC =	0xF,
> +};
> +
> +/*
> + * Initializer useful for decoding table.
> + * Please keep this in sync with the above definitions.
> + */
> +#define FC_FPIN_CONGN_EVT_TYPES_INIT {					\
> +	{ FPIN_CONGN_CLEAR,		"Clear" },			\
> +	{ FPIN_CONGN_LOST_CREDIT,	"Lost Credit" },		\
> +	{ FPIN_CONGN_CREDIT_STALL,	"Credit Stall" },		\
> +	{ FPIN_CONGN_OVERSUBSCRIPTION,	"Oversubscription" },		\
> +	{ FPIN_CONGN_DEVICE_SPEC,	"Device Specific" },		\
> +}
> +
> +enum fc_fpin_congn_severity_types {
> +	FPIN_CONGN_SEVERITY_WARNING =	0xF1,
> +	FPIN_CONGN_SEVERITY_ERROR =	0xF7,
> +};
> +
> 
> /*
>  * Link Integrity Notification Descriptor
> @@ -974,6 +1026,68 @@ struct fc_fn_li_desc {
> 					 */
> };
> 
> +/*
> + * Delivery Notification Descriptor
> + */
> +struct fc_fn_deli_desc {
> +	__be32		desc_tag;	/* Descriptor Tag (0x00020002) */
> +	__be32		desc_len;	/* Length of Descriptor (in bytes).
> +					 * Size of descriptor excluding
> +					 * desc_tag and desc_len fields.
> +					 */
> +	__be64		detecting_wwpn;	/* Port Name that detected event */
> +	__be64		attached_wwpn;	/* Port Name of device attached to
> +					 * detecting Port Name
> +					 */
> +	__be32		deli_reason_code;/* see enum fc_fpin_deli_event_types */
> +};
> +
> +/*
> + * Peer Congestion Notification Descriptor
> + */
> +struct fc_fn_peer_congn_desc {
> +	__be32		desc_tag;	/* Descriptor Tag (0x00020003) */
> +	__be32		desc_len;	/* Length of Descriptor (in bytes).
> +					 * Size of descriptor excluding
> +					 * desc_tag and desc_len fields.
> +					 */
> +	__be64		detecting_wwpn;	/* Port Name that detected event */
> +	__be64		attached_wwpn;	/* Port Name of device attached to
> +					 * detecting Port Name
> +					 */
> +	__be16		event_type;	/* see enum fc_fpin_congn_event_types */
> +	__be16		event_modifier;	/* Implementation specific value
> +					 * describing the event type
> +					 */
> +	__be32		event_period;	/* duration (ms) of the detected
> +					 * congestion event
> +					 */
> +	__be32		pname_count;	/* number of portname_list elements */
> +	__be64		pname_list[0];	/* list of N_Port_Names accessible
> +					 * through the attached port
> +					 */
> +};
> +
> +/*
> + * Congestion Notification Descriptor
> + */
> +struct fc_fn_congn_desc {
> +	__be32		desc_tag;	/* Descriptor Tag (0x00020004) */
> +	__be32		desc_len;	/* Length of Descriptor (in bytes).
> +					 * Size of descriptor excluding
> +					 * desc_tag and desc_len fields.
> +					 */
> +	__be16		event_type;	/* see enum fc_fpin_congn_event_types */
> +	__be16		event_modifier;	/* Implementation specific value
> +					 * describing the event type
> +					 */
> +	__be32		event_period;	/* duration (ms) of the detected
> +					 * congestion event
> +					 */
> +	__u8		severity;	/* command */
> +	__u8		resv[3];	/* reserved - must be zero */
> +};
> +
> /*
>  * ELS_FPIN - Fabric Performance Impact Notification
>  */
> -- 
> 2.19.0.rc0
> 
Looks Good to me. 

Reviewed-by: Himanshu Madhani <himanshu.madhani@xxxxxxxxxx>

--
Himanshu Madhani	 Oracle Linux Engineering





[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux