1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#undef CSR_WIFI_HIP_NOISY
24
25#include "csr_wifi_hip_unifi.h"
26#include "csr_wifi_hip_conversions.h"
27#include "csr_wifi_hip_card.h"
28#include "csr_wifi_hip_xbv.h"
29
30
31
32
33
34
35
36#define UNIFI_DEFAULT_HOST_IDLE_TIMEOUT 5
37
38
39
40
41
42#define UNIFI_DEFAULT_WAKE_TIMEOUT 1000
43
44
45static CsrResult process_bh(card_t *card);
46static CsrResult handle_host_protocol(card_t *card, u8 *processed_something);
47
48static CsrResult flush_fh_buffer(card_t *card);
49
50static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space);
51
52static CsrResult read_to_host_signals(card_t *card, s32 *processed);
53static CsrResult process_to_host_signals(card_t *card, s32 *processed);
54
55static CsrResult process_bulk_data_command(card_t *card,
56 const u8 *cmdptr,
57 s16 cmd, u16 len);
58static CsrResult process_clear_slot_command(card_t *card,
59 const u8 *cmdptr);
60static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed);
61static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed);
62static void restart_packet_flow(card_t *card);
63static CsrResult process_clock_request(card_t *card);
64
65#ifdef CSR_WIFI_HIP_NOISY
66s16 dump_fh_buf = 0;
67#endif
68
69#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
70
71
72
73
74
75
76
77
78
79
80
81
82
83#define UNIFI_DEBUG_GBUFFER_SIZE 8192
84static char unifi_debug_output[UNIFI_DEBUG_GBUFFER_SIZE];
85static char *unifi_dbgbuf_ptr = unifi_debug_output;
86static char *unifi_dbgbuf_start = unifi_debug_output;
87
88static void append_char(char c)
89{
90
91 *unifi_dbgbuf_ptr++ = c;
92
93 if ((unifi_dbgbuf_ptr - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE)
94 {
95 unifi_dbgbuf_ptr = unifi_debug_output;
96 }
97}
98
99
100void unifi_debug_string_to_buf(const char *str)
101{
102 const char *p = str;
103 while (*p)
104 {
105 append_char(*p);
106 p++;
107 }
108
109 unifi_dbgbuf_start = unifi_dbgbuf_ptr + 1;
110 if ((unifi_dbgbuf_start - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE)
111 {
112 unifi_dbgbuf_start = unifi_debug_output;
113 }
114}
115
116
117void unifi_debug_log_to_buf(const char *fmt, ...)
118{
119#define DEBUG_BUFFER_SIZE 80
120 static char s[DEBUG_BUFFER_SIZE];
121 va_list args;
122
123 va_start(args, fmt);
124 vsnprintf(s, DEBUG_BUFFER_SIZE, fmt, args);
125 va_end(args);
126
127 unifi_debug_string_to_buf(s);
128}
129
130
131
132static void CsrUInt16ToHex(u16 number, char *str)
133{
134 u16 index;
135 u16 currentValue;
136
137 for (index = 0; index < 4; index++)
138 {
139 currentValue = (u16) (number & 0x000F);
140 number >>= 4;
141 str[3 - index] = (char) (currentValue > 9 ? currentValue + 55 : currentValue + '0');
142 }
143 str[4] = '\0';
144}
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162void unifi_debug_hex_to_buf(const char *buff, u16 length)
163{
164 char s[5];
165 u16 i;
166
167 for (i = 0; i < length; i = i + 2)
168 {
169 CsrUInt16ToHex(*((u16 *)(buff + i)), s);
170 unifi_debug_string_to_buf(s);
171 }
172}
173
174
175void unifi_debug_buf_dump(void)
176{
177 s32 offset = unifi_dbgbuf_ptr - unifi_debug_output;
178
179 unifi_error(NULL, "HIP debug buffer offset=%d\n", offset);
180 dump_str(unifi_debug_output + offset, UNIFI_DEBUG_GBUFFER_SIZE - offset);
181 dump_str(unifi_debug_output, offset);
182}
183
184
185#endif
186
187#ifdef CSR_PRE_ALLOC_NET_DATA
188#define NETDATA_PRE_ALLOC_BUF_SIZE 8000
189
190void prealloc_netdata_free(card_t *card)
191{
192 unifi_warning(card->ospriv, "prealloc_netdata_free: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
193
194 while (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length != 0)
195 {
196 unifi_warning(card->ospriv, "prealloc_netdata_free: r=%d\n", card->prealloc_netdata_r);
197
198 unifi_net_data_free(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_r]);
199 card->prealloc_netdata_r++;
200 card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM;
201 }
202 card->prealloc_netdata_r = card->prealloc_netdata_w = 0;
203
204 unifi_warning(card->ospriv, "prealloc_netdata_free: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
205}
206
207
208CsrResult prealloc_netdata_alloc(card_t *card)
209{
210 CsrResult r;
211
212 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
213
214 while (card->bulk_data_desc_list[card->prealloc_netdata_w].data_length == 0)
215 {
216 r = unifi_net_data_malloc(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_w], NETDATA_PRE_ALLOC_BUF_SIZE);
217 if (r != CSR_RESULT_SUCCESS)
218 {
219 unifi_error(card->ospriv, "prealloc_netdata_alloc: Failed to allocate t-h bulk data\n");
220 return CSR_RESULT_FAILURE;
221 }
222 card->prealloc_netdata_w++;
223 card->prealloc_netdata_w %= BULK_DATA_PRE_ALLOC_NUM;
224 }
225 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
226
227 return CSR_RESULT_SUCCESS;
228}
229
230
231static CsrResult prealloc_netdata_get(card_t *card, bulk_data_desc_t *bulk_data_slot, u32 size)
232{
233 CsrResult r;
234
235 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
236
237 if (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0)
238 {
239 unifi_error(card->ospriv, "prealloc_netdata_get: data_length = 0\n");
240 }
241
242 if ((size > NETDATA_PRE_ALLOC_BUF_SIZE) || (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length == 0))
243 {
244 unifi_warning(card->ospriv, "prealloc_netdata_get: Calling net_data_malloc\n");
245
246 r = unifi_net_data_malloc(card->ospriv, bulk_data_slot, size);
247 if (r != CSR_RESULT_SUCCESS)
248 {
249 unifi_error(card->ospriv, "prealloc_netdata_get: Failed to allocate t-h bulk data\n");
250 return CSR_RESULT_FAILURE;
251 }
252 return CSR_RESULT_SUCCESS;
253 }
254
255 *bulk_data_slot = card->bulk_data_desc_list[card->prealloc_netdata_r];
256 card->bulk_data_desc_list[card->prealloc_netdata_r].os_data_ptr = NULL;
257 card->bulk_data_desc_list[card->prealloc_netdata_r].os_net_buf_ptr = NULL;
258 card->bulk_data_desc_list[card->prealloc_netdata_r].net_buf_length = 0;
259 card->bulk_data_desc_list[card->prealloc_netdata_r].data_length = 0;
260
261 card->prealloc_netdata_r++;
262 card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM;
263
264 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_get: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
265
266 return CSR_RESULT_SUCCESS;
267}
268
269
270#endif
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289void unifi_sdio_interrupt_handler(card_t *card)
290{
291
292
293
294
295 card->bh_reason_unifi = 1;
296 (void)unifi_run_bh(card->ospriv);
297}
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316CsrResult unifi_configure_low_power_mode(card_t *card,
317 enum unifi_low_power_mode low_power_mode,
318 enum unifi_periodic_wake_mode periodic_wake_mode)
319{
320 card->low_power_mode = low_power_mode;
321 card->periodic_wake_mode = periodic_wake_mode;
322
323 unifi_trace(card->ospriv, UDBG1,
324 "unifi_configure_low_power_mode: new mode = %s, wake_host = %s\n",
325 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled",
326 (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE");
327
328 (void)unifi_run_bh(card->ospriv);
329 return CSR_RESULT_SUCCESS;
330}
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347CsrResult unifi_force_low_power_mode(card_t *card)
348{
349 if (card->low_power_mode == UNIFI_LOW_POWER_DISABLED)
350 {
351 unifi_error(card->ospriv, "Attempt to set mode to TORPID when lower power mode is disabled\n");
352 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
353 }
354
355 return unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID);
356}
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373CsrResult unifi_bh(card_t *card, u32 *remaining)
374{
375 CsrResult r;
376 CsrResult csrResult;
377 u8 pending;
378 s32 iostate, j;
379 const enum unifi_low_power_mode low_power_mode = card->low_power_mode;
380 u16 data_slots_used = 0;
381
382
383
384 r = process_clock_request(card);
385 if (r != CSR_RESULT_SUCCESS)
386 {
387 unifi_error(card->ospriv, "Error setting maximum SDIO clock\n");
388 goto exit;
389 }
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 do
419 {
420
421
422
423
424
425 if (card->host_state == UNIFI_HOST_STATE_DROWSY || card->host_state == UNIFI_HOST_STATE_TORPID)
426 {
427 u8 reason_unifi;
428
429
430
431
432
433
434
435 reason_unifi = card->bh_reason_unifi;
436
437
438
439
440
441 r = CardPendingInt(card, &pending);
442 if (r != CSR_RESULT_SUCCESS)
443 {
444 goto exit;
445 }
446
447 if (pending)
448 {
449 unifi_trace(card->ospriv, UDBG5,
450 "UNIFI_HOST_STATE_%s: Set state to AWAKE.\n",
451 (card->host_state == UNIFI_HOST_STATE_TORPID)?"TORPID" : "DROWSY");
452
453 r = unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
454 if (r == CSR_RESULT_SUCCESS)
455 {
456 (*remaining) = 0;
457 break;
458 }
459 }
460 else if (reason_unifi)
461 {
462 CsrSdioInterruptAcknowledge(card->sdio_if);
463 }
464
465
466
467
468
469 if ((card->host_state == UNIFI_HOST_STATE_TORPID) && card->bh_reason_host)
470 {
471 r = unifi_set_host_state(card, UNIFI_HOST_STATE_DROWSY);
472 if (r == CSR_RESULT_SUCCESS)
473 {
474
475
476
477
478 card->bh_reason_host = 0;
479 (*remaining) = UNIFI_DEFAULT_WAKE_TIMEOUT;
480 return CSR_RESULT_SUCCESS;
481 }
482
483 goto exit;
484 }
485
486
487
488
489
490
491
492 if ((card->host_state == UNIFI_HOST_STATE_DROWSY) && ((*remaining) == 0))
493 {
494 unifi_error(card->ospriv, "UniFi did not wake up on time...\n");
495
496
497
498
499
500 r = unifi_check_io_status(card, &iostate);
501 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
502 {
503 goto exit;
504 }
505
506 return CSR_RESULT_FAILURE;
507 }
508 }
509 else
510 {
511 if (card->bh_reason_unifi || card->bh_reason_host)
512 {
513 break;
514 }
515
516 if (((*remaining) == 0) && (low_power_mode == UNIFI_LOW_POWER_ENABLED))
517 {
518 r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID);
519 if (r == CSR_RESULT_SUCCESS)
520 {
521 (*remaining) = 0;
522 return CSR_RESULT_SUCCESS;
523 }
524
525 goto exit;
526 }
527 }
528
529
530 return CSR_RESULT_SUCCESS;
531 } while (0);
532
533
534
535 csrResult = CsrSdioInterruptDisable(card->sdio_if);
536 if (csrResult == CSR_SDIO_RESULT_NO_DEVICE)
537 {
538 r = CSR_WIFI_HIP_RESULT_NO_DEVICE;
539 goto exit;
540 }
541 if (csrResult != CSR_RESULT_SUCCESS)
542 {
543 r = ConvertCsrSdioToCsrHipResult(card, csrResult);
544 unifi_error(card->ospriv, "Failed to disable SDIO interrupts. unifi_bh queues error.\n");
545 goto exit;
546 }
547
548
549 CsrSdioInterruptAcknowledge(card->sdio_if);
550
551
552 r = process_bh(card);
553 if (r != CSR_RESULT_SUCCESS)
554 {
555 goto exit;
556 }
557
558
559
560
561
562
563
564
565 for (j = 0; j < UNIFI_NO_OF_TX_QS; j++)
566 {
567 data_slots_used += CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[j]);
568 }
569
570 if ((low_power_mode == UNIFI_LOW_POWER_ENABLED) && (data_slots_used == 0))
571 {
572#ifndef CSR_WIFI_HIP_TA_DISABLE
573 if (card->ta_sampling.traffic_type != CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC)
574 {
575#endif
576
577 unifi_trace(card->ospriv, UDBG5,
578 "Traffic is not periodic, set timer for TORPID.\n");
579 (*remaining) = UNIFI_DEFAULT_HOST_IDLE_TIMEOUT;
580#ifndef CSR_WIFI_HIP_TA_DISABLE
581 }
582 else
583 {
584 unifi_trace(card->ospriv, UDBG5,
585 "Traffic is periodic, set unifi to TORPID immediately.\n");
586 if (CardAreAllFromHostDataSlotsEmpty(card) == 1)
587 {
588 r = unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID);
589 if (r != CSR_RESULT_SUCCESS)
590 {
591 goto exit;
592 }
593 }
594 }
595#endif
596 }
597
598 csrResult = CsrSdioInterruptEnable(card->sdio_if);
599 if (csrResult == CSR_SDIO_RESULT_NO_DEVICE)
600 {
601 r = CSR_WIFI_HIP_RESULT_NO_DEVICE;
602 }
603 if (csrResult != CSR_RESULT_SUCCESS)
604 {
605 r = ConvertCsrSdioToCsrHipResult(card, csrResult);
606 unifi_error(card->ospriv, "Failed to enable SDIO interrupt\n");
607 }
608
609exit:
610
611 unifi_trace(card->ospriv, UDBG4, "New state=%d\n", card->host_state);
612
613 if (r != CSR_RESULT_SUCCESS)
614 {
615#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE)
616 unifi_debug_buf_dump();
617#endif
618
619 if (card->bh_reason_unifi)
620 {
621 CsrSdioInterruptAcknowledge(card->sdio_if);
622 }
623
624 unifi_error(card->ospriv,
625 "unifi_bh: state=%d %c, clock=%dkHz, interrupt=%d host=%d, power_save=%s\n",
626 card->host_state,
627 (card->host_state == UNIFI_HOST_STATE_AWAKE)?'A' : (card->host_state == UNIFI_HOST_STATE_DROWSY)?'D' : 'T',
628 card->sdio_clock_speed / 1000,
629 card->bh_reason_unifi, card->bh_reason_host,
630 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled");
631
632
633 (void)unifi_capture_panic(card);
634
635
636 (void)unifi_coredump_request_at_next_reset(card, 1);
637 }
638
639 return r;
640}
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658static CsrResult process_clock_request(card_t *card)
659{
660 CsrResult r = CSR_RESULT_SUCCESS;
661 CsrResult csrResult;
662
663 if (!card->request_max_clock)
664 {
665 return CSR_RESULT_SUCCESS;
666 }
667
668
669
670
671
672
673
674
675
676 if (card->host_state == UNIFI_HOST_STATE_AWAKE)
677 {
678 unifi_trace(card->ospriv, UDBG1, "Set SDIO max clock\n");
679 csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_MAX_HZ);
680 if (csrResult != CSR_RESULT_SUCCESS)
681 {
682 r = ConvertCsrSdioToCsrHipResult(card, csrResult);
683 }
684 else
685 {
686 card->sdio_clock_speed = UNIFI_SDIO_CLOCK_MAX_HZ;
687 }
688 }
689 else
690 {
691 unifi_trace(card->ospriv, UDBG1, "Will set SDIO max clock after wakeup\n");
692 }
693
694
695
696
697 card->request_max_clock = 0;
698
699 return r;
700}
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716static CsrResult process_bh(card_t *card)
717{
718 CsrResult r;
719 u8 more;
720 more = FALSE;
721
722
723 do
724 {
725
726
727
728
729 do
730 {
731
732 if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE)
733 {
734 break;
735 }
736
737 r = handle_host_protocol(card, &more);
738 if (r != CSR_RESULT_SUCCESS)
739 {
740 return r;
741 }
742
743#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
744 unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n",
745 card->cmd_prof.cmd52_count,
746 card->cmd_prof.cmd53_count,
747 card->cmd_prof.tx_count,
748 card->cmd_prof.tx_cfm_count,
749 card->cmd_prof.rx_count,
750 card->cmd_prof.sdio_cmd_signal,
751 card->cmd_prof.sdio_cmd_to_host,
752 card->cmd_prof.sdio_cmd_from_host_and_clear
753 );
754
755 card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0;
756 card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0;
757
758 card->cmd_prof.cmd52_f0_r_count = 0;
759 card->cmd_prof.cmd52_f0_w_count = 0;
760 card->cmd_prof.cmd52_r8or16_count = 0;
761 card->cmd_prof.cmd52_w8or16_count = 0;
762 card->cmd_prof.cmd52_r16_count = 0;
763 card->cmd_prof.cmd52_w16_count = 0;
764 card->cmd_prof.cmd52_r32_count = 0;
765
766 card->cmd_prof.sdio_cmd_signal = 0;
767 card->cmd_prof.sdio_cmd_clear_slot = 0;
768 card->cmd_prof.sdio_cmd_to_host = 0;
769 card->cmd_prof.sdio_cmd_from_host = 0;
770 card->cmd_prof.sdio_cmd_from_host_and_clear = 0;
771#endif
772
773
774 } while (more || card->bh_reason_unifi || card->bh_reason_host);
775
776
777 r = CardClearInt(card);
778 if (r != CSR_RESULT_SUCCESS)
779 {
780 unifi_error(card->ospriv, "Failed to acknowledge interrupt.\n");
781 return r;
782 }
783
784
785
786
787
788
789 r = handle_host_protocol(card, &more);
790 if (r != CSR_RESULT_SUCCESS)
791 {
792 return r;
793 }
794
795#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
796 unifi_debug_log_to_buf("c52=%d c53=%d tx=%d txc=%d rx=%d s=%d t=%d fc=%d\n",
797 card->cmd_prof.cmd52_count,
798 card->cmd_prof.cmd53_count,
799 card->cmd_prof.tx_count,
800 card->cmd_prof.tx_cfm_count,
801 card->cmd_prof.rx_count,
802 card->cmd_prof.sdio_cmd_signal,
803 card->cmd_prof.sdio_cmd_to_host,
804 card->cmd_prof.sdio_cmd_from_host_and_clear
805 );
806
807 card->cmd_prof.cmd52_count = card->cmd_prof.cmd53_count = 0;
808 card->cmd_prof.tx_count = card->cmd_prof.tx_cfm_count = card->cmd_prof.rx_count = 0;
809
810 card->cmd_prof.cmd52_f0_r_count = 0;
811 card->cmd_prof.cmd52_f0_w_count = 0;
812 card->cmd_prof.cmd52_r8or16_count = 0;
813 card->cmd_prof.cmd52_w8or16_count = 0;
814 card->cmd_prof.cmd52_r16_count = 0;
815 card->cmd_prof.cmd52_w16_count = 0;
816 card->cmd_prof.cmd52_r32_count = 0;
817
818 card->cmd_prof.sdio_cmd_signal = 0;
819 card->cmd_prof.sdio_cmd_clear_slot = 0;
820 card->cmd_prof.sdio_cmd_to_host = 0;
821 card->cmd_prof.sdio_cmd_from_host = 0;
822 card->cmd_prof.sdio_cmd_from_host_and_clear = 0;
823#endif
824
825 if (card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE)
826 {
827 break;
828 }
829
830 } while (more || card->bh_reason_unifi || card->bh_reason_host);
831
832#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
833 if ((card->intmode & CSR_WIFI_INTMODE_RUN_BH_ONCE) == 0)
834 {
835 unifi_debug_log_to_buf("proc=%d\n",
836 card->cmd_prof.process_count);
837 }
838#endif
839
840 return CSR_RESULT_SUCCESS;
841}
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
862{
863 CsrResult r;
864 s32 done;
865
866 *processed_something = FALSE;
867
868#ifdef CSR_WIFI_HIP_NOISY
869 unifi_error(card->ospriv, " ======================== \n");
870#endif
871
872#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
873 card->cmd_prof.process_count++;
874#endif
875
876 card->bh_reason_unifi = card->bh_reason_host = 0;
877 card->generate_interrupt = 0;
878
879
880
881
882
883 r = read_to_host_signals(card, &done);
884 if (r != CSR_RESULT_SUCCESS)
885 {
886 unifi_error(card->ospriv, "Error occurred reading to-host signals\n");
887 return r;
888 }
889 if (done > 0)
890 {
891 *processed_something = TRUE;
892 }
893
894
895
896
897
898
899 r = process_to_host_signals(card, &done);
900 if (r != CSR_RESULT_SUCCESS)
901 {
902 unifi_error(card->ospriv, "Error occurred processing to-host signals\n");
903 return r;
904 }
905
906
907
908 r = process_fh_cmd_queue(card, &done);
909 if (r != CSR_RESULT_SUCCESS)
910 {
911 unifi_error(card->ospriv, "Error occurred processing from-host signals\n");
912 return r;
913 }
914 if (done > 0)
915 {
916 *processed_something = TRUE;
917 }
918
919 r = process_fh_traffic_queue(card, &done);
920 if (r != CSR_RESULT_SUCCESS)
921 {
922 unifi_error(card->ospriv, "Error occurred processing from-host data signals\n");
923 return r;
924 }
925 if (done > 0)
926 {
927 *processed_something = TRUE;
928 }
929
930
931 r = flush_fh_buffer(card);
932 if (r != CSR_RESULT_SUCCESS)
933 {
934 unifi_error(card->ospriv, "Failed to copy from-host signals to UniFi\n");
935 return r;
936 }
937
938
939
940
941
942 if (card->generate_interrupt)
943 {
944 r = CardGenInt(card);
945 if (r != CSR_RESULT_SUCCESS)
946 {
947 unifi_error(card->ospriv, "Failed to notify UniFi that queues have been modified.\n");
948 return r;
949 }
950 }
951
952#ifdef CSR_WIFI_RX_PATH_SPLIT
953#ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
954 unifi_rx_queue_flush(card->ospriv);
955#endif
956#endif
957
958
959 restart_packet_flow(card);
960
961#ifdef CSR_PRE_ALLOC_NET_DATA
962 r = prealloc_netdata_alloc(card);
963 if (r != CSR_RESULT_SUCCESS)
964 {
965 unifi_error(card->ospriv, "prealloc_netdata failed\n");
966 return r;
967 }
968#endif
969
970
971
972
973
974 return r;
975}
976
977
978
979
980
981
982#define GET_CHUNKS_FOR(SIG_FRAG_SIZE, LENGTH) (((LENGTH) + ((SIG_FRAG_SIZE)-1)) / (SIG_FRAG_SIZE))
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001static CsrResult read_to_host_signals(card_t *card, s32 *processed)
1002{
1003 s32 count_thw, count_thr;
1004 s32 unread_chunks, unread_bytes;
1005 CsrResult r;
1006
1007 *processed = 0;
1008
1009
1010 count_thw = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4);
1011 if (count_thw < 0)
1012 {
1013 unifi_error(card->ospriv, "Failed to read to-host sig written count\n");
1014 return CSR_RESULT_FAILURE;
1015 }
1016 card->to_host_signals_w = count_thw;
1017
1018 count_thr = card->to_host_signals_r;
1019
1020 if (count_thw == count_thr)
1021 {
1022 return CSR_RESULT_SUCCESS;
1023 }
1024
1025 unread_chunks =
1026 (((count_thw - count_thr) + 128) % 128) - card->th_buffer.count;
1027
1028 if (unread_chunks == 0)
1029 {
1030 return CSR_RESULT_SUCCESS;
1031 }
1032
1033 unread_bytes = card->config_data.sig_frag_size * unread_chunks;
1034
1035
1036 r = unifi_bulk_rw(card,
1037 card->config_data.tohost_sigbuf_handle,
1038 card->th_buffer.ptr,
1039 unread_bytes,
1040 UNIFI_SDIO_READ);
1041 if (r != CSR_RESULT_SUCCESS)
1042 {
1043 unifi_error(card->ospriv, "Failed to read ToHost signal\n");
1044 return r;
1045 }
1046
1047 card->th_buffer.ptr += unread_bytes;
1048 card->th_buffer.count += (u16)unread_chunks;
1049
1050 *processed = 1;
1051
1052 return CSR_RESULT_SUCCESS;
1053}
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073static CsrResult update_to_host_signals_r(card_t *card, s16 pending)
1074{
1075 CsrResult r;
1076
1077 card->to_host_signals_r =
1078 (card->to_host_signals_r + (card->th_buffer.count - pending)) % 128;
1079 card->th_buffer.count = pending;
1080
1081
1082 r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 6,
1083 (u8)card->to_host_signals_r);
1084 if (r != CSR_RESULT_SUCCESS)
1085 {
1086 unifi_error(card->ospriv, "Failed to update to-host signals read\n");
1087 return r;
1088 }
1089
1090 r = CardGenInt(card);
1091 if (r != CSR_RESULT_SUCCESS)
1092 {
1093 unifi_error(card->ospriv, "Failed to notify UniFi that we processed to-host signals.\n");
1094 return r;
1095 }
1096
1097 card->generate_interrupt = 0;
1098
1099 return CSR_RESULT_SUCCESS;
1100}
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117static void read_unpack_cmd(const u8 *ptr, bulk_data_cmd_t *bulk_data_cmd)
1118{
1119 s16 index = 0;
1120 bulk_data_cmd->cmd_and_len = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index);
1121 index += SIZEOF_UINT16;
1122 bulk_data_cmd->data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index);
1123 index += SIZEOF_UINT16;
1124 bulk_data_cmd->offset = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index);
1125 index += SIZEOF_UINT16;
1126 bulk_data_cmd->buffer_handle = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(ptr + index);
1127 index += SIZEOF_UINT16;
1128}
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162static CsrResult process_to_host_signals(card_t *card, s32 *processed)
1163{
1164 s16 pending;
1165 s16 remaining;
1166 u8 *bufptr;
1167 bulk_data_param_t data_ptrs;
1168 s16 cmd;
1169 u16 sig_len;
1170 s16 i;
1171 u16 chunks_in_buf;
1172 u16 bytes_transferred = 0;
1173 CsrResult r = CSR_RESULT_SUCCESS;
1174
1175 *processed = 0;
1176
1177 pending = card->th_buffer.count;
1178
1179
1180 unifi_trace(card->ospriv, UDBG4, "handling %d to-host chunks\n", pending);
1181
1182 if (!pending)
1183 {
1184 return CSR_RESULT_SUCCESS;
1185 }
1186
1187
1188
1189
1190
1191
1192 bufptr = card->th_buffer.buf;
1193
1194 while (pending > 0)
1195 {
1196 s16 f_flush_count = 0;
1197
1198
1199
1200
1201
1202
1203 cmd = bufptr[1] >> 4;
1204 sig_len = bufptr[0] + ((bufptr[1] & 0x0F) << 8);
1205
1206#ifdef CSR_WIFI_HIP_NOISY
1207 unifi_error(card->ospriv, "Received UniFi msg cmd=%d, len=%d\n",
1208 cmd, sig_len);
1209#endif
1210
1211 if ((sig_len == 0) &&
1212 ((cmd != SDIO_CMD_CLEAR_SLOT) && (cmd != SDIO_CMD_PADDING)))
1213 {
1214 unifi_error(card->ospriv, "incomplete signal or command: has size zero\n");
1215 return CSR_RESULT_FAILURE;
1216 }
1217
1218
1219
1220
1221
1222 if (cmd == SDIO_CMD_SIGNAL)
1223 {
1224 chunks_in_buf = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(sig_len + 2));
1225 }
1226 else
1227 {
1228 chunks_in_buf = 1;
1229 }
1230
1231 if (chunks_in_buf > (u16)pending)
1232 {
1233 unifi_error(card->ospriv, "incomplete signal (0x%x?): need %d chunks, got %d\n",
1234 GET_SIGNAL_ID(bufptr + 2),
1235 chunks_in_buf, pending);
1236 unifi_error(card->ospriv, " thsw=%d, thsr=%d\n",
1237 card->to_host_signals_w,
1238 card->to_host_signals_r);
1239 return CSR_RESULT_FAILURE;
1240 }
1241
1242
1243 switch (cmd)
1244 {
1245 case SDIO_CMD_SIGNAL:
1246
1247#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
1248 card->cmd_prof.sdio_cmd_signal++;
1249#endif
1250
1251 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++)
1252 {
1253
1254 u16 data_len = GET_PACKED_DATAREF_LEN(bufptr + 2, i);
1255
1256
1257
1258
1259
1260 if (data_len > card->config_data.data_slot_size)
1261 {
1262 unifi_error(card->ospriv,
1263 "Bulk Data length (%d) exceeds Maximum Bulk Data length (%d)\n",
1264 data_len, card->config_data.data_slot_size);
1265 return CSR_RESULT_FAILURE;
1266 }
1267
1268
1269
1270
1271
1272
1273 if (data_len != 0)
1274 {
1275
1276 s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i);
1277
1278 if (slot >= card->config_data.num_tohost_data_slots)
1279 {
1280 unifi_error(card->ospriv, "!!!bad slot number in to-host signal: %d, sig 0x%X\n",
1281 slot, cmd);
1282 return CSR_RESULT_FAILURE;
1283 }
1284
1285 data_ptrs.d[i].os_data_ptr = card->to_host_data[slot].os_data_ptr;
1286 data_ptrs.d[i].os_net_buf_ptr = card->to_host_data[slot].os_net_buf_ptr;
1287 data_ptrs.d[i].net_buf_length = card->to_host_data[slot].net_buf_length;
1288 data_ptrs.d[i].data_length = data_len;
1289 }
1290 else
1291 {
1292 UNIFI_INIT_BULK_DATA(&data_ptrs.d[i]);
1293 }
1294 }
1295
1296
1297
1298
1299
1300 if (card->udi_hook)
1301 {
1302 (*card->udi_hook)(card->ospriv, bufptr + 2, sig_len,
1303 &data_ptrs, UDI_LOG_TO_HOST);
1304 }
1305
1306#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
1307 if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID)
1308 {
1309 card->cmd_prof.tx_cfm_count++;
1310 }
1311 else if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_INDICATION_ID)
1312 {
1313 if (data_ptrs.d[0].os_data_ptr)
1314 {
1315 if ((*data_ptrs.d[0].os_data_ptr) & 0x08)
1316 {
1317 card->cmd_prof.rx_count++;
1318 }
1319 }
1320 }
1321#endif
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331 if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID)
1332 {
1333
1334 u32 host_tag = GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(bufptr + 2);
1335 u16 status = GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(bufptr + 2);
1336
1337 unifi_trace(card->ospriv, UDBG4, "process_to_host_signals signal ID=%x host Tag=%x status=%x\n",
1338 GET_SIGNAL_ID(bufptr + 2), host_tag, status);
1339
1340
1341
1342
1343
1344 if (status && (card->fh_slot_host_tag_record))
1345 {
1346 u16 num_fh_slots = card->config_data.num_fromhost_data_slots;
1347
1348
1349
1350
1351 for (i = 0; i < num_fh_slots; i++)
1352 {
1353 if (card->fh_slot_host_tag_record[i] == host_tag)
1354 {
1355#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
1356
1357 r = unifi_reque_ma_packet_request(card->ospriv, host_tag, status, &card->from_host_data[i].bd);
1358 card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
1359 if (CSR_RESULT_SUCCESS != r)
1360 {
1361 unifi_trace(card->ospriv, UDBG5, "process_to_host_signals: Failed to requeue Packet(hTag:%x) back to HAL \n", host_tag);
1362 CardClearFromHostDataSlot(card, i);
1363 }
1364 else
1365 {
1366 CardClearFromHostDataSlotWithoutFreeingBulkData(card, i);
1367 }
1368
1369#else
1370 unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag);
1371 card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
1372
1373
1374 CardClearFromHostDataSlot(card, i);
1375#endif
1376 break;
1377 }
1378 }
1379 }
1380 }
1381
1382
1383 unifi_receive_event(card->ospriv, bufptr + 2, sig_len, &data_ptrs);
1384
1385
1386 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++)
1387 {
1388
1389 if (GET_PACKED_DATAREF_LEN(bufptr + 2, i) != 0)
1390 {
1391 s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i);
1392 if (slot < card->config_data.num_tohost_data_slots)
1393 {
1394 UNIFI_INIT_BULK_DATA(&card->to_host_data[slot]);
1395 }
1396 }
1397 }
1398
1399#ifndef CSR_WIFI_DEFER_TH_FLUSH
1400
1401
1402
1403
1404
1405 if (bytes_transferred >= TO_HOST_FLUSH_THRESHOLD)
1406 {
1407 f_flush_count = 1;
1408 }
1409#endif
1410 break;
1411
1412
1413 case SDIO_CMD_CLEAR_SLOT:
1414#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
1415 card->cmd_prof.sdio_cmd_clear_slot++;
1416#endif
1417
1418 if (sig_len != 0)
1419 {
1420 unifi_error(card->ospriv, "process_to_host_signals: clear slot, bad data len: 0x%X at offset %d\n",
1421 sig_len, bufptr - card->th_buffer.buf);
1422 return CSR_RESULT_FAILURE;
1423 }
1424
1425 r = process_clear_slot_command(card, bufptr);
1426 if (r != CSR_RESULT_SUCCESS)
1427 {
1428 unifi_error(card->ospriv, "Failed to process clear slot\n");
1429 return r;
1430 }
1431 break;
1432
1433 case SDIO_CMD_TO_HOST_TRANSFER:
1434 case SDIO_CMD_FROM_HOST_TRANSFER:
1435 case SDIO_CMD_FROM_HOST_AND_CLEAR:
1436 case SDIO_CMD_OVERLAY_TRANSFER:
1437
1438 if (sig_len & 1)
1439 {
1440 unifi_error(card->ospriv, "process_to_host_signals: bulk data, bad data len: 0x%X at offset %d\n",
1441 sig_len, bufptr - card->th_buffer.buf);
1442 return CSR_RESULT_FAILURE;
1443 }
1444
1445 r = process_bulk_data_command(card, bufptr, cmd, sig_len);
1446 if (r != CSR_RESULT_SUCCESS)
1447 {
1448 unifi_error(card->ospriv, "Failed to process bulk cmd\n");
1449 return r;
1450 }
1451
1452 bytes_transferred += sig_len;
1453
1454 if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR)
1455 {
1456#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
1457 card->cmd_prof.sdio_cmd_from_host_and_clear++;
1458#endif
1459#ifndef CSR_WIFI_DEFER_TH_FLUSH
1460 f_flush_count = 1;
1461#endif
1462 }
1463#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
1464 else if (cmd == SDIO_CMD_FROM_HOST_TRANSFER)
1465 {
1466 card->cmd_prof.sdio_cmd_from_host++;
1467 }
1468 else if (cmd == SDIO_CMD_TO_HOST_TRANSFER)
1469 {
1470 card->cmd_prof.sdio_cmd_to_host++;
1471 }
1472#endif
1473 break;
1474
1475 case SDIO_CMD_PADDING:
1476 break;
1477
1478 default:
1479 unifi_error(card->ospriv, "Unrecognised to-host command: %d\n", cmd);
1480 break;
1481 }
1482
1483 bufptr += chunks_in_buf * card->config_data.sig_frag_size;
1484 pending -= chunks_in_buf;
1485
1486
1487
1488
1489
1490
1491 if (f_flush_count)
1492 {
1493 r = update_to_host_signals_r(card, pending);
1494 if (r != CSR_RESULT_SUCCESS)
1495 {
1496 return r;
1497 }
1498 bytes_transferred = 0;
1499 }
1500 }
1501
1502 if (pending)
1503 {
1504 unifi_warning(card->ospriv, "proc_th_sigs: %d unprocessed\n", pending);
1505 }
1506
1507
1508 if (card->th_buffer.count != pending)
1509 {
1510 r = update_to_host_signals_r(card, pending);
1511 if (r != CSR_RESULT_SUCCESS)
1512 {
1513 return r;
1514 }
1515 }
1516
1517
1518
1519
1520
1521
1522 remaining = card->th_buffer.ptr - bufptr;
1523 if (remaining < 0)
1524 {
1525 unifi_error(card->ospriv, "Processing TH signals overran the buffer\n");
1526 return CSR_RESULT_FAILURE;
1527 }
1528 if (remaining > 0)
1529 {
1530
1531 u8 *d = card->th_buffer.buf;
1532 u8 *s = bufptr;
1533 s32 n = remaining;
1534 while (n--)
1535 {
1536 *d++ = *s++;
1537 }
1538 }
1539 card->th_buffer.ptr = card->th_buffer.buf + remaining;
1540
1541
1542
1543 *processed = 1;
1544 return CSR_RESULT_SUCCESS;
1545}
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562static CsrResult process_clear_slot_command(card_t *card, const u8 *cmdptr)
1563{
1564 u16 data_slot;
1565 s16 slot;
1566
1567 data_slot = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cmdptr + SIZEOF_UINT16);
1568
1569 unifi_trace(card->ospriv, UDBG4, "Processing clear slot cmd, slot=0x%X\n",
1570 data_slot);
1571
1572 slot = data_slot & 0x7FFF;
1573
1574#ifdef CSR_WIFI_HIP_NOISY
1575 unifi_error(card->ospriv, "CMD clear data slot 0x%04x\n", data_slot);
1576#endif
1577
1578 if (data_slot & SLOT_DIR_TO_HOST)
1579 {
1580 if (slot >= card->config_data.num_tohost_data_slots)
1581 {
1582 unifi_error(card->ospriv,
1583 "Invalid to-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n",
1584 slot);
1585 return CSR_RESULT_FAILURE;
1586 }
1587
1588 unifi_warning(card->ospriv, "Unexpected clear to-host data slot cmd: 0x%04x\n",
1589 data_slot);
1590 }
1591 else
1592 {
1593 if (slot >= card->config_data.num_fromhost_data_slots)
1594 {
1595 unifi_error(card->ospriv,
1596 "Invalid from-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n",
1597 slot);
1598 return CSR_RESULT_FAILURE;
1599 }
1600
1601
1602
1603
1604
1605
1606
1607 return CSR_RESULT_SUCCESS;
1608
1609
1610
1611 }
1612
1613 return CSR_RESULT_SUCCESS;
1614}
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637static CsrResult process_bulk_data_command(card_t *card, const u8 *cmdptr,
1638 s16 cmd, u16 len)
1639{
1640 bulk_data_desc_t *bdslot;
1641#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
1642 u8 *host_bulk_data_slot;
1643#endif
1644 bulk_data_cmd_t bdcmd;
1645 s16 offset;
1646 s16 slot;
1647 s16 dir;
1648 CsrResult r;
1649
1650 read_unpack_cmd(cmdptr, &bdcmd);
1651
1652 unifi_trace(card->ospriv, UDBG4, "Processing bulk data cmd %d %s, len=%d, slot=0x%X\n",
1653 cmd, lookup_bulkcmd_name(cmd), len, bdcmd.data_slot);
1654
1655
1656
1657
1658
1659
1660
1661 if (card->sdio_io_block_pad)
1662 {
1663 len = (len + card->sdio_io_block_size - 1) & ~(card->sdio_io_block_size - 1);
1664 unifi_trace(card->ospriv, UDBG4, "Rounded bulk data length up to %d\n", len);
1665 }
1666
1667 slot = bdcmd.data_slot & 0x7FFF;
1668
1669 if (cmd == SDIO_CMD_OVERLAY_TRANSFER)
1670 {
1671 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
1672 }
1673 else
1674 {
1675 if (bdcmd.data_slot & SLOT_DIR_TO_HOST)
1676 {
1677
1678
1679
1680 if (slot >= card->config_data.num_tohost_data_slots)
1681 {
1682 unifi_error(card->ospriv,
1683 "Invalid to-host data slot in SDIO bulk xfr req: %d\n",
1684 slot);
1685 return CSR_RESULT_FAILURE;
1686 }
1687
1688
1689#ifdef CSR_PRE_ALLOC_NET_DATA
1690 r = prealloc_netdata_get(card, &card->to_host_data[slot], len);
1691#else
1692 r = unifi_net_data_malloc(card->ospriv, &card->to_host_data[slot], len);
1693#endif
1694 if (r != CSR_RESULT_SUCCESS)
1695 {
1696 unifi_error(card->ospriv, "Failed to allocate t-h bulk data\n");
1697 return CSR_RESULT_FAILURE;
1698 }
1699
1700 bdslot = &card->to_host_data[slot];
1701
1702
1703 r = unifi_net_dma_align(card->ospriv, bdslot);
1704 if (r != CSR_RESULT_SUCCESS)
1705 {
1706 unifi_error(card->ospriv, "Failed to align t-h bulk data buffer for DMA\n");
1707 return CSR_RESULT_FAILURE;
1708 }
1709 }
1710 else
1711 {
1712
1713
1714 if (slot >= card->config_data.num_fromhost_data_slots)
1715 {
1716 unifi_error(card->ospriv,
1717 "Invalid from-host data slot in SDIO bulk xfr req: %d\n",
1718 slot);
1719 return CSR_RESULT_FAILURE;
1720 }
1721 bdslot = &card->from_host_data[slot].bd;
1722 }
1723 offset = bdcmd.offset;
1724 }
1725
1726 dir = (cmd == SDIO_CMD_TO_HOST_TRANSFER)?
1727 UNIFI_SDIO_READ : UNIFI_SDIO_WRITE;
1728
1729 unifi_trace(card->ospriv, UDBG4,
1730 "Bulk %c %s len=%d, handle %d - slot=%d %p+(%d)\n",
1731 (dir == UNIFI_SDIO_READ)?'R' : 'W',
1732 lookup_bulkcmd_name(cmd),
1733 len,
1734 bdcmd.buffer_handle,
1735 slot, bdslot->os_data_ptr, offset);
1736#ifdef CSR_WIFI_HIP_NOISY
1737 unifi_error(card->ospriv, "Bulk %s len=%d, handle %d - slot=%d %p+(%d)\n",
1738 lookup_bulkcmd_name(cmd),
1739 len,
1740 bdcmd.buffer_handle,
1741 slot, bdslot->os_data_ptr, offset);
1742#endif
1743
1744
1745 if (bdslot->os_data_ptr == NULL)
1746 {
1747 unifi_error(card->ospriv, "Null os_data_ptr - Bulk %s handle %d - slot=%d o=(%d)\n",
1748 lookup_bulkcmd_name(cmd),
1749 bdcmd.buffer_handle,
1750 slot,
1751 offset);
1752 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
1753 }
1754
1755#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
1756
1757
1758
1759 if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3))
1760 {
1761 host_bulk_data_slot = kmalloc(len, GFP_KERNEL);
1762
1763 if (!host_bulk_data_slot)
1764 {
1765 unifi_error(card->ospriv, " failed to allocate request_data before unifi_bulk_rw\n");
1766 return -1;
1767 }
1768
1769 memcpy((void *)host_bulk_data_slot,
1770 (void *)(bdslot->os_data_ptr + offset), len);
1771
1772 r = unifi_bulk_rw(card,
1773 bdcmd.buffer_handle,
1774 (void *)host_bulk_data_slot,
1775 len,
1776 dir);
1777 }
1778 else
1779#endif
1780 {
1781 r = unifi_bulk_rw(card,
1782 bdcmd.buffer_handle,
1783 (void *)(bdslot->os_data_ptr + offset),
1784 len,
1785 dir);
1786 }
1787
1788 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
1789 {
1790 return r;
1791 }
1792 if (r != CSR_RESULT_SUCCESS)
1793 {
1794 unifi_error(card->ospriv,
1795 "Failed: %s hlen=%d, slen=%d, handle %d - slot=%d %p+0x%X\n",
1796 lookup_bulkcmd_name(cmd),
1797 len,
1798 bdslot->data_length,
1799 bdcmd.buffer_handle,
1800 slot, bdslot->os_data_ptr, offset);
1801 return r;
1802 }
1803
1804 bdslot->data_length = len;
1805
1806 if (cmd == SDIO_CMD_FROM_HOST_AND_CLEAR)
1807 {
1808 if (slot >= card->config_data.num_fromhost_data_slots)
1809 {
1810 unifi_error(card->ospriv,
1811 "Invalid from-host data slot in SDIO_CMD_FROM_HOST_AND_CLEAR: %d\n",
1812 slot);
1813 return CSR_RESULT_FAILURE;
1814 }
1815
1816#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
1817
1818 if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3))
1819 {
1820 kfree(host_bulk_data_slot);
1821 }
1822#endif
1823
1824 if (card->fh_slot_host_tag_record)
1825 {
1826 unifi_trace(card->ospriv, UDBG5, "CopyFromHostAndClearSlot Reset entry for slot=%d\n", slot);
1827
1828
1829 card->fh_slot_host_tag_record[slot] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
1830 }
1831
1832
1833
1834 CardClearFromHostDataSlot(card, slot);
1835 }
1836
1837 return CSR_RESULT_SUCCESS;
1838}
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space_fh)
1859{
1860 u32 count_fhw;
1861 u32 occupied_fh, slots_fh;
1862 s32 count_fhr;
1863
1864 count_fhw = card->from_host_signals_w;
1865 count_fhr = card->from_host_signals_r;
1866 slots_fh = card->config_data.num_fromhost_sig_frags;
1867
1868
1869 occupied_fh = (count_fhw - count_fhr) % 128;
1870
1871 if (slots_fh < occupied_fh)
1872 {
1873 *space_fh = 0;
1874 }
1875 else
1876 {
1877 *space_fh = slots_fh - occupied_fh;
1878 }
1879
1880 if ((occupied_fh != 0) && (*space_fh < needed))
1881 {
1882 count_fhr = unifi_read_shared_count(card, card->sdio_ctrl_addr + 2);
1883 if (count_fhr < 0)
1884 {
1885 unifi_error(card->ospriv, "Failed to read from-host sig read count\n");
1886 return CSR_RESULT_FAILURE;
1887 }
1888 card->from_host_signals_r = count_fhr;
1889
1890 occupied_fh = (count_fhw - count_fhr) % 128;
1891 *space_fh = slots_fh - occupied_fh;
1892 }
1893
1894 return CSR_RESULT_SUCCESS;
1895}
1896
1897
1898
1899
1900
1901
1902#define ROUND_UP_NEEDED_CHUNKS(_card, _needed_chunks) \
1903 { \
1904 u16 _chunks_per_block; \
1905 u16 _chunks_in_last_block; \
1906 \
1907 if (_card->sdio_io_block_pad) \
1908 { \
1909 _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \
1910 _chunks_in_last_block = _needed_chunks % _chunks_per_block; \
1911 if (_chunks_in_last_block != 0) \
1912 { \
1913 _needed_chunks = _needed_chunks + (_chunks_per_block - _chunks_in_last_block); \
1914 } \
1915 } \
1916 }
1917
1918
1919#define ROUND_UP_SPACE_CHUNKS(_card, _space_chunks) \
1920 { \
1921 u16 _chunks_per_block; \
1922 \
1923 if (_card->sdio_io_block_pad) \
1924 { \
1925 _chunks_per_block = _card->sdio_io_block_size / _card->config_data.sig_frag_size; \
1926 _space_chunks = ((_space_chunks / _chunks_per_block) * _chunks_per_block); \
1927 } \
1928 }
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed)
1960{
1961 q_t *sigq = &card->fh_command_queue;
1962
1963 CsrResult r;
1964 u16 pending_sigs;
1965 u16 pending_chunks;
1966 u16 needed_chunks;
1967 s32 space_chunks;
1968 u16 q_index;
1969
1970 *processed = 0;
1971
1972
1973 pending_sigs = CSR_WIFI_HIP_Q_SLOTS_USED(sigq);
1974 unifi_trace(card->ospriv, UDBG5, "proc_fh: %d pending\n", pending_sigs);
1975 if (pending_sigs == 0)
1976 {
1977
1978 return CSR_RESULT_SUCCESS;
1979 }
1980
1981
1982 for (pending_chunks = 0, q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq);
1983 q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq);
1984 q_index = CSR_WIFI_HIP_Q_WRAP(sigq, q_index + 1))
1985 {
1986 card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index);
1987
1988
1989
1990
1991
1992 pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
1993 }
1994
1995
1996
1997
1998
1999 needed_chunks = pending_chunks + card->fh_buffer.count;
2000
2001
2002 ROUND_UP_NEEDED_CHUNKS(card, needed_chunks);
2003
2004 r = check_fh_sig_slots(card, needed_chunks, &space_chunks);
2005 if (r != CSR_RESULT_SUCCESS)
2006 {
2007
2008 unifi_error(card->ospriv, "Failed to read fh sig count\n");
2009 return r;
2010 }
2011
2012#ifdef CSR_WIFI_HIP_NOISY
2013 unifi_error(card->ospriv, "proc_fh: %d chunks free, need %d\n",
2014 space_chunks, needed_chunks);
2015#endif
2016
2017
2018
2019
2020
2021
2022 if (needed_chunks > (u16)space_chunks)
2023 {
2024
2025 ROUND_UP_SPACE_CHUNKS(card, space_chunks);
2026
2027
2028
2029
2030
2031 if ((u16)space_chunks <= card->fh_buffer.count)
2032 {
2033
2034
2035
2036
2037 unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n",
2038 card->fh_buffer.count, space_chunks);
2039 card->generate_interrupt = 1;
2040 return CSR_RESULT_SUCCESS;
2041 }
2042 pending_chunks = (u16)(space_chunks - card->fh_buffer.count);
2043 }
2044
2045 while (pending_sigs-- && pending_chunks > 0)
2046 {
2047 card_signal_t *csptr;
2048 s16 i;
2049 u16 sig_chunks, total_length, free_chunks_in_fh_buffer;
2050 bulk_data_param_t bulkdata;
2051 u8 *packed_sigptr;
2052 u16 signal_length = 0;
2053
2054
2055 q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq);
2056
2057
2058 csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index);
2059
2060
2061 signal_length = csptr->signal_length;
2062
2063 if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE))
2064 {
2065 unifi_error(card->ospriv, "process_fh_queue: Bad len: %d\n", signal_length);
2066 return CSR_RESULT_FAILURE;
2067 }
2068
2069
2070 sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2));
2071
2072 free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size,
2073 (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr));
2074 if (free_chunks_in_fh_buffer < sig_chunks)
2075 {
2076
2077 unifi_notice(card->ospriv, "proc_fh_cmd_q: no room in fh buffer for 0x%.4X, deferring\n",
2078 (u16)(GET_SIGNAL_ID(csptr->sigbuf)));
2079 break;
2080 }
2081
2082 packed_sigptr = csptr->sigbuf;
2083
2084
2085 if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, UNIFI_TRAFFIC_Q_MLME))
2086 {
2087 unifi_notice(card->ospriv, "proc_fh_cmd_q: no fh data slots for 0x%.4X, deferring\n",
2088 (u16)(GET_SIGNAL_ID(csptr->sigbuf)));
2089 break;
2090 }
2091
2092 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++)
2093 {
2094 if (csptr->bulkdata[i].data_length == 0)
2095 {
2096 UNIFI_INIT_BULK_DATA(&bulkdata.d[i]);
2097 }
2098 else
2099 {
2100 bulkdata.d[i].os_data_ptr = csptr->bulkdata[i].os_data_ptr;
2101 bulkdata.d[i].data_length = csptr->bulkdata[i].data_length;
2102 }
2103
2104
2105 UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]);
2106 }
2107
2108 unifi_trace(card->ospriv, UDBG2, "Sending signal 0x%.4X\n",
2109 GET_SIGNAL_ID(packed_sigptr));
2110#ifdef CSR_WIFI_HIP_NOISY
2111 unifi_error(card->ospriv, "Sending signal 0x%.4X\n",
2112 GET_SIGNAL_ID(packed_sigptr));
2113#endif
2114
2115
2116
2117 total_length = sig_chunks * card->config_data.sig_frag_size;
2118
2119 card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff);
2120 card->fh_buffer.ptr[1] =
2121 (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4));
2122
2123 memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length);
2124 memset(card->fh_buffer.ptr + 2 + signal_length, 0,
2125 total_length - (2 + signal_length));
2126
2127#ifdef CSR_WIFI_HIP_NOISY
2128 unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n",
2129 signal_length + 2);
2130 dump(card->fh_buffer.ptr, signal_length + 2);
2131 unifi_trace(card->ospriv, UDBG1, " \n");
2132#endif
2133
2134 card->fh_buffer.ptr += total_length;
2135 card->fh_buffer.count += sig_chunks;
2136
2137#ifdef CSR_WIFI_HIP_NOISY
2138 unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n",
2139 signal_length,
2140 card->fh_buffer.ptr - card->fh_buffer.buf,
2141 card->fh_buffer.count);
2142#endif
2143
2144 (*processed)++;
2145 pending_chunks -= sig_chunks;
2146
2147
2148
2149
2150 if (card->udi_hook)
2151 {
2152 (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length,
2153 &bulkdata, UDI_LOG_FROM_HOST);
2154 }
2155
2156
2157 csptr->signal_length = 0;
2158 CSR_WIFI_HIP_Q_INC_R(sigq);
2159 }
2160
2161 return CSR_RESULT_SUCCESS;
2162}
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed)
2188{
2189 q_t *sigq = card->fh_traffic_queue;
2190
2191 CsrResult r;
2192 s16 n = 0;
2193 s32 q_no;
2194 u16 pending_sigs = 0;
2195 u16 pending_chunks = 0;
2196 u16 needed_chunks;
2197 s32 space_chunks;
2198 u16 q_index;
2199 u32 host_tag = 0;
2200 u16 slot_num = 0;
2201
2202 *processed = 0;
2203
2204
2205 for (n = UNIFI_NO_OF_TX_QS - 1; n >= 0; n--)
2206 {
2207
2208 pending_sigs += CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[n]);
2209 unifi_trace(card->ospriv, UDBG5, "proc_fh%d: %d pending\n", n, pending_sigs);
2210
2211
2212 for (q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[n]);
2213 q_index != CSR_WIFI_HIP_Q_NEXT_W_SLOT(&sigq[n]);
2214 q_index = CSR_WIFI_HIP_Q_WRAP(&sigq[n], q_index + 1))
2215 {
2216 card_signal_t *csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[n], q_index);
2217
2218
2219
2220
2221
2222 pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
2223 }
2224 }
2225
2226
2227 if (pending_sigs == 0)
2228 {
2229
2230 return CSR_RESULT_SUCCESS;
2231 }
2232
2233
2234
2235
2236
2237 needed_chunks = pending_chunks + card->fh_buffer.count;
2238
2239
2240 ROUND_UP_NEEDED_CHUNKS(card, needed_chunks);
2241
2242 r = check_fh_sig_slots(card, needed_chunks, &space_chunks);
2243 if (r != CSR_RESULT_SUCCESS)
2244 {
2245
2246 unifi_error(card->ospriv, "Failed to read fh sig count\n");
2247 return r;
2248 }
2249
2250#ifdef CSR_WIFI_HIP_NOISY
2251 unifi_error(card->ospriv,
2252 "process_fh_traffic_queue: %d chunks free, need %d\n",
2253 space_chunks, needed_chunks);
2254 read_fhsr(card);
2255#endif
2256
2257
2258
2259 if (needed_chunks > (u16)space_chunks)
2260 {
2261
2262 ROUND_UP_SPACE_CHUNKS(card, space_chunks);
2263
2264 if ((u16)space_chunks <= card->fh_buffer.count)
2265 {
2266
2267
2268
2269
2270 unifi_error(card->ospriv, "not enough room to send signals, need %d chunks, %d free\n",
2271 card->fh_buffer.count, space_chunks);
2272 card->generate_interrupt = 1;
2273 return 0;
2274 }
2275
2276 pending_chunks = (u16)space_chunks - card->fh_buffer.count;
2277 }
2278
2279 q_no = UNIFI_NO_OF_TX_QS - 1;
2280
2281
2282
2283
2284
2285
2286
2287 do
2288 {
2289 card_signal_t *csptr;
2290 u16 sig_chunks, total_length, free_chunks_in_fh_buffer;
2291 bulk_data_param_t bulkdata;
2292 u8 *packed_sigptr;
2293 u16 signal_length = 0;
2294
2295
2296 if (CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[q_no]) == 0)
2297 {
2298 q_no--;
2299 continue;
2300 }
2301
2302
2303 q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[q_no]);
2304
2305
2306 csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[q_no], q_index);
2307
2308
2309 signal_length = csptr->signal_length;
2310
2311 if ((signal_length & 1) || (signal_length > UNIFI_PACKED_SIGBUF_SIZE))
2312 {
2313 unifi_error(card->ospriv, "process_fh_traffic_queue: Bad len: %d\n", signal_length);
2314 return CSR_RESULT_FAILURE;
2315 }
2316
2317
2318 sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2));
2319 free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size,
2320 (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr));
2321 if (free_chunks_in_fh_buffer < sig_chunks)
2322 {
2323
2324 unifi_notice(card->ospriv, "process_fh_traffic_queue: no more chunks.\n");
2325 break;
2326 }
2327
2328 packed_sigptr = csptr->sigbuf;
2329
2330 if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, (unifi_TrafficQueue)q_no))
2331 {
2332 q_no--;
2333 continue;
2334 }
2335
2336
2337 if ((csptr->bulkdata[0].data_length == 0) || (csptr->bulkdata[0].os_data_ptr == NULL))
2338 {
2339 unifi_error(card->ospriv, "MA-PACKET.req with empty bulk data (%d bytes in %p)\n",
2340 csptr->bulkdata[0].data_length, csptr->bulkdata[0].os_data_ptr);
2341 dump(packed_sigptr, signal_length);
2342 return CSR_RESULT_FAILURE;
2343 }
2344
2345 bulkdata.d[0].os_data_ptr = csptr->bulkdata[0].os_data_ptr;
2346 bulkdata.d[0].data_length = csptr->bulkdata[0].data_length;
2347 bulkdata.d[0].os_net_buf_ptr = csptr->bulkdata[0].os_net_buf_ptr;
2348 bulkdata.d[0].net_buf_length = csptr->bulkdata[0].net_buf_length;
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363 if (card->fh_slot_host_tag_record)
2364 {
2365
2366 host_tag = GET_PACKED_MA_PACKET_REQUEST_HOST_TAG(packed_sigptr);
2367 slot_num = GET_PACKED_DATAREF_SLOT(packed_sigptr, 0) & 0x00FF;
2368
2369 unifi_trace(card->ospriv, UDBG5,
2370 "process_fh_traffic_queue signal ID =%x fh slot=%x Host tag =%x\n",
2371 GET_SIGNAL_ID(packed_sigptr), slot_num, host_tag);
2372 card->fh_slot_host_tag_record[slot_num] = host_tag;
2373 }
2374 UNIFI_INIT_BULK_DATA(&bulkdata.d[1]);
2375 UNIFI_INIT_BULK_DATA(&csptr->bulkdata[0]);
2376 UNIFI_INIT_BULK_DATA(&csptr->bulkdata[1]);
2377
2378#ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
2379 if (bulkdata.d[0].os_data_ptr)
2380 {
2381 if ((*bulkdata.d[0].os_data_ptr) & 0x08)
2382 {
2383 card->cmd_prof.tx_count++;
2384 }
2385 }
2386#endif
2387 unifi_trace(card->ospriv, UDBG3, "Sending signal 0x%.4X\n",
2388 GET_SIGNAL_ID(packed_sigptr));
2389#ifdef CSR_WIFI_HIP_NOISY
2390 unifi_error(card->ospriv, "Sending signal 0x%.4X\n",
2391 GET_SIGNAL_ID(packed_sigptr));
2392#endif
2393
2394
2395 total_length = sig_chunks * card->config_data.sig_frag_size;
2396
2397 card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff);
2398 card->fh_buffer.ptr[1] =
2399 (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4));
2400
2401 memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length);
2402 memset(card->fh_buffer.ptr + 2 + signal_length, 0,
2403 total_length - (2 + signal_length));
2404
2405#ifdef CSR_WIFI_HIP_NOISY
2406 unifi_error(card->ospriv, "proc_fh: fh_buffer %d bytes \n",
2407 signal_length + 2);
2408 dump(card->fh_buffer.ptr, signal_length + 2);
2409 unifi_trace(card->ospriv, UDBG1, " \n");
2410#endif
2411
2412 card->fh_buffer.ptr += total_length;
2413 card->fh_buffer.count += sig_chunks;
2414
2415#ifdef CSR_WIFI_HIP_NOISY
2416 unifi_error(card->ospriv, "Added %d to fh buf, len now %d, count %d\n",
2417 signal_length,
2418 card->fh_buffer.ptr - card->fh_buffer.buf,
2419 card->fh_buffer.count);
2420#endif
2421
2422 (*processed)++;
2423 pending_sigs--;
2424 pending_chunks -= sig_chunks;
2425
2426
2427
2428
2429 if (card->udi_hook)
2430 {
2431 (*card->udi_hook)(card->ospriv, packed_sigptr, signal_length,
2432 &bulkdata, UDI_LOG_FROM_HOST);
2433 }
2434
2435
2436 csptr->signal_length = 0;
2437
2438 csptr->bulkdata[0].data_length = 0;
2439
2440 CSR_WIFI_HIP_Q_INC_R(&sigq[q_no]);
2441 } while ((pending_sigs > 0) && (pending_chunks > 0) && (q_no >= 0));
2442
2443 return CSR_RESULT_SUCCESS;
2444}
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460static CsrResult flush_fh_buffer(card_t *card)
2461{
2462 CsrResult r;
2463 u16 len;
2464 u16 sig_units;
2465 u16 data_round;
2466 u16 chunks_in_last_block;
2467 u16 padding_chunks;
2468 u16 i;
2469
2470 len = card->fh_buffer.ptr - card->fh_buffer.buf;
2471
2472#ifdef CSR_WIFI_HIP_NOISY
2473 unifi_error(card->ospriv, "fh_buffer is at %p, ptr= %p\n",
2474 card->fh_buffer.buf, card->fh_buffer.ptr);
2475#endif
2476
2477 if (len == 0)
2478 {
2479 return CSR_RESULT_SUCCESS;
2480 }
2481
2482#ifdef CSR_WIFI_HIP_NOISY
2483 if (dump_fh_buf)
2484 {
2485 dump(card->fh_buffer.buf, len);
2486 dump_fh_buf = 0;
2487 }
2488#endif
2489
2490 if (card->sdio_io_block_pad)
2491 {
2492
2493 sig_units = card->config_data.sig_frag_size;
2494 data_round = card->sdio_io_block_size;
2495
2496 if (data_round > sig_units)
2497 {
2498 chunks_in_last_block = (len % data_round) / sig_units;
2499
2500 if (chunks_in_last_block != 0)
2501 {
2502 padding_chunks = (data_round / sig_units) - chunks_in_last_block;
2503
2504 memset(card->fh_buffer.ptr, 0, padding_chunks * sig_units);
2505 for (i = 0; i < padding_chunks; i++)
2506 {
2507 card->fh_buffer.ptr[1] = SDIO_CMD_PADDING << 4;
2508 card->fh_buffer.ptr += sig_units;
2509 }
2510
2511 card->fh_buffer.count += padding_chunks;
2512 len += padding_chunks * sig_units;
2513 }
2514 }
2515 }
2516
2517 r = unifi_bulk_rw(card,
2518 card->config_data.fromhost_sigbuf_handle,
2519 card->fh_buffer.buf,
2520 len, UNIFI_SDIO_WRITE);
2521 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
2522 {
2523 return r;
2524 }
2525 if (r != CSR_RESULT_SUCCESS)
2526 {
2527 unifi_error(card->ospriv, "Failed to write fh signals: %u bytes, error %d\n", len, r);
2528 return r;
2529 }
2530
2531
2532 card->from_host_signals_w =
2533 (card->from_host_signals_w + card->fh_buffer.count) % 128u;
2534 r = unifi_write_8_or_16(card, card->sdio_ctrl_addr + 0,
2535 (u8)card->from_host_signals_w);
2536 if (r != CSR_RESULT_SUCCESS)
2537 {
2538 unifi_error(card->ospriv, "Failed to write fh signal count %u with error %d\n",
2539 card->from_host_signals_w, r);
2540 return r;
2541 }
2542 card->generate_interrupt = 1;
2543
2544
2545 card->fh_buffer.ptr = card->fh_buffer.buf;
2546 card->fh_buffer.count = 0;
2547
2548#ifdef CSR_WIFI_HIP_NOISY
2549 unifi_error(card->ospriv, "END flush: fh len %d, count %d\n",
2550 card->fh_buffer.ptr - card->fh_buffer.buf,
2551 card->fh_buffer.count);
2552#endif
2553
2554 return CSR_RESULT_SUCCESS;
2555}
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573static void restart_packet_flow(card_t *card)
2574{
2575 u8 q;
2576
2577
2578
2579
2580
2581 for (q = 0; q <= UNIFI_TRAFFIC_Q_VO; q++)
2582 {
2583 if (card_is_tx_q_paused(card, q) &&
2584 CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_traffic_queue[q]) >= RESUME_XMIT_THRESHOLD)
2585 {
2586#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
2587 unifi_debug_log_to_buf("U");
2588#endif
2589 card_tx_q_unpause(card, q);
2590 unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue)q);
2591 }
2592 }
2593}
2594
2595
2596