Ejemplo n.º 1
0
int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg)
{
    u8 enable_okc;
    u8 *enable_okc_params;
    int rc;

    CsrWifiSmeStaConfig staConfig;
    CsrWifiSmeDeviceConfig deviceConfig;

    enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
    if (get_user(enable_okc, (u8*)enable_okc_params)) {
        unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n");
        return -EFAULT;
    }

    unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no"));

    rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
    if (rc) {
        unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
        return -EFAULT;
    }

    staConfig.enableOpportunisticKeyCaching = enable_okc;

    rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
    if (rc) {
        unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
        rc = -EFAULT;
    }

    return rc;
}
Ejemplo n.º 2
0
    void
uf_sme_config_wq(struct work_struct *work)
{
    CsrWifiSmeStaConfig  staConfig;
    CsrWifiSmeDeviceConfig  deviceConfig;
    unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);

    /* Register to receive indications from the SME */
    CsrWifiSmeEventMaskSetReqSend(0,
            CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY |
            CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE);

    if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) {
        unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
        return;
    }

    if (priv->if_index == CSR_INDEX_5G) {
        staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0;
    } else {
        staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4;
    }

    deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d;
    if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) {
        unifi_warning(priv,
                "SME config for 802.11d Trust Level and Radio Band failed.\n");
        return;
    }

} /* uf_sme_config_wq() */
Ejemplo n.º 3
0
void
uf_sme_config_wq(struct work_struct *work)
{
    unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);
    unifi_AppValue sme_app_value;

    /* Register to receive indications from the SME */
    unifi_mgt_event_mask_set_req(priv->smepriv, NULL,
                                 unifi_IndWifiOff | unifi_IndConnectionQuality |
                                 unifi_IndMediaStatus | unifi_IndMicFailure);

    sme_app_value.id = unifi_SmeConfigValue;
    if (sme_mgt_get_value(priv, &sme_app_value)) {
        unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
        return;
    }

    if (priv->if_index == CSR_INDEX_5G) {
        sme_app_value.unifi_Value_union.smeConfig.ifIndex = unifi_GHZ_5_0;
    } else {
        sme_app_value.unifi_Value_union.smeConfig.ifIndex = unifi_GHZ_2_4;
    }

    sme_app_value.unifi_Value_union.smeConfig.trustLevel = (unifi_80211dTrustLevel)tl_80211d;
    if (sme_mgt_set_value(priv, &sme_app_value)) {
        unifi_warning(priv,
                      "SME config for 802.11d Trust Level and Radio Band failed.\n");
        return;
    }

} /* uf_sme_config_wq() */
Ejemplo n.º 4
0
int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg)
{
    u8 strict_draft_n;
    u8 *strict_draft_n_params;
    int rc;

    CsrWifiSmeStaConfig  staConfig;
    CsrWifiSmeDeviceConfig  deviceConfig;

    strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
    if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) {
        unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n");
        return -EFAULT;
    }

    unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no"));

    rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);

    if (rc) {
        unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
        return -EFAULT;
    }

    deviceConfig.enableStrictDraftN = strict_draft_n;

    rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
    if (rc) {
        unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
        rc = -EFAULT;
    }

    return rc;
}
Ejemplo n.º 5
0
/*
 * ---------------------------------------------------------------------------
 *  unifi_ta_indicate_protocol
 *
 *      Report that a packet of a particular type has been seen
 *
 *  Arguments:
 *      drv_priv        The device context pointer passed to ta_init.
 *      protocol        The protocol type enum value.
 *      direction       Whether the packet was a tx or rx.
 *      src_addr        The source MAC address from the data packet.
 *
 *  Returns:
 *      None.
 *
 *  Notes:
 *      We defer the actual sending to a background workqueue,
 *      see uf_ta_ind_wq().
 * ---------------------------------------------------------------------------
 */
void
unifi_ta_indicate_protocol(void *ospriv,
                           CsrWifiRouterCtrlTrafficPacketType packet_type,
                           CsrWifiRouterCtrlProtocolDirection direction,
                           const CsrWifiMacAddress *src_addr)
{
    unifi_priv_t *priv = (unifi_priv_t*)ospriv;

    if (priv->ta_ind_work.in_use) {
        unifi_warning(priv,
                "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n");
        return;
    }

    if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX == direction)
    {
        u16 interfaceTag = 0;
        CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
                interfaceTag,
                packet_type,
                direction,
                *src_addr);
    }
    else
    {
        priv->ta_ind_work.packet_type = packet_type;
        priv->ta_ind_work.direction = direction;
        priv->ta_ind_work.src_addr = *src_addr;

        queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task);
    }

} /* unifi_ta_indicate_protocol() */
Ejemplo n.º 6
0
/*
 * ---------------------------------------------------------------------------
 * unifi_ta_indicate_sampling
 *
 *      Send the TA sampling information to the SME.
 * 
 *  Arguments:
 *      drv_priv        The device context pointer passed to ta_init.
 *      stats   The TA sampling data to send.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
void
unifi_ta_indicate_sampling(void *ospriv, unifi_TrafficStats *stats)
{
    unifi_priv_t *priv = (unifi_priv_t*)ospriv;

    if (!priv) {
        return;
    }

    if (priv->ta_sample_ind_work.in_use) {
        unifi_warning(priv,
                      "unifi_ta_indicate_sampling: workqueue item still in use, not sending\n");
        return;
    }

    priv->ta_sample_ind_work.stats = *stats;

    queue_work(priv->unifi_workqueue, &priv->ta_sample_ind_work.task);

} /* unifi_ta_indicate_sampling() */
Ejemplo n.º 7
0
/*
 * ---------------------------------------------------------------------------
 *  unifi_ta_indicate_protocol
 *
 *      Report that a packet of a particular type has been seen
 * 
 *  Arguments:
 *      drv_priv        The device context pointer passed to ta_init.
 *      protocol        The protocol type enum value.
 *      direction       Whether the packet was a tx or rx.
 *      src_addr        The source MAC address from the data packet.
 *
 *  Returns:
 *      None.
 *
 *  Notes:
 *      We defer the actual sending to a background workqueue,
 *      see uf_ta_ind_wq().
 * ---------------------------------------------------------------------------
 */
void
unifi_ta_indicate_protocol(void *ospriv, 
                           unifi_TrafficPacketType packet_type,
                           unifi_ProtocolDirection direction,
                           const unifi_MACAddress *src_addr)
{
    unifi_priv_t *priv = (unifi_priv_t*)ospriv;

    if (priv->ta_ind_work.in_use) {
        unifi_warning(priv,
                      "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n");
        return;
    }

    priv->ta_ind_work.packet_type = packet_type;
    priv->ta_ind_work.direction = direction;
    priv->ta_ind_work.src_addr = *src_addr;

    queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task);

} /* unifi_ta_indicate_protocol() */
Ejemplo n.º 8
0
/*
 * ---------------------------------------------------------------------------
 *  uf_send_pkt_to_encrypt
 *
 *      Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
 *      These are done in a deferred work queue for two reasons:
 *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
 *       - we want to load the main driver data path as lightly as possible
 *
 *  Arguments:
 *      work    Pointer to work queue item.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
void uf_send_pkt_to_encrypt(struct work_struct *work)
{
    netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
    u16 interfaceTag = interfacePriv->InterfaceTag;
    unifi_priv_t *priv = interfacePriv->privPtr;

    u32 pktBulkDataLength;
    u8 *pktBulkData;
    unsigned long flags;

    if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {

        pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;

        if (pktBulkDataLength > 0) {
		    pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
	    } else {
		    unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
		    return;
	    }

        spin_lock_irqsave(&priv->wapi_lock, flags);
        /* Copy over the MA PKT REQ bulk data */
        memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
        /* Free any bulk data buffers allocated for the WAPI Data pkt */
        unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
        interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
        interfacePriv->wapi_unicast_bulk_data.data_length = 0;
        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
        spin_unlock_irqrestore(&priv->wapi_lock, flags);

        CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
        unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");

        kfree(pktBulkData); /* Would have been copied over by the SME Handler */

    } else {
	    unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n", interfacePriv->interfaceMode);
    }
}/* uf_send_pkt_to_encrypt() */
Ejemplo n.º 9
0
static CsrResult
ConvertSdioToCsrSdioResult(int r)
{
    CsrResult csrResult = CSR_RESULT_FAILURE;

    switch (r) {
    case 0:
        csrResult = CSR_RESULT_SUCCESS;
    break;
    case -EIO:
    case -EILSEQ:
        csrResult = CSR_SDIO_RESULT_CRC_ERROR;
    break;
    /* Timeout errors */
    case -ETIMEDOUT:
    case -EBUSY:
        csrResult = CSR_SDIO_RESULT_TIMEOUT;
    break;
    case -ENODEV:
    case -ENOMEDIUM:
        csrResult = CSR_SDIO_RESULT_NO_DEVICE;
    break;
    case -EINVAL:
        csrResult = CSR_SDIO_RESULT_INVALID_VALUE;
    break;
    case -ENOMEM:
    case -ENOSYS:
    case -ERANGE:
    case -ENXIO:
        csrResult = CSR_RESULT_FAILURE;
    break;
    default:
        unifi_warning(NULL, "Unrecognised SDIO error code: %d\n", r);
    break;
    }

    return csrResult;
}
Ejemplo n.º 10
0
int sme_mgt_wifi_on(unifi_priv_t *priv)
{
    int r,i;
    s32 csrResult;

    if (priv == NULL) {
        return -EINVAL;
    }
    /* Initialize the interface mode to None */
    for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
        priv->interfacePriv[i]->interfaceMode = 0;
    }

    /* Set up interface mode so that get_packet_priority() can
     * select the right QOS priority when WMM is enabled.
     */
    priv->interfacePriv[0]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_STA;

    r = uf_request_firmware_files(priv, UNIFI_FW_STA);
    if (r) {
        unifi_error(priv, "sme_mgt_wifi_on: Failed to get f/w\n");
        return r;
    }

    /*
     * The request to initialise UniFi might come while UniFi is running.
     * We need to block all I/O activity until the reset completes, otherwise
     * an SDIO error might occur resulting an indication to the SME which
     * makes it think that the initialisation has failed.
     */
    priv->bh_thread.block_thread = 1;

    /* Power on UniFi */
    CsrSdioClaim(priv->sdio);
    csrResult = CsrSdioPowerOn(priv->sdio);
    CsrSdioRelease(priv->sdio);
    if(csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) {
        return -EIO;
    }

    if (csrResult == CSR_RESULT_SUCCESS) {
        /* Initialise UniFi hardware */
        r = uf_init_hw(priv);
        if (r) {
            return r;
        }
    }

    /* Re-enable the I/O thread */
    priv->bh_thread.block_thread = 0;

    /* Disable deep sleep signalling during the firmware initialisation, to
     * prevent the wakeup mechanism raising the SDIO clock beyond INIT before
     * the first MLME-RESET.ind. It gets re-enabled at the CONNECTED.ind,
     * immediately after the MLME-RESET.ind
     */
    csrResult = unifi_configure_low_power_mode(priv->card,
                                           UNIFI_LOW_POWER_DISABLED,
                                           UNIFI_PERIODIC_WAKE_HOST_DISABLED);
    if (csrResult != CSR_RESULT_SUCCESS) {
        unifi_warning(priv,
                      "sme_mgt_wifi_on: unifi_configure_low_power_mode() returned an error\n");
    }


    /* Start the I/O thread */
    CsrSdioClaim(priv->sdio);
    r = uf_init_bh(priv);
    if (r) {
        CsrSdioPowerOff(priv->sdio);
        CsrSdioRelease(priv->sdio);
        return r;
    }
    CsrSdioRelease(priv->sdio);

    priv->init_progress = UNIFI_INIT_FW_DOWNLOADED;

    return 0;
}
/*
 * ---------------------------------------------------------------------------
 *  send_signal
 *
 *      This function queues a signal for sending to UniFi.  It first checks
 *      that there is space on the fh_signal_queue for another entry, then
 *      claims any bulk data slots required and copies data into them. Then
 *      increments the fh_signal_queue write count.
 *
 *      The fh_signal_queue is later processed by the driver bottom half
 *      (in unifi_bh()).
 *
 *      This function call unifi_pause_xmit() to pause the flow of data plane
 *      packets when:
 *        - the fh_signal_queue ring buffer is full
 *        - there are less than UNIFI_MAX_DATA_REFERENCES (2) bulk data
 *          slots available.
 *
 *  Arguments:
 *      card            Pointer to card context structure
 *      sigptr          Pointer to the signal to write to UniFi.
 *      siglen          Number of bytes pointer to by sigptr.
 *      bulkdata        Array of pointers to an associated bulk data.
 *      sigq            To which from-host queue to add the signal.
 *
 *  Returns:
 *      CSR_RESULT_SUCCESS on success
 *      CSR_WIFI_HIP_RESULT_NO_SPACE if there were insufficient data slots or
 *                              no free signal queue entry
 *
 * Notes:
 *      Calls unifi_pause_xmit() when the last slots are used.
 * ---------------------------------------------------------------------------
 */
static CsrResult send_signal(card_t *card, const CsrUint8 *sigptr, CsrUint32 siglen,
                             const bulk_data_param_t *bulkdata,
                             q_t *sigq, CsrUint32 priority_q, CsrUint32 run_bh)
{
    CsrUint16 i, data_slot_size;
    card_signal_t *csptr;
    CsrInt16 qe;
    CsrResult r;
    CsrInt16 debug_print = 0;
#ifdef CSR_WIFI_RUN_BH_CHECK
    CsrUint8 from_host_used_slots = 0;
#endif

    data_slot_size = CardGetDataSlotSize(card);

    /* Check that the fh_data_queue has a free slot */
    if (!CSR_WIFI_HIP_Q_SLOTS_FREE(sigq))
    {
        unifi_trace(card->ospriv, UDBG3, "send_signal: %s full\n", sigq->name);

        return CSR_WIFI_HIP_RESULT_NO_SPACE;
    }

    /*
     * Now add the signal to the From Host signal queue
     */
    /* Get next slot on queue */
    qe = CSR_WIFI_HIP_Q_NEXT_W_SLOT(sigq);
    csptr = CSR_WIFI_HIP_Q_SLOT_DATA(sigq, qe);

    /* Make up the card_signal struct */
    csptr->signal_length = (CsrUint16)siglen;
    CsrMemCpy((void *)csptr->sigbuf, (void *)sigptr, siglen);

    for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
    {
        if ((bulkdata != NULL) && (bulkdata->d[i].data_length != 0))
        {
            CsrUint32 datalen = bulkdata->d[i].data_length;

            /* Make sure data will fit in a bulk data slot */
            if (bulkdata->d[i].os_data_ptr == NULL)
            {
                unifi_error(card->ospriv, "send_signal - NULL bulkdata[%d]\n", i);
                debug_print++;
                csptr->bulkdata[i].data_length = 0;
            }
            else
            {
                if (datalen > data_slot_size)
                {
                    unifi_error(card->ospriv,
                                "send_signal - Invalid data length %u (@%p), "
                                "truncating\n",
                                datalen, bulkdata->d[i].os_data_ptr);
                    datalen = data_slot_size;
                    debug_print++;
                }
                /* Store the bulk data info in the soft queue. */
                csptr->bulkdata[i].os_data_ptr = (CsrUint8 *)bulkdata->d[i].os_data_ptr;
                csptr->bulkdata[i].os_net_buf_ptr = (CsrUint8 *)bulkdata->d[i].os_net_buf_ptr;
                csptr->bulkdata[i].net_buf_length = bulkdata->d[i].net_buf_length;
                csptr->bulkdata[i].data_length = datalen;
            }
        }
        else
        {
            UNIFI_INIT_BULK_DATA(&csptr->bulkdata[i]);
        }
    }

    if (debug_print)
    {
        const CsrUint8 *sig = sigptr;

        unifi_error(card->ospriv, "Signal(%d): %02x %02x %02x %02x %02x %02x %02x %02x"
                    " %02x %02x %02x %02x %02x %02x %02x %02x\n",
                    siglen,
                    sig[0], sig[1], sig[2], sig[3],
                    sig[4], sig[5], sig[6], sig[7],
                    sig[8], sig[9], sig[10], sig[11],
                    sig[12], sig[13], sig[14], sig[15]);
        unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n",
                    bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL,
                    bulkdata != NULL?bulkdata->d[0].data_length : 0,
                    bulkdata != NULL?bulkdata->d[1].os_data_ptr : NULL,
                    bulkdata != NULL?bulkdata->d[1].data_length : 0);
    }

    /* Advance the written count to say there is a new entry */
    CSR_WIFI_HIP_Q_INC_W(sigq);

#ifdef CSR_WIFI_RUN_BH_CHECK
    FROM_HOST_USED_SLOTS(card, from_host_used_slots);

    if (from_host_used_slots)
    {
        RUN_BH(sigq, card, priority_q, run_bh);
    }
#endif

    /*
     * Set the flag to say reason for waking was a host request.
     * Then ask the OS layer to run the unifi_bh.
     */
    if (run_bh == 1)
    {
        card->bh_reason_host = 1;
        r = unifi_run_bh(card->ospriv);
        if (r != CSR_RESULT_SUCCESS)
        {
            unifi_error(card->ospriv, "failed to run bh.\n");
            card->bh_reason_host = 0;

            /*
             * The bulk data buffer will be freed by the caller.
             * We need to invalidate the description of the bulk data in our
             * soft queue, to prevent the core freeing the bulk data again later.
             */
            for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; ++i)
            {
                if (csptr->bulkdata[i].data_length != 0)
                {
                    csptr->bulkdata[i].os_data_ptr = csptr->bulkdata[i].os_net_buf_ptr = NULL;
                    csptr->bulkdata[i].net_buf_length = csptr->bulkdata[i].data_length = 0;
                }
            }
            return r;
        }
    }
#ifndef CSR_WIFI_RUN_BH_CHECK
    else
    {
        unifi_error(card->ospriv, "run_bh=%d, bh not called.\n", run_bh);
    }
#endif

    /*
     * Have we used up all the fh signal list entries?
     */
    if (CSR_WIFI_HIP_Q_SLOTS_FREE(sigq) == 0)
    {
        /* We have filled the queue, so stop the upper layer. The command queue
         * is an exception, as suspending due to that being full could delay
         * resume/retry until new commands or data are received.
         */
        if (sigq != &card->fh_command_queue)
        {
            /*
             * Must call unifi_pause_xmit() *before* setting the paused flag.
             * (the unifi_pause_xmit call should not be after setting the flag because of the possibility of being interrupted
             * by the bh thread between our setting the flag and the call to unifi_pause_xmit()
             * If bh thread then cleared the flag, we would end up paused, but without the flag set)
             * Instead, setting it afterwards means that if this thread is interrupted by the bh thread
             * the pause flag is still guaranteed to end up set
             * However the potential deadlock now is that if bh thread emptied the queue and cleared the flag before this thread's
             * call to unifi_pause_xmit(), then bh thread may not run again because it will be waiting for
             * a packet to appear in the queue but nothing ever will because xmit is paused.
             * So we will end up with the queue paused, and the flag set to say it is paused, but bh never runs to unpause it.
             * (Note even this bad situation would not persist long in practice, because something else (eg rx, or tx in different queue)
             * is likely to wake bh thread quite soon)
             * But to avoid this deadlock completely, after setting the flag we check that there is something left in the queue.
             * If there is, we know that bh thread has not emptied the queue yet.
             * Since bh thread checks to unpause the queue *after* taking packets from the queue, we know that it is still going to make at
             * least one more check to see whether it needs to unpause the queue.  So all is well.
             * If there are no packets in the queue, then the deadlock described above might happen.  To make sure it does not, we
             * unpause the queue here. A possible side effect is that unifi_restart_xmit() may (rarely) be called for second time
             *  unnecessarily, which is harmless
             */

#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) && defined (CSR_WIFI_HIP_DATA_PLANE_PROFILE)
            unifi_debug_log_to_buf("P");
#endif
            unifi_pause_xmit(card->ospriv, (unifi_TrafficQueue)priority_q);
            card_tx_q_pause(card, priority_q);
            if (CSR_WIFI_HIP_Q_SLOTS_USED(sigq) == 0)
            {
                card_tx_q_unpause(card, priority_q);
                unifi_restart_xmit(card->ospriv, (unifi_TrafficQueue) priority_q);
            }
        }
        else
        {
            unifi_warning(card->ospriv,
                          "send_signal: fh_cmd_q full, not pausing (run_bh=%d)\n",
                          run_bh);
        }
    }

    func_exit();

    return CSR_RESULT_SUCCESS;
} /*  send_signal() */