Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath10k: fix descriptor size in ce tx completion for WCN3990

When the driver receives the tx completion of the
descriptor over ce, it clears the nbytes configured
for that particular descriptor. WCN3990 uses ce
descriptors with 64-bit address.

Currently during handling the tx completion of the
descriptors, the nbytes are accessed from the descriptors
using ce_desc for 32-bit targets. This will lead to clearing
of memory at incorrect offset if DMA MASK is set to greater
than 32 bits.

Attach different ce tx copy completed handler for targets
using address above 32-bit address.

Tested HW: WCN3990
Tested FW: WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1

Signed-off-by: Rakesh Pillai <pillair@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Rakesh Pillai and committed by
Kalle Valo
02f73d3a bd16693f

+66 -2
+64 -2
drivers/net/wireless/ath/ath10k/ce.c
··· 1066 1066 * Guts of ath10k_ce_completed_send_next. 1067 1067 * The caller takes responsibility for any necessary locking. 1068 1068 */ 1069 - int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, 1070 - void **per_transfer_contextp) 1069 + static int _ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, 1070 + void **per_transfer_contextp) 1071 1071 { 1072 1072 struct ath10k_ce_ring *src_ring = ce_state->src_ring; 1073 1073 u32 ctrl_addr = ce_state->ctrl_addr; ··· 1117 1117 src_ring->sw_index = sw_index; 1118 1118 1119 1119 return 0; 1120 + } 1121 + 1122 + static int _ath10k_ce_completed_send_next_nolock_64(struct ath10k_ce_pipe *ce_state, 1123 + void **per_transfer_contextp) 1124 + { 1125 + struct ath10k_ce_ring *src_ring = ce_state->src_ring; 1126 + u32 ctrl_addr = ce_state->ctrl_addr; 1127 + struct ath10k *ar = ce_state->ar; 1128 + unsigned int nentries_mask = src_ring->nentries_mask; 1129 + unsigned int sw_index = src_ring->sw_index; 1130 + unsigned int read_index; 1131 + struct ce_desc_64 *desc; 1132 + 1133 + if (src_ring->hw_index == sw_index) { 1134 + /* 1135 + * The SW completion index has caught up with the cached 1136 + * version of the HW completion index. 1137 + * Update the cached HW completion index to see whether 1138 + * the SW has really caught up to the HW, or if the cached 1139 + * value of the HW index has become stale. 1140 + */ 1141 + 1142 + read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); 1143 + if (read_index == 0xffffffff) 1144 + return -ENODEV; 1145 + 1146 + read_index &= nentries_mask; 1147 + src_ring->hw_index = read_index; 1148 + } 1149 + 1150 + if (ar->hw_params.rri_on_ddr) 1151 + read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); 1152 + else 1153 + read_index = src_ring->hw_index; 1154 + 1155 + if (read_index == sw_index) 1156 + return -EIO; 1157 + 1158 + if (per_transfer_contextp) 1159 + *per_transfer_contextp = 1160 + src_ring->per_transfer_context[sw_index]; 1161 + 1162 + /* sanity */ 1163 + src_ring->per_transfer_context[sw_index] = NULL; 1164 + desc = CE_SRC_RING_TO_DESC_64(src_ring->base_addr_owner_space, 1165 + sw_index); 1166 + desc->nbytes = 0; 1167 + 1168 + /* Update sw_index */ 1169 + sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); 1170 + src_ring->sw_index = sw_index; 1171 + 1172 + return 0; 1173 + } 1174 + 1175 + int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, 1176 + void **per_transfer_contextp) 1177 + { 1178 + return ce_state->ops->ce_completed_send_next_nolock(ce_state, 1179 + per_transfer_contextp); 1120 1180 } 1121 1181 EXPORT_SYMBOL(ath10k_ce_completed_send_next_nolock); 1122 1182 ··· 1899 1839 .ce_send_nolock = _ath10k_ce_send_nolock, 1900 1840 .ce_set_src_ring_base_addr_hi = NULL, 1901 1841 .ce_set_dest_ring_base_addr_hi = NULL, 1842 + .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock, 1902 1843 }; 1903 1844 1904 1845 static const struct ath10k_ce_ops ce_64_ops = { ··· 1914 1853 .ce_send_nolock = _ath10k_ce_send_nolock_64, 1915 1854 .ce_set_src_ring_base_addr_hi = ath10k_ce_set_src_ring_base_addr_hi, 1916 1855 .ce_set_dest_ring_base_addr_hi = ath10k_ce_set_dest_ring_base_addr_hi, 1856 + .ce_completed_send_next_nolock = _ath10k_ce_completed_send_next_nolock_64, 1917 1857 }; 1918 1858 1919 1859 static void ath10k_ce_set_ops(struct ath10k *ar,
+2
drivers/net/wireless/ath/ath10k/ce.h
··· 329 329 void (*ce_set_dest_ring_base_addr_hi)(struct ath10k *ar, 330 330 u32 ce_ctrl_addr, 331 331 u64 addr); 332 + int (*ce_completed_send_next_nolock)(struct ath10k_ce_pipe *ce_state, 333 + void **per_transfer_contextp); 332 334 }; 333 335 334 336 static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)