Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes
[pandora-kernel.git] / drivers / staging / csr / csr_wifi_hip_card_sdio_intr.c
1 /*****************************************************************************
2
3             (c) Cambridge Silicon Radio Limited 2012
4             All rights reserved and confidential information of CSR
5
6             Refer to LICENSE.txt included with this source for details
7             on the license terms.
8
9 *****************************************************************************/
10
11 /*
12  * ---------------------------------------------------------------------------
13  *  FILE:     csr_wifi_hip_card_sdio_intr.c
14  *
15  *  PURPOSE:
16  *      Interrupt processing for the UniFi SDIO driver.
17  *
18  *      We may need another signal queue of responses to UniFi to hold
19  *      bulk data commands generated by read_to_host_signals().
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  * If the SDIO link is idle for this time (in milliseconds),
33  * signal UniFi to go into Deep Sleep.
34  * Valid return value of unifi_bh().
35  */
36 #define UNIFI_DEFAULT_HOST_IDLE_TIMEOUT 5
37 /*
38  * If the UniFi has not woken up for this time (in milliseconds),
39  * signal the bottom half to take action.
40  * Valid return value of unifi_bh().
41  */
42 #define UNIFI_DEFAULT_WAKE_TIMEOUT      1000
43
44
45 static CsrResult process_bh(card_t *card);
46 static CsrResult handle_host_protocol(card_t *card, u8 *processed_something);
47
48 static CsrResult flush_fh_buffer(card_t *card);
49
50 static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space);
51
52 static CsrResult read_to_host_signals(card_t *card, s32 *processed);
53 static CsrResult process_to_host_signals(card_t *card, s32 *processed);
54
55 static CsrResult process_bulk_data_command(card_t *card,
56                                            const u8 *cmdptr,
57                                            s16 cmd, u16 len);
58 static CsrResult process_clear_slot_command(card_t         *card,
59                                             const u8 *cmdptr);
60 static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed);
61 static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed);
62 static void restart_packet_flow(card_t *card);
63 static CsrResult process_clock_request(card_t *card);
64
65 #ifdef CSR_WIFI_HIP_NOISY
66 s16 dump_fh_buf = 0;
67 #endif /* CSR_WIFI_HIP_NOISY */
68
69 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
70
71 /*
72  * The unifi_debug_output buffer can be used to debug the HIP behaviour offline
73  * i.e. without using the tracing functions that change the timing.
74  *
75  * Call unifi_debug_log_to_buf() with printf arguments to store a string into
76  * unifi_debug_output. When unifi_debug_buf_dump() is called, the contents of the
77  * buffer are dumped with dump_str() which has to be implemented in the
78  * OS layer, during the porting exercise. The offset printed, holds the
79  * offset where the last character is (always a zero).
80  *
81  */
82
83 #define UNIFI_DEBUG_GBUFFER_SIZE       8192
84 static char unifi_debug_output[UNIFI_DEBUG_GBUFFER_SIZE];
85 static char *unifi_dbgbuf_ptr = unifi_debug_output;
86 static char *unifi_dbgbuf_start = unifi_debug_output;
87
88 static void append_char(char c)
89 {
90     /* write char and advance pointer */
91     *unifi_dbgbuf_ptr++ = c;
92     /* wrap pointer at end of buffer */
93     if ((unifi_dbgbuf_ptr - unifi_debug_output) >= UNIFI_DEBUG_GBUFFER_SIZE)
94     {
95         unifi_dbgbuf_ptr = unifi_debug_output;
96     }
97 } /* append_char() */
98
99
100 void 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     /* Update start-of-buffer pointer */
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
117 void 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 } /* unifi_debug_log_to_buf() */
129
130
131 /* Convert signed 32 bit (or less) integer to string */
132 static 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  *  unifi_debug_hex_to_buf
150  *
151  *  puts the contents of the passed buffer into the debug buffer as a hex string
152  *
153  *  Arguments:
154  *      buff         buffer to print as hex
155  *      length       number of chars to print
156  *
157  *  Returns:
158  *      None.
159  *
160  * ---------------------------------------------------------------------------
161  */
162 void 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
175 void 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 } /* unifi_debug_buf_dump() */
183
184
185 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
186
187 #ifdef CSR_PRE_ALLOC_NET_DATA
188 #define NETDATA_PRE_ALLOC_BUF_SIZE 8000
189
190 void 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
208 CsrResult 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
231 static 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  *  unifi_sdio_interrupt_handler
275  *
276  *      This function should be called by the OS-dependent code to handle
277  *      an SDIO interrupt from the UniFi.
278  *
279  *  Arguments:
280  *      card            Pointer to card context structure.
281  *
282  *  Returns:
283  *      None.
284  *
285  *  Notes: This function may be called in DRS context. In this case,
286  *         tracing with the unifi_trace(), etc, is not allowed.
287  * ---------------------------------------------------------------------------
288  */
289 void unifi_sdio_interrupt_handler(card_t *card)
290 {
291     /*
292      * Set the flag to say reason for waking was SDIO interrupt.
293      * Then ask the OS layer to run the unifi_bh to give attention to the UniFi.
294      */
295     card->bh_reason_unifi = 1;
296     (void)unifi_run_bh(card->ospriv);
297 } /*  sdio_interrupt_handler() */
298
299
300 /*
301  * ---------------------------------------------------------------------------
302  *  unifi_configure_low_power_mode
303  *
304  *      This function should be called by the OS-dependent when
305  *      the deep sleep signaling needs to be enabled or disabled.
306  *
307  *  Arguments:
308  *      card            Pointer to card context structure.
309  *      low_power_mode  Disable/Enable the deep sleep signaling
310  *      periodic_wake_mode UniFi wakes host periodically.
311  *
312  *  Returns:
313  *      CSR_RESULT_SUCCESS on success or a CSR error code.
314  * ---------------------------------------------------------------------------
315  */
316 CsrResult 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 } /* unifi_configure_low_power_mode() */
331
332
333 /*
334  * ---------------------------------------------------------------------------
335  *  unifi_force_low_power_mode
336  *
337  *      This function should be called by the OS-dependent when
338  *      UniFi needs to be set to the low power mode (e.g. on suspend)
339  *
340  *  Arguments:
341  *      card            Pointer to card context structure.
342  *
343  *  Returns:
344  *      CSR_RESULT_SUCCESS on success or a CSR error code.
345  * ---------------------------------------------------------------------------
346  */
347 CsrResult 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 } /* unifi_force_low_power_mode() */
357
358
359 /*
360  * ---------------------------------------------------------------------------
361  *  unifi_bh
362  *
363  *      This function should be called by the OS-dependent code when
364  *      host and/or UniFi has requested an exchange of messages.
365  *
366  *  Arguments:
367  *      card            Pointer to card context structure.
368  *
369  *  Returns:
370  *      CSR_RESULT_SUCCESS on success or a CSR error code.
371  * ---------------------------------------------------------------------------
372  */
373 CsrResult 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     /* Process request to raise the maximum SDIO clock */
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      * Why was the BH thread woken?
393      * If it was an SDIO interrupt, UniFi is awake and we need to process it.
394      * If it was a host process queueing data, then we need to awaken UniFi.
395      *
396      * Priority of flags is top down.
397      *
398      * ----------------------------------------------------------+
399      *    \state|   AWAKE      |    DROWSY      |    TORPID      |
400      * flag\    |              |                |                |
401      * ---------+--------------+----------------+----------------|
402      *          | do the host  | go to AWAKE and| go to AWAKE and|
403      *   unifi  | protocol     | do the host    | do the host    |
404      *          |              | protocol       | protocol       |
405      * ---------+--------------+----------------+----------------|
406      *          | do the host  |                |                |
407      *   host   | protocol     |  do nothing    | go to DROWSY   |
408      *          |              |                |                |
409      * ---------+--------------+----------------+----------------|
410      *          |              |                | should not     |
411      *  timeout | go to TORPID | error, unifi   | occur          |
412      *          |              | didn't wake up | do nothing     |
413      * ----------------------------------------------------------+
414      *
415      * Note that if we end up in the AWAKE state we always do the host protocol.
416      */
417
418     do
419     {
420         /*
421          * When the host state is set to DROWSY, then we can not disable the
422          * interrupts as UniFi can generate an interrupt even when the INT_ENABLE
423          * register has the interrupts disabled. This interrupt will be lost.
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              * An interrupt may occur while or after we cache the reason.
431              * This interrupt will cause the unifi_bh() to be scheduled again.
432              * Any interrupt that has happened before the register is read
433              * and is considered spurious has to acknowledged.
434              */
435             reason_unifi = card->bh_reason_unifi;
436
437             /*
438              * If an interrupt is received, check if it was a real one,
439              * set the host state to AWAKE and run the BH.
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              * If an chip is in TORPID, and the host wants to wake it up,
467              * set the host state to DROWSY and wait for the wake-up interrupt.
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                      * set the timeout value to UNIFI_DEFAULT_WAKE_TIMEOUT
476                      * to capture a wake error.
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              * If the chip is in DROWSY, and the timeout expires,
488              * we need to reset the chip. This should never occur.
489              * (If it does, check that the calling thread set "remaining"
490              * according to the time remaining when unifi_bh() was called).
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                  * Check if Function1 has gone away or
498                  * if we missed an SDIO interrupt.
499                  */
500                 r = unifi_check_io_status(card, &iostate);
501                 if (r == CSR_WIFI_HIP_RESULT_NO_DEVICE)
502                 {
503                     goto exit;
504                 }
505                 /* Need to reset and reboot */
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         /* No need to run the host protocol */
530         return CSR_RESULT_SUCCESS;
531     } while (0);
532
533
534     /* Disable the SDIO interrupts while doing SDIO ops */
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     /* Now that the interrupts are disabled, ack the interrupt */
549     CsrSdioInterruptAcknowledge(card->sdio_if);
550
551     /* Run the HIP */
552     r = process_bh(card);
553     if (r != CSR_RESULT_SUCCESS)
554     {
555         goto exit;
556     }
557
558     /*
559      * If host is now idle, schedule a timer for the delay before we
560      * let UniFi go into deep sleep.
561      * If the timer goes off, we will move to TORPID state.
562      * If UniFi raises an interrupt in the meantime, we will cancel
563      * the timer and start a new one when we become idle.
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         /* return the UNIFI_DEFAULT_HOST_IDLE_TIMEOUT, so we can go to sleep. */
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
609 exit:
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         /* If an interrupt has been raised, ack it here */
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         /* Try to capture firmware panic codes */
633         (void)unifi_capture_panic(card);
634
635         /* Ask for a mini-coredump when the driver has reset UniFi */
636         (void)unifi_coredump_request_at_next_reset(card, 1);
637     }
638
639     return r;
640 } /* unifi_bh() */
641
642
643 /*
644  * ---------------------------------------------------------------------------
645  *  process_clock_request
646  *
647  *      Handle request from the OS layer to increase the SDIO clock speed.
648  *      The fast clock is limited until the firmware has indicated that it has
649  *      completed initialisation to the OS layer.
650  *
651  *  Arguments:
652  *      card            Pointer to card context structure.
653  *
654  *  Returns:
655  *      CSR_RESULT_SUCCESS on success or CSR error code.
656  * ---------------------------------------------------------------------------
657  */
658 static 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;   /* No pending request */
666     }
667
668     /*
669      * The SDIO clock speed request from the OS layer is only acted upon if
670      * the UniFi is awake. If it was in any other state, the clock speed will
671      * transition through SAFE to MAX while the host wakes it up, and the
672      * final speed reached will be UNIFI_SDIO_CLOCK_MAX_HZ.
673      * This assumes that the SME never requests low power mode while the f/w
674      * initialisation takes place.
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;  /* log the new freq */
687         }
688     }
689     else
690     {
691         unifi_trace(card->ospriv, UDBG1, "Will set SDIO max clock after wakeup\n");
692     }
693
694     /* Cancel the request now that it has been acted upon, or is about to be
695      * by the wakeup mechanism
696      */
697     card->request_max_clock = 0;
698
699     return r;
700 }
701
702
703 /*
704  * ---------------------------------------------------------------------------
705  *  process_bh
706  *
707  *      Exchange messages with UniFi
708  *
709  *  Arguments:
710  *      card            Pointer to card context structure.
711  *
712  *  Returns:
713  *      CSR_RESULT_SUCCESS on success or CSR error code.
714  * ---------------------------------------------------------------------------
715  */
716 static CsrResult process_bh(card_t *card)
717 {
718     CsrResult r;
719     u8 more;
720     more = FALSE;
721
722     /* Process the reasons (interrupt, signals) */
723     do
724     {
725         /*
726          * Run in a while loop, to save clearing the interrupts
727          * every time around the outside loop.
728          */
729         do
730         {
731             /* If configured to run the HIP just once, skip first loop */
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         /* Acknowledge the h/w interrupt */
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          * UniFi may have tried to generate an interrupt during the
786          * CardClearInt() was running. So, we need to run the host
787          * protocol again, to check if there are any pending requests.
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         /* If configured to run the HIP just once, work is now done */
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 } /* process_bh() */
842
843
844 /*
845  * ---------------------------------------------------------------------------
846  *  handle_host_protocol
847  *
848  *      This function implements the Host Interface Protocol (HIP) as
849  *      described in the Host Interface Protocol Specification.
850  *
851  *  Arguments:
852  *      card                 Pointer to card context structure.
853  *      processed_something  Pointer to location to update processing status:
854  *                              TRUE when data was transferred
855  *                              FALSE when no data was transferred (queues empty)
856  *
857  *  Returns:
858  *      CSR_RESULT_SUCCESS on success or CSR error code.
859  * ---------------------------------------------------------------------------
860  */
861 static 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 /* CSR_WIFI_HIP_NOISY */
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      * (Re)fill the T-H signal buffer
882      */
883     r = read_to_host_signals(card, &done);
884     if (r != CSR_RESULT_SUCCESS)
885     {
886         unifi_error(card->ospriv, "Error occured reading to-host signals\n");
887         return r;
888     }
889     if (done > 0)
890     {
891         *processed_something = TRUE;
892     }
893
894     /*
895      * Process any to-host signals.
896      * Perform any requested CMD53 transfers here, but just queue any
897      * bulk data command responses.
898      */
899     r = process_to_host_signals(card, &done);
900     if (r != CSR_RESULT_SUCCESS)
901     {
902         unifi_error(card->ospriv, "Error occured processing to-host signals\n");
903         return r;
904     }
905
906     /* Now send any signals in the F-H queues */
907     /* Give precedence to the command queue */
908     r = process_fh_cmd_queue(card, &done);
909     if (r != CSR_RESULT_SUCCESS)
910     {
911         unifi_error(card->ospriv, "Error occured 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 occured processing from-host data signals\n");
923         return r;
924     }
925     if (done > 0)
926     {
927         *processed_something = TRUE;
928     }
929
930     /* Flush out the batch of signals to the UniFi. */
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      * Send the host interrupt to say the queues have been modified.
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     /* See if we can re-enable transmission now */
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      * Don't put the thread sleep if we just interacted with the chip,
972      * there might be more to do if we look again.
973      */
974     return r;
975 } /* handle_host_protocol() */
976
977
978 /*
979  *      Rounds the given signal length in bytes to a whole number
980  *      of sig_frag_size.
981  */
982 #define GET_CHUNKS_FOR(SIG_FRAG_SIZE, LENGTH) (((LENGTH) + ((SIG_FRAG_SIZE)-1)) / (SIG_FRAG_SIZE))
983
984
985 /*
986  * ---------------------------------------------------------------------------
987  *  read_to_host_signals
988  *
989  *      Read everything pending in the UniFi TH signal buffer.
990  *      Only do it if the local buffer is empty.
991  *
992  *  Arguments:
993  *      card        Pointer to card context struct
994  *      processed   Number of signals read:
995  *                      0 if there were no signals pending,
996  *                      1 if we read at least one signal
997  *  Returns:
998  *      CSR error code if an error occurred.
999  * ---------------------------------------------------------------------------
1000  */
1001 static 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     /* Read any pending signals or bulk data commands */
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; /* diag */
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 } /* read_to_host_signals() */
1054
1055
1056 /*
1057  * ---------------------------------------------------------------------------
1058  *  update_to_host_signals_r
1059  *
1060  *      Advance the shared-memory count of chunks read from the to-host
1061  *      signal buffer.
1062  *      Raise a UniFi internal interrupt to tell the firmware that the
1063  *      count has changed.
1064  *
1065  *  Arguments:
1066  *      card            Pointer to card context struct
1067  *      pending         Number of chunks remaining
1068  *
1069  *  Returns:
1070  *      CSR_RESULT_SUCCESS on success or CSR error code
1071  * ---------------------------------------------------------------------------
1072  */
1073 static 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     /* Update the count of signals read */
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 } /* update_to_host_signals_r() */
1101
1102
1103 /*
1104  * ---------------------------------------------------------------------------
1105  *  read_unpack_cmd
1106  *
1107  *      Converts a wire-formatted command to the host bulk_data_cmd_t structure.
1108  *
1109  *  Arguments:
1110  *      ptr             Pointer to the command
1111  *      bulk_data_cmd   Pointer to the host structure
1112  *
1113  *  Returns:
1114  *      None.
1115  * ---------------------------------------------------------------------------
1116  */
1117 static 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 } /* read_unpack_cmd */
1129
1130
1131 /*
1132  * ---------------------------------------------------------------------------
1133  *  process_to_host_signals
1134  *
1135  *      Read and dispatch signals from the UniFi
1136  *
1137  *  Arguments:
1138  *      card        Pointer to card context struct
1139  *      processed   Pointer to location to write processing result:
1140  *                      0 if there were no signals pending,
1141  *                      1 if we read at least one signal
1142  *
1143  *  Returns:
1144  *      CSR error code if there was an error
1145  *
1146  *  Notes:
1147  *      Since bulk data transfers can take a long time, if we wait until
1148  *      all are done before we acknowledge the signals, the UniFi runs out
1149  *      of buffer space. Therefore we keep a count of the bytes transferred
1150  *      in bulk data commands, and update the to-host-signals-read count
1151  *      if we've done a large transfer.
1152  *
1153  *      All data in the f/w is stored in a little endian format, without any
1154  *      padding bytes. Every read from the memory has to be transformed in
1155  *      host (cpu specific) format, before we can process it. Therefore we
1156  *      use read_unpack_cmd() and read_unpack_signal() to convert the raw data
1157  *      contained in the card->th_buffer.buf to host structures.
1158  *      Important: UDI clients use wire-formatted structures, so we need to
1159  *      indicate all data, as we have read it from the device.
1160  * ---------------------------------------------------------------------------
1161  */
1162 static 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     /* Are there new to-host signals? */
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      * This is a pointer to the raw data we have read from the f/w.
1189      * Can be a signal or a command. Note that we need to convert
1190      * it to a host structure before we process it.
1191      */
1192     bufptr = card->th_buffer.buf;
1193
1194     while (pending > 0)
1195     {
1196         s16 f_flush_count = 0;
1197
1198         /*
1199          * Command and length are common to signal and bulk data msgs.
1200          * If command == 0 (i.e. a signal), len is number of bytes
1201          * *following* the 2-byte header.
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  /* CSR_WIFI_HIP_NOISY */
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          * Make sure the buffer contains a complete message.
1219          * Signals may occupy multiple chunks, bulk-data commands occupy
1220          * one chunk.
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                 /* This is a signal. Read the rest of it and then handle it. */
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                     /* Retrieve dataRefs[i].DataLength */
1254                     u16 data_len = GET_PACKED_DATAREF_LEN(bufptr + 2, i);
1255
1256                     /*
1257                      * The bulk data length in the signal can not be greater than
1258                      * the maximun length allowed by the SDIO config structure.
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                      * Len here might not be the same as the length in the
1270                      * bulk data slot.  The slot length will always be even,
1271                      * but len could be odd.
1272                      */
1273                     if (data_len != 0)
1274                     {
1275                     /* Retrieve dataRefs[i].SlotNumber */
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              * Log the signal to the UDI, before call unifi_receive_event() as
1298              * it can modify the bulk data.
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                  * Check if the signal is MA-PACKET.cfm and if so check the status.
1324                  * If the status is failure, search through the slot records to find
1325                  * if any slots are occupied for this host tag. This can happen if
1326                  * f/w has not downloaded the bulkdata and before that itself it has
1327                  * signalled the confirm with failure. If it finds a slot with that
1328                  * host tag then, it clears the corresponding slot
1329                  */
1330
1331                 if (GET_SIGNAL_ID(bufptr + 2) == CSR_MA_PACKET_CONFIRM_ID)
1332                 {
1333                     /* Get host tag and transmission status */
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                     /* If transmission status is failure then search through the slot records
1341                      * and if for any slot records the clear slot is not done then do it now
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                         /* search through the list of slot records and match with host tag
1349                          * If a slot is not yet cleared then clear the slot from here
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                                 /* Invoke the HAL module function to requeue it back to HAL Queues */
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                                 /* Set length field in from_host_data array to 0 */
1374                                 CardClearFromHostDataSlot(card, i);
1375 #endif
1376                                 break;
1377                             }
1378                         }
1379                     }
1380                 }
1381
1382                 /* Pass event to OS layer */
1383                 unifi_receive_event(card->ospriv, bufptr + 2, sig_len, &data_ptrs);
1384
1385                 /* Initialise the to_host data, so it can be re-used. */
1386                 for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++)
1387                 {
1388                 /* The slot is only valid if the length is non-zero. */
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                  * If we have previously transferred a lot of data, ack
1402                  * the signals read so far, so f/w can reclaim the buffer
1403                  * memory sooner.
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                 /* This is a clear slot command. */
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                 /* This is a bulk data command. */
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                 /* Count the bytes transferred */
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          * Write out the host signal count when a significant
1488          * number of bytes of bulk data have been transferred or
1489          * when we have performed a CopyFromHostAndClear.
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     /* If we processed any signals, write the updated count to UniFi */
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      * Reset the buffer pointer, copying down any un-processed signals.
1519      * This can happen if we enable the optimisation in read_to_host_signals()
1520      * that limits the length to whole blocks.
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         /* Use a safe copy because source and destination may overlap */
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     /* If we reach here then we processed something */
1543     *processed = 1;
1544     return CSR_RESULT_SUCCESS;
1545 } /* process_to_host_signals() */
1546
1547
1548 /*
1549  * ---------------------------------------------------------------------------
1550  *  process_clear_slot_command
1551  *
1552  *      Process a clear slot command fom the UniFi.
1553  *
1554  *  Arguments:
1555  *   card       Pointer to card context struct
1556  *   bdcmd      Pointer to bulk-data command msg from UniFi
1557  *
1558  *  Returns:
1559  *      0 on success, CSR error code on error
1560  * ---------------------------------------------------------------------------
1561  */
1562 static 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 /* CSR_WIFI_HIP_NOISY */
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         /* clear to-host data slot */
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          * The driver is the owner to clear all slots now
1603          * Ref - comment in process_fh_traffic_queue
1604          * so it will just ignore the clear slot command from firmware
1605          * and return success
1606          */
1607         return CSR_RESULT_SUCCESS;
1608
1609         /* Set length field in from_host_data array to 0 */
1610         /* CardClearFromHostDataSlot(card, slot); */
1611     }
1612
1613     return CSR_RESULT_SUCCESS;
1614 } /* process_clear_slot_command() */
1615
1616
1617 /*
1618  * ---------------------------------------------------------------------------
1619  *  process_bulk_data_command
1620  *
1621  *      Process a bulk data request from the UniFi.
1622  *
1623  *  Arguments:
1624  *   card       Pointer to card context struct
1625  *   bdcmd      Pointer to bulk-data command msg from UniFi
1626  *   cmd, len   Decoded values of command and length from the msg header
1627  *              Cmd will only be one of:
1628  *                      SDIO_CMD_TO_HOST_TRANSFER
1629  *                      SDIO_CMD_FROM_HOST_TRANSFER
1630  *                      SDIO_CMD_FROM_HOST_AND_CLEAR
1631  *                      SDIO_CMD_OVERLAY_TRANSFER
1632  *
1633  *  Returns:
1634  *      CSR_RESULT_SUCCESS on success, CSR error code on error
1635  * ---------------------------------------------------------------------------
1636  */
1637 static 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      * Round up the transfer length if required.
1657      * This is useful to force all transfers to be a multiple of the SDIO block
1658      * size, so the SDIO driver won't try to use a byte-mode CMD53. These are
1659      * broken on some hardware platforms.
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;     /* Not used on CSR6xxx */
1672     }
1673     else
1674     {
1675         if (bdcmd.data_slot & SLOT_DIR_TO_HOST)
1676         {
1677             /* Request is for to-host bulk data */
1678
1679             /* Check sanity of slot number */
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             /* Allocate memory for card->to_host_data[slot] bulk data here. */
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             /* Make sure that the buffer is 4-bytes aligned */
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             /* Request is for from-host bulk data */
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     /* Do the transfer */
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 /* CSR_WIFI_HIP_NOISY */
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     /* if os_data_ptr is not 4-byte aligned, then allocate a new buffer and copy data
1757     to new buffer to ensure the address passed to unifi_bulk_rw is 4-byte aligned */
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,                    /* Header length */
1798                     bdslot->data_length,    /* Length stored in slot */
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         /* moving this check before we clear host data slot */
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             /* reset the host tag entry for the corresponding slot */
1829             card->fh_slot_host_tag_record[slot] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
1830         }
1831
1832
1833         /* Set length field in from_host_data array to 0 */
1834         CardClearFromHostDataSlot(card, slot);
1835     }
1836
1837     return CSR_RESULT_SUCCESS;
1838 } /* process_bulk_data_command() */
1839
1840
1841 /*
1842  * ---------------------------------------------------------------------------
1843  *  check_fh_sig_slots
1844  *
1845  *      Check whether there are <n> free signal slots available on UniFi.
1846  *      This takes into account the signals already batched since the
1847  *      from_host_signal counts were last read.
1848  *      If the from_host_signal counts indicate not enough space, we read
1849  *      the latest count from UniFi to see if some more have been freed.
1850  *
1851  *  Arguments:
1852  *      None.
1853  *
1854  *  Returns:
1855  *      CSR_RESULT_SUCCESS, otherwise CSR error code on error.
1856  * ---------------------------------------------------------------------------
1857  */
1858 static 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     /* Only read the space in from-host queue if necessary */
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; /* diag */
1889
1890         occupied_fh = (count_fhw - count_fhr) % 128;
1891         *space_fh = slots_fh - occupied_fh;
1892     }
1893
1894     return CSR_RESULT_SUCCESS;
1895 } /* check_fh_sig_slots() */
1896
1897
1898 /*
1899 * If we are padding the From-Host signals to the SDIO block size,
1900 * we need to round up the needed_chunks to the SDIO block size.
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  *  process_fh_cmd_queue
1937  *
1938  *      Take one signal off the from-host queue and copy it to the UniFi.
1939  *      Does nothing if the UniFi has no slots free.
1940  *
1941  *  Arguments:
1942  *      card       Pointer to card context struct
1943  *      processed  Location to write:
1944  *                      0 if there is nothing on the queue to process
1945  *                      1 if a signal was successfully processed
1946  *
1947  *  Returns:
1948  *      CSR error code if an error occurred.
1949  *
1950  *  Notes:
1951  *      The from-host queue contains signal requests from the network driver
1952  *      and any UDI clients interspersed. UDI clients' requests have been stored
1953  *      in the from-host queue using the wire-format structures, as they arrive.
1954  *      All other requests are stored in the from-host queue using the host
1955  *      (cpu specific) structures. We use the is_packed member of the card_signal_t
1956  *      structure that describes the queue to make the distiction.
1957  * ---------------------------------------------------------------------------
1958  */
1959 static 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     /* Get the number of pending signals. */
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         /* Nothing to do */
1978         return CSR_RESULT_SUCCESS;
1979     }
1980
1981     /* Work out how many chunks we have waiting to send */
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          * Note that GET_CHUNKS_FOR() needs the size of the packed
1990          * (wire-formatted) structure
1991          */
1992         pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
1993     }
1994
1995     /*
1996      * Check whether UniFi has space for all the buffered bulk-data
1997      * commands and signals as well.
1998      */
1999     needed_chunks = pending_chunks + card->fh_buffer.count;
2000
2001     /* Round up to the block size if necessary */
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         /* Error */
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 /* CSR_WIFI_HIP_NOISY */
2016
2017
2018     /*
2019      * Coalesce as many from-host signals as possible
2020      * into a single block and write using a single CMD53
2021      */
2022     if (needed_chunks > (u16)space_chunks)
2023     {
2024         /* Round up to the block size if necessary */
2025         ROUND_UP_SPACE_CHUNKS(card, space_chunks);
2026
2027         /*
2028          * If the f/w has less free chunks than those already pending
2029          * return immediately.
2030          */
2031         if ((u16)space_chunks <= card->fh_buffer.count)
2032         {
2033             /*
2034              * No room in UniFi for any signals after the buffered bulk
2035              * data commands have been sent.
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         /* Retrieve the entry at the head of the queue */
2055         q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq);
2056
2057         /* Get a pointer to the containing card_signal_t struct */
2058         csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, q_index);
2059
2060         /* Get the new length of the packed signal */
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         /* Need space for 2-byte SDIO protocol header + signal */
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             /* No more room */
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         /* Claim and set up a from-host data slot */
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             /* Pass the free responsibility to the lower layer. */
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  /* CSR_WIFI_HIP_NOISY */
2114
2115
2116         /* Append packed signal to F-H buffer */
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  /* CSR_WIFI_HIP_NOISY */
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  /* CSR_WIFI_HIP_NOISY */
2143
2144         (*processed)++;
2145         pending_chunks -= sig_chunks;
2146
2147         /* Log the signal to the UDI. */
2148         /* UDI will get the packed structure */
2149         /* Can not log the unpacked signal, unless we reconstruct it! */
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         /* Remove entry from q */
2157         csptr->signal_length = 0;
2158         CSR_WIFI_HIP_Q_INC_R(sigq);
2159     }
2160
2161     return CSR_RESULT_SUCCESS;
2162 } /* process_fh_cmd_queue() */
2163
2164
2165 /*
2166  * ---------------------------------------------------------------------------
2167  *  process_fh_traffic_queue
2168  *
2169  *      Take signals off the from-host queue and copy them to the UniFi.
2170  *      Does nothing if the UniFi has no slots free.
2171  *
2172  *  Arguments:
2173  *      card       Pointer to card context struct
2174  *      sigq       Pointer to the traffic queue
2175  *      processed  Pointer to location to write:
2176  *                      0 if there is nothing on the queue to process
2177  *                      1 if a signal was successfully processed
2178  *
2179  *  Returns:
2180  *      CSR error code if an error occurred.
2181  *
2182  *  Notes:
2183  *      The from-host queue contains signal requests from the network driver
2184  *      and any UDI clients interspersed.
2185  * ---------------------------------------------------------------------------
2186  */
2187 static 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     /* calculate how many signals are in queues and how many chunks are needed. */
2205     for (n = UNIFI_NO_OF_TX_QS - 1; n >= 0; n--)
2206     {
2207         /* Get the number of pending signals. */
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         /* Work out how many chunks we have waiting to send */
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              * Note that GET_CHUNKS_FOR() needs the size of the packed
2220              * (wire-formatted) structure
2221              */
2222             pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
2223         }
2224     }
2225
2226     /* If there are no pending signals, just return */
2227     if (pending_sigs == 0)
2228     {
2229         /* Nothing to do */
2230         return CSR_RESULT_SUCCESS;
2231     }
2232
2233     /*
2234      * Check whether UniFi has space for all the buffered bulk-data
2235      * commands and signals as well.
2236      */
2237     needed_chunks = pending_chunks + card->fh_buffer.count;
2238
2239     /* Round up to the block size if necessary */
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         /* Error */
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);            /* debugging only */
2255 #endif /* CSR_WIFI_HIP_NOISY */
2256
2257     /* Coalesce as many from-host signals as possible
2258        into a single block and write using a single CMD53 */
2259     if (needed_chunks > (u16)space_chunks)
2260     {
2261         /* Round up to the block size if necessary */
2262         ROUND_UP_SPACE_CHUNKS(card, space_chunks);
2263
2264         if ((u16)space_chunks <= card->fh_buffer.count)
2265         {
2266             /*
2267              * No room in UniFi for any signals after the buffered bulk
2268              * data commands have been sent.
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      * pending_sigs will be exhausted if there are is no restriction to the pending
2283      * signals per queue. pending_chunks may be exhausted if there is a restriction.
2284      * q_no check will be exhausted if there is a restriction and our round-robin
2285      * algorith fails to fill all chunks.
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         /* if this queue is empty go to next one. */
2296         if (CSR_WIFI_HIP_Q_SLOTS_USED(&sigq[q_no]) == 0)
2297         {
2298             q_no--;
2299             continue;
2300         }
2301
2302         /* Retrieve the entry at the head of the queue */
2303         q_index = CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq[q_no]);
2304
2305         /* Get a pointer to the containing card_signal_t struct */
2306         csptr = CSR_WIFI_HIP_Q_SLOT_DATA(&sigq[q_no], q_index);
2307
2308         /* Get the new length of the packed signal */
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         /* Need space for 2-byte SDIO protocol header + signal */
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             /* No more room */
2324             unifi_notice(card->ospriv, "process_fh_traffic_queue: no more chunks.\n");
2325             break;
2326         }
2327
2328         packed_sigptr = csptr->sigbuf;
2329         /* Claim and set up a from-host data slot */
2330         if (CSR_RESULT_FAILURE == CardWriteBulkData(card, csptr, (unifi_TrafficQueue)q_no))
2331         {
2332             q_no--;
2333             continue;
2334         }
2335
2336         /* Sanity check: MA-PACKET.req must have a valid bulk data */
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         /* The driver owns clearing of HIP slots for following scenario
2351          * - driver has requested a MA-PACKET.req signal
2352          * - The f/w after receiving the signal decides it can't send it out due to various reasons
2353          * - So the f/w without downloading the bulk data decides to just send a confirmation with fail
2354          * - and then sends a clear slot signal to HIP
2355          *
2356          * But in some cases the clear slot signal never comes and the slot remains --NOT-- freed for ever
2357          *
2358          * To handle this, HIP will keep the record of host tag for each occupied slot
2359          * and then based on status of that Host tag and slot the driver will decide if the slot is
2360          * cleared by f/w signal or the slot has to be freed by driver
2361          */
2362
2363         if (card->fh_slot_host_tag_record)
2364         {
2365             /* Update the f-h slot record for the corresponding host tag */
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  /* CSR_WIFI_HIP_NOISY */
2393
2394         /* Append packed signal to F-H buffer */
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  /* CSR_WIFI_HIP_NOISY */
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  /* CSR_WIFI_HIP_NOISY */
2421
2422         (*processed)++;
2423         pending_sigs--;
2424         pending_chunks -= sig_chunks;
2425
2426         /* Log the signal to the UDI. */
2427         /* UDI will get the packed structure */
2428         /* Can not log the unpacked signal, unless we reconstruct it! */
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         /* Remove entry from q */
2436         csptr->signal_length = 0;
2437         /* Note that the traffic queue has only one valid bulk data buffer. */
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 } /* process_fh_traffic_queue() */
2445
2446
2447 /*
2448  * ---------------------------------------------------------------------------
2449  *  flush_fh_buffer
2450  *
2451  *      Write out the cache from-hosts signals to the UniFi.
2452  *
2453  *  Arguments:
2454  *      card       Pointer to card context struct
2455  *
2456  *  Returns:
2457  *      CSR error code if an SDIO error occurred.
2458  * ---------------------------------------------------------------------------
2459  */
2460 static 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 /* CSR_WIFI_HIP_NOISY */
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 /* CSR_WIFI_HIP_NOISY */
2489
2490     if (card->sdio_io_block_pad)
2491     {
2492         /* Both of these are powers of 2 */
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     /* Update from-host-signals-written signal count */
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     /* Reset the fh buffer pointer */
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 /* CSR_WIFI_HIP_NOISY */
2553
2554     return CSR_RESULT_SUCCESS;
2555 } /* flush_fh_buffer() */
2556
2557
2558 /*
2559  * ---------------------------------------------------------------------------
2560  *  restart_packet_flow
2561  *
2562  *      This function is called before the bottom-half thread sleeps.
2563  *      It checks whether both data and signal resources are available and
2564  *      then calls the OS-layer function to re-enable packet transmission.
2565  *
2566  *  Arguments:
2567  *      card       Pointer to card context struct
2568  *
2569  *  Returns:
2570  *      None.
2571  * ---------------------------------------------------------------------------
2572  */
2573 static void restart_packet_flow(card_t *card)
2574 {
2575     u8 q;
2576
2577     /*
2578      * We only look at the fh_traffic_queue, because that is where packets from
2579      * the network stack are placed.
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 } /* restart_packet_flow() */
2594
2595