From c7d54294286302a7be251b718fb3c6da01b719f5 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Wed, 13 Apr 2016 18:55:37 -0700 Subject: [PATCH] qcacmn: Support multiple RX CEs for NAPI/LRO/FastPath Make changes so that LRO and FastPath can check whether a given CE is a datapath RX CE. This is done through new flags in CE_state which indicate whether or not a given CE is a htt_[tr]rx CE. Also add support to enable multi-queue NAPI. Note that the paths are not yet parallel-execution protected, but this should be OK as all NAPI instances are processing the same interrupt now and as such as serialized. Acked-by: Orhan K AKYILDIZ Change-Id: I57125b3e1fbad0345b6e1f4ed25e71babaf4f520 CRs-Fixed: 982728 --- hif/inc/hif.h | 2 +- hif/inc/hif_napi.h | 1 - hif/src/ce/ce_internal.h | 4 + hif/src/ce/ce_main.c | 512 +++++++++++++++++++++------------------ hif/src/hif_napi.c | 73 +++--- 5 files changed, 324 insertions(+), 268 deletions(-) diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 4a851e840f43..1846117c8e68 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -116,6 +116,7 @@ struct qca_napi_stat { * instances. */ struct qca_napi_info { + struct net_device netdev; /* dummy net_dev */ struct napi_struct napi; /* one NAPI Instance per CE in phase I */ uint8_t scale; /* currently same on all instances */ uint8_t id; @@ -138,7 +139,6 @@ struct qca_napi_data { instances, indexed by pipe_id, not used by clients (clients use an id returned by create) */ - struct net_device netdev; /* dummy net_dev */ struct qca_napi_info napis[CE_COUNT_MAX]; }; diff --git a/hif/inc/hif_napi.h b/hif/inc/hif_napi.h index f1f07b2258ed..5a7e338f43c4 100644 --- a/hif/inc/hif_napi.h +++ b/hif/inc/hif_napi.h @@ -70,7 +70,6 @@ enum qca_napi_event { */ int hif_napi_create(struct hif_opaque_softc *hif, - uint8_t pipe_id, int (*poll)(struct napi_struct *, int), int budget, int scale); diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index 60f483a04dbd..e06957b0f2a5 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -140,6 +140,10 @@ struct CE_state { /* epping */ bool timer_inited; qdf_timer_t poll_timer; + + /* datapath - for faster access, use bools instead of a bitmap */ + bool htt_tx_data; + bool htt_rx_data; void (*lro_flush_cb)(void *); void *lro_data; }; diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 1b07de89b2de..42d896a98005 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -101,6 +101,262 @@ static unsigned int roundup_pwr2(unsigned int n) return 0; } +#define ADRASTEA_SRC_WR_INDEX_OFFSET 0x3C +#define ADRASTEA_DST_WR_INDEX_OFFSET 0x40 + +static struct shadow_reg_cfg target_shadow_reg_cfg_map[] = { + { 0, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 3, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 4, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 5, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 7, ADRASTEA_SRC_WR_INDEX_OFFSET}, + { 1, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 2, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 7, ADRASTEA_DST_WR_INDEX_OFFSET}, + { 8, ADRASTEA_DST_WR_INDEX_OFFSET}, +}; + + + +/* CE_PCI TABLE */ +/* + * NOTE: the table below is out of date, though still a useful reference. + * Refer to target_service_to_ce_map and hif_map_service_to_pipe for the actual + * mapping of HTC services to HIF pipes. + */ +/* + * This authoritative table defines Copy Engine configuration and the mapping + * of services/endpoints to CEs. A subset of this information is passed to + * the Target during startup as a prerequisite to entering BMI phase. + * See: + * target_service_to_ce_map - Target-side mapping + * hif_map_service_to_pipe - Host-side mapping + * target_ce_config - Target-side configuration + * host_ce_config - Host-side configuration + ============================================================================ + Purpose | Service / Endpoint | CE | Dire | Xfer | Xfer + | | | ctio | Size | Frequency + | | | n | | + ============================================================================ + tx | HTT_DATA (downlink) | CE 0 | h->t | medium - | very frequent + descriptor | | | | O(100B) | and regular + download | | | | | + ---------------------------------------------------------------------------- + rx | HTT_DATA (uplink) | CE 1 | t->h | small - | frequent and + indication | | | | O(10B) | regular + upload | | | | | + ---------------------------------------------------------------------------- + MSDU | DATA_BK (uplink) | CE 2 | t->h | large - | rare + upload | | | | O(1000B) | (frequent + e.g. noise | | | | | during IP1.0 + packets | | | | | testing) + ---------------------------------------------------------------------------- + MSDU | DATA_BK (downlink) | CE 3 | h->t | large - | very rare + download | | | | O(1000B) | (frequent + e.g. | | | | | during IP1.0 + misdirecte | | | | | testing) + d EAPOL | | | | | + packets | | | | | + ---------------------------------------------------------------------------- + n/a | DATA_BE, DATA_VI | CE 2 | t->h | | never(?) + | DATA_VO (uplink) | | | | + ---------------------------------------------------------------------------- + n/a | DATA_BE, DATA_VI | CE 3 | h->t | | never(?) + | DATA_VO (downlink) | | | | + ---------------------------------------------------------------------------- + WMI events | WMI_CONTROL (uplink) | CE 4 | t->h | medium - | infrequent + | | | | O(100B) | + ---------------------------------------------------------------------------- + WMI | WMI_CONTROL | CE 5 | h->t | medium - | infrequent + messages | (downlink) | | | O(100B) | + | | | | | + ---------------------------------------------------------------------------- + n/a | HTC_CTRL_RSVD, | CE 1 | t->h | | never(?) + | HTC_RAW_STREAMS | | | | + | (uplink) | | | | + ---------------------------------------------------------------------------- + n/a | HTC_CTRL_RSVD, | CE 0 | h->t | | never(?) + | HTC_RAW_STREAMS | | | | + | (downlink) | | | | + ---------------------------------------------------------------------------- + diag | none (raw CE) | CE 7 | t<>h | 4 | Diag Window + | | | | | infrequent + ============================================================================ + */ + +/* + * Map from service/endpoint to Copy Engine. + * This table is derived from the CE_PCI TABLE, above. + * It is passed to the Target at startup for use by firmware. + */ +static struct service_to_pipe target_service_to_ce_map_wlan[] = { + { + WMI_DATA_VO_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VO_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, /* could be moved to 3 (share with WMI) */ + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 4, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + WDI_IPA_TX_SVC, + PIPEDIR_OUT, /* in = DL = target -> host */ + 5, + }, + /* (Additions here) */ + + { /* Must be last */ + 0, + 0, + 0, + }, +}; + +static struct service_to_pipe *target_service_to_ce_map = + target_service_to_ce_map_wlan; +static int target_service_to_ce_map_sz = sizeof(target_service_to_ce_map_wlan); + +static struct shadow_reg_cfg *target_shadow_reg_cfg = target_shadow_reg_cfg_map; +static int shadow_cfg_sz = sizeof(target_shadow_reg_cfg_map); + +static struct service_to_pipe target_service_to_ce_map_wlan_epping[] = { + {WMI_DATA_VO_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ + {WMI_DATA_VO_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {WMI_DATA_BK_SVC, PIPEDIR_OUT, 4,}, /* out = UL = host -> target */ + {WMI_DATA_BK_SVC, PIPEDIR_IN, 1,}, /* in = DL = target -> host */ + {WMI_DATA_BE_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ + {WMI_DATA_BE_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {WMI_DATA_VI_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ + {WMI_DATA_VI_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {WMI_CONTROL_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ + {WMI_CONTROL_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0,}, /* out = UL = host -> target */ + {HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0,}, /* out = UL = host -> target */ + {HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ + {HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4,}, /* out = UL = host -> target */ + {HTT_DATA_MSG_SVC, PIPEDIR_IN, 1,}, /* in = DL = target -> host */ + {0, 0, 0,}, /* Must be last */ +}; + +/** + * ce_mark_datapath() - marks the ce_state->htt_rx_data accordingly + * @ce_state : pointer to the state context of the CE + * + * Description: + * Sets htt_rx_data attribute of the state structure if the + * CE serves one of the HTT DATA services. + * + * Return: + * false (attribute set to false) + * true (attribute set to true); + */ +bool ce_mark_datapath(struct CE_state *ce_state) +{ + struct service_to_pipe *svc_map; + size_t map_sz; + int i; + bool rc = false; + + if (ce_state != NULL) { + if (WLAN_IS_EPPING_ENABLED(hif_get_conparam(ce_state->scn))) { + svc_map = target_service_to_ce_map_wlan_epping; + map_sz = sizeof(target_service_to_ce_map_wlan_epping) / + sizeof(struct service_to_pipe); + } else { + svc_map = target_service_to_ce_map_wlan; + map_sz = sizeof(target_service_to_ce_map_wlan) / + sizeof(struct service_to_pipe); + } + for (i = 0; i < map_sz; i++) { + if ((svc_map[i].pipenum == ce_state->id) && + ((svc_map[i].service_id == HTT_DATA_MSG_SVC) || + (svc_map[i].service_id == HTT_DATA2_MSG_SVC) || + (svc_map[i].service_id == HTT_DATA3_MSG_SVC))) { + /* HTT CEs are unidirectional */ + if (svc_map[i].pipedir == PIPEDIR_IN) + ce_state->htt_rx_data = true; + else + ce_state->htt_tx_data = true; + rc = true; + } + } + } + return rc; +} + /* * Initialize a Copy Engine based on caller-supplied attributes. * This may be called once to initialize both source and destination @@ -456,6 +712,9 @@ struct CE_handle *ce_init(struct hif_softc *scn, if (Q_TARGET_ACCESS_END(scn) < 0) goto error_target_access; + /* update the htt_data attribute */ + ce_mark_datapath(CE_state); + return (struct CE_handle *)CE_state; error_target_access: @@ -486,7 +745,7 @@ ce_h2t_tx_ce_cleanup(struct CE_handle *ce_hdl) struct hif_softc *sc = ce_state->scn; uint32_t sw_index, write_index; - if (sc->fastpath_mode_on && (ce_state->id == CE_HTT_H2T_MSG)) { + if (sc->fastpath_mode_on && ce_state->htt_tx_data) { HIF_INFO("%s %d Fastpath mode ON, Cleaning up HTT Tx CE\n", __func__, __LINE__); sw_index = src_ring->sw_index; @@ -1296,217 +1555,6 @@ void hif_stop(struct hif_opaque_softc *hif_ctx) hif_state->started = false; } -#define ADRASTEA_SRC_WR_INDEX_OFFSET 0x3C -#define ADRASTEA_DST_WR_INDEX_OFFSET 0x40 - - -static struct shadow_reg_cfg target_shadow_reg_cfg_map[] = { - { 0, ADRASTEA_SRC_WR_INDEX_OFFSET}, - { 3, ADRASTEA_SRC_WR_INDEX_OFFSET}, - { 4, ADRASTEA_SRC_WR_INDEX_OFFSET}, - { 5, ADRASTEA_SRC_WR_INDEX_OFFSET}, - { 7, ADRASTEA_SRC_WR_INDEX_OFFSET}, - { 1, ADRASTEA_DST_WR_INDEX_OFFSET}, - { 2, ADRASTEA_DST_WR_INDEX_OFFSET}, - { 7, ADRASTEA_DST_WR_INDEX_OFFSET}, - { 8, ADRASTEA_DST_WR_INDEX_OFFSET}, -}; - - - -/* CE_PCI TABLE */ -/* - * NOTE: the table below is out of date, though still a useful reference. - * Refer to target_service_to_ce_map and hif_map_service_to_pipe for the actual - * mapping of HTC services to HIF pipes. - */ -/* - * This authoritative table defines Copy Engine configuration and the mapping - * of services/endpoints to CEs. A subset of this information is passed to - * the Target during startup as a prerequisite to entering BMI phase. - * See: - * target_service_to_ce_map - Target-side mapping - * hif_map_service_to_pipe - Host-side mapping - * target_ce_config - Target-side configuration - * host_ce_config - Host-side configuration - ============================================================================ - Purpose | Service / Endpoint | CE | Dire | Xfer | Xfer - | | | ctio | Size | Frequency - | | | n | | - ============================================================================ - tx | HTT_DATA (downlink) | CE 0 | h->t | medium - | very frequent - descriptor | | | | O(100B) | and regular - download | | | | | - ---------------------------------------------------------------------------- - rx | HTT_DATA (uplink) | CE 1 | t->h | small - | frequent and - indication | | | | O(10B) | regular - upload | | | | | - ---------------------------------------------------------------------------- - MSDU | DATA_BK (uplink) | CE 2 | t->h | large - | rare - upload | | | | O(1000B) | (frequent - e.g. noise | | | | | during IP1.0 - packets | | | | | testing) - ---------------------------------------------------------------------------- - MSDU | DATA_BK (downlink) | CE 3 | h->t | large - | very rare - download | | | | O(1000B) | (frequent - e.g. | | | | | during IP1.0 - misdirecte | | | | | testing) - d EAPOL | | | | | - packets | | | | | - ---------------------------------------------------------------------------- - n/a | DATA_BE, DATA_VI | CE 2 | t->h | | never(?) - | DATA_VO (uplink) | | | | - ---------------------------------------------------------------------------- - n/a | DATA_BE, DATA_VI | CE 3 | h->t | | never(?) - | DATA_VO (downlink) | | | | - ---------------------------------------------------------------------------- - WMI events | WMI_CONTROL (uplink) | CE 4 | t->h | medium - | infrequent - | | | | O(100B) | - ---------------------------------------------------------------------------- - WMI | WMI_CONTROL | CE 5 | h->t | medium - | infrequent - messages | (downlink) | | | O(100B) | - | | | | | - ---------------------------------------------------------------------------- - n/a | HTC_CTRL_RSVD, | CE 1 | t->h | | never(?) - | HTC_RAW_STREAMS | | | | - | (uplink) | | | | - ---------------------------------------------------------------------------- - n/a | HTC_CTRL_RSVD, | CE 0 | h->t | | never(?) - | HTC_RAW_STREAMS | | | | - | (downlink) | | | | - ---------------------------------------------------------------------------- - diag | none (raw CE) | CE 7 | t<>h | 4 | Diag Window - | | | | | infrequent - ============================================================================ - */ - -/* - * Map from service/endpoint to Copy Engine. - * This table is derived from the CE_PCI TABLE, above. - * It is passed to the Target at startup for use by firmware. - */ -static struct service_to_pipe target_service_to_ce_map_wlan[] = { - { - WMI_DATA_VO_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 3, - }, - { - WMI_DATA_VO_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - WMI_DATA_BK_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 3, - }, - { - WMI_DATA_BK_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - WMI_DATA_BE_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 3, - }, - { - WMI_DATA_BE_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - WMI_DATA_VI_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 3, - }, - { - WMI_DATA_VI_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - WMI_CONTROL_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 3, - }, - { - WMI_CONTROL_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - HTC_CTRL_RSVD_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 0, /* could be moved to 3 (share with WMI) */ - }, - { - HTC_CTRL_RSVD_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - HTC_RAW_STREAMS_SVC, /* not currently used */ - PIPEDIR_OUT, /* out = UL = host -> target */ - 0, - }, - { - HTC_RAW_STREAMS_SVC, /* not currently used */ - PIPEDIR_IN, /* in = DL = target -> host */ - 2, - }, - { - HTT_DATA_MSG_SVC, - PIPEDIR_OUT, /* out = UL = host -> target */ - 4, - }, - { - HTT_DATA_MSG_SVC, - PIPEDIR_IN, /* in = DL = target -> host */ - 1, - }, - { - WDI_IPA_TX_SVC, - PIPEDIR_OUT, /* in = DL = target -> host */ - 5, - }, - /* (Additions here) */ - - { /* Must be last */ - 0, - 0, - 0, - }, -}; - -static struct service_to_pipe *target_service_to_ce_map = - target_service_to_ce_map_wlan; -static int target_service_to_ce_map_sz = sizeof(target_service_to_ce_map_wlan); - -static struct shadow_reg_cfg *target_shadow_reg_cfg = target_shadow_reg_cfg_map; -static int shadow_cfg_sz = sizeof(target_shadow_reg_cfg_map); - -static struct service_to_pipe target_service_to_ce_map_wlan_epping[] = { - {WMI_DATA_VO_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ - {WMI_DATA_VO_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {WMI_DATA_BK_SVC, PIPEDIR_OUT, 4,}, /* out = UL = host -> target */ - {WMI_DATA_BK_SVC, PIPEDIR_IN, 1,}, /* in = DL = target -> host */ - {WMI_DATA_BE_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ - {WMI_DATA_BE_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {WMI_DATA_VI_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ - {WMI_DATA_VI_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {WMI_CONTROL_SVC, PIPEDIR_OUT, 3,}, /* out = UL = host -> target */ - {WMI_CONTROL_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {HTC_CTRL_RSVD_SVC, PIPEDIR_OUT, 0,}, /* out = UL = host -> target */ - {HTC_CTRL_RSVD_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {HTC_RAW_STREAMS_SVC, PIPEDIR_OUT, 0,}, /* out = UL = host -> target */ - {HTC_RAW_STREAMS_SVC, PIPEDIR_IN, 2,}, /* in = DL = target -> host */ - {HTT_DATA_MSG_SVC, PIPEDIR_OUT, 4,}, /* out = UL = host -> target */ - {HTT_DATA_MSG_SVC, PIPEDIR_IN, 1,}, /* in = DL = target -> host */ - {0, 0, 0,}, /* Must be last */ -}; - /** * hif_get_target_ce_config() - get copy engine configuration * @target_ce_config_ret: basic copy engine configuration @@ -1967,22 +2015,18 @@ u32 shadow_dst_wr_ind_addr(struct hif_softc *scn, u32 ctrl_addr) void ce_lro_flush_cb_register(struct hif_opaque_softc *hif_hdl, void (handler)(void *), void *data) { - uint8_t ul, dl; - int ul_polled, dl_polled; + int i; + struct CE_state *ce_state; struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); QDF_ASSERT(scn != NULL); - if (QDF_STATUS_SUCCESS != - hif_map_service_to_pipe(hif_hdl, HTT_DATA_MSG_SVC, - &ul, &dl, &ul_polled, &dl_polled)) { - printk("%s cannot map service to pipe\n", __FUNCTION__); - return; - } else { - struct CE_state *ce_state; - ce_state = scn->ce_id_to_state[dl]; - ce_state->lro_flush_cb = handler; - ce_state->lro_data = data; + for (i = 0; i < CE_COUNT_MAX; i++) { + ce_state = scn->ce_id_to_state[i]; + if (ce_state->htt_rx_data) { + ce_state->lro_flush_cb = handler; + ce_state->lro_data = data; + } } } @@ -1997,22 +2041,18 @@ void ce_lro_flush_cb_register(struct hif_opaque_softc *hif_hdl, */ void ce_lro_flush_cb_deregister(struct hif_opaque_softc *hif_hdl) { - uint8_t ul, dl; - int ul_polled, dl_polled; + int i; + struct CE_state *ce_state; struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); QDF_ASSERT(scn != NULL); - if (QDF_STATUS_SUCCESS != - hif_map_service_to_pipe(hif_hdl, HTT_DATA_MSG_SVC, - &ul, &dl, &ul_polled, &dl_polled)) { - printk("%s cannot map service to pipe\n", __FUNCTION__); - return; - } else { - struct CE_state *ce_state; - ce_state = scn->ce_id_to_state[dl]; - ce_state->lro_flush_cb = NULL; - ce_state->lro_data = NULL; + for (i = 0; i < CE_COUNT_MAX; i++) { + ce_state = scn->ce_id_to_state[i]; + if (ce_state->htt_rx_data) { + ce_state->lro_flush_cb = NULL; + ce_state->lro_data = NULL; + } } } #endif diff --git a/hif/src/hif_napi.c b/hif/src/hif_napi.c index 6e8fb4d068b9..efb9da70e4d3 100644 --- a/hif/src/hif_napi.c +++ b/hif/src/hif_napi.c @@ -67,17 +67,18 @@ enum napi_decision_vector { * > 0: id of the created object (for multi-NAPI, number of objects created) */ int hif_napi_create(struct hif_opaque_softc *hif_ctx, - uint8_t pipe_id, int (*poll)(struct napi_struct *, int), int budget, int scale) { + int i; struct qca_napi_data *napid; struct qca_napi_info *napii; + struct CE_state *ce_state; struct hif_softc *hif = HIF_GET_SOFTC(hif_ctx); - NAPI_DEBUG("-->(pipe=%d, budget=%d, scale=%d)", - pipe_id, budget, scale); + NAPI_DEBUG("-->(budget=%d, scale=%d)", + budget, scale); NAPI_DEBUG("hif->napi_data.state = 0x%08x", hif->napi_data.state); NAPI_DEBUG("hif->napi_data.ce_map = 0x%08x", @@ -88,40 +89,52 @@ int hif_napi_create(struct hif_opaque_softc *hif_ctx, memset(napid, 0, sizeof(struct qca_napi_data)); mutex_init(&(napid->mutex)); - init_dummy_netdev(&(napid->netdev)); - napid->state |= HIF_NAPI_INITED; HIF_INFO("%s: NAPI structures initialized", __func__); NAPI_DEBUG("NAPI structures initialized"); } - napii = &(napid->napis[pipe_id]); - memset(napii, 0, sizeof(struct qca_napi_info)); - napii->scale = scale; - napii->id = NAPI_PIPE2ID(pipe_id); + for (i = 0; i < CE_COUNT_MAX; i++) { + ce_state = hif->ce_id_to_state[i]; + NAPI_DEBUG("ce %d: htt_rx=%d htt_rx=%d", + i, ce_state->htt_rx_data, + ce_state->htt_tx_data); + if (!ce_state->htt_rx_data) + continue; - NAPI_DEBUG("adding napi=%p to netdev=%p (poll=%p, bdgt=%d)", - &(napii->napi), &(napid->netdev), poll, budget); - netif_napi_add(&(napid->netdev), &(napii->napi), poll, budget); + /* Now this is a CE where we need NAPI on */ + NAPI_DEBUG("Creating NAPI on pipe %d", i); - NAPI_DEBUG("after napi_add"); - NAPI_DEBUG("napi=0x%p, netdev=0x%p", - &(napii->napi), &(napid->netdev)); - NAPI_DEBUG("napi.dev_list.prev=0x%p, next=0x%p", - napii->napi.dev_list.prev, napii->napi.dev_list.next); - NAPI_DEBUG("dev.napi_list.prev=0x%p, next=0x%p", - napid->netdev.napi_list.prev, napid->netdev.napi_list.next); + napii = &(napid->napis[i]); + memset(napii, 0, sizeof(struct qca_napi_info)); + napii->scale = scale; + napii->id = NAPI_PIPE2ID(i); + init_dummy_netdev(&(napii->netdev)); - /* It is OK to change the state variable below without protection - * as there should be no-one around yet - */ - napid->ce_map |= (0x01 << pipe_id); - HIF_INFO("%s: NAPI id %d created for pipe %d", __func__, - napii->id, pipe_id); + NAPI_DEBUG("adding napi=%p to netdev=%p (poll=%p, bdgt=%d)", + &(napii->napi), &(napii->netdev), poll, budget); + netif_napi_add(&(napii->netdev), &(napii->napi), poll, budget); - NAPI_DEBUG("NAPI id %d created for pipe %d", napii->id, pipe_id); - NAPI_DEBUG("<--napi_id=%d]", napii->id); - return napii->id; + NAPI_DEBUG("after napi_add"); + NAPI_DEBUG("napi=0x%p, netdev=0x%p", + &(napii->napi), &(napii->netdev)); + NAPI_DEBUG("napi.dev_list.prev=0x%p, next=0x%p", + napii->napi.dev_list.prev, + napii->napi.dev_list.next); + NAPI_DEBUG("dev.napi_list.prev=0x%p, next=0x%p", + napii->netdev.napi_list.prev, + napii->netdev.napi_list.next); + + /* It is OK to change the state variable below without + * protection as there should be no-one around yet + */ + napid->ce_map |= (0x01 << i); + HIF_INFO("%s: NAPI id %d created for pipe %d", __func__, + napii->id, i); + } + NAPI_DEBUG("NAPI idscreated for pipe all applicable pipes"); + NAPI_DEBUG("<--napi_instances_map=%x]", napid->ce_map); + return napid->ce_map; } /** @@ -186,8 +199,8 @@ int hif_napi_destroy(struct hif_opaque_softc *hif_ctx, napii->napi.dev_list.prev, napii->napi.dev_list.next); NAPI_DEBUG("dev.napi_l.prv=0x%p, next=0x%p", - napid->netdev.napi_list.prev, - napid->netdev.napi_list.next); + napii->netdev.napi_list.prev, + napii->netdev.napi_list.next); netif_napi_del(&(napii->napi));