xref: /linux/drivers/net/wireless/ath/wcn36xx/dxe.c (revision 38fd2c202a3d82bc12430bce5789fa2c2a406f71)
1 /*
2  * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* DXE - DMA transfer engine
18  * we have 2 channels(High prio and Low prio) for TX and 2 channels for RX.
19  * through low channels data packets are transfered
20  * through high channels managment packets are transfered
21  */
22 
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24 
25 #include <linux/interrupt.h>
26 #include "wcn36xx.h"
27 #include "txrx.h"
28 
29 void *wcn36xx_dxe_get_next_bd(struct wcn36xx *wcn, bool is_low)
30 {
31 	struct wcn36xx_dxe_ch *ch = is_low ?
32 		&wcn->dxe_tx_l_ch :
33 		&wcn->dxe_tx_h_ch;
34 
35 	return ch->head_blk_ctl->bd_cpu_addr;
36 }
37 
38 static void wcn36xx_dxe_write_register(struct wcn36xx *wcn, int addr, int data)
39 {
40 	wcn36xx_dbg(WCN36XX_DBG_DXE,
41 		    "wcn36xx_dxe_write_register: addr=%x, data=%x\n",
42 		    addr, data);
43 
44 	writel(data, wcn->mmio + addr);
45 }
46 
47 static void wcn36xx_dxe_read_register(struct wcn36xx *wcn, int addr, int *data)
48 {
49 	*data = readl(wcn->mmio + addr);
50 
51 	wcn36xx_dbg(WCN36XX_DBG_DXE,
52 		    "wcn36xx_dxe_read_register: addr=%x, data=%x\n",
53 		    addr, *data);
54 }
55 
56 static void wcn36xx_dxe_free_ctl_block(struct wcn36xx_dxe_ch *ch)
57 {
58 	struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl, *next;
59 	int i;
60 
61 	for (i = 0; i < ch->desc_num && ctl; i++) {
62 		next = ctl->next;
63 		kfree(ctl);
64 		ctl = next;
65 	}
66 }
67 
68 static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
69 {
70 	struct wcn36xx_dxe_ctl *prev_ctl = NULL;
71 	struct wcn36xx_dxe_ctl *cur_ctl = NULL;
72 	int i;
73 
74 	for (i = 0; i < ch->desc_num; i++) {
75 		cur_ctl = kzalloc(sizeof(*cur_ctl), GFP_KERNEL);
76 		if (!cur_ctl)
77 			goto out_fail;
78 
79 		cur_ctl->ctl_blk_order = i;
80 		if (i == 0) {
81 			ch->head_blk_ctl = cur_ctl;
82 			ch->tail_blk_ctl = cur_ctl;
83 		} else if (ch->desc_num - 1 == i) {
84 			prev_ctl->next = cur_ctl;
85 			cur_ctl->next = ch->head_blk_ctl;
86 		} else {
87 			prev_ctl->next = cur_ctl;
88 		}
89 		prev_ctl = cur_ctl;
90 	}
91 
92 	return 0;
93 
94 out_fail:
95 	wcn36xx_dxe_free_ctl_block(ch);
96 	return -ENOMEM;
97 }
98 
99 int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn)
100 {
101 	int ret;
102 
103 	wcn->dxe_tx_l_ch.ch_type = WCN36XX_DXE_CH_TX_L;
104 	wcn->dxe_tx_h_ch.ch_type = WCN36XX_DXE_CH_TX_H;
105 	wcn->dxe_rx_l_ch.ch_type = WCN36XX_DXE_CH_RX_L;
106 	wcn->dxe_rx_h_ch.ch_type = WCN36XX_DXE_CH_RX_H;
107 
108 	wcn->dxe_tx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_L;
109 	wcn->dxe_tx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_TX_H;
110 	wcn->dxe_rx_l_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_L;
111 	wcn->dxe_rx_h_ch.desc_num = WCN36XX_DXE_CH_DESC_NUMB_RX_H;
112 
113 	wcn->dxe_tx_l_ch.dxe_wq =  WCN36XX_DXE_WQ_TX_L;
114 	wcn->dxe_tx_h_ch.dxe_wq =  WCN36XX_DXE_WQ_TX_H;
115 
116 	wcn->dxe_tx_l_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_L_BD;
117 	wcn->dxe_tx_h_ch.ctrl_bd = WCN36XX_DXE_CTRL_TX_H_BD;
118 
119 	wcn->dxe_tx_l_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_L_SKB;
120 	wcn->dxe_tx_h_ch.ctrl_skb = WCN36XX_DXE_CTRL_TX_H_SKB;
121 
122 	wcn->dxe_tx_l_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_L;
123 	wcn->dxe_tx_h_ch.reg_ctrl = WCN36XX_DXE_REG_CTL_TX_H;
124 
125 	wcn->dxe_tx_l_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_L;
126 	wcn->dxe_tx_h_ch.def_ctrl = WCN36XX_DXE_CH_DEFAULT_CTL_TX_H;
127 
128 	/* DXE control block allocation */
129 	ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_l_ch);
130 	if (ret)
131 		goto out_err;
132 	ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_tx_h_ch);
133 	if (ret)
134 		goto out_err;
135 	ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_l_ch);
136 	if (ret)
137 		goto out_err;
138 	ret = wcn36xx_dxe_allocate_ctl_block(&wcn->dxe_rx_h_ch);
139 	if (ret)
140 		goto out_err;
141 
142 	/* Initialize SMSM state  Clear TX Enable RING EMPTY STATE */
143 	ret = wcn->ctrl_ops->smsm_change_state(
144 		WCN36XX_SMSM_WLAN_TX_ENABLE,
145 		WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY);
146 
147 	return 0;
148 
149 out_err:
150 	wcn36xx_err("Failed to allocate DXE control blocks\n");
151 	wcn36xx_dxe_free_ctl_blks(wcn);
152 	return -ENOMEM;
153 }
154 
155 void wcn36xx_dxe_free_ctl_blks(struct wcn36xx *wcn)
156 {
157 	wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_l_ch);
158 	wcn36xx_dxe_free_ctl_block(&wcn->dxe_tx_h_ch);
159 	wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_l_ch);
160 	wcn36xx_dxe_free_ctl_block(&wcn->dxe_rx_h_ch);
161 }
162 
163 static int wcn36xx_dxe_init_descs(struct wcn36xx_dxe_ch *wcn_ch)
164 {
165 	struct wcn36xx_dxe_desc *cur_dxe = NULL;
166 	struct wcn36xx_dxe_desc *prev_dxe = NULL;
167 	struct wcn36xx_dxe_ctl *cur_ctl = NULL;
168 	size_t size;
169 	int i;
170 
171 	size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
172 	wcn_ch->cpu_addr = dma_alloc_coherent(NULL, size, &wcn_ch->dma_addr,
173 					      GFP_KERNEL);
174 	if (!wcn_ch->cpu_addr)
175 		return -ENOMEM;
176 
177 	memset(wcn_ch->cpu_addr, 0, size);
178 
179 	cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr;
180 	cur_ctl = wcn_ch->head_blk_ctl;
181 
182 	for (i = 0; i < wcn_ch->desc_num; i++) {
183 		cur_ctl->desc = cur_dxe;
184 		cur_ctl->desc_phy_addr = wcn_ch->dma_addr +
185 			i * sizeof(struct wcn36xx_dxe_desc);
186 
187 		switch (wcn_ch->ch_type) {
188 		case WCN36XX_DXE_CH_TX_L:
189 			cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_L;
190 			cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_L;
191 			break;
192 		case WCN36XX_DXE_CH_TX_H:
193 			cur_dxe->ctrl = WCN36XX_DXE_CTRL_TX_H;
194 			cur_dxe->dst_addr_l = WCN36XX_DXE_WQ_TX_H;
195 			break;
196 		case WCN36XX_DXE_CH_RX_L:
197 			cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
198 			cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_L;
199 			break;
200 		case WCN36XX_DXE_CH_RX_H:
201 			cur_dxe->ctrl = WCN36XX_DXE_CTRL_RX_H;
202 			cur_dxe->src_addr_l = WCN36XX_DXE_WQ_RX_H;
203 			break;
204 		}
205 		if (0 == i) {
206 			cur_dxe->phy_next_l = 0;
207 		} else if ((0 < i) && (i < wcn_ch->desc_num - 1)) {
208 			prev_dxe->phy_next_l =
209 				cur_ctl->desc_phy_addr;
210 		} else if (i == (wcn_ch->desc_num - 1)) {
211 			prev_dxe->phy_next_l =
212 				cur_ctl->desc_phy_addr;
213 			cur_dxe->phy_next_l =
214 				wcn_ch->head_blk_ctl->desc_phy_addr;
215 		}
216 		cur_ctl = cur_ctl->next;
217 		prev_dxe = cur_dxe;
218 		cur_dxe++;
219 	}
220 
221 	return 0;
222 }
223 
224 static void wcn36xx_dxe_init_tx_bd(struct wcn36xx_dxe_ch *ch,
225 				   struct wcn36xx_dxe_mem_pool *pool)
226 {
227 	int i, chunk_size = pool->chunk_size;
228 	dma_addr_t bd_phy_addr = pool->phy_addr;
229 	void *bd_cpu_addr = pool->virt_addr;
230 	struct wcn36xx_dxe_ctl *cur = ch->head_blk_ctl;
231 
232 	for (i = 0; i < ch->desc_num; i++) {
233 		/* Only every second dxe needs a bd pointer,
234 		   the other will point to the skb data */
235 		if (!(i & 1)) {
236 			cur->bd_phy_addr = bd_phy_addr;
237 			cur->bd_cpu_addr = bd_cpu_addr;
238 			bd_phy_addr += chunk_size;
239 			bd_cpu_addr += chunk_size;
240 		} else {
241 			cur->bd_phy_addr = 0;
242 			cur->bd_cpu_addr = NULL;
243 		}
244 		cur = cur->next;
245 	}
246 }
247 
248 static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
249 {
250 	int reg_data = 0;
251 
252 	wcn36xx_dxe_read_register(wcn,
253 				  WCN36XX_DXE_INT_MASK_REG,
254 				  &reg_data);
255 
256 	reg_data |= wcn_ch;
257 
258 	wcn36xx_dxe_write_register(wcn,
259 				   WCN36XX_DXE_INT_MASK_REG,
260 				   (int)reg_data);
261 	return 0;
262 }
263 
264 static int wcn36xx_dxe_fill_skb(struct wcn36xx_dxe_ctl *ctl)
265 {
266 	struct wcn36xx_dxe_desc *dxe = ctl->desc;
267 	struct sk_buff *skb;
268 
269 	skb = alloc_skb(WCN36XX_PKT_SIZE, GFP_ATOMIC);
270 	if (skb == NULL)
271 		return -ENOMEM;
272 
273 	dxe->dst_addr_l = dma_map_single(NULL,
274 					 skb_tail_pointer(skb),
275 					 WCN36XX_PKT_SIZE,
276 					 DMA_FROM_DEVICE);
277 	ctl->skb = skb;
278 
279 	return 0;
280 }
281 
282 static int wcn36xx_dxe_ch_alloc_skb(struct wcn36xx *wcn,
283 				    struct wcn36xx_dxe_ch *wcn_ch)
284 {
285 	int i;
286 	struct wcn36xx_dxe_ctl *cur_ctl = NULL;
287 
288 	cur_ctl = wcn_ch->head_blk_ctl;
289 
290 	for (i = 0; i < wcn_ch->desc_num; i++) {
291 		wcn36xx_dxe_fill_skb(cur_ctl);
292 		cur_ctl = cur_ctl->next;
293 	}
294 
295 	return 0;
296 }
297 
298 static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn,
299 				     struct wcn36xx_dxe_ch *wcn_ch)
300 {
301 	struct wcn36xx_dxe_ctl *cur = wcn_ch->head_blk_ctl;
302 	int i;
303 
304 	for (i = 0; i < wcn_ch->desc_num; i++) {
305 		kfree_skb(cur->skb);
306 		cur = cur->next;
307 	}
308 }
309 
310 void wcn36xx_dxe_tx_ack_ind(struct wcn36xx *wcn, u32 status)
311 {
312 	struct ieee80211_tx_info *info;
313 	struct sk_buff *skb;
314 	unsigned long flags;
315 
316 	spin_lock_irqsave(&wcn->dxe_lock, flags);
317 	skb = wcn->tx_ack_skb;
318 	wcn->tx_ack_skb = NULL;
319 	spin_unlock_irqrestore(&wcn->dxe_lock, flags);
320 
321 	if (!skb) {
322 		wcn36xx_warn("Spurious TX complete indication\n");
323 		return;
324 	}
325 
326 	info = IEEE80211_SKB_CB(skb);
327 
328 	if (status == 1)
329 		info->flags |= IEEE80211_TX_STAT_ACK;
330 
331 	wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status);
332 
333 	ieee80211_tx_status_irqsafe(wcn->hw, skb);
334 	ieee80211_wake_queues(wcn->hw);
335 }
336 
337 static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
338 {
339 	struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl;
340 	struct ieee80211_tx_info *info;
341 	unsigned long flags;
342 
343 	/*
344 	 * Make at least one loop of do-while because in case ring is
345 	 * completely full head and tail are pointing to the same element
346 	 * and while-do will not make any cycles.
347 	 */
348 	do {
349 		if (ctl->skb) {
350 			dma_unmap_single(NULL, ctl->desc->src_addr_l,
351 					 ctl->skb->len, DMA_TO_DEVICE);
352 			info = IEEE80211_SKB_CB(ctl->skb);
353 			if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
354 				/* Keep frame until TX status comes */
355 				ieee80211_free_txskb(wcn->hw, ctl->skb);
356 			}
357 			spin_lock_irqsave(&ctl->skb_lock, flags);
358 			if (wcn->queues_stopped) {
359 				wcn->queues_stopped = false;
360 				ieee80211_wake_queues(wcn->hw);
361 			}
362 			spin_unlock_irqrestore(&ctl->skb_lock, flags);
363 
364 			ctl->skb = NULL;
365 		}
366 		ctl = ctl->next;
367 	} while (ctl != ch->head_blk_ctl &&
368 	       !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK));
369 
370 	ch->tail_blk_ctl = ctl;
371 }
372 
373 static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
374 {
375 	struct wcn36xx *wcn = (struct wcn36xx *)dev;
376 	int int_src, int_reason;
377 
378 	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
379 
380 	if (int_src & WCN36XX_INT_MASK_CHAN_TX_H) {
381 		wcn36xx_dxe_read_register(wcn,
382 					  WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_H,
383 					  &int_reason);
384 
385 		/* TODO: Check int_reason */
386 
387 		wcn36xx_dxe_write_register(wcn,
388 					   WCN36XX_DXE_0_INT_CLR,
389 					   WCN36XX_INT_MASK_CHAN_TX_H);
390 
391 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
392 					   WCN36XX_INT_MASK_CHAN_TX_H);
393 		wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n");
394 		reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
395 	}
396 
397 	if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
398 		wcn36xx_dxe_read_register(wcn,
399 					  WCN36XX_DXE_CH_STATUS_REG_ADDR_TX_L,
400 					  &int_reason);
401 		/* TODO: Check int_reason */
402 
403 		wcn36xx_dxe_write_register(wcn,
404 					   WCN36XX_DXE_0_INT_CLR,
405 					   WCN36XX_INT_MASK_CHAN_TX_L);
406 
407 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
408 					   WCN36XX_INT_MASK_CHAN_TX_L);
409 		wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n");
410 		reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
411 	}
412 
413 	return IRQ_HANDLED;
414 }
415 
416 static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev)
417 {
418 	struct wcn36xx *wcn = (struct wcn36xx *)dev;
419 
420 	disable_irq_nosync(wcn->rx_irq);
421 	wcn36xx_dxe_rx_frame(wcn);
422 	enable_irq(wcn->rx_irq);
423 	return IRQ_HANDLED;
424 }
425 
426 static int wcn36xx_dxe_request_irqs(struct wcn36xx *wcn)
427 {
428 	int ret;
429 
430 	ret = request_irq(wcn->tx_irq, wcn36xx_irq_tx_complete,
431 			  IRQF_TRIGGER_HIGH, "wcn36xx_tx", wcn);
432 	if (ret) {
433 		wcn36xx_err("failed to alloc tx irq\n");
434 		goto out_err;
435 	}
436 
437 	ret = request_irq(wcn->rx_irq, wcn36xx_irq_rx_ready, IRQF_TRIGGER_HIGH,
438 			  "wcn36xx_rx", wcn);
439 	if (ret) {
440 		wcn36xx_err("failed to alloc rx irq\n");
441 		goto out_txirq;
442 	}
443 
444 	enable_irq_wake(wcn->rx_irq);
445 
446 	return 0;
447 
448 out_txirq:
449 	free_irq(wcn->tx_irq, wcn);
450 out_err:
451 	return ret;
452 
453 }
454 
455 static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
456 				     struct wcn36xx_dxe_ch *ch)
457 {
458 	struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl;
459 	struct wcn36xx_dxe_desc *dxe = ctl->desc;
460 	dma_addr_t  dma_addr;
461 	struct sk_buff *skb;
462 
463 	while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
464 		skb = ctl->skb;
465 		dma_addr = dxe->dst_addr_l;
466 		wcn36xx_dxe_fill_skb(ctl);
467 
468 		switch (ch->ch_type) {
469 		case WCN36XX_DXE_CH_RX_L:
470 			dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
471 			wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR,
472 						   WCN36XX_DXE_INT_CH1_MASK);
473 			break;
474 		case WCN36XX_DXE_CH_RX_H:
475 			dxe->ctrl = WCN36XX_DXE_CTRL_RX_H;
476 			wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR,
477 						   WCN36XX_DXE_INT_CH3_MASK);
478 			break;
479 		default:
480 			wcn36xx_warn("Unknown channel\n");
481 		}
482 
483 		dma_unmap_single(NULL, dma_addr, WCN36XX_PKT_SIZE,
484 				 DMA_FROM_DEVICE);
485 		wcn36xx_rx_skb(wcn, skb);
486 		ctl = ctl->next;
487 		dxe = ctl->desc;
488 	}
489 
490 	ch->head_blk_ctl = ctl;
491 
492 	return 0;
493 }
494 
495 void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn)
496 {
497 	int int_src;
498 
499 	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
500 
501 	/* RX_LOW_PRI */
502 	if (int_src & WCN36XX_DXE_INT_CH1_MASK) {
503 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
504 					   WCN36XX_DXE_INT_CH1_MASK);
505 		wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch));
506 	}
507 
508 	/* RX_HIGH_PRI */
509 	if (int_src & WCN36XX_DXE_INT_CH3_MASK) {
510 		/* Clean up all the INT within this channel */
511 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR,
512 					   WCN36XX_DXE_INT_CH3_MASK);
513 		wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch));
514 	}
515 
516 	if (!int_src)
517 		wcn36xx_warn("No DXE interrupt pending\n");
518 }
519 
520 int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
521 {
522 	size_t s;
523 	void *cpu_addr;
524 
525 	/* Allocate BD headers for MGMT frames */
526 
527 	/* Where this come from ask QC */
528 	wcn->mgmt_mem_pool.chunk_size =	WCN36XX_BD_CHUNK_SIZE +
529 		16 - (WCN36XX_BD_CHUNK_SIZE % 8);
530 
531 	s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
532 	cpu_addr = dma_alloc_coherent(NULL, s, &wcn->mgmt_mem_pool.phy_addr,
533 				      GFP_KERNEL);
534 	if (!cpu_addr)
535 		goto out_err;
536 
537 	wcn->mgmt_mem_pool.virt_addr = cpu_addr;
538 	memset(cpu_addr, 0, s);
539 
540 	/* Allocate BD headers for DATA frames */
541 
542 	/* Where this come from ask QC */
543 	wcn->data_mem_pool.chunk_size = WCN36XX_BD_CHUNK_SIZE +
544 		16 - (WCN36XX_BD_CHUNK_SIZE % 8);
545 
546 	s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
547 	cpu_addr = dma_alloc_coherent(NULL, s, &wcn->data_mem_pool.phy_addr,
548 				      GFP_KERNEL);
549 	if (!cpu_addr)
550 		goto out_err;
551 
552 	wcn->data_mem_pool.virt_addr = cpu_addr;
553 	memset(cpu_addr, 0, s);
554 
555 	return 0;
556 
557 out_err:
558 	wcn36xx_dxe_free_mem_pools(wcn);
559 	wcn36xx_err("Failed to allocate BD mempool\n");
560 	return -ENOMEM;
561 }
562 
563 void wcn36xx_dxe_free_mem_pools(struct wcn36xx *wcn)
564 {
565 	if (wcn->mgmt_mem_pool.virt_addr)
566 		dma_free_coherent(NULL, wcn->mgmt_mem_pool.chunk_size *
567 				  WCN36XX_DXE_CH_DESC_NUMB_TX_H,
568 				  wcn->mgmt_mem_pool.virt_addr,
569 				  wcn->mgmt_mem_pool.phy_addr);
570 
571 	if (wcn->data_mem_pool.virt_addr) {
572 		dma_free_coherent(NULL, wcn->data_mem_pool.chunk_size *
573 				  WCN36XX_DXE_CH_DESC_NUMB_TX_L,
574 				  wcn->data_mem_pool.virt_addr,
575 				  wcn->data_mem_pool.phy_addr);
576 	}
577 }
578 
579 int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn,
580 			 struct wcn36xx_vif *vif_priv,
581 			 struct sk_buff *skb,
582 			 bool is_low)
583 {
584 	struct wcn36xx_dxe_ctl *ctl = NULL;
585 	struct wcn36xx_dxe_desc *desc = NULL;
586 	struct wcn36xx_dxe_ch *ch = NULL;
587 	unsigned long flags;
588 
589 	ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch;
590 
591 	ctl = ch->head_blk_ctl;
592 
593 	spin_lock_irqsave(&ctl->next->skb_lock, flags);
594 
595 	/*
596 	 * If skb is not null that means that we reached the tail of the ring
597 	 * hence ring is full. Stop queues to let mac80211 back off until ring
598 	 * has an empty slot again.
599 	 */
600 	if (NULL != ctl->next->skb) {
601 		ieee80211_stop_queues(wcn->hw);
602 		wcn->queues_stopped = true;
603 		spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
604 		return -EBUSY;
605 	}
606 	spin_unlock_irqrestore(&ctl->next->skb_lock, flags);
607 
608 	ctl->skb = NULL;
609 	desc = ctl->desc;
610 
611 	/* Set source address of the BD we send */
612 	desc->src_addr_l = ctl->bd_phy_addr;
613 
614 	desc->dst_addr_l = ch->dxe_wq;
615 	desc->fr_len = sizeof(struct wcn36xx_tx_bd);
616 	desc->ctrl = ch->ctrl_bd;
617 
618 	wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n");
619 
620 	wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ",
621 			 (char *)desc, sizeof(*desc));
622 	wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP,
623 			 "BD   >>> ", (char *)ctl->bd_cpu_addr,
624 			 sizeof(struct wcn36xx_tx_bd));
625 
626 	/* Set source address of the SKB we send */
627 	ctl = ctl->next;
628 	ctl->skb = skb;
629 	desc = ctl->desc;
630 	if (ctl->bd_cpu_addr) {
631 		wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n");
632 		return -EINVAL;
633 	}
634 
635 	desc->src_addr_l = dma_map_single(NULL,
636 					  ctl->skb->data,
637 					  ctl->skb->len,
638 					  DMA_TO_DEVICE);
639 
640 	desc->dst_addr_l = ch->dxe_wq;
641 	desc->fr_len = ctl->skb->len;
642 
643 	/* set dxe descriptor to VALID */
644 	desc->ctrl = ch->ctrl_skb;
645 
646 	wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ",
647 			 (char *)desc, sizeof(*desc));
648 	wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB   >>> ",
649 			 (char *)ctl->skb->data, ctl->skb->len);
650 
651 	/* Move the head of the ring to the next empty descriptor */
652 	 ch->head_blk_ctl = ctl->next;
653 
654 	/*
655 	 * When connected and trying to send data frame chip can be in sleep
656 	 * mode and writing to the register will not wake up the chip. Instead
657 	 * notify chip about new frame through SMSM bus.
658 	 */
659 	if (is_low &&  vif_priv->pw_state == WCN36XX_BMPS) {
660 		wcn->ctrl_ops->smsm_change_state(
661 				  0,
662 				  WCN36XX_SMSM_WLAN_TX_ENABLE);
663 	} else {
664 		/* indicate End Of Packet and generate interrupt on descriptor
665 		 * done.
666 		 */
667 		wcn36xx_dxe_write_register(wcn,
668 			ch->reg_ctrl, ch->def_ctrl);
669 	}
670 
671 	return 0;
672 }
673 
674 int wcn36xx_dxe_init(struct wcn36xx *wcn)
675 {
676 	int reg_data = 0, ret;
677 
678 	reg_data = WCN36XX_DXE_REG_RESET;
679 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
680 
681 	/* Setting interrupt path */
682 	reg_data = WCN36XX_DXE_CCU_INT;
683 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CCU_INT, reg_data);
684 
685 	/***************************************/
686 	/* Init descriptors for TX LOW channel */
687 	/***************************************/
688 	wcn36xx_dxe_init_descs(&wcn->dxe_tx_l_ch);
689 	wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_l_ch, &wcn->data_mem_pool);
690 
691 	/* Write channel head to a NEXT register */
692 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_L,
693 		wcn->dxe_tx_l_ch.head_blk_ctl->desc_phy_addr);
694 
695 	/* Program DMA destination addr for TX LOW */
696 	wcn36xx_dxe_write_register(wcn,
697 		WCN36XX_DXE_CH_DEST_ADDR_TX_L,
698 		WCN36XX_DXE_WQ_TX_L);
699 
700 	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
701 	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
702 
703 	/***************************************/
704 	/* Init descriptors for TX HIGH channel */
705 	/***************************************/
706 	wcn36xx_dxe_init_descs(&wcn->dxe_tx_h_ch);
707 	wcn36xx_dxe_init_tx_bd(&wcn->dxe_tx_h_ch, &wcn->mgmt_mem_pool);
708 
709 	/* Write channel head to a NEXT register */
710 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_TX_H,
711 		wcn->dxe_tx_h_ch.head_blk_ctl->desc_phy_addr);
712 
713 	/* Program DMA destination addr for TX HIGH */
714 	wcn36xx_dxe_write_register(wcn,
715 		WCN36XX_DXE_CH_DEST_ADDR_TX_H,
716 		WCN36XX_DXE_WQ_TX_H);
717 
718 	wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
719 
720 	/* Enable channel interrupts */
721 	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
722 
723 	/***************************************/
724 	/* Init descriptors for RX LOW channel */
725 	/***************************************/
726 	wcn36xx_dxe_init_descs(&wcn->dxe_rx_l_ch);
727 
728 	/* For RX we need to preallocated buffers */
729 	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
730 
731 	/* Write channel head to a NEXT register */
732 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_L,
733 		wcn->dxe_rx_l_ch.head_blk_ctl->desc_phy_addr);
734 
735 	/* Write DMA source address */
736 	wcn36xx_dxe_write_register(wcn,
737 		WCN36XX_DXE_CH_SRC_ADDR_RX_L,
738 		WCN36XX_DXE_WQ_RX_L);
739 
740 	/* Program preallocated destination address */
741 	wcn36xx_dxe_write_register(wcn,
742 		WCN36XX_DXE_CH_DEST_ADDR_RX_L,
743 		wcn->dxe_rx_l_ch.head_blk_ctl->desc->phy_next_l);
744 
745 	/* Enable default control registers */
746 	wcn36xx_dxe_write_register(wcn,
747 		WCN36XX_DXE_REG_CTL_RX_L,
748 		WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
749 
750 	/* Enable channel interrupts */
751 	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
752 
753 	/***************************************/
754 	/* Init descriptors for RX HIGH channel */
755 	/***************************************/
756 	wcn36xx_dxe_init_descs(&wcn->dxe_rx_h_ch);
757 
758 	/* For RX we need to prealocat buffers */
759 	wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_h_ch);
760 
761 	/* Write chanel head to a NEXT register */
762 	wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_CH_NEXT_DESC_ADDR_RX_H,
763 		wcn->dxe_rx_h_ch.head_blk_ctl->desc_phy_addr);
764 
765 	/* Write DMA source address */
766 	wcn36xx_dxe_write_register(wcn,
767 		WCN36XX_DXE_CH_SRC_ADDR_RX_H,
768 		WCN36XX_DXE_WQ_RX_H);
769 
770 	/* Program preallocated destination address */
771 	wcn36xx_dxe_write_register(wcn,
772 		WCN36XX_DXE_CH_DEST_ADDR_RX_H,
773 		 wcn->dxe_rx_h_ch.head_blk_ctl->desc->phy_next_l);
774 
775 	/* Enable default control registers */
776 	wcn36xx_dxe_write_register(wcn,
777 		WCN36XX_DXE_REG_CTL_RX_H,
778 		WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
779 
780 	/* Enable channel interrupts */
781 	wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
782 
783 	ret = wcn36xx_dxe_request_irqs(wcn);
784 	if (ret < 0)
785 		goto out_err;
786 
787 	return 0;
788 
789 out_err:
790 	return ret;
791 }
792 
793 void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
794 {
795 	free_irq(wcn->tx_irq, wcn);
796 	free_irq(wcn->rx_irq, wcn);
797 
798 	if (wcn->tx_ack_skb) {
799 		ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
800 		wcn->tx_ack_skb = NULL;
801 	}
802 
803 	wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch);
804 	wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch);
805 }
806