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