Index: bnxt.h =================================================================== --- bnxt.h +++ bnxt.h @@ -236,6 +236,8 @@ ifmedia_add(softc->media, IFM_ETHER | (ifm_speed), 0, NULL); \ } while(0) +#define BNXT_MIN_PKT_SIZE 52 + /* NVRAM access */ enum bnxt_nvm_directory_type { BNX_DIR_TYPE_UNUSED = 0, @@ -559,6 +561,7 @@ #define BNXT_FLAG_VF 0x0001 #define BNXT_FLAG_NPAR 0x0002 #define BNXT_FLAG_WOL_CAP 0x0004 +#define BNXT_FLAG_SHORT_CMD 0x0008 uint32_t flags; uint32_t total_msix; @@ -570,6 +573,7 @@ uint16_t hwrm_cmd_seq; uint32_t hwrm_cmd_timeo; /* milliseconds */ struct iflib_dma_info hwrm_cmd_resp; + struct iflib_dma_info hwrm_short_cmd_req_addr; /* Interrupt info for HWRM */ struct if_irq irq; struct mtx hwrm_lock; Index: bnxt_hwrm.h =================================================================== --- bnxt_hwrm.h +++ bnxt_hwrm.h @@ -36,6 +36,7 @@ #define BNXT_PAUSE_RX (HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX) #define BNXT_AUTO_PAUSE_AUTONEG_PAUSE \ (HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_PAUSE_AUTONEG_PAUSE) +#define BNXT_HWRM_SHORT_REQ_LEN sizeof(struct hwrm_short_input) /* HWRM Function Prototypes */ int bnxt_alloc_hwrm_dma_mem(struct bnxt_softc *softc); Index: bnxt_hwrm.c =================================================================== --- bnxt_hwrm.c +++ bnxt_hwrm.c @@ -122,12 +122,37 @@ uint16_t cp_ring_id; uint8_t *valid; uint16_t err; + uint16_t max_req_len = HWRM_MAX_REQ_LEN; + struct hwrm_short_input short_input = {0}; /* TODO: DMASYNC in here. */ req->seq_id = htole16(softc->hwrm_cmd_seq++); memset(resp, 0, PAGE_SIZE); cp_ring_id = le16toh(req->cmpl_ring); + if (softc->flags & BNXT_FLAG_SHORT_CMD) { + void *short_cmd_req = softc->hwrm_short_cmd_req_addr.idi_vaddr; + + memcpy(short_cmd_req, req, msg_len); + memset((uint8_t *) short_cmd_req + msg_len, 0, softc->hwrm_max_req_len- + msg_len); + + short_input.req_type = req->req_type; + short_input.signature = + htole16(HWRM_SHORT_INPUT_SIGNATURE_SHORT_CMD); + short_input.size = htole16(msg_len); + short_input.req_addr = + htole64(softc->hwrm_short_cmd_req_addr.idi_paddr); + + data = (uint32_t *)&short_input; + msg_len = sizeof(short_input); + + /* Sync memory write before updating doorbell */ + wmb(); + + max_req_len = BNXT_HWRM_SHORT_REQ_LEN; + } + /* Write request msg to hwrm channel */ for (i = 0; i < msg_len; i += 4) { bus_space_write_4(softc->hwrm_bar.tag, @@ -137,7 +162,7 @@ } /* Clear to the end of the request buffer */ - for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4) + for (i = msg_len; i < max_req_len; i += 4) bus_space_write_4(softc->hwrm_bar.tag, softc->hwrm_bar.handle, i, 0); @@ -248,6 +273,7 @@ int rc; const char nastr[] = ""; const char naver[] = ""; + uint32_t dev_caps_cfg; softc->hwrm_max_req_len = HWRM_MAX_REQ_LEN; softc->hwrm_cmd_timeo = 1000; @@ -323,6 +349,10 @@ if (resp->def_req_timeout) softc->hwrm_cmd_timeo = le16toh(resp->def_req_timeout); + dev_caps_cfg = le32toh(resp->dev_caps_cfg); + if ((dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_SUPPORTED) && + (dev_caps_cfg & HWRM_VER_GET_OUTPUT_DEV_CAPS_CFG_SHORT_CMD_REQUIRED)) + softc->flags |= BNXT_FLAG_SHORT_CMD; fail: BNXT_HWRM_UNLOCK(softc); return rc; @@ -939,15 +969,15 @@ bnxt_cfg_async_cr(struct bnxt_softc *softc) { int rc = 0; - + if (BNXT_PF(softc)) { struct hwrm_func_cfg_input req = {0}; bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_CFG); - req.fid = 0xffff; + req.fid = htole16(0xffff); req.enables = htole32(HWRM_FUNC_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); - req.async_event_cr = softc->def_cp_ring.ring.phys_id; + req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id); rc = hwrm_send_message(softc, &req, sizeof(req)); } @@ -957,7 +987,7 @@ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_VF_CFG); req.enables = htole32(HWRM_FUNC_VF_CFG_INPUT_ENABLES_ASYNC_EVENT_CR); - req.async_event_cr = softc->def_cp_ring.ring.phys_id; + req.async_event_cr = htole16(softc->def_cp_ring.ring.phys_id); rc = hwrm_send_message(softc, &req, sizeof(req)); } Index: bnxt_txrx.c =================================================================== --- bnxt_txrx.c +++ bnxt_txrx.c @@ -115,6 +115,12 @@ /* No need to byte-swap the opaque value */ tbd->opaque = ((pi->ipi_nsegs + need_hi) << 24) | pi->ipi_new_pidx; tbd->len = htole16(pi->ipi_segs[seg].ds_len); + + /* Few BRCM A0 NICs requires padding for shorter than 52 byte pkts */ + if (tbd->len < BNXT_MIN_PKT_SIZE) { + tbd->len = BNXT_MIN_PKT_SIZE; + } + tbd->addr = htole64(pi->ipi_segs[seg++].ds_addr); flags_type = ((pi->ipi_nsegs + need_hi) << TX_BD_SHORT_FLAGS_BD_CNT_SFT) & TX_BD_SHORT_FLAGS_BD_CNT_MASK; Index: if_bnxt.c =================================================================== --- if_bnxt.c +++ if_bnxt.c @@ -643,6 +643,23 @@ return rc; } +static void bnxt_free_hwrm_short_cmd_req(struct bnxt_softc *softc) +{ + if (softc->hwrm_short_cmd_req_addr.idi_vaddr) + iflib_dma_free(&softc->hwrm_short_cmd_req_addr); + softc->hwrm_short_cmd_req_addr.idi_vaddr = NULL; +} + +static int bnxt_alloc_hwrm_short_cmd_req(struct bnxt_softc *softc) +{ + int rc; + + rc = iflib_dma_alloc(softc->ctx, softc->hwrm_max_req_len, + &softc->hwrm_short_cmd_req_addr, BUS_DMA_NOWAIT); + + return rc; +} + /* Device setup and teardown */ static int bnxt_attach_pre(if_ctx_t ctx) @@ -714,6 +731,12 @@ goto ver_fail; } + if (softc->flags & BNXT_FLAG_SHORT_CMD) { + rc = bnxt_alloc_hwrm_short_cmd_req(softc); + if (rc) + goto hwrm_short_cmd_alloc_fail; + } + /* Get NVRAM info */ softc->nvm_info = malloc(sizeof(struct bnxt_nvram_info), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -723,10 +746,13 @@ "Unable to allocate space for NVRAM info\n"); goto nvm_alloc_fail; } - rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, - &softc->nvm_info->device_id, &softc->nvm_info->sector_size, - &softc->nvm_info->size, &softc->nvm_info->reserved_size, - &softc->nvm_info->available_size); + + if (BNXT_PF(softc)) { + rc = bnxt_hwrm_nvm_get_dev_info(softc, &softc->nvm_info->mfg_id, + &softc->nvm_info->device_id, &softc->nvm_info->sector_size, + &softc->nvm_info->size, &softc->nvm_info->reserved_size, + &softc->nvm_info->available_size); + } /* Register the driver with the FW */ rc = bnxt_hwrm_func_drv_rgtr(softc); @@ -895,6 +921,8 @@ drv_rgtr_fail: free(softc->nvm_info, M_DEVBUF); nvm_alloc_fail: + bnxt_free_hwrm_short_cmd_req(softc); +hwrm_short_cmd_alloc_fail: ver_fail: free(softc->ver_info, M_DEVBUF); ver_alloc_fail: @@ -966,6 +994,7 @@ bnxt_hwrm_func_drv_unrgtr(softc, false); bnxt_free_hwrm_dma_mem(softc); + bnxt_free_hwrm_short_cmd_req(softc); BNXT_HWRM_LOCK_DESTROY(softc); pci_disable_busmaster(softc->dev);