Loading drivers/net/wireless/ath/ath10k/ce.c +76 −3 Original line number Diff line number Diff line Loading @@ -96,13 +96,29 @@ static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_get_from_ddr( struct ath10k *ar, u32 ce_id) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); return ar_opaque->vaddr_rri_on_ddr[ce_id] & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; u32 index; return ar_opaque->bus_ops->read32(ar, if (ar->rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_src_ring_read_index_get_from_ddr(ar, ce_id); else index = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + ar->hw_ce_regs->current_srri_addr); return index; } static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar, Loading Loading @@ -195,9 +211,19 @@ static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; u32 index; return ar_opaque->bus_ops->read32(ar, if (ar->rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = (ar_opaque->vaddr_rri_on_ddr[ce_id] >> CE_DDR_RRI_SHIFT) & CE_DDR_RRI_MASK; else index = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + ar->hw_ce_regs->current_drri_addr); return index; } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, Loading Loading @@ -449,7 +475,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, 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 sw_index; unsigned int write_index = src_ring->write_index; u32 ctrl_addr = ce_state->ctrl_addr; u32 desc_flags = 0; Loading @@ -462,6 +488,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n", __func__, nbytes, ce_state->src_sz_max); sw_index = ath10k_ce_src_ring_read_index_get_from_ddr(ar, ce_state->id); if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) <= 0)) { ret = -ENOSR; Loading Loading @@ -1235,6 +1262,52 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, return dest_ring; } void ce_config_rri_on_ddr(struct ath10k *ar) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 hi_paddr, low_paddr; u32 ce_base_addr; u32 ctrl1_regs; int i; ar_opaque->vaddr_rri_on_ddr = (u32 *)dma_alloc_coherent(ar->dev, (CE_COUNT * sizeof(u32)), &ar_opaque->paddr_rri_on_ddr, GFP_KERNEL); if (!ar_opaque->vaddr_rri_on_ddr) return; low_paddr = lower_32_bits(ar_opaque->paddr_rri_on_ddr); hi_paddr = upper_32_bits(ar_opaque->paddr_rri_on_ddr) & CE_DESC_FLAGS_GET_MASK; ar_opaque->bus_ops->write32(ar, ar->hw_ce_regs->ce_rri_low, low_paddr); ar_opaque->bus_ops->write32(ar, ar->hw_ce_regs->ce_rri_high, hi_paddr); for (i = 0; i < CE_COUNT; i++) { ctrl1_regs = ar->hw_ce_regs->ctrl1_regs->addr; ce_base_addr = ath10k_ce_base_address(ar, i); ar_opaque->bus_ops->write32(ar, ce_base_addr + ctrl1_regs, ar_opaque->bus_ops->read32(ar, ce_base_addr + ctrl1_regs) | ar->hw_ce_regs->upd->mask); } memset(ar_opaque->vaddr_rri_on_ddr, 0, CE_COUNT * sizeof(u32)); } void ce_remove_rri_on_ddr(struct ath10k *ar) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); if (!ar_opaque->vaddr_rri_on_ddr) return; dma_free_coherent(ar->dev, (CE_COUNT * sizeof(u32)), ar_opaque->vaddr_rri_on_ddr, ar_opaque->paddr_rri_on_ddr); } /* * Initialize a Copy Engine based on caller-supplied attributes. * This may be called once to initialize both source and destination Loading drivers/net/wireless/ath/ath10k/ce.h +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_GET_MASK 0x1F #define CE_DESC_37BIT_ADDR_MASK 0x1FFFFFFFFF #define CE_DDR_RRI_MASK 0xFFFF #define CE_DDR_RRI_SHIFT 16 /* Following desc flags are used in QCA99X0 */ #define CE_DESC_FLAGS_HOST_INT_DIS (1 << 2) Loading Loading @@ -211,6 +213,8 @@ struct bus_opaque { spinlock_t ce_lock; const struct ath10k_bus_ops *bus_ops; struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; u32 *vaddr_rri_on_ddr; dma_addr_t paddr_rri_on_ddr; }; /*==================Send====================*/ Loading Loading @@ -288,6 +292,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); void ce_config_rri_on_ddr(struct ath10k *ar); void ce_remove_rri_on_ddr(struct ath10k *ar); /*==================CE Engine Shutdown=======================*/ /* Loading drivers/net/wireless/ath/ath10k/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -2374,6 +2374,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->fw_flags = &wcn3990_fw_flags; ar->shadow_reg_value = &wcn3990_shadow_reg_value; ar->shadow_reg_address = &wcn3990_shadow_reg_address; ar->rri_on_ddr = true; break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", Loading drivers/net/wireless/ath/ath10k/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -967,6 +967,7 @@ struct ath10k { struct completion peer_delete_done; bool is_bmi; enum ieee80211_sta_state sta_state; bool rri_on_ddr; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; Loading drivers/net/wireless/ath/ath10k/hw.c +7 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,12 @@ struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { .wm_high = &wcn3990_dst_wm_high, }; static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = { .shift = 19, .mask = 0x00080000, .enable = 0x00000000, }; struct ath10k_hw_ce_regs wcn3990_ce_regs = { .sr_base_addr = 0x00000000, .sr_size_addr = 0x00000008, Loading @@ -305,6 +311,7 @@ struct ath10k_hw_ce_regs wcn3990_ce_regs = { .misc_regs = &wcn3990_misc_reg, .wm_srcr = &wcn3990_wm_src_ring, .wm_dstr = &wcn3990_wm_dst_ring, .upd = &wcn3990_ctrl1_upd, }; struct ath10k_hw_ce_regs_addr_map qcax_src_ring = { Loading Loading
drivers/net/wireless/ath/ath10k/ce.c +76 −3 Original line number Diff line number Diff line Loading @@ -96,13 +96,29 @@ static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_get_from_ddr( struct ath10k *ar, u32 ce_id) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); return ar_opaque->vaddr_rri_on_ddr[ce_id] & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; u32 index; return ar_opaque->bus_ops->read32(ar, if (ar->rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_src_ring_read_index_get_from_ddr(ar, ce_id); else index = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + ar->hw_ce_regs->current_srri_addr); return index; } static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar, Loading Loading @@ -195,9 +211,19 @@ static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; u32 index; return ar_opaque->bus_ops->read32(ar, if (ar->rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = (ar_opaque->vaddr_rri_on_ddr[ce_id] >> CE_DDR_RRI_SHIFT) & CE_DDR_RRI_MASK; else index = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + ar->hw_ce_regs->current_drri_addr); return index; } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, Loading Loading @@ -449,7 +475,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, 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 sw_index; unsigned int write_index = src_ring->write_index; u32 ctrl_addr = ce_state->ctrl_addr; u32 desc_flags = 0; Loading @@ -462,6 +488,7 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n", __func__, nbytes, ce_state->src_sz_max); sw_index = ath10k_ce_src_ring_read_index_get_from_ddr(ar, ce_state->id); if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) <= 0)) { ret = -ENOSR; Loading Loading @@ -1235,6 +1262,52 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, return dest_ring; } void ce_config_rri_on_ddr(struct ath10k *ar) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); u32 hi_paddr, low_paddr; u32 ce_base_addr; u32 ctrl1_regs; int i; ar_opaque->vaddr_rri_on_ddr = (u32 *)dma_alloc_coherent(ar->dev, (CE_COUNT * sizeof(u32)), &ar_opaque->paddr_rri_on_ddr, GFP_KERNEL); if (!ar_opaque->vaddr_rri_on_ddr) return; low_paddr = lower_32_bits(ar_opaque->paddr_rri_on_ddr); hi_paddr = upper_32_bits(ar_opaque->paddr_rri_on_ddr) & CE_DESC_FLAGS_GET_MASK; ar_opaque->bus_ops->write32(ar, ar->hw_ce_regs->ce_rri_low, low_paddr); ar_opaque->bus_ops->write32(ar, ar->hw_ce_regs->ce_rri_high, hi_paddr); for (i = 0; i < CE_COUNT; i++) { ctrl1_regs = ar->hw_ce_regs->ctrl1_regs->addr; ce_base_addr = ath10k_ce_base_address(ar, i); ar_opaque->bus_ops->write32(ar, ce_base_addr + ctrl1_regs, ar_opaque->bus_ops->read32(ar, ce_base_addr + ctrl1_regs) | ar->hw_ce_regs->upd->mask); } memset(ar_opaque->vaddr_rri_on_ddr, 0, CE_COUNT * sizeof(u32)); } void ce_remove_rri_on_ddr(struct ath10k *ar) { struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); if (!ar_opaque->vaddr_rri_on_ddr) return; dma_free_coherent(ar->dev, (CE_COUNT * sizeof(u32)), ar_opaque->vaddr_rri_on_ddr, ar_opaque->paddr_rri_on_ddr); } /* * Initialize a Copy Engine based on caller-supplied attributes. * This may be called once to initialize both source and destination Loading
drivers/net/wireless/ath/ath10k/ce.h +6 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,8 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_GET_MASK 0x1F #define CE_DESC_37BIT_ADDR_MASK 0x1FFFFFFFFF #define CE_DDR_RRI_MASK 0xFFFF #define CE_DDR_RRI_SHIFT 16 /* Following desc flags are used in QCA99X0 */ #define CE_DESC_FLAGS_HOST_INT_DIS (1 << 2) Loading Loading @@ -211,6 +213,8 @@ struct bus_opaque { spinlock_t ce_lock; const struct ath10k_bus_ops *bus_ops; struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; u32 *vaddr_rri_on_ddr; dma_addr_t paddr_rri_on_ddr; }; /*==================Send====================*/ Loading Loading @@ -288,6 +292,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); void ce_config_rri_on_ddr(struct ath10k *ar); void ce_remove_rri_on_ddr(struct ath10k *ar); /*==================CE Engine Shutdown=======================*/ /* Loading
drivers/net/wireless/ath/ath10k/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -2374,6 +2374,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->fw_flags = &wcn3990_fw_flags; ar->shadow_reg_value = &wcn3990_shadow_reg_value; ar->shadow_reg_address = &wcn3990_shadow_reg_address; ar->rri_on_ddr = true; break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", Loading
drivers/net/wireless/ath/ath10k/core.h +1 −0 Original line number Diff line number Diff line Loading @@ -967,6 +967,7 @@ struct ath10k { struct completion peer_delete_done; bool is_bmi; enum ieee80211_sta_state sta_state; bool rri_on_ddr; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; Loading
drivers/net/wireless/ath/ath10k/hw.c +7 −0 Original line number Diff line number Diff line Loading @@ -284,6 +284,12 @@ struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { .wm_high = &wcn3990_dst_wm_high, }; static struct ath10k_hw_ce_ctrl1_upd wcn3990_ctrl1_upd = { .shift = 19, .mask = 0x00080000, .enable = 0x00000000, }; struct ath10k_hw_ce_regs wcn3990_ce_regs = { .sr_base_addr = 0x00000000, .sr_size_addr = 0x00000008, Loading @@ -305,6 +311,7 @@ struct ath10k_hw_ce_regs wcn3990_ce_regs = { .misc_regs = &wcn3990_misc_reg, .wm_srcr = &wcn3990_wm_src_ring, .wm_dstr = &wcn3990_wm_dst_ring, .upd = &wcn3990_ctrl1_upd, }; struct ath10k_hw_ce_regs_addr_map qcax_src_ring = { Loading