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; }
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries) { struct ath10k *ar = pipe->ar; struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; u32 ctrl_addr = pipe->ctrl_addr; u32 cur_write_idx = ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); /* Prevent CE ring stuck issue that will occur when ring is full. * Make sure that write index is 1 less than read index. */ if ((cur_write_idx + nentries) == dest_ring->sw_index) nentries -= 1; write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries); ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index); dest_ring->write_index = write_index; }
void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_fw_crash_data *crash_data) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_ce_crash_data ce; u32 addr, id; lockdep_assert_held(&ar->data_lock); ath10k_err(ar, "Copy Engine register dump:\n"); spin_lock_bh(&ar_pci->ce_lock); for (id = 0; id < CE_COUNT; id++) { addr = ath10k_ce_base_address(ar, id); ce.base_addr = cpu_to_le32(addr); ce.src_wr_idx = cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr)); ce.src_r_idx = cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr)); ce.dst_wr_idx = cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr)); ce.dst_r_idx = cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr)); if (crash_data) crash_data->ce_crash_data[id] = ce; ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id, le32_to_cpu(ce.base_addr), le32_to_cpu(ce.src_wr_idx), le32_to_cpu(ce.src_r_idx), le32_to_cpu(ce.dst_wr_idx), le32_to_cpu(ce.dst_r_idx)); } spin_unlock_bh(&ar_pci->ce_lock); }
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; }