Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / drivers / staging / csr / csr_wifi_hip_card_sdio_intr.c
CommitLineData
635d2b00
GKH
1/*****************************************************************************
2
95edd09e 3 (c) Cambridge Silicon Radio Limited 2012
635d2b00
GKH
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
45static CsrResult process_bh(card_t *card);
5379b13d 46static CsrResult handle_host_protocol(card_t *card, u8 *processed_something);
635d2b00
GKH
47
48static CsrResult flush_fh_buffer(card_t *card);
49
95e326c2 50static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space);
635d2b00 51
95e326c2
GKH
52static CsrResult read_to_host_signals(card_t *card, s32 *processed);
53static CsrResult process_to_host_signals(card_t *card, s32 *processed);
635d2b00
GKH
54
55static CsrResult process_bulk_data_command(card_t *card,
7e6f5794 56 const u8 *cmdptr,
ab2b8c73 57 s16 cmd, u16 len);
635d2b00 58static CsrResult process_clear_slot_command(card_t *card,
7e6f5794 59 const u8 *cmdptr);
95e326c2
GKH
60static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed);
61static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed);
635d2b00
GKH
62static void restart_packet_flow(card_t *card);
63static CsrResult process_clock_request(card_t *card);
64
65#ifdef CSR_WIFI_HIP_NOISY
ab2b8c73 66s16 dump_fh_buf = 0;
635d2b00
GKH
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
c781b96b
GKH
84static char unifi_debug_output[UNIFI_DEBUG_GBUFFER_SIZE];
85static char *unifi_dbgbuf_ptr = unifi_debug_output;
86static char *unifi_dbgbuf_start = unifi_debug_output;
635d2b00 87
c781b96b 88static void append_char(char c)
635d2b00
GKH
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
c781b96b 100void unifi_debug_string_to_buf(const char *str)
635d2b00 101{
c781b96b 102 const char *p = str;
635d2b00
GKH
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
c781b96b 117void unifi_debug_log_to_buf(const char *fmt, ...)
635d2b00
GKH
118{
119#define DEBUG_BUFFER_SIZE 80
c781b96b 120 static char s[DEBUG_BUFFER_SIZE];
635d2b00
GKH
121 va_list args;
122
123 va_start(args, fmt);
e4bcecd9 124 vsnprintf(s, DEBUG_BUFFER_SIZE, fmt, args);
635d2b00
GKH
125 va_end(args);
126
127 unifi_debug_string_to_buf(s);
128} /* unifi_debug_log_to_buf() */
129
130
ed51b4d8
GKH
131/* Convert signed 32 bit (or less) integer to string */
132static void CsrUInt16ToHex(u16 number, char *str)
133{
134 u16 index;
135 u16 currentValue;
136
137 for (index = 0; index < 4; index++)
138 {
139 currentValue = (u16) (number & 0x000F);
140 number >>= 4;
141 str[3 - index] = (char) (currentValue > 9 ? currentValue + 55 : currentValue + '0');
142 }
143 str[4] = '\0';
144}
145
146
635d2b00
GKH
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 */
c781b96b 162void unifi_debug_hex_to_buf(const char *buff, u16 length)
635d2b00 163{
c781b96b 164 char s[5];
8c87f69a 165 u16 i;
635d2b00 166
95edd09e 167 for (i = 0; i < length; i = i + 2)
635d2b00 168 {
8c87f69a 169 CsrUInt16ToHex(*((u16 *)(buff + i)), s);
635d2b00
GKH
170 unifi_debug_string_to_buf(s);
171 }
172}
173
174
175void unifi_debug_buf_dump(void)
176{
95e326c2 177 s32 offset = unifi_dbgbuf_ptr - unifi_debug_output;
635d2b00
GKH
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
190void prealloc_netdata_free(card_t *card)
191{
192 unifi_warning(card->ospriv, "prealloc_netdata_free: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
193
194 while (card->bulk_data_desc_list[card->prealloc_netdata_r].data_length != 0)
195 {
196 unifi_warning(card->ospriv, "prealloc_netdata_free: r=%d\n", card->prealloc_netdata_r);
197
198 unifi_net_data_free(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_r]);
199 card->prealloc_netdata_r++;
200 card->prealloc_netdata_r %= BULK_DATA_PRE_ALLOC_NUM;
201 }
202 card->prealloc_netdata_r = card->prealloc_netdata_w = 0;
203
204 unifi_warning(card->ospriv, "prealloc_netdata_free: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
205}
206
207
208CsrResult prealloc_netdata_alloc(card_t *card)
209{
210 CsrResult r;
211
212 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: IN: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
213
214 while (card->bulk_data_desc_list[card->prealloc_netdata_w].data_length == 0)
215 {
216 r = unifi_net_data_malloc(card->ospriv, &card->bulk_data_desc_list[card->prealloc_netdata_w], NETDATA_PRE_ALLOC_BUF_SIZE);
217 if (r != CSR_RESULT_SUCCESS)
218 {
219 unifi_error(card->ospriv, "prealloc_netdata_alloc: Failed to allocate t-h bulk data\n");
220 return CSR_RESULT_FAILURE;
221 }
222 card->prealloc_netdata_w++;
223 card->prealloc_netdata_w %= BULK_DATA_PRE_ALLOC_NUM;
224 }
225 unifi_trace(card->ospriv, UDBG5, "prealloc_netdata_alloc: OUT: w=%d r=%d\n", card->prealloc_netdata_w, card->prealloc_netdata_r);
226
227 return CSR_RESULT_SUCCESS;
228}
229
230
26a6b2e1 231static CsrResult prealloc_netdata_get(card_t *card, bulk_data_desc_t *bulk_data_slot, u32 size)
635d2b00
GKH
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 */
289void 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;
95edd09e 296 (void)unifi_run_bh(card->ospriv);
635d2b00
GKH
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 */
316CsrResult unifi_configure_low_power_mode(card_t *card,
317 enum unifi_low_power_mode low_power_mode,
318 enum unifi_periodic_wake_mode periodic_wake_mode)
319{
320 card->low_power_mode = low_power_mode;
321 card->periodic_wake_mode = periodic_wake_mode;
322
323 unifi_trace(card->ospriv, UDBG1,
324 "unifi_configure_low_power_mode: new mode = %s, wake_host = %s\n",
325 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled",
326 (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE");
327
95edd09e 328 (void)unifi_run_bh(card->ospriv);
635d2b00
GKH
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 */
347CsrResult unifi_force_low_power_mode(card_t *card)
348{
349 if (card->low_power_mode == UNIFI_LOW_POWER_DISABLED)
350 {
351 unifi_error(card->ospriv, "Attempt to set mode to TORPID when lower power mode is disabled\n");
352 return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
353 }
354
355 return unifi_set_host_state(card, UNIFI_HOST_STATE_TORPID);
356} /* 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 */
26a6b2e1 373CsrResult unifi_bh(card_t *card, u32 *remaining)
635d2b00
GKH
374{
375 CsrResult r;
376 CsrResult csrResult;
5379b13d 377 u8 pending;
95e326c2 378 s32 iostate, j;
635d2b00 379 const enum unifi_low_power_mode low_power_mode = card->low_power_mode;
8c87f69a 380 u16 data_slots_used = 0;
635d2b00
GKH
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 {
7e6f5794 427 u8 reason_unifi;
635d2b00
GKH
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
609exit:
610
611 unifi_trace(card->ospriv, UDBG4, "New state=%d\n", card->host_state);
612
613 if (r != CSR_RESULT_SUCCESS)
614 {
615#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE)
616 unifi_debug_buf_dump();
617#endif
618 /* 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 */
95edd09e 633 (void)unifi_capture_panic(card);
635d2b00
GKH
634
635 /* Ask for a mini-coredump when the driver has reset UniFi */
95edd09e 636 (void)unifi_coredump_request_at_next_reset(card, 1);
635d2b00
GKH
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 */
658static CsrResult process_clock_request(card_t *card)
659{
660 CsrResult r = CSR_RESULT_SUCCESS;
661 CsrResult csrResult;
662
663 if (!card->request_max_clock)
664 {
665 return CSR_RESULT_SUCCESS; /* 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 */
716static CsrResult process_bh(card_t *card)
717{
718 CsrResult r;
5379b13d 719 u8 more;
635d2b00
GKH
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 */
5379b13d 861static CsrResult handle_host_protocol(card_t *card, u8 *processed_something)
635d2b00
GKH
862{
863 CsrResult r;
95e326c2 864 s32 done;
635d2b00
GKH
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 }
95edd09e
GKH
951
952#ifdef CSR_WIFI_RX_PATH_SPLIT
635d2b00
GKH
953#ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
954 unifi_rx_queue_flush(card->ospriv);
955#endif
95edd09e
GKH
956#endif
957
635d2b00
GKH
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 */
95e326c2 1001static CsrResult read_to_host_signals(card_t *card, s32 *processed)
635d2b00 1002{
95e326c2
GKH
1003 s32 count_thw, count_thr;
1004 s32 unread_chunks, unread_bytes;
635d2b00
GKH
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;
8c87f69a 1048 card->th_buffer.count += (u16)unread_chunks;
635d2b00
GKH
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 */
ab2b8c73 1073static CsrResult update_to_host_signals_r(card_t *card, s16 pending)
635d2b00
GKH
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,
7e6f5794 1083 (u8)card->to_host_signals_r);
635d2b00
GKH
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 */
7e6f5794 1117static void read_unpack_cmd(const u8 *ptr, bulk_data_cmd_t *bulk_data_cmd)
635d2b00 1118{
ab2b8c73 1119 s16 index = 0;
635d2b00
GKH
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 */
95e326c2 1162static CsrResult process_to_host_signals(card_t *card, s32 *processed)
635d2b00 1163{
ab2b8c73
GKH
1164 s16 pending;
1165 s16 remaining;
7e6f5794 1166 u8 *bufptr;
635d2b00 1167 bulk_data_param_t data_ptrs;
ab2b8c73 1168 s16 cmd;
8c87f69a 1169 u16 sig_len;
ab2b8c73 1170 s16 i;
8c87f69a
GKH
1171 u16 chunks_in_buf;
1172 u16 bytes_transferred = 0;
635d2b00
GKH
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 {
ab2b8c73 1196 s16 f_flush_count = 0;
635d2b00
GKH
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 {
8c87f69a 1224 chunks_in_buf = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(sig_len + 2));
635d2b00
GKH
1225 }
1226 else
1227 {
1228 chunks_in_buf = 1;
1229 }
1230
8c87f69a 1231 if (chunks_in_buf > (u16)pending)
635d2b00
GKH
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 */
8c87f69a 1254 u16 data_len = GET_PACKED_DATAREF_LEN(bufptr + 2, i);
635d2b00
GKH
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 */
ab2b8c73 1276 s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i);
635d2b00
GKH
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 */
26a6b2e1 1334 u32 host_tag = GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(bufptr + 2);
8c87f69a 1335 u16 status = GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(bufptr + 2);
635d2b00
GKH
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 {
8c87f69a 1346 u16 num_fh_slots = card->config_data.num_fromhost_data_slots;
635d2b00
GKH
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 {
95edd09e
GKH
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
635d2b00
GKH
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);
95edd09e 1375#endif
635d2b00
GKH
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 {
ab2b8c73 1391 s16 slot = GET_PACKED_DATAREF_SLOT(bufptr + 2, i);
635d2b00
GKH
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 */
7e6f5794
GKH
1531 u8 *d = card->th_buffer.buf;
1532 u8 *s = bufptr;
95e326c2 1533 s32 n = remaining;
635d2b00
GKH
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 */
7e6f5794 1562static CsrResult process_clear_slot_command(card_t *card, const u8 *cmdptr)
635d2b00 1563{
8c87f69a 1564 u16 data_slot;
ab2b8c73 1565 s16 slot;
635d2b00
GKH
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 */
7e6f5794 1637static CsrResult process_bulk_data_command(card_t *card, const u8 *cmdptr,
ab2b8c73 1638 s16 cmd, u16 len)
635d2b00
GKH
1639{
1640 bulk_data_desc_t *bdslot;
1641#ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
7e6f5794 1642 u8 *host_bulk_data_slot;
635d2b00
GKH
1643#endif
1644 bulk_data_cmd_t bdcmd;
ab2b8c73
GKH
1645 s16 offset;
1646 s16 slot;
1647 s16 dir;
635d2b00
GKH
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
3c0b461e 1759 if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3))
635d2b00 1760 {
4becf12d 1761 host_bulk_data_slot = kmalloc(len, GFP_KERNEL);
635d2b00
GKH
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
25aebdb1 1769 memcpy((void *)host_bulk_data_slot,
635d2b00
GKH
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 */
3c0b461e 1818 if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((ptrdiff_t)bdslot->os_data_ptr + offset) & 3))
635d2b00 1819 {
4fe9db37 1820 kfree(host_bulk_data_slot);
635d2b00
GKH
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 */
95e326c2 1858static CsrResult check_fh_sig_slots(card_t *card, u16 needed, s32 *space_fh)
635d2b00 1859{
26a6b2e1
GKH
1860 u32 count_fhw;
1861 u32 occupied_fh, slots_fh;
95e326c2 1862 s32 count_fhr;
635d2b00
GKH
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 { \
8c87f69a
GKH
1904 u16 _chunks_per_block; \
1905 u16 _chunks_in_last_block; \
635d2b00
GKH
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 { \
8c87f69a 1921 u16 _chunks_per_block; \
635d2b00
GKH
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 */
95e326c2 1959static CsrResult process_fh_cmd_queue(card_t *card, s32 *processed)
635d2b00
GKH
1960{
1961 q_t *sigq = &card->fh_command_queue;
1962
1963 CsrResult r;
8c87f69a
GKH
1964 u16 pending_sigs;
1965 u16 pending_chunks;
1966 u16 needed_chunks;
95e326c2 1967 s32 space_chunks;
8c87f69a 1968 u16 q_index;
635d2b00
GKH
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 */
8c87f69a 1992 pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
635d2b00
GKH
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 */
8c87f69a 2022 if (needed_chunks > (u16)space_chunks)
635d2b00
GKH
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 */
8c87f69a 2031 if ((u16)space_chunks <= card->fh_buffer.count)
635d2b00
GKH
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 }
8c87f69a 2042 pending_chunks = (u16)(space_chunks - card->fh_buffer.count);
635d2b00
GKH
2043 }
2044
2045 while (pending_sigs-- && pending_chunks > 0)
2046 {
2047 card_signal_t *csptr;
ab2b8c73 2048 s16 i;
8c87f69a 2049 u16 sig_chunks, total_length, free_chunks_in_fh_buffer;
635d2b00 2050 bulk_data_param_t bulkdata;
7e6f5794 2051 u8 *packed_sigptr;
8c87f69a 2052 u16 signal_length = 0;
635d2b00
GKH
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 */
8c87f69a 2070 sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2));
635d2b00
GKH
2071
2072 free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size,
8c87f69a 2073 (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr));
635d2b00
GKH
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",
8c87f69a 2078 (u16)(GET_SIGNAL_ID(csptr->sigbuf)));
635d2b00
GKH
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",
8c87f69a 2088 (u16)(GET_SIGNAL_ID(csptr->sigbuf)));
635d2b00
GKH
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
7e6f5794 2119 card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff);
635d2b00 2120 card->fh_buffer.ptr[1] =
7e6f5794 2121 (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4));
635d2b00 2122
25aebdb1 2123 memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length);
b7244a31 2124 memset(card->fh_buffer.ptr + 2 + signal_length, 0,
635d2b00
GKH
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 */
95e326c2 2187static CsrResult process_fh_traffic_queue(card_t *card, s32 *processed)
635d2b00
GKH
2188{
2189 q_t *sigq = card->fh_traffic_queue;
2190
2191 CsrResult r;
ab2b8c73 2192 s16 n = 0;
95e326c2 2193 s32 q_no;
8c87f69a
GKH
2194 u16 pending_sigs = 0;
2195 u16 pending_chunks = 0;
2196 u16 needed_chunks;
95e326c2 2197 s32 space_chunks;
8c87f69a 2198 u16 q_index;
26a6b2e1 2199 u32 host_tag = 0;
8c87f69a 2200 u16 slot_num = 0;
635d2b00
GKH
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 */
8c87f69a 2222 pending_chunks += GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(csptr->signal_length + 2));
635d2b00
GKH
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 */
8c87f69a 2259 if (needed_chunks > (u16)space_chunks)
635d2b00
GKH
2260 {
2261 /* Round up to the block size if necessary */
2262 ROUND_UP_SPACE_CHUNKS(card, space_chunks);
2263
8c87f69a 2264 if ((u16)space_chunks <= card->fh_buffer.count)
635d2b00
GKH
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
8c87f69a 2276 pending_chunks = (u16)space_chunks - card->fh_buffer.count;
635d2b00
GKH
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;
8c87f69a 2290 u16 sig_chunks, total_length, free_chunks_in_fh_buffer;
635d2b00 2291 bulk_data_param_t bulkdata;
7e6f5794 2292 u8 *packed_sigptr;
8c87f69a 2293 u16 signal_length = 0;
635d2b00
GKH
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 */
8c87f69a 2318 sig_chunks = GET_CHUNKS_FOR(card->config_data.sig_frag_size, (u16)(signal_length + 2));
635d2b00 2319 free_chunks_in_fh_buffer = GET_CHUNKS_FOR(card->config_data.sig_frag_size,
8c87f69a 2320 (u16)((card->fh_buffer.buf + UNIFI_FH_BUF_SIZE) - card->fh_buffer.ptr));
635d2b00
GKH
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
7e6f5794 2397 card->fh_buffer.ptr[0] = (u8)(signal_length & 0xff);
635d2b00 2398 card->fh_buffer.ptr[1] =
7e6f5794 2399 (u8)(((signal_length >> 8) & 0xf) | (SDIO_CMD_SIGNAL << 4));
635d2b00 2400
25aebdb1 2401 memcpy(card->fh_buffer.ptr + 2, packed_sigptr, signal_length);
b7244a31 2402 memset(card->fh_buffer.ptr + 2 + signal_length, 0,
635d2b00
GKH
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 */
2460static CsrResult flush_fh_buffer(card_t *card)
2461{
2462 CsrResult r;
8c87f69a
GKH
2463 u16 len;
2464 u16 sig_units;
2465 u16 data_round;
2466 u16 chunks_in_last_block;
2467 u16 padding_chunks;
2468 u16 i;
635d2b00
GKH
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
b7244a31 2504 memset(card->fh_buffer.ptr, 0, padding_chunks * sig_units);
635d2b00
GKH
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,
7e6f5794 2535 (u8)card->from_host_signals_w);
635d2b00
GKH
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 */
2573static void restart_packet_flow(card_t *card)
2574{
7e6f5794 2575 u8 q;
635d2b00
GKH
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