net:wireless:Support eswin usb wifi ECR6600U
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_utils.c
1 /**
2  * ecrnx_utils.c
3  *
4  * IPC utility function definitions
5  *
6  * Copyright (C) ESWIN 2015-2020
7  */
8 #include "ecrnx_utils.h"
9 #include "ecrnx_defs.h"
10 #include "ecrnx_rx.h"
11 #include "ecrnx_tx.h"
12 #include "ecrnx_msg_rx.h"
13 #include "ecrnx_debugfs.h"
14 #include "ecrnx_prof.h"
15 #include "ipc_host.h"
16
17 #ifdef CONFIG_ECRNX_ESWIN_SDIO
18 #include "eswin_utils.h"
19 #include "ecrnx_sdio.h"
20 #include "sdio.h"
21 #elif defined(CONFIG_ECRNX_ESWIN_USB)
22 #include "eswin_utils.h"
23 #include "ecrnx_usb.h"
24 #include "usb.h"
25 #endif
26
27
28 /**
29  * ecrnx_ipc_elem_pool_allocs() - Allocate and push to fw a pool of buffer.
30  *
31  * @ecrnx_hw: Main driver structure
32  * @pool: Pool to allocate
33  * @nb: Size of the pool to allocate
34  * @elem_size: SIze of one pool element
35  * @pool_name: Name of the pool
36  * @push: Function to push one pool element to fw
37  *
38  * This function will allocate an array to store the list of element addresses,
39  * a dma pool and @nb element in the dma pool.
40  * Each element is set with '0' and then push to fw using the @push function.
41  * It assumes that pointer inside @ipc parameter are set to NULL at start.
42  *
43  * Return: 0 on success and <0 upon error. If error is returned any allocated
44  * memory is NOT freed and ecrnx_ipc_elem_pool_deallocs() must be called.
45  */
46 #ifndef CONFIG_ECRNX_ESWIN
47 static int ecrnx_ipc_elem_pool_allocs(struct ecrnx_hw *ecrnx_hw,
48                                      struct ecrnx_ipc_elem_pool *pool,
49                                      int nb, size_t elem_size, char *pool_name,
50                                      int (*push)(struct ipc_host_env_tag *,
51                                                  void *, uint32_t))
52 {
53     struct ecrnx_ipc_elem *buf;
54     int i;
55
56     pool->nb = 0;
57
58     /* allocate buf array */
59     pool->buf = kmalloc(nb * sizeof(struct ecrnx_ipc_elem), GFP_KERNEL);
60     if (!pool->buf) {
61         dev_err(ecrnx_hw->dev, "Allocation of buffer array for %s failed\n",
62                 pool_name);
63         return -ENOMEM;
64     }
65
66     /* allocate dma pool */
67     pool->pool = dma_pool_create(pool_name, ecrnx_hw->dev, elem_size,
68                                  cache_line_size(), 0);
69     if (!pool->pool) {
70         dev_err(ecrnx_hw->dev, "Allocation of dma pool %s failed\n",
71                 pool_name);
72         return -ENOMEM;
73     }
74
75     for (i = 0, buf = pool->buf; i < nb; buf++, i++) {
76
77         /* allocate an elem */
78         buf->addr = dma_pool_alloc(pool->pool, GFP_KERNEL, &buf->dma_addr);
79         if (!buf->addr) {
80             dev_err(ecrnx_hw->dev, "Allocation of block %d/%d in %s failed\n",
81                     (i + 1), nb, pool_name);
82             return -ENOMEM;
83         }
84         pool->nb++;
85
86         /* reset the element */
87         memset(buf->addr, 0, elem_size);
88
89         /* push it to FW */
90         push(ecrnx_hw->ipc_env, buf, (uint32_t)buf->dma_addr);
91     }
92
93     return 0;
94 }
95 #endif
96 /**
97  * ecrnx_ipc_elem_pool_deallocs() - Free all memory allocated for a pool
98  *
99  * @pool: Pool to free
100  *
101  * Must be call once after ecrnx_ipc_elem_pool_allocs(), even if it returned
102  * an error
103  */
104 #ifndef CONFIG_ECRNX_ESWIN
105 static void ecrnx_ipc_elem_pool_deallocs(struct ecrnx_ipc_elem_pool *pool)
106 {
107     struct ecrnx_ipc_elem *buf;
108     int i;
109
110     for (i = 0, buf = pool->buf; i < pool->nb ; buf++, i++) {
111         dma_pool_free(pool->pool, buf->addr, buf->dma_addr);
112     }
113     pool->nb = 0;
114
115     if (pool->pool)
116         dma_pool_destroy(pool->pool);
117     pool->pool = NULL;
118
119     if (pool->buf)
120         kfree(pool->buf);
121     pool->buf = NULL;
122 }
123 #endif
124 /**
125  * ecrnx_ipc_elem_var_allocs - Alloc a single ipc buffer and push it to fw
126  *
127  * @ecrnx_hw: Main driver structure
128  * @elem: Element to allocate
129  * @elem_size: Size of the element to allcoate
130  * @dir: DMA direction
131  * @buf: If not NULL, used this buffer instead of allocating a new one. It must
132  * be @elem_size long and be allocated by kmalloc as kfree will be called.
133  * @init: Pointer to initial data to write in buffer before DMA sync. Needed
134  * only if direction is DMA_TO_DEVICE. If set it is assume that its size is
135  * @elem_size.
136  * @push: Function to push the element to fw. May be set to NULL.
137  *
138  * It allocates a buffer (or use the one provided with @buf), initializes it if
139  * @init is set, map buffer for DMA transfer, initializes @elem and push buffer
140  * to FW if @push is seet.
141  *
142  * Return: 0 on success and <0 upon error. If error is returned any allocated
143  * memory has been freed (including @buf if set).
144  */
145 int ecrnx_ipc_elem_var_allocs(struct ecrnx_hw *ecrnx_hw,
146                              struct ecrnx_ipc_elem_var *elem, size_t elem_size,
147                              enum dma_data_direction dir,
148                              void *buf, const void *init,
149                              void (*push)(struct ipc_host_env_tag *, uint32_t))
150 {
151     if (buf) {
152         elem->addr = buf;
153     } else {
154         elem->addr = kmalloc(elem_size, GFP_KERNEL);
155         if (!elem->addr) {
156             dev_err(ecrnx_hw->dev, "Allocation of ipc buffer failed\n");
157             return -ENOMEM;
158         }
159     }
160     elem->size = elem_size;
161
162     if ((dir == DMA_TO_DEVICE) && init) {
163         memcpy(elem->addr, init, elem_size);
164     }
165
166 #ifdef CONFIG_ECRNX_ESWIN
167     elem->dma_addr = (ptr_addr)elem->addr;
168 #else
169     elem->dma_addr = dma_map_single(ecrnx_hw->dev, elem->addr, elem_size, dir);
170     if (dma_mapping_error(ecrnx_hw->dev, elem->dma_addr)) {
171         dev_err(ecrnx_hw->dev, "DMA mapping failed\n");
172         kfree(elem->addr);
173         elem->addr = NULL;
174         return -EIO;
175     }
176
177     if (push)
178         push(ecrnx_hw->ipc_env, elem->dma_addr);
179 #endif
180     return 0;
181 }
182
183 /**
184  * ecrnx_ipc_elem_var_deallocs() - Free memory allocated for a single ipc buffer
185  *
186  * @ecrnx_hw: Main driver structure
187  * @elem: Element to free
188  */
189 void ecrnx_ipc_elem_var_deallocs(struct ecrnx_hw *ecrnx_hw,
190                                 struct ecrnx_ipc_elem_var *elem)
191 {
192     if (!elem->addr)
193         return;
194 #ifndef CONFIG_ECRNX_ESWIN
195     dma_unmap_single(ecrnx_hw->dev, elem->dma_addr, elem->size, DMA_TO_DEVICE);
196 #endif
197     kfree(elem->addr);
198     elem->addr = NULL;
199 }
200
201 /**
202  * ecrnx_ipc_skb_elem_allocs() - Allocate and push a skb buffer for the FW
203  *
204  * @ecrnx_hw: Main driver data
205  * @elem: Pointer to the skb elem that will contain the address of the buffer
206  */
207 int ecrnx_ipc_skb_elem_allocs(struct ecrnx_hw *ecrnx_hw,
208                                  struct ecrnx_ipc_skb_elem *elem, size_t skb_size,
209                                  enum dma_data_direction dir,
210                                  int (*push)(struct ipc_host_env_tag *,
211                                              void *, uint32_t))
212 {
213     elem->skb = dev_alloc_skb(skb_size);
214     if (unlikely(!elem->skb)) {
215         dev_err(ecrnx_hw->dev, "Allocation of ipc skb failed\n");
216         return -ENOMEM;
217     }
218
219     elem->dma_addr = dma_map_single(ecrnx_hw->dev, elem->skb->data, skb_size, dir);
220     if (unlikely(dma_mapping_error(ecrnx_hw->dev, elem->dma_addr))) {
221         dev_err(ecrnx_hw->dev, "DMA mapping failed\n");
222         dev_kfree_skb(elem->skb);
223         elem->skb = NULL;
224         return -EIO;
225     }
226
227     if (push){
228         push(ecrnx_hw->ipc_env, elem, elem->dma_addr);
229     }
230     return 0;
231 }
232
233 /**
234  * ecrnx_ipc_skb_elem_deallocs() - Free a skb buffer allocated for the FW
235  *
236  * @ecrnx_hw: Main driver data
237  * @elem: Pointer to the skb elem that contains the address of the buffer
238  * @skb_size: size of the skb buffer data
239  * @dir: DMA direction
240  */
241 #ifndef CONFIG_ECRNX_ESWIN
242 static void ecrnx_ipc_skb_elem_deallocs(struct ecrnx_hw *ecrnx_hw,
243                                        struct ecrnx_ipc_skb_elem *elem,
244                                        size_t skb_size, enum dma_data_direction dir) 
245 {
246     if (elem->skb) {
247         dma_unmap_single(ecrnx_hw->dev, elem->dma_addr, skb_size, dir);
248         dev_kfree_skb(elem->skb);
249         elem->skb = NULL;
250     }
251 }
252 #endif
253 /**
254  * ecrnx_ipc_unsup_rx_vec_elem_allocs() - Allocate and push an unsupported
255  *                                       RX vector buffer for the FW
256  *
257  * @ecrnx_hw: Main driver data
258  * @elem: Pointer to the skb elem that will contain the address of the buffer
259  */
260 #ifndef CONFIG_ECRNX_ESWIN
261 int ecrnx_ipc_unsup_rx_vec_elem_allocs(struct ecrnx_hw *ecrnx_hw,
262                                       struct ecrnx_ipc_skb_elem *elem)
263 {
264     struct rx_vector_desc *rxdesc;
265
266     if (ecrnx_ipc_skb_elem_allocs(ecrnx_hw, elem,
267             ecrnx_hw->ipc_env->unsuprxvec_bufsz, DMA_FROM_DEVICE, NULL))
268         return -ENOMEM;
269
270     rxdesc = (struct rx_vector_desc *) elem->skb->data;
271     rxdesc->pattern = 0;
272     dma_sync_single_for_device(ecrnx_hw->dev,
273                         elem->dma_addr + offsetof(struct rx_vector_desc, pattern),
274                         sizeof(rxdesc->pattern), DMA_BIDIRECTIONAL);
275
276     ipc_host_unsup_rx_vec_buf_push(ecrnx_hw->ipc_env, elem, (u32) elem->dma_addr);
277
278     return 0;
279 }
280 #endif
281
282 /**
283  * ecrnx_ipc_rxbuf_elems_deallocs() - Free all unsupported rx vector buffer
284  *                                   allocated for the FW
285  *
286  * @ecrnx_hw: Main driver data
287  */
288 #ifndef CONFIG_ECRNX_ESWIN
289 static void ecrnx_ipc_unsup_rx_vec_elems_deallocs(struct ecrnx_hw *ecrnx_hw)
290 {
291     struct ecrnx_ipc_skb_elem *elem;
292     int i, nb = ecrnx_hw->ipc_env->unsuprxvec_bufnb;
293
294     if (!ecrnx_hw->e2aunsuprxvec_elems)
295         return;
296
297     for (i = 0, elem = ecrnx_hw->e2aunsuprxvec_elems; i < nb; i++, elem++) {
298         ecrnx_ipc_skb_elem_deallocs(ecrnx_hw, elem, ecrnx_hw->ipc_env->unsuprxvec_bufsz, DMA_FROM_DEVICE);
299     }
300
301     kfree(ecrnx_hw->e2aunsuprxvec_elems);
302     ecrnx_hw->e2aunsuprxvec_elems = NULL;
303 }
304 #endif
305
306 /**
307 * ecrnx_ipc_unsup_rx_vec_elems_allocs() - Allocate and push all unsupported RX
308 *                                        vector buffer for the FW
309 *
310 * @ecrnx_hw: Main driver data
311 */
312 #ifndef CONFIG_ECRNX_ESWIN
313 static int ecrnx_ipc_unsup_rx_vec_elems_allocs(struct ecrnx_hw *ecrnx_hw)
314 {
315    struct ecrnx_ipc_skb_elem *elem;
316    int i, nb = ecrnx_hw->ipc_env->unsuprxvec_bufnb;
317
318    ecrnx_hw->e2aunsuprxvec_elems = kzalloc(nb * sizeof(struct ecrnx_ipc_skb_elem),
319                                    GFP_KERNEL);
320    if (!ecrnx_hw->e2aunsuprxvec_elems) {
321        dev_err(ecrnx_hw->dev, "Failed to allocate unsuprxvec_elems\n");
322        return -ENOMEM;
323    }
324
325    for (i = 0, elem = ecrnx_hw->e2aunsuprxvec_elems; i < nb; i++, elem++)
326    {
327        if (ecrnx_ipc_unsup_rx_vec_elem_allocs(ecrnx_hw, elem)) {
328            dev_err(ecrnx_hw->dev, "Failed to allocate unsuprxvec buf %d/%d\n",
329                    i + 1, nb);
330            return -ENOMEM;
331        }
332    }
333    return 0;
334 }
335 #endif
336
337 #ifdef CONFIG_ECRNX_SOFTMAC
338 /**
339  * ecrnx_ipc_rxbuf_elem_allocs() - Allocate and push a rx buffer for the FW
340  *
341  * @ecrnx_hw: Main driver data
342  * @elem: Pointer to the skb elem that will contain the address of the buffer
343  */
344 #ifndef CONFIG_ECRNX_ESWIN
345 int ecrnx_ipc_rxbuf_elem_allocs(struct ecrnx_hw *ecrnx_hw,
346                                struct ecrnx_ipc_skb_elem *elem)
347 {
348     struct hw_rxhdr *hw_rxhdr;
349
350     if (ecrnx_ipc_skb_elem_allocs(ecrnx_hw, elem,
351             ecrnx_hw->ipc_env->rx_bufsz, DMA_FROM_DEVICE, NULL))
352         return -ENOMEM;
353
354     hw_rxhdr = (struct hw_rxhdr *) elem->skb->data;
355     hw_rxhdr->pattern = 0;
356     dma_sync_single_for_device(ecrnx_hw->dev,
357             elem->dma_addr + offsetof(struct hw_rxhdr, pattern),
358             sizeof(hw_rxhdr->pattern), DMA_BIDIRECTIONAL);
359
360     ipc_host_rxbuf_push(ecrnx_hw->ipc_env, elem, (u32) elem->dma_addr);
361
362     return 0;
363 }
364 #endif
365
366 /**
367  * ecrnx_ipc_rxbuf_elem_repush() - Reset and repush an already allocated RX buffer
368  *
369  * @ecrnx_hw: Main driver data
370  * @elem: Pointer to the skb elem that contains the address of the buffer
371  */
372 #ifndef CONFIG_ECRNX_ESWIN
373 void ecrnx_ipc_rxbuf_elem_repush(struct ecrnx_hw *ecrnx_hw,
374                                 struct ecrnx_ipc_skb_elem *elem)
375 {
376     struct sk_buff *skb = elem->skb;
377     int pattern_offset = sizeof(struct hw_rxhdr);
378
379     ((struct hw_rxhdr *)skb->data)->pattern = 0;
380     dma_sync_single_for_device(ecrnx_hw->dev, elem->dma_addr,
381                                pattern_offset, DMA_BIDIRECTIONAL);
382     ipc_host_rxbuf_push(ecrnx_hw->ipc_env, elem, (u32)elem->dma_addr);
383 }
384 #endif
385
386 /**
387  * ecrnx_ipc_rxbuf_elems_allocs() - Allocate and push all RX buffer for the FW
388  *
389  * @ecrnx_hw: Main driver data
390  */
391 #ifndef CONFIG_ECRNX_ESWIN
392 static int ecrnx_ipc_rxbuf_elems_allocs(struct ecrnx_hw *ecrnx_hw)
393 {
394     struct ecrnx_ipc_skb_elem *elem;
395     int i, nb = ecrnx_hw->ipc_env->rx_bufnb;
396
397     ecrnx_hw->rxbuf_elems = kzalloc(nb * sizeof(struct ecrnx_ipc_skb_elem),
398                                 GFP_KERNEL);
399     if (!ecrnx_hw->rxbuf_elems) {
400         dev_err(ecrnx_hw->dev, "Failed to allocate rx_elems\n");
401         return -ENOMEM;
402     }
403
404     for (i = 0, elem = ecrnx_hw->rxbuf_elems; i < nb; i++, elem++) {
405         if (ecrnx_ipc_rxbuf_elem_allocs(ecrnx_hw, elem)) {
406             dev_err(ecrnx_hw->dev, "Failed to allocate rx buf %d/%d\n",
407                     i + 1, nb);
408             return -ENOMEM;
409         }
410     }
411
412     return 0;
413 }
414 #endif
415
416 /**
417  * ecrnx_ipc_rxbuf_elems_deallocs() - Free all RX buffer allocated for the FW
418  *
419  * @ecrnx_hw: Main driver data
420  */
421 #ifndef CONFIG_ECRNX_ESWIN
422 static void ecrnx_ipc_rxbuf_elems_deallocs(struct ecrnx_hw *ecrnx_hw)
423 {
424     struct ecrnx_ipc_skb_elem *elem;
425     int i, nb = ecrnx_hw->ipc_env->rx_bufnb;
426
427     if (!ecrnx_hw->rxbuf_elems)
428         return;
429
430     for (i = 0, elem = ecrnx_hw->rxbuf_elems; i < nb; i++, elem++) {
431         ecrnx_ipc_skb_elem_deallocs(ecrnx_hw, elem, ecrnx_hw->ipc_env->rx_bufsz, DMA_FROM_DEVICE);
432     }
433
434     kfree(ecrnx_hw->rxbuf_elems);
435     ecrnx_hw->rxbuf_elems = NULL;   
436 }
437 #endif 
438
439 #else /* ! CONFIG_ECRNX_SOFTMAC */
440
441 /**
442  * ecrnx_ipc_rxdesc_elem_repush() - Repush a rxdesc to FW
443  *
444  * @ecrnx_hw: Main driver data
445  * @elem: Rx desc to repush
446  *
447  * Once rx buffer has been received, the rxdesc used by FW to upload this
448  * buffer can be re-used for another rx buffer.
449  */
450 #ifndef CONFIG_ECRNX_ESWIN
451 void ecrnx_ipc_rxdesc_elem_repush(struct ecrnx_hw *ecrnx_hw,
452                                  struct ecrnx_ipc_elem *elem)
453 {
454     struct rxdesc_tag *rxdesc = elem->addr;
455     rxdesc->status = 0;
456     dma_sync_single_for_device(ecrnx_hw->dev, elem->dma_addr,
457                                sizeof(struct rxdesc_tag), DMA_BIDIRECTIONAL);
458     ipc_host_rxdesc_push(ecrnx_hw->ipc_env, elem, (u32)elem->dma_addr);
459 }
460 #endif
461 /**
462  * ecrnx_ipc_rxbuf_elem_allocs() - Allocate and push a RX buffer for the FW
463  *
464  * @ecrnx_hw: Main driver data
465  */
466 #ifndef CONFIG_ECRNX_ESWIN
467 int ecrnx_ipc_rxbuf_elem_allocs(struct ecrnx_hw *ecrnx_hw)
468 {
469     struct sk_buff *skb;
470     struct hw_rxhdr *hw_rxhdr;
471     dma_addr_t dma_addr;
472     int size = ecrnx_hw->ipc_env->rx_bufsz;
473     int nb, idx;
474
475     skb = dev_alloc_skb(size);
476     if (unlikely(!skb)) {
477         dev_err(ecrnx_hw->dev, "Failed to allocate rx buffer\n");
478         return -ENOMEM;
479     }
480
481     dma_addr = dma_map_single(ecrnx_hw->dev, skb->data, size, DMA_FROM_DEVICE);
482
483     if (unlikely(dma_mapping_error(ecrnx_hw->dev, dma_addr))) {
484         dev_err(ecrnx_hw->dev, "Failed to map rx buffer\n");
485         goto err_skb;
486     }
487
488     hw_rxhdr = (struct hw_rxhdr *)skb->data;
489     hw_rxhdr->pattern = 0;
490     dma_sync_single_for_device(ecrnx_hw->dev,
491                                dma_addr + offsetof(struct hw_rxhdr, pattern),
492                                sizeof(hw_rxhdr->pattern), DMA_BIDIRECTIONAL);
493
494     /* Find first free slot */
495     nb = 0;
496     idx = ecrnx_hw->rxbuf_elems.idx;
497     while (ecrnx_hw->rxbuf_elems.skb[idx] && nb < ECRNX_RXBUFF_MAX) {
498         idx = ( idx + 1 ) % ECRNX_RXBUFF_MAX;
499         nb++;
500     }
501
502     if (WARN((nb == ECRNX_RXBUFF_MAX), "No more free space for rxbuff")) {
503         goto err_dma;
504     }
505
506     ecrnx_hw->rxbuf_elems.skb[idx] = skb;
507
508     /* Save info in skb control buffer  */
509     ECRNX_RXBUFF_DMA_ADDR_SET(skb, dma_addr);
510     ECRNX_RXBUFF_PATTERN_SET(skb, ecrnx_rxbuff_pattern);
511     ECRNX_RXBUFF_IDX_SET(skb, idx);
512
513     /* Push buffer to FW */
514     ipc_host_rxbuf_push(ecrnx_hw->ipc_env, ECRNX_RXBUFF_IDX_TO_HOSTID(idx),
515                         dma_addr);
516
517     /* Save idx so that on next push the free slot will be found quicker */
518     ecrnx_hw->rxbuf_elems.idx = ( idx + 1 ) % ECRNX_RXBUFF_MAX;
519
520     return 0;
521
522   err_dma:
523     dma_unmap_single(ecrnx_hw->dev, dma_addr, size, DMA_FROM_DEVICE);
524   err_skb:
525     dev_kfree_skb(skb);
526     return -ENOMEM;
527
528     return 0;
529 }
530 #endif
531
532 /**
533  * ecrnx_ipc_rxbuf_elem_repush() - Repush a rxbuf to FW
534  *
535  * @ecrnx_hw: Main driver data
536  * @skb: Skb to repush
537  *
538  * In case a skb is not forwarded to upper layer it can be re-used.
539  * It is assumed that @skb has been verified before calling this function and
540  * that it is a valid rx buffer
541  * (i.e. skb == ecrnx_hw->rxbuf_elems.skb[ECRNX_RXBUFF_IDX_GET(skb)])
542  */
543 #ifndef CONFIG_ECRNX_ESWIN
544 void ecrnx_ipc_rxbuf_elem_repush(struct ecrnx_hw *ecrnx_hw,
545                                 struct sk_buff *skb)
546 {
547     dma_addr_t dma_addr;
548     struct hw_rxhdr *hw_rxhdr = (struct hw_rxhdr *)skb->data;
549     int idx;
550
551     /* reset pattern */
552     hw_rxhdr->pattern = 0;
553     dma_addr = ECRNX_RXBUFF_DMA_ADDR_GET(skb);
554     dma_sync_single_for_device(ecrnx_hw->dev,
555                                dma_addr + offsetof(struct hw_rxhdr, pattern),
556                                sizeof(hw_rxhdr->pattern), DMA_BIDIRECTIONAL);
557
558     /* re-push buffer to FW */
559     idx = ECRNX_RXBUFF_IDX_GET(skb);
560  
561    ipc_host_rxbuf_push(ecrnx_hw->ipc_env, ECRNX_RXBUFF_IDX_TO_HOSTID(idx),
562                        dma_addr);
563 }
564 #endif
565
566 /**
567  * ecrnx_ipc_rxbuf_elems_allocs() - Allocate and push all RX buffer for the FW
568  *
569  * @ecrnx_hw: Main driver data
570  */
571 #ifndef CONFIG_ECRNX_ESWIN
572 static int ecrnx_ipc_rxbuf_elems_allocs(struct ecrnx_hw *ecrnx_hw)
573 {
574     //int i, nb = ecrnx_hw->ipc_env->rx_bufnb;
575     int i, nb = 0;
576
577     for (i = 0; i < ECRNX_RXBUFF_MAX; i++) {
578         ecrnx_hw->rxbuf_elems.skb[i] = NULL;
579     }
580     ecrnx_hw->rxbuf_elems.idx = 0;
581
582     for (i = 0; i < nb; i++) {
583         if (ecrnx_ipc_rxbuf_elem_allocs(ecrnx_hw)) {
584             dev_err(ecrnx_hw->dev, "Failed to allocate rx buf %d/%d\n",
585                     i + 1, nb);
586             return -ENOMEM;
587         }
588     }
589     return 0;
590 }
591 #endif
592
593 /**
594  * ecrnx_ipc_rxbuf_elems_deallocs() - Free all RX buffer allocated for the FW
595  *
596  * @ecrnx_hw: Main driver data
597  */
598 #ifndef CONFIG_ECRNX_ESWIN
599 static void ecrnx_ipc_rxbuf_elems_deallocs(struct ecrnx_hw *ecrnx_hw)
600 {
601     struct sk_buff *skb;
602     int i;
603
604     for (i = 0; i < ECRNX_RXBUFF_MAX; i++) {
605         if (ecrnx_hw->rxbuf_elems.skb[i]) {
606             skb = ecrnx_hw->rxbuf_elems.skb[i];
607             dma_unmap_single(ecrnx_hw->dev, ECRNX_RXBUFF_DMA_ADDR_GET(skb),
608                              ecrnx_hw->ipc_env->rx_bufsz, DMA_FROM_DEVICE);
609             dev_kfree_skb(skb);
610             ecrnx_hw->rxbuf_elems.skb[i] = NULL;
611         }
612     }   
613 }
614 #endif
615
616 /**
617  * ecrnx_ipc_rxbuf_elem_pull() - Extract a skb from local table
618  *
619  * @ecrnx_hw: Main driver data
620  * @skb: SKb to extract for table
621  *
622  * After checking that skb is actually a pointer of local table, extract it
623  * from the table.
624  * When buffer is removed, DMA mapping is remove which has the effect to
625  * synchronize the buffer for the cpu.
626  * To be called before passing skb to upper layer.
627  */
628 #ifndef CONFIG_ECRNX_ESWIN
629 void ecrnx_ipc_rxbuf_elem_pull(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
630 {
631     unsigned int idx = ECRNX_RXBUFF_IDX_GET(skb);
632
633     if (ECRNX_RXBUFF_VALID_IDX(idx) && (ecrnx_hw->rxbuf_elems.skb[idx] == skb)) {
634         dma_addr_t dma_addr = ECRNX_RXBUFF_DMA_ADDR_GET(skb);
635         ecrnx_hw->rxbuf_elems.skb[idx] = NULL;
636         dma_unmap_single(ecrnx_hw->dev, dma_addr,
637                          ecrnx_hw->ipc_env->rx_bufsz, DMA_FROM_DEVICE);
638     } else {
639         WARN(1, "Incorrect rxbuff idx skb=%p table[%u]=%p", skb, idx,
640              idx < ECRNX_RXBUFF_MAX ? ecrnx_hw->rxbuf_elems.skb[idx] : NULL);
641     }
642
643     /* Reset the pattern and idx */
644     ECRNX_RXBUFF_PATTERN_SET(skb, 0);
645     ECRNX_RXBUFF_IDX_SET(skb, ECRNX_RXBUFF_MAX);
646 }
647 #endif
648
649 /**
650  * ecrnx_ipc_rxbuf_elem_sync() - Sync part of a RX buffer
651  *
652  * @ecrnx_hw: Main driver data
653  * @skb: SKb to sync
654  * @len: Len to sync
655  *
656  * After checking that skb is actually a pointer of local table, sync @p len
657  * bytes of the buffer for CPU. Buffer is not removed from the table
658  */
659 #ifndef CONFIG_ECRNX_ESWIN
660 void ecrnx_ipc_rxbuf_elem_sync(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb,
661                               int len)
662 {
663     unsigned int idx = ECRNX_RXBUFF_IDX_GET(skb);
664
665     if (ECRNX_RXBUFF_VALID_IDX(idx) && (ecrnx_hw->rxbuf_elems.skb[idx] == skb)) {
666         dma_addr_t dma_addr = ECRNX_RXBUFF_DMA_ADDR_GET(skb);
667         dma_sync_single_for_cpu(ecrnx_hw->dev, dma_addr, len, DMA_FROM_DEVICE);
668     } else {
669         WARN(1, "Incorrect rxbuff idx skb=%p table[%u]=%p", skb, idx,
670              idx < ECRNX_RXBUFF_MAX ? ecrnx_hw->rxbuf_elems.skb[idx] : NULL);
671     }
672 }
673 #endif
674 #endif /* ! CONFIG_ECRNX_SOFTMAC */
675
676 /**
677  * ecrnx_elems_deallocs() - Deallocate IPC storage elements.
678  * @ecrnx_hw: Main driver data
679  *
680  * This function deallocates all the elements required for communications with
681  * LMAC, such as Rx Data elements, MSGs elements, ...
682  * This function should be called in correspondence with the allocation function.
683  */
684 #ifndef CONFIG_ECRNX_ESWIN
685 static void ecrnx_elems_deallocs(struct ecrnx_hw *ecrnx_hw)
686 {
687     ecrnx_ipc_rxbuf_elems_deallocs(ecrnx_hw);
688     ecrnx_ipc_unsup_rx_vec_elems_deallocs(ecrnx_hw);
689 #ifdef CONFIG_ECRNX_FULLMAC
690     ecrnx_ipc_elem_pool_deallocs(&ecrnx_hw->e2arxdesc_pool);
691 #endif
692     ecrnx_ipc_elem_pool_deallocs(&ecrnx_hw->e2amsgs_pool);
693     ecrnx_ipc_elem_pool_deallocs(&ecrnx_hw->dbgmsgs_pool);
694     ecrnx_ipc_elem_pool_deallocs(&ecrnx_hw->e2aradars_pool);
695     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &ecrnx_hw->pattern_elem);
696     ecrnx_ipc_elem_var_deallocs(ecrnx_hw, &ecrnx_hw->dbgdump_elem.buf);   
697 }
698 #endif
699
700 /**
701  * ecrnx_elems_allocs() - Allocate IPC storage elements.
702  * @ecrnx_hw: Main driver data
703  *
704  * This function allocates all the elements required for communications with
705  * LMAC, such as Rx Data elements, MSGs elements, ...
706  * This function should be called in correspondence with the deallocation function.
707  */
708 static int ecrnx_elems_allocs(struct ecrnx_hw *ecrnx_hw)
709 {
710     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
711
712 #ifndef CONFIG_ECRNX_ESWIN
713     if (dma_set_coherent_mask(ecrnx_hw->dev, DMA_BIT_MASK(32)))
714         goto err_alloc;
715     if (ecrnx_ipc_elem_pool_allocs(ecrnx_hw, &ecrnx_hw->e2amsgs_pool,
716                                   ecrnx_hw->ipc_env->ipc_e2amsg_bufnb,
717                                   ecrnx_hw->ipc_env->ipc_e2amsg_bufsz,
718                                   "ecrnx_ipc_e2amsgs_pool",
719                                   ipc_host_msgbuf_push))
720         goto err_alloc;
721
722     if (ecrnx_ipc_elem_pool_allocs(ecrnx_hw, &ecrnx_hw->dbgmsgs_pool,
723                                   ecrnx_hw->ipc_env->ipc_dbg_bufnb,
724                                   ecrnx_hw->ipc_env->ipc_dbg_bufsz,
725                                   "ecrnx_ipc_dbgmsgs_pool",
726                                   ipc_host_dbgbuf_push))
727         goto err_alloc;
728
729     if (ecrnx_ipc_elem_pool_allocs(ecrnx_hw, &ecrnx_hw->e2aradars_pool,
730                                   ecrnx_hw->ipc_env->radar_bufnb,
731                                   ecrnx_hw->ipc_env->radar_bufsz,
732                                   "ecrnx_ipc_e2aradars_pool",
733                                   ipc_host_radarbuf_push))
734         goto err_alloc;
735
736     if (ecrnx_ipc_unsup_rx_vec_elems_allocs(ecrnx_hw))
737     #error 1111
738         goto err_alloc;
739
740     if (ecrnx_ipc_elem_var_allocs(ecrnx_hw, &ecrnx_hw->pattern_elem,
741                                  sizeof(u32), DMA_TO_DEVICE,
742                                  NULL, &ecrnx_rxbuff_pattern,
743                                  ipc_host_patt_addr_push))
744         goto err_alloc;
745
746     if (ecrnx_ipc_elem_var_allocs(ecrnx_hw, &ecrnx_hw->dbgdump_elem.buf,
747                                  sizeof(struct dbg_debug_dump_tag),
748                                  DMA_FROM_DEVICE, NULL, NULL,
749                                  ipc_host_dbginfobuf_push))
750         goto err_alloc;
751
752     /*
753      * Note that the RX buffers are no longer allocated here as their size depends on the
754      * FW configuration, which is not available at that time.
755      * They will be allocated when checking the parameter compatibility between the driver
756      * and the underlying components (i.e. during the ecrnx_handle_dynparams() execution)
757      */
758
759 #ifdef CONFIG_ECRNX_FULLMAC
760     if (ecrnx_ipc_elem_pool_allocs(ecrnx_hw, &ecrnx_hw->e2arxdesc_pool,
761                                   ecrnx_hw->ipc_env->rxdesc_nb,
762                                   sizeof(struct rxdesc_tag),
763                                   "ecrnx_ipc_e2arxdesc_pool",
764                                   ipc_host_rxdesc_push))
765         goto err_alloc;
766
767 #endif /* CONFIG_ECRNX_FULLMAC */
768
769     return 0;
770
771 err_alloc:
772     ecrnx_elems_deallocs(ecrnx_hw);
773     return -ENOMEM;
774 #else
775     return 0;
776 #endif
777 }
778
779 /**
780  * ecrnx_ipc_msg_push() - Push a msg to IPC queue
781  *
782  * @ecrnx_hw: Main driver data
783  * @msg_buf: Pointer to message
784  * @len: Size, in bytes, of message
785  */
786 void ecrnx_ipc_msg_push(struct ecrnx_hw *ecrnx_hw, void *msg_buf, uint16_t len)
787 {
788     ecrnx_hw->msg_tx++;
789     ipc_host_msg_push(ecrnx_hw->ipc_env, msg_buf, len);
790 }
791
792 /**
793  * ecrnx_ipc_txdesc_push() - Push a txdesc to FW
794  *
795  * @ecrnx_hw: Main driver data
796  * @tx_desc: Pointer on &struct txdesc_api to push to FW
797  * @hostid: Pointer save in ipc env to retrieve tx buffer upon confirmation.
798  * @hw_queue: Hw queue to push txdesc to
799  * @user: User position to push the txdesc to. It must be set to 0 if  MU-MIMMO
800  * is not used.
801  */
802 void ecrnx_ipc_txdesc_push(struct ecrnx_hw *ecrnx_hw, void *tx_desc,
803                           void *hostid, int hw_queue, int user)
804 {
805
806 #if !defined(CONFIG_ECRNX_ESWIN_SDIO) && !defined(CONFIG_ECRNX_ESWIN_USB)
807     volatile struct txdesc_host *txdesc_host;
808     u32 *src, *dst;
809     int i;
810
811     txdesc_host = ipc_host_txdesc_get(ecrnx_hw->ipc_env, hw_queue, user);
812     BUG_ON(!txdesc_host);
813
814     dst = (typeof(dst))&txdesc_host->api;
815     src = (typeof(src))tx_desc;
816     for (i = 0; i < sizeof(txdesc_host->api) / sizeof(*src); i++)
817         *dst++ = *src++;
818
819     wmb(); /* vs desc */
820
821         ipc_host_txdesc_push(ecrnx_hw->ipc_env, hw_queue, user, hostid);
822 #else
823     ecrnx_frame_send(ecrnx_hw, tx_desc, hostid, hw_queue, user);
824 #endif
825 }
826
827 /**
828  * ecrnx_ipc_fw_trace_desc_get() - Return pointer to the start of trace
829  * description in IPC environment
830  *
831  * @ecrnx_hw: Main driver data
832  */
833 void *ecrnx_ipc_fw_trace_desc_get(struct ecrnx_hw *ecrnx_hw)
834 {
835 #ifndef CONFIG_ECRNX_ESWIN
836     return (void *)&(ecrnx_hw->ipc_env->shared->trace_pattern);
837 #else
838     return NULL;
839 #endif
840 }
841
842 #ifndef CONFIG_ECRNX_ESWIN
843 /**
844  * ecrnx_ipc_sta_buffer_init - Initialize counter of bufferred data for a given sta
845  *
846  * @ecrnx_hw: Main driver data
847  * @sta_idx: Index of the station to initialize
848  */
849 void ecrnx_ipc_sta_buffer_init(struct ecrnx_hw *ecrnx_hw, int sta_idx)
850 {
851     int i;
852     volatile u32_l *buffered;
853
854     if (sta_idx >= NX_REMOTE_STA_MAX)
855         return;
856
857     buffered = ecrnx_hw->ipc_env->shared->buffered[sta_idx];
858
859     for (i = 0; i < TID_MAX; i++) {
860         *buffered++ = 0;
861     }
862 }
863 #endif
864 /**
865  * ecrnx_ipc_sta_buffer - Update counter of bufferred data for a given sta
866  *
867  * @ecrnx_hw: Main driver data
868  * @sta: Managed station
869  * @tid: TID on which data has been added or removed
870  * @size: Size of data to add (or remove if < 0) to STA buffer.
871  */
872 void ecrnx_ipc_sta_buffer(struct ecrnx_hw *ecrnx_hw, struct ecrnx_sta *sta, int tid, int size)
873 {
874 #ifndef CONFIG_ECRNX_ESWIN
875     u32_l *buffered;
876
877     if (!sta)
878         return;
879
880     if ((sta->sta_idx >= NX_REMOTE_STA_MAX) || (tid >= TID_MAX))
881         return;
882
883     buffered = &ecrnx_hw->ipc_env->shared->buffered[sta->sta_idx][tid];
884
885     if (size < 0) {
886         size = -size;
887         if (*buffered < size)
888             *buffered = 0;
889         else
890             *buffered -= size;
891     } else {
892         // no test on overflow
893         *buffered += size;
894     }
895 #endif
896 }
897
898 /**
899  * ecrnx_msgind() - IRQ handler callback for %IPC_IRQ_E2A_MSG
900  *
901  * @pthis: Pointer to main driver data
902  * @hostid: Pointer to IPC elem from e2amsgs_pool
903  */
904 static u8 ecrnx_msgind(void *pthis, void *hostid)
905 {
906     struct ecrnx_hw *ecrnx_hw = pthis;
907         u8 ret = 0;
908 #ifndef CONFIG_ECRNX_ESWIN
909     struct ecrnx_ipc_elem *elem = hostid;
910     struct ipc_e2a_msg *msg = elem->addr;
911
912     REG_SW_SET_PROFILING(ecrnx_hw, SW_PROF_MSGIND);
913
914     /* Look for pattern which means that this hostbuf has been used for a MSG */
915     if (msg->pattern != IPC_MSGE2A_VALID_PATTERN) {
916         ret = -1;
917         goto msg_no_push;
918     }
919 #else
920     struct ipc_e2a_msg *msg = NULL;
921
922     ecrnx_hw->msg_rx++;
923     ECRNX_DBG("%s enter 0x%x, 0x%x!!\n", __func__, pthis, hostid);
924     if(!pthis || !hostid){
925         ECRNX_ERR(" %s input param error!! \n", __func__);
926         return ret;
927     }
928     msg = hostid;
929 #endif
930     /* Relay further actions to the msg parser */
931     ecrnx_rx_handle_msg(ecrnx_hw, msg);
932     
933 #ifndef CONFIG_ECRNX_ESWIN
934     /* Reset the msg element and re-use it */
935     msg->pattern = 0;
936     wmb();
937
938     /* Push back the buffer to the LMAC */
939     ipc_host_msgbuf_push(ecrnx_hw->ipc_env, elem, elem->dma_addr);
940
941 msg_no_push:
942     REG_SW_CLEAR_PROFILING(ecrnx_hw, SW_PROF_MSGIND);
943 #endif
944     ECRNX_DBG("%s exit!!", __func__);
945     return ret;
946 }
947
948 /**
949  * ecrnx_msgackind() - IRQ handler callback for %IPC_IRQ_E2A_MSG_ACK
950  *
951  * @pthis: Pointer to main driver data
952  * @hostid: Pointer to command acknoledged
953  */
954 static u8 ecrnx_msgackind(void *pthis, void *hostid)
955 {
956     struct ecrnx_hw *ecrnx_hw = (struct ecrnx_hw *)pthis;
957
958     ecrnx_hw->msg_tx_done++;
959     ecrnx_hw->cmd_mgr.llind(&ecrnx_hw->cmd_mgr, (struct ecrnx_cmd *)hostid);
960     return -1;
961 }
962
963 /**
964  * ecrnx_radarind() - IRQ handler callback for %IPC_IRQ_E2A_RADAR
965  *
966  * @pthis: Pointer to main driver data
967  * @hostid: Pointer to IPC elem from e2aradars_pool
968  */
969 static u8 ecrnx_radarind(void *pthis, void *hostid)
970 {
971 #ifdef CONFIG_ECRNX_RADAR
972     struct ecrnx_hw *ecrnx_hw = pthis;
973     struct ecrnx_ipc_elem *elem = hostid;
974     struct radar_pulse_array_desc *pulses = elem->addr;
975     u8 ret = 0;
976     int i;
977
978     /* Look for pulse count meaning that this hostbuf contains RADAR pulses */
979     if (pulses->cnt == 0) {
980         ret = -1;
981         goto radar_no_push;
982     }
983
984     if (ecrnx_radar_detection_is_enable(&ecrnx_hw->radar, pulses->idx)) {
985         /* Save the received pulses only if radar detection is enabled */
986         for (i = 0; i < pulses->cnt; i++) {
987             struct ecrnx_radar_pulses *p = &ecrnx_hw->radar.pulses[pulses->idx];
988
989             p->buffer[p->index] = pulses->pulse[i];
990             p->index = (p->index + 1) % ECRNX_RADAR_PULSE_MAX;
991             if (p->count < ECRNX_RADAR_PULSE_MAX)
992                 p->count++;
993         }
994
995         /* Defer pulse processing in separate work */
996         if (! work_pending(&ecrnx_hw->radar.detection_work))
997             schedule_work(&ecrnx_hw->radar.detection_work);
998     }
999
1000     /* Reset the radar element and re-use it */
1001     pulses->cnt = 0;
1002 #ifndef CONFIG_ECRNX_ESWIN
1003     wmb();
1004
1005     /* Push back the buffer to the LMAC */
1006     ipc_host_radarbuf_push(ecrnx_hw->ipc_env, elem, (u32)elem->dma_addr);
1007 #endif
1008 radar_no_push:
1009     return ret;
1010 #else
1011     return -1;
1012 #endif
1013 }
1014
1015 /**
1016  * ecrnx_prim_tbtt_ind() - IRQ handler callback for %IPC_IRQ_E2A_TBTT_PRIM
1017  *
1018  * @pthis: Pointer to main driver data
1019  */
1020 static void ecrnx_prim_tbtt_ind(void *pthis)
1021 {
1022 #ifdef CONFIG_ECRNX_SOFTMAC
1023     struct ecrnx_hw *ecrnx_hw = (struct ecrnx_hw *)pthis;
1024     ecrnx_tx_bcns(ecrnx_hw);
1025 #endif /* CONFIG_ECRNX_SOFTMAC */
1026 }
1027
1028 /**
1029  * ecrnx_sec_tbtt_ind() - IRQ handler callback for %IPC_IRQ_E2A_TBTT_SEC
1030  *
1031  * @pthis: Pointer to main driver data
1032  */
1033 static void ecrnx_sec_tbtt_ind(void *pthis)
1034 {
1035 }
1036
1037 /**
1038  * ecrnx_dbgind() - IRQ handler callback for %IPC_IRQ_E2A_DBG
1039  *
1040  * @pthis: Pointer to main driver data
1041  * @hostid: Pointer to IPC elem from dbgmsgs_pool
1042  */
1043  
1044 #ifdef CONFIG_ECRNX_ESWIN_USB
1045  extern void usb_dbg_printf(void * data, int len);
1046 #endif
1047 static u8 ecrnx_dbgind(void *pthis, void *hostid)
1048 {
1049     u8 ret = 0;
1050 #ifndef CONFIG_ECRNX_ESWIN
1051     struct ecrnx_hw *ecrnx_hw = (struct ecrnx_hw *)pthis;
1052     struct ecrnx_ipc_elem *elem = hostid;
1053     struct ipc_dbg_msg *dbg_msg = elem->addr;
1054
1055     REG_SW_SET_PROFILING(ecrnx_hw, SW_PROF_DBGIND);
1056
1057     /* Look for pattern which means that this hostbuf has been used for a MSG */
1058     if (dbg_msg->pattern != IPC_DBG_VALID_PATTERN) {
1059         ret = -1;
1060         goto dbg_no_push;
1061     }
1062
1063     /* Display the string */
1064     //printk("%s %s", (char *)FW_STR, (char *)dbg_msg->string);
1065
1066     /* Reset the msg element and re-use it */
1067     dbg_msg->pattern = 0;
1068     wmb();
1069
1070     /* Push back the buffer to the LMAC */
1071     ipc_host_dbgbuf_push(ecrnx_hw->ipc_env, elem, (u32)elem->dma_addr);
1072
1073 dbg_no_push:
1074     REG_SW_CLEAR_PROFILING(ecrnx_hw, SW_PROF_DBGIND);
1075
1076 #else
1077     struct sk_buff *skb = (struct sk_buff *)hostid;
1078 #ifdef CONFIG_ECRNX_ESWIN_USB
1079     usb_dbg_printf(skb->data, skb->len);
1080 #else
1081     uint8_t string[IPC_DBG_PARAM_SIZE] = {0}; 
1082     if(skb->len < IPC_DBG_PARAM_SIZE)
1083     {
1084         memcpy(string, skb->data, skb->len);
1085     }
1086     else
1087     {
1088         printk("waring: string buff no enough \n");
1089         memcpy(string, skb->data, IPC_DBG_PARAM_SIZE-1);
1090     }
1091     ECRNX_PRINT("%s %s", (char *)FW_STR, (char *)string);
1092 #endif
1093 #endif
1094
1095     return ret;
1096 }
1097
1098 /**
1099  * ecrnx_ipc_rxbuf_init() - Allocate and initialize RX buffers.
1100  *
1101  * @ecrnx_hw: Main driver data
1102  * @rx_bufsz: Size of the buffer to be allocated
1103  *
1104  * This function updates the RX buffer size according to the parameter and allocates the
1105  * RX buffers
1106  */
1107 #ifndef CONFIG_ECRNX_ESWIN
1108 int ecrnx_ipc_rxbuf_init(struct ecrnx_hw *ecrnx_hw, uint32_t rx_bufsz)
1109 {
1110     ecrnx_hw->ipc_env->rx_bufsz = rx_bufsz;
1111     return(ecrnx_ipc_rxbuf_elems_allocs(ecrnx_hw));
1112 }
1113 #endif
1114 /**
1115  * ecrnx_ipc_init() - Initialize IPC interface.
1116  *
1117  * @ecrnx_hw: Main driver data
1118  * @shared_ram: Pointer to shared memory that contains IPC shared struct
1119  *
1120  * This function initializes IPC interface by registering callbacks, setting
1121  * shared memory area and calling IPC Init function.
1122  * It should be called only once during driver's lifetime.
1123  */
1124 int ecrnx_ipc_init(struct ecrnx_hw *ecrnx_hw, u8 *shared_ram)
1125 {
1126     struct ipc_host_cb_tag cb;
1127     int res;
1128     ECRNX_DBG("%s entry!!", __func__);
1129     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1130
1131     /* initialize the API interface */
1132     cb.recv_data_ind   = ecrnx_rxdataind;
1133     cb.recv_radar_ind  = ecrnx_radarind;
1134     cb.recv_msg_ind    = ecrnx_msgind;
1135     cb.recv_msgack_ind = ecrnx_msgackind;
1136     cb.recv_dbg_ind    = ecrnx_dbgind;
1137     cb.send_data_cfm   = ecrnx_txdatacfm;
1138     cb.handle_data_cfm   = ecrnx_handle_tx_datacfm;
1139
1140     cb.prim_tbtt_ind   = ecrnx_prim_tbtt_ind;
1141     cb.sec_tbtt_ind    = ecrnx_sec_tbtt_ind;
1142     cb.recv_unsup_rx_vec_ind = ecrnx_unsup_rx_vec_ind;
1143
1144     /* set the IPC environment */
1145     ecrnx_hw->ipc_env = (struct ipc_host_env_tag *)
1146                        kzalloc(sizeof(struct ipc_host_env_tag), GFP_KERNEL);
1147
1148     if (!ecrnx_hw->ipc_env)
1149         return -ENOMEM;
1150
1151     /* call the initialization of the IPC */
1152     ipc_host_init(ecrnx_hw->ipc_env, &cb,
1153                   (struct ipc_shared_env_tag *)shared_ram, ecrnx_hw);
1154
1155     ecrnx_cmd_mgr_init(&ecrnx_hw->cmd_mgr);
1156
1157     ecrnx_rx_reord_init(ecrnx_hw);
1158 #ifdef CONFIG_ECRNX_ESWIN_SDIO
1159     ecrnx_sdio_init(ecrnx_hw);
1160 #elif defined(CONFIG_ECRNX_ESWIN_USB)
1161     ecrnx_usb_init(ecrnx_hw);
1162 #endif
1163
1164     res = ecrnx_elems_allocs(ecrnx_hw);
1165     if (res) {
1166
1167         kfree(ecrnx_hw->ipc_env);
1168         ecrnx_hw->ipc_env = NULL;
1169     }
1170     ECRNX_DBG("%s exit!!", __func__);
1171     return res;
1172 }
1173
1174 /**
1175  * ecrnx_ipc_deinit() - Release IPC interface
1176  *
1177  * @ecrnx_hw: Main driver data
1178  */
1179 void ecrnx_ipc_deinit(struct ecrnx_hw *ecrnx_hw)
1180 {
1181     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1182
1183     ecrnx_ipc_tx_drain(ecrnx_hw);
1184     ecrnx_cmd_mgr_deinit(&ecrnx_hw->cmd_mgr);
1185 #ifndef CONFIG_ECRNX_ESWIN
1186     ecrnx_elems_deallocs(ecrnx_hw);
1187 #endif
1188
1189     ecrnx_rx_reord_deinit(ecrnx_hw);
1190 #ifdef CONFIG_ECRNX_ESWIN_SDIO
1191     if (ecrnx_hw->ipc_env->shared) {
1192         kfree(ecrnx_hw->ipc_env->shared);
1193         ecrnx_hw->ipc_env->shared = NULL;
1194     }
1195     ecrnx_sdio_deinit(ecrnx_hw);
1196 #elif defined(CONFIG_ECRNX_ESWIN_USB)
1197     ecrnx_usb_deinit(ecrnx_hw);
1198 #endif
1199
1200     if (ecrnx_hw->ipc_env) {
1201         kfree(ecrnx_hw->ipc_env);
1202         ecrnx_hw->ipc_env = NULL;
1203     }
1204 }
1205
1206 /**
1207  * ecrnx_ipc_start() - Start IPC interface
1208  *
1209  * @ecrnx_hw: Main driver data
1210  */
1211 void ecrnx_ipc_start(struct ecrnx_hw *ecrnx_hw)
1212 {
1213     ipc_host_enable_irq(ecrnx_hw->ipc_env, IPC_IRQ_E2A_ALL);
1214 }
1215
1216 /**
1217  * ecrnx_ipc_stop() - Stop IPC interface
1218  *
1219  * @ecrnx_hw: Main driver data
1220  */
1221 void ecrnx_ipc_stop(struct ecrnx_hw *ecrnx_hw)
1222 {
1223     ipc_host_disable_irq(ecrnx_hw->ipc_env, IPC_IRQ_E2A_ALL);
1224 }
1225
1226 /**
1227  * ecrnx_ipc_tx_drain() - Flush IPC TX buffers
1228  *
1229  * @ecrnx_hw: Main driver data
1230  *
1231  * This assumes LMAC is still (tx wise) and there's no TX race until LMAC is up
1232  * tx wise.
1233  * This also lets both IPC sides remain in sync before resetting the LMAC,
1234  * e.g with ecrnx_send_reset.
1235  */
1236 void ecrnx_ipc_tx_drain(struct ecrnx_hw *ecrnx_hw)
1237 {
1238     int i, j;
1239
1240     ECRNX_DBG(ECRNX_FN_ENTRY_STR);
1241
1242     if (!ecrnx_hw->ipc_env) {
1243         printk(KERN_CRIT "%s: bypassing (restart must have failed)\n", __func__);
1244         return;
1245     }
1246
1247     for (i = 0; i < ECRNX_HWQ_NB; i++) {
1248         for (j = 0; j < nx_txuser_cnt[i]; j++) {
1249             struct sk_buff *skb;
1250             while ((skb = (struct sk_buff *)ipc_host_tx_flush(ecrnx_hw->ipc_env, i, j))) {
1251                 struct ecrnx_sw_txhdr *sw_txhdr =
1252                     ((struct ecrnx_txhdr *)skb->data)->sw_hdr;
1253 #ifndef CONFIG_ECRNX_ESWIN        
1254         #ifdef CONFIG_ECRNX_AMSDUS_TX
1255                 if (sw_txhdr->desc.host.packet_cnt > 1) {
1256                     struct ecrnx_amsdu_txhdr *amsdu_txhdr;
1257                     list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) {
1258                         dma_unmap_single(ecrnx_hw->dev, amsdu_txhdr->dma_addr,
1259                                          amsdu_txhdr->map_len, DMA_TO_DEVICE);
1260                         dev_kfree_skb_any(amsdu_txhdr->skb);
1261                     }
1262                 }
1263         #endif
1264                 kmem_cache_free(ecrnx_hw->sw_txhdr_cache, sw_txhdr);
1265                 dma_unmap_single(ecrnx_hw->dev, sw_txhdr->dma_addr,
1266                                  sw_txhdr->map_len, DMA_TO_DEVICE);
1267 #endif
1268                 skb_pull(skb, sw_txhdr->headroom);
1269 #ifdef CONFIG_ECRNX_SOFTMAC
1270                 ieee80211_free_txskb(ecrnx_hw->hw, skb);
1271 #else
1272                 dev_kfree_skb_any(skb);
1273 #endif /* CONFIG_ECRNX_SOFTMAC */
1274             }
1275         }
1276     }
1277 }
1278
1279 /**
1280  * ecrnx_ipc_tx_pending() - Check if TX pframes are pending at FW level
1281  *
1282  * @ecrnx_hw: Main driver data
1283  */
1284 bool ecrnx_ipc_tx_pending(struct ecrnx_hw *ecrnx_hw)
1285 {
1286     return ipc_host_tx_frames_pending(ecrnx_hw->ipc_env);
1287 }
1288
1289 /**
1290  * ecrnx_error_ind() - %DBG_ERROR_IND message callback
1291  *
1292  * @ecrnx_hw: Main driver data
1293  *
1294  * This function triggers the UMH script call that will indicate to the user
1295  * space the error that occurred and stored the debug dump. Once the UMH script
1296  * is executed, the ecrnx_umh_done() function has to be called.
1297  */
1298 void ecrnx_error_ind(struct ecrnx_hw *ecrnx_hw)
1299 {
1300     struct ecrnx_ipc_elem_var *elem = &ecrnx_hw->dbgdump_elem.buf;
1301     struct dbg_debug_dump_tag *dump = elem->addr;
1302
1303     dma_sync_single_for_device(ecrnx_hw->dev, elem->dma_addr, elem->size,
1304                                DMA_FROM_DEVICE);
1305     dev_err(ecrnx_hw->dev, "(type %d): dump received\n",
1306             dump->dbg_info.error_type);
1307
1308 #ifdef CONFIG_ECRNX_DEBUGFS
1309     ecrnx_hw->debugfs.trace_prst = true;
1310     ecrnx_trigger_um_helper(&ecrnx_hw->debugfs);
1311 #endif
1312 }
1313
1314 /**
1315  * ecrnx_umh_done() - Indicate User Mode helper finished
1316  *
1317  * @ecrnx_hw: Main driver data
1318  *
1319  */
1320 void ecrnx_umh_done(struct ecrnx_hw *ecrnx_hw)
1321 {
1322     if (!test_bit(ECRNX_DEV_STARTED, &ecrnx_hw->flags))
1323         return;
1324
1325     /* this assumes error_ind won't trigger before ipc_host_dbginfobuf_push
1326        is called and so does not irq protect (TODO) against error_ind */
1327 #ifdef CONFIG_ECRNX_DEBUGFS
1328     ecrnx_hw->debugfs.trace_prst = false;
1329 #ifndef CONFIG_ECRNX_ESWIN
1330     ipc_host_dbginfobuf_push(ecrnx_hw->ipc_env, ecrnx_hw->dbgdump_elem.buf.dma_addr);
1331 #endif
1332 #endif
1333 }