From: Harish Patil Date: Wed, 29 Mar 2017 20:36:59 +0000 (-0700) Subject: net/qede/base: support ARFS mode X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=53437002903f647d10dc6f7d4ed0049bbcf040ec;p=dpdk.git net/qede/base: support ARFS mode Add base driver APIs to enable accelerated RFS[aRFS] mode and ramrod to configure rfs and ntuple filter. Signed-off-by: Harish Patil --- diff --git a/drivers/net/qede/base/ecore_cxt.c b/drivers/net/qede/base/ecore_cxt.c index 1a2a701651..80ad102420 100644 --- a/drivers/net/qede/base/ecore_cxt.c +++ b/drivers/net/qede/base/ecore_cxt.c @@ -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: diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.c b/drivers/net/qede/base/ecore_init_fw_funcs.c index af0deaabea..004ab351a3 100644 --- a/drivers/net/qede/base/ecore_init_fw_funcs.c +++ b/drivers/net/qede/base/ecore_init_fw_funcs.c @@ -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) diff --git a/drivers/net/qede/base/ecore_init_fw_funcs.h b/drivers/net/qede/base/ecore_init_fw_funcs.h index 2d1ab7cfe4..4da3fc29b8 100644 --- a/drivers/net/qede/base/ecore_init_fw_funcs.h +++ b/drivers/net/qede/base/ecore_init_fw_funcs.h @@ -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 * diff --git a/drivers/net/qede/base/ecore_l2.c b/drivers/net/qede/base/ecore_l2.c index c4af895792..4ab8fd5f26 100644 --- a/drivers/net/qede/base/ecore_l2.c +++ b/drivers/net/qede/base/ecore_l2.c @@ -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); +} diff --git a/drivers/net/qede/base/ecore_l2.h b/drivers/net/qede/base/ecore_l2.h index 3f86eac119..7fe4cbcb37 100644 --- a/drivers/net/qede/base/ecore_l2.h +++ b/drivers/net/qede/base/ecore_l2.h @@ -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 diff --git a/drivers/net/qede/base/ecore_l2_api.h b/drivers/net/qede/base/ecore_l2_api.h index 5a7db7600a..d09f3c4a35 100644 --- a/drivers/net/qede/base/ecore_l2_api.h +++ b/drivers/net/qede/base/ecore_l2_api.h @@ -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 diff --git a/drivers/net/qede/base/ecore_proto_if.h b/drivers/net/qede/base/ecore_proto_if.h index 0ac153f732..226e3d2acc 100644 --- a/drivers/net/qede/base/ecore_proto_if.h +++ b/drivers/net/qede/base/ecore_proto_if.h @@ -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 */ diff --git a/drivers/net/qede/base/ecore_spq.h b/drivers/net/qede/base/ecore_spq.h index e2468b7be4..e530f83484 100644 --- a/drivers/net/qede/base/ecore_spq.h +++ b/drivers/net/qede/base/ecore_spq.h @@ -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;