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.marre...@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));
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to