From 3d491e2e07628535a362f1fe56dc40f85c114e0b Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 28 Sep 2015 12:56:25 -0700 Subject: [PATCH] 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 --- core/hif/src/ce/ce_main.c | 88 +++++++++++++++------------------------ 1 file changed, 33 insertions(+), 55 deletions(-) diff --git a/core/hif/src/ce/ce_main.c b/core/hif/src/ce/ce_main.c index f27ab12125fe..683f86d4d183 100644 --- a/core/hif/src/ce/ce_main.c +++ b/core/hif/src/ce/ce_main.c @@ -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 */