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>