123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #include "hif.h"
- #include "hif_io32.h"
- #include "reg_struct.h"
- #include "ce_api.h"
- #include "ce_main.h"
- #include "ce_internal.h"
- #include "ce_reg.h"
- #include "qdf_lock.h"
- #include "regtable.h"
- #include "hif_main.h"
- #include "hif_debug.h"
- #include "hal_api.h"
- #include "pld_common.h"
- /*
- * Support for Copy Engine hardware, which is mainly used for
- * communication between Host and Target over a PCIe interconnect.
- */
- /*
- * A single CopyEngine (CE) comprises two "rings":
- * a source ring
- * a destination ring
- *
- * Each ring consists of a number of descriptors which specify
- * an address, length, and meta-data.
- *
- * Typically, one side of the PCIe interconnect (Host or Target)
- * controls one ring and the other side controls the other ring.
- * The source side chooses when to initiate a transfer and it
- * chooses what to send (buffer address, length). The destination
- * side keeps a supply of "anonymous receive buffers" available and
- * it handles incoming data as it arrives (when the destination
- * receives an interrupt).
- *
- * The sender may send a simple buffer (address/length) or it may
- * send a small list of buffers. When a small list is sent, hardware
- * "gathers" these and they end up in a single destination buffer
- * with a single interrupt.
- *
- * There are several "contexts" managed by this layer -- more, it
- * may seem -- than should be needed. These are provided mainly for
- * maximum flexibility and especially to facilitate a simpler HIF
- * implementation. There are per-CopyEngine recv, send, and watermark
- * contexts. These are supplied by the caller when a recv, send,
- * or watermark handler is established and they are echoed back to
- * the caller when the respective callbacks are invoked. There is
- * also a per-transfer context supplied by the caller when a buffer
- * (or sendlist) is sent and when a buffer is enqueued for recv.
- * These per-transfer contexts are echoed back to the caller when
- * the buffer is sent/received.
- * Target TX harsh result toeplitz_hash_result
- */
- #define CE_ADDR_COPY(desc, dma_addr) do {\
- (desc)->buffer_addr_lo = (uint32_t)((dma_addr) &\
- 0xFFFFFFFF);\
- (desc)->buffer_addr_hi =\
- (uint32_t)(((dma_addr) >> 32) & 0xFF);\
- } while (0)
- int
- ce_send_nolock_srng(struct CE_handle *copyeng,
- void *per_transfer_context,
- qdf_dma_addr_t buffer,
- uint32_t nbytes,
- uint32_t transfer_id,
- uint32_t flags,
- uint32_t user_flags)
- {
- int status;
- struct CE_state *CE_state = (struct CE_state *)copyeng;
- struct CE_ring_state *src_ring = CE_state->src_ring;
- unsigned int nentries_mask = src_ring->nentries_mask;
- unsigned int write_index = src_ring->write_index;
- uint64_t dma_addr = buffer;
- struct hif_softc *scn = CE_state->scn;
- if (Q_TARGET_ACCESS_BEGIN(scn) < 0)
- return QDF_STATUS_E_FAILURE;
- if (unlikely(hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx,
- false) <= 0)) {
- OL_ATH_CE_PKT_ERROR_COUNT_INCR(scn, CE_RING_DELTA_FAIL);
- Q_TARGET_ACCESS_END(scn);
- return QDF_STATUS_E_FAILURE;
- }
- {
- enum hif_ce_event_type event_type = HIF_TX_GATHER_DESC_POST;
- struct ce_srng_src_desc *src_desc;
- if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
- Q_TARGET_ACCESS_END(scn);
- return QDF_STATUS_E_FAILURE;
- }
- src_desc = hal_srng_src_get_next_reaped(scn->hal_soc,
- src_ring->srng_ctx);
- /* Update low 32 bits source descriptor address */
- src_desc->buffer_addr_lo =
- (uint32_t)(dma_addr & 0xFFFFFFFF);
- src_desc->buffer_addr_hi =
- (uint32_t)((dma_addr >> 32) & 0xFF);
- src_desc->meta_data = transfer_id;
- /*
- * Set the swap bit if:
- * typical sends on this CE are swapped (host is big-endian)
- * and this send doesn't disable the swapping
- * (data is not bytestream)
- */
- src_desc->byte_swap =
- (((CE_state->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
- != 0) & ((flags & CE_SEND_FLAG_SWAP_DISABLE) == 0));
- src_desc->gather = ((flags & CE_SEND_FLAG_GATHER) != 0);
- src_desc->nbytes = nbytes;
- src_ring->per_transfer_context[write_index] =
- per_transfer_context;
- write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
- hal_srng_access_end(scn->hal_soc, src_ring->srng_ctx);
- /* src_ring->write index hasn't been updated event though
- * the register has allready been written to.
- */
- hif_record_ce_desc_event(scn, CE_state->id, event_type,
- (union ce_desc *) src_desc, per_transfer_context,
- src_ring->write_index);
- src_ring->write_index = write_index;
- status = QDF_STATUS_SUCCESS;
- }
- Q_TARGET_ACCESS_END(scn);
- return status;
- }
- int
- ce_sendlist_send_srng(struct CE_handle *copyeng,
- void *per_transfer_context,
- struct ce_sendlist *sendlist, unsigned int transfer_id)
- {
- int status = -ENOMEM;
- struct ce_sendlist_s *sl = (struct ce_sendlist_s *)sendlist;
- struct CE_state *CE_state = (struct CE_state *)copyeng;
- struct CE_ring_state *src_ring = CE_state->src_ring;
- unsigned int num_items = sl->num_items;
- unsigned int sw_index;
- unsigned int write_index;
- struct hif_softc *scn = CE_state->scn;
- QDF_ASSERT((num_items > 0) && (num_items < src_ring->nentries));
- qdf_spin_lock_bh(&CE_state->ce_index_lock);
- sw_index = src_ring->sw_index;
- write_index = src_ring->write_index;
- if (hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx, false) >=
- num_items) {
- struct ce_sendlist_item *item;
- int i;
- /* handle all but the last item uniformly */
- for (i = 0; i < num_items - 1; i++) {
- item = &sl->item[i];
- /* TBDXXX: Support extensible sendlist_types? */
- QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE);
- status = ce_send_nolock_srng(copyeng,
- CE_SENDLIST_ITEM_CTXT,
- (qdf_dma_addr_t) item->data,
- item->u.nbytes, transfer_id,
- item->flags | CE_SEND_FLAG_GATHER,
- item->user_flags);
- QDF_ASSERT(status == QDF_STATUS_SUCCESS);
- }
- /* provide valid context pointer for final item */
- item = &sl->item[i];
- /* TBDXXX: Support extensible sendlist_types? */
- QDF_ASSERT(item->send_type == CE_SIMPLE_BUFFER_TYPE);
- status = ce_send_nolock_srng(copyeng, per_transfer_context,
- (qdf_dma_addr_t) item->data,
- item->u.nbytes,
- transfer_id, item->flags,
- item->user_flags);
- QDF_ASSERT(status == QDF_STATUS_SUCCESS);
- QDF_NBUF_UPDATE_TX_PKT_COUNT((qdf_nbuf_t)per_transfer_context,
- QDF_NBUF_TX_PKT_CE);
- DPTRACE(qdf_dp_trace((qdf_nbuf_t)per_transfer_context,
- QDF_DP_TRACE_CE_PACKET_PTR_RECORD,
- (uint8_t *)(((qdf_nbuf_t)per_transfer_context)->data),
- sizeof(((qdf_nbuf_t)per_transfer_context)->data), QDF_TX));
- } else {
- /*
- * Probably not worth the additional complexity to support
- * partial sends with continuation or notification. We expect
- * to use large rings and small sendlists. If we can't handle
- * the entire request at once, punt it back to the caller.
- */
- }
- qdf_spin_unlock_bh(&CE_state->ce_index_lock);
- return status;
- }
- #define SLOTS_PER_DATAPATH_TX 2
- #ifndef AH_NEED_TX_DATA_SWAP
- #define AH_NEED_TX_DATA_SWAP 0
- #endif
- /**
- * ce_recv_buf_enqueue_srng() - enqueue a recv buffer into a copy engine
- * @coyeng: copy engine handle
- * @per_recv_context: virtual address of the nbuf
- * @buffer: physical address of the nbuf
- *
- * Return: 0 if the buffer is enqueued
- */
- int
- ce_recv_buf_enqueue_srng(struct CE_handle *copyeng,
- void *per_recv_context, qdf_dma_addr_t buffer)
- {
- int status;
- struct CE_state *CE_state = (struct CE_state *)copyeng;
- struct CE_ring_state *dest_ring = CE_state->dest_ring;
- unsigned int nentries_mask = dest_ring->nentries_mask;
- unsigned int write_index;
- unsigned int sw_index;
- uint64_t dma_addr = buffer;
- struct hif_softc *scn = CE_state->scn;
- qdf_spin_lock_bh(&CE_state->ce_index_lock);
- write_index = dest_ring->write_index;
- sw_index = dest_ring->sw_index;
- if (Q_TARGET_ACCESS_BEGIN(scn) < 0) {
- qdf_spin_unlock_bh(&CE_state->ce_index_lock);
- return -EIO;
- }
- if (hal_srng_access_start(scn->hal_soc, dest_ring->srng_ctx)) {
- qdf_spin_unlock_bh(&CE_state->ce_index_lock);
- return QDF_STATUS_E_FAILURE;
- }
- if ((hal_srng_src_num_avail(scn->hal_soc,
- dest_ring->srng_ctx, false) > 0)) {
- struct ce_srng_dest_desc *dest_desc =
- hal_srng_src_get_next(scn->hal_soc,
- dest_ring->srng_ctx);
- if (dest_desc == NULL) {
- status = QDF_STATUS_E_FAILURE;
- } else {
- CE_ADDR_COPY(dest_desc, dma_addr);
- dest_ring->per_transfer_context[write_index] =
- per_recv_context;
- /* Update Destination Ring Write Index */
- write_index = CE_RING_IDX_INCR(nentries_mask,
- write_index);
- status = QDF_STATUS_SUCCESS;
- }
- } else
- status = QDF_STATUS_E_FAILURE;
- dest_ring->write_index = write_index;
- hal_srng_access_end(scn->hal_soc, dest_ring->srng_ctx);
- Q_TARGET_ACCESS_END(scn);
- qdf_spin_unlock_bh(&CE_state->ce_index_lock);
- return status;
- }
- /**
- * ce_send_watermarks_set_srng
- */
- void
- ce_send_watermarks_set_srng(struct CE_handle *copyeng,
- unsigned int low_alert_nentries,
- unsigned int high_alert_nentries)
- {
- /*TODO*/
- }
- /*
- * ce_recv_watermarks_set_srng
- */
- void
- ce_recv_watermarks_set_srng(struct CE_handle *copyeng,
- unsigned int low_alert_nentries,
- unsigned int high_alert_nentries)
- {
- /*TODO*/
- }
- unsigned int ce_send_entries_avail_srng(struct CE_handle *copyeng)
- {
- struct CE_state *CE_state = (struct CE_state *)copyeng;
- struct CE_ring_state *src_ring = CE_state->src_ring;
- struct hif_softc *scn = CE_state->scn;
- return hal_srng_src_num_avail(scn->hal_soc, src_ring->srng_ctx, false);
- }
- unsigned int ce_recv_entries_avail_srng(struct CE_handle *copyeng)
- {
- struct CE_state *CE_state = (struct CE_state *)copyeng;
- struct CE_ring_state *dest_ring = CE_state->dest_ring;
- struct hif_softc *scn = CE_state->scn;
- return hal_srng_src_num_avail(scn->hal_soc, dest_ring->srng_ctx, false);
- }
- /*
- * Guts of ce_recv_entries_done.
- * The caller takes responsibility for any necessary locking.
- */
- unsigned int
- ce_recv_entries_done_nolock_srng(struct hif_softc *scn,
- struct CE_state *CE_state)
- {
- struct CE_ring_state *status_ring = CE_state->status_ring;
- return hal_srng_dst_num_valid(scn->hal_soc,
- status_ring->srng_ctx, false);
- }
- /*
- * Guts of ce_send_entries_done.
- * The caller takes responsibility for any necessary locking.
- */
- unsigned int
- ce_send_entries_done_nolock_srng(struct hif_softc *scn,
- struct CE_state *CE_state)
- {
- struct CE_ring_state *src_ring = CE_state->src_ring;
- int count = 0;
- if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx))
- return 0;
- count = hal_srng_src_done_val(scn->hal_soc, src_ring->srng_ctx);
- hal_srng_access_end(scn->hal_soc, src_ring->srng_ctx);
- return count;
- }
- /* Debug support */
- void *ce_debug_cmplrn_context_srng; /* completed recv next context */
- void *ce_debug_cmplsn_context_srng; /* completed send next context */
- /*
- * Guts of ce_completed_recv_next.
- * The caller takes responsibility for any necessary locking.
- */
- int
- ce_completed_recv_next_nolock_srng(struct CE_state *CE_state,
- void **per_CE_contextp,
- void **per_transfer_contextp,
- qdf_dma_addr_t *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp,
- unsigned int *flagsp)
- {
- int status;
- struct CE_ring_state *dest_ring = CE_state->dest_ring;
- struct CE_ring_state *status_ring = CE_state->status_ring;
- unsigned int nentries_mask = dest_ring->nentries_mask;
- unsigned int sw_index = dest_ring->sw_index;
- struct hif_softc *scn = CE_state->scn;
- struct ce_srng_dest_status_desc *dest_status;
- int nbytes;
- struct ce_srng_dest_status_desc dest_status_info;
- if (hal_srng_access_start(scn->hal_soc, status_ring->srng_ctx)) {
- status = QDF_STATUS_E_FAILURE;
- goto done;
- }
- dest_status = hal_srng_dst_get_next(scn->hal_soc,
- status_ring->srng_ctx);
- if (dest_status == NULL) {
- status = QDF_STATUS_E_FAILURE;
- goto done;
- }
- /*
- * By copying the dest_desc_info element to local memory, we could
- * avoid extra memory read from non-cachable memory.
- */
- dest_status_info = *dest_status;
- nbytes = dest_status_info.nbytes;
- if (nbytes == 0) {
- /*
- * This closes a relatively unusual race where the Host
- * sees the updated DRRI before the update to the
- * corresponding descriptor has completed. We treat this
- * as a descriptor that is not yet done.
- */
- status = QDF_STATUS_E_FAILURE;
- goto done;
- }
- dest_status->nbytes = 0;
- *nbytesp = nbytes;
- *transfer_idp = dest_status_info.meta_data;
- *flagsp = (dest_status_info.byte_swap) ? CE_RECV_FLAG_SWAPPED : 0;
- if (per_CE_contextp)
- *per_CE_contextp = CE_state->recv_context;
- /* NOTE: sw_index is more like a read_index in this context. It has a
- * one-to-one mapping with status ring.
- * Get the per trasnfer context from dest_ring.
- */
- ce_debug_cmplrn_context_srng =
- dest_ring->per_transfer_context[sw_index];
- if (per_transfer_contextp)
- *per_transfer_contextp = ce_debug_cmplrn_context_srng;
- dest_ring->per_transfer_context[sw_index] = 0; /* sanity */
- /* Update sw_index */
- sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
- dest_ring->sw_index = sw_index;
- status = QDF_STATUS_SUCCESS;
- done:
- hal_srng_access_end(scn->hal_soc, status_ring->srng_ctx);
- return status;
- }
- QDF_STATUS
- ce_revoke_recv_next_srng(struct CE_handle *copyeng,
- void **per_CE_contextp,
- void **per_transfer_contextp, qdf_dma_addr_t *bufferp)
- {
- QDF_STATUS status = QDF_STATUS_E_FAILURE;
- return status;
- }
- /*
- * Guts of ce_completed_send_next.
- * The caller takes responsibility for any necessary locking.
- */
- int
- ce_completed_send_next_nolock_srng(struct CE_state *CE_state,
- void **per_CE_contextp,
- void **per_transfer_contextp,
- qdf_dma_addr_t *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp,
- unsigned int *sw_idx,
- unsigned int *hw_idx,
- uint32_t *toeplitz_hash_result)
- {
- int status = QDF_STATUS_E_FAILURE;
- struct CE_ring_state *src_ring = CE_state->src_ring;
- unsigned int nentries_mask = src_ring->nentries_mask;
- unsigned int sw_index = src_ring->sw_index;
- struct hif_softc *scn = CE_state->scn;
- struct ce_srng_src_desc *src_desc;
- if (hal_srng_access_start(scn->hal_soc, src_ring->srng_ctx)) {
- status = QDF_STATUS_E_FAILURE;
- return status;
- }
- src_desc = hal_srng_src_reap_next(scn->hal_soc, src_ring->srng_ctx);
- if (src_desc) {
- /* Return data from completed source descriptor */
- *bufferp = (qdf_dma_addr_t)
- (((uint64_t)(src_desc)->buffer_addr_lo +
- ((uint64_t)((src_desc)->buffer_addr_hi &
- 0xFF) << 32)));
- *nbytesp = src_desc->nbytes;
- *transfer_idp = src_desc->meta_data;
- *toeplitz_hash_result = 0; /*src_desc->toeplitz_hash_result;*/
- if (per_CE_contextp)
- *per_CE_contextp = CE_state->send_context;
- /* sw_index is used more like read index */
- ce_debug_cmplsn_context_srng =
- src_ring->per_transfer_context[sw_index];
- if (per_transfer_contextp)
- *per_transfer_contextp = ce_debug_cmplsn_context_srng;
- src_ring->per_transfer_context[sw_index] = 0; /* sanity */
- /* Update sw_index */
- sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
- src_ring->sw_index = sw_index;
- status = QDF_STATUS_SUCCESS;
- }
- hal_srng_access_end_reap(scn->hal_soc, src_ring->srng_ctx);
- return status;
- }
- /* NB: Modelled after ce_completed_send_next */
- QDF_STATUS
- ce_cancel_send_next_srng(struct CE_handle *copyeng,
- void **per_CE_contextp,
- void **per_transfer_contextp,
- qdf_dma_addr_t *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp,
- uint32_t *toeplitz_hash_result)
- {
- return 0;
- }
- /* Shift bits to convert IS_*_RING_*_WATERMARK_MASK to CE_WM_FLAG_*_* */
- #define CE_WM_SHFT 1
- /*
- * Number of times to check for any pending tx/rx completion on
- * a copy engine, this count should be big enough. Once we hit
- * this threashold we'll not check for any Tx/Rx comlpetion in same
- * interrupt handling. Note that this threashold is only used for
- * Rx interrupt processing, this can be used tor Tx as well if we
- * suspect any infinite loop in checking for pending Tx completion.
- */
- #define CE_TXRX_COMP_CHECK_THRESHOLD 20
- /*
- * Adjust interrupts for the copy complete handler.
- * If it's needed for either send or recv, then unmask
- * this interrupt; otherwise, mask it.
- *
- * Called with target_lock held.
- */
- static void
- ce_per_engine_handler_adjust_srng(struct CE_state *CE_state,
- int disable_copy_compl_intr)
- {
- }
- bool ce_check_int_watermark_srng(struct CE_state *CE_state, unsigned int *flags)
- {
- /*TODO*/
- return false;
- }
- uint32_t ce_get_desc_size_srng(uint8_t ring_type)
- {
- switch (ring_type) {
- case CE_RING_SRC:
- return sizeof(struct ce_srng_src_desc);
- case CE_RING_DEST:
- return sizeof(struct ce_srng_dest_desc);
- case CE_RING_STATUS:
- return sizeof(struct ce_srng_dest_status_desc);
- default:
- return 0;
- }
- return 0;
- }
- static void ce_srng_msi_ring_params_setup(struct hif_softc *scn, uint32_t ce_id,
- struct hal_srng_params *ring_params)
- {
- uint32_t addr_low;
- uint32_t addr_high;
- uint32_t msi_data_start;
- uint32_t msi_data_count;
- uint32_t msi_irq_start;
- int ret;
- ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
- &msi_data_count, &msi_data_start,
- &msi_irq_start);
- /* msi config not found */
- if (ret)
- return;
- HIF_INFO("%s: ce_id %d, msi_start: %d, msi_count %d", __func__, ce_id,
- msi_data_start, msi_data_count);
- pld_get_msi_address(scn->qdf_dev->dev, &addr_low, &addr_high);
- ring_params->msi_addr = addr_low;
- ring_params->msi_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32);
- ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
- ring_params->flags |= HAL_SRNG_MSI_INTR;
- HIF_INFO("%s: ce_id %d, msi_addr %p, msi_data %d", __func__, ce_id,
- (void *)ring_params->msi_addr, ring_params->msi_data);
- }
- void ce_srng_src_ring_setup(struct hif_softc *scn, uint32_t ce_id,
- struct CE_ring_state *src_ring)
- {
- struct hal_srng_params ring_params = {0};
- HIF_INFO("%s: ce_id %d", __func__, ce_id);
- ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
- ring_params.ring_base_paddr = src_ring->base_addr_CE_space;
- ring_params.ring_base_vaddr = src_ring->base_addr_owner_space;
- ring_params.num_entries = src_ring->nentries;
- /*
- * The minimum increment for the timer is 8us
- * A default value of 0 disables the timer
- * A valid default value caused continuous interrupts to
- * fire with MSI enabled. Need to revisit usage of the timer
- */
- ring_params.intr_timer_thres_us = 0;
- ring_params.intr_batch_cntr_thres_entries = 1;
- /* TODO
- * ring_params.msi_addr = XXX;
- * ring_params.msi_data = XXX;
- * ring_params.flags = XXX;
- */
- src_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_SRC, ce_id, 0,
- &ring_params);
- }
- void ce_srng_dest_ring_setup(struct hif_softc *scn, uint32_t ce_id,
- struct CE_ring_state *dest_ring,
- struct CE_attr *attr)
- {
- struct hal_srng_params ring_params = {0};
- HIF_INFO("%s: ce_id %d", __func__, ce_id);
- ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
- ring_params.ring_base_paddr = dest_ring->base_addr_CE_space;
- ring_params.ring_base_vaddr = dest_ring->base_addr_owner_space;
- ring_params.num_entries = dest_ring->nentries;
- ring_params.intr_timer_thres_us = 0;
- ring_params.intr_batch_cntr_thres_entries = 1;
- ring_params.max_buffer_length = attr->src_sz_max;
- /* TODO
- * ring_params.msi_addr = XXX;
- * ring_params.msi_data = XXX;
- * ring_params.flags = XXX;
- */
- /*Dest ring is also source ring*/
- dest_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST, ce_id, 0,
- &ring_params);
- }
- void ce_srng_status_ring_setup(struct hif_softc *scn, uint32_t ce_id,
- struct CE_ring_state *status_ring)
- {
- struct hal_srng_params ring_params = {0};
- HIF_INFO("%s: ce_id %d", __func__, ce_id);
- ce_srng_msi_ring_params_setup(scn, ce_id, &ring_params);
- ring_params.ring_base_paddr = status_ring->base_addr_CE_space;
- ring_params.ring_base_vaddr = status_ring->base_addr_owner_space;
- ring_params.num_entries = status_ring->nentries;
- ring_params.intr_timer_thres_us = 0;
- ring_params.intr_batch_cntr_thres_entries = 1;
- /* TODO
- * ring_params.msi_addr = XXX;
- * ring_params.msi_data = XXX;
- * ring_params.flags = XXX;
- */
- status_ring->srng_ctx = hal_srng_setup(scn->hal_soc, CE_DST_STATUS,
- ce_id, 0, &ring_params);
- }
- void ce_ring_setup_srng(struct hif_softc *scn, uint8_t ring_type,
- uint32_t ce_id, struct CE_ring_state *ring,
- struct CE_attr *attr)
- {
- switch (ring_type) {
- case CE_RING_SRC:
- ce_srng_src_ring_setup(scn, ce_id, ring);
- break;
- case CE_RING_DEST:
- ce_srng_dest_ring_setup(scn, ce_id, ring, attr);
- break;
- case CE_RING_STATUS:
- ce_srng_status_ring_setup(scn, ce_id, ring);
- break;
- default:
- qdf_assert(0);
- break;
- }
- }
- struct ce_ops ce_service_srng = {
- .ce_get_desc_size = ce_get_desc_size_srng,
- .ce_ring_setup = ce_ring_setup_srng,
- .ce_sendlist_send = ce_sendlist_send_srng,
- .ce_completed_recv_next_nolock = ce_completed_recv_next_nolock_srng,
- .ce_revoke_recv_next = ce_revoke_recv_next_srng,
- .ce_cancel_send_next = ce_cancel_send_next_srng,
- .ce_recv_buf_enqueue = ce_recv_buf_enqueue_srng,
- .ce_per_engine_handler_adjust = ce_per_engine_handler_adjust_srng,
- .ce_send_nolock = ce_send_nolock_srng,
- .watermark_int = ce_check_int_watermark_srng,
- .ce_completed_send_next_nolock = ce_completed_send_next_nolock_srng,
- .ce_recv_entries_done_nolock = ce_recv_entries_done_nolock_srng,
- .ce_send_entries_done_nolock = ce_send_entries_done_nolock_srng,
- };
- struct ce_ops *ce_services_srng()
- {
- return &ce_service_srng;
- }
|