Author: davidcs
Date: Thu Oct 19 17:57:38 2017
New Revision: 324766
URL: https://svnweb.freebsd.org/changeset/base/324766

Log:
  MFC r324538
  Added support driver state capture/retrieval

Modified:
  stable/9/sys/dev/qlxgbe/ql_def.h
  stable/9/sys/dev/qlxgbe/ql_glbl.h
  stable/9/sys/dev/qlxgbe/ql_hw.h
  stable/9/sys/dev/qlxgbe/ql_ioctl.c
  stable/9/sys/dev/qlxgbe/ql_ioctl.h
  stable/9/sys/dev/qlxgbe/ql_os.c
  stable/9/sys/dev/qlxgbe/ql_ver.h
Directory Properties:
  stable/9/   (props changed)
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/qlxgbe/ql_def.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_def.h    Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_def.h    Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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;
@@ -264,7 +263,7 @@ struct qla_host {
 typedef struct qla_host qla_host_t;
 
 /* note that align has to be a power of 2 */
-#define QL_ALIGN(size, align) (size + (align - 1)) & ~(align - 1);
+#define QL_ALIGN(size, align) (((size) + ((align) - 1)) & (~((align) - 1)));
 #define QL_MIN(x, y) ((x < y) ? x : y)
 
 #define QL_RUNNING(ifp) (ifp->if_drv_flags & IFF_DRV_RUNNING)

Modified: stable/9/sys/dev/qlxgbe/ql_glbl.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_glbl.h   Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_glbl.h   Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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: stable/9/sys/dev/qlxgbe/ql_hw.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_hw.h     Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_hw.h     Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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: stable/9/sys/dev/qlxgbe/ql_ioctl.c
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_ioctl.c  Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_ioctl.c  Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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: stable/9/sys/dev/qlxgbe/ql_ioctl.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_ioctl.h  Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_ioctl.h  Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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: stable/9/sys/dev/qlxgbe/ql_os.c
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_os.c     Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_os.c     Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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: stable/9/sys/dev/qlxgbe/ql_ver.h
==============================================================================
--- stable/9/sys/dev/qlxgbe/ql_ver.h    Thu Oct 19 17:40:51 2017        
(r324765)
+++ stable/9/sys/dev/qlxgbe/ql_ver.h    Thu Oct 19 17:57:38 2017        
(r324766)
@@ -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_ */
_______________________________________________
svn-src-stable-9@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-9
To unsubscribe, send any mail to "svn-src-stable-9-unsubscr...@freebsd.org"

Reply via email to