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