svn commit: r321481 - head/sys/dev/bnxt
Sean Bruno
sbruno at FreeBSD.org
Tue Jul 25 15:33:35 UTC 2017
Author: sbruno
Date: Tue Jul 25 15:33:34 2017
New Revision: 321481
URL: https://svnweb.freebsd.org/changeset/base/321481
Log:
bnxt: Implement interrupt coalescing options using sysctl.
Submitted by: bhargava.marreddy at broadcom.com
Differential Revision: https://reviews.freebsd.org/D11702
Modified:
head/sys/dev/bnxt/bnxt.h
head/sys/dev/bnxt/bnxt_hwrm.c
head/sys/dev/bnxt/bnxt_hwrm.h
head/sys/dev/bnxt/bnxt_sysctl.c
head/sys/dev/bnxt/if_bnxt.c
Modified: head/sys/dev/bnxt/bnxt.h
==============================================================================
--- head/sys/dev/bnxt/bnxt.h Tue Jul 25 15:08:52 2017 (r321480)
+++ head/sys/dev/bnxt/bnxt.h Tue Jul 25 15:33:34 2017 (r321481)
@@ -214,6 +214,18 @@ __FBSDID("$FreeBSD$");
/* Chip info */
#define BNXT_TSO_SIZE UINT16_MAX
+#define min_t(type, x, y) ({ \
+ type __min1 = (x); \
+ type __min2 = (y); \
+ __min1 < __min2 ? __min1 : __min2; })
+
+#define max_t(type, x, y) ({ \
+ type __max1 = (x); \
+ type __max2 = (y); \
+ __max1 > __max2 ? __max1 : __max2; })
+
+#define clamp_t(type, _x, min, max) min_t(type, max_t(type, _x, min), max)
+
/* NVRAM access */
enum bnxt_nvm_directory_type {
BNX_DIR_TYPE_UNUSED = 0,
@@ -569,6 +581,20 @@ struct bnxt_softc {
struct bnxt_nvram_info *nvm_info;
bool wol;
uint8_t wol_filter_id;
+ uint16_t rx_coal_usecs;
+ uint16_t rx_coal_usecs_irq;
+ uint16_t rx_coal_frames;
+ uint16_t rx_coal_frames_irq;
+ uint16_t tx_coal_usecs;
+ uint16_t tx_coal_usecs_irq;
+ uint16_t tx_coal_frames;
+ uint16_t tx_coal_frames_irq;
+
+#define BNXT_USEC_TO_COAL_TIMER(x) ((x) * 25 / 2)
+#define BNXT_DEF_STATS_COAL_TICKS 1000000
+#define BNXT_MIN_STATS_COAL_TICKS 250000
+#define BNXT_MAX_STATS_COAL_TICKS 1000000
+
};
struct bnxt_filter_info {
Modified: head/sys/dev/bnxt/bnxt_hwrm.c
==============================================================================
--- head/sys/dev/bnxt/bnxt_hwrm.c Tue Jul 25 15:08:52 2017 (r321480)
+++ head/sys/dev/bnxt/bnxt_hwrm.c Tue Jul 25 15:33:34 2017 (r321481)
@@ -30,6 +30,7 @@
__FBSDID("$FreeBSD$");
#include <sys/endian.h>
+#include <sys/bitstring.h>
#include "bnxt.h"
#include "bnxt_hwrm.h"
@@ -1547,3 +1548,131 @@ bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc)
req.wol_filter_id = softc->wol_filter_id;
return hwrm_send_message(softc, &req, sizeof(req));
}
+
+static void bnxt_hwrm_set_coal_params(struct bnxt_softc *softc, uint32_t max_frames,
+ uint32_t buf_tmrs, uint16_t flags,
+ struct hwrm_ring_cmpl_ring_cfg_aggint_params_input *req)
+{
+ req->flags = htole16(flags);
+ req->num_cmpl_dma_aggr = htole16((uint16_t)max_frames);
+ req->num_cmpl_dma_aggr_during_int = htole16(max_frames >> 16);
+ req->cmpl_aggr_dma_tmr = htole16((uint16_t)buf_tmrs);
+ req->cmpl_aggr_dma_tmr_during_int = htole16(buf_tmrs >> 16);
+ /* Minimum time between 2 interrupts set to buf_tmr x 2 */
+ req->int_lat_tmr_min = htole16((uint16_t)buf_tmrs * 2);
+ req->int_lat_tmr_max = htole16((uint16_t)buf_tmrs * 4);
+ req->num_cmpl_aggr_int = htole16((uint16_t)max_frames * 4);
+}
+
+
+int bnxt_hwrm_set_coal(struct bnxt_softc *softc)
+{
+ int i, rc = 0;
+ struct hwrm_ring_cmpl_ring_cfg_aggint_params_input req_rx = {0},
+ req_tx = {0}, *req;
+ uint16_t max_buf, max_buf_irq;
+ uint16_t buf_tmr, buf_tmr_irq;
+ uint32_t flags;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req_rx,
+ HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
+ bnxt_hwrm_cmd_hdr_init(softc, &req_tx,
+ HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS);
+
+ /* Each rx completion (2 records) should be DMAed immediately.
+ * DMA 1/4 of the completion buffers at a time.
+ */
+ max_buf = min_t(uint16_t, softc->rx_coal_frames / 4, 2);
+ /* max_buf must not be zero */
+ max_buf = clamp_t(uint16_t, max_buf, 1, 63);
+ max_buf_irq = clamp_t(uint16_t, softc->rx_coal_frames_irq, 1, 63);
+ buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs);
+ /* buf timer set to 1/4 of interrupt timer */
+ buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
+ buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->rx_coal_usecs_irq);
+ buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
+
+ flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
+
+ /* RING_IDLE generates more IRQs for lower latency. Enable it only
+ * if coal_usecs is less than 25 us.
+ */
+ if (softc->rx_coal_usecs < 25)
+ flags |= HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_RING_IDLE;
+
+ bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
+ buf_tmr_irq << 16 | buf_tmr, flags, &req_rx);
+
+ /* max_buf must not be zero */
+ max_buf = clamp_t(uint16_t, softc->tx_coal_frames, 1, 63);
+ max_buf_irq = clamp_t(uint16_t, softc->tx_coal_frames_irq, 1, 63);
+ buf_tmr = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs);
+ /* buf timer set to 1/4 of interrupt timer */
+ buf_tmr = max_t(uint16_t, buf_tmr / 4, 1);
+ buf_tmr_irq = BNXT_USEC_TO_COAL_TIMER(softc->tx_coal_usecs_irq);
+ buf_tmr_irq = max_t(uint16_t, buf_tmr_irq, 1);
+ flags = HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS_INPUT_FLAGS_TIMER_RESET;
+ bnxt_hwrm_set_coal_params(softc, max_buf_irq << 16 | max_buf,
+ buf_tmr_irq << 16 | buf_tmr, flags, &req_tx);
+
+ for (i = 0; i < softc->nrxqsets; i++) {
+
+
+ req = &req_rx;
+ /*
+ * TBD:
+ * Check if Tx also needs to be done
+ * So far, Tx processing has been done in softirq contest
+ *
+ * req = &req_tx;
+ */
+ req->ring_id = htole16(softc->grp_info[i].cp_ring_id);
+
+ rc = hwrm_send_message(softc, req, sizeof(*req));
+ if (rc)
+ break;
+ }
+ return rc;
+}
+
+
+
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
+ int bmap_size)
+{
+ struct hwrm_func_drv_rgtr_input req = {0};
+ bitstr_t *async_events_bmap;
+ uint32_t *events;
+ int i;
+
+ async_events_bmap = bit_alloc(256, M_DEVBUF, M_WAITOK|M_ZERO);
+ events = (uint32_t *)async_events_bmap;
+
+ bnxt_hwrm_cmd_hdr_init(softc, &req, HWRM_FUNC_DRV_RGTR);
+
+ req.enables =
+ htole32(HWRM_FUNC_DRV_RGTR_INPUT_ENABLES_ASYNC_EVENT_FWD);
+
+ memset(async_events_bmap, 0, sizeof(256 / 8));
+
+ bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
+ bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
+ bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED);
+ bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE);
+ bit_set(async_events_bmap, HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE);
+
+ if (bmap && bmap_size) {
+ for (i = 0; i < bmap_size; i++) {
+ if (bit_test(bmap, i))
+ bit_set(async_events_bmap, i);
+ }
+ }
+
+ for (i = 0; i < 8; i++)
+ req.async_event_fwd[i] |= htole32(events[i]);
+
+ free(async_events_bmap, M_DEVBUF);
+
+ return hwrm_send_message(softc, &req, sizeof(req));
+}
+
Modified: head/sys/dev/bnxt/bnxt_hwrm.h
==============================================================================
--- head/sys/dev/bnxt/bnxt_hwrm.h Tue Jul 25 15:08:52 2017 (r321480)
+++ head/sys/dev/bnxt/bnxt_hwrm.h Tue Jul 25 15:33:34 2017 (r321481)
@@ -101,5 +101,7 @@ int bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc);
uint16_t bnxt_hwrm_get_wol_fltrs(struct bnxt_softc *softc, uint16_t handle);
int bnxt_hwrm_alloc_wol_fltr(struct bnxt_softc *softc);
int bnxt_hwrm_free_wol_fltr(struct bnxt_softc *softc);
-
+int bnxt_hwrm_set_coal(struct bnxt_softc *softc);
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt_softc *softc, unsigned long *bmap,
+ int bmap_size);
#endif
Modified: head/sys/dev/bnxt/bnxt_sysctl.c
==============================================================================
--- head/sys/dev/bnxt/bnxt_sysctl.c Tue Jul 25 15:08:52 2017 (r321480)
+++ head/sys/dev/bnxt/bnxt_sysctl.c Tue Jul 25 15:33:34 2017 (r321481)
@@ -549,6 +549,166 @@ bnxt_vlan_strip_sysctl(SYSCTL_HANDLER_ARGS) {
return rc;
}
+static int
+bnxt_set_coal_rx_usecs(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->rx_coal_usecs;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->rx_coal_usecs = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_rx_frames(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->rx_coal_frames;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->rx_coal_frames = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_rx_usecs_irq(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->rx_coal_usecs_irq;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->rx_coal_usecs_irq = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_rx_frames_irq(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->rx_coal_frames_irq;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->rx_coal_frames_irq = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_tx_usecs(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->tx_coal_usecs;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->tx_coal_usecs = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_tx_frames(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->tx_coal_frames;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->tx_coal_frames = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_tx_usecs_irq(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->tx_coal_usecs_irq;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->tx_coal_usecs_irq = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
+static int
+bnxt_set_coal_tx_frames_irq(SYSCTL_HANDLER_ARGS) {
+ struct bnxt_softc *softc = arg1;
+ int rc;
+ int val;
+
+ if (softc == NULL)
+ return EBUSY;
+
+ val = softc->tx_coal_frames_irq;
+ rc = sysctl_handle_int(oidp, &val, 0, req);
+ if (rc || !req->newptr)
+ return rc;
+
+ softc->tx_coal_frames_irq = val;
+ rc = bnxt_hwrm_set_coal(softc);
+
+ return rc;
+}
+
int
bnxt_create_config_sysctls_pre(struct bnxt_softc *softc)
{
@@ -571,6 +731,31 @@ bnxt_create_config_sysctls_pre(struct bnxt_softc *soft
"strip VLAN tag in the RX path");
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "if_name", CTLFLAG_RD,
iflib_get_ifp(softc->ctx)->if_xname, 0, "interface name");
+
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_usecs,
+ "I", "interrupt coalescing Rx Usecs");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_frames,
+ "I", "interrupt coalescing Rx Frames");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_usecs_irq",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_usecs_irq,
+ "I", "interrupt coalescing Rx Usecs IRQ");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_rx_frames_irq",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_rx_frames_irq,
+ "I", "interrupt coalescing Rx Frames IRQ");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_usecs,
+ "I", "interrupt coalescing Tx Usces");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_frames,
+ "I", "interrupt coalescing Tx Frames");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_usecs_irq",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_usecs_irq,
+ "I", "interrupt coalescing Tx Usecs IRQ");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "intr_coal_tx_frames_irq",
+ CTLTYPE_INT|CTLFLAG_RWTUN, softc, 0, bnxt_set_coal_tx_frames_irq,
+ "I", "interrupt coalescing Tx Frames IRQ");
return 0;
}
Modified: head/sys/dev/bnxt/if_bnxt.c
==============================================================================
--- head/sys/dev/bnxt/if_bnxt.c Tue Jul 25 15:08:52 2017 (r321480)
+++ head/sys/dev/bnxt/if_bnxt.c Tue Jul 25 15:33:34 2017 (r321481)
@@ -691,6 +691,12 @@ bnxt_attach_pre(if_ctx_t ctx)
goto drv_rgtr_fail;
}
+ rc = bnxt_hwrm_func_rgtr_async_events(softc, NULL, 0);
+ if (rc) {
+ device_printf(softc->dev, "attach: hwrm rgtr async evts failed\n");
+ goto drv_rgtr_fail;
+ }
+
/* Get the HW capabilities */
rc = bnxt_hwrm_func_qcaps(softc);
if (rc)
@@ -2286,11 +2292,11 @@ bnxt_report_link(struct bnxt_softc *softc)
HWRM_PORT_PHY_QCFG_OUTPUT_PAUSE_RX)
flow_ctrl = "FC - receive";
else
- flow_ctrl = "none";
+ flow_ctrl = "FC - none";
iflib_link_state_change(softc->ctx, LINK_STATE_UP,
IF_Gbps(100));
- device_printf(softc->dev, "Link is UP %s, %s\n", duplex,
- flow_ctrl);
+ device_printf(softc->dev, "Link is UP %s, %s - %d Mbps \n", duplex,
+ flow_ctrl, (softc->link_info.link_speed * 100));
} else {
iflib_link_state_change(softc->ctx, LINK_STATE_DOWN,
bnxt_get_baudrate(&softc->link_info));
More information about the svn-src-head
mailing list