static int ath10k_ce_init_dest_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); nentries = roundup_pow_of_two(attr->dest_nentries); memset(dest_ring->base_addr_owner_space, 0, nentries * sizeof(struct ce_desc)); dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); dest_ring->sw_index &= dest_ring->nentries_mask; dest_ring->write_index = ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); dest_ring->write_index &= dest_ring->nentries_mask; ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, dest_ring->base_addr_ce_space); ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ce dest ring id %d entries %d base_addr %pK\n", ce_id, nentries, dest_ring->base_addr_owner_space); return 0; }
static int ath10k_ce_init_dest_ring(struct ath10k *ar, unsigned int ce_id, struct ath10k_ce_pipe *ce_state, const struct ce_attr *attr) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_ring *dest_ring; unsigned int nentries = attr->dest_nentries; unsigned int ce_nbytes; u32 ctrl_addr = ath10k_ce_base_address(ce_id); dma_addr_t base_addr; char *ptr; nentries = roundup_pow_of_two(nentries); if (ce_state->dest_ring) { WARN_ON(ce_state->dest_ring->nentries != nentries); return 0; } ce_nbytes = sizeof(struct ath10k_ce_ring) + (nentries * sizeof(void *)); ptr = kzalloc(ce_nbytes, GFP_KERNEL); if (ptr == NULL) return -ENOMEM; ce_state->dest_ring = (struct ath10k_ce_ring *)ptr; dest_ring = ce_state->dest_ring; ptr += sizeof(struct ath10k_ce_ring); dest_ring->nentries = nentries; dest_ring->nentries_mask = nentries - 1; dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); dest_ring->sw_index &= dest_ring->nentries_mask; dest_ring->write_index = ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); dest_ring->write_index &= dest_ring->nentries_mask; dest_ring->per_transfer_context = (void **)ptr; /* * Legacy platforms that do not support cache * coherent DMA are unsupported */ dest_ring->base_addr_owner_space_unaligned = pci_alloc_consistent(ar_pci->pdev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), &base_addr); if (!dest_ring->base_addr_owner_space_unaligned) { kfree(ce_state->dest_ring); ce_state->dest_ring = NULL; return -ENOMEM; } dest_ring->base_addr_ce_space_unaligned = base_addr; /* * Correctly initialize memory to 0 to prevent garbage * data crashing system when download firmware */ memset(dest_ring->base_addr_owner_space_unaligned, 0, nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN); dest_ring->base_addr_owner_space = PTR_ALIGN( dest_ring->base_addr_owner_space_unaligned, CE_DESC_RING_ALIGN); dest_ring->base_addr_ce_space = ALIGN( dest_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); ath10k_ce_dest_ring_base_addr_set(ar, ctrl_addr, dest_ring->base_addr_ce_space); ath10k_ce_dest_ring_size_set(ar, ctrl_addr, nentries); ath10k_ce_dest_ring_byte_swap_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); ath10k_dbg(ATH10K_DBG_BOOT, "boot ce dest ring id %d entries %d base_addr %p\n", ce_id, nentries, dest_ring->base_addr_owner_space); return 0; }