Loading drivers/net/wireless/ath/ath10k/ce.c +237 −8 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading Loading @@ -58,6 +59,74 @@ * the buffer is sent/received. */ static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar, struct ath10k_ce_pipe *ce_state) { u32 ce_id = ce_state->id; u32 addr = 0; switch (ce_id) { case 0: addr = 0x00032000; break; case 3: addr = 0x0003200C; break; case 4: addr = 0x00032010; break; case 5: addr = 0x00032014; break; case 7: addr = 0x0003201C; break; default: ath10k_warn(ar, "invalid CE id: %d", ce_id); break; } return addr; } static inline u32 shadow_dst_wr_ind_addr(struct ath10k *ar, struct ath10k_ce_pipe *ce_state) { u32 ce_id = ce_state->id; u32 addr = 0; switch (ce_id) { case 1: addr = 0x00032034; break; case 2: addr = 0x00032038; break; case 5: addr = 0x00032044; break; case 7: addr = 0x0003204C; break; case 8: addr = 0x00032050; break; case 9: addr = 0x00032054; break; case 10: addr = 0x00032058; break; case 11: addr = 0x0003205C; break; default: ath10k_warn(ar, "invalid CE id: %d", ce_id); break; } return addr; } static inline unsigned int ath10k_set_ring_byte(unsigned int offset, struct ath10k_hw_ce_regs_addr_map *addr_map) Loading Loading @@ -116,11 +185,46 @@ static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_from_ddr(struct ath10k *ar, u32 ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); return ce->vaddr_rri[ce_id] & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { return ath10k_ce_read32(ar, ce_ctrl_addr + struct ath10k_ce *ce = ath10k_ce_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; u32 index; if (ar->hw_params.rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_id); else index = ath10k_ce_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, struct ath10k_ce_pipe *ce_state, unsigned int value) { ath10k_ce_write32(ar, shadow_sr_wr_ind_addr(ar, ce_state), value); } static inline void ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar, struct ath10k_ce_pipe *ce_state, unsigned int value) { ath10k_ce_write32(ar, shadow_dst_wr_ind_addr(ar, ce_state), value); } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, Loading Loading @@ -181,11 +285,31 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, ath10k_set_ring_byte(n, ctrl_regs->dst_ring)); } static inline u32 ath10k_ce_dest_ring_read_index_from_ddr(struct ath10k *ar, u32 ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); return (ce->vaddr_rri[ce_id] >> CE_DDR_DRRI_SHIFT) & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { return ath10k_ce_read32(ar, ce_ctrl_addr + struct ath10k_ce *ce = ath10k_ce_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; u32 index; if (ar->hw_params.rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_dest_ring_read_index_from_ddr(ar, ce_id); else index = ath10k_ce_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 @@ -376,8 +500,14 @@ static int _ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, 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); if (!(flags & CE_SEND_FLAG_GATHER)) { if (ar->hw_params.shadow_reg_support) ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state, write_index); else ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); } src_ring->write_index = write_index; exit: Loading @@ -395,7 +525,7 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state, struct ath10k_ce_ring *src_ring = ce_state->src_ring; struct ce_desc_64 *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; __le32 *addr; Loading @@ -409,6 +539,11 @@ static int _ath10k_ce_send_nolock_64(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); if (ar->hw_params.rri_on_ddr) sw_index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_state->id); else sw_index = src_ring->sw_index; if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) <= 0)) { ret = -ENOSR; Loading Loading @@ -925,6 +1060,9 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, src_ring->hw_index = read_index; } if (ar->hw_params.rri_on_ddr) read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); else read_index = src_ring->hw_index; if (read_index == sw_index) Loading Loading @@ -1251,6 +1389,22 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, return 0; } static int ath10k_ce_alloc_shadow_base(struct ath10k *ar, struct ath10k_ce_ring *src_ring, u32 nentries) { src_ring->shadow_base_unaligned = kcalloc(nentries, sizeof(struct ce_desc), GFP_KERNEL); if (!src_ring->shadow_base_unaligned) return -ENOMEM; src_ring->shadow_base = (struct ce_desc *) PTR_ALIGN(src_ring->shadow_base_unaligned, CE_DESC_RING_ALIGN); return 0; } static struct ath10k_ce_ring * ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) Loading @@ -1258,6 +1412,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, struct ath10k_ce_ring *src_ring; u32 nentries = attr->src_nentries; dma_addr_t base_addr; int ret; nentries = roundup_pow_of_two(nentries); Loading Loading @@ -1294,6 +1449,19 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, ALIGN(src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); if (ar->hw_params.shadow_reg_support) { ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); kfree(src_ring); return ERR_PTR(ret); } } return src_ring; } Loading @@ -1304,6 +1472,7 @@ ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id, struct ath10k_ce_ring *src_ring; u32 nentries = attr->src_nentries; dma_addr_t base_addr; int ret; nentries = roundup_pow_of_two(nentries); Loading Loading @@ -1339,6 +1508,19 @@ ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id, ALIGN(src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); if (ar->hw_params.shadow_reg_support) { ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); kfree(src_ring); return ERR_PTR(ret); } } return src_ring; } Loading Loading @@ -1505,6 +1687,8 @@ static void _ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; if (ce_state->src_ring) { if (ar->hw_params.shadow_reg_support) kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc) + Loading Loading @@ -1534,6 +1718,8 @@ static void _ath10k_ce_free_pipe_64(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; if (ce_state->src_ring) { if (ar->hw_params.shadow_reg_support) kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc_64) + Loading Loading @@ -1702,3 +1888,46 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, return 0; } EXPORT_SYMBOL(ath10k_ce_alloc_pipe); void ath10k_ce_alloc_rri(struct ath10k *ar) { int i; u32 value; u32 ctrl1_regs; u32 ce_base_addr; struct ath10k_ce *ce = ath10k_ce_priv(ar); ce->vaddr_rri = dma_alloc_coherent(ar->dev, (CE_COUNT * sizeof(u32)), &ce->paddr_rri, GFP_KERNEL); if (!ce->vaddr_rri) return; ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_low, lower_32_bits(ce->paddr_rri)); ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_high, (upper_32_bits(ce->paddr_rri) & CE_DESC_FLAGS_GET_MASK)); 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); value = ath10k_ce_read32(ar, ce_base_addr + ctrl1_regs); value |= ar->hw_ce_regs->upd->mask; ath10k_ce_write32(ar, ce_base_addr + ctrl1_regs, value); } memset(ce->vaddr_rri, 0, CE_COUNT * sizeof(u32)); } EXPORT_SYMBOL(ath10k_ce_alloc_rri); void ath10k_ce_free_rri(struct ath10k *ar) { struct ath10k_ce *ce = ath10k_ce_priv(ar); dma_free_coherent(ar->dev, (CE_COUNT * sizeof(u32)), ce->vaddr_rri, ce->paddr_rri); } EXPORT_SYMBOL(ath10k_ce_free_rri); drivers/net/wireless/ath/ath10k/ce.h +14 −0 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading Loading @@ -48,6 +49,9 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_META_DATA_MASK ar->hw_values->ce_desc_meta_data_mask #define CE_DESC_FLAGS_META_DATA_LSB ar->hw_values->ce_desc_meta_data_lsb #define CE_DDR_RRI_MASK GENMASK(15, 0) #define CE_DDR_DRRI_SHIFT 16 struct ce_desc { __le32 addr; __le16 nbytes; Loading Loading @@ -113,6 +117,9 @@ struct ath10k_ce_ring { /* CE address space */ u32 base_addr_ce_space; char *shadow_base_unaligned; struct ce_desc *shadow_base; /* keep last */ void *per_transfer_context[0]; }; Loading Loading @@ -153,6 +160,8 @@ struct ath10k_ce { spinlock_t ce_lock; const struct ath10k_bus_ops *bus_ops; struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; u32 *vaddr_rri; dma_addr_t paddr_rri; }; /*==================Send====================*/ Loading Loading @@ -261,6 +270,8 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar); void ath10k_ce_enable_interrupts(struct ath10k *ar); void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_fw_crash_data *crash_data); void ath10k_ce_alloc_rri(struct ath10k *ar); void ath10k_ce_free_rri(struct ath10k *ar); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ Loading Loading @@ -326,6 +337,9 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; } #define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) (((COPY_ENGINE_BASE_ADDRESS) \ - CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) #define CE_SRC_RING_TO_DESC(baddr, idx) \ (&(((struct ce_desc *)baddr)[idx])) Loading drivers/net/wireless/ath/ath10k/core.c +57 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,39 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA988X_HW_2_0_VERSION, .dev_id = QCA988X_2_0_DEVICE_ID_UBNT, .name = "qca988x hw2.0 ubiquiti", .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .board = QCA988X_HW_2_0_BOARD_DATA_FILE, .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, .num_peers = TARGET_TLV_NUM_PEERS, .ast_skid_limit = 0x10, .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9887_HW_1_0_VERSION, Loading Loading @@ -120,6 +153,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_2_1_VERSION, Loading Loading @@ -149,6 +184,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_2_1_VERSION, Loading Loading @@ -178,6 +215,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_3_0_VERSION, Loading Loading @@ -207,6 +246,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_3_2_VERSION, Loading Loading @@ -239,6 +280,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, Loading Loading @@ -274,6 +317,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9984_HW_1_0_DEV_VERSION, Loading Loading @@ -316,6 +361,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9888_HW_2_0_DEV_VERSION, Loading Loading @@ -355,6 +402,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9377_HW_1_0_DEV_VERSION, Loading Loading @@ -384,6 +433,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, Loading Loading @@ -415,6 +466,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA4019_HW_1_0_DEV_VERSION, Loading Loading @@ -451,6 +504,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = WCN3990_HW_1_0_DEV_VERSION, Loading @@ -472,6 +527,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = true, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, .per_ce_irq = true, .shadow_reg_support = true, .rri_on_ddr = true, }, }; Loading drivers/net/wireless/ath/ath10k/hw.c +7 −2 Original line number Diff line number Diff line Loading @@ -310,6 +310,12 @@ static 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 @@ -320,8 +326,6 @@ struct ath10k_hw_ce_regs wcn3990_ce_regs = { .dst_wr_index_addr = 0x00000040, .current_srri_addr = 0x00000044, .current_drri_addr = 0x00000048, .ddr_addr_for_rri_low = 0x00000004, .ddr_addr_for_rri_high = 0x00000008, .ce_rri_low = 0x0024C004, .ce_rri_high = 0x0024C008, .host_ie_addr = 0x0000002c, Loading @@ -331,6 +335,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, }; const struct ath10k_hw_values wcn3990_values = { Loading drivers/net/wireless/ath/ath10k/hw.h +17 −1 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading @@ -22,6 +23,7 @@ #define ATH10K_FW_DIR "ath10k" #define QCA988X_2_0_DEVICE_ID_UBNT (0x11ac) #define QCA988X_2_0_DEVICE_ID (0x003c) #define QCA6164_2_1_DEVICE_ID (0x0041) #define QCA6174_2_1_DEVICE_ID (0x003e) Loading Loading @@ -336,6 +338,12 @@ struct ath10k_hw_ce_dst_src_wm_regs { struct ath10k_hw_ce_regs_addr_map *wm_low; struct ath10k_hw_ce_regs_addr_map *wm_high; }; struct ath10k_hw_ce_ctrl1_upd { u32 shift; u32 mask; u32 enable; }; struct ath10k_hw_ce_regs { u32 sr_base_addr; u32 sr_size_addr; Loading @@ -358,7 +366,9 @@ struct ath10k_hw_ce_regs { struct ath10k_hw_ce_cmd_halt *cmd_halt; struct ath10k_hw_ce_host_ie *host_ie; struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr; struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; }; struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; struct ath10k_hw_ce_ctrl1_upd *upd; }; struct ath10k_hw_values { u32 rtc_state_val_on; Loading Loading @@ -574,6 +584,12 @@ struct ath10k_hw_params { /* target supporting per ce IRQ */ bool per_ce_irq; /* target supporting shadow register for ce write */ bool shadow_reg_support; /* target supporting retention restore on ddr */ bool rri_on_ddr; }; struct htt_rx_desc; Loading Loading
drivers/net/wireless/ath/ath10k/ce.c +237 −8 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading Loading @@ -58,6 +59,74 @@ * the buffer is sent/received. */ static inline u32 shadow_sr_wr_ind_addr(struct ath10k *ar, struct ath10k_ce_pipe *ce_state) { u32 ce_id = ce_state->id; u32 addr = 0; switch (ce_id) { case 0: addr = 0x00032000; break; case 3: addr = 0x0003200C; break; case 4: addr = 0x00032010; break; case 5: addr = 0x00032014; break; case 7: addr = 0x0003201C; break; default: ath10k_warn(ar, "invalid CE id: %d", ce_id); break; } return addr; } static inline u32 shadow_dst_wr_ind_addr(struct ath10k *ar, struct ath10k_ce_pipe *ce_state) { u32 ce_id = ce_state->id; u32 addr = 0; switch (ce_id) { case 1: addr = 0x00032034; break; case 2: addr = 0x00032038; break; case 5: addr = 0x00032044; break; case 7: addr = 0x0003204C; break; case 8: addr = 0x00032050; break; case 9: addr = 0x00032054; break; case 10: addr = 0x00032058; break; case 11: addr = 0x0003205C; break; default: ath10k_warn(ar, "invalid CE id: %d", ce_id); break; } return addr; } static inline unsigned int ath10k_set_ring_byte(unsigned int offset, struct ath10k_hw_ce_regs_addr_map *addr_map) Loading Loading @@ -116,11 +185,46 @@ static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_from_ddr(struct ath10k *ar, u32 ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); return ce->vaddr_rri[ce_id] & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { return ath10k_ce_read32(ar, ce_ctrl_addr + struct ath10k_ce *ce = ath10k_ce_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; u32 index; if (ar->hw_params.rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_id); else index = ath10k_ce_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, struct ath10k_ce_pipe *ce_state, unsigned int value) { ath10k_ce_write32(ar, shadow_sr_wr_ind_addr(ar, ce_state), value); } static inline void ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar, struct ath10k_ce_pipe *ce_state, unsigned int value) { ath10k_ce_write32(ar, shadow_dst_wr_ind_addr(ar, ce_state), value); } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, Loading Loading @@ -181,11 +285,31 @@ static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, ath10k_set_ring_byte(n, ctrl_regs->dst_ring)); } static inline u32 ath10k_ce_dest_ring_read_index_from_ddr(struct ath10k *ar, u32 ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); return (ce->vaddr_rri[ce_id] >> CE_DDR_DRRI_SHIFT) & CE_DDR_RRI_MASK; } static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { return ath10k_ce_read32(ar, ce_ctrl_addr + struct ath10k_ce *ce = ath10k_ce_priv(ar); u32 ce_id = COPY_ENGINE_ID(ce_ctrl_addr); struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; u32 index; if (ar->hw_params.rri_on_ddr && (ce_state->attr_flags & CE_ATTR_DIS_INTR)) index = ath10k_ce_dest_ring_read_index_from_ddr(ar, ce_id); else index = ath10k_ce_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 @@ -376,8 +500,14 @@ static int _ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, 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); if (!(flags & CE_SEND_FLAG_GATHER)) { if (ar->hw_params.shadow_reg_support) ath10k_ce_shadow_src_ring_write_index_set(ar, ce_state, write_index); else ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); } src_ring->write_index = write_index; exit: Loading @@ -395,7 +525,7 @@ static int _ath10k_ce_send_nolock_64(struct ath10k_ce_pipe *ce_state, struct ath10k_ce_ring *src_ring = ce_state->src_ring; struct ce_desc_64 *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; __le32 *addr; Loading @@ -409,6 +539,11 @@ static int _ath10k_ce_send_nolock_64(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); if (ar->hw_params.rri_on_ddr) sw_index = ath10k_ce_src_ring_read_index_from_ddr(ar, ce_state->id); else sw_index = src_ring->sw_index; if (unlikely(CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) <= 0)) { ret = -ENOSR; Loading Loading @@ -925,6 +1060,9 @@ int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, src_ring->hw_index = read_index; } if (ar->hw_params.rri_on_ddr) read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); else read_index = src_ring->hw_index; if (read_index == sw_index) Loading Loading @@ -1251,6 +1389,22 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, return 0; } static int ath10k_ce_alloc_shadow_base(struct ath10k *ar, struct ath10k_ce_ring *src_ring, u32 nentries) { src_ring->shadow_base_unaligned = kcalloc(nentries, sizeof(struct ce_desc), GFP_KERNEL); if (!src_ring->shadow_base_unaligned) return -ENOMEM; src_ring->shadow_base = (struct ce_desc *) PTR_ALIGN(src_ring->shadow_base_unaligned, CE_DESC_RING_ALIGN); return 0; } static struct ath10k_ce_ring * ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) Loading @@ -1258,6 +1412,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, struct ath10k_ce_ring *src_ring; u32 nentries = attr->src_nentries; dma_addr_t base_addr; int ret; nentries = roundup_pow_of_two(nentries); Loading Loading @@ -1294,6 +1449,19 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, ALIGN(src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); if (ar->hw_params.shadow_reg_support) { ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); kfree(src_ring); return ERR_PTR(ret); } } return src_ring; } Loading @@ -1304,6 +1472,7 @@ ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id, struct ath10k_ce_ring *src_ring; u32 nentries = attr->src_nentries; dma_addr_t base_addr; int ret; nentries = roundup_pow_of_two(nentries); Loading Loading @@ -1339,6 +1508,19 @@ ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id, ALIGN(src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); if (ar->hw_params.shadow_reg_support) { ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); kfree(src_ring); return ERR_PTR(ret); } } return src_ring; } Loading Loading @@ -1505,6 +1687,8 @@ static void _ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; if (ce_state->src_ring) { if (ar->hw_params.shadow_reg_support) kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc) + Loading Loading @@ -1534,6 +1718,8 @@ static void _ath10k_ce_free_pipe_64(struct ath10k *ar, int ce_id) struct ath10k_ce_pipe *ce_state = &ce->ce_states[ce_id]; if (ce_state->src_ring) { if (ar->hw_params.shadow_reg_support) kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc_64) + Loading Loading @@ -1702,3 +1888,46 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, return 0; } EXPORT_SYMBOL(ath10k_ce_alloc_pipe); void ath10k_ce_alloc_rri(struct ath10k *ar) { int i; u32 value; u32 ctrl1_regs; u32 ce_base_addr; struct ath10k_ce *ce = ath10k_ce_priv(ar); ce->vaddr_rri = dma_alloc_coherent(ar->dev, (CE_COUNT * sizeof(u32)), &ce->paddr_rri, GFP_KERNEL); if (!ce->vaddr_rri) return; ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_low, lower_32_bits(ce->paddr_rri)); ath10k_ce_write32(ar, ar->hw_ce_regs->ce_rri_high, (upper_32_bits(ce->paddr_rri) & CE_DESC_FLAGS_GET_MASK)); 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); value = ath10k_ce_read32(ar, ce_base_addr + ctrl1_regs); value |= ar->hw_ce_regs->upd->mask; ath10k_ce_write32(ar, ce_base_addr + ctrl1_regs, value); } memset(ce->vaddr_rri, 0, CE_COUNT * sizeof(u32)); } EXPORT_SYMBOL(ath10k_ce_alloc_rri); void ath10k_ce_free_rri(struct ath10k *ar) { struct ath10k_ce *ce = ath10k_ce_priv(ar); dma_free_coherent(ar->dev, (CE_COUNT * sizeof(u32)), ce->vaddr_rri, ce->paddr_rri); } EXPORT_SYMBOL(ath10k_ce_free_rri);
drivers/net/wireless/ath/ath10k/ce.h +14 −0 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading Loading @@ -48,6 +49,9 @@ struct ath10k_ce_pipe; #define CE_DESC_FLAGS_META_DATA_MASK ar->hw_values->ce_desc_meta_data_mask #define CE_DESC_FLAGS_META_DATA_LSB ar->hw_values->ce_desc_meta_data_lsb #define CE_DDR_RRI_MASK GENMASK(15, 0) #define CE_DDR_DRRI_SHIFT 16 struct ce_desc { __le32 addr; __le16 nbytes; Loading Loading @@ -113,6 +117,9 @@ struct ath10k_ce_ring { /* CE address space */ u32 base_addr_ce_space; char *shadow_base_unaligned; struct ce_desc *shadow_base; /* keep last */ void *per_transfer_context[0]; }; Loading Loading @@ -153,6 +160,8 @@ struct ath10k_ce { spinlock_t ce_lock; const struct ath10k_bus_ops *bus_ops; struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; u32 *vaddr_rri; dma_addr_t paddr_rri; }; /*==================Send====================*/ Loading Loading @@ -261,6 +270,8 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar); void ath10k_ce_enable_interrupts(struct ath10k *ar); void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_fw_crash_data *crash_data); void ath10k_ce_alloc_rri(struct ath10k *ar); void ath10k_ce_free_rri(struct ath10k *ar); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ Loading Loading @@ -326,6 +337,9 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; } #define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) (((COPY_ENGINE_BASE_ADDRESS) \ - CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) #define CE_SRC_RING_TO_DESC(baddr, idx) \ (&(((struct ce_desc *)baddr)[idx])) Loading
drivers/net/wireless/ath/ath10k/core.c +57 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,39 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA988X_HW_2_0_VERSION, .dev_id = QCA988X_2_0_DEVICE_ID_UBNT, .name = "qca988x hw2.0 ubiquiti", .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, .uart_pin = 7, .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL, .otp_exe_param = 0, .channel_counters_freq_hz = 88000, .max_probe_resp_desc_thres = 0, .cal_data_len = 2116, .fw = { .dir = QCA988X_HW_2_0_FW_DIR, .board = QCA988X_HW_2_0_BOARD_DATA_FILE, .board_size = QCA988X_BOARD_DATA_SZ, .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ, }, .hw_ops = &qca988x_ops, .decap_align_bytes = 4, .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, .num_peers = TARGET_TLV_NUM_PEERS, .ast_skid_limit = 0x10, .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9887_HW_1_0_VERSION, Loading Loading @@ -120,6 +153,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_2_1_VERSION, Loading Loading @@ -149,6 +184,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_2_1_VERSION, Loading Loading @@ -178,6 +215,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_3_0_VERSION, Loading Loading @@ -207,6 +246,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA6174_HW_3_2_VERSION, Loading Loading @@ -239,6 +280,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, Loading Loading @@ -274,6 +317,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9984_HW_1_0_DEV_VERSION, Loading Loading @@ -316,6 +361,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9888_HW_2_0_DEV_VERSION, Loading Loading @@ -355,6 +402,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9377_HW_1_0_DEV_VERSION, Loading Loading @@ -384,6 +433,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, Loading Loading @@ -415,6 +466,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = QCA4019_HW_1_0_DEV_VERSION, Loading Loading @@ -451,6 +504,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, }, { .id = WCN3990_HW_1_0_DEV_VERSION, Loading @@ -472,6 +527,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .target_64bit = true, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, .per_ce_irq = true, .shadow_reg_support = true, .rri_on_ddr = true, }, }; Loading
drivers/net/wireless/ath/ath10k/hw.c +7 −2 Original line number Diff line number Diff line Loading @@ -310,6 +310,12 @@ static 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 @@ -320,8 +326,6 @@ struct ath10k_hw_ce_regs wcn3990_ce_regs = { .dst_wr_index_addr = 0x00000040, .current_srri_addr = 0x00000044, .current_drri_addr = 0x00000048, .ddr_addr_for_rri_low = 0x00000004, .ddr_addr_for_rri_high = 0x00000008, .ce_rri_low = 0x0024C004, .ce_rri_high = 0x0024C008, .host_ie_addr = 0x0000002c, Loading @@ -331,6 +335,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, }; const struct ath10k_hw_values wcn3990_values = { Loading
drivers/net/wireless/ath/ath10k/hw.h +17 −1 Original line number Diff line number Diff line /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. * Copyright (c) 2018 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 Loading @@ -22,6 +23,7 @@ #define ATH10K_FW_DIR "ath10k" #define QCA988X_2_0_DEVICE_ID_UBNT (0x11ac) #define QCA988X_2_0_DEVICE_ID (0x003c) #define QCA6164_2_1_DEVICE_ID (0x0041) #define QCA6174_2_1_DEVICE_ID (0x003e) Loading Loading @@ -336,6 +338,12 @@ struct ath10k_hw_ce_dst_src_wm_regs { struct ath10k_hw_ce_regs_addr_map *wm_low; struct ath10k_hw_ce_regs_addr_map *wm_high; }; struct ath10k_hw_ce_ctrl1_upd { u32 shift; u32 mask; u32 enable; }; struct ath10k_hw_ce_regs { u32 sr_base_addr; u32 sr_size_addr; Loading @@ -358,7 +366,9 @@ struct ath10k_hw_ce_regs { struct ath10k_hw_ce_cmd_halt *cmd_halt; struct ath10k_hw_ce_host_ie *host_ie; struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr; struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; }; struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; struct ath10k_hw_ce_ctrl1_upd *upd; }; struct ath10k_hw_values { u32 rtc_state_val_on; Loading Loading @@ -574,6 +584,12 @@ struct ath10k_hw_params { /* target supporting per ce IRQ */ bool per_ce_irq; /* target supporting shadow register for ce write */ bool shadow_reg_support; /* target supporting retention restore on ddr */ bool rri_on_ddr; }; struct htt_rx_desc; Loading