aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/bnxt
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/bnxt')
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt.h44
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_mgmt.c378
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_mgmt.h31
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_ulp.c35
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_ulp.h4
-rw-r--r--sys/dev/bnxt/bnxt_en/if_bnxt.c82
-rw-r--r--sys/dev/bnxt/bnxt_re/main.c65
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)