bnxt_en: Support for 64-bit flow handle.
authorVenkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Thu, 20 Dec 2018 08:38:52 +0000 (03:38 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 20 Dec 2018 16:26:16 +0000 (08:26 -0800)
Older firmware only supports 16-bit flow handle, because of which the
number of flows that can be offloaded can’t scale beyond a point.
Newer firmware supports 64-bit flow handle enabling the host to scale
upto millions of flows. With the new 64-bit flow handle support, driver
has to query flow stats in a different way compared to the older approach.

This patch adds support for 64-bit flow handle and new way to query
flow stats.

Signed-off-by: Venkat Duvvuru <venkatkumar.duvvuru@broadcom.com>
Reviewed-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.h

index d328764..6872db9 100644 (file)
@@ -4055,6 +4055,10 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
                        cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD);
        }
 
+       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
+               req.flags |= cpu_to_le32(
+                       FUNC_DRV_RGTR_REQ_FLAGS_FLOW_HANDLE_64BIT_MODE);
+
        mutex_lock(&bp->hwrm_cmd_lock);
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
@@ -6662,6 +6666,10 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp)
        if (dev_caps_cfg & VER_GET_RESP_DEV_CAPS_CFG_KONG_MB_CHNL_SUPPORTED)
                bp->fw_cap |= BNXT_FW_CAP_KONG_MB_CHNL;
 
+       if (dev_caps_cfg &
+           VER_GET_RESP_DEV_CAPS_CFG_FLOW_HANDLE_64BIT_SUPPORTED)
+               bp->fw_cap |= BNXT_FW_CAP_OVS_64BIT_HANDLE;
+
 hwrm_ver_get_exit:
        mutex_unlock(&bp->hwrm_cmd_lock);
        return rc;
index 61d07a4..a451796 100644 (file)
@@ -1478,6 +1478,7 @@ struct bnxt {
        #define BNXT_FW_CAP_NEW_RM                      0x00000008
        #define BNXT_FW_CAP_IF_CHANGE                   0x00000010
        #define BNXT_FW_CAP_KONG_MB_CHNL                0x00000080
+       #define BNXT_FW_CAP_OVS_64BIT_HANDLE            0x00000400
 
 #define BNXT_NEW_RM(bp)                ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
        u32                     hwrm_spec_code;
index b395848..c683b5e 100644 (file)
@@ -337,18 +337,21 @@ static int bnxt_tc_parse_flow(struct bnxt *bp,
        return bnxt_tc_parse_actions(bp, &flow->actions, tc_flow_cmd->exts);
 }
 
-static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp, __le16 flow_handle)
+static int bnxt_hwrm_cfa_flow_free(struct bnxt *bp,
+                                  struct bnxt_tc_flow_node *flow_node)
 {
        struct hwrm_cfa_flow_free_input req = { 0 };
        int rc;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_FLOW_FREE, -1, -1);
-       req.flow_handle = flow_handle;
+       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
+               req.ext_flow_handle = flow_node->ext_flow_handle;
+       else
+               req.flow_handle = flow_node->flow_handle;
 
        rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
-               netdev_info(bp->dev, "Error: %s: flow_handle=0x%x rc=%d",
-                           __func__, flow_handle, rc);
+               netdev_info(bp->dev, "%s: Error rc=%d", __func__, rc);
 
        if (rc)
                rc = -EIO;
@@ -418,7 +421,8 @@ static bool bits_set(void *key, int len)
 
 static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
                                    __le16 ref_flow_handle,
-                                   __le32 tunnel_handle, __le16 *flow_handle)
+                                   __le32 tunnel_handle,
+                                   struct bnxt_tc_flow_node *flow_node)
 {
        struct bnxt_tc_actions *actions = &flow->actions;
        struct bnxt_tc_l3_key *l3_mask = &flow->l3_mask;
@@ -529,7 +533,20 @@ static int bnxt_hwrm_cfa_flow_alloc(struct bnxt *bp, struct bnxt_tc_flow *flow,
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (!rc) {
                resp = bnxt_get_hwrm_resp_addr(bp, &req);
-               *flow_handle = resp->flow_handle;
+               /* CFA_FLOW_ALLOC response interpretation:
+                *                  fw with          fw with
+                *                  16-bit           64-bit
+                *                  flow handle      flow handle
+                *                  ===========      ===========
+                * flow_handle      flow handle      flow context id
+                * ext_flow_handle  INVALID          flow handle
+                * flow_id          INVALID          flow counter id
+                */
+               flow_node->flow_handle = resp->flow_handle;
+               if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE) {
+                       flow_node->ext_flow_handle = resp->ext_flow_handle;
+                       flow_node->flow_id = resp->flow_id;
+               }
        }
        mutex_unlock(&bp->hwrm_cmd_lock);
 
@@ -1228,7 +1245,7 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
        int rc;
 
        /* send HWRM cmd to free the flow-id */
-       bnxt_hwrm_cfa_flow_free(bp, flow_node->flow_handle);
+       bnxt_hwrm_cfa_flow_free(bp, flow_node);
 
        mutex_lock(&tc_info->lock);
 
@@ -1250,6 +1267,12 @@ static int __bnxt_tc_del_flow(struct bnxt *bp,
        return 0;
 }
 
+static void bnxt_tc_set_flow_dir(struct bnxt *bp, struct bnxt_tc_flow *flow,
+                                u16 src_fid)
+{
+       flow->dir = (bp->pf.fw_fid == src_fid) ? BNXT_DIR_RX : BNXT_DIR_TX;
+}
+
 static void bnxt_tc_set_src_fid(struct bnxt *bp, struct bnxt_tc_flow *flow,
                                u16 src_fid)
 {
@@ -1297,6 +1320,9 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
 
        bnxt_tc_set_src_fid(bp, flow, src_fid);
 
+       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE)
+               bnxt_tc_set_flow_dir(bp, flow, src_fid);
+
        if (!bnxt_tc_can_offload(bp, flow)) {
                rc = -ENOSPC;
                goto free_node;
@@ -1324,7 +1350,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
 
        /* send HWRM cmd to alloc the flow */
        rc = bnxt_hwrm_cfa_flow_alloc(bp, flow, ref_flow_handle,
-                                     tunnel_handle, &new_node->flow_handle);
+                                     tunnel_handle, new_node);
        if (rc)
                goto put_tunnel;
 
@@ -1340,7 +1366,7 @@ static int bnxt_tc_add_flow(struct bnxt *bp, u16 src_fid,
        return 0;
 
 hwrm_flow_free:
-       bnxt_hwrm_cfa_flow_free(bp, new_node->flow_handle);
+       bnxt_hwrm_cfa_flow_free(bp, new_node);
 put_tunnel:
        bnxt_tc_put_tunnel_handle(bp, flow, new_node);
 put_l2:
@@ -1401,6 +1427,32 @@ static int bnxt_tc_get_flow_stats(struct bnxt *bp,
        return 0;
 }
 
+static void bnxt_fill_cfa_stats_req(struct bnxt *bp,
+                                   struct bnxt_tc_flow_node *flow_node,
+                                   __le16 *flow_handle, __le32 *flow_id)
+{
+       u16 handle;
+
+       if (bp->fw_cap & BNXT_FW_CAP_OVS_64BIT_HANDLE) {
+               *flow_id = flow_node->flow_id;
+
+               /* If flow_id is used to fetch flow stats then:
+                * 1. lower 12 bits of flow_handle must be set to all 1s.
+                * 2. 15th bit of flow_handle must specify the flow
+                *    direction (TX/RX).
+                */
+               if (flow_node->flow.dir == BNXT_DIR_RX)
+                       handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_DIR_RX |
+                                CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
+               else
+                       handle = CFA_FLOW_INFO_REQ_FLOW_HANDLE_MAX_MASK;
+
+               *flow_handle = cpu_to_le16(handle);
+       } else {
+               *flow_handle = flow_node->flow_handle;
+       }
+}
+
 static int
 bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
                             struct bnxt_tc_stats_batch stats_batch[])
@@ -1408,6 +1460,7 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
        struct hwrm_cfa_flow_stats_input req = { 0 };
        struct hwrm_cfa_flow_stats_output *resp;
        __le16 *req_flow_handles = &req.flow_handle_0;
+       __le32 *req_flow_ids = &req.flow_id_0;
        int rc, i;
 
        bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_CFA_FLOW_STATS, -1, -1);
@@ -1415,7 +1468,8 @@ bnxt_hwrm_cfa_flow_stats_get(struct bnxt *bp, int num_flows,
        for (i = 0; i < num_flows; i++) {
                struct bnxt_tc_flow_node *flow_node = stats_batch[i].flow_node;
 
-               req_flow_handles[i] = flow_node->flow_handle;
+               bnxt_fill_cfa_stats_req(bp, flow_node,
+                                       &req_flow_handles[i], &req_flow_ids[i]);
        }
 
        mutex_lock(&bp->hwrm_cmd_lock);
index 97e09a8..8a09689 100644 (file)
@@ -98,6 +98,9 @@ struct bnxt_tc_flow {
 
        /* flow applicable to pkts ingressing on this fid */
        u16                             src_fid;
+       u8                              dir;
+#define BNXT_DIR_RX    1
+#define BNXT_DIR_TX    0
        struct bnxt_tc_l2_key           l2_key;
        struct bnxt_tc_l2_key           l2_mask;
        struct bnxt_tc_l3_key           l3_key;
@@ -170,7 +173,9 @@ struct bnxt_tc_flow_node {
 
        struct bnxt_tc_flow             flow;
 
+       __le64                          ext_flow_handle;
        __le16                          flow_handle;
+       __le32                          flow_id;
 
        /* L2 node in l2 hashtable that shares flow's l2 key */
        struct bnxt_tc_l2_node          *l2_node;