Linux-SCSI Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support
@ 2020-05-14 10:10 Nilesh Javali
  2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Nilesh Javali @ 2020-05-14 10:10 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Martin,

Please apply the qla2xxx patch series implementing SAN Congestion Management
(SCM) support to the scsi tree at your earliest convenience.

Thanks,
Nilesh

Shyam Sundar (3):
  qla2xxx: Change in PUREX to handle FPIN ELS requests.
  qla2xxx: SAN congestion management(SCM) implementation.
  qla2xxx: Pass SCM counters to the application.

 drivers/scsi/qla2xxx/qla_bsg.c  | 114 ++++++
 drivers/scsi/qla2xxx/qla_bsg.h  | 118 ++++++
 drivers/scsi/qla2xxx/qla_dbg.c  |  13 +-
 drivers/scsi/qla2xxx/qla_def.h  | 106 +++++-
 drivers/scsi/qla2xxx/qla_fw.h   |   7 +-
 drivers/scsi/qla2xxx/qla_gbl.h  |   4 +-
 drivers/scsi/qla2xxx/qla_init.c |   9 +-
 drivers/scsi/qla2xxx/qla_isr.c  | 632 ++++++++++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_mbx.c  |  65 +++-
 drivers/scsi/qla2xxx/qla_os.c   |  37 +-
 10 files changed, 1039 insertions(+), 66 deletions(-)


base-commit: 47742bde281b2920aae8bb82ed2d61d890aa4f56
-- 
2.19.0.rc0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests.
  2020-05-14 10:10 [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Nilesh Javali
@ 2020-05-14 10:10 ` Nilesh Javali
  2020-05-14 17:03   ` himanshu.madhani
  2020-05-15 18:52   ` James Smart
  2020-05-14 10:10 ` [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation Nilesh Javali
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 15+ messages in thread
From: Nilesh Javali @ 2020-05-14 10:10 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Shyam Sundar <ssundar@marvell.com>

SAN Congestion Management generates ELS pkts whose size
can vary, and be > 64 bytes. Change the purex
handling code to support non standard ELS pkt size.

Signed-off-by: Shyam Sundar <ssundar@marvell.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h |  17 ++++-
 drivers/scsi/qla2xxx/qla_gbl.h |   3 +-
 drivers/scsi/qla2xxx/qla_isr.c | 116 ++++++++++++++++++++++++---------
 drivers/scsi/qla2xxx/qla_mbx.c |  22 +++++--
 drivers/scsi/qla2xxx/qla_os.c  |  19 ++++--
 5 files changed, 136 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 172ea4e5887d..954d1a230b8a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1270,6 +1270,11 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
 
 #define ELS_CMD_MAP_SIZE	32
 #define ELS_COMMAND_RDP		0x18
+/* Fabric Perf Impact Notification */
+#define ELS_COMMAND_FPIN	0x16
+/* Read Diagnostic Functions */
+#define ELS_COMMAND_RDF		0x19
+#define ELS_COMMAND_PUN		0x31
 
 /*
  * Firmware state codes from get firmware state mailbox command
@@ -4487,10 +4492,19 @@ struct active_regions {
 #define QLA_SET_DATA_RATE_NOLR	1
 #define QLA_SET_DATA_RATE_LR	2 /* Set speed and initiate LR */
 
+#define QLA_DEFAULT_PAYLOAD_SIZE	64
+/*
+ * This item might be allocated with a size > sizeof(struct purex_item).
+ * The "size" variable gives the size of the payload (which
+ * is variable) starting at "iocb".
+ */
 struct purex_item {
 	struct list_head list;
 	struct scsi_qla_host *vha;
-	void (*process_item)(struct scsi_qla_host *vha, void *pkt);
+	void (*process_item)(struct scsi_qla_host *vha,
+			     struct purex_item *pkt);
+	atomic_t in_use;
+	uint16_t size;
 	struct {
 		uint8_t iocb[64];
 	} iocb;
@@ -4690,6 +4704,7 @@ typedef struct scsi_qla_host {
 		struct list_head head;
 		spinlock_t lock;
 	} purex_list;
+	struct purex_item default_item;
 
 	struct name_list_extended gnl;
 	/* Count of active session/fcport */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index f62b71e47581..54d82f7d478f 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -229,7 +229,8 @@ void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
 int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
 void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *);
-void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt);
+void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
+			       struct purex_item *pkt);
 
 /*
  * Global Functions in qla_mid.c source file.
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a9e8513e1cf1..401ce0023cd5 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -31,35 +31,11 @@ const char *const port_state_str[] = {
 	"ONLINE"
 };
 
-static void qla24xx_purex_iocb(scsi_qla_host_t *vha, void *pkt,
-	void (*process_item)(struct scsi_qla_host *vha, void *pkt))
-{
-	struct purex_list *list = &vha->purex_list;
-	struct purex_item *item;
-	ulong flags;
-
-	item = kzalloc(sizeof(*item), GFP_KERNEL);
-	if (!item) {
-		ql_log(ql_log_warn, vha, 0x5092,
-		    ">> Failed allocate purex list item.\n");
-		return;
-	}
-
-	item->vha = vha;
-	item->process_item = process_item;
-	memcpy(&item->iocb, pkt, sizeof(item->iocb));
-
-	spin_lock_irqsave(&list->lock, flags);
-	list_add_tail(&item->list, &list->head);
-	spin_unlock_irqrestore(&list->lock, flags);
-
-	set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
-}
-
 static void
-qla24xx_process_abts(struct scsi_qla_host *vha, void *pkt)
+qla24xx_process_abts(struct scsi_qla_host *vha, struct purex_item *pkt)
 {
-	struct abts_entry_24xx *abts = pkt;
+	struct abts_entry_24xx *abts =
+	    (struct abts_entry_24xx *)&pkt->iocb;
 	struct qla_hw_data *ha = vha->hw;
 	struct els_entry_24xx *rsp_els;
 	struct abts_entry_24xx *abts_rsp;
@@ -790,6 +766,76 @@ qla27xx_handle_8200_aen(scsi_qla_host_t *vha, uint16_t *mb)
 	}
 }
 
+struct purex_item *
+qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
+{
+	struct purex_item *item = NULL;
+	uint8_t item_hdr_size = sizeof(*item);
+	uint8_t default_usable = 0;
+
+	if (size > QLA_DEFAULT_PAYLOAD_SIZE) {
+		item = kzalloc(item_hdr_size +
+		    (size - QLA_DEFAULT_PAYLOAD_SIZE), GFP_ATOMIC);
+	} else {
+		item = kzalloc(item_hdr_size, GFP_ATOMIC);
+		default_usable = 1;
+	}
+	if (!item) {
+		if (default_usable &&
+		    (atomic_inc_return(&vha->default_item.in_use) == 1)) {
+			item = &vha->default_item;
+			goto initialize_purex_header;
+		}
+		ql_log(ql_log_warn, vha, 0x5092,
+		       ">> Failed allocate purex list item.\n");
+
+		return NULL;
+	}
+
+initialize_purex_header:
+	item->vha = vha;
+	item->size = size;
+	return item;
+}
+
+static void
+qla24xx_queue_purex_item(scsi_qla_host_t *vha, struct purex_item *pkt,
+			 void (*process_item)(struct scsi_qla_host *vha,
+					      struct purex_item *pkt))
+{
+	struct purex_list *list = &vha->purex_list;
+	ulong flags;
+
+	pkt->process_item = process_item;
+
+	spin_lock_irqsave(&list->lock, flags);
+	list_add_tail(&pkt->list, &list->head);
+	spin_unlock_irqrestore(&list->lock, flags);
+
+	set_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags);
+}
+
+/**
+ * qla24xx_copy_std_pkt() - Copy over purex ELS which is
+ * contained in a single IOCB.
+ * purex packet.
+ * @vha: SCSI driver HA context
+ * @pkt: ELS packet
+ */
+struct purex_item
+*qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt)
+{
+	struct purex_item *item;
+
+	item = qla24xx_alloc_purex_item(vha,
+					QLA_DEFAULT_PAYLOAD_SIZE);
+	if (!item)
+		return item;
+
+	memcpy(&item->iocb, pkt, sizeof(item->iocb));
+	return item;
+}
+
 /**
  * qla2x00_async_event() - Process aynchronous events.
  * @vha: SCSI driver HA context
@@ -3233,6 +3279,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 {
 	struct sts_entry_24xx *pkt;
 	struct qla_hw_data *ha = vha->hw;
+	struct purex_item *pure_item;
 
 	if (!ha->flags.fw_started)
 		return;
@@ -3284,8 +3331,12 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			break;
 		case ABTS_RECV_24XX:
 			if (qla_ini_mode_enabled(vha)) {
-				qla24xx_purex_iocb(vha, pkt,
-				    qla24xx_process_abts);
+				pure_item = qla24xx_copy_std_pkt(vha, pkt);
+				if (!pure_item)
+					break;
+
+				qla24xx_queue_purex_item(vha, pure_item,
+							 qla24xx_process_abts);
 				break;
 			}
 			if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
@@ -3342,7 +3393,12 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 				    purex->els_frame_payload[3]);
 				break;
 			}
-			qla24xx_purex_iocb(vha, pkt, qla24xx_process_purex_rdp);
+			pure_item = qla24xx_copy_std_pkt(vha, pkt);
+			if (!pure_item)
+				break;
+
+			qla24xx_queue_purex_item(vha, pure_item,
+						 qla24xx_process_purex_rdp);
 			break;
 		}
 		default:
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 9fd83d1bffe0..76a4f2bfdbed 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -59,6 +59,7 @@ static struct rom_cmd {
 	{ MBC_IOCB_COMMAND_A64 },
 	{ MBC_GET_ADAPTER_LOOP_ID },
 	{ MBC_READ_SFP },
+	{ MBC_SET_RNID_PARAMS },
 	{ MBC_GET_RNID_PARAMS },
 	{ MBC_GET_SET_ZIO_THRESHOLD },
 };
@@ -4867,6 +4868,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
 	return rval;
 }
 
+#define PUREX_CMD_COUNT	3
 int
 qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
 {
@@ -4875,12 +4877,12 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
 	mbx_cmd_t *mcp = &mc;
 	uint8_t *els_cmd_map;
 	dma_addr_t els_cmd_map_dma;
-	uint cmd_opcode = ELS_COMMAND_RDP;
-	uint index = cmd_opcode / 8;
-	uint bit = cmd_opcode % 8;
+	uint cmd_opcode[PUREX_CMD_COUNT];
+	uint i, index, purex_bit;
 	struct qla_hw_data *ha = vha->hw;
 
-	if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha))
+	if (!IS_QLA25XX(ha) && !IS_QLA2031(ha) &&
+	    !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
 		return QLA_SUCCESS;
 
 	ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1197,
@@ -4896,7 +4898,17 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
 
 	memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE);
 
-	els_cmd_map[index] |= 1 << bit;
+	memset(els_cmd_map, 0, ELS_CMD_MAP_SIZE);
+
+	/* List of Purex ELS */
+	cmd_opcode[0] = ELS_COMMAND_FPIN;
+	cmd_opcode[1] = ELS_COMMAND_PUN;
+
+	for (i = 0; i < PUREX_CMD_COUNT; i++) {
+		index = cmd_opcode[i] / 8;
+		purex_bit = cmd_opcode[i] % 8;
+		els_cmd_map[index] |= 1 << purex_bit;
+	}
 
 	mcp->mb[0] = MBC_SET_RNID_PARAMS;
 	mcp->mb[1] = RNID_TYPE_ELS_CMD << 8;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 382e1f977d01..007f39128dbf 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5891,10 +5891,12 @@ qla25xx_rdp_port_speed_currently(struct qla_hw_data *ha)
  * vha:	SCSI qla host
  * purex: RDP request received by HBA
  */
-void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
+void qla24xx_process_purex_rdp(struct scsi_qla_host *vha,
+			       struct purex_item *item)
 {
 	struct qla_hw_data *ha = vha->hw;
-	struct purex_entry_24xx *purex = pkt;
+	struct purex_entry_24xx *purex =
+	    (struct purex_entry_24xx *)&item->iocb;
 	dma_addr_t rsp_els_dma;
 	dma_addr_t rsp_payload_dma;
 	dma_addr_t stat_dma;
@@ -6304,6 +6306,15 @@ void qla24xx_process_purex_rdp(struct scsi_qla_host *vha, void *pkt)
 		    rsp_els, rsp_els_dma);
 }
 
+void
+qla24xx_free_purex_item(struct purex_item *item)
+{
+	if (item == &item->vha->default_item)
+		memset(&item->vha->default_item, 0, sizeof(struct purex_item));
+	else
+		kfree(item);
+}
+
 void qla24xx_process_purex_list(struct purex_list *list)
 {
 	struct list_head head = LIST_HEAD_INIT(head);
@@ -6316,8 +6327,8 @@ void qla24xx_process_purex_list(struct purex_list *list)
 
 	list_for_each_entry_safe(item, next, &head, list) {
 		list_del(&item->list);
-		item->process_item(item->vha, &item->iocb);
-		kfree(item);
+		item->process_item(item->vha, item);
+		qla24xx_free_purex_item(item);
 	}
 }
 
-- 
2.19.0.rc0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-05-14 10:10 [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Nilesh Javali
  2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
@ 2020-05-14 10:10 ` Nilesh Javali
  2020-05-14 18:52   ` himanshu.madhani
  2020-05-15 22:48   ` James Smart
  2020-05-14 10:10 ` [PATCH 3/3] qla2xxx: Pass SCM counters to the application Nilesh Javali
  2020-05-14 14:11 ` [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Bart Van Assche
  3 siblings, 2 replies; 15+ messages in thread
From: Nilesh Javali @ 2020-05-14 10:10 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Shyam Sundar <ssundar@marvell.com>

* Firmware Initialization with SCM enabled based on NVRAM setting and
  firmware support (About Firmware).
* Enable PUREX and add support for fabric performance impact
  notification(FPIN) handling.
* Support for the following FPIN descriptors:
  	1. Link Integrity Notification.
	2. Delivery Notification.
	3. Peer Congestion Notification.
	4. Congestion Notification.
* Mark a device as slow when a Peer Congestion Notification is received.
* Allocate a default purex item for each vha, to handle memory
  allocation failures in ISR.

Signed-off-by: Shyam Sundar <ssundar@marvell.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_bsg.h  | 115 +++++++
 drivers/scsi/qla2xxx/qla_dbg.c  |  13 +-
 drivers/scsi/qla2xxx/qla_def.h  |  89 ++++++
 drivers/scsi/qla2xxx/qla_fw.h   |   7 +-
 drivers/scsi/qla2xxx/qla_gbl.h  |   1 +
 drivers/scsi/qla2xxx/qla_init.c |   9 +-
 drivers/scsi/qla2xxx/qla_isr.c  | 532 ++++++++++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_mbx.c  |  45 ++-
 drivers/scsi/qla2xxx/qla_os.c   |  18 ++
 9 files changed, 795 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 7594fad7b5b5..0b308859047c 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -290,4 +290,119 @@ struct qla_active_regions {
 	uint8_t reserved[32];
 } __packed;
 
+#define SCM_LINK_EVENT_UNKNOWN			0x0
+#define SCM_LINK_EVENT_LINK_FAILURE			0x1
+#define SCM_LINK_EVENT_LOSS_OF_SYNC			0x2
+#define SCM_LINK_EVENT_LOSS_OF_SIGNAL		0x3
+#define SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR	0x4
+#define SCM_LINK_EVENT_INVALID_TX_WORD		0x5
+#define SCM_LINK_EVENT_INVALID_CRC			0x6
+#define SCM_LINK_EVENT_DEVICE_SPECIFIC		0xF
+#define SCM_LINK_EVENT_V1_SIZE			20
+struct qla_scm_link_event {
+	uint64_t	timestamp;
+	uint16_t	event_type;
+	uint16_t	event_modifier;
+	uint32_t	event_threshold;
+	uint32_t	event_count;
+	uint8_t		reserved[12];
+} __packed;
+
+#define SCM_DELIVERY_REASON_UNKNOWN		0x0
+#define SCM_DELIVERY_REASON_TIMEOUT		0x1
+#define SCM_DELIVERY_REASON_UNABLE_TO_ROUTE	0x2
+#define SCM_DELIVERY_REASON_DEVICE_SPECIFIC	0xF
+struct qla_scm_delivery_event {
+	uint64_t	timestamp;
+	uint32_t	delivery_reason;
+	uint8_t		deliver_frame_hdr[24];
+	uint8_t		reserved[28];
+
+} __packed;
+
+#define SCM_CONGESTION_EVENT_CLEAR		0x0
+#define SCM_CONGESTION_EVENT_LOST_CREDIT	0x1
+#define SCM_CONGESTION_EVENT_CREDIT_STALL	0x2
+#define SCM_CONGESTION_EVENT_OVERSUBSCRIPTION	0x3
+#define SCM_CONGESTION_EVENT_DEVICE_SPECIFIC	0xF
+struct qla_scm_peer_congestion_event {
+	uint64_t	timestamp;
+	uint16_t	event_type;
+	uint16_t	event_modifier;
+	uint32_t	event_period;
+	uint8_t		reserved[16];
+} __packed;
+
+#define SCM_CONGESTION_SEVERITY_WARNING	0xF1
+#define SCM_CONGESTION_SEVERITY_ERROR	0xF7
+struct qla_scm_congestion_event {
+	uint64_t	timestamp;
+	uint16_t	event_type;
+	uint16_t	event_modifier;
+	uint32_t	event_period;
+	uint8_t		severity;
+	uint8_t		reserved[15];
+} __packed;
+
+#define SCM_FLAG_RDF_REJECT		0x00
+#define SCM_FLAG_RDF_COMPLETED		0x01
+#define SCM_FLAG_BROCADE_CONNECTED	0x02
+#define SCM_FLAG_CISCO_CONNECTED	0x04
+
+#define SCM_STATE_CONGESTION	0x1
+#define SCM_STATE_DELIVERY		0x2
+#define SCM_STATE_LINK_INTEGRITY	0x4
+#define SCM_STATE_PEER_CONGESTION	0x8
+
+#define QLA_CON_PRIMITIVE_RECEIVED	0x1
+#define QLA_CONGESTION_ARB_WARNING	0x1
+#define QLA_CONGESTION_ARB_ALARM	0X2
+struct qla_scm_port {
+	uint32_t			current_events;
+
+	struct qla_scm_link_event	link_integrity;
+	struct qla_scm_delivery_event	delivery;
+	struct qla_scm_congestion_event	congestion;
+	uint64_t			scm_congestion_alarm;
+	uint64_t			scm_congestion_warning;
+	uint8_t				scm_fabric_connection_flags;
+	uint8_t				reserved[43];
+} __packed;
+
+struct qla_scm_target {
+	uint8_t		wwpn[8];
+	uint32_t	current_events;
+
+	struct qla_scm_link_event		link_integrity;
+	struct qla_scm_delivery_event		delivery;
+	struct qla_scm_peer_congestion_event	peer_congestion;
+
+	uint32_t	link_failure_count;
+	uint32_t	loss_of_sync_count;
+	uint32_t        loss_of_signals_count;
+	uint32_t        primitive_seq_protocol_err_count;
+	uint32_t        invalid_transmission_word_count;
+	uint32_t        invalid_crc_count;
+
+	uint32_t        delivery_failure_unknown;
+	uint32_t        delivery_timeout;
+	uint32_t        delivery_unable_to_route;
+	uint32_t        delivery_failure_device_specific;
+
+	uint32_t        peer_congestion_clear;
+	uint32_t        peer_congestion_lost_credit;
+	uint32_t        peer_congestion_credit_stall;
+	uint32_t        peer_congestion_oversubscription;
+	uint32_t        peer_congestion_device_specific;
+	uint32_t	link_unknown_event;
+	uint32_t	link_device_specific_event;
+	uint8_t		reserved[48];
+} __packed;
+
+#define QLA_DRV_ATTR_SCM_SUPPORTED	0x00800000
+struct qla_drv_attr {
+	uint32_t	attributes;
+	uint8_t		reserved[28];
+} __packed;
+
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 1206f7c1ce6a..8af26be684d4 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -11,10 +11,8 @@
  * ----------------------------------------------------------------------
  * |             Level            |   Last Value Used  |     Holes	|
  * ----------------------------------------------------------------------
- * | Module Init and Probe        |       0x0193       | 0x0146         |
- * |                              |                    | 0x015b-0x0160	|
- * |                              |                    | 0x016e		|
- * | Mailbox commands             |       0x1206       | 0x11a2-0x11ff	|
+ * | Module Init and Probe        |       0x0199       |                |
+ * | Mailbox commands             |       0x1206       | 0x11a5-0x11ff	|
  * | Device Discovery             |       0x2134       | 0x210e-0x2116  |
  * |				  | 		       | 0x211a         |
  * |                              |                    | 0x211c-0x2128  |
@@ -26,11 +24,7 @@
  * |                              |                    | 0x3036,0x3038  |
  * |                              |                    | 0x303a		|
  * | DPC Thread                   |       0x4023       | 0x4002,0x4013  |
- * | Async Events                 |       0x5090       | 0x502b-0x502f  |
- * |				  | 		       | 0x5047         |
- * |                              |                    | 0x5084,0x5075	|
- * |                              |                    | 0x503d,0x5044  |
- * |                              |                    | 0x505f		|
+ * | Async Events                 |       0x509c       |                |
  * | Timer Routines               |       0x6012       |                |
  * | User Space Interactions      |       0x70e3       | 0x7018,0x702e  |
  * |				  |		       | 0x7020,0x7024  |
@@ -2752,7 +2746,6 @@ ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id)
 		    "mbox[%d] %#04x\n", i, RD_REG_WORD(mbx_reg));
 }
 
-
 void
 ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, const void *buf,
 	       uint size)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 954d1a230b8a..882961d7246b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1018,6 +1018,7 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
 #define MBA_LIP_F8		0x8016	/* Received a LIP F8. */
 #define MBA_LOOP_INIT_ERR	0x8017	/* Loop Initialization Error. */
 #define MBA_FABRIC_AUTH_REQ	0x801b	/* Fabric Authentication Required. */
+#define MBA_CONGN_NOTI_RECV	0x801e	/* Congestion Notification Received */
 #define MBA_SCSI_COMPLETION	0x8020	/* SCSI Command Complete. */
 #define MBA_CTIO_COMPLETION	0x8021	/* CTIO Complete. */
 #define MBA_IP_COMPLETION	0x8022	/* IP Transmit Command Complete. */
@@ -1479,6 +1480,25 @@ typedef struct {
 	uint8_t  reserved_3[26];
 } init_cb_t;
 
+/* Special Features Control Block */
+struct init_sf_cb {
+	uint8_t	format;
+	uint8_t	reserved0;
+	/*
+	 * BIT 15-14 = Reserved
+	 * BIT_13 = SAN Congestion Management (1 - Enabled, 0 - Disabled)
+	 * BIT_12 = Remote Write Optimization (1 - Enabled, 0 - Disabled)
+	 * BIT 11-0 = Reserved
+	 */
+	uint16_t flags;
+	uint8_t	reserved1[32];
+	uint16_t discard_OHRB_timeout_value;
+	uint16_t remote_write_opt_queue_num;
+	uint8_t	reserved2[40];
+	uint8_t scm_related_parameter[16];
+	uint8_t reserved3[32];
+};
+
 /*
  * Get Link Status mailbox command return buffer.
  */
@@ -2152,6 +2172,52 @@ typedef struct {
 	struct dsd64 rsp_dsd;
 } ms_iocb_entry_t;
 
+#define SCM_EDC_ACC_RECEIVED		BIT_6
+#define SCM_RDF_ACC_RECEIVED		BIT_7
+#define SCM_NOTIFICATION_TYPE_LINK_INTEGRITY	0x00020001
+#define SCM_NOTIFICATION_TYPE_DELIVERY		0x00020002
+#define SCM_NOTIFICATION_TYPE_PEER_CONGESTION	0x00020003
+#define SCM_NOTIFICATION_TYPE_CONGESTION	0x00020004
+#define FPIN_DESCRIPTOR_HEADER_SIZE	4
+#define FPIN_ELS_DESCRIPTOR_LIST_OFFSET	8
+struct fpin_descriptor {
+	__be32 descriptor_tag;
+	__be32 descriptor_length;
+	union {
+		uint8_t common_detecting_port_name[WWN_SIZE];
+		struct {
+			uint8_t detecting_port_name[WWN_SIZE];
+			uint8_t attached_port_name[WWN_SIZE];
+			__be16 event_type;
+			__be16 event_modifier;
+			__be32 event_threshold;
+			__be32 event_count;
+			__be32 port_name_count;
+			uint8_t port_name_list[1][WWN_SIZE];
+		} link_integrity;
+		struct {
+			uint8_t detecting_port_name[WWN_SIZE];
+			uint8_t attached_port_name[WWN_SIZE];
+			__be32 delivery_reason_code;
+		} delivery;
+		struct {
+			uint8_t detecting_port_name[WWN_SIZE];
+			uint8_t attached_port_name[WWN_SIZE];
+			__be16 event_type;
+			__be16 event_modifier;
+			__be32 event_period;
+			__be32 port_name_count;
+			uint8_t port_name_list[1][WWN_SIZE];
+		} peer_congestion;
+		struct {
+			__be16 event_type;
+			__be16 event_modifier;
+			__be32 event_period;
+			uint8_t severity;
+			uint8_t reserved[3];
+		} congestion;
+	};
+};
 
 /*
  * ISP queue - Mailbox Command entry structure definition.
@@ -2412,6 +2478,7 @@ typedef struct fc_port {
 	unsigned int n2n_flag:1;
 	unsigned int explicit_logout:1;
 	unsigned int prli_pend_timer:1;
+	unsigned int slow_device:1;
 
 	struct completion nvme_del_done;
 	uint32_t nvme_prli_service_param;
@@ -2491,6 +2558,8 @@ typedef struct fc_port {
 	u8 last_login_state;
 	u16 n2n_link_reset_cnt;
 	u16 n2n_chip_reset;
+
+	struct qla_scm_target scm_stats;
 } fc_port_t;
 
 enum {
@@ -3821,6 +3890,12 @@ struct qla_hw_data {
 		uint32_t        n2n_bigger:1;
 		uint32_t	secure_adapter:1;
 		uint32_t	secure_fw:1;
+				/* Supported by Adapter */
+		uint32_t	scm_supported_a:1;
+				/* Supported by Firmware */
+		uint32_t	scm_supported_f:1;
+				/* Enabled in Driver */
+		uint32_t	scm_enabled:1;
 	} flags;
 
 	uint16_t max_exchg;
@@ -4138,6 +4213,13 @@ struct qla_hw_data {
 	int		init_cb_size;
 	dma_addr_t	ex_init_cb_dma;
 	struct ex_init_cb_81xx *ex_init_cb;
+	dma_addr_t	sf_init_cb_dma;
+	struct init_sf_cb *sf_init_cb;
+
+	void		*scm_fpin_els_buff;
+	uint64_t	scm_fpin_els_buff_size;
+	bool		scm_fpin_valid;
+	bool		scm_fpin_payload_size;
 
 	void		*async_pd;
 	dma_addr_t	async_pd_dma;
@@ -4200,6 +4282,12 @@ struct qla_hw_data {
 #define FW_ATTR_H_NVME		BIT_10
 #define FW_ATTR_H_NVME_UPDATED  BIT_14
 
+	/* About firmware SCM support */
+#define FW_ATTR_EXT0_SCM_SUPPORTED	BIT_12
+	/* Brocade fabric attached */
+#define FW_ATTR_EXT0_SCM_BROCADE	0x00001000
+	/* Cisco fabric attached */
+#define FW_ATTR_EXT0_SCM_CISCO		0x00002000
 	uint16_t	fw_attributes_ext[2];
 	uint32_t	fw_memory_size;
 	uint32_t	fw_transfer_size;
@@ -4718,6 +4806,7 @@ typedef struct scsi_qla_host {
 	__le16 dport_data[4];
 	struct list_head gpnid_list;
 	struct fab_scan scan;
+	struct qla_scm_port scm_stats;
 
 	unsigned int irq_offset;
 } scsi_qla_host_t;
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index f9bad5bd7198..fa45fc7e6e2b 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -723,6 +723,9 @@ struct ct_entry_24xx {
 	struct dsd64 dsd[2];
 };
 
+#define PURX_ELS_HEADER_SIZE	0x18
+#define FPIN_ELS_DESCRIPTOR_LIST_OFFSET	8
+
 /*
  * ISP queue - PUREX IOCB entry structure definition
  */
@@ -2020,7 +2023,9 @@ struct nvram_81xx {
 	 * BIT 0    = Extended BB credits for LR
 	 * BIT 1    = Virtual Fabric Enable
 	 * BIT 2-5  = Distance Support if BIT 0 is on
-	 * BIT 6-15 = Unused
+	 * BIT 6    = Prefer FCP
+	 * BIT 7    = SCM Disabled if BIT is set (1)
+	 * BIT 8-15 = Unused
 	 */
 	uint16_t enhanced_features;
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 54d82f7d478f..3ba21368d5b6 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -127,6 +127,7 @@ int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
 void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
 int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *);
 void qla_rscn_replay(fc_port_t *fcport);
+void qla24xx_free_purex_item(struct purex_item *item);
 extern bool qla24xx_risc_firmware_invalid(uint32_t *);
 
 /*
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 95b6166ae0cc..dcadf1719711 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3752,7 +3752,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
 		}
 
 		/* Enable PUREX PASSTHRU */
-		if (ql2xrdpenable)
+		if (ql2xrdpenable || ha->flags.scm_supported_f)
 			qla25xx_set_els_cmds_supported(vha);
 	} else
 		goto failed;
@@ -3965,7 +3965,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
 			ha->fw_options[2] &= ~BIT_8;
 	}
 
-	if (ql2xrdpenable)
+	if (ql2xrdpenable || ha->flags.scm_supported_f)
 		ha->fw_options[1] |= ADD_FO1_ENABLE_PUREX_IOCB;
 
 	/* Enable Async 8130/8131 events -- transceiver insertion/removal */
@@ -8514,6 +8514,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
 		icb->node_name[0] &= 0xF0;
 	}
 
+	if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
+		if ((le16_to_cpu(nv->enhanced_features) & BIT_7) == 0)
+			ha->flags.scm_supported_a = 1;
+	}
+
 	/* Set host adapter parameters. */
 	ha->flags.disable_risc_code_load = 0;
 	ha->flags.enable_lip_reset = 0;
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 401ce0023cd5..7ba8a881fd4b 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -23,6 +23,372 @@ static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
 static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
 	sts_entry_t *);
 
+void
+qla_link_integrity_tgt_stats_update(struct fpin_descriptor *fpin_desc,
+				    fc_port_t *fcport)
+{
+	ql_log(ql_log_info, fcport->vha, 0x502d,
+	       "Link Integrity Event Type %d for Port %8phN\n",
+	       be16_to_cpu(fpin_desc->link_integrity.event_type),
+	       fcport->port_name);
+
+	fcport->scm_stats.link_integrity.event_type =
+	    be16_to_cpu(fpin_desc->link_integrity.event_type);
+	fcport->scm_stats.link_integrity.event_modifier =
+	    be16_to_cpu(fpin_desc->link_integrity.event_modifier);
+	fcport->scm_stats.link_integrity.event_threshold =
+	    be32_to_cpu(fpin_desc->link_integrity.event_threshold);
+	fcport->scm_stats.link_integrity.event_count =
+	    be32_to_cpu(fpin_desc->link_integrity.event_count);
+	fcport->scm_stats.link_integrity.timestamp = ktime_get_real_seconds();
+
+	fcport->scm_stats.current_events |= SCM_STATE_LINK_INTEGRITY;
+	switch (be16_to_cpu(fpin_desc->link_integrity.event_type)) {
+	case SCM_LINK_EVENT_UNKNOWN:
+		fcport->scm_stats.link_unknown_event +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_LINK_FAILURE:
+		fcport->scm_stats.link_failure_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_LOSS_OF_SYNC:
+		fcport->scm_stats.loss_of_sync_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_LOSS_OF_SIGNAL:
+		fcport->scm_stats.loss_of_signals_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR:
+		fcport->scm_stats.primitive_seq_protocol_err_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_INVALID_TX_WORD:
+		fcport->scm_stats.invalid_transmission_word_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_INVALID_CRC:
+		fcport->scm_stats.invalid_crc_count +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	case SCM_LINK_EVENT_DEVICE_SPECIFIC:
+		fcport->scm_stats.link_device_specific_event +=
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		break;
+	}
+}
+
+void
+qla_scm_process_link_integrity_d(struct scsi_qla_host *vha,
+				 struct fpin_descriptor *fpin_desc)
+{
+	int i;
+	fc_port_t *fcport =  NULL;
+	fc_port_t *d_fcport = NULL, *a_fcport = NULL;
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+				fpin_desc->link_integrity.detecting_port_name,
+				0);
+	if (fcport) {
+		d_fcport = fcport;
+		qla_link_integrity_tgt_stats_update(fpin_desc, fcport);
+	}
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+				fpin_desc->link_integrity.attached_port_name,
+				0);
+	if (fcport) {
+		a_fcport = fcport;
+		qla_link_integrity_tgt_stats_update(fpin_desc, fcport);
+	}
+
+	if (fpin_desc->link_integrity.port_name_count > 0) {
+		for (i = 0;
+		    i < be32_to_cpu(fpin_desc->link_integrity.port_name_count);
+		    i++) {
+			fcport = qla2x00_find_fcport_by_wwpn(vha,
+				fpin_desc->link_integrity.port_name_list[i],
+				0);
+			if (fcport && (fcport != d_fcport) &&
+			    (fcport != a_fcport)) {
+				qla_link_integrity_tgt_stats_update(fpin_desc,
+								    fcport);
+			}
+		}
+	}
+
+	if (memcmp(vha->port_name, fpin_desc->link_integrity.attached_port_name,
+		   WWN_SIZE) == 0) {
+		ql_log(ql_log_info, vha, 0x5093,
+		       "Link Integrity Event Type %d for HBA WWN %8phN\n",
+		       be16_to_cpu(fpin_desc->link_integrity.event_type),
+		       vha->port_name);
+
+		vha->scm_stats.current_events |= SCM_STATE_LINK_INTEGRITY;
+		vha->scm_stats.link_integrity.event_type =
+		    be16_to_cpu(fpin_desc->link_integrity.event_type);
+		vha->scm_stats.link_integrity.event_modifier =
+		    be16_to_cpu(fpin_desc->link_integrity.event_modifier);
+		vha->scm_stats.link_integrity.event_threshold =
+		    be32_to_cpu(fpin_desc->link_integrity.event_threshold);
+		vha->scm_stats.link_integrity.event_count =
+		    be32_to_cpu(fpin_desc->link_integrity.event_count);
+		vha->scm_stats.link_integrity.timestamp =
+		    ktime_get_real_seconds();
+	}
+}
+
+void
+qla_delivery_tgt_stats_update(struct fpin_descriptor *fpin_desc,
+			      fc_port_t *fcport)
+{
+	ql_log(ql_log_info, fcport->vha, 0x5095,
+	       "Delivery Notification Reason Code %d for Port %8phN\n",
+	       be32_to_cpu(fpin_desc->delivery.delivery_reason_code),
+	       fcport->port_name);
+
+	switch (be32_to_cpu(fpin_desc->delivery.delivery_reason_code)) {
+	case SCM_DELIVERY_REASON_UNKNOWN:
+		fcport->scm_stats.delivery_failure_unknown++;
+		break;
+	case SCM_DELIVERY_REASON_TIMEOUT:
+		fcport->scm_stats.delivery_timeout++;
+		break;
+	case SCM_DELIVERY_REASON_UNABLE_TO_ROUTE:
+		fcport->scm_stats.delivery_unable_to_route++;
+		break;
+	case SCM_DELIVERY_REASON_DEVICE_SPECIFIC:
+		fcport->scm_stats.delivery_failure_device_specific++;
+		break;
+	}
+	fcport->scm_stats.delivery.timestamp =
+	    ktime_get_real_seconds();
+}
+
+/*
+ * Process Delivery Notification Descriptor
+ */
+void
+qla_scm_process_delivery_notification_d(struct scsi_qla_host *vha,
+					struct fpin_descriptor *fpin_desc)
+{
+	fc_port_t *fcport =  NULL;
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+				fpin_desc->delivery.detecting_port_name, 0);
+	if (fcport)
+		qla_delivery_tgt_stats_update(fpin_desc, fcport);
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+				fpin_desc->delivery.attached_port_name, 0);
+	if (fcport)
+		qla_delivery_tgt_stats_update(fpin_desc, fcport);
+
+	if (memcmp(vha->port_name, fpin_desc->delivery.attached_port_name,
+		   WWN_SIZE) == 0) {
+		ql_log(ql_log_info, vha, 0x5096,
+		       "Delivery Notification Reason Code %d for HBA WWN %8phN\n",
+		       be32_to_cpu(fpin_desc->delivery.delivery_reason_code),
+		       vha->port_name);
+
+		vha->scm_stats.delivery.delivery_reason =
+		    be32_to_cpu(fpin_desc->delivery.delivery_reason_code);
+		vha->scm_stats.current_events |= SCM_STATE_DELIVERY;
+		vha->scm_stats.delivery.timestamp =
+		    ktime_get_real_seconds();
+	}
+}
+
+void
+qla_scm_set_target_device_state(fc_port_t *fcport,
+				struct fpin_descriptor *fpin_desc)
+{
+	switch (be16_to_cpu(fpin_desc->peer_congestion.event_type)) {
+	case SCM_CONGESTION_EVENT_CLEAR:
+		ql_log(ql_log_warn, fcport->vha, 0x5097,
+		       "Port %8phN Slow Device: Cleared\n", fcport->port_name);
+		fcport->slow_device = 0;
+		break;
+	case SCM_CONGESTION_EVENT_LOST_CREDIT:
+		break;
+	case SCM_CONGESTION_EVENT_CREDIT_STALL:
+	case SCM_CONGESTION_EVENT_OVERSUBSCRIPTION:
+		ql_log(ql_log_warn, fcport->vha, 0x508c,
+		       "Port %8phN Slow Device: Set\n", fcport->port_name);
+		fcport->slow_device = 1;
+		break;
+	case SCM_CONGESTION_EVENT_DEVICE_SPECIFIC:
+		break;
+	}
+}
+
+void
+qla_peer_congestion_tgt_stats_update(struct fpin_descriptor *fpin_desc,
+				     fc_port_t *fcport)
+{
+	ql_log(ql_log_info, fcport->vha, 0x5098,
+	       "Peer Congestion Event Type %d for Port %8phN\n",
+	       be16_to_cpu(fpin_desc->peer_congestion.event_type),
+	       fcport->port_name);
+
+	fcport->scm_stats.peer_congestion.timestamp = ktime_get_real_seconds();
+	fcport->scm_stats.peer_congestion.event_type =
+	    be16_to_cpu(fpin_desc->peer_congestion.event_type);
+	fcport->scm_stats.peer_congestion.event_modifier =
+	    be16_to_cpu(fpin_desc->peer_congestion.event_modifier);
+	fcport->scm_stats.peer_congestion.event_period =
+	    fpin_desc->peer_congestion.event_period;
+
+	// What is the API to get system time ?
+	fcport->scm_stats.current_events |= SCM_STATE_PEER_CONGESTION;
+	switch (be16_to_cpu(fpin_desc->peer_congestion.event_type)) {
+	case SCM_CONGESTION_EVENT_CLEAR:
+		fcport->scm_stats.peer_congestion_clear++;
+		fcport->scm_stats.current_events &= ~SCM_STATE_PEER_CONGESTION;
+		break;
+	case SCM_CONGESTION_EVENT_LOST_CREDIT:
+		fcport->scm_stats.peer_congestion_lost_credit++;
+		break;
+	case SCM_CONGESTION_EVENT_CREDIT_STALL:
+		fcport->scm_stats.peer_congestion_credit_stall++;
+		break;
+	case SCM_CONGESTION_EVENT_OVERSUBSCRIPTION:
+		fcport->scm_stats.peer_congestion_oversubscription++;
+		break;
+	case SCM_CONGESTION_EVENT_DEVICE_SPECIFIC:
+		fcport->scm_stats.peer_congestion_device_specific++;
+		break;
+	}
+	qla_scm_set_target_device_state(fcport, fpin_desc);
+}
+
+/*
+ * Process Peer-Congestion Notification Descriptor
+ */
+void
+qla_scm_process_peer_congestion_notification_d(struct scsi_qla_host *vha,
+					struct fpin_descriptor *fpin_desc)
+{
+	int i;
+	fc_port_t *fcport =  NULL;
+	fc_port_t *d_fcport = NULL, *a_fcport = NULL;
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+			fpin_desc->peer_congestion.detecting_port_name, 0);
+	if (fcport) {
+		d_fcport = fcport;
+		qla_peer_congestion_tgt_stats_update(fpin_desc, fcport);
+	}
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha,
+			fpin_desc->peer_congestion.attached_port_name, 0);
+	if (fcport) {
+		a_fcport = fcport;
+		qla_peer_congestion_tgt_stats_update(fpin_desc, fcport);
+	}
+
+	if (be32_to_cpu(fpin_desc->peer_congestion.port_name_count) > 0) {
+		for (i = 0;
+		    i < be32_to_cpu(fpin_desc->peer_congestion.port_name_count);
+		    i++) {
+			fcport = qla2x00_find_fcport_by_wwpn(vha,
+			fpin_desc->peer_congestion.port_name_list[i], 0);
+			if (fcport && fcport != d_fcport &&
+			    fcport != a_fcport) {
+				qla_peer_congestion_tgt_stats_update(fpin_desc,
+								fcport);
+			}
+		}
+	}
+}
+
+/*
+ * qla_scm_process_congestion_notification_d() - Process
+ * Process Congestion Notification Descriptor
+ * @rsp: response queue
+ * @pkt: Entry pointer
+ */
+void
+qla_scm_process_congestion_notification_d(struct scsi_qla_host *vha,
+					  struct fpin_descriptor *fpin_desc)
+{
+	ql_log(ql_log_info, vha, 0x5099,
+	       "Congestion Notification Event Type %d\n",
+	       be16_to_cpu(fpin_desc->congestion.event_type));
+
+	vha->scm_stats.congestion.event_type =
+	    be16_to_cpu(fpin_desc->congestion.event_type);
+	vha->scm_stats.congestion.event_modifier =
+	    be16_to_cpu(fpin_desc->congestion.event_modifier);
+	vha->scm_stats.congestion.event_period =
+	    be32_to_cpu(fpin_desc->congestion.event_period);
+	vha->scm_stats.congestion.severity =
+	    fpin_desc->congestion.severity;
+
+	if (be16_to_cpu(fpin_desc->congestion.event_type) ==
+	    SCM_CONGESTION_EVENT_CLEAR)
+		vha->scm_stats.current_events &= ~SCM_STATE_CONGESTION;
+	else
+		vha->scm_stats.current_events |= SCM_STATE_CONGESTION;
+
+	if (fpin_desc->congestion.severity == SCM_CONGESTION_SEVERITY_WARNING)
+		vha->scm_stats.scm_congestion_warning++;
+	else if (fpin_desc->congestion.severity ==
+	     SCM_CONGESTION_SEVERITY_ERROR)
+		vha->scm_stats.scm_congestion_alarm++;
+}
+
+void
+qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct purex_item *item)
+{
+	struct fpin_descriptor *fpin_desc;
+	uint16_t fpin_desc_len;
+	uint32_t fpin_offset = 0;
+	void *pkt = &item->iocb;
+	uint16_t pkt_size = item->size;
+
+	ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508d,
+	       "%s: Enter\n", __func__);
+
+	ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x508e,
+	       "-------- ELS REQ -------\n");
+	ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha, 0x508f,
+		       pkt, pkt_size);
+
+	fpin_desc = (struct fpin_descriptor *)((uint8_t *)pkt +
+	    FPIN_ELS_DESCRIPTOR_LIST_OFFSET);
+
+	fpin_desc_len = pkt_size - FPIN_ELS_DESCRIPTOR_LIST_OFFSET;
+	while (fpin_offset <= fpin_desc_len) {
+		fpin_desc = (struct fpin_descriptor *)((uint8_t *)fpin_desc +
+		    fpin_offset);
+
+		if (fpin_offset >= fpin_desc_len - 8)
+			return;
+
+		switch (be32_to_cpu(fpin_desc->descriptor_tag)) {
+		case SCM_NOTIFICATION_TYPE_LINK_INTEGRITY:
+			qla_scm_process_link_integrity_d(vha, fpin_desc);
+			break;
+		case SCM_NOTIFICATION_TYPE_DELIVERY:
+			qla_scm_process_delivery_notification_d(vha, fpin_desc);
+			break;
+		case SCM_NOTIFICATION_TYPE_PEER_CONGESTION:
+			qla_scm_process_peer_congestion_notification_d(vha,
+								fpin_desc);
+			break;
+		case SCM_NOTIFICATION_TYPE_CONGESTION:
+			qla_scm_process_congestion_notification_d(vha,
+								fpin_desc);
+			break;
+		}
+		fpin_offset += be32_to_cpu(fpin_desc->descriptor_length) +
+		    FPIN_DESCRIPTOR_HEADER_SIZE;
+	}
+	fc_host_fpin_rcv(vha->host, pkt_size, (char *)pkt);
+}
+
 const char *const port_state_str[] = {
 	"Unknown",
 	"UNCONFIGURED",
@@ -836,6 +1202,111 @@ struct purex_item
 	return item;
 }
 
+/**
+ * qla27xx_copy_fpin_pkt() - Copy over fpin packets that can
+ * span over multiple IOCBs.
+ * @vha: SCSI driver HA context
+ * @pkt: ELS packet
+ * @rsp: Response queue
+ */
+struct purex_item *
+qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
+		      struct rsp_que **rsp)
+{
+	struct purex_entry_24xx *purex = *pkt;
+	struct rsp_que *rsp_q = *rsp;
+	sts_cont_entry_t *new_pkt;
+	uint16_t no_bytes = 0, total_bytes = 0, pending_bytes = 0;
+	uint16_t buffer_copy_offset = 0;
+	uint16_t entry_count, entry_count_remaining;
+	struct purex_item *item;
+	void *fpin_pkt = NULL;
+
+	total_bytes = le16_to_cpu(purex->frame_size & 0x0FFF)
+	    - PURX_ELS_HEADER_SIZE;
+	pending_bytes = total_bytes;
+	entry_count = entry_count_remaining = purex->entry_count;
+	no_bytes = (pending_bytes > sizeof(purex->els_frame_payload))  ?
+		   sizeof(purex->els_frame_payload) : pending_bytes;
+	ql_log(ql_log_info, vha, 0x509a,
+	       "FPIN ELS, frame_size 0x%x, entry count %d\n",
+	       total_bytes, entry_count);
+
+	item = qla24xx_alloc_purex_item(vha, total_bytes);
+	if (!item)
+		return item;
+
+	fpin_pkt = &item->iocb;
+
+	memcpy(fpin_pkt, &purex->els_frame_payload[0], no_bytes);
+	buffer_copy_offset += no_bytes;
+	pending_bytes -= no_bytes;
+	--entry_count_remaining;
+
+	((response_t *)purex)->signature = RESPONSE_PROCESSED;
+	wmb();
+
+	do {
+		while ((total_bytes > 0) && (entry_count_remaining > 0)) {
+			if (rsp_q->ring_ptr->signature == RESPONSE_PROCESSED) {
+				ql_dbg(ql_dbg_async, vha, 0x5084,
+				       "Ran out of IOCBs, partial data 0x%x\n",
+				       buffer_copy_offset);
+				cpu_relax();
+				continue;
+			}
+
+			new_pkt = (sts_cont_entry_t *)rsp_q->ring_ptr;
+			*pkt = new_pkt;
+
+			if (new_pkt->entry_type != STATUS_CONT_TYPE) {
+				ql_log(ql_log_warn, vha, 0x507a,
+				       "Unexpected IOCB type, partial data 0x%x\n",
+				       buffer_copy_offset);
+				break;
+			}
+
+			rsp_q->ring_index++;
+			if (rsp_q->ring_index == rsp_q->length) {
+				rsp_q->ring_index = 0;
+				rsp_q->ring_ptr = rsp_q->ring;
+			} else {
+				rsp_q->ring_ptr++;
+			}
+			no_bytes = (pending_bytes > sizeof(new_pkt->data)) ?
+			    sizeof(new_pkt->data) : pending_bytes;
+			if ((buffer_copy_offset + no_bytes) <= total_bytes) {
+				memcpy(((uint8_t *)fpin_pkt +
+				    buffer_copy_offset), new_pkt->data,
+				    no_bytes);
+				buffer_copy_offset += no_bytes;
+				pending_bytes -= no_bytes;
+				--entry_count_remaining;
+			} else {
+				ql_log(ql_log_warn, vha, 0x5044,
+				       "Attempt to copy more that we got, optimizing..%x\n",
+				       buffer_copy_offset);
+				memcpy(((uint8_t *)fpin_pkt +
+				    buffer_copy_offset), new_pkt->data,
+				    total_bytes - buffer_copy_offset);
+			}
+
+			((response_t *)new_pkt)->signature = RESPONSE_PROCESSED;
+			wmb();
+		}
+
+		if (pending_bytes != 0 || entry_count_remaining != 0) {
+			ql_log(ql_log_fatal, vha, 0x508b,
+			       "Dropping partial FPIN, underrun bytes = 0x%x, entry cnts 0x%x\n",
+			       total_bytes, entry_count_remaining);
+			qla24xx_free_purex_item(item);
+			return NULL;
+		}
+	} while (entry_count_remaining > 0);
+	host_to_fcp_swap((uint8_t *)&item->iocb, total_bytes);
+	return item;
+}
+
 /**
  * qla2x00_async_event() - Process aynchronous events.
  * @vha: SCSI driver HA context
@@ -1350,6 +1821,19 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 			qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
 		}
 		break;
+	case MBA_CONGN_NOTI_RECV:
+		if (!ha->flags.scm_enabled ||
+		    mb[1] != QLA_CON_PRIMITIVE_RECEIVED)
+			break;
+
+		if (mb[2] == QLA_CONGESTION_ARB_WARNING) {
+			vha->scm_stats.scm_congestion_warning++;
+		} else if (mb[2] == QLA_CONGESTION_ARB_ALARM) {
+			ql_log(ql_log_warn, vha, 0x509b,
+			       "Congestion Alarm %04x %04x.\n", mb[1], mb[2]);
+			vha->scm_stats.scm_congestion_alarm++;
+		}
+		break;
 	/* case MBA_RIO_RESPONSE: */
 	case MBA_ZIO_RESPONSE:
 		ql_dbg(ql_dbg_async, vha, 0x5015,
@@ -3279,6 +3763,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 {
 	struct sts_entry_24xx *pkt;
 	struct qla_hw_data *ha = vha->hw;
+	struct purex_entry_24xx *purex_entry;
 	struct purex_item *pure_item;
 
 	if (!ha->flags.fw_started)
@@ -3334,7 +3819,6 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 				pure_item = qla24xx_copy_std_pkt(vha, pkt);
 				if (!pure_item)
 					break;
-
 				qla24xx_queue_purex_item(vha, pure_item,
 							 qla24xx_process_abts);
 				break;
@@ -3384,29 +3868,41 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha,
 			    (struct vp_ctrl_entry_24xx *)pkt);
 			break;
 		case PUREX_IOCB_TYPE:
-		{
-			struct purex_entry_24xx *purex = (void *)pkt;
-
-			if (purex->els_frame_payload[3] != ELS_COMMAND_RDP) {
-				ql_dbg(ql_dbg_init, vha, 0x5091,
-				    "Discarding ELS Request opcode %#x...\n",
-				    purex->els_frame_payload[3]);
+			purex_entry = (void *)pkt;
+			switch (purex_entry->els_frame_payload[3]) {
+			case ELS_COMMAND_RDP:
+				pure_item = qla24xx_copy_std_pkt(vha, pkt);
+				if (!pure_item)
+					break;
+				qla24xx_queue_purex_item(vha, pure_item,
+						 qla24xx_process_purex_rdp);
 				break;
-			}
-			pure_item = qla24xx_copy_std_pkt(vha, pkt);
-			if (!pure_item)
+			case ELS_COMMAND_FPIN:
+				if (!vha->hw->flags.scm_enabled) {
+					ql_log(ql_log_warn, vha, 0x5094,
+					       "SCM not active for this port\n");
+					break;
+				}
+				pure_item = qla27xx_copy_fpin_pkt(vha,
+							  (void **)&pkt, &rsp);
+				if (!pure_item)
+					break;
+				qla24xx_queue_purex_item(vha, pure_item,
+						 qla27xx_process_purex_fpin);
 				break;
-
-			qla24xx_queue_purex_item(vha, pure_item,
-						 qla24xx_process_purex_rdp);
+			case ELS_COMMAND_PUN:
+				break;
+			default:
+				ql_log(ql_log_warn, vha, 0x509c,
+				       "Discarding ELS Request opcode 0x%x\n",
+				       purex_entry->els_frame_payload[3]);
+			}
 			break;
-		}
 		default:
 			/* Type Not Supported. */
 			ql_dbg(ql_dbg_async, vha, 0x5042,
-			    "Received unknown response pkt type %x "
-			    "entry status=%x.\n",
-			    pkt->entry_type, pkt->entry_status);
+			       "Received unknown response pkt type 0x%x entry status=%x.\n",
+			       pkt->entry_type, pkt->entry_status);
 			break;
 		}
 		((response_t *)pkt)->signature = RESPONSE_PROCESSED;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 76a4f2bfdbed..3c411b5914ce 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -1126,6 +1126,16 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
 			    (ha->flags.secure_fw) ? "Supported" :
 			    "Not Supported");
 		}
+
+		if (ha->flags.scm_supported_a &&
+		    (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) {
+			ha->flags.scm_supported_f = 1;
+			memset(ha->sf_init_cb, 0, sizeof(struct init_sf_cb));
+			ha->sf_init_cb->flags |= BIT_13;
+		}
+		ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n",
+		       (ha->flags.scm_supported_f) ? "Supported" :
+		       "Not Supported");
 	}
 
 failed:
@@ -1635,8 +1645,11 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
 		mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
 	if (IS_FWI2_CAPABLE(vha->hw))
 		mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
-	if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
+	if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
 		mcp->in_mb |= MBX_15;
+		mcp->out_mb |= MBX_7|MBX_21|MBX_22|MBX_23;
+	}
+
 	mcp->tov = MBX_TOV_SECONDS;
 	mcp->flags = 0;
 	rval = qla2x00_mailbox_command(vha, mcp);
@@ -1689,8 +1702,22 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
 			}
 		}
 
-		if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
+		if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw)) {
 			vha->bbcr = mcp->mb[15];
+			if (mcp->mb[7] & SCM_EDC_ACC_RECEIVED) {
+				ql_log(ql_log_info, vha, 0x11a4,
+				       "SCM: EDC ELS completed, flags 0x%x\n",
+				       mcp->mb[21]);
+			}
+			if (mcp->mb[7] & SCM_RDF_ACC_RECEIVED) {
+				vha->hw->flags.scm_enabled = 1;
+				vha->scm_stats.scm_fabric_connection_flags |=
+				    SCM_FLAG_RDF_COMPLETED;
+				ql_log(ql_log_info, vha, 0x11a5,
+				       "SCM: RDF ELS completed, flags 0x%x\n",
+				       mcp->mb[23]);
+			}
+		}
 	}
 
 	return rval;
@@ -1803,6 +1830,17 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
 		mcp->mb[14] = sizeof(*ha->ex_init_cb);
 		mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
 	}
+
+	if (ha->flags.scm_supported_f) {
+		mcp->mb[1] |= BIT_1;
+		mcp->mb[16] = MSW(ha->sf_init_cb_dma);
+		mcp->mb[17] = LSW(ha->sf_init_cb_dma);
+		mcp->mb[18] = MSW(MSD(ha->sf_init_cb_dma));
+		mcp->mb[19] = LSW(MSD(ha->sf_init_cb_dma));
+		mcp->mb[15] = sizeof(*ha->sf_init_cb);
+		mcp->out_mb |= MBX_19|MBX_18|MBX_17|MBX_16|MBX_15;
+	}
+
 	/* 1 and 2 should normally be captured. */
 	mcp->in_mb = MBX_2|MBX_1|MBX_0;
 	if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
@@ -4902,7 +4940,8 @@ qla25xx_set_els_cmds_supported(scsi_qla_host_t *vha)
 
 	/* List of Purex ELS */
 	cmd_opcode[0] = ELS_COMMAND_FPIN;
-	cmd_opcode[1] = ELS_COMMAND_PUN;
+	cmd_opcode[1] = ELS_COMMAND_RDP;
+	cmd_opcode[2] = ELS_COMMAND_PUN;
 
 	for (i = 0; i < PUREX_CMD_COUNT; i++) {
 		index = cmd_opcode[i] / 8;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 007f39128dbf..70241506d0ca 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4220,6 +4220,16 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 		    "ex_init_cb=%p.\n", ha->ex_init_cb);
 	}
 
+	/* Get consistent memory allocated for Special Features-CB. */
+	if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+		ha->sf_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+						&ha->sf_init_cb_dma);
+		if (!ha->sf_init_cb)
+			goto fail_sf_init_cb;
+		ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0199,
+			   "sf_init_cb=%p.\n", ha->sf_init_cb);
+	}
+
 	INIT_LIST_HEAD(&ha->gbl_dsd_list);
 
 	/* Get consistent memory allocated for Async Port-Database. */
@@ -4273,6 +4283,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
 fail_loop_id_map:
 	dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
 fail_async_pd:
+	dma_pool_free(ha->s_dma_pool, ha->sf_init_cb, ha->sf_init_cb_dma);
+fail_sf_init_cb:
 	dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
 fail_ex_init_cb:
 	kfree(ha->npiv_info);
@@ -4695,6 +4707,10 @@ qla2x00_mem_free(struct qla_hw_data *ha)
 	ha->ms_iocb = NULL;
 	ha->ms_iocb_dma = 0;
 
+	if (ha->sf_init_cb)
+		dma_pool_free(ha->s_dma_pool,
+			      ha->sf_init_cb, ha->sf_init_cb_dma);
+
 	if (ha->ex_init_cb)
 		dma_pool_free(ha->s_dma_pool,
 			ha->ex_init_cb, ha->ex_init_cb_dma);
@@ -4782,6 +4798,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
 	kfree(ha->swl);
 	ha->swl = NULL;
 	kfree(ha->loop_id_map);
+	ha->sf_init_cb = NULL;
+	ha->sf_init_cb_dma = 0;
 	ha->loop_id_map = NULL;
 }
 
-- 
2.19.0.rc0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 3/3] qla2xxx: Pass SCM counters to the application.
  2020-05-14 10:10 [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Nilesh Javali
  2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
  2020-05-14 10:10 ` [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation Nilesh Javali
@ 2020-05-14 10:10 ` Nilesh Javali
  2020-05-14 19:15   ` himanshu.madhani
  2020-05-14 14:11 ` [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Bart Van Assche
  3 siblings, 1 reply; 15+ messages in thread
From: Nilesh Javali @ 2020-05-14 10:10 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Shyam Sundar <ssundar@marvell.com>

Implement 3 functions to pass on SAN congestion management
related counters tracked by the driver, up to the Marvell
application using the BSG interface.

Signed-off-by: Shyam Sundar <ssundar@marvell.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_bsg.c | 114 +++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_bsg.h |   3 +
 2 files changed, 117 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 97b51c477972..bd898bbdd44d 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -2446,6 +2446,111 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
 	return 0;
 }
 
+static int
+qla2x00_get_drv_attr(struct bsg_job *bsg_job)
+{
+	struct qla_drv_attr drv_attr;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+
+	memset(&drv_attr, 0, sizeof(struct qla_drv_attr));
+	/* Additional check should be added if SCM is not enabled
+	 * by default for a given driver version.
+	 */
+	drv_attr.attributes |= QLA_DRV_ATTR_SCM_SUPPORTED;
+
+	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+			    bsg_job->reply_payload.sg_cnt, &drv_attr,
+			    sizeof(struct qla_drv_attr));
+
+	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr);
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+	bsg_job->reply_len = sizeof(*bsg_job->reply);
+	bsg_reply->result = DID_OK << 16;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	return 0;
+}
+
+static int
+qla2x00_get_port_scm(struct bsg_job *bsg_job)
+{
+	struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job);
+	scsi_qla_host_t *vha = shost_priv(shost);
+	struct qla_hw_data *ha = vha->hw;
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+
+	if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+		return -EPERM;
+
+	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+			    bsg_job->reply_payload.sg_cnt, &vha->scm_stats,
+			    sizeof(struct qla_scm_port));
+
+	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_port);
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+	bsg_job->reply_len = sizeof(*bsg_job->reply);
+	bsg_reply->result = DID_OK << 16;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	return 0;
+}
+
+static int
+qla2x00_get_target_scm(struct bsg_job *bsg_job)
+{
+	struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job);
+	scsi_qla_host_t *vha = shost_priv(shost);
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct qla_hw_data *ha = vha->hw;
+	fc_port_t *fcport =  NULL;
+	int rval;
+	struct qla_scm_target *scm_stats = NULL;
+
+	if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+		return -EPERM;
+
+	scm_stats = kzalloc(sizeof(*scm_stats), GFP_KERNEL);
+	if (!scm_stats) {
+		ql_log(ql_log_warn, vha, 0x7024,
+		       "Failed to allocate memory for target scm stats.\n");
+		return -ENOMEM;
+	}
+
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+			  bsg_job->request_payload.sg_cnt, scm_stats,
+			  sizeof(struct qla_scm_target));
+
+	fcport = qla2x00_find_fcport_by_wwpn(vha, scm_stats->wwpn, 0);
+	if (fcport) {
+		/* Copy SCM Target data to local struct, keep WWPN from user */
+		memcpy(&scm_stats->current_events,
+		       &fcport->scm_stats.current_events,
+		       (sizeof(struct qla_scm_target) -
+			sizeof(scm_stats->wwpn)));
+		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+				    bsg_job->reply_payload.sg_cnt, scm_stats,
+				    sizeof(struct qla_scm_target));
+		rval = EXT_STATUS_OK;
+	} else {
+		rval = EXT_STATUS_ERR;
+	}
+
+	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_target);
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
+
+	bsg_job->reply_len = sizeof(*bsg_job->reply);
+	bsg_reply->result = DID_OK << 16;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	kfree(scm_stats);
+	return 0;
+}
+
 static int
 qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
 {
@@ -2522,6 +2627,15 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
 	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
 		return qla2x00_get_flash_image_status(bsg_job);
 
+	case QL_VND_GET_PORT_SCM:
+		return qla2x00_get_port_scm(bsg_job);
+
+	case QL_VND_GET_TARGET_SCM:
+		return qla2x00_get_target_scm(bsg_job);
+
+	case QL_VND_GET_DRV_ATTR:
+		return qla2x00_get_drv_attr(bsg_job);
+
 	default:
 		return -ENOSYS;
 	}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 0b308859047c..c7cf5f772ad3 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -32,6 +32,9 @@
 #define QL_VND_DPORT_DIAGNOSTICS	0x19
 #define QL_VND_GET_PRIV_STATS_EX	0x1A
 #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
+#define QL_VND_GET_PORT_SCM		0x20
+#define QL_VND_GET_TARGET_SCM		0x21
+#define QL_VND_GET_DRV_ATTR		0x22
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK			0
-- 
2.19.0.rc0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support
  2020-05-14 10:10 [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Nilesh Javali
                   ` (2 preceding siblings ...)
  2020-05-14 10:10 ` [PATCH 3/3] qla2xxx: Pass SCM counters to the application Nilesh Javali
@ 2020-05-14 14:11 ` Bart Van Assche
  3 siblings, 0 replies; 15+ messages in thread
From: Bart Van Assche @ 2020-05-14 14:11 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

On 2020-05-14 03:10, Nilesh Javali wrote:
> Please apply the qla2xxx patch series implementing SAN Congestion Management
> (SCM) support to the scsi tree at your earliest convenience.

Hi Nilesh,

This patch series introduces the following compiler warnings (W=1):

drivers/scsi/qla2xxx/qla_isr.c:27:1: warning: no previous prototype for
‘qla_link_integrity_tgt_stats_update’ [-Wmissing-prototypes]
   27 | qla_link_integrity_tgt_stats_update(struct fpin_descriptor
*fpin_desc,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:83:1: warning: no previous prototype for
‘qla_scm_process_link_integrity_d’ [-Wmissing-prototypes]
   83 | qla_scm_process_link_integrity_d(struct scsi_qla_host *vha,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:143:1: warning: no previous prototype for
‘qla_delivery_tgt_stats_update’ [-Wmissing-prototypes]
  143 | qla_delivery_tgt_stats_update(struct fpin_descriptor *fpin_desc,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:173:1: warning: no previous prototype for
‘qla_scm_process_delivery_notification_d’ [-Wmissing-prototypes]
  173 | qla_scm_process_delivery_notification_d(struct scsi_qla_host *vha,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:204:1: warning: no previous prototype for
‘qla_scm_set_target_device_state’ [-Wmissing-prototypes]
  204 | qla_scm_set_target_device_state(fc_port_t *fcport,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:227:1: warning: no previous prototype for
‘qla_peer_congestion_tgt_stats_update’ [-Wmissing-prototypes]
  227 | qla_peer_congestion_tgt_stats_update(struct fpin_descriptor
*fpin_desc,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:270:1: warning: no previous prototype for
‘qla_scm_process_peer_congestion_notification_d’ [-Wmissing-prototypes]
  270 | qla_scm_process_peer_congestion_notification_d(struct
scsi_qla_host *vha,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:313:1: warning: no previous prototype for
‘qla_scm_process_congestion_notification_d’ [-Wmissing-prototypes]
  313 | qla_scm_process_congestion_notification_d(struct scsi_qla_host *vha,
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:343:1: warning: no previous prototype for
‘qla27xx_process_purex_fpin’ [-Wmissing-prototypes]
  343 | qla27xx_process_purex_fpin(struct scsi_qla_host *vha, struct
purex_item *item)
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:1136:1: warning: no previous prototype
for ‘qla24xx_alloc_purex_item’ [-Wmissing-prototypes]
 1136 | qla24xx_alloc_purex_item(scsi_qla_host_t *vha, uint16_t size)
      | ^~~~~~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:1192:2: warning: no previous prototype
for ‘qla24xx_copy_std_pkt’ [-Wmissing-prototypes]
 1192 | *qla24xx_copy_std_pkt(struct scsi_qla_host *vha, void *pkt)
      |  ^~~~~~~~~~~~~~~~~~~~
drivers/scsi/qla2xxx/qla_isr.c:1213:1: warning: no previous prototype
for ‘qla27xx_copy_fpin_pkt’ [-Wmissing-prototypes]
 1213 | qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
      | ^~~~~~~~~~~~~~~~~~~~~
  CC [M]  drivers/scsi/qla2xxx/qla_gs.o
  CC [M]  drivers/scsi/qla2xxx/qla_dbg.o
  CC [M]  drivers/scsi/qla2xxx/qla_sup.o
  CC [M]  drivers/scsi/qla2xxx/qla_attr.o
  CC [M]  drivers/scsi/qla2xxx/qla_mid.o
  CC [M]  drivers/scsi/qla2xxx/qla_dfs.o
drivers/scsi/qla2xxx/qla_dfs.c: In function
‘qla2x00_dfs_tgt_port_database_show’:
drivers/scsi/qla2xxx/qla_dfs.c:107:1: warning: the frame size of 1280
bytes is larger than 1024 bytes [-Wframe-larger-than=]
  107 | }
      | ^


and also the following sparse complaints:

$ make M=drivers/scsi/qla2xxx C=2
  CHECK   drivers/scsi/qla2xxx/qla_os.c
  CC [M]  drivers/scsi/qla2xxx/qla_os.o
  CHECK   drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_init.c:8520:22: warning: cast to restricted __le16
  CC [M]  drivers/scsi/qla2xxx/qla_init.o
  CHECK   drivers/scsi/qla2xxx/qla_mbx.c
  CC [M]  drivers/scsi/qla2xxx/qla_mbx.o
  CHECK   drivers/scsi/qla2xxx/qla_iocb.c
  CC [M]  drivers/scsi/qla2xxx/qla_iocb.o
  CHECK   drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_isr.c:27:1: warning: symbol
'qla_link_integrity_tgt_stats_update' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:106:38: warning: restricted __be32
degrades to integer
drivers/scsi/qla2xxx/qla_isr.c:83:1: warning: symbol
'qla_scm_process_link_integrity_d' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:143:1: warning: symbol
'qla_delivery_tgt_stats_update' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:173:1: warning: symbol
'qla_scm_process_delivery_notification_d' was not declared. Should it be
static?
drivers/scsi/qla2xxx/qla_isr.c:204:1: warning: symbol
'qla_scm_set_target_device_state' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:240:56: warning: incorrect type in
assignment (different base types)
drivers/scsi/qla2xxx/qla_isr.c:240:56:    expected unsigned int
[usertype] event_period
drivers/scsi/qla2xxx/qla_isr.c:240:56:    got restricted __be32
[usertype] event_period
drivers/scsi/qla2xxx/qla_isr.c:227:1: warning: symbol
'qla_peer_congestion_tgt_stats_update' was not declared. Should it be
static?
drivers/scsi/qla2xxx/qla_isr.c:270:1: warning: symbol
'qla_scm_process_peer_congestion_notification_d' was not declared.
Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:313:1: warning: symbol
'qla_scm_process_congestion_notification_d' was not declared. Should it
be static?
drivers/scsi/qla2xxx/qla_isr.c:343:1: warning: symbol
'qla27xx_process_purex_fpin' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:1135:19: warning: symbol
'qla24xx_alloc_purex_item' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:1192:1: warning: symbol
'qla24xx_copy_std_pkt' was not declared. Should it be static?
drivers/scsi/qla2xxx/qla_isr.c:1225:23: warning: restricted __le16
degrades to integer
drivers/scsi/qla2xxx/qla_isr.c:1225:23: warning: cast to restricted __le16
drivers/scsi/qla2xxx/qla_isr.c:1212:19: warning: symbol
'qla27xx_copy_fpin_pkt' was not declared. Should it be static?
  CC [M]  drivers/scsi/qla2xxx/qla_isr.o
  CHECK   drivers/scsi/qla2xxx/qla_gs.c
  CC [M]  drivers/scsi/qla2xxx/qla_gs.o
  CHECK   drivers/scsi/qla2xxx/qla_dbg.c
  CC [M]  drivers/scsi/qla2xxx/qla_dbg.o
  CHECK   drivers/scsi/qla2xxx/qla_sup.c
  CC [M]  drivers/scsi/qla2xxx/qla_sup.o
  CHECK   drivers/scsi/qla2xxx/qla_attr.c
  CC [M]  drivers/scsi/qla2xxx/qla_attr.o
  CHECK   drivers/scsi/qla2xxx/qla_mid.c
  CC [M]  drivers/scsi/qla2xxx/qla_mid.o
  CHECK   drivers/scsi/qla2xxx/qla_dfs.c
  CC [M]  drivers/scsi/qla2xxx/qla_dfs.o
drivers/scsi/qla2xxx/qla_dfs.c: In function
‘qla2x00_dfs_tgt_port_database_show’:
drivers/scsi/qla2xxx/qla_dfs.c:107:1: warning: the frame size of 1280
bytes is larger than 1024 bytes [-Wframe-larger-than=]
  107 | }
      | ^

Please fix these issues.

Thanks,

Bart.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests.
  2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
@ 2020-05-14 17:03   ` himanshu.madhani
  2020-05-15 18:52   ` James Smart
  1 sibling, 0 replies; 15+ messages in thread
From: himanshu.madhani @ 2020-05-14 17:03 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream



On 5/14/20 5:10 AM, Nilesh Javali wrote:
> SAN Congestion Management generates ELS pkts whose size
> can vary, and be > 64 bytes. Change the purex
> handling code to support non standard ELS pkt size.


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

-- 
Himanshu Madhani
Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-05-14 10:10 ` [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation Nilesh Javali
@ 2020-05-14 18:52   ` himanshu.madhani
  2020-05-15 22:48   ` James Smart
  1 sibling, 0 replies; 15+ messages in thread
From: himanshu.madhani @ 2020-05-14 18:52 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Nilesh,

On 5/14/20 5:10 AM, Nilesh Javali wrote:
> * Firmware Initialization with SCM enabled based on NVRAM setting and
>    firmware support (About Firmware).
> * Enable PUREX and add support for fabric performance impact
>    notification(FPIN) handling.
> * Support for the following FPIN descriptors:
>    	1. Link Integrity Notification.
> 	2. Delivery Notification.
> 	3. Peer Congestion Notification.
> 	4. Congestion Notification.
> * Mark a device as slow when a Peer Congestion Notification is received.
> * Allocate a default purex item for each vha, to handle memory
>    allocation failures in ISR.

When you repost this series, fix comments for function header and places 
where its using windows style comments in this patch.


-- 
Himanshu Madhani
Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/3] qla2xxx: Pass SCM counters to the application.
  2020-05-14 10:10 ` [PATCH 3/3] qla2xxx: Pass SCM counters to the application Nilesh Javali
@ 2020-05-14 19:15   ` himanshu.madhani
  0 siblings, 0 replies; 15+ messages in thread
From: himanshu.madhani @ 2020-05-14 19:15 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream



On 5/14/20 5:10 AM, Nilesh Javali wrote:
> From: Shyam Sundar <ssundar@marvell.com>
> 
> Implement 3 functions to pass on SAN congestion management
> related counters tracked by the driver, up to the Marvell
> application using the BSG interface.
> 
> Signed-off-by: Shyam Sundar <ssundar@marvell.com>
> Signed-off-by: Arun Easi <aeasi@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
>   drivers/scsi/qla2xxx/qla_bsg.c | 114 +++++++++++++++++++++++++++++++++
>   drivers/scsi/qla2xxx/qla_bsg.h |   3 +
>   2 files changed, 117 insertions(+)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index 97b51c477972..bd898bbdd44d 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -2446,6 +2446,111 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
>   	return 0;
>   }
>   
> +static int
> +qla2x00_get_drv_attr(struct bsg_job *bsg_job)
> +{
> +	struct qla_drv_attr drv_attr;
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +
> +	memset(&drv_attr, 0, sizeof(struct qla_drv_attr));
> +	/* Additional check should be added if SCM is not enabled
> +	 * by default for a given driver version.
> +	 */
> +	drv_attr.attributes |= QLA_DRV_ATTR_SCM_SUPPORTED;
> +
> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +			    bsg_job->reply_payload.sg_cnt, &drv_attr,
> +			    sizeof(struct qla_drv_attr));
> +
> +	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_drv_attr);
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +
> +	bsg_job->reply_len = sizeof(*bsg_job->reply);
> +	bsg_reply->result = DID_OK << 16;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	return 0;
> +}
> +
> +static int
> +qla2x00_get_port_scm(struct bsg_job *bsg_job)
> +{
> +	struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job);
> +	scsi_qla_host_t *vha = shost_priv(shost);
> +	struct qla_hw_data *ha = vha->hw;
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +
> +	if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
> +		return -EPERM;
> +
> +	sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +			    bsg_job->reply_payload.sg_cnt, &vha->scm_stats,
> +			    sizeof(struct qla_scm_port));
> +
> +	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_port);
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +
> +	bsg_job->reply_len = sizeof(*bsg_job->reply);
> +	bsg_reply->result = DID_OK << 16;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	return 0;
> +}
> +
> +static int
> +qla2x00_get_target_scm(struct bsg_job *bsg_job)
> +{
> +	struct Scsi_Host *shost = fc_bsg_to_shost(bsg_job);
> +	scsi_qla_host_t *vha = shost_priv(shost);
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +	struct qla_hw_data *ha = vha->hw;
> +	fc_port_t *fcport =  NULL;
> +	int rval;
> +	struct qla_scm_target *scm_stats = NULL;
> +
> +	if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
> +		return -EPERM;
> +
> +	scm_stats = kzalloc(sizeof(*scm_stats), GFP_KERNEL);
> +	if (!scm_stats) {
> +		ql_log(ql_log_warn, vha, 0x7024,
> +		       "Failed to allocate memory for target scm stats.\n");
> +		return -ENOMEM;
> +	}
> +
> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> +			  bsg_job->request_payload.sg_cnt, scm_stats,
> +			  sizeof(struct qla_scm_target));
> +
> +	fcport = qla2x00_find_fcport_by_wwpn(vha, scm_stats->wwpn, 0);
> +	if (fcport) {
> +		/* Copy SCM Target data to local struct, keep WWPN from user */
> +		memcpy(&scm_stats->current_events,
> +		       &fcport->scm_stats.current_events,
> +		       (sizeof(struct qla_scm_target) -
> +			sizeof(scm_stats->wwpn)));
> +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +				    bsg_job->reply_payload.sg_cnt, scm_stats,
> +				    sizeof(struct qla_scm_target));
> +		rval = EXT_STATUS_OK;
> +	} else {
> +		rval = EXT_STATUS_ERR;
> +	}
> +
> +	bsg_reply->reply_payload_rcv_len = sizeof(struct qla_scm_target);
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
> +
> +	bsg_job->reply_len = sizeof(*bsg_job->reply);
> +	bsg_reply->result = DID_OK << 16;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	kfree(scm_stats);
> +	return 0;
> +}
> +
>   static int
>   qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
>   {
> @@ -2522,6 +2627,15 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
>   	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
>   		return qla2x00_get_flash_image_status(bsg_job);
>   
> +	case QL_VND_GET_PORT_SCM:
> +		return qla2x00_get_port_scm(bsg_job);
> +
> +	case QL_VND_GET_TARGET_SCM:
> +		return qla2x00_get_target_scm(bsg_job);
> +
> +	case QL_VND_GET_DRV_ATTR:
> +		return qla2x00_get_drv_attr(bsg_job);
> +
>   	default:
>   		return -ENOSYS;
>   	}
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> index 0b308859047c..c7cf5f772ad3 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.h
> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> @@ -32,6 +32,9 @@
>   #define QL_VND_DPORT_DIAGNOSTICS	0x19
>   #define QL_VND_GET_PRIV_STATS_EX	0x1A
>   #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
> +#define QL_VND_GET_PORT_SCM		0x20
> +#define QL_VND_GET_TARGET_SCM		0x21
> +#define QL_VND_GET_DRV_ATTR		0x22
>   
>   /* BSG Vendor specific subcode returns */
>   #define EXT_STATUS_OK			0
> 

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

-- 
Himanshu Madhani
Oracle Linux Engineering

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests.
  2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
  2020-05-14 17:03   ` himanshu.madhani
@ 2020-05-15 18:52   ` James Smart
  1 sibling, 0 replies; 15+ messages in thread
From: James Smart @ 2020-05-15 18:52 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream



On 5/14/2020 3:10 AM, Nilesh Javali wrote:
> From: Shyam Sundar <ssundar@marvell.com>
>
> SAN Congestion Management generates ELS pkts whose size
> can vary, and be > 64 bytes. Change the purex
> handling code to support non standard ELS pkt size.
>
> Signed-off-by: Shyam Sundar <ssundar@marvell.com>
> Signed-off-by: Arun Easi <aeasi@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
>   drivers/scsi/qla2xxx/qla_def.h |  17 ++++-
>   drivers/scsi/qla2xxx/qla_gbl.h |   3 +-
>   drivers/scsi/qla2xxx/qla_isr.c | 116 ++++++++++++++++++++++++---------
>   drivers/scsi/qla2xxx/qla_mbx.c |  22 +++++--
>   drivers/scsi/qla2xxx/qla_os.c  |  19 ++++--
>   5 files changed, 136 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 172ea4e5887d..954d1a230b8a 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -1270,6 +1270,11 @@ static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
>   
>   #define ELS_CMD_MAP_SIZE	32
>   #define ELS_COMMAND_RDP		0x18
> +/* Fabric Perf Impact Notification */
> +#define ELS_COMMAND_FPIN	0x16
> +/* Read Diagnostic Functions */
> +#define ELS_COMMAND_RDF		0x19
> +#define ELS_COMMAND_PUN		0x31

You should use the definitions for FPIN, RDF from 
include/uapi/scsi/fc/fc_els.h.  And add PUN to the file.

Note datastructures for FPIN and RDF are there as well.

-- james


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-05-14 10:10 ` [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation Nilesh Javali
  2020-05-14 18:52   ` himanshu.madhani
@ 2020-05-15 22:48   ` James Smart
       [not found]     ` <CA+ihqdiA7AN05k5MjPG=o8_pf=L-La6UigY4t0emKgJMXm=hnQ@mail.gmail.com>
       [not found]     ` <CA+ihqdjtoA=1q7N0pg1TQDAMGo1XtNN8+XnO1qXORyqGYfpq=A@mail.gmail.com>
  1 sibling, 2 replies; 15+ messages in thread
From: James Smart @ 2020-05-15 22:48 UTC (permalink / raw)
  To: Nilesh Javali, martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream



On 5/14/2020 3:10 AM, Nilesh Javali wrote:
> From: Shyam Sundar <ssundar@marvell.com>
>
> * Firmware Initialization with SCM enabled based on NVRAM setting and
>    firmware support (About Firmware).
> * Enable PUREX and add support for fabric performance impact
>    notification(FPIN) handling.
> * Support for the following FPIN descriptors:
>    	1. Link Integrity Notification.
> 	2. Delivery Notification.
> 	3. Peer Congestion Notification.
> 	4. Congestion Notification.
> * Mark a device as slow when a Peer Congestion Notification is received.
> * Allocate a default purex item for each vha, to handle memory
>    allocation failures in ISR.

In general, there's a lot of generic things here that are done in 
driver-specific manners.

All the FPIN statistics should be added to the scsi fc transport objects 
and transport routines created to parse the fpin payloads and set 
statistics.  Also, statistics can be reported via sysfs on the transport 
object rather than creating vendor-specific bsg requests to obtain them.

In line with this - FPIN definitions should use the existing the 
existing common headers in include/uapi/fc/fc_els.h.  The file doesn't 
have the congestion fpin definitions, so rather than putting in a driver 
header - put the structure definitions in the common header.


>
> Signed-off-by: Shyam Sundar <ssundar@marvell.com>
> Signed-off-by: Arun Easi <aeasi@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
>   drivers/scsi/qla2xxx/qla_bsg.h  | 115 +++++++
>   drivers/scsi/qla2xxx/qla_dbg.c  |  13 +-
>   drivers/scsi/qla2xxx/qla_def.h  |  89 ++++++
>   drivers/scsi/qla2xxx/qla_fw.h   |   7 +-
>   drivers/scsi/qla2xxx/qla_gbl.h  |   1 +
>   drivers/scsi/qla2xxx/qla_init.c |   9 +-
>   drivers/scsi/qla2xxx/qla_isr.c  | 532 ++++++++++++++++++++++++++++++--
>   drivers/scsi/qla2xxx/qla_mbx.c  |  45 ++-
>   drivers/scsi/qla2xxx/qla_os.c   |  18 ++
>   9 files changed, 795 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> index 7594fad7b5b5..0b308859047c 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.h
> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> @@ -290,4 +290,119 @@ struct qla_active_regions {
>   	uint8_t reserved[32];
>   } __packed;
>   
> +#define SCM_LINK_EVENT_UNKNOWN			0x0
> +#define SCM_LINK_EVENT_LINK_FAILURE			0x1
> +#define SCM_LINK_EVENT_LOSS_OF_SYNC			0x2
> +#define SCM_LINK_EVENT_LOSS_OF_SIGNAL		0x3
> +#define SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR	0x4
> +#define SCM_LINK_EVENT_INVALID_TX_WORD		0x5
> +#define SCM_LINK_EVENT_INVALID_CRC			0x6
> +#define SCM_LINK_EVENT_DEVICE_SPECIFIC		0xF
> +#define SCM_LINK_EVENT_V1_SIZE			20

These should be the existing defines in the common fc_els.h header. Also 
make sure SCM_LINK_EVENT_V1_SIZE is actually used.

> +struct qla_scm_link_event {
> +	uint64_t	timestamp;
> +	uint16_t	event_type;
> +	uint16_t	event_modifier;
> +	uint32_t	event_threshold;
> +	uint32_t	event_count;
> +	uint8_t		reserved[12];
> +} __packed;
> +
> +#define SCM_DELIVERY_REASON_UNKNOWN		0x0
> +#define SCM_DELIVERY_REASON_TIMEOUT		0x1
> +#define SCM_DELIVERY_REASON_UNABLE_TO_ROUTE	0x2
> +#define SCM_DELIVERY_REASON_DEVICE_SPECIFIC	0xF
> +struct qla_scm_delivery_event {
> +	uint64_t	timestamp;
> +	uint32_t	delivery_reason;
> +	uint8_t		deliver_frame_hdr[24];
> +	uint8_t		reserved[28];
> +
> +} __packed;
> +
> +#define SCM_CONGESTION_EVENT_CLEAR		0x0
> +#define SCM_CONGESTION_EVENT_LOST_CREDIT	0x1
> +#define SCM_CONGESTION_EVENT_CREDIT_STALL	0x2
> +#define SCM_CONGESTION_EVENT_OVERSUBSCRIPTION	0x3
> +#define SCM_CONGESTION_EVENT_DEVICE_SPECIFIC	0xF
> +struct qla_scm_peer_congestion_event {
> +	uint64_t	timestamp;
> +	uint16_t	event_type;
> +	uint16_t	event_modifier;
> +	uint32_t	event_period;
> +	uint8_t		reserved[16];
> +} __packed;
> +
> +#define SCM_CONGESTION_SEVERITY_WARNING	0xF1
> +#define SCM_CONGESTION_SEVERITY_ERROR	0xF7
> +struct qla_scm_congestion_event {
> +	uint64_t	timestamp;
> +	uint16_t	event_type;
> +	uint16_t	event_modifier;
> +	uint32_t	event_period;
> +	uint8_t		severity;
> +	uint8_t		reserved[15];
> +} __packed;

I expect many of these defines also should map to std-defined defines, 
thus should be added to fc_els.h


> +
> +#define SCM_FLAG_RDF_REJECT		0x00
> +#define SCM_FLAG_RDF_COMPLETED		0x01
> +#define SCM_FLAG_BROCADE_CONNECTED	0x02
> +#define SCM_FLAG_CISCO_CONNECTED	0x04
> +
> +#define SCM_STATE_CONGESTION	0x1
> +#define SCM_STATE_DELIVERY		0x2
> +#define SCM_STATE_LINK_INTEGRITY	0x4
> +#define SCM_STATE_PEER_CONGESTION	0x8
> +
> +#define QLA_CON_PRIMITIVE_RECEIVED	0x1
> +#define QLA_CONGESTION_ARB_WARNING	0x1
> +#define QLA_CONGESTION_ARB_ALARM	0X2
> +struct qla_scm_port {
> +	uint32_t			current_events;
> +
> +	struct qla_scm_link_event	link_integrity;
> +	struct qla_scm_delivery_event	delivery;
> +	struct qla_scm_congestion_event	congestion;
> +	uint64_t			scm_congestion_alarm;
> +	uint64_t			scm_congestion_warning;
> +	uint8_t				scm_fabric_connection_flags;
> +	uint8_t				reserved[43];
> +} __packed;
> +
> +struct qla_scm_target {
> +	uint8_t		wwpn[8];
> +	uint32_t	current_events;
> +
> +	struct qla_scm_link_event		link_integrity;
> +	struct qla_scm_delivery_event		delivery;
> +	struct qla_scm_peer_congestion_event	peer_congestion;
> +
> +	uint32_t	link_failure_count;
> +	uint32_t	loss_of_sync_count;
> +	uint32_t        loss_of_signals_count;
> +	uint32_t        primitive_seq_protocol_err_count;
> +	uint32_t        invalid_transmission_word_count;
> +	uint32_t        invalid_crc_count;
> +
> +	uint32_t        delivery_failure_unknown;
> +	uint32_t        delivery_timeout;
> +	uint32_t        delivery_unable_to_route;
> +	uint32_t        delivery_failure_device_specific;
> +
> +	uint32_t        peer_congestion_clear;
> +	uint32_t        peer_congestion_lost_credit;
> +	uint32_t        peer_congestion_credit_stall;
> +	uint32_t        peer_congestion_oversubscription;
> +	uint32_t        peer_congestion_device_specific;
> +	uint32_t	link_unknown_event;
> +	uint32_t	link_device_specific_event;
> +	uint8_t		reserved[48];
> +} __packed;
> +

Q: what purpose are these shorter "meta" event structures serving ? Why 
hold onto (what I assume is) the last event.  Wouldn't something 
monitoring netlink and use of the existing fc_host_fpin_rcv() interface 
be enough ? it should see all events.


>   
> +#define SCM_EDC_ACC_RECEIVED		BIT_6
> +#define SCM_RDF_ACC_RECEIVED		BIT_7
> +#define SCM_NOTIFICATION_TYPE_LINK_INTEGRITY	0x00020001
> +#define SCM_NOTIFICATION_TYPE_DELIVERY		0x00020002
> +#define SCM_NOTIFICATION_TYPE_PEER_CONGESTION	0x00020003
> +#define SCM_NOTIFICATION_TYPE_CONGESTION	0x00020004
> +#define FPIN_DESCRIPTOR_HEADER_SIZE	4
> +#define FPIN_ELS_DESCRIPTOR_LIST_OFFSET	8
> +struct fpin_descriptor {
> +	__be32 descriptor_tag;
> +	__be32 descriptor_length;
> +	union {
> +		uint8_t common_detecting_port_name[WWN_SIZE];
> +		struct {
> +			uint8_t detecting_port_name[WWN_SIZE];
> +			uint8_t attached_port_name[WWN_SIZE];
> +			__be16 event_type;
> +			__be16 event_modifier;
> +			__be32 event_threshold;
> +			__be32 event_count;
> +			__be32 port_name_count;
> +			uint8_t port_name_list[1][WWN_SIZE];
> +		} link_integrity;
> +		struct {
> +			uint8_t detecting_port_name[WWN_SIZE];
> +			uint8_t attached_port_name[WWN_SIZE];
> +			__be32 delivery_reason_code;
> +		} delivery;
> +		struct {
> +			uint8_t detecting_port_name[WWN_SIZE];
> +			uint8_t attached_port_name[WWN_SIZE];
> +			__be16 event_type;
> +			__be16 event_modifier;
> +			__be32 event_period;
> +			__be32 port_name_count;
> +			uint8_t port_name_list[1][WWN_SIZE];
> +		} peer_congestion;
> +		struct {
> +			__be16 event_type;
> +			__be16 event_modifier;
> +			__be32 event_period;
> +			uint8_t severity;
> +			uint8_t reserved[3];
> +		} congestion;
> +	};
> +};

The fpin descriptor is already in the common fc_els.h header. Use it.  
And feel free to extend the common header definitions for the 
congestion/delivery events.


>   
> +void
> +qla_link_integrity_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> +				    fc_port_t *fcport)
> +{
> +	ql_log(ql_log_info, fcport->vha, 0x502d,
> +	       "Link Integrity Event Type %d for Port %8phN\n",
> +	       be16_to_cpu(fpin_desc->link_integrity.event_type),
> +	       fcport->port_name);
> +
> +	fcport->scm_stats.link_integrity.event_type =
> +	    be16_to_cpu(fpin_desc->link_integrity.event_type);
> +	fcport->scm_stats.link_integrity.event_modifier =
> +	    be16_to_cpu(fpin_desc->link_integrity.event_modifier);
> +	fcport->scm_stats.link_integrity.event_threshold =
> +	    be32_to_cpu(fpin_desc->link_integrity.event_threshold);
> +	fcport->scm_stats.link_integrity.event_count =
> +	    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +	fcport->scm_stats.link_integrity.timestamp = ktime_get_real_seconds();
> +
> +	fcport->scm_stats.current_events |= SCM_STATE_LINK_INTEGRITY;
> +	switch (be16_to_cpu(fpin_desc->link_integrity.event_type)) {
> +	case SCM_LINK_EVENT_UNKNOWN:
> +		fcport->scm_stats.link_unknown_event +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_LINK_FAILURE:
> +		fcport->scm_stats.link_failure_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_LOSS_OF_SYNC:
> +		fcport->scm_stats.loss_of_sync_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_LOSS_OF_SIGNAL:
> +		fcport->scm_stats.loss_of_signals_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR:
> +		fcport->scm_stats.primitive_seq_protocol_err_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_INVALID_TX_WORD:
> +		fcport->scm_stats.invalid_transmission_word_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_INVALID_CRC:
> +		fcport->scm_stats.invalid_crc_count +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	case SCM_LINK_EVENT_DEVICE_SPECIFIC:
> +		fcport->scm_stats.link_device_specific_event +=
> +		    be32_to_cpu(fpin_desc->link_integrity.event_count);
> +		break;
> +	}
> +}
> +

A prime example of a routine that should be put into the fc transport 
and a list of statistics that should be visible via sysfs on the 
transport host (aka port) object.


> +void
> +qla_scm_process_link_integrity_d(struct scsi_qla_host *vha,
> +				 struct fpin_descriptor *fpin_desc)
> +{
> ...
> +}
> +
> +void
> +qla_delivery_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> +			      fc_port_t *fcport)
> +{
> ...
> +}
> +
> +/*
> + * Process Delivery Notification Descriptor
> + */
> +void
> +qla_scm_process_delivery_notification_d(struct scsi_qla_host *vha,
> +					struct fpin_descriptor *fpin_desc)
> +{
> ...
> +}
> +
> ...
> +
> +void
> +qla_peer_congestion_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> +				     fc_port_t *fcport)
> +{
> ...
> +}
> +
> +/*
> + * Process Peer-Congestion Notification Descriptor
> + */
> +void
> +qla_scm_process_peer_congestion_notification_d(struct scsi_qla_host *vha,
> +					struct fpin_descriptor *fpin_desc)
> +{
> ...
> +}
> +
> +/*
> + * qla_scm_process_congestion_notification_d() - Process
> + * Process Congestion Notification Descriptor
> + * @rsp: response queue
> + * @pkt: Entry pointer
> + */
> +void
> +qla_scm_process_congestion_notification_d(struct scsi_qla_host *vha,
> +					  struct fpin_descriptor *fpin_desc)
> ...
> +}

Same comment as prior - should be in scsi fc transport routines and 
stats set on appropriate transport object

-- james


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
       [not found]       ` <BYAPR18MB2805AEA357302FCFA20D2B57B48F0@BYAPR18MB2805.namprd18.prod.outlook.com>
@ 2020-06-11 17:42         ` Shyam Sundar
  2020-06-25 23:25           ` James Smart
  0 siblings, 1 reply; 15+ messages in thread
From: Shyam Sundar @ 2020-06-11 17:42 UTC (permalink / raw)
  To: james.smart
  Cc: Nilesh Javali, Martin K . Petersen, GR-QLogic-Storage-Upstream,
	linux-scsi, Arun Easi

Seems like this (and a previous email) never made it to the reflector, resending.

The suggestions make sense to me, and I have made most of the recommended changes.
I was looking for some guidance on placements of the sim stats structures.

> On May 29, 2020, at 11:53 AM, Shyam Sundar <ssundar@marvell.com> wrote:
> 
> James,
>      I was thinking of adding a structures for tracking the target FPIN stats.
> 
> struct fc_rport_statistics {
> uint32_t link_failure_count;
> uint32_t loss_of_sync_count;
> ....
> }
> 
> under fc_rport:
> 
> struct fc_rport {
> 
> /* Private (Transport-managed) Attributes */
> struct fc_rport_statistics;
> 
>      For host FPIN stats (essentially the alarm & warning), was not sure if I should add them to the fc_host_statistics or
> define a new structure under the Private Attributes section within the fc_host_attrs/fc_vport.
> 
>      In theory, given that the host stats could be updated both via signals and FPIN, one could argue that it would make sense
> to maintain it with the current host statistics, but keeping it confined to transport will ensure we have a uniform way of handling
> congestion and peer congestion events.  
> 
>     Would appreciate your thoughts there.
> 
> Thanks
> Shyam
>    
> ---------- Forwarded message ---------
> From: James Smart <james.smart@broadcom.com>
> Date: Fri, May 15, 2020 at 3:51 PM
> Subject: Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
> To: Nilesh Javali <njavali@marvell.com>, <martin.petersen@oracle.com>
> Cc: <linux-scsi@vger.kernel.org>, <GR-QLogic-Storage-Upstream@marvell.com>
> 
> 
> 
> 
> On 5/14/2020 3:10 AM, Nilesh Javali wrote:
> > From: Shyam Sundar <ssundar@marvell.com>
> >
> > * Firmware Initialization with SCM enabled based on NVRAM setting and
> >    firmware support (About Firmware).
> > * Enable PUREX and add support for fabric performance impact
> >    notification(FPIN) handling.
> > * Support for the following FPIN descriptors:
> >       1. Link Integrity Notification.
> >       2. Delivery Notification.
> >       3. Peer Congestion Notification.
> >       4. Congestion Notification.
> > * Mark a device as slow when a Peer Congestion Notification is received.
> > * Allocate a default purex item for each vha, to handle memory
> >    allocation failures in ISR.
> 
> In general, there's a lot of generic things here that are done in 
> driver-specific manners.
> 
> All the FPIN statistics should be added to the scsi fc transport objects 
> and transport routines created to parse the fpin payloads and set 
> statistics.  Also, statistics can be reported via sysfs on the transport 
> object rather than creating vendor-specific bsg requests to obtain them.
> 
> In line with this - FPIN definitions should use the existing the 
> existing common headers in include/uapi/fc/fc_els.h.  The file doesn't 
> have the congestion fpin definitions, so rather than putting in a driver 
> header - put the structure definitions in the common header.
> 
> 
> >
> > Signed-off-by: Shyam Sundar <ssundar@marvell.com>
> > Signed-off-by: Arun Easi <aeasi@marvell.com>
> > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > ---
> >   drivers/scsi/qla2xxx/qla_bsg.h  | 115 +++++++
> >   drivers/scsi/qla2xxx/qla_dbg.c  |  13 +-
> >   drivers/scsi/qla2xxx/qla_def.h  |  89 ++++++
> >   drivers/scsi/qla2xxx/qla_fw.h   |   7 +-
> >   drivers/scsi/qla2xxx/qla_gbl.h  |   1 +
> >   drivers/scsi/qla2xxx/qla_init.c |   9 +-
> >   drivers/scsi/qla2xxx/qla_isr.c  | 532 ++++++++++++++++++++++++++++++--
> >   drivers/scsi/qla2xxx/qla_mbx.c  |  45 ++-
> >   drivers/scsi/qla2xxx/qla_os.c   |  18 ++
> >   9 files changed, 795 insertions(+), 34 deletions(-)
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> > index 7594fad7b5b5..0b308859047c 100644
> > --- a/drivers/scsi/qla2xxx/qla_bsg.h
> > +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> > @@ -290,4 +290,119 @@ struct qla_active_regions {
> >       uint8_t reserved[32];
> >   } __packed;
> >   
> > +#define SCM_LINK_EVENT_UNKNOWN                       0x0
> > +#define SCM_LINK_EVENT_LINK_FAILURE                  0x1
> > +#define SCM_LINK_EVENT_LOSS_OF_SYNC                  0x2
> > +#define SCM_LINK_EVENT_LOSS_OF_SIGNAL                0x3
> > +#define SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR  0x4
> > +#define SCM_LINK_EVENT_INVALID_TX_WORD               0x5
> > +#define SCM_LINK_EVENT_INVALID_CRC                   0x6
> > +#define SCM_LINK_EVENT_DEVICE_SPECIFIC               0xF
> > +#define SCM_LINK_EVENT_V1_SIZE                       20
> 
> These should be the existing defines in the common fc_els.h header. Also 
> make sure SCM_LINK_EVENT_V1_SIZE is actually used.
> 
> > +struct qla_scm_link_event {
> > +     uint64_t        timestamp;
> > +     uint16_t        event_type;
> > +     uint16_t        event_modifier;
> > +     uint32_t        event_threshold;
> > +     uint32_t        event_count;
> > +     uint8_t         reserved[12];
> > +} __packed;
> > +
> > +#define SCM_DELIVERY_REASON_UNKNOWN          0x0
> > +#define SCM_DELIVERY_REASON_TIMEOUT          0x1
> > +#define SCM_DELIVERY_REASON_UNABLE_TO_ROUTE  0x2
> > +#define SCM_DELIVERY_REASON_DEVICE_SPECIFIC  0xF
> > +struct qla_scm_delivery_event {
> > +     uint64_t        timestamp;
> > +     uint32_t        delivery_reason;
> > +     uint8_t         deliver_frame_hdr[24];
> > +     uint8_t         reserved[28];
> > +
> > +} __packed;
> > +
> > +#define SCM_CONGESTION_EVENT_CLEAR           0x0
> > +#define SCM_CONGESTION_EVENT_LOST_CREDIT     0x1
> > +#define SCM_CONGESTION_EVENT_CREDIT_STALL    0x2
> > +#define SCM_CONGESTION_EVENT_OVERSUBSCRIPTION        0x3
> > +#define SCM_CONGESTION_EVENT_DEVICE_SPECIFIC 0xF
> > +struct qla_scm_peer_congestion_event {
> > +     uint64_t        timestamp;
> > +     uint16_t        event_type;
> > +     uint16_t        event_modifier;
> > +     uint32_t        event_period;
> > +     uint8_t         reserved[16];
> > +} __packed;
> > +
> > +#define SCM_CONGESTION_SEVERITY_WARNING      0xF1
> > +#define SCM_CONGESTION_SEVERITY_ERROR        0xF7
> > +struct qla_scm_congestion_event {
> > +     uint64_t        timestamp;
> > +     uint16_t        event_type;
> > +     uint16_t        event_modifier;
> > +     uint32_t        event_period;
> > +     uint8_t         severity;
> > +     uint8_t         reserved[15];
> > +} __packed;
> 
> I expect many of these defines also should map to std-defined defines, 
> thus should be added to fc_els.h
> 
> 
> > +
> > +#define SCM_FLAG_RDF_REJECT          0x00
> > +#define SCM_FLAG_RDF_COMPLETED               0x01
> > +#define SCM_FLAG_BROCADE_CONNECTED   0x02
> > +#define SCM_FLAG_CISCO_CONNECTED     0x04
> > +
> > +#define SCM_STATE_CONGESTION 0x1
> > +#define SCM_STATE_DELIVERY           0x2
> > +#define SCM_STATE_LINK_INTEGRITY     0x4
> > +#define SCM_STATE_PEER_CONGESTION    0x8
> > +
> > +#define QLA_CON_PRIMITIVE_RECEIVED   0x1
> > +#define QLA_CONGESTION_ARB_WARNING   0x1
> > +#define QLA_CONGESTION_ARB_ALARM     0X2
> > +struct qla_scm_port {
> > +     uint32_t                        current_events;
> > +
> > +     struct qla_scm_link_event       link_integrity;
> > +     struct qla_scm_delivery_event   delivery;
> > +     struct qla_scm_congestion_event congestion;
> > +     uint64_t                        scm_congestion_alarm;
> > +     uint64_t                        scm_congestion_warning;
> > +     uint8_t                         scm_fabric_connection_flags;
> > +     uint8_t                         reserved[43];
> > +} __packed;
> > +
> > +struct qla_scm_target {
> > +     uint8_t         wwpn[8];
> > +     uint32_t        current_events;
> > +
> > +     struct qla_scm_link_event               link_integrity;
> > +     struct qla_scm_delivery_event           delivery;
> > +     struct qla_scm_peer_congestion_event    peer_congestion;
> > +
> > +     uint32_t        link_failure_count;
> > +     uint32_t        loss_of_sync_count;
> > +     uint32_t        loss_of_signals_count;
> > +     uint32_t        primitive_seq_protocol_err_count;
> > +     uint32_t        invalid_transmission_word_count;
> > +     uint32_t        invalid_crc_count;
> > +
> > +     uint32_t        delivery_failure_unknown;
> > +     uint32_t        delivery_timeout;
> > +     uint32_t        delivery_unable_to_route;
> > +     uint32_t        delivery_failure_device_specific;
> > +
> > +     uint32_t        peer_congestion_clear;
> > +     uint32_t        peer_congestion_lost_credit;
> > +     uint32_t        peer_congestion_credit_stall;
> > +     uint32_t        peer_congestion_oversubscription;
> > +     uint32_t        peer_congestion_device_specific;
> > +     uint32_t        link_unknown_event;
> > +     uint32_t        link_device_specific_event;
> > +     uint8_t         reserved[48];
> > +} __packed;
> > +
> 
> Q: what purpose are these shorter "meta" event structures serving ? Why 
> hold onto (what I assume is) the last event.  Wouldn't something 
> monitoring netlink and use of the existing fc_host_fpin_rcv() interface 
> be enough ? it should see all events.
> 
> 
> >   
> > +#define SCM_EDC_ACC_RECEIVED         BIT_6
> > +#define SCM_RDF_ACC_RECEIVED         BIT_7
> > +#define SCM_NOTIFICATION_TYPE_LINK_INTEGRITY 0x00020001
> > +#define SCM_NOTIFICATION_TYPE_DELIVERY               0x00020002
> > +#define SCM_NOTIFICATION_TYPE_PEER_CONGESTION        0x00020003
> > +#define SCM_NOTIFICATION_TYPE_CONGESTION     0x00020004
> > +#define FPIN_DESCRIPTOR_HEADER_SIZE  4
> > +#define FPIN_ELS_DESCRIPTOR_LIST_OFFSET      8
> > +struct fpin_descriptor {
> > +     __be32 descriptor_tag;
> > +     __be32 descriptor_length;
> > +     union {
> > +             uint8_t common_detecting_port_name[WWN_SIZE];
> > +             struct {
> > +                     uint8_t detecting_port_name[WWN_SIZE];
> > +                     uint8_t attached_port_name[WWN_SIZE];
> > +                     __be16 event_type;
> > +                     __be16 event_modifier;
> > +                     __be32 event_threshold;
> > +                     __be32 event_count;
> > +                     __be32 port_name_count;
> > +                     uint8_t port_name_list[1][WWN_SIZE];
> > +             } link_integrity;
> > +             struct {
> > +                     uint8_t detecting_port_name[WWN_SIZE];
> > +                     uint8_t attached_port_name[WWN_SIZE];
> > +                     __be32 delivery_reason_code;
> > +             } delivery;
> > +             struct {
> > +                     uint8_t detecting_port_name[WWN_SIZE];
> > +                     uint8_t attached_port_name[WWN_SIZE];
> > +                     __be16 event_type;
> > +                     __be16 event_modifier;
> > +                     __be32 event_period;
> > +                     __be32 port_name_count;
> > +                     uint8_t port_name_list[1][WWN_SIZE];
> > +             } peer_congestion;
> > +             struct {
> > +                     __be16 event_type;
> > +                     __be16 event_modifier;
> > +                     __be32 event_period;
> > +                     uint8_t severity;
> > +                     uint8_t reserved[3];
> > +             } congestion;
> > +     };
> > +};
> 
> The fpin descriptor is already in the common fc_els.h header. Use it.  
> And feel free to extend the common header definitions for the 
> congestion/delivery events.
> 
> 
> >   
> > +void
> > +qla_link_integrity_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> > +                                 fc_port_t *fcport)
> > +{
> > +     ql_log(ql_log_info, fcport->vha, 0x502d,
> > +            "Link Integrity Event Type %d for Port %8phN\n",
> > +            be16_to_cpu(fpin_desc->link_integrity.event_type),
> > +            fcport->port_name);
> > +
> > +     fcport->scm_stats.link_integrity.event_type =
> > +         be16_to_cpu(fpin_desc->link_integrity.event_type);
> > +     fcport->scm_stats.link_integrity.event_modifier =
> > +         be16_to_cpu(fpin_desc->link_integrity.event_modifier);
> > +     fcport->scm_stats.link_integrity.event_threshold =
> > +         be32_to_cpu(fpin_desc->link_integrity.event_threshold);
> > +     fcport->scm_stats.link_integrity.event_count =
> > +         be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +     fcport->scm_stats.link_integrity.timestamp = ktime_get_real_seconds();
> > +
> > +     fcport->scm_stats.current_events |= SCM_STATE_LINK_INTEGRITY;
> > +     switch (be16_to_cpu(fpin_desc->link_integrity.event_type)) {
> > +     case SCM_LINK_EVENT_UNKNOWN:
> > +             fcport->scm_stats.link_unknown_event +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_LINK_FAILURE:
> > +             fcport->scm_stats.link_failure_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_LOSS_OF_SYNC:
> > +             fcport->scm_stats.loss_of_sync_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_LOSS_OF_SIGNAL:
> > +             fcport->scm_stats.loss_of_signals_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_PRIMITIVE_SEQ_PROTOCOL_ERROR:
> > +             fcport->scm_stats.primitive_seq_protocol_err_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_INVALID_TX_WORD:
> > +             fcport->scm_stats.invalid_transmission_word_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_INVALID_CRC:
> > +             fcport->scm_stats.invalid_crc_count +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     case SCM_LINK_EVENT_DEVICE_SPECIFIC:
> > +             fcport->scm_stats.link_device_specific_event +=
> > +                 be32_to_cpu(fpin_desc->link_integrity.event_count);
> > +             break;
> > +     }
> > +}
> > +
> 
> A prime example of a routine that should be put into the fc transport 
> and a list of statistics that should be visible via sysfs on the 
> transport host (aka port) object.
> 
> 
> > +void
> > +qla_scm_process_link_integrity_d(struct scsi_qla_host *vha,
> > +                              struct fpin_descriptor *fpin_desc)
> > +{
> > ...
> > +}
> > +
> > +void
> > +qla_delivery_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> > +                           fc_port_t *fcport)
> > +{
> > ...
> > +}
> > +
> > +/*
> > + * Process Delivery Notification Descriptor
> > + */
> > +void
> > +qla_scm_process_delivery_notification_d(struct scsi_qla_host *vha,
> > +                                     struct fpin_descriptor *fpin_desc)
> > +{
> > ...
> > +}
> > +
> > ...
> > +
> > +void
> > +qla_peer_congestion_tgt_stats_update(struct fpin_descriptor *fpin_desc,
> > +                                  fc_port_t *fcport)
> > +{
> > ...
> > +}
> > +
> > +/*
> > + * Process Peer-Congestion Notification Descriptor
> > + */
> > +void
> > +qla_scm_process_peer_congestion_notification_d(struct scsi_qla_host *vha,
> > +                                     struct fpin_descriptor *fpin_desc)
> > +{
> > ...
> > +}
> > +
> > +/*
> > + * qla_scm_process_congestion_notification_d() - Process
> > + * Process Congestion Notification Descriptor
> > + * @rsp: response queue
> > + * @pkt: Entry pointer
> > + */
> > +void
> > +qla_scm_process_congestion_notification_d(struct scsi_qla_host *vha,
> > +                                       struct fpin_descriptor *fpin_desc)
> > ...
> > +}
> 
> Same comment as prior - should be in scsi fc transport routines and 
> stats set on appropriate transport object
> 
> -- james


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
       [not found]     ` <CA+ihqdjtoA=1q7N0pg1TQDAMGo1XtNN8+XnO1qXORyqGYfpq=A@mail.gmail.com>
@ 2020-06-11 18:10       ` Shyam S
  0 siblings, 0 replies; 15+ messages in thread
From: Shyam S @ 2020-06-11 18:10 UTC (permalink / raw)
  To: James Smart
  Cc: Nilesh Javali, martin.petersen, linux-scsi, GR-QLogic-Storage-Upstream

Resending to the reflector.

On Mon, May 18, 2020 at 4:25 PM Shyam S <born27thfeb@gmail.com> wrote:
>
>
>>
>>
>> > Q: what purpose are these shorter "meta" event structures serving ? Why
>> > hold onto (what I assume is) the last event.  Wouldn't something
>> > monitoring netlink and use of the existing fc_host_fpin_rcv() interface
>> > be enough ? it should see all events.
>
>
> The Idea was to be able to have a longer term view within the driver so that while debugging issues, correlations can be made between symptoms exhibited by the driver with these statistics.
>
> All your other comments make complete sense to me. I'll re-work the changes to move them up the stack.
>
>
> Regards
> Shyam

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-06-11 17:42         ` Shyam Sundar
@ 2020-06-25 23:25           ` James Smart
  2020-06-26  0:14             ` Shyam Sundar
  2020-07-30 16:10             ` Shyam Sundar
  0 siblings, 2 replies; 15+ messages in thread
From: James Smart @ 2020-06-25 23:25 UTC (permalink / raw)
  To: Shyam Sundar
  Cc: Nilesh Javali, Martin K . Petersen, GR-QLogic-Storage-Upstream,
	linux-scsi, Arun Easi



On 6/11/2020 10:42 AM, Shyam Sundar wrote:
> Seems like this (and a previous email) never made it to the reflector, resending.
>
> The suggestions make sense to me, and I have made most of the recommended changes.
> I was looking for some guidance on placements of the sim stats structures.
>
>> On May 29, 2020, at 11:53 AM, Shyam Sundar <ssundar@marvell.com> wrote:
>>
>> James,
>>       I was thinking of adding a structures for tracking the target FPIN stats.
>>
>> struct fc_rport_statistics {
>> uint32_t link_failure_count;
>> uint32_t loss_of_sync_count;
>> ....
>> }
>>
>> under fc_rport:
>>
>> struct fc_rport {
>>
>> /* Private (Transport-managed) Attributes */
>> struct fc_rport_statistics;
>>
>>       For host FPIN stats (essentially the alarm & warning), was not sure if I should add them to the fc_host_statistics or
>> define a new structure under the Private Attributes section within the fc_host_attrs/fc_vport.

my initial thought was the same

>>
>>       In theory, given that the host stats could be updated both via signals and FPIN, one could argue that it would make sense
>> to maintain it with the current host statistics, but keeping it confined to transport will ensure we have a uniform way of handling
>> congestion and peer congestion events.

but then I have the same thoughts as well. And the commonization of the 
parsing and incrementing makes a lot more sense.

>>
>>      Would appreciate your thoughts there.
>>
>> Thanks
>> Shyam
>>     
>>


I would put them under the Dynamic attributes area in fc_host_attrs and 
fc_rport.
fc_host_attrs:
fpin_cn              incremented for each Congestion Notify FPIN
cn_sig_warn     incremented for each congestion warning signal
cn_sig_alarm    incremented for each congestion alarm signal
fpin_dn             incremented for each Delivery Notification FPIN 
where attached wwpn is local port
fpin_li                incremented for each Link Integrity FPIN where 
attached wwpn is local port

fc_rport:
fpin_dn             incremented for each Delivery Notification FPIN 
where attached wwpn is the rport
fpin_li               incremented for each Link Integrity FPIN where 
attached wwpn is the rport
fpin_pcn           incremented for each Peer Congestion Notify FPIN 
where attached wwpn is the rport

For the cn_sig_xxx values, the driver would just increment them.
For the fpin_xxx values - we'll augment the fc_host_fpin_rcv routine to 
parse the fpin and increment the fc_host or fc_rport counter.

-- james



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-06-25 23:25           ` James Smart
@ 2020-06-26  0:14             ` Shyam Sundar
  2020-07-30 16:10             ` Shyam Sundar
  1 sibling, 0 replies; 15+ messages in thread
From: Shyam Sundar @ 2020-06-26  0:14 UTC (permalink / raw)
  To: James Smart
  Cc: Nilesh Javali, Martin K . Petersen, GR-QLogic-Storage-Upstream,
	linux-scsi, Arun Easi



> On Jun 25, 2020, at 4:25 PM, James Smart <james.smart@broadcom.com> wrote:
> 
> 
> 
> On 6/11/2020 10:42 AM, Shyam Sundar wrote:
>> Seems like this (and a previous email) never made it to the reflector, resending.
>> 
>> The suggestions make sense to me, and I have made most of the recommended changes.
>> I was looking for some guidance on placements of the sim stats structures.
>> 
>>> On May 29, 2020, at 11:53 AM, Shyam Sundar <ssundar@marvell.com> wrote:
>>> 
>>> James,
>>>      I was thinking of adding a structures for tracking the target FPIN stats.
>>> 
>>> struct fc_rport_statistics {
>>> uint32_t link_failure_count;
>>> uint32_t loss_of_sync_count;
>>> ....
>>> }
>>> 
>>> under fc_rport:
>>> 
>>> struct fc_rport {
>>> 
>>> /* Private (Transport-managed) Attributes */
>>> struct fc_rport_statistics;
>>> 
>>>      For host FPIN stats (essentially the alarm & warning), was not sure if I should add them to the fc_host_statistics or
>>> define a new structure under the Private Attributes section within the fc_host_attrs/fc_vport.
> 
> my initial thought was the same
> 
>>> 
>>>      In theory, given that the host stats could be updated both via signals and FPIN, one could argue that it would make sense
>>> to maintain it with the current host statistics, but keeping it confined to transport will ensure we have a uniform way of handling
>>> congestion and peer congestion events.
> 
> but then I have the same thoughts as well. And the commonization of the parsing and incrementing makes a lot more sense.
> 
>>> 
>>>     Would appreciate your thoughts there.
>>> 
>>> Thanks
>>> Shyam
>>>    
> 
> 
> I would put them under the Dynamic attributes area in fc_host_attrs and fc_rport.
> fc_host_attrs:
> fpin_cn              incremented for each Congestion Notify FPIN
> cn_sig_warn     incremented for each congestion warning signal
> cn_sig_alarm    incremented for each congestion alarm signal
> fpin_dn             incremented for each Delivery Notification FPIN where attached wwpn is local port
> fpin_li                incremented for each Link Integrity FPIN where attached wwpn is local port
> 
> fc_rport:
> fpin_dn             incremented for each Delivery Notification FPIN where attached wwpn is the rport
> fpin_li               incremented for each Link Integrity FPIN where attached wwpn is the rport
> fpin_pcn           incremented for each Peer Congestion Notify FPIN where attached wwpn is the rport
> 
> For the cn_sig_xxx values, the driver would just increment them.
> For the fpin_xxx values - we'll augment the fc_host_fpin_rcv routine to parse the fpin and increment the fc_host or fc_rport counter.

Sounds good. Will do.

Thanks
Shyam
 
> 
> -- james


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation.
  2020-06-25 23:25           ` James Smart
  2020-06-26  0:14             ` Shyam Sundar
@ 2020-07-30 16:10             ` Shyam Sundar
  1 sibling, 0 replies; 15+ messages in thread
From: Shyam Sundar @ 2020-07-30 16:10 UTC (permalink / raw)
  To: James Smart
  Cc: Nilesh Javali, Martin K . Petersen, GR-QLogic-Storage-Upstream,
	linux-scsi, Arun Easi

James,                                                                          
                                                                                
Please review the updated patchset to see if the changes make sense to you.                
There are a few deviations from what we discussed here.           
                                                                                
I have used a single structure definition to maintain all fpin statistics       
and we are maintain them at the granularity provided by the fabric instead of
Using a single counter per category. The same    
structure is used across the fc_host_attr and the fc_rport structures.          
                                                                                
Given that the congestion signals will have to be maintained by the LLDs,       
as we do not have the plumbing to push those notifications to the transport,    
I have added them to the fc_host_statistics maintained and filled in by the     
LLD. All of the stats are displayed under the "statistics" folder under the     
sysfs.                                                                          
                                                                                
Under the host stats, a subset of stats (the Link Integrity FPINs) are          
redundunt, and are already maintained, read via the traditional mechanism.      
I have rolled them in nonetheless because during testing, they did not        
update to the same values (using the FPIN error injection commands). If we      
determine that these values will be in sync consistently, we can remove one     
of the subset at a later point.                                                 
                                                                                
Regards                                                                         
Shyam                        

> On Jun 25, 2020, at 4:25 PM, James Smart <james.smart@broadcom.com> wrote:
> 
> 
> 
> On 6/11/2020 10:42 AM, Shyam Sundar wrote:
>> Seems like this (and a previous email) never made it to the reflector, resending.
>> 
>> The suggestions make sense to me, and I have made most of the recommended changes.
>> I was looking for some guidance on placements of the sim stats structures.
>> 
>>> On May 29, 2020, at 11:53 AM, Shyam Sundar <ssundar@marvell.com> wrote:
>>> 
>>> James,
>>>      I was thinking of adding a structures for tracking the target FPIN stats.
>>> 
>>> struct fc_rport_statistics {
>>> uint32_t link_failure_count;
>>> uint32_t loss_of_sync_count;
>>> ....
>>> }
>>> 
>>> under fc_rport:
>>> 
>>> struct fc_rport {
>>> 
>>> /* Private (Transport-managed) Attributes */
>>> struct fc_rport_statistics;
>>> 
>>>      For host FPIN stats (essentially the alarm & warning), was not sure if I should add them to the fc_host_statistics or
>>> define a new structure under the Private Attributes section within the fc_host_attrs/fc_vport.
> 
> my initial thought was the same
> 
>>> 
>>>      In theory, given that the host stats could be updated both via signals and FPIN, one could argue that it would make sense
>>> to maintain it with the current host statistics, but keeping it confined to transport will ensure we have a uniform way of handling
>>> congestion and peer congestion events.
> 
> but then I have the same thoughts as well. And the commonization of the parsing and incrementing makes a lot more sense.
> 
>>> 
>>>     Would appreciate your thoughts there.
>>> 
>>> Thanks
>>> Shyam
>>>    
> 
> 
> I would put them under the Dynamic attributes area in fc_host_attrs and fc_rport.
> fc_host_attrs:
> fpin_cn              incremented for each Congestion Notify FPIN
> cn_sig_warn     incremented for each congestion warning signal
> cn_sig_alarm    incremented for each congestion alarm signal
> fpin_dn             incremented for each Delivery Notification FPIN where attached wwpn is local port
> fpin_li                incremented for each Link Integrity FPIN where attached wwpn is local port
> 
> fc_rport:
> fpin_dn             incremented for each Delivery Notification FPIN where attached wwpn is the rport
> fpin_li               incremented for each Link Integrity FPIN where attached wwpn is the rport
> fpin_pcn           incremented for each Peer Congestion Notify FPIN where attached wwpn is the rport
> 
> For the cn_sig_xxx values, the driver would just increment them.
> For the fpin_xxx values - we'll augment the fc_host_fpin_rcv routine to parse the fpin and increment the fc_host or fc_rport counter.
> 
> -- james


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, back to index

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-14 10:10 [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Nilesh Javali
2020-05-14 10:10 ` [PATCH 1/3] qla2xxx: Change in PUREX to handle FPIN ELS requests Nilesh Javali
2020-05-14 17:03   ` himanshu.madhani
2020-05-15 18:52   ` James Smart
2020-05-14 10:10 ` [PATCH 2/3] qla2xxx: SAN congestion management(SCM) implementation Nilesh Javali
2020-05-14 18:52   ` himanshu.madhani
2020-05-15 22:48   ` James Smart
     [not found]     ` <CA+ihqdiA7AN05k5MjPG=o8_pf=L-La6UigY4t0emKgJMXm=hnQ@mail.gmail.com>
     [not found]       ` <BYAPR18MB2805AEA357302FCFA20D2B57B48F0@BYAPR18MB2805.namprd18.prod.outlook.com>
2020-06-11 17:42         ` Shyam Sundar
2020-06-25 23:25           ` James Smart
2020-06-26  0:14             ` Shyam Sundar
2020-07-30 16:10             ` Shyam Sundar
     [not found]     ` <CA+ihqdjtoA=1q7N0pg1TQDAMGo1XtNN8+XnO1qXORyqGYfpq=A@mail.gmail.com>
2020-06-11 18:10       ` Shyam S
2020-05-14 10:10 ` [PATCH 3/3] qla2xxx: Pass SCM counters to the application Nilesh Javali
2020-05-14 19:15   ` himanshu.madhani
2020-05-14 14:11 ` [PATCH 0/3] qla2xxx SAN Congestion Management (SCM) support Bart Van Assche

Linux-SCSI Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-scsi/0 linux-scsi/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-scsi linux-scsi/ https://lore.kernel.org/linux-scsi \
		linux-scsi@vger.kernel.org
	public-inbox-index linux-scsi

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-scsi


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git