Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Oct 2017 20:22:01 +0000 (UTC)
From:      David C Somayajulu <davidcs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324538 - head/sys/dev/qlxgbe
Message-ID:  <201710112022.v9BKM1g2068880@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidcs
Date: Wed Oct 11 20:22:01 2017
New Revision: 324538
URL: https://svnweb.freebsd.org/changeset/base/324538

Log:
  Added support driver state capture/retrieval
  
  MFC after:5 days

Modified:
  head/sys/dev/qlxgbe/ql_def.h
  head/sys/dev/qlxgbe/ql_glbl.h
  head/sys/dev/qlxgbe/ql_hw.h
  head/sys/dev/qlxgbe/ql_ioctl.c
  head/sys/dev/qlxgbe/ql_ioctl.h
  head/sys/dev/qlxgbe/ql_os.c
  head/sys/dev/qlxgbe/ql_ver.h

Modified: head/sys/dev/qlxgbe/ql_def.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_def.h	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_def.h	Wed Oct 11 20:22:01 2017	(r324538)
@@ -201,7 +201,6 @@ struct qla_host {
 
 	qla_rx_buf_t		*rxb_free;
 	uint32_t		rxb_free_count;
-	volatile uint32_t	posting;
 
 	/* stats */
 	uint32_t		err_m_getcl;

Modified: head/sys/dev/qlxgbe/ql_glbl.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_glbl.h	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_glbl.h	Wed Oct 11 20:22:01 2017	(r324538)
@@ -112,4 +112,8 @@ extern unsigned int ql83xx_resetseq_len;
 extern unsigned char ql83xx_minidump[];
 extern unsigned int ql83xx_minidump_len;
 
+extern void ql_alloc_drvr_state_buffer(qla_host_t *ha);
+extern void ql_free_drvr_state_buffer(qla_host_t *ha);
+extern void ql_capture_drvr_state(qla_host_t *ha);
+
 #endif /* #ifndef_QL_GLBL_H_ */

Modified: head/sys/dev/qlxgbe/ql_hw.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_hw.h	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_hw.h	Wed Oct 11 20:22:01 2017	(r324538)
@@ -1703,6 +1703,9 @@ typedef struct _qla_hw {
 	uint32_t	mdump_buffer_size;
 	void		*mdump_template;
 	uint32_t	mdump_template_size;
+
+	/* driver state related */
+	void		*drvr_state;
 } qla_hw_t;
 
 #define QL_UPDATE_RDS_PRODUCER_INDEX(ha, prod_reg, val) \

Modified: head/sys/dev/qlxgbe/ql_ioctl.c
==============================================================================
--- head/sys/dev/qlxgbe/ql_ioctl.c	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_ioctl.c	Wed Oct 11 20:22:01 2017	(r324538)
@@ -39,7 +39,11 @@ __FBSDID("$FreeBSD$");
 #include "ql_inline.h"
 #include "ql_glbl.h"
 #include "ql_ioctl.h"
+#include "ql_ver.h"
+#include "ql_dbg.h"
 
+static int ql_drvr_state(qla_host_t *ha, qla_driver_state_t *drvr_state);
+static uint32_t ql_drvr_state_size(qla_host_t *ha);
 static int ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
 		struct thread *td);
 
@@ -279,6 +283,10 @@ ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, 
 			rval = ENXIO;
 		break;
 
+	case QLA_RD_DRVR_STATE:
+		rval = ql_drvr_state(ha, (qla_driver_state_t *)data);
+		break;
+
 	case QLA_RD_PCI_IDS:
 		pci_ids = (qla_rd_pci_ids_t *)data;
 		pci_ids->ven_id = pci_get_vendor(pci_dev);
@@ -293,5 +301,225 @@ ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, 
         }
 
         return rval;
+}
+
+
+static int
+ql_drvr_state(qla_host_t *ha, qla_driver_state_t *state)
+{
+	int rval = 0;
+	uint32_t drvr_state_size;
+	qla_drvr_state_hdr_t *hdr;
+
+	drvr_state_size = ql_drvr_state_size(ha);
+
+	if (state->buffer == NULL) {
+		state->size = drvr_state_size;
+		return (0);
+	}
+		
+	if (state->size < drvr_state_size)
+		return (ENXIO);
+
+	if (ha->hw.drvr_state == NULL)
+		return (ENOMEM);
+
+	hdr = ha->hw.drvr_state;
+
+	if (!hdr->drvr_version_major)
+		ql_capture_drvr_state(ha);
+
+	rval = copyout(ha->hw.drvr_state, state->buffer, drvr_state_size);
+
+	bzero(ha->hw.drvr_state, drvr_state_size);
+
+	return (rval);
+}
+
+static uint32_t
+ql_drvr_state_size(qla_host_t *ha)
+{
+	uint32_t drvr_state_size;
+	uint32_t size;
+
+	size = sizeof (qla_drvr_state_hdr_t);
+	drvr_state_size = QL_ALIGN(size, 64);
+
+	size =  ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t));
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	size =  ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t));
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	size =  ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t));
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS * ha->hw.num_tx_rings;
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS * ha->hw.num_rds_rings;
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS *
+			ha->hw.num_sds_rings;
+	drvr_state_size += QL_ALIGN(size, 64);
+
+	return (drvr_state_size);
+}
+
+static void
+ql_get_tx_state(qla_host_t *ha, qla_drvr_state_tx_t *tx_state)
+{
+	int i;
+
+	for (i = 0; i < ha->hw.num_tx_rings; i++) {
+		tx_state->base_p_addr = ha->hw.tx_cntxt[i].tx_ring_paddr;
+		tx_state->cons_p_addr = ha->hw.tx_cntxt[i].tx_cons_paddr;
+		tx_state->tx_prod_reg = ha->hw.tx_cntxt[i].tx_prod_reg;
+		tx_state->tx_cntxt_id = ha->hw.tx_cntxt[i].tx_cntxt_id;
+		tx_state->txr_free = ha->hw.tx_cntxt[i].txr_free;
+		tx_state->txr_next = ha->hw.tx_cntxt[i].txr_next;
+		tx_state->txr_comp = ha->hw.tx_cntxt[i].txr_comp;
+		tx_state++;
+	}
+	return;
+}
+
+static void
+ql_get_rx_state(qla_host_t *ha, qla_drvr_state_rx_t *rx_state)
+{
+	int i;
+
+	for (i = 0; i < ha->hw.num_rds_rings; i++) {
+		rx_state->prod_std = ha->hw.rds[i].prod_std;
+		rx_state->rx_next = ha->hw.rds[i].rx_next;
+		rx_state++;
+	}
+	return;
+}
+
+static void
+ql_get_sds_state(qla_host_t *ha, qla_drvr_state_sds_t *sds_state)
+{
+	int i;
+
+	for (i = 0; i < ha->hw.num_sds_rings; i++) {
+		sds_state->sdsr_next = ha->hw.sds[i].sdsr_next;
+		sds_state->sds_consumer = ha->hw.sds[i].sds_consumer;
+		sds_state++;
+	}
+	return;
+}
+
+void
+ql_capture_drvr_state(qla_host_t *ha)
+{
+	uint8_t *state_buffer;
+	uint8_t *ptr;
+	uint32_t drvr_state_size;
+	qla_drvr_state_hdr_t *hdr;
+	uint32_t size;
+	int i;
+
+	drvr_state_size = ql_drvr_state_size(ha);
+
+	state_buffer =  ha->hw.drvr_state;
+
+	if (state_buffer == NULL)
+		return;
+	
+	bzero(state_buffer, drvr_state_size);
+
+	hdr = (qla_drvr_state_hdr_t *)state_buffer;
+
+	hdr->drvr_version_major = QLA_VERSION_MAJOR;
+	hdr->drvr_version_minor = QLA_VERSION_MINOR;
+	hdr->drvr_version_build = QLA_VERSION_BUILD;
+
+	bcopy(ha->hw.mac_addr, hdr->mac_addr, ETHER_ADDR_LEN);
+
+	hdr->link_speed = ha->hw.link_speed;
+	hdr->cable_length = ha->hw.cable_length;
+	hdr->cable_oui = ha->hw.cable_oui;
+	hdr->link_up = ha->hw.link_up;
+	hdr->module_type = ha->hw.module_type;
+	hdr->link_faults = ha->hw.link_faults;
+	hdr->rcv_intr_coalesce = ha->hw.rcv_intr_coalesce;
+	hdr->xmt_intr_coalesce = ha->hw.xmt_intr_coalesce;
+
+	size = sizeof (qla_drvr_state_hdr_t);
+	hdr->tx_state_offset = QL_ALIGN(size, 64);
+
+	ptr = state_buffer + hdr->tx_state_offset;
+
+	ql_get_tx_state(ha, (qla_drvr_state_tx_t *)ptr);
+
+	size =  ha->hw.num_tx_rings * (sizeof (qla_drvr_state_tx_t));
+	hdr->rx_state_offset = hdr->tx_state_offset + QL_ALIGN(size, 64);
+	ptr = state_buffer + hdr->rx_state_offset;
+
+	ql_get_rx_state(ha, (qla_drvr_state_rx_t *)ptr);
+
+	size =  ha->hw.num_rds_rings * (sizeof (qla_drvr_state_rx_t));
+	hdr->sds_state_offset = hdr->rx_state_offset + QL_ALIGN(size, 64);
+	ptr = state_buffer + hdr->sds_state_offset;
+
+	ql_get_sds_state(ha, (qla_drvr_state_sds_t *)ptr);
+
+	size =  ha->hw.num_sds_rings * (sizeof (qla_drvr_state_sds_t));
+	hdr->txr_offset = hdr->sds_state_offset + QL_ALIGN(size, 64);
+	ptr = state_buffer + hdr->txr_offset;
+
+	hdr->num_tx_rings = ha->hw.num_tx_rings;
+	hdr->txr_size = sizeof(q80_tx_cmd_t) * NUM_TX_DESCRIPTORS;
+	hdr->txr_entries = NUM_TX_DESCRIPTORS;
+
+	size = hdr->num_tx_rings * hdr->txr_size;
+	bcopy(ha->hw.dma_buf.tx_ring.dma_b, ptr, size);
+
+	hdr->rxr_offset = hdr->txr_offset + QL_ALIGN(size, 64);
+	ptr = state_buffer + hdr->rxr_offset;
+
+	hdr->rxr_size = sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS;
+	hdr->rxr_entries = NUM_RX_DESCRIPTORS;
+	hdr->num_rx_rings = ha->hw.num_rds_rings;
+
+	for (i = 0; i < ha->hw.num_rds_rings; i++) {
+		bcopy(ha->hw.dma_buf.rds_ring[i].dma_b, ptr, hdr->rxr_size);
+		ptr += hdr->rxr_size;
+	}
+
+	size = hdr->rxr_size * hdr->num_rx_rings;
+	hdr->sds_offset = hdr->rxr_offset + QL_ALIGN(size, 64);
+	hdr->sds_ring_size = sizeof(q80_stat_desc_t) * NUM_STATUS_DESCRIPTORS;
+	hdr->sds_entries = NUM_STATUS_DESCRIPTORS;
+	hdr->num_sds_rings = ha->hw.num_sds_rings;
+
+	ptr = state_buffer + hdr->sds_offset;
+	for (i = 0; i < ha->hw.num_sds_rings; i++) {
+		bcopy(ha->hw.dma_buf.sds_ring[i].dma_b, ptr, hdr->sds_ring_size);
+		ptr += hdr->sds_ring_size;
+	}
+	return;
+}
+
+void
+ql_alloc_drvr_state_buffer(qla_host_t *ha)
+{
+	uint32_t drvr_state_size;
+
+	drvr_state_size = ql_drvr_state_size(ha);
+
+	ha->hw.drvr_state =  malloc(drvr_state_size, M_QLA83XXBUF, M_NOWAIT);	
+
+	return;
+}
+
+void
+ql_free_drvr_state_buffer(qla_host_t *ha)
+{
+	if (ha->hw.drvr_state != NULL)
+		free(ha->hw.drvr_state, M_QLA83XXBUF);
+	return;
 }
 

Modified: head/sys/dev/qlxgbe/ql_ioctl.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_ioctl.h	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_ioctl.h	Wed Oct 11 20:22:01 2017	(r324538)
@@ -93,6 +93,72 @@ struct qla_rd_fw_dump {
 };
 typedef struct qla_rd_fw_dump qla_rd_fw_dump_t;
 
+struct qla_drvr_state_tx {
+	uint64_t	base_p_addr;
+	uint64_t	cons_p_addr;
+	uint32_t	tx_prod_reg;
+	uint32_t	tx_cntxt_id;
+	uint32_t	txr_free;
+	uint32_t	txr_next;
+	uint32_t	txr_comp;
+};
+typedef struct qla_drvr_state_tx qla_drvr_state_tx_t;
+
+struct qla_drvr_state_sds {
+	uint32_t        sdsr_next; /* next entry in SDS ring to process */
+	uint32_t        sds_consumer;
+};
+typedef struct qla_drvr_state_sds qla_drvr_state_sds_t;
+
+struct qla_drvr_state_rx {
+	uint32_t	prod_std;
+	uint32_t	rx_next; /* next standard rcv ring to arm fw */;
+};
+typedef struct qla_drvr_state_rx qla_drvr_state_rx_t;
+
+struct qla_drvr_state_hdr {
+	uint32_t	drvr_version_major;
+	uint32_t	drvr_version_minor;
+	uint32_t	drvr_version_build;
+
+	uint8_t         mac_addr[ETHER_ADDR_LEN];
+        uint16_t        link_speed;
+        uint16_t        cable_length;
+        uint32_t        cable_oui;
+        uint8_t         link_up;
+        uint8_t         module_type;
+        uint8_t         link_faults;
+        uint32_t        rcv_intr_coalesce;
+        uint32_t        xmt_intr_coalesce;
+
+	uint32_t	tx_state_offset;/* size = sizeof (qla_drvr_state_tx_t) * num_tx_rings */
+	uint32_t	rx_state_offset;/* size = sizeof (qla_drvr_state_rx_t) * num_rx_rings */
+	uint32_t	sds_state_offset;/* size = sizeof (qla_drvr_state_sds_t) * num_sds_rings */
+
+	uint32_t	num_tx_rings; /* number of tx rings */
+	uint32_t	txr_size; /* size of each tx ring in bytes */
+	uint32_t	txr_entries; /* number of descriptors in each tx ring */
+	uint32_t	txr_offset; /* start of tx ring [0 - #rings] content */
+
+	uint32_t	num_rx_rings; /* number of rx rings */
+	uint32_t	rxr_size; /* size of each rx ring in bytes */
+	uint32_t	rxr_entries; /* number of descriptors in each rx ring */
+	uint32_t	rxr_offset; /* start of rx ring [0 - #rings] content */
+
+	uint32_t	num_sds_rings; /* number of sds rings */
+	uint32_t	sds_ring_size; /* size of each sds ring in bytes */
+	uint32_t	sds_entries; /* number of descriptors in each sds ring */
+	uint32_t	sds_offset; /* start of sds ring [0 - #rings] content */
+};
+
+typedef struct qla_drvr_state_hdr qla_drvr_state_hdr_t;
+
+struct qla_driver_state {
+	uint32_t	size;
+	void		*buffer;
+};
+typedef struct qla_driver_state qla_driver_state_t;
+
 /*
  * Read/Write Register
  */
@@ -132,5 +198,11 @@ typedef struct qla_rd_fw_dump qla_rd_fw_dump_t;
  * Read Minidump Template
  */
 #define QLA_RD_FW_DUMP		_IOWR('q', 8, qla_rd_fw_dump_t)
+
+/*
+ * Read Driver State
+ */
+#define QLA_RD_DRVR_STATE	_IOWR('q', 9, qla_driver_state_t)
+
 
 #endif /* #ifndef _QL_IOCTL_H_ */

Modified: head/sys/dev/qlxgbe/ql_os.c
==============================================================================
--- head/sys/dev/qlxgbe/ql_os.c	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_os.c	Wed Oct 11 20:22:01 2017	(r324538)
@@ -492,6 +492,7 @@ qla_pci_attach(device_t dev)
 		device_printf(dev, "%s: ql_minidump_init failed\n", __func__);
 		goto qla_pci_attach_err;
 	}
+	ql_alloc_drvr_state_buffer(ha);
 	/* create the o.s ethernet interface */
 	qla_init_ifnet(dev, ha);
 
@@ -645,6 +646,7 @@ qla_release(qla_host_t *ha)
 	if (ha->ifp != NULL)
 		ether_ifdetach(ha->ifp);
 
+	ql_free_drvr_state_buffer(ha);
 	ql_free_dma(ha); 
 	qla_free_parent_dma_tag(ha);
 

Modified: head/sys/dev/qlxgbe/ql_ver.h
==============================================================================
--- head/sys/dev/qlxgbe/ql_ver.h	Wed Oct 11 20:04:30 2017	(r324537)
+++ head/sys/dev/qlxgbe/ql_ver.h	Wed Oct 11 20:22:01 2017	(r324538)
@@ -36,6 +36,6 @@
 
 #define QLA_VERSION_MAJOR 	3
 #define QLA_VERSION_MINOR	10
-#define QLA_VERSION_BUILD       34
+#define QLA_VERSION_BUILD       35
 
 #endif /* #ifndef _QL_VER_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710112022.v9BKM1g2068880>