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 <oka@qca.qualcomm.com>

Change-Id: I57125b3e1fbad0345b6e1f4ed25e71babaf4f520
CRs-Fixed: 982728
This commit is contained in:
Houston Hoffman 2016-04-13 18:55:37 -07:00 • committed by Gerrit - the friendly Code Review server
commit c7d5429428
5 changed files with 328 additions and 272 deletions

View file

@ -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];
};

View file

@ -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);

View file

@ -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;
};

View file

@ -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

View file

@ -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));