diff options
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/bnxt.h | 44 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/bnxt_mgmt.c | 378 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/bnxt_mgmt.h | 31 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/bnxt_ulp.c | 35 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/bnxt_ulp.h | 4 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_en/if_bnxt.c | 82 | ||||
| -rw-r--r-- | sys/dev/bnxt/bnxt_re/main.c | 65 |
7 files changed, 591 insertions, 48 deletions
diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h index b15cc65e290e..554e24563db6 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -829,10 +829,34 @@ struct bnxt_ctx_mem_type { #define BNXT_CTX_L2_MAX (BNXT_CTX_FTQM + 1) #define BNXT_CTX_V2_MAX (HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE + 1) -#define BNXT_CTX_SRT_TRACE HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT_TRACE -#define BNXT_CTX_ROCE_HWRM_TRACE HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE + +#define BNXT_CTX_SRT_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT_TRACE + +#define BNXT_CTX_SRT2_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_SRT2_TRACE + +#define BNXT_CTX_CRT_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CRT_TRACE + +#define BNXT_CTX_CRT2_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_CRT2_TRACE + +#define BNXT_CTX_RIGP0_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_RIGP0_TRACE + +#define BNXT_CTX_L2_HWRM_TRACE \ + HWRM_FUNC_BACKING_STORE_QCFG_V2_OUTPUT_TYPE_L2_HWRM_TRACE + +#define BNXT_CTX_ROCE_HWRM_TRACE \ + HWRM_FUNC_BACKING_STORE_CFG_V2_INPUT_TYPE_ROCE_HWRM_TRACE + #define BNXT_CTX_INV ((u16)-1) +#define BNXT_CTX_TRACE_BUF_COUNT \ + (BNXT_CTX_ROCE_HWRM_TRACE - BNXT_CTX_SRT_TRACE + 1) + + struct bnxt_ctx_mem_info { u8 tqm_fp_rings_count; @@ -1045,6 +1069,17 @@ struct bnxt_fw_health { #define DB_RING_IDX(ring, idx, bit) (((idx) & (ring)->db_ring_mask) | \ ((bit) << (24))) +struct bnxt_bs_trace_info { + u8 *magic_byte; +#define BNXT_TRACE_BUF_MAGIC_BYTE ((uint8_t)0xBC) + u32 last_offset; + u8 wrapped:1; + u16 ctx_type; + u16 trace_type; +}; + +struct bnxt_logger; + struct bnxt_softc { device_t dev; if_ctx_t ctx; @@ -1344,6 +1379,11 @@ struct bnxt_softc { struct bnxt_fw_health *fw_health; char board_partno[64]; + TAILQ_HEAD(, bnxt_logger) loggers_list; + void *debug_buf; + struct mtx log_lock; /* logging ops lock */ + struct callout time_sync_callout; + struct bnxt_bs_trace_info bs_trace[BNXT_CTX_TRACE_BUF_COUNT]; }; struct bnxt_filter_info { diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c index 98ae9848c42b..fd6d7b904dca 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c @@ -26,9 +26,10 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include "bnxt_mgmt.h" +#include "bnxt_mgmt.h" #include "bnxt.h" -#include "bnxt_hwrm.h" +#include "bnxt_hwrm.h" +#include "bnxt_log.h" #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <sys/endian.h> @@ -54,6 +55,217 @@ struct mtx mgmt_lock; MALLOC_DEFINE(M_BNXT, "bnxt_mgmt_buffer", "buffer for bnxt_mgmt module"); + +static uint32_t +bnxt_get_driver_coredump_len(struct bnxt_softc *softc) +{ + + uint32_t type, i, j, n; + uint32_t buf_size = 0; + int ctx_page_count = 0; + int segment_len = 0; + int driver_segment_record_len = 0; + uint32_t dump_len = 0; + int record_len = sizeof(struct bnxt_driver_segment_record); + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + + if (!ctx) + return (dump_len); + + for (type = BNXT_CTX_SRT_TRACE; type <= BNXT_CTX_ROCE_HWRM_TRACE; + type++) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + + if (!ctx_pg) + continue; + + if (ctxm->instance_bmap) + n = bitcount32(ctxm->instance_bmap); + else + n = 1; + + for (i = 0; i < n; i++) { + struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem; + + if (ctx_pg->nr_pages > MAX_CTX_PAGES || + ctx_pg->ctx_pg_tbl) { + int k = 0, nr_tbls = rmem->nr_pages; + + for (k = 0; k < nr_tbls; k++) { + struct bnxt_ctx_pg_info *pg_tbl; + struct bnxt_ring_mem_info *rmem2; + + pg_tbl = ctx_pg->ctx_pg_tbl[k]; + if (!pg_tbl) + continue; + rmem2 = &pg_tbl->ring_mem; + for (j = 0; j < rmem2->nr_pages; j++) { + if (!rmem2->pg_arr[j].idi_vaddr) + continue; + ctx_page_count++; + } + } + } else { + struct bnxt_ring_mem_info *rmem2 = rmem; + + for (j = 0; j < rmem2->nr_pages; j++) { + if (!rmem2->pg_arr[j].idi_vaddr) + continue; + ctx_page_count++; + } + } + } + segment_len += 64; + driver_segment_record_len += record_len; + } + + buf_size = driver_segment_record_len + segment_len + + (ctx_page_count * 4096); + + return (buf_size); +} + +inline void +bnxt_bs_trace_check_wrapping(struct bnxt_bs_trace_info *bs_trace, + u32 offset) +{ + if (!bs_trace->wrapped && + *bs_trace->magic_byte != BNXT_TRACE_BUF_MAGIC_BYTE) + bs_trace->wrapped = 1; + bs_trace->last_offset = offset; +} + + + +static int +bnxt_hwrm_dbg_log_buffer_flush(struct bnxt_softc *bp, u16 type, u32 flags, + u32 *offset) +{ + int status = 0; + + hwrm_dbg_log_buffer_flush_input_t buff_flush_req; + hwrm_dbg_log_buffer_flush_output_t *buff_flush_resp = + (hwrm_dbg_log_buffer_flush_output_t *)(void *) + bp->hwrm_cmd_resp.idi_vaddr; + bnxt_hwrm_cmd_hdr_init(bp, &buff_flush_req, HWRM_DBG_LOG_BUFFER_FLUSH); + buff_flush_req.type = type; + buff_flush_req.flags = flags; + + status = hwrm_send_message(bp, &buff_flush_req, sizeof(buff_flush_req)); + if (!status) + *offset = buff_flush_resp->current_buffer_offset; + return (status); +} + +static void +bnxt_fill_driver_segment_record(struct bnxt_softc *bp, + struct bnxt_driver_segment_record *drv_seg_rec, + struct bnxt_ctx_mem_type *ctxm, uint16_t type) +{ + struct bnxt_bs_trace_info *bs_trace = &bp->bs_trace[type]; + uint32_t offset; + + if (bnxt_hwrm_dbg_log_buffer_flush(bp, type, 0, &offset) == 0) { + bnxt_bs_trace_check_wrapping(bs_trace, offset); + } + drv_seg_rec->max_entries = ctxm->max_entries; + drv_seg_rec->entry_size = ctxm->entry_size; + drv_seg_rec->offset = bs_trace->last_offset; + drv_seg_rec->wrapped = bs_trace->wrapped; +} + +static void +bnxt_retrieve_driver_coredump(struct bnxt_softc *softc, void *buf, + uint16_t type, uint32_t *seg_len) +{ + struct bnxt_driver_segment_record drv_seg_rec = {0}; + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + uint32_t dump_len, data_offset, record_len, seg_hdr_len; + uint32_t i, j, k, n = 1, nr_tbls; + + dump_len = 0; + + record_len = sizeof(struct bnxt_driver_segment_record); + seg_hdr_len = sizeof(struct bnxt_coredump_segment_hdr); + data_offset = seg_hdr_len + record_len; + + bnxt_fill_driver_segment_record(softc, &drv_seg_rec, ctxm, + (type - BNXT_CTX_SRT_TRACE)); + + for (i = 0; i < n; i++) { + struct bnxt_ring_mem_info *rmem = &ctx_pg->ring_mem; + + if (ctx_pg->nr_pages > MAX_CTX_PAGES || ctx_pg->ctx_pg_tbl) { + nr_tbls = rmem->nr_pages; + for (j = 0; j < nr_tbls; j++) { + struct bnxt_ctx_pg_info *pg_tbl; + struct bnxt_ring_mem_info *rmem2; + + pg_tbl = ctx_pg->ctx_pg_tbl[j]; + if (!pg_tbl) + continue; + rmem2 = &pg_tbl->ring_mem; + for (k = 0; k < rmem2->nr_pages; k++) { + if (!rmem2->pg_arr[k].idi_vaddr) + continue; + memcpy((uint8_t *)buf + data_offset, + rmem2->pg_arr[k].idi_vaddr, + rmem2->page_size); + data_offset += rmem2->page_size; + dump_len += rmem2->page_size; + } + } + } else { + for (k = 0; k < rmem->nr_pages; k++) { + if (!rmem->pg_arr[k].idi_vaddr) + continue; + memcpy((uint8_t *)buf + data_offset, + rmem->pg_arr[k].idi_vaddr, + rmem->page_size); + data_offset += rmem->page_size; + dump_len += rmem->page_size; + } + } + } + memcpy((uint8_t *)buf + seg_hdr_len, &drv_seg_rec, record_len); + *seg_len = dump_len + record_len; +} + +void +bnxt_get_ctx_coredump(struct bnxt_softc *softc, void *buf) +{ + struct bnxt_ctx_mem_info *ctx = softc->ctx_mem; + struct bnxt_coredump_segment_hdr seg_hdr; + uint32_t type = 0, i = 0; + uint32_t seg_hdr_len = 0; + + seg_hdr_len = sizeof(seg_hdr); + for (type = BNXT_CTX_SRT_TRACE, i = DRV_SRT_TRACE_SEG_ID; + type <= BNXT_CTX_ROCE_HWRM_TRACE; type++, i++) { + struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type]; + uint16_t comp_id = DRV_COREDUMP_COMP_ID; + uint16_t seg_id = i; + uint32_t seg_len = 0; + + ctxm = &ctx->ctx_arr[type]; + + if (!(ctxm->flags & BNXT_CTX_MEM_TYPE_VALID) || + !ctxm->mem_valid) + continue; + + bnxt_retrieve_driver_coredump(softc, buf, type, &seg_len); + + bnxt_fill_coredump_seg_hdr(softc, &seg_hdr, NULL, seg_len, + 0, 0, 0, comp_id, seg_id); + + memcpy((uint8_t *)buf, &seg_hdr, seg_hdr_len); + buf = (uint8_t *)buf + seg_hdr_len + seg_len; + } +} + /* * This function is called by the kld[un]load(2) system calls to * determine what actions to take when a module is loaded or unloaded. @@ -76,7 +288,7 @@ bnxt_mgmt_loader(struct module *m, int what, void *arg) if (error != 0) { printf("%s: %s:%s:%d Failed to create the" "bnxt_mgmt device node\n", DRIVER_NAME, - __FILE__, __FUNCTION__, __LINE__); + __FILE__, __func__, __LINE__); return (error); } @@ -107,14 +319,14 @@ bnxt_mgmt_process_dcb(struct cdev *dev, u_long cmd, caddr_t data, memcpy(&user_ptr, data, sizeof(user_ptr)); if (copyin(user_ptr, &mgmt_dcb, sizeof(mgmt_dcb))) { printf("%s: %s:%d Failed to copy data from user\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -EFAULT; } softc = bnxt_find_dev(mgmt_dcb.hdr.domain, mgmt_dcb.hdr.bus, mgmt_dcb.hdr.devfn, NULL); if (!softc) { printf("%s: %s:%d unable to find softc reference\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -ENODEV; } @@ -144,14 +356,14 @@ bnxt_mgmt_process_dcb(struct cdev *dev, u_long cmd, caddr_t data, break; default: device_printf(softc->dev, "%s:%d Invalid op 0x%x\n", - __FUNCTION__, __LINE__, mgmt_dcb.op); + __func__, __LINE__, mgmt_dcb.op); ret = -EFAULT; goto end; } if (copyout(&mgmt_dcb, user_ptr, sizeof(mgmt_dcb))) { device_printf(softc->dev, "%s:%d Failed to copy response to user\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); ret = -EFAULT; goto end; } @@ -173,35 +385,35 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, uint16_t num_ind = 0; memcpy(&user_ptr, data, sizeof(user_ptr)); - if (copyin(user_ptr, &mgmt_req, sizeof(struct bnxt_mgmt_req))) { + if (copyin(user_ptr, &mgmt_req, sizeof(struct bnxt_mgmt_req))) { printf("%s: %s:%d Failed to copy data from user\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -EFAULT; } softc = bnxt_find_dev(mgmt_req.hdr.domain, mgmt_req.hdr.bus, mgmt_req.hdr.devfn, NULL); if (!softc) { printf("%s: %s:%d unable to find softc reference\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -ENODEV; } if (copyin((void*)mgmt_req.req.hreq, &msg_temp, sizeof(msg_temp))) { device_printf(softc->dev, "%s:%d Failed to copy data from user\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); return -EFAULT; } if (msg_temp.len_req > BNXT_MGMT_MAX_HWRM_REQ_LENGTH || msg_temp.len_resp > BNXT_MGMT_MAX_HWRM_RESP_LENGTH) { - device_printf(softc->dev, "%s:%d Invalid length\n", - __FUNCTION__, __LINE__); + device_printf(softc->dev, "%s:%d Invalid length\n", + __func__, __LINE__); return -EINVAL; } if (msg_temp.num_dma_indications > 1) { device_printf(softc->dev, "%s:%d Max num_dma_indications " - "supported is 1 \n", __FUNCTION__, __LINE__); + "supported is 1\n", __func__, __LINE__); return -EINVAL; } @@ -210,7 +422,7 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, if (copyin((void *)msg_temp.usr_req, req, msg_temp.len_req)) { device_printf(softc->dev, "%s:%d Failed to copy data from user\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); ret = -EFAULT; goto end; } @@ -222,35 +434,35 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, void *dma_ptr; uint64_t *dmap; - size = sizeof(struct bnxt_mgmt_fw_msg) + + size = sizeof(struct bnxt_mgmt_fw_msg) + (num_ind * sizeof(struct dma_info)); msg2 = malloc(size, M_BNXT, M_WAITOK | M_ZERO); - if (copyin((void *)mgmt_req.req.hreq, msg2, size)) { + if (copyin((void *)mgmt_req.req.hreq, msg2, size)) { device_printf(softc->dev, "%s:%d Failed to copy" - "data from user\n", __FUNCTION__, __LINE__); + "data from user\n", __func__, __LINE__); ret = -EFAULT; goto end; } msg = msg2; - + ret = iflib_dma_alloc(softc->ctx, msg->dma[0].length, &dma_data, BUS_DMA_NOWAIT); if (ret) { device_printf(softc->dev, "%s:%d iflib_dma_alloc" - "failed with ret = 0x%x\n", __FUNCTION__, + "failed with ret = 0x%x\n", __func__, __LINE__, ret); ret = -ENOMEM; goto end; } if (!(msg->dma[0].read_or_write)) { - if (copyin((void *)msg->dma[0].data, - dma_data.idi_vaddr, + if (copyin((void *)msg->dma[0].data, + dma_data.idi_vaddr, msg->dma[0].length)) { device_printf(softc->dev, "%s:%d Failed to copy" - "data from user\n", __FUNCTION__, + "data from user\n", __func__, __LINE__); ret = -EFAULT; goto end; @@ -260,27 +472,27 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data, dmap = dma_ptr; *dmap = htole64(dma_data.idi_paddr); } - + ret = bnxt_hwrm_passthrough(softc, req, msg->len_req, resp, msg->len_resp, msg->timeout); if(ret) goto end; - + if (num_ind) { if ((msg->dma[0].read_or_write)) { - if (copyout(dma_data.idi_vaddr, - (void *)msg->dma[0].data, + if (copyout(dma_data.idi_vaddr, + (void *)msg->dma[0].data, msg->dma[0].length)) { device_printf(softc->dev, "%s:%d Failed to copy data" - "to user\n", __FUNCTION__, __LINE__); + "to user\n", __func__, __LINE__); ret = -EFAULT; goto end; } } } - + if (copyout(resp, (void *) msg->usr_resp, msg->len_resp)) { device_printf(softc->dev, "%s:%d Failed to copy response to user\n", - __FUNCTION__, __LINE__); + __func__, __LINE__); ret = -EFAULT; goto end; } @@ -313,14 +525,14 @@ bnxt_mgmt_get_dev_info(struct cdev *dev, u_long cmd, caddr_t data, memcpy(&user_ptr, data, sizeof(user_ptr)); if (copyin(user_ptr, &dev_info, sizeof(dev_info))) { printf("%s: %s:%d Failed to copy data from user\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -EFAULT; } - + softc = bnxt_find_dev(0, 0, 0, dev_info.nic_info.dev_name); if (!softc) { printf("%s: %s:%d unable to find softc reference\n", - DRIVER_NAME, __FUNCTION__, __LINE__); + DRIVER_NAME, __func__, __LINE__); return -ENODEV; } @@ -339,7 +551,7 @@ bnxt_mgmt_get_dev_info(struct cdev *dev, u_long cmd, caddr_t data, dev_info.pci_info.chip_rev_id |= dev_info.pci_info.revision; if (pci_find_extcap(softc->dev, PCIZ_SERNUM, &dev_sn_offset)) { device_printf(softc->dev, "%s:%d device serial number is not found" - "or not supported\n", __FUNCTION__, __LINE__); + "or not supported\n", __func__, __LINE__); } else { dev_sn_lo = pci_read_config(softc->dev, dev_sn_offset + 4, 4); dev_sn_hi = pci_read_config(softc->dev, dev_sn_offset + 8, 4); @@ -354,27 +566,103 @@ bnxt_mgmt_get_dev_info(struct cdev *dev, u_long cmd, caddr_t data, (dev_sn_hi >> 24 ) & 0xFF); strncpy(dev_info.nic_info.device_serial_number, dsn, sizeof(dsn)); } - + if_t ifp = iflib_get_ifp(softc->ctx); dev_info.nic_info.mtu = if_getmtu(ifp); memcpy(dev_info.nic_info.mac, softc->func.mac_addr, ETHER_ADDR_LEN); - + if (pci_find_cap(softc->dev, PCIY_EXPRESS, &capreg)) { device_printf(softc->dev, "%s:%d pci link capability is not found" - "or not supported\n", __FUNCTION__, __LINE__); + "or not supported\n", __func__, __LINE__); } else { lnk = pci_read_config(softc->dev, capreg + PCIER_LINK_STA, 2); dev_info.nic_info.pci_link_speed = (lnk & PCIEM_LINK_STA_SPEED); dev_info.nic_info.pci_link_width = (lnk & PCIEM_LINK_STA_WIDTH) >> 4; } - + if (copyout(&dev_info, user_ptr, sizeof(dev_info))) { device_printf(softc->dev, "%s:%d Failed to copy data to user\n", - __FUNCTION__, __LINE__); - return -EFAULT; + __func__, __LINE__); + return (-EFAULT); + } + + return (0); +} + +static int +bnxt_mgmt_drv_dump(struct cdev *dev, u_long cmd, caddr_t data, + int flag, struct thread *td) +{ + struct bnxt_softc *softc = NULL; + void *buf = NULL; + struct bnxt_logger *logger = NULL, *lg_tmp; + int buf_sz = 0; + struct bnxt_mgmt_drv_dump mgmt_drv_dump = {}; + void *user_ptr; + int ret = 0, offset = 0; + + memcpy(&user_ptr, data, sizeof(user_ptr)); + if (copyin(user_ptr, &mgmt_drv_dump, sizeof(mgmt_drv_dump))) { + printf("%s: %s:%d Failed to copy data from user\n", + DRIVER_NAME, __func__, __LINE__); + return (-EFAULT); } + softc = bnxt_find_dev(mgmt_drv_dump.hdr.domain, mgmt_drv_dump.hdr.bus, + mgmt_drv_dump.hdr.devfn, NULL); + if (!softc) { + printf("%s: %s:%d unable to find softc reference\n", + DRIVER_NAME, __func__, __LINE__); + return (-ENODEV); + } + + switch (mgmt_drv_dump.op) { + case BNXT_MGMT_GET_DRV_DUMP_SIZE: + mtx_lock(&softc->log_lock); + TAILQ_FOREACH_SAFE(logger, &softc->loggers_list, list, lg_tmp) + buf_sz += logger->buffer_size; + mtx_unlock(&softc->log_lock); + + mgmt_drv_dump.buf_size = buf_sz + + bnxt_get_driver_coredump_len(softc); + if (copyout(&mgmt_drv_dump, user_ptr, sizeof(mgmt_drv_dump))) { + device_printf(softc->dev, + "%s:%d Failed to copy response to user\n", + __func__, __LINE__); + ret = -EFAULT; + } + break; + case BNXT_MGMT_GET_DRV_DUMP: + buf = malloc(mgmt_drv_dump.buf_size, M_BNXT, M_WAITOK); + /*Dump the driver logs */ + memset(buf, 0, mgmt_drv_dump.buf_size); + offset = bnxt_start_logging_driver_coredump(softc, buf); + + if (!offset) { + device_printf(softc->dev, + "%s:%d Drivers logs are empty\n", + __func__, __LINE__); + } - return 0; + /* Dump the ctx logs*/ + if (softc->ctx_mem) + bnxt_get_ctx_coredump(softc, (uint8_t *)buf + offset); + + if (copyout(buf, mgmt_drv_dump.buf, mgmt_drv_dump.buf_size)) { + device_printf(softc->dev, + "%s:%d Failed to copy response to user\n", + __func__, __LINE__); + ret = -EFAULT; + } + + free(buf, M_BNXT); + break; + default: + device_printf(softc->dev, "%s:%d Invalid op 0x%x\n", + __func__, __LINE__, mgmt_drv_dump.op); + ret = -EFAULT; + } + + return (ret); } /* @@ -385,7 +673,7 @@ bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) { int ret = 0; - + switch(cmd) { case IO_BNXT_MGMT_OPCODE_GET_DEV_INFO: case IOW_BNXT_MGMT_OPCODE_GET_DEV_INFO: @@ -401,13 +689,17 @@ bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, case IOW_BNXT_MGMT_OPCODE_DCB_OPS: ret = bnxt_mgmt_process_dcb(dev, cmd, data, flag, td); break; + case IO_BNXT_MGMT_OPCODE_DRV_DUMP: + case IOW_BNXT_MGMT_OPCODE_DRV_DUMP: + ret = bnxt_mgmt_drv_dump(dev, cmd, data, flag, td); + break; default: printf("%s: Unknown command 0x%lx\n", DRIVER_NAME, cmd); ret = -EINVAL; break; } - return ret; + return (ret); } static int diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h index 5b94184b1646..cdd6964158ee 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h @@ -43,10 +43,12 @@ #define IOW_BNXT_MGMT_OPCODE_GET_DEV_INFO _IOW(0, 0, 0) #define IOW_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM _IOW(0, 1, 0) #define IOW_BNXT_MGMT_OPCODE_DCB_OPS _IOW(0, 2, 0) +#define IOW_BNXT_MGMT_OPCODE_DRV_DUMP _IOW(0, 3, 0) #define IO_BNXT_MGMT_OPCODE_GET_DEV_INFO _IO(0, 0) #define IO_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM _IO(0, 1) #define IO_BNXT_MGMT_OPCODE_DCB_OPS _IO(0, 2) +#define IO_BNXT_MGMT_OPCODE_DRV_DUMP _IO(0, 3) #define BNXT_MGMT_MAX_HWRM_REQ_LENGTH HWRM_MAX_REQ_LEN #define BNXT_MGMT_MAX_HWRM_RESP_LENGTH (512) @@ -152,3 +154,32 @@ struct bnxt_mgmt_dcb { struct bnxt_mgmt_app_tlv app_tlv; } req; } __attribute__ ((__packed__)); + +struct bnxt_mgmt_drv_dump { + struct bnxt_mgmt_req_hdr hdr; +#define BNXT_MGMT_GET_DRV_DUMP_SIZE 0x1 +#define BNXT_MGMT_GET_DRV_DUMP 0x2 +#define BNXT_MGMT_DRV_DUMP_MAX BNXT_MGMT_GET_DRV_DUMP + uint32_t op; + void *buf; + uint32_t buf_size; +} __attribute__ ((__packed__)); + +struct bnxt_driver_segment_record { + uint32_t max_entries; + uint32_t entry_size; + uint32_t offset; + uint8_t wrapped:1; + uint8_t reserved[3]; +}; + +#define DRV_COREDUMP_COMP_ID 0xD +#define DRV_SRT_TRACE_SEG_ID 1 +#define DRV_SRT2_TRACE_SEG_ID 2 +#define DRV_CRT_TRACE_SEG_ID 3 +#define DRV_CRT2_TRACE_SEG_ID 4 +#define DRV_RIGP0_TRACE_SEG_ID 5 +#define DRV_LOG_HWRM_L2_TRACE_SEG_ID 6 +#define DRV_LOG_HWRM_ROCE_TRACE_SEG_ID 7 + +void bnxt_get_ctx_coredump(struct bnxt_softc *, void *); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c index c6d862a36a9a..c38521abd17f 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c @@ -48,6 +48,7 @@ #include "bnxt.h" #include "bnxt_hwrm.h" #include "bnxt_ulp.h" +#include "bnxt_log.h" void bnxt_destroy_irq(struct bnxt_softc *softc); @@ -335,6 +336,40 @@ void bnxt_ulp_irq_stop(struct bnxt_softc *bp) } } +void +bnxt_logger_ulp_live_data(void *d) +{ + struct bnxt_en_dev *edev; + struct bnxt_softc *bp; + + bp = d; + edev = bp->edev; + + if (!edev) + return; + + if (bnxt_ulp_registered(edev, BNXT_ROCE_ULP)) { + struct bnxt_ulp_ops *ops; + struct bnxt_ulp *ulp; + + ulp = edev->ulp_tbl; + //ops = rtnl_dereference(ulp->ulp_ops); + ops = ulp->ulp_ops; + if (!ops || !ops->ulp_log_live) + return; + + ops->ulp_log_live(ulp->handle); + } +} + +void +bnxt_ulp_log_live(struct bnxt_en_dev *edev, u16 logger_id, + const char *format, ...) +{ + bnxt_log_live(if_getsoftc(edev->net), logger_id, format); +} +EXPORT_SYMBOL(bnxt_ulp_log_live); + void bnxt_ulp_async_events(struct bnxt_softc *bp, struct hwrm_async_event_cmpl *cmpl) { u16 event_id = le16_to_cpu(cmpl->event_id); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h index 53bb51b07135..057e193aa00b 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h @@ -57,6 +57,7 @@ struct bnxt_ulp_ops { void (*ulp_shutdown)(void *); void (*ulp_irq_stop)(void *); void (*ulp_irq_restart)(void *, struct bnxt_msix_entry *); + void (*ulp_log_live)(void *handle); }; struct bnxt_fw_msg { @@ -162,8 +163,11 @@ void bnxt_ulp_shutdown(struct bnxt_softc *bp); void bnxt_ulp_irq_stop(struct bnxt_softc *bp); void bnxt_ulp_irq_restart(struct bnxt_softc *bp, int err); void bnxt_ulp_async_events(struct bnxt_softc *bp, struct hwrm_async_event_cmpl *cmpl); +void bnxt_ulp_log_live(struct bnxt_en_dev *edev, u16 logger_id, + const char *format, ...); struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev); void bnxt_aux_dev_release(struct device *dev); int bnxt_rdma_aux_device_add(struct bnxt_softc *bp); int bnxt_rdma_aux_device_del(struct bnxt_softc *bp); +void bnxt_logger_ulp_live_data(void *d); #endif diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c index 6d82302615e1..83f339bb045f 100644 --- a/sys/dev/bnxt/bnxt_en/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -71,6 +71,8 @@ #include "bnxt_mgmt.h" #include "bnxt_ulp.h" #include "bnxt_auxbus_compat.h" +#include "bnxt_log.h" +#include "bnxt_log_data.h" /* * PCI Device ID Table @@ -1243,6 +1245,64 @@ static void bnxt_free_ctx_mem(struct bnxt_softc *softc) softc->ctx_mem = NULL; } +const u16 bnxt_bstore_to_trace[] = { + [BNXT_CTX_SRT_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_SRT_TRACE, + [BNXT_CTX_SRT2_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_SRT2_TRACE, + [BNXT_CTX_CRT_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CRT_TRACE, + [BNXT_CTX_CRT2_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_CRT2_TRACE, + [BNXT_CTX_RIGP0_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_RIGP0_TRACE, + [BNXT_CTX_L2_HWRM_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_L2_HWRM_TRACE, + [BNXT_CTX_ROCE_HWRM_TRACE] = + HWRM_DBG_LOG_BUFFER_FLUSH_INPUT_TYPE_ROCE_HWRM_TRACE, +}; + +static void +bnxt_bs_trace_init(struct bnxt_softc *bp, struct bnxt_ctx_mem_type *ctxm) +{ + uint32_t mem_size, pages, rem_bytes, magic_byte_offset; + struct bnxt_ctx_pg_info *ctx_pg = ctxm->pg_info; + struct bnxt_ring_mem_info *rmem, *rmem_pg_tbl; + uint32_t last_pg, n = 1, size = sizeof(uint8_t); + struct bnxt_bs_trace_info *bs_trace; + uint16_t trace_type; + + mem_size = ctxm->max_entries * ctxm->entry_size; + rem_bytes = mem_size % BNXT_PAGE_SIZE; + pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE); + + last_pg = (pages - 1) & (MAX_CTX_PAGES - 1); + magic_byte_offset = ((rem_bytes ? rem_bytes : BNXT_PAGE_SIZE) - size); + + if (ctxm->instance_bmap) { + if (ctxm->instance_bmap > 1) + return; + n = bitcount32(ctxm->instance_bmap); + } + + rmem = &ctx_pg[n - 1].ring_mem; + trace_type = bnxt_bstore_to_trace[ctxm->type]; + bs_trace = &bp->bs_trace[trace_type]; + bs_trace->ctx_type = ctxm->type; + bs_trace->trace_type = trace_type; + if (pages > MAX_CTX_PAGES) { + int last_pg_directory = rmem->nr_pages - 1; + + rmem_pg_tbl = + &ctx_pg[n - 1].ctx_pg_tbl[last_pg_directory]->ring_mem; + bs_trace->magic_byte = rmem_pg_tbl->pg_arr[last_pg].idi_vaddr; + } else { + bs_trace->magic_byte = rmem->pg_arr[last_pg].idi_vaddr; + } + bs_trace->magic_byte += magic_byte_offset; + *bs_trace->magic_byte = BNXT_TRACE_BUF_MAGIC_BYTE; +} + static int bnxt_backing_store_cfg_v2(struct bnxt_softc *softc, u32 ena) { @@ -1264,7 +1324,7 @@ bnxt_backing_store_cfg_v2(struct bnxt_softc *softc, u32 ena) continue; } /* ckp TODO: this is trace buffer related stuff, so keeping it diabled now. needs revisit */ - //bnxt_bs_trace_init(bp, ctxm, type - BNXT_CTX_SRT_TRACE); + bnxt_bs_trace_init(softc, ctxm); last_type = type; } } @@ -2198,7 +2258,7 @@ static int bnxt_open(struct bnxt_softc *bp) if (BNXT_CHIP_P5_PLUS(bp)) bnxt_hwrm_reserve_rings(bp); - + /* Get the current configuration of this function */ rc = bnxt_hwrm_func_qcfg(bp); if (rc) { @@ -2446,6 +2506,14 @@ bnxt_hwrm_reserve_rings(struct bnxt_softc *softc) return bnxt_hwrm_reserve_vf_rings(softc); } +static void +bnxt_log_live_data(void *d) +{ + struct bnxt_softc *bp = d; + + bnxt_log_ring_states(bp); +} + /* Device setup and teardown */ static int bnxt_attach_pre(if_ctx_t ctx) @@ -2495,6 +2563,11 @@ bnxt_attach_pre(if_ctx_t ctx) goto pci_attach_fail; } + mtx_init(&softc->log_lock, "BNXT LOG Lock", NULL, MTX_DEF); + TAILQ_INIT(&softc->loggers_list); + bnxt_register_logger(softc, BNXT_LOGGER_L2, BNXT_L2_MAX_LOG_BUFFERS, + bnxt_log_live_data, BNXT_L2_MAX_LIVE_LOG_SIZE); + /* HWRM setup/init */ BNXT_HWRM_LOCK_INIT(softc, device_get_nameunit(softc->dev)); rc = bnxt_alloc_hwrm_dma_mem(softc); @@ -2527,7 +2600,7 @@ bnxt_attach_pre(if_ctx_t ctx) if (rc) goto hwrm_short_cmd_alloc_fail; } - + /* Now perform a function reset */ rc = bnxt_hwrm_func_reset(softc); @@ -2931,6 +3004,9 @@ bnxt_detach(if_ctx_t ctx) bnxt_free_hwrm_short_cmd_req(softc); BNXT_HWRM_LOCK_DESTROY(softc); + bnxt_unregister_logger(softc, BNXT_LOGGER_L2); + mtx_destroy(&softc->log_lock); + if (!bnxt_num_pfs && bnxt_pf_wq) destroy_workqueue(bnxt_pf_wq); diff --git a/sys/dev/bnxt/bnxt_re/main.c b/sys/dev/bnxt/bnxt_re/main.c index 01c2710bc3ea..5b1fe2ae0faa 100644 --- a/sys/dev/bnxt/bnxt_re/main.c +++ b/sys/dev/bnxt/bnxt_re/main.c @@ -52,6 +52,7 @@ #include "ib_verbs.h" #include "bnxt_re-abi.h" #include "bnxt.h" +#include "bnxt_log.h" static char drv_version[] = "Broadcom NetXtreme-C/E RoCE Driver " ROCE_DRV_MODULE_NAME \ @@ -112,6 +113,7 @@ static int bnxt_re_hwrm_qcfg(struct bnxt_re_dev *rdev, u32 *db_len, static int bnxt_re_ib_init(struct bnxt_re_dev *rdev); static void bnxt_re_ib_init_2(struct bnxt_re_dev *rdev); void _bnxt_re_remove(struct auxiliary_device *adev); + void writel_fbsd(struct bnxt_softc *bp, u32, u8, u32); u32 readl_fbsd(struct bnxt_softc *bp, u32, u8); static int bnxt_re_hwrm_dbr_pacing_qcfg(struct bnxt_re_dev *rdev); @@ -1327,6 +1329,68 @@ static void bnxt_re_start_irq(void *handle, struct bnxt_msix_entry *ent) } /* + * bnxt_re_create_snapdump_logs - Collect required debug data for snapdump. + * @rdev - rdma device instance + * + * This function will use bnxt_ulp_log_live API and dump all + * the required information for debugging. + * + * Returns: Nothing + */ +static void +bnxt_re_create_snapdump_logs(struct bnxt_re_dev *rdev) +{ + struct bnxt_re_ext_rstat *ext_s; + + ext_s = &rdev->stats.dstat.ext_rstat[0]; + + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "tx_atomic_req: %llu", ext_s->tx.atomic_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_atomic_req: %llu", ext_s->rx.atomic_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "tx_read_req: %llu\n", ext_s->tx.read_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "tx_read_resp: %llu\n", ext_s->tx.read_resp); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_read_req: %llu\n", ext_s->rx.read_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_read_resp: %llu\n", ext_s->rx.read_resp); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "tx_write_req: %llu\n", ext_s->tx.write_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_write_req: %llu\n", ext_s->rx.write_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "tx_send_req: %llu\n", ext_s->tx.send_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_send_req: %llu\n", ext_s->rx.send_req); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_good_pkts: %llu\n", ext_s->grx.rx_pkts); + bnxt_ulp_log_live(rdev->en_dev, BNXT_LOGGER_ROCE, + "rx_good_bytes: %llu\n", ext_s->grx.rx_bytes); +} + +/* + * bnxt_re_ulp_log_live - Callback from L2 driver to collect snapdump + * @handle - en_dev information. L2 and RoCE device information + * + * This function is callback to support L2 and RoCE common API. + * bnxt_ulp_ops.ulp_log_live(). + * + * Returns: Nothing + */ +static void +bnxt_re_ulp_log_live(void *handle) +{ + struct bnxt_re_en_dev_info *en_info = auxiliary_get_drvdata(handle); + + if (!en_info || !en_info->rdev) + return; + + bnxt_re_create_snapdump_logs(en_info->rdev); +} + +/* * Except for ulp_async_notifier, the remaining ulp_ops * below are called with rtnl_lock held */ @@ -1337,6 +1401,7 @@ static struct bnxt_ulp_ops bnxt_re_ulp_ops = { .ulp_shutdown = bnxt_re_shutdown, .ulp_irq_stop = bnxt_re_stop_irq, .ulp_irq_restart = bnxt_re_start_irq, + .ulp_log_live = bnxt_re_ulp_log_live, }; static inline const char *bnxt_re_netevent(unsigned long event) |
