net/qede/base: support ARFS mode
authorHarish Patil <harish.patil@qlogic.com>
Wed, 29 Mar 2017 20:36:59 +0000 (13:36 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 17:02:55 +0000 (19:02 +0200)
Add base driver APIs to enable accelerated RFS[aRFS] mode and ramrod
to configure rfs and ntuple filter.

Signed-off-by: Harish Patil <harish.patil@qlogic.com>
drivers/net/qede/base/ecore_cxt.c
drivers/net/qede/base/ecore_init_fw_funcs.c
drivers/net/qede/base/ecore_init_fw_funcs.h
drivers/net/qede/base/ecore_l2.c
drivers/net/qede/base/ecore_l2.h
drivers/net/qede/base/ecore_l2_api.h
drivers/net/qede/base/ecore_proto_if.h
drivers/net/qede/base/ecore_spq.h

index 1a2a701..80ad102 100644 (file)
@@ -192,9 +192,6 @@ struct ecore_cxt_mngr {
         */
        u32 vf_count;
 
-       /* total number of SRQ's for this hwfn */
-       u32                             srq_count;
-
        /* Acquired CIDs */
        struct ecore_cid_acquired_map acquired[MAX_CONN_TYPES];
        /* TBD - do we want this allocated to reserve space? */
@@ -213,10 +210,29 @@ struct ecore_cxt_mngr {
        u32 t2_num_pages;
        u64 first_free;
        u64 last_free;
+
+       /* The infrastructure originally was very generic and context/task
+        * oriented - per connection-type we would set how many of those
+        * are needed, and later when determining how much memory we're
+        * needing for a given block we'd iterate over all the relevant
+        * connection-types.
+        * But since then we've had some additional resources, some of which
+        * require memory which is indepent of the general context/task
+        * scheme. We add those here explicitly per-feature.
+        */
+
+       /* total number of SRQ's for this hwfn */
+       u32                             srq_count;
+
+       /* Maximal number of L2 steering filters */
+       u32                             arfs_count;
+
+       /* TODO - VF arfs filters ? */
 };
 
 /* check if resources/configuration is required according to protocol type */
-static OSAL_INLINE bool src_proto(enum protocol_type type)
+static OSAL_INLINE bool src_proto(struct ecore_hwfn *p_hwfn,
+                                 enum protocol_type type)
 {
        return type == PROTOCOLID_TOE;
 }
@@ -254,18 +270,22 @@ struct ecore_src_iids {
        u32 per_vf_cids;
 };
 
-static OSAL_INLINE void ecore_cxt_src_iids(struct ecore_cxt_mngr *p_mngr,
+static OSAL_INLINE void ecore_cxt_src_iids(struct ecore_hwfn *p_hwfn,
+                                          struct ecore_cxt_mngr *p_mngr,
                                           struct ecore_src_iids *iids)
 {
        u32 i;
 
        for (i = 0; i < MAX_CONN_TYPES; i++) {
-               if (!src_proto(i))
+               if (!src_proto(p_hwfn, i))
                        continue;
 
                iids->pf_cids += p_mngr->conn_cfg[i].cid_count;
                iids->per_vf_cids += p_mngr->conn_cfg[i].cids_per_vf;
        }
+
+       /* Add L2 filtering filters in addition */
+       iids->pf_cids += p_mngr->arfs_count;
 }
 
 /* counts the iids for the Timers block configuration */
@@ -686,7 +706,7 @@ enum _ecore_status_t ecore_cxt_cfg_ilt_compute(struct ecore_hwfn *p_hwfn)
 
        /* SRC */
        p_cli = &p_mngr->clients[ILT_CLI_SRC];
-       ecore_cxt_src_iids(p_mngr, &src_iids);
+       ecore_cxt_src_iids(p_hwfn, p_mngr, &src_iids);
 
        /* Both the PF and VFs searcher connections are stored in the per PF
         * database. Thus sum the PF searcher cids and all the VFs searcher
@@ -800,7 +820,7 @@ static enum _ecore_status_t ecore_cxt_src_t2_alloc(struct ecore_hwfn *p_hwfn)
        if (!p_src->active)
                return ECORE_SUCCESS;
 
-       ecore_cxt_src_iids(p_mngr, &src_iids);
+       ecore_cxt_src_iids(p_hwfn, p_mngr, &src_iids);
        conn_num = src_iids.pf_cids + src_iids.per_vf_cids * p_mngr->vf_count;
        total_size = conn_num * sizeof(struct src_ent);
 
@@ -1619,7 +1639,7 @@ static void ecore_src_init_pf(struct ecore_hwfn *p_hwfn)
        struct ecore_src_iids src_iids;
 
        OSAL_MEM_ZERO(&src_iids, sizeof(src_iids));
-       ecore_cxt_src_iids(p_mngr, &src_iids);
+       ecore_cxt_src_iids(p_hwfn, p_mngr, &src_iids);
        conn_num = src_iids.pf_cids + src_iids.per_vf_cids * p_mngr->vf_count;
        if (!conn_num)
                return;
@@ -1635,6 +1655,9 @@ static void ecore_src_init_pf(struct ecore_hwfn *p_hwfn)
                         p_hwfn->p_cxt_mngr->first_free);
        STORE_RT_REG_AGG(p_hwfn, SRC_REG_LASTFREE_RT_OFFSET,
                         p_hwfn->p_cxt_mngr->last_free);
+       DP_VERBOSE(p_hwfn, ECORE_MSG_ILT,
+                  "Configured SEARCHER for 0x%08x connections\n",
+                  conn_num);
 }
 
 /* Timers PF */
@@ -1978,10 +2001,10 @@ enum _ecore_status_t ecore_cxt_set_pf_params(struct ecore_hwfn *p_hwfn)
                         * As of now, allocates 16 * 2 per-VF [to retain regular
                         * functionality].
                         */
-                       ecore_cxt_set_proto_cid_count(p_hwfn,
-                               PROTOCOLID_ETH,
-                               p_params->num_cons, 32);
-
+                       ecore_cxt_set_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
+                                                     p_params->num_cons, 32);
+                       p_hwfn->p_cxt_mngr->arfs_count =
+                                               p_params->num_arfs_filters;
                        break;
                }
        default:
index af0deaa..004ab35 100644 (file)
@@ -1497,6 +1497,37 @@ void ecore_set_geneve_enable(struct ecore_hwfn *p_hwfn,
 #define RAM_LINE_SIZE sizeof(u64)
 #define REG_SIZE sizeof(u32)
 
+void ecore_set_rfs_mode_disable(struct ecore_hwfn *p_hwfn,
+       struct ecore_ptt *p_ptt,
+       u16 pf_id)
+{
+       union gft_cam_line_union cam_line;
+       struct gft_ram_line ram_line;
+       u32 i, *ram_line_ptr;
+
+       ram_line_ptr = (u32 *)&ram_line;
+
+       /* Stop using gft logic, disable gft search */
+       ecore_wr(p_hwfn, p_ptt, PRS_REG_SEARCH_GFT, 0);
+       ecore_wr(p_hwfn, p_ptt, PRS_REG_CM_HDR_GFT, 0x0);
+
+       /* Clean ram & cam for next rfs/gft session*/
+
+       /* Zero camline */
+       OSAL_MEMSET(&cam_line, 0, sizeof(cam_line));
+       ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,
+                                       cam_line.cam_line_mapped.camline);
+
+       /* Zero ramline */
+       OSAL_MEMSET(&ram_line, 0, sizeof(ram_line));
+
+       /* Each iteration write to reg */
+       for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++)
+               ecore_wr(p_hwfn, p_ptt, PRS_REG_GFT_PROFILE_MASK_RAM +
+                        RAM_LINE_SIZE * pf_id +
+                        i * REG_SIZE, *(ram_line_ptr + i));
+}
+
 
 void ecore_set_gft_event_id_cm_hdr(struct ecore_hwfn *p_hwfn,
                                   struct ecore_ptt *p_ptt)
index 2d1ab7c..4da3fc2 100644 (file)
@@ -350,6 +350,17 @@ void ecore_set_geneve_enable(struct ecore_hwfn *p_hwfn,
 void ecore_set_gft_event_id_cm_hdr(struct ecore_hwfn *p_hwfn,
                                   struct ecore_ptt *p_ptt);
 
+/**
+ * @brief ecore_set_rfs_mode_disable - Disable and configure HW for RFS
+ *
+ * @param p_hwfn -   HW device data
+ * @param p_ptt -   ptt window used for writing the registers.
+ * @param pf_id - pf on which to disable RFS.
+ */
+void ecore_set_rfs_mode_disable(struct ecore_hwfn *p_hwfn,
+                               struct ecore_ptt *p_ptt,
+                               u16 pf_id);
+
 /**
 * @brief ecore_set_rfs_mode_enable - enable and configure HW for RFS
 *
index c4af895..4ab8fd5 100644 (file)
@@ -2018,3 +2018,87 @@ void ecore_reset_vport_stats(struct ecore_dev *p_dev)
        else
                _ecore_get_vport_stats(p_dev, p_dev->reset_stats);
 }
+
+void ecore_arfs_mode_configure(struct ecore_hwfn *p_hwfn,
+                              struct ecore_ptt *p_ptt,
+                              struct ecore_arfs_config_params *p_cfg_params)
+{
+       if (p_cfg_params->arfs_enable) {
+               ecore_set_rfs_mode_enable(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
+                                         p_cfg_params->tcp,
+                                         p_cfg_params->udp,
+                                         p_cfg_params->ipv4,
+                                         p_cfg_params->ipv6);
+               DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
+                          "tcp = %s, udp = %s, ipv4 = %s, ipv6 =%s\n",
+                          p_cfg_params->tcp ? "Enable" : "Disable",
+                          p_cfg_params->udp ? "Enable" : "Disable",
+                          p_cfg_params->ipv4 ? "Enable" : "Disable",
+                          p_cfg_params->ipv6 ? "Enable" : "Disable");
+       } else {
+               ecore_set_rfs_mode_disable(p_hwfn, p_ptt, p_hwfn->rel_pf_id);
+       }
+       DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Configured ARFS mode : %s\n",
+                  p_cfg_params->arfs_enable ? "Enable" : "Disable");
+}
+
+enum _ecore_status_t
+ecore_configure_rfs_ntuple_filter(struct ecore_hwfn *p_hwfn,
+                                 struct ecore_ptt *p_ptt,
+                                 struct ecore_spq_comp_cb *p_cb,
+                                 dma_addr_t p_addr, u16 length,
+                                 u16 qid, u8 vport_id,
+                                 bool b_is_add)
+{
+       struct rx_update_gft_filter_data *p_ramrod = OSAL_NULL;
+       struct ecore_spq_entry *p_ent = OSAL_NULL;
+       struct ecore_sp_init_data init_data;
+       u16 abs_rx_q_id = 0;
+       u8 abs_vport_id = 0;
+       enum _ecore_status_t rc = ECORE_NOTIMPL;
+
+       rc = ecore_fw_vport(p_hwfn, vport_id, &abs_vport_id);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       rc = ecore_fw_l2_queue(p_hwfn, qid, &abs_rx_q_id);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       /* Get SPQ entry */
+       OSAL_MEMSET(&init_data, 0, sizeof(init_data));
+       init_data.cid = ecore_spq_get_cid(p_hwfn);
+
+       init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+
+       if (p_cb) {
+               init_data.comp_mode = ECORE_SPQ_MODE_CB;
+               init_data.p_comp_data = p_cb;
+       } else {
+               init_data.comp_mode = ECORE_SPQ_MODE_EBLOCK;
+       }
+
+       rc = ecore_sp_init_request(p_hwfn, &p_ent,
+                                  ETH_RAMROD_GFT_UPDATE_FILTER,
+                                  PROTOCOLID_ETH, &init_data);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       p_ramrod = &p_ent->ramrod.rx_update_gft;
+
+       DMA_REGPAIR_LE(p_ramrod->pkt_hdr_addr, p_addr);
+       p_ramrod->pkt_hdr_length = OSAL_CPU_TO_LE16(length);
+       p_ramrod->rx_qid_or_action_icid = OSAL_CPU_TO_LE16(abs_rx_q_id);
+       p_ramrod->vport_id = abs_vport_id;
+       p_ramrod->filter_type = RFS_FILTER_TYPE;
+       p_ramrod->filter_action = b_is_add ? GFT_ADD_FILTER
+                                          : GFT_DELETE_FILTER;
+
+       DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
+                  "V[%0x], Q[%04x] - %s filter from 0x%lx [length %04xb]\n",
+                  abs_vport_id, abs_rx_q_id,
+                  b_is_add ? "Adding" : "Removing",
+                  (unsigned long)p_addr, length);
+
+       return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL);
+}
index 3f86eac..7fe4cbc 100644 (file)
@@ -129,4 +129,31 @@ ecore_eth_txq_start_ramrod(struct ecore_hwfn *p_hwfn,
 
 u8 ecore_mcast_bin_from_mac(u8 *mac);
 
+/**
+ * @brief - ecore_configure_rfs_ntuple_filter
+ *
+ * This ramrod should be used to add or remove arfs hw filter
+ *
+ * @params p_hwfn
+ * @params p_ptt
+ * @params p_cb                Used for ECORE_SPQ_MODE_CB,where client would initialize
+                       it with cookie and callback function address, if not
+                       using this mode then client must pass NULL.
+ * @params p_addr      p_addr is an actual packet header that needs to be
+ *                     filter. It has to mapped with IO to read prior to
+ *                     calling this, [contains 4 tuples- src ip, dest ip,
+ *                     src port, dest port].
+ * @params length      length of p_addr header up to past the transport header.
+ * @params qid         receive packet will be directed to this queue.
+ * @params vport_id
+ * @params b_is_add    flag to add or remove filter.
+ *
+ */
+enum _ecore_status_t
+ecore_configure_rfs_ntuple_filter(struct ecore_hwfn *p_hwfn,
+                                 struct ecore_ptt *p_ptt,
+                                 struct ecore_spq_comp_cb *p_cb,
+                                 dma_addr_t p_addr, u16 length,
+                                 u16 qid, u8 vport_id,
+                                 bool b_is_add);
 #endif
index 5a7db76..d09f3c4 100644 (file)
@@ -141,6 +141,14 @@ struct ecore_filter_accept_flags {
 #define ECORE_ACCEPT_BCAST             0x20
 };
 
+struct ecore_arfs_config_params {
+       bool tcp;
+       bool udp;
+       bool ipv4;
+       bool ipv6;
+       bool arfs_enable;       /* Enable or disable arfs mode */
+};
+
 /* Add / remove / move / remove-all unicast MAC-VLAN filters.
  * FW will assert in the following cases, so driver should take care...:
  * 1. Adding a filter to a full table.
@@ -414,4 +422,18 @@ void ecore_get_vport_stats(struct ecore_dev *p_dev,
 
 void ecore_reset_vport_stats(struct ecore_dev *p_dev);
 
+/**
+ *@brief ecore_arfs_mode_configure -
+ *
+ *Enable or disable rfs mode. It must accept atleast one of tcp or udp true
+ *and atleast one of ipv4 or ipv6 true to enable rfs mode.
+ *
+ *@param p_hwfn
+ *@param p_ptt
+ *@param p_cfg_params          arfs mode configuration parameters.
+ *
+ */
+void ecore_arfs_mode_configure(struct ecore_hwfn *p_hwfn,
+                              struct ecore_ptt *p_ptt,
+                              struct ecore_arfs_config_params *p_cfg_params);
 #endif
index 0ac153f..226e3d2 100644 (file)
@@ -21,6 +21,12 @@ struct ecore_eth_pf_params {
         * to update_pf_params routine invoked before slowpath start
         */
        u16     num_cons;
+
+       /* To enable arfs, previous to HW-init a positive number needs to be
+        * set [as filters require allocated searcher ILT memory].
+        * This will set the maximal number of configured steering-filters.
+        */
+       u32     num_arfs_filters;
 };
 
 /* Most of the the parameters below are described in the FW iSCSI / TCP HSI */
index e2468b7..e530f83 100644 (file)
@@ -26,6 +26,7 @@ union ramrod_data {
        struct tx_queue_stop_ramrod_data                tx_queue_stop;
        struct vport_start_ramrod_data                  vport_start;
        struct vport_stop_ramrod_data                   vport_stop;
+       struct rx_update_gft_filter_data                rx_update_gft;
        struct vport_update_ramrod_data                 vport_update;
        struct core_rx_start_ramrod_data                core_rx_queue_start;
        struct core_rx_stop_ramrod_data                 core_rx_queue_stop;