/* NB: Modeled after ath10k_ce_completed_send_next */ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, u32 *bufferp, unsigned int *nbytesp, unsigned int *transfer_idp) { struct ath10k_ce_ring *src_ring; unsigned int nentries_mask; unsigned int sw_index; unsigned int write_index; int ret; struct ath10k *ar; struct ath10k_pci *ar_pci; src_ring = ce_state->src_ring; if (!src_ring) return -EIO; ar = ce_state->ar; ar_pci = ath10k_pci_priv(ar); spin_lock_bh(&ar_pci->ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; write_index = src_ring->write_index; if (write_index != sw_index) { struct ce_desc *base = src_ring->base_addr_owner_space; struct ce_desc *desc = CE_SRC_RING_TO_DESC(base, sw_index); /* Return data from completed source descriptor */ *bufferp = __le32_to_cpu(desc->addr); *nbytesp = __le16_to_cpu(desc->nbytes); *transfer_idp = MS(__le16_to_cpu(desc->flags), CE_DESC_FLAGS_META_DATA); if (per_transfer_contextp) *per_transfer_contextp = src_ring->per_transfer_context[sw_index]; /* sanity */ src_ring->per_transfer_context[sw_index] = NULL; /* Update sw_index */ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); src_ring->sw_index = sw_index; ret = 0; } else { ret = -EIO; } spin_unlock_bh(&ar_pci->ce_lock); return ret; }
/* * Guts of ath10k_ce_send. * The caller takes responsibility for any needed locking. */ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, void *per_transfer_context, u32 buffer, unsigned int nbytes, unsigned int transfer_id, unsigned int flags) { struct ath10k *ar = ce_state->ar; struct ath10k_ce_ring *src_ring = ce_state->src_ring; struct ce_desc *desc, sdesc; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; unsigned int write_index = src_ring->write_index; u32 ctrl_addr = ce_state->ctrl_addr; u32 desc_flags = 0; int ret = 0; if (nbytes > ce_state->src_sz_max) ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n", __func__, nbytes, ce_state->src_sz_max); if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) <= 0)) { ret = -ENOSR; goto exit; } desc = CE_SRC_RING_TO_DESC(src_ring->base_addr_owner_space, write_index); desc_flags |= SM(transfer_id, CE_DESC_FLAGS_META_DATA); if (flags & CE_SEND_FLAG_GATHER) desc_flags |= CE_DESC_FLAGS_GATHER; if (flags & CE_SEND_FLAG_BYTE_SWAP) desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; sdesc.addr = __cpu_to_le32(buffer); sdesc.nbytes = __cpu_to_le16(nbytes); sdesc.flags = __cpu_to_le16(desc_flags); *desc = sdesc; src_ring->per_transfer_context[write_index] = per_transfer_context; /* Update Source Ring Write Index */ write_index = CE_RING_IDX_INCR(nentries_mask, write_index); /* WORKAROUND */ if (!(flags & CE_SEND_FLAG_GATHER)) ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); src_ring->write_index = write_index; exit: return ret; }
/* * Guts of ath10k_ce_completed_send_next. * The caller takes responsibility for any necessary locking. */ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp, u32 *bufferp, unsigned int *nbytesp, unsigned int *transfer_idp) { struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 ctrl_addr = ce_state->ctrl_addr; struct ath10k *ar = ce_state->ar; unsigned int nentries_mask = src_ring->nentries_mask; unsigned int sw_index = src_ring->sw_index; struct ce_desc *sdesc, *sbase; unsigned int read_index; int ret; if (src_ring->hw_index == sw_index) { /* * The SW completion index has caught up with the cached * version of the HW completion index. * Update the cached HW completion index to see whether * the SW has really caught up to the HW, or if the cached * value of the HW index has become stale. */ ret = ath10k_pci_wake(ar); if (ret) return ret; src_ring->hw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); src_ring->hw_index &= nentries_mask; ath10k_pci_sleep(ar); } read_index = src_ring->hw_index; if ((read_index == sw_index) || (read_index == 0xffffffff)) return -EIO; sbase = src_ring->shadow_base; sdesc = CE_SRC_RING_TO_DESC(sbase, sw_index); /* Return data from completed source descriptor */ *bufferp = __le32_to_cpu(sdesc->addr); *nbytesp = __le16_to_cpu(sdesc->nbytes); *transfer_idp = MS(__le16_to_cpu(sdesc->flags), CE_DESC_FLAGS_META_DATA); if (per_transfer_contextp) *per_transfer_contextp = src_ring->per_transfer_context[sw_index]; /* sanity */ src_ring->per_transfer_context[sw_index] = NULL; /* Update sw_index */ sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); src_ring->sw_index = sw_index; return 0; }