1 /*****************************************************************************
3 (c) Cambridge Silicon Radio Limited 2012
4 All rights reserved and confidential information of CSR
6 Refer to LICENSE.txt included with this source for details
9 *****************************************************************************/
12 * ---------------------------------------------------------------------------
13 * FILE: csr_wifi_hip_card_sdio_intr.c
16 * Interrupt processing for the UniFi SDIO driver.
18 * We may need another signal queue of responses to UniFi to hold
19 * bulk data commands generated by read_to_host_signals().
21 * ---------------------------------------------------------------------------
23 #undef CSR_WIFI_HIP_NOISY
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"
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().
36 #define UNIFI_DEFAULT_HOST_IDLE_TIMEOUT 5
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().
42 #define UNIFI_DEFAULT_WAKE_TIMEOUT 1000
45 static CsrResult
process_bh(card_t
*card
);
46 static CsrResult
handle_host_protocol(card_t
*card
, u8
*processed_something
);
48 static CsrResult
flush_fh_buffer(card_t
*card
);
50 static CsrResult
check_fh_sig_slots(card_t
*card
, u16 needed
, s32
*space
);
52 static CsrResult
read_to_host_signals(card_t
*card
, s32
*processed
);
53 static CsrResult
process_to_host_signals(card_t
*card
, s32
*processed
);
55 static CsrResult
process_bulk_data_command(card_t
*card
,
58 static CsrResult
process_clear_slot_command(card_t
*card
,
60 static CsrResult
process_fh_cmd_queue(card_t
*card
, s32
*processed
);
61 static CsrResult
process_fh_traffic_queue(card_t
*card
, s32
*processed
);
62 static void restart_packet_flow(card_t
*card
);
63 static CsrResult
process_clock_request(card_t
*card
);
65 #ifdef CSR_WIFI_HIP_NOISY
67 #endif /* CSR_WIFI_HIP_NOISY */
69 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
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.
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).
83 #define UNIFI_DEBUG_GBUFFER_SIZE 8192
84 static char unifi_debug_output
[UNIFI_DEBUG_GBUFFER_SIZE
];
85 static char *unifi_dbgbuf_ptr
= unifi_debug_output
;
86 static char *unifi_dbgbuf_start
= unifi_debug_output
;
88 static void append_char(char c
)
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
)
95 unifi_dbgbuf_ptr
= unifi_debug_output
;
100 void unifi_debug_string_to_buf(const char *str
)
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
)
112 unifi_dbgbuf_start
= unifi_debug_output
;
117 void unifi_debug_log_to_buf(const char *fmt
, ...)
119 #define DEBUG_BUFFER_SIZE 80
120 static char s
[DEBUG_BUFFER_SIZE
];
124 vsnprintf(s
, DEBUG_BUFFER_SIZE
, fmt
, args
);
127 unifi_debug_string_to_buf(s
);
128 } /* unifi_debug_log_to_buf() */
131 /* Convert signed 32 bit (or less) integer to string */
132 static void CsrUInt16ToHex(u16 number
, char *str
)
137 for (index
= 0; index
< 4; index
++)
139 currentValue
= (u16
) (number
& 0x000F);
141 str
[3 - index
] = (char) (currentValue
> 9 ? currentValue
+ 55 : currentValue
+ '0');
148 * ---------------------------------------------------------------------------
149 * unifi_debug_hex_to_buf
151 * puts the contents of the passed buffer into the debug buffer as a hex string
154 * buff buffer to print as hex
155 * length number of chars to print
160 * ---------------------------------------------------------------------------
162 void unifi_debug_hex_to_buf(const char *buff
, u16 length
)
167 for (i
= 0; i
< length
; i
= i
+ 2)
169 CsrUInt16ToHex(*((u16
*)(buff
+ i
)), s
);
170 unifi_debug_string_to_buf(s
);
175 void unifi_debug_buf_dump(void)
177 s32 offset
= unifi_dbgbuf_ptr
- unifi_debug_output
;
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() */
185 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
187 #ifdef CSR_PRE_ALLOC_NET_DATA
188 #define NETDATA_PRE_ALLOC_BUF_SIZE 8000
190 void prealloc_netdata_free(card_t
*card
)
192 unifi_warning(card
->ospriv
, "prealloc_netdata_free: IN: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
194 while (card
->bulk_data_desc_list
[card
->prealloc_netdata_r
].data_length
!= 0)
196 unifi_warning(card
->ospriv
, "prealloc_netdata_free: r=%d\n", card
->prealloc_netdata_r
);
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
;
202 card
->prealloc_netdata_r
= card
->prealloc_netdata_w
= 0;
204 unifi_warning(card
->ospriv
, "prealloc_netdata_free: OUT: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
208 CsrResult
prealloc_netdata_alloc(card_t
*card
)
212 unifi_trace(card
->ospriv
, UDBG5
, "prealloc_netdata_alloc: IN: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
214 while (card
->bulk_data_desc_list
[card
->prealloc_netdata_w
].data_length
== 0)
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
)
219 unifi_error(card
->ospriv
, "prealloc_netdata_alloc: Failed to allocate t-h bulk data\n");
220 return CSR_RESULT_FAILURE
;
222 card
->prealloc_netdata_w
++;
223 card
->prealloc_netdata_w
%= BULK_DATA_PRE_ALLOC_NUM
;
225 unifi_trace(card
->ospriv
, UDBG5
, "prealloc_netdata_alloc: OUT: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
227 return CSR_RESULT_SUCCESS
;
231 static CsrResult
prealloc_netdata_get(card_t
*card
, bulk_data_desc_t
*bulk_data_slot
, u32 size
)
235 unifi_trace(card
->ospriv
, UDBG5
, "prealloc_netdata_get: IN: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
237 if (card
->bulk_data_desc_list
[card
->prealloc_netdata_r
].data_length
== 0)
239 unifi_error(card
->ospriv
, "prealloc_netdata_get: data_length = 0\n");
242 if ((size
> NETDATA_PRE_ALLOC_BUF_SIZE
) || (card
->bulk_data_desc_list
[card
->prealloc_netdata_r
].data_length
== 0))
244 unifi_warning(card
->ospriv
, "prealloc_netdata_get: Calling net_data_malloc\n");
246 r
= unifi_net_data_malloc(card
->ospriv
, bulk_data_slot
, size
);
247 if (r
!= CSR_RESULT_SUCCESS
)
249 unifi_error(card
->ospriv
, "prealloc_netdata_get: Failed to allocate t-h bulk data\n");
250 return CSR_RESULT_FAILURE
;
252 return CSR_RESULT_SUCCESS
;
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;
261 card
->prealloc_netdata_r
++;
262 card
->prealloc_netdata_r
%= BULK_DATA_PRE_ALLOC_NUM
;
264 unifi_trace(card
->ospriv
, UDBG5
, "prealloc_netdata_get: OUT: w=%d r=%d\n", card
->prealloc_netdata_w
, card
->prealloc_netdata_r
);
266 return CSR_RESULT_SUCCESS
;
273 * ---------------------------------------------------------------------------
274 * unifi_sdio_interrupt_handler
276 * This function should be called by the OS-dependent code to handle
277 * an SDIO interrupt from the UniFi.
280 * card Pointer to card context structure.
285 * Notes: This function may be called in DRS context. In this case,
286 * tracing with the unifi_trace(), etc, is not allowed.
287 * ---------------------------------------------------------------------------
289 void unifi_sdio_interrupt_handler(card_t
*card
)
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.
295 card
->bh_reason_unifi
= 1;
296 (void)unifi_run_bh(card
->ospriv
);
297 } /* sdio_interrupt_handler() */
301 * ---------------------------------------------------------------------------
302 * unifi_configure_low_power_mode
304 * This function should be called by the OS-dependent when
305 * the deep sleep signaling needs to be enabled or disabled.
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.
313 * CSR_RESULT_SUCCESS on success or a CSR error code.
314 * ---------------------------------------------------------------------------
316 CsrResult
unifi_configure_low_power_mode(card_t
*card
,
317 enum unifi_low_power_mode low_power_mode
,
318 enum unifi_periodic_wake_mode periodic_wake_mode
)
320 card
->low_power_mode
= low_power_mode
;
321 card
->periodic_wake_mode
= periodic_wake_mode
;
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");
328 (void)unifi_run_bh(card
->ospriv
);
329 return CSR_RESULT_SUCCESS
;
330 } /* unifi_configure_low_power_mode() */
334 * ---------------------------------------------------------------------------
335 * unifi_force_low_power_mode
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)
341 * card Pointer to card context structure.
344 * CSR_RESULT_SUCCESS on success or a CSR error code.
345 * ---------------------------------------------------------------------------
347 CsrResult
unifi_force_low_power_mode(card_t
*card
)
349 if (card
->low_power_mode
== UNIFI_LOW_POWER_DISABLED
)
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
;
355 return unifi_set_host_state(card
, UNIFI_HOST_STATE_TORPID
);
356 } /* unifi_force_low_power_mode() */
360 * ---------------------------------------------------------------------------
363 * This function should be called by the OS-dependent code when
364 * host and/or UniFi has requested an exchange of messages.
367 * card Pointer to card context structure.
370 * CSR_RESULT_SUCCESS on success or a CSR error code.
371 * ---------------------------------------------------------------------------
373 CsrResult
unifi_bh(card_t
*card
, u32
*remaining
)
379 const enum unifi_low_power_mode low_power_mode
= card
->low_power_mode
;
380 u16 data_slots_used
= 0;
383 /* Process request to raise the maximum SDIO clock */
384 r
= process_clock_request(card
);
385 if (r
!= CSR_RESULT_SUCCESS
)
387 unifi_error(card
->ospriv
, "Error setting maximum SDIO clock\n");
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.
396 * Priority of flags is top down.
398 * ----------------------------------------------------------+
399 * \state| AWAKE | DROWSY | TORPID |
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 |
409 * ---------+--------------+----------------+----------------|
411 * timeout | go to TORPID | error, unifi | occur |
412 * | | didn't wake up | do nothing |
413 * ----------------------------------------------------------+
415 * Note that if we end up in the AWAKE state we always do the host protocol.
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.
425 if (card
->host_state
== UNIFI_HOST_STATE_DROWSY
|| card
->host_state
== UNIFI_HOST_STATE_TORPID
)
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.
435 reason_unifi
= card
->bh_reason_unifi
;
438 * If an interrupt is received, check if it was a real one,
439 * set the host state to AWAKE and run the BH.
441 r
= CardPendingInt(card
, &pending
);
442 if (r
!= CSR_RESULT_SUCCESS
)
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");
453 r
= unifi_set_host_state(card
, UNIFI_HOST_STATE_AWAKE
);
454 if (r
== CSR_RESULT_SUCCESS
)
460 else if (reason_unifi
)
462 CsrSdioInterruptAcknowledge(card
->sdio_if
);
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.
469 if ((card
->host_state
== UNIFI_HOST_STATE_TORPID
) && card
->bh_reason_host
)
471 r
= unifi_set_host_state(card
, UNIFI_HOST_STATE_DROWSY
);
472 if (r
== CSR_RESULT_SUCCESS
)
475 * set the timeout value to UNIFI_DEFAULT_WAKE_TIMEOUT
476 * to capture a wake error.
478 card
->bh_reason_host
= 0;
479 (*remaining
) = UNIFI_DEFAULT_WAKE_TIMEOUT
;
480 return CSR_RESULT_SUCCESS
;
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).
492 if ((card
->host_state
== UNIFI_HOST_STATE_DROWSY
) && ((*remaining
) == 0))
494 unifi_error(card
->ospriv
, "UniFi did not wake up on time...\n");
497 * Check if Function1 has gone away or
498 * if we missed an SDIO interrupt.
500 r
= unifi_check_io_status(card
, &iostate
);
501 if (r
== CSR_WIFI_HIP_RESULT_NO_DEVICE
)
505 /* Need to reset and reboot */
506 return CSR_RESULT_FAILURE
;
511 if (card
->bh_reason_unifi
|| card
->bh_reason_host
)
516 if (((*remaining
) == 0) && (low_power_mode
== UNIFI_LOW_POWER_ENABLED
))
518 r
= unifi_set_host_state(card
, UNIFI_HOST_STATE_TORPID
);
519 if (r
== CSR_RESULT_SUCCESS
)
522 return CSR_RESULT_SUCCESS
;
529 /* No need to run the host protocol */
530 return CSR_RESULT_SUCCESS
;
534 /* Disable the SDIO interrupts while doing SDIO ops */
535 csrResult
= CsrSdioInterruptDisable(card
->sdio_if
);
536 if (csrResult
== CSR_SDIO_RESULT_NO_DEVICE
)
538 r
= CSR_WIFI_HIP_RESULT_NO_DEVICE
;
541 if (csrResult
!= CSR_RESULT_SUCCESS
)
543 r
= ConvertCsrSdioToCsrHipResult(card
, csrResult
);
544 unifi_error(card
->ospriv
, "Failed to disable SDIO interrupts. unifi_bh queues error.\n");
548 /* Now that the interrupts are disabled, ack the interrupt */
549 CsrSdioInterruptAcknowledge(card
->sdio_if
);
552 r
= process_bh(card
);
553 if (r
!= CSR_RESULT_SUCCESS
)
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.
565 for (j
= 0; j
< UNIFI_NO_OF_TX_QS
; j
++)
567 data_slots_used
+= CSR_WIFI_HIP_Q_SLOTS_USED(&card
->fh_traffic_queue
[j
]);
570 if ((low_power_mode
== UNIFI_LOW_POWER_ENABLED
) && (data_slots_used
== 0))
572 #ifndef CSR_WIFI_HIP_TA_DISABLE
573 if (card
->ta_sampling
.traffic_type
!= CSR_WIFI_ROUTER_CTRL_TRAFFIC_TYPE_PERIODIC
)
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
584 unifi_trace(card
->ospriv
, UDBG5
,
585 "Traffic is periodic, set unifi to TORPID immediately.\n");
586 if (CardAreAllFromHostDataSlotsEmpty(card
) == 1)
588 r
= unifi_set_host_state(card
, UNIFI_HOST_STATE_TORPID
);
589 if (r
!= CSR_RESULT_SUCCESS
)
598 csrResult
= CsrSdioInterruptEnable(card
->sdio_if
);
599 if (csrResult
== CSR_SDIO_RESULT_NO_DEVICE
)
601 r
= CSR_WIFI_HIP_RESULT_NO_DEVICE
;
603 if (csrResult
!= CSR_RESULT_SUCCESS
)
605 r
= ConvertCsrSdioToCsrHipResult(card
, csrResult
);
606 unifi_error(card
->ospriv
, "Failed to enable SDIO interrupt\n");
611 unifi_trace(card
->ospriv
, UDBG4
, "New state=%d\n", card
->host_state
);
613 if (r
!= CSR_RESULT_SUCCESS
)
615 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_SDIO_TRACE)
616 unifi_debug_buf_dump();
618 /* If an interrupt has been raised, ack it here */
619 if (card
->bh_reason_unifi
)
621 CsrSdioInterruptAcknowledge(card
->sdio_if
);
624 unifi_error(card
->ospriv
,
625 "unifi_bh: state=%d %c, clock=%dkHz, interrupt=%d host=%d, power_save=%s\n",
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");
632 /* Try to capture firmware panic codes */
633 (void)unifi_capture_panic(card
);
635 /* Ask for a mini-coredump when the driver has reset UniFi */
636 (void)unifi_coredump_request_at_next_reset(card
, 1);
644 * ---------------------------------------------------------------------------
645 * process_clock_request
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.
652 * card Pointer to card context structure.
655 * CSR_RESULT_SUCCESS on success or CSR error code.
656 * ---------------------------------------------------------------------------
658 static CsrResult
process_clock_request(card_t
*card
)
660 CsrResult r
= CSR_RESULT_SUCCESS
;
663 if (!card
->request_max_clock
)
665 return CSR_RESULT_SUCCESS
; /* No pending request */
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.
676 if (card
->host_state
== UNIFI_HOST_STATE_AWAKE
)
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
)
682 r
= ConvertCsrSdioToCsrHipResult(card
, csrResult
);
686 card
->sdio_clock_speed
= UNIFI_SDIO_CLOCK_MAX_HZ
; /* log the new freq */
691 unifi_trace(card
->ospriv
, UDBG1
, "Will set SDIO max clock after wakeup\n");
694 /* Cancel the request now that it has been acted upon, or is about to be
695 * by the wakeup mechanism
697 card
->request_max_clock
= 0;
704 * ---------------------------------------------------------------------------
707 * Exchange messages with UniFi
710 * card Pointer to card context structure.
713 * CSR_RESULT_SUCCESS on success or CSR error code.
714 * ---------------------------------------------------------------------------
716 static CsrResult
process_bh(card_t
*card
)
722 /* Process the reasons (interrupt, signals) */
726 * Run in a while loop, to save clearing the interrupts
727 * every time around the outside loop.
731 /* If configured to run the HIP just once, skip first loop */
732 if (card
->intmode
& CSR_WIFI_INTMODE_RUN_BH_ONCE
)
737 r
= handle_host_protocol(card
, &more
);
738 if (r
!= CSR_RESULT_SUCCESS
)
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
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;
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;
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;
774 } while (more
|| card
->bh_reason_unifi
|| card
->bh_reason_host
);
776 /* Acknowledge the h/w interrupt */
777 r
= CardClearInt(card
);
778 if (r
!= CSR_RESULT_SUCCESS
)
780 unifi_error(card
->ospriv
, "Failed to acknowledge interrupt.\n");
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.
789 r
= handle_host_protocol(card
, &more
);
790 if (r
!= CSR_RESULT_SUCCESS
)
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
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;
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;
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;
824 /* If configured to run the HIP just once, work is now done */
825 if (card
->intmode
& CSR_WIFI_INTMODE_RUN_BH_ONCE
)
830 } while (more
|| card
->bh_reason_unifi
|| card
->bh_reason_host
);
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)
835 unifi_debug_log_to_buf("proc=%d\n",
836 card
->cmd_prof
.process_count
);
840 return CSR_RESULT_SUCCESS
;
845 * ---------------------------------------------------------------------------
846 * handle_host_protocol
848 * This function implements the Host Interface Protocol (HIP) as
849 * described in the Host Interface Protocol Specification.
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)
858 * CSR_RESULT_SUCCESS on success or CSR error code.
859 * ---------------------------------------------------------------------------
861 static CsrResult
handle_host_protocol(card_t
*card
, u8
*processed_something
)
866 *processed_something
= FALSE
;
868 #ifdef CSR_WIFI_HIP_NOISY
869 unifi_error(card
->ospriv
, " ======================== \n");
870 #endif /* CSR_WIFI_HIP_NOISY */
872 #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
873 card
->cmd_prof
.process_count
++;
876 card
->bh_reason_unifi
= card
->bh_reason_host
= 0;
877 card
->generate_interrupt
= 0;
881 * (Re)fill the T-H signal buffer
883 r
= read_to_host_signals(card
, &done
);
884 if (r
!= CSR_RESULT_SUCCESS
)
886 unifi_error(card
->ospriv
, "Error occured reading to-host signals\n");
891 *processed_something
= TRUE
;
895 * Process any to-host signals.
896 * Perform any requested CMD53 transfers here, but just queue any
897 * bulk data command responses.
899 r
= process_to_host_signals(card
, &done
);
900 if (r
!= CSR_RESULT_SUCCESS
)
902 unifi_error(card
->ospriv
, "Error occured processing to-host signals\n");
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
)
911 unifi_error(card
->ospriv
, "Error occured processing from-host signals\n");
916 *processed_something
= TRUE
;
919 r
= process_fh_traffic_queue(card
, &done
);
920 if (r
!= CSR_RESULT_SUCCESS
)
922 unifi_error(card
->ospriv
, "Error occured processing from-host data signals\n");
927 *processed_something
= TRUE
;
930 /* Flush out the batch of signals to the UniFi. */
931 r
= flush_fh_buffer(card
);
932 if (r
!= CSR_RESULT_SUCCESS
)
934 unifi_error(card
->ospriv
, "Failed to copy from-host signals to UniFi\n");
940 * Send the host interrupt to say the queues have been modified.
942 if (card
->generate_interrupt
)
944 r
= CardGenInt(card
);
945 if (r
!= CSR_RESULT_SUCCESS
)
947 unifi_error(card
->ospriv
, "Failed to notify UniFi that queues have been modified.\n");
952 #ifdef CSR_WIFI_RX_PATH_SPLIT
953 #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
954 unifi_rx_queue_flush(card
->ospriv
);
958 /* See if we can re-enable transmission now */
959 restart_packet_flow(card
);
961 #ifdef CSR_PRE_ALLOC_NET_DATA
962 r
= prealloc_netdata_alloc(card
);
963 if (r
!= CSR_RESULT_SUCCESS
)
965 unifi_error(card
->ospriv
, "prealloc_netdata failed\n");
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.
975 } /* handle_host_protocol() */
979 * Rounds the given signal length in bytes to a whole number
982 #define GET_CHUNKS_FOR(SIG_FRAG_SIZE, LENGTH) (((LENGTH) + ((SIG_FRAG_SIZE)-1)) / (SIG_FRAG_SIZE))
986 * ---------------------------------------------------------------------------
987 * read_to_host_signals
989 * Read everything pending in the UniFi TH signal buffer.
990 * Only do it if the local buffer is empty.
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
998 * CSR error code if an error occurred.
999 * ---------------------------------------------------------------------------
1001 static CsrResult
read_to_host_signals(card_t
*card
, s32
*processed
)
1003 s32 count_thw
, count_thr
;
1004 s32 unread_chunks
, unread_bytes
;
1009 /* Read any pending signals or bulk data commands */
1010 count_thw
= unifi_read_shared_count(card
, card
->sdio_ctrl_addr
+ 4);
1013 unifi_error(card
->ospriv
, "Failed to read to-host sig written count\n");
1014 return CSR_RESULT_FAILURE
;
1016 card
->to_host_signals_w
= count_thw
; /* diag */
1018 count_thr
= card
->to_host_signals_r
;
1020 if (count_thw
== count_thr
)
1022 return CSR_RESULT_SUCCESS
;
1026 (((count_thw
- count_thr
) + 128) % 128) - card
->th_buffer
.count
;
1028 if (unread_chunks
== 0)
1030 return CSR_RESULT_SUCCESS
;
1033 unread_bytes
= card
->config_data
.sig_frag_size
* unread_chunks
;
1036 r
= unifi_bulk_rw(card
,
1037 card
->config_data
.tohost_sigbuf_handle
,
1038 card
->th_buffer
.ptr
,
1041 if (r
!= CSR_RESULT_SUCCESS
)
1043 unifi_error(card
->ospriv
, "Failed to read ToHost signal\n");
1047 card
->th_buffer
.ptr
+= unread_bytes
;
1048 card
->th_buffer
.count
+= (u16
)unread_chunks
;
1052 return CSR_RESULT_SUCCESS
;
1053 } /* read_to_host_signals() */
1057 * ---------------------------------------------------------------------------
1058 * update_to_host_signals_r
1060 * Advance the shared-memory count of chunks read from the to-host
1062 * Raise a UniFi internal interrupt to tell the firmware that the
1063 * count has changed.
1066 * card Pointer to card context struct
1067 * pending Number of chunks remaining
1070 * CSR_RESULT_SUCCESS on success or CSR error code
1071 * ---------------------------------------------------------------------------
1073 static CsrResult
update_to_host_signals_r(card_t
*card
, s16 pending
)
1077 card
->to_host_signals_r
=
1078 (card
->to_host_signals_r
+ (card
->th_buffer
.count
- pending
)) % 128;
1079 card
->th_buffer
.count
= pending
;
1081 /* Update the count of signals read */
1082 r
= unifi_write_8_or_16(card
, card
->sdio_ctrl_addr
+ 6,
1083 (u8
)card
->to_host_signals_r
);
1084 if (r
!= CSR_RESULT_SUCCESS
)
1086 unifi_error(card
->ospriv
, "Failed to update to-host signals read\n");
1090 r
= CardGenInt(card
);
1091 if (r
!= CSR_RESULT_SUCCESS
)
1093 unifi_error(card
->ospriv
, "Failed to notify UniFi that we processed to-host signals.\n");
1097 card
->generate_interrupt
= 0;
1099 return CSR_RESULT_SUCCESS
;
1100 } /* update_to_host_signals_r() */
1104 * ---------------------------------------------------------------------------
1107 * Converts a wire-formatted command to the host bulk_data_cmd_t structure.
1110 * ptr Pointer to the command
1111 * bulk_data_cmd Pointer to the host structure
1115 * ---------------------------------------------------------------------------
1117 static void read_unpack_cmd(const u8
*ptr
, bulk_data_cmd_t
*bulk_data_cmd
)
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 */
1132 * ---------------------------------------------------------------------------
1133 * process_to_host_signals
1135 * Read and dispatch signals from the UniFi
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
1144 * CSR error code if there was an error
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.
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 * ---------------------------------------------------------------------------
1162 static CsrResult
process_to_host_signals(card_t
*card
, s32
*processed
)
1167 bulk_data_param_t data_ptrs
;
1172 u16 bytes_transferred
= 0;
1173 CsrResult r
= CSR_RESULT_SUCCESS
;
1177 pending
= card
->th_buffer
.count
;
1179 /* Are there new to-host signals? */
1180 unifi_trace(card
->ospriv
, UDBG4
, "handling %d to-host chunks\n", pending
);
1184 return CSR_RESULT_SUCCESS
;
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.
1192 bufptr
= card
->th_buffer
.buf
;
1196 s16 f_flush_count
= 0;
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.
1203 cmd
= bufptr
[1] >> 4;
1204 sig_len
= bufptr
[0] + ((bufptr
[1] & 0x0F) << 8);
1206 #ifdef CSR_WIFI_HIP_NOISY
1207 unifi_error(card
->ospriv
, "Received UniFi msg cmd=%d, len=%d\n",
1209 #endif /* CSR_WIFI_HIP_NOISY */
1211 if ((sig_len
== 0) &&
1212 ((cmd
!= SDIO_CMD_CLEAR_SLOT
) && (cmd
!= SDIO_CMD_PADDING
)))
1214 unifi_error(card
->ospriv
, "incomplete signal or command: has size zero\n");
1215 return CSR_RESULT_FAILURE
;
1218 * Make sure the buffer contains a complete message.
1219 * Signals may occupy multiple chunks, bulk-data commands occupy
1222 if (cmd
== SDIO_CMD_SIGNAL
)
1224 chunks_in_buf
= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
, (u16
)(sig_len
+ 2));
1231 if (chunks_in_buf
> (u16
)pending
)
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
;
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
++;
1251 for (i
= 0; i
< UNIFI_MAX_DATA_REFERENCES
; i
++)
1253 /* Retrieve dataRefs[i].DataLength */
1254 u16 data_len
= GET_PACKED_DATAREF_LEN(bufptr
+ 2, i
);
1257 * The bulk data length in the signal can not be greater than
1258 * the maximun length allowed by the SDIO config structure.
1260 if (data_len
> card
->config_data
.data_slot_size
)
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
;
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.
1275 /* Retrieve dataRefs[i].SlotNumber */
1276 s16 slot
= GET_PACKED_DATAREF_SLOT(bufptr
+ 2, i
);
1278 if (slot
>= card
->config_data
.num_tohost_data_slots
)
1280 unifi_error(card
->ospriv
, "!!!bad slot number in to-host signal: %d, sig 0x%X\n",
1282 return CSR_RESULT_FAILURE
;
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
;
1292 UNIFI_INIT_BULK_DATA(&data_ptrs
.d
[i
]);
1297 * Log the signal to the UDI, before call unifi_receive_event() as
1298 * it can modify the bulk data.
1302 (*card
->udi_hook
)(card
->ospriv
, bufptr
+ 2, sig_len
,
1303 &data_ptrs
, UDI_LOG_TO_HOST
);
1306 #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
1307 if (GET_SIGNAL_ID(bufptr
+ 2) == CSR_MA_PACKET_CONFIRM_ID
)
1309 card
->cmd_prof
.tx_cfm_count
++;
1311 else if (GET_SIGNAL_ID(bufptr
+ 2) == CSR_MA_PACKET_INDICATION_ID
)
1313 if (data_ptrs
.d
[0].os_data_ptr
)
1315 if ((*data_ptrs
.d
[0].os_data_ptr
) & 0x08)
1317 card
->cmd_prof
.rx_count
++;
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
1331 if (GET_SIGNAL_ID(bufptr
+ 2) == CSR_MA_PACKET_CONFIRM_ID
)
1333 /* Get host tag and transmission status */
1334 u32 host_tag
= GET_PACKED_MA_PACKET_CONFIRM_HOST_TAG(bufptr
+ 2);
1335 u16 status
= GET_PACKED_MA_PACKET_CONFIRM_TRANSMISSION_STATUS(bufptr
+ 2);
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
);
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
1344 if (status
&& (card
->fh_slot_host_tag_record
))
1346 u16 num_fh_slots
= card
->config_data
.num_fromhost_data_slots
;
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
1351 for (i
= 0; i
< num_fh_slots
; i
++)
1353 if (card
->fh_slot_host_tag_record
[i
] == host_tag
)
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
)
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
);
1366 CardClearFromHostDataSlotWithoutFreeingBulkData(card
, i
);
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
;
1373 /* Set length field in from_host_data array to 0 */
1374 CardClearFromHostDataSlot(card
, i
);
1382 /* Pass event to OS layer */
1383 unifi_receive_event(card
->ospriv
, bufptr
+ 2, sig_len
, &data_ptrs
);
1385 /* Initialise the to_host data, so it can be re-used. */
1386 for (i
= 0; i
< UNIFI_MAX_DATA_REFERENCES
; i
++)
1388 /* The slot is only valid if the length is non-zero. */
1389 if (GET_PACKED_DATAREF_LEN(bufptr
+ 2, i
) != 0)
1391 s16 slot
= GET_PACKED_DATAREF_SLOT(bufptr
+ 2, i
);
1392 if (slot
< card
->config_data
.num_tohost_data_slots
)
1394 UNIFI_INIT_BULK_DATA(&card
->to_host_data
[slot
]);
1399 #ifndef CSR_WIFI_DEFER_TH_FLUSH
1401 * If we have previously transferred a lot of data, ack
1402 * the signals read so far, so f/w can reclaim the buffer
1405 if (bytes_transferred
>= TO_HOST_FLUSH_THRESHOLD
)
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
++;
1417 /* This is a clear slot command. */
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
;
1425 r
= process_clear_slot_command(card
, bufptr
);
1426 if (r
!= CSR_RESULT_SUCCESS
)
1428 unifi_error(card
->ospriv
, "Failed to process clear slot\n");
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. */
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
;
1445 r
= process_bulk_data_command(card
, bufptr
, cmd
, sig_len
);
1446 if (r
!= CSR_RESULT_SUCCESS
)
1448 unifi_error(card
->ospriv
, "Failed to process bulk cmd\n");
1451 /* Count the bytes transferred */
1452 bytes_transferred
+= sig_len
;
1454 if (cmd
== SDIO_CMD_FROM_HOST_AND_CLEAR
)
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
++;
1459 #ifndef CSR_WIFI_DEFER_TH_FLUSH
1463 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
1464 else if (cmd
== SDIO_CMD_FROM_HOST_TRANSFER
)
1466 card
->cmd_prof
.sdio_cmd_from_host
++;
1468 else if (cmd
== SDIO_CMD_TO_HOST_TRANSFER
)
1470 card
->cmd_prof
.sdio_cmd_to_host
++;
1475 case SDIO_CMD_PADDING
:
1479 unifi_error(card
->ospriv
, "Unrecognised to-host command: %d\n", cmd
);
1483 bufptr
+= chunks_in_buf
* card
->config_data
.sig_frag_size
;
1484 pending
-= chunks_in_buf
;
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.
1493 r
= update_to_host_signals_r(card
, pending
);
1494 if (r
!= CSR_RESULT_SUCCESS
)
1498 bytes_transferred
= 0;
1504 unifi_warning(card
->ospriv
, "proc_th_sigs: %d unprocessed\n", pending
);
1507 /* If we processed any signals, write the updated count to UniFi */
1508 if (card
->th_buffer
.count
!= pending
)
1510 r
= update_to_host_signals_r(card
, pending
);
1511 if (r
!= CSR_RESULT_SUCCESS
)
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.
1522 remaining
= card
->th_buffer
.ptr
- bufptr
;
1525 unifi_error(card
->ospriv
, "Processing TH signals overran the buffer\n");
1526 return CSR_RESULT_FAILURE
;
1530 /* Use a safe copy because source and destination may overlap */
1531 u8
*d
= card
->th_buffer
.buf
;
1539 card
->th_buffer
.ptr
= card
->th_buffer
.buf
+ remaining
;
1542 /* If we reach here then we processed something */
1544 return CSR_RESULT_SUCCESS
;
1545 } /* process_to_host_signals() */
1549 * ---------------------------------------------------------------------------
1550 * process_clear_slot_command
1552 * Process a clear slot command fom the UniFi.
1555 * card Pointer to card context struct
1556 * bdcmd Pointer to bulk-data command msg from UniFi
1559 * 0 on success, CSR error code on error
1560 * ---------------------------------------------------------------------------
1562 static CsrResult
process_clear_slot_command(card_t
*card
, const u8
*cmdptr
)
1567 data_slot
= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(cmdptr
+ SIZEOF_UINT16
);
1569 unifi_trace(card
->ospriv
, UDBG4
, "Processing clear slot cmd, slot=0x%X\n",
1572 slot
= data_slot
& 0x7FFF;
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 */
1578 if (data_slot
& SLOT_DIR_TO_HOST
)
1580 if (slot
>= card
->config_data
.num_tohost_data_slots
)
1582 unifi_error(card
->ospriv
,
1583 "Invalid to-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n",
1585 return CSR_RESULT_FAILURE
;
1587 /* clear to-host data slot */
1588 unifi_warning(card
->ospriv
, "Unexpected clear to-host data slot cmd: 0x%04x\n",
1593 if (slot
>= card
->config_data
.num_fromhost_data_slots
)
1595 unifi_error(card
->ospriv
,
1596 "Invalid from-host data slot in SDIO_CMD_CLEAR_SLOT: %d\n",
1598 return CSR_RESULT_FAILURE
;
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
1607 return CSR_RESULT_SUCCESS
;
1609 /* Set length field in from_host_data array to 0 */
1610 /* CardClearFromHostDataSlot(card, slot); */
1613 return CSR_RESULT_SUCCESS
;
1614 } /* process_clear_slot_command() */
1618 * ---------------------------------------------------------------------------
1619 * process_bulk_data_command
1621 * Process a bulk data request from the UniFi.
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
1634 * CSR_RESULT_SUCCESS on success, CSR error code on error
1635 * ---------------------------------------------------------------------------
1637 static CsrResult
process_bulk_data_command(card_t
*card
, const u8
*cmdptr
,
1640 bulk_data_desc_t
*bdslot
;
1641 #ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
1642 u8
*host_bulk_data_slot
;
1644 bulk_data_cmd_t bdcmd
;
1650 read_unpack_cmd(cmdptr
, &bdcmd
);
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
);
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.
1661 if (card
->sdio_io_block_pad
)
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
);
1667 slot
= bdcmd
.data_slot
& 0x7FFF;
1669 if (cmd
== SDIO_CMD_OVERLAY_TRANSFER
)
1671 return CSR_WIFI_HIP_RESULT_INVALID_VALUE
; /* Not used on CSR6xxx */
1675 if (bdcmd
.data_slot
& SLOT_DIR_TO_HOST
)
1677 /* Request is for to-host bulk data */
1679 /* Check sanity of slot number */
1680 if (slot
>= card
->config_data
.num_tohost_data_slots
)
1682 unifi_error(card
->ospriv
,
1683 "Invalid to-host data slot in SDIO bulk xfr req: %d\n",
1685 return CSR_RESULT_FAILURE
;
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
);
1692 r
= unifi_net_data_malloc(card
->ospriv
, &card
->to_host_data
[slot
], len
);
1694 if (r
!= CSR_RESULT_SUCCESS
)
1696 unifi_error(card
->ospriv
, "Failed to allocate t-h bulk data\n");
1697 return CSR_RESULT_FAILURE
;
1700 bdslot
= &card
->to_host_data
[slot
];
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
)
1706 unifi_error(card
->ospriv
, "Failed to align t-h bulk data buffer for DMA\n");
1707 return CSR_RESULT_FAILURE
;
1712 /* Request is for from-host bulk data */
1714 if (slot
>= card
->config_data
.num_fromhost_data_slots
)
1716 unifi_error(card
->ospriv
,
1717 "Invalid from-host data slot in SDIO bulk xfr req: %d\n",
1719 return CSR_RESULT_FAILURE
;
1721 bdslot
= &card
->from_host_data
[slot
].bd
;
1723 offset
= bdcmd
.offset
;
1725 /* Do the transfer */
1726 dir
= (cmd
== SDIO_CMD_TO_HOST_TRANSFER
)?
1727 UNIFI_SDIO_READ
: UNIFI_SDIO_WRITE
;
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
),
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
),
1740 bdcmd
.buffer_handle
,
1741 slot
, bdslot
->os_data_ptr
, offset
);
1742 #endif /* CSR_WIFI_HIP_NOISY */
1745 if (bdslot
->os_data_ptr
== NULL
)
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
,
1752 return CSR_WIFI_HIP_RESULT_INVALID_VALUE
;
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 */
1759 if (len
!= 0 && (dir
== UNIFI_SDIO_WRITE
) && (((ptrdiff_t)bdslot
->os_data_ptr
+ offset
) & 3))
1761 host_bulk_data_slot
= kmalloc(len
, GFP_KERNEL
);
1763 if (!host_bulk_data_slot
)
1765 unifi_error(card
->ospriv
, " failed to allocate request_data before unifi_bulk_rw\n");
1769 memcpy((void *)host_bulk_data_slot
,
1770 (void *)(bdslot
->os_data_ptr
+ offset
), len
);
1772 r
= unifi_bulk_rw(card
,
1773 bdcmd
.buffer_handle
,
1774 (void *)host_bulk_data_slot
,
1781 r
= unifi_bulk_rw(card
,
1782 bdcmd
.buffer_handle
,
1783 (void *)(bdslot
->os_data_ptr
+ offset
),
1788 if (r
== CSR_WIFI_HIP_RESULT_NO_DEVICE
)
1792 if (r
!= CSR_RESULT_SUCCESS
)
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
);
1804 bdslot
->data_length
= len
;
1806 if (cmd
== SDIO_CMD_FROM_HOST_AND_CLEAR
)
1808 if (slot
>= card
->config_data
.num_fromhost_data_slots
)
1810 unifi_error(card
->ospriv
,
1811 "Invalid from-host data slot in SDIO_CMD_FROM_HOST_AND_CLEAR: %d\n",
1813 return CSR_RESULT_FAILURE
;
1816 #ifdef CSR_WIFI_ALIGNMENT_WORKAROUND
1817 /* moving this check before we clear host data slot */
1818 if ((len
!= 0) && (dir
== UNIFI_SDIO_WRITE
) && (((ptrdiff_t)bdslot
->os_data_ptr
+ offset
) & 3))
1820 kfree(host_bulk_data_slot
);
1824 if (card
->fh_slot_host_tag_record
)
1826 unifi_trace(card
->ospriv
, UDBG5
, "CopyFromHostAndClearSlot Reset entry for slot=%d\n", slot
);
1828 /* reset the host tag entry for the corresponding slot */
1829 card
->fh_slot_host_tag_record
[slot
] = CSR_WIFI_HIP_RESERVED_HOST_TAG
;
1833 /* Set length field in from_host_data array to 0 */
1834 CardClearFromHostDataSlot(card
, slot
);
1837 return CSR_RESULT_SUCCESS
;
1838 } /* process_bulk_data_command() */
1842 * ---------------------------------------------------------------------------
1843 * check_fh_sig_slots
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.
1855 * CSR_RESULT_SUCCESS, otherwise CSR error code on error.
1856 * ---------------------------------------------------------------------------
1858 static CsrResult
check_fh_sig_slots(card_t
*card
, u16 needed
, s32
*space_fh
)
1861 u32 occupied_fh
, slots_fh
;
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
;
1868 /* Only read the space in from-host queue if necessary */
1869 occupied_fh
= (count_fhw
- count_fhr
) % 128;
1871 if (slots_fh
< occupied_fh
)
1877 *space_fh
= slots_fh
- occupied_fh
;
1880 if ((occupied_fh
!= 0) && (*space_fh
< needed
))
1882 count_fhr
= unifi_read_shared_count(card
, card
->sdio_ctrl_addr
+ 2);
1885 unifi_error(card
->ospriv
, "Failed to read from-host sig read count\n");
1886 return CSR_RESULT_FAILURE
;
1888 card
->from_host_signals_r
= count_fhr
; /* diag */
1890 occupied_fh
= (count_fhw
- count_fhr
) % 128;
1891 *space_fh
= slots_fh
- occupied_fh
;
1894 return CSR_RESULT_SUCCESS
;
1895 } /* check_fh_sig_slots() */
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.
1902 #define ROUND_UP_NEEDED_CHUNKS(_card, _needed_chunks) \
1904 u16 _chunks_per_block; \
1905 u16 _chunks_in_last_block; \
1907 if (_card->sdio_io_block_pad) \
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) \
1913 _needed_chunks = _needed_chunks + (_chunks_per_block - _chunks_in_last_block); \
1919 #define ROUND_UP_SPACE_CHUNKS(_card, _space_chunks) \
1921 u16 _chunks_per_block; \
1923 if (_card->sdio_io_block_pad) \
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); \
1935 * ---------------------------------------------------------------------------
1936 * process_fh_cmd_queue
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.
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
1948 * CSR error code if an error occurred.
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 * ---------------------------------------------------------------------------
1959 static CsrResult
process_fh_cmd_queue(card_t
*card
, s32
*processed
)
1961 q_t
*sigq
= &card
->fh_command_queue
;
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)
1978 return CSR_RESULT_SUCCESS
;
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))
1986 card_signal_t
*csptr
= CSR_WIFI_HIP_Q_SLOT_DATA(sigq
, q_index
);
1989 * Note that GET_CHUNKS_FOR() needs the size of the packed
1990 * (wire-formatted) structure
1992 pending_chunks
+= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
, (u16
)(csptr
->signal_length
+ 2));
1996 * Check whether UniFi has space for all the buffered bulk-data
1997 * commands and signals as well.
1999 needed_chunks
= pending_chunks
+ card
->fh_buffer
.count
;
2001 /* Round up to the block size if necessary */
2002 ROUND_UP_NEEDED_CHUNKS(card
, needed_chunks
);
2004 r
= check_fh_sig_slots(card
, needed_chunks
, &space_chunks
);
2005 if (r
!= CSR_RESULT_SUCCESS
)
2008 unifi_error(card
->ospriv
, "Failed to read fh sig count\n");
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 */
2019 * Coalesce as many from-host signals as possible
2020 * into a single block and write using a single CMD53
2022 if (needed_chunks
> (u16
)space_chunks
)
2024 /* Round up to the block size if necessary */
2025 ROUND_UP_SPACE_CHUNKS(card
, space_chunks
);
2028 * If the f/w has less free chunks than those already pending
2029 * return immediately.
2031 if ((u16
)space_chunks
<= card
->fh_buffer
.count
)
2034 * No room in UniFi for any signals after the buffered bulk
2035 * data commands have been sent.
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
;
2042 pending_chunks
= (u16
)(space_chunks
- card
->fh_buffer
.count
);
2045 while (pending_sigs
-- && pending_chunks
> 0)
2047 card_signal_t
*csptr
;
2049 u16 sig_chunks
, total_length
, free_chunks_in_fh_buffer
;
2050 bulk_data_param_t bulkdata
;
2052 u16 signal_length
= 0;
2054 /* Retrieve the entry at the head of the queue */
2055 q_index
= CSR_WIFI_HIP_Q_NEXT_R_SLOT(sigq
);
2057 /* Get a pointer to the containing card_signal_t struct */
2058 csptr
= CSR_WIFI_HIP_Q_SLOT_DATA(sigq
, q_index
);
2060 /* Get the new length of the packed signal */
2061 signal_length
= csptr
->signal_length
;
2063 if ((signal_length
& 1) || (signal_length
> UNIFI_PACKED_SIGBUF_SIZE
))
2065 unifi_error(card
->ospriv
, "process_fh_queue: Bad len: %d\n", signal_length
);
2066 return CSR_RESULT_FAILURE
;
2069 /* Need space for 2-byte SDIO protocol header + signal */
2070 sig_chunks
= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
, (u16
)(signal_length
+ 2));
2072 free_chunks_in_fh_buffer
= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
,
2073 (u16
)((card
->fh_buffer
.buf
+ UNIFI_FH_BUF_SIZE
) - card
->fh_buffer
.ptr
));
2074 if (free_chunks_in_fh_buffer
< sig_chunks
)
2077 unifi_notice(card
->ospriv
, "proc_fh_cmd_q: no room in fh buffer for 0x%.4X, deferring\n",
2078 (u16
)(GET_SIGNAL_ID(csptr
->sigbuf
)));
2082 packed_sigptr
= csptr
->sigbuf
;
2084 /* Claim and set up a from-host data slot */
2085 if (CSR_RESULT_FAILURE
== CardWriteBulkData(card
, csptr
, UNIFI_TRAFFIC_Q_MLME
))
2087 unifi_notice(card
->ospriv
, "proc_fh_cmd_q: no fh data slots for 0x%.4X, deferring\n",
2088 (u16
)(GET_SIGNAL_ID(csptr
->sigbuf
)));
2092 for (i
= 0; i
< UNIFI_MAX_DATA_REFERENCES
; i
++)
2094 if (csptr
->bulkdata
[i
].data_length
== 0)
2096 UNIFI_INIT_BULK_DATA(&bulkdata
.d
[i
]);
2100 bulkdata
.d
[i
].os_data_ptr
= csptr
->bulkdata
[i
].os_data_ptr
;
2101 bulkdata
.d
[i
].data_length
= csptr
->bulkdata
[i
].data_length
;
2104 /* Pass the free responsibility to the lower layer. */
2105 UNIFI_INIT_BULK_DATA(&csptr
->bulkdata
[i
]);
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 */
2116 /* Append packed signal to F-H buffer */
2117 total_length
= sig_chunks
* card
->config_data
.sig_frag_size
;
2119 card
->fh_buffer
.ptr
[0] = (u8
)(signal_length
& 0xff);
2120 card
->fh_buffer
.ptr
[1] =
2121 (u8
)(((signal_length
>> 8) & 0xf) | (SDIO_CMD_SIGNAL
<< 4));
2123 memcpy(card
->fh_buffer
.ptr
+ 2, packed_sigptr
, signal_length
);
2124 memset(card
->fh_buffer
.ptr
+ 2 + signal_length
, 0,
2125 total_length
- (2 + signal_length
));
2127 #ifdef CSR_WIFI_HIP_NOISY
2128 unifi_error(card
->ospriv
, "proc_fh: fh_buffer %d bytes \n",
2130 dump(card
->fh_buffer
.ptr
, signal_length
+ 2);
2131 unifi_trace(card
->ospriv
, UDBG1
, " \n");
2132 #endif /* CSR_WIFI_HIP_NOISY */
2134 card
->fh_buffer
.ptr
+= total_length
;
2135 card
->fh_buffer
.count
+= sig_chunks
;
2137 #ifdef CSR_WIFI_HIP_NOISY
2138 unifi_error(card
->ospriv
, "Added %d to fh buf, len now %d, count %d\n",
2140 card
->fh_buffer
.ptr
- card
->fh_buffer
.buf
,
2141 card
->fh_buffer
.count
);
2142 #endif /* CSR_WIFI_HIP_NOISY */
2145 pending_chunks
-= sig_chunks
;
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! */
2152 (*card
->udi_hook
)(card
->ospriv
, packed_sigptr
, signal_length
,
2153 &bulkdata
, UDI_LOG_FROM_HOST
);
2156 /* Remove entry from q */
2157 csptr
->signal_length
= 0;
2158 CSR_WIFI_HIP_Q_INC_R(sigq
);
2161 return CSR_RESULT_SUCCESS
;
2162 } /* process_fh_cmd_queue() */
2166 * ---------------------------------------------------------------------------
2167 * process_fh_traffic_queue
2169 * Take signals off the from-host queue and copy them to the UniFi.
2170 * Does nothing if the UniFi has no slots free.
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
2180 * CSR error code if an error occurred.
2183 * The from-host queue contains signal requests from the network driver
2184 * and any UDI clients interspersed.
2185 * ---------------------------------------------------------------------------
2187 static CsrResult
process_fh_traffic_queue(card_t
*card
, s32
*processed
)
2189 q_t
*sigq
= card
->fh_traffic_queue
;
2194 u16 pending_sigs
= 0;
2195 u16 pending_chunks
= 0;
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
--)
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
);
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))
2216 card_signal_t
*csptr
= CSR_WIFI_HIP_Q_SLOT_DATA(&sigq
[n
], q_index
);
2219 * Note that GET_CHUNKS_FOR() needs the size of the packed
2220 * (wire-formatted) structure
2222 pending_chunks
+= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
, (u16
)(csptr
->signal_length
+ 2));
2226 /* If there are no pending signals, just return */
2227 if (pending_sigs
== 0)
2230 return CSR_RESULT_SUCCESS
;
2234 * Check whether UniFi has space for all the buffered bulk-data
2235 * commands and signals as well.
2237 needed_chunks
= pending_chunks
+ card
->fh_buffer
.count
;
2239 /* Round up to the block size if necessary */
2240 ROUND_UP_NEEDED_CHUNKS(card
, needed_chunks
);
2242 r
= check_fh_sig_slots(card
, needed_chunks
, &space_chunks
);
2243 if (r
!= CSR_RESULT_SUCCESS
)
2246 unifi_error(card
->ospriv
, "Failed to read fh sig count\n");
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 */
2257 /* Coalesce as many from-host signals as possible
2258 into a single block and write using a single CMD53 */
2259 if (needed_chunks
> (u16
)space_chunks
)
2261 /* Round up to the block size if necessary */
2262 ROUND_UP_SPACE_CHUNKS(card
, space_chunks
);
2264 if ((u16
)space_chunks
<= card
->fh_buffer
.count
)
2267 * No room in UniFi for any signals after the buffered bulk
2268 * data commands have been sent.
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;
2276 pending_chunks
= (u16
)space_chunks
- card
->fh_buffer
.count
;
2279 q_no
= UNIFI_NO_OF_TX_QS
- 1;
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.
2289 card_signal_t
*csptr
;
2290 u16 sig_chunks
, total_length
, free_chunks_in_fh_buffer
;
2291 bulk_data_param_t bulkdata
;
2293 u16 signal_length
= 0;
2295 /* if this queue is empty go to next one. */
2296 if (CSR_WIFI_HIP_Q_SLOTS_USED(&sigq
[q_no
]) == 0)
2302 /* Retrieve the entry at the head of the queue */
2303 q_index
= CSR_WIFI_HIP_Q_NEXT_R_SLOT(&sigq
[q_no
]);
2305 /* Get a pointer to the containing card_signal_t struct */
2306 csptr
= CSR_WIFI_HIP_Q_SLOT_DATA(&sigq
[q_no
], q_index
);
2308 /* Get the new length of the packed signal */
2309 signal_length
= csptr
->signal_length
;
2311 if ((signal_length
& 1) || (signal_length
> UNIFI_PACKED_SIGBUF_SIZE
))
2313 unifi_error(card
->ospriv
, "process_fh_traffic_queue: Bad len: %d\n", signal_length
);
2314 return CSR_RESULT_FAILURE
;
2317 /* Need space for 2-byte SDIO protocol header + signal */
2318 sig_chunks
= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
, (u16
)(signal_length
+ 2));
2319 free_chunks_in_fh_buffer
= GET_CHUNKS_FOR(card
->config_data
.sig_frag_size
,
2320 (u16
)((card
->fh_buffer
.buf
+ UNIFI_FH_BUF_SIZE
) - card
->fh_buffer
.ptr
));
2321 if (free_chunks_in_fh_buffer
< sig_chunks
)
2324 unifi_notice(card
->ospriv
, "process_fh_traffic_queue: no more chunks.\n");
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
))
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
))
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
;
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
;
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
2356 * But in some cases the clear slot signal never comes and the slot remains --NOT-- freed for ever
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
2363 if (card
->fh_slot_host_tag_record
)
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;
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
;
2374 UNIFI_INIT_BULK_DATA(&bulkdata
.d
[1]);
2375 UNIFI_INIT_BULK_DATA(&csptr
->bulkdata
[0]);
2376 UNIFI_INIT_BULK_DATA(&csptr
->bulkdata
[1]);
2378 #ifdef CSR_WIFI_HIP_DATA_PLANE_PROFILE
2379 if (bulkdata
.d
[0].os_data_ptr
)
2381 if ((*bulkdata
.d
[0].os_data_ptr
) & 0x08)
2383 card
->cmd_prof
.tx_count
++;
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 */
2394 /* Append packed signal to F-H buffer */
2395 total_length
= sig_chunks
* card
->config_data
.sig_frag_size
;
2397 card
->fh_buffer
.ptr
[0] = (u8
)(signal_length
& 0xff);
2398 card
->fh_buffer
.ptr
[1] =
2399 (u8
)(((signal_length
>> 8) & 0xf) | (SDIO_CMD_SIGNAL
<< 4));
2401 memcpy(card
->fh_buffer
.ptr
+ 2, packed_sigptr
, signal_length
);
2402 memset(card
->fh_buffer
.ptr
+ 2 + signal_length
, 0,
2403 total_length
- (2 + signal_length
));
2405 #ifdef CSR_WIFI_HIP_NOISY
2406 unifi_error(card
->ospriv
, "proc_fh: fh_buffer %d bytes \n",
2408 dump(card
->fh_buffer
.ptr
, signal_length
+ 2);
2409 unifi_trace(card
->ospriv
, UDBG1
, " \n");
2410 #endif /* CSR_WIFI_HIP_NOISY */
2412 card
->fh_buffer
.ptr
+= total_length
;
2413 card
->fh_buffer
.count
+= sig_chunks
;
2415 #ifdef CSR_WIFI_HIP_NOISY
2416 unifi_error(card
->ospriv
, "Added %d to fh buf, len now %d, count %d\n",
2418 card
->fh_buffer
.ptr
- card
->fh_buffer
.buf
,
2419 card
->fh_buffer
.count
);
2420 #endif /* CSR_WIFI_HIP_NOISY */
2424 pending_chunks
-= sig_chunks
;
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! */
2431 (*card
->udi_hook
)(card
->ospriv
, packed_sigptr
, signal_length
,
2432 &bulkdata
, UDI_LOG_FROM_HOST
);
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;
2440 CSR_WIFI_HIP_Q_INC_R(&sigq
[q_no
]);
2441 } while ((pending_sigs
> 0) && (pending_chunks
> 0) && (q_no
>= 0));
2443 return CSR_RESULT_SUCCESS
;
2444 } /* process_fh_traffic_queue() */
2448 * ---------------------------------------------------------------------------
2451 * Write out the cache from-hosts signals to the UniFi.
2454 * card Pointer to card context struct
2457 * CSR error code if an SDIO error occurred.
2458 * ---------------------------------------------------------------------------
2460 static CsrResult
flush_fh_buffer(card_t
*card
)
2466 u16 chunks_in_last_block
;
2470 len
= card
->fh_buffer
.ptr
- card
->fh_buffer
.buf
;
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 */
2479 return CSR_RESULT_SUCCESS
;
2482 #ifdef CSR_WIFI_HIP_NOISY
2485 dump(card
->fh_buffer
.buf
, len
);
2488 #endif /* CSR_WIFI_HIP_NOISY */
2490 if (card
->sdio_io_block_pad
)
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
;
2496 if (data_round
> sig_units
)
2498 chunks_in_last_block
= (len
% data_round
) / sig_units
;
2500 if (chunks_in_last_block
!= 0)
2502 padding_chunks
= (data_round
/ sig_units
) - chunks_in_last_block
;
2504 memset(card
->fh_buffer
.ptr
, 0, padding_chunks
* sig_units
);
2505 for (i
= 0; i
< padding_chunks
; i
++)
2507 card
->fh_buffer
.ptr
[1] = SDIO_CMD_PADDING
<< 4;
2508 card
->fh_buffer
.ptr
+= sig_units
;
2511 card
->fh_buffer
.count
+= padding_chunks
;
2512 len
+= padding_chunks
* sig_units
;
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
)
2525 if (r
!= CSR_RESULT_SUCCESS
)
2527 unifi_error(card
->ospriv
, "Failed to write fh signals: %u bytes, error %d\n", len
, r
);
2531 /* Update from-host-signals-written signal count */
2532 card
->from_host_signals_w
=
2533 (card
->from_host_signals_w
+ card
->fh_buffer
.count
) % 128u;
2534 r
= unifi_write_8_or_16(card
, card
->sdio_ctrl_addr
+ 0,
2535 (u8
)card
->from_host_signals_w
);
2536 if (r
!= CSR_RESULT_SUCCESS
)
2538 unifi_error(card
->ospriv
, "Failed to write fh signal count %u with error %d\n",
2539 card
->from_host_signals_w
, r
);
2542 card
->generate_interrupt
= 1;
2544 /* Reset the fh buffer pointer */
2545 card
->fh_buffer
.ptr
= card
->fh_buffer
.buf
;
2546 card
->fh_buffer
.count
= 0;
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 */
2554 return CSR_RESULT_SUCCESS
;
2555 } /* flush_fh_buffer() */
2559 * ---------------------------------------------------------------------------
2560 * restart_packet_flow
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.
2567 * card Pointer to card context struct
2571 * ---------------------------------------------------------------------------
2573 static void restart_packet_flow(card_t
*card
)
2578 * We only look at the fh_traffic_queue, because that is where packets from
2579 * the network stack are placed.
2581 for (q
= 0; q
<= UNIFI_TRAFFIC_Q_VO
; q
++)
2583 if (card_is_tx_q_paused(card
, q
) &&
2584 CSR_WIFI_HIP_Q_SLOTS_FREE(&card
->fh_traffic_queue
[q
]) >= RESUME_XMIT_THRESHOLD
)
2586 #if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
2587 unifi_debug_log_to_buf("U");
2589 card_tx_q_unpause(card
, q
);
2590 unifi_restart_xmit(card
->ospriv
, (unifi_TrafficQueue
)q
);
2593 } /* restart_packet_flow() */