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