qcacld-3.0: Bypass hif_completion_thread in recv

We want to process the completions in parallel.
Upper layer should take care of its own thread safety.
hif_completion_thread is a legacy function that does in
context serialization of hif completions. Bypass it.

Change-Id: I7953545b55dae093931741359bbf985e2fb9faca
CRs-Fixed: 941358
This commit is contained in:
Houston Hoffman 2015-09-28 12:56:25 -07:00 • committed by Satish Singh
commit 3d491e2e07

View file

@ -719,6 +719,33 @@ hif_pci_ce_send_done(struct CE_handle *copyeng, void *ce_context,
&toeplitz_hash_result) == CDF_STATUS_SUCCESS);
}
/**
* hif_ce_do_recv(): send message from copy engine to upper layers
* @msg_callbacks: structure containing callback and callback context
* @netbuff: skb containing message
* @nbytes: number of bytes in the message
* @pipe_info: used for the pipe_number info
*
* Checks the packet length, configures the lenght in the netbuff,
* and calls the upper layer callback.
*
* return: None
*/
static inline void hif_ce_do_recv(struct hif_msg_callbacks *msg_callbacks,
cdf_nbuf_t netbuf, int nbytes,
struct HIF_CE_pipe_info *pipe_info) {
if (nbytes <= pipe_info->buf_sz) {
cdf_nbuf_set_pktlen(netbuf, nbytes);
msg_callbacks->
rxCompletionHandler(msg_callbacks->Context,
netbuf, pipe_info->pipe_num);
} else {
HIF_ERROR("%s: Invalid Rx msg buf:%p nbytes:%d",
__func__, netbuf, nbytes);
cdf_nbuf_free(netbuf);
}
}
/* Called by lower (CE) layer when data is received from the Target. */
void
hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context,
@ -731,50 +758,18 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context,
struct HIF_CE_state *hif_state = pipe_info->HIF_CE_state;
struct CE_state *ce_state = (struct CE_state *) copyeng;
struct ol_softc *scn = hif_state->scn;
struct HIF_CE_completion_state *compl_state;
struct HIF_CE_completion_state *compl_queue_head, *compl_queue_tail;
struct hif_msg_callbacks *msg_callbacks =
&hif_state->msg_callbacks_current;
compl_queue_head = compl_queue_tail = NULL;
do {
cdf_spin_lock(&pipe_info->completion_freeq_lock);
compl_state = pipe_info->completion_freeq_head;
ASSERT(compl_state != NULL);
pipe_info->completion_freeq_head = compl_state->next;
cdf_spin_unlock(&pipe_info->completion_freeq_lock);
compl_state->next = NULL;
compl_state->send_or_recv = HIF_CE_COMPLETE_RECV;
compl_state->copyeng = copyeng;
compl_state->ce_context = ce_context;
compl_state->transfer_context = transfer_context;
compl_state->data = CE_data;
compl_state->nbytes = nbytes;
compl_state->transfer_id = transfer_id;
compl_state->flags = flags;
/* Enqueue at end of local queue */
if (compl_queue_tail) {
compl_queue_tail->next = compl_state;
} else {
compl_queue_head = compl_state;
}
compl_queue_tail = compl_state;
cdf_nbuf_unmap_single(scn->cdf_dev,
(cdf_nbuf_t) transfer_context,
CDF_DMA_FROM_DEVICE);
/*
* EV #112693 - [Peregrine][ES1][WB342][Win8x86][Performance]
* BSoD_0x133 occurred in VHT80 UDP_DL
* Break out DPC by force if number of loops in
* hif_pci_ce_recv_data reaches MAX_NUM_OF_RECEIVES to avoid
* spending too long time in DPC for each interrupt handling.
* Schedule another DPC to avoid data loss if we had taken
* force-break action before apply to Windows OS only
* currently, Linux/MAC os can expand to their platform
* if necessary
*/
atomic_inc(&pipe_info->recv_bufs_needed);
hif_post_recv_buffers_for_pipe(pipe_info);
hif_ce_do_recv(msg_callbacks, transfer_context, nbytes,
pipe_info);
/* Set up force_break flag if num of receices reaches
* MAX_NUM_OF_RECEIVES */
@ -787,23 +782,6 @@ hif_pci_ce_recv_data(struct CE_handle *copyeng, void *ce_context,
} while (ce_completed_recv_next(copyeng, &ce_context, &transfer_context,
&CE_data, &nbytes, &transfer_id,
&flags) == CDF_STATUS_SUCCESS);
cdf_spin_lock(&hif_state->completion_pendingq_lock);
/* Enqueue the local completion queue on the
* per-device completion queue */
if (hif_state->completion_pendingq_head) {
hif_state->completion_pendingq_tail->next = compl_queue_head;
hif_state->completion_pendingq_tail = compl_queue_tail;
cdf_spin_unlock(&hif_state->completion_pendingq_lock);
} else {
hif_state->completion_pendingq_head = compl_queue_head;
hif_state->completion_pendingq_tail = compl_queue_tail;
cdf_spin_unlock(&hif_state->completion_pendingq_lock);
/* Alert the recv completion service thread */
hif_completion_thread(hif_state);
}
}
/* TBDXXX: Set CE High Watermark; invoke txResourceAvailHandler in response */