linux/drivers/staging/csr/unifi_sme.c
<<
>>
Prefs
   1/*
   2 * ***************************************************************************
   3 *  FILE:     unifi_sme.c
   4 *
   5 *  PURPOSE:    SME related functions.
   6 *
   7 *  Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
   8 *
   9 * Refer to LICENSE.txt included with this source code for details on
  10 * the license terms.
  11 *
  12 * ***************************************************************************
  13 */
  14
  15#include "unifi_priv.h"
  16#include "csr_wifi_hip_unifi.h"
  17#include "csr_wifi_hip_conversions.h"
  18
  19
  20
  21
  22    int
  23convert_sme_error(CsrResult error)
  24{
  25    switch (error) {
  26        case CSR_RESULT_SUCCESS:
  27            return 0;
  28        case CSR_RESULT_FAILURE:
  29        case CSR_WIFI_RESULT_NOT_FOUND:
  30        case CSR_WIFI_RESULT_TIMED_OUT:
  31        case CSR_WIFI_RESULT_CANCELLED:
  32        case CSR_WIFI_RESULT_UNAVAILABLE:
  33            return -EIO;
  34        case CSR_WIFI_RESULT_NO_ROOM:
  35            return -EBUSY;
  36        case CSR_WIFI_RESULT_INVALID_PARAMETER:
  37            return -EINVAL;
  38        case CSR_WIFI_RESULT_UNSUPPORTED:
  39            return -EOPNOTSUPP;
  40        default:
  41            return -EIO;
  42    }
  43}
  44
  45
  46/*
  47 * ---------------------------------------------------------------------------
  48 *  sme_log_event
  49 *
  50 *      Callback function to be registered as the SME event callback.
  51 *      Copies the signal content into a new udi_log_t struct and adds
  52 *      it to the read queue for the SME client.
  53 *
  54 *  Arguments:
  55 *      arg             This is the value given to unifi_add_udi_hook, in
  56 *                      this case a pointer to the client instance.
  57 *      signal          Pointer to the received signal.
  58 *      signal_len      Size of the signal structure in bytes.
  59 *      bulkdata        Pointers to any associated bulk data.
  60 *      dir             Direction of the signal. Zero means from host,
  61 *                      non-zero means to host.
  62 *
  63 *  Returns:
  64 *      None.
  65 * ---------------------------------------------------------------------------
  66 */
  67    void
  68sme_log_event(ul_client_t *pcli,
  69        const u8 *signal, int signal_len,
  70        const bulk_data_param_t *bulkdata,
  71        int dir)
  72{
  73    unifi_priv_t *priv;
  74    CSR_SIGNAL unpacked_signal;
  75    CsrWifiSmeDataBlock mlmeCommand;
  76    CsrWifiSmeDataBlock dataref1;
  77    CsrWifiSmeDataBlock dataref2;
  78    CsrResult result = CSR_RESULT_SUCCESS;
  79    int r;
  80
  81    func_enter();
  82    /* Just a sanity check */
  83    if ((signal == NULL) || (signal_len <= 0)) {
  84        func_exit();
  85        return;
  86    }
  87
  88    priv = uf_find_instance(pcli->instance);
  89    if (!priv) {
  90        unifi_error(priv, "sme_log_event: invalid priv\n");
  91        func_exit();
  92        return;
  93    }
  94
  95    if (priv->smepriv == NULL) {
  96        unifi_error(priv, "sme_log_event: invalid smepriv\n");
  97        func_exit();
  98        return;
  99    }
 100
 101    unifi_trace(priv, UDBG3,
 102            "sme_log_event: Process signal 0x%.4X\n",
 103            CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal));
 104
 105
 106    /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */
 107    r = read_unpack_signal(signal, &unpacked_signal);
 108    if (r == CSR_RESULT_SUCCESS) {
 109        if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) ||
 110            (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID))
 111        {
 112            func_exit();
 113            return;
 114        }
 115        if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID)
 116        {
 117            u16 frmCtrl;
 118            u8 unicastPdu = TRUE;
 119            u8 *macHdrLocation;
 120            u8 *raddr = NULL, *taddr = NULL;
 121            CsrWifiMacAddress peerMacAddress;
 122            /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
 123            CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication;
 124
 125            macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
 126            /* Fetch the frame control value from  mac header */
 127            frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);
 128
 129            /* Point to the addresses */
 130            raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET;
 131            taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET;
 132
 133            memcpy(peerMacAddress.a, taddr, ETH_ALEN);
 134
 135            if(ind->ReceptionStatus == CSR_MICHAEL_MIC_ERROR)
 136            {
 137                if (*raddr & 0x1)
 138                    unicastPdu = FALSE;
 139
 140                CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0,
 141                        (ind->VirtualInterfaceIdentifier & 0xff),peerMacAddress,
 142                        unicastPdu);
 143                return;
 144            }
 145            else
 146            {
 147                if(ind->ReceptionStatus == CSR_RX_SUCCESS)
 148                {
 149                    u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00;
 150                    u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff);
 151                    CsrWifiRouterCtrlStaInfo_t *srcStaInfo =  CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,taddr,interfaceTag);
 152                    if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE))
 153                    {
 154                        uf_process_pm_bit_for_peer(priv,srcStaInfo,pmBit,interfaceTag);
 155
 156                        /* Update station last activity flag */
 157                        srcStaInfo->activity_flag = TRUE;
 158                    }
 159                }
 160            }
 161        }
 162
 163        if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_CONFIRM_ID)
 164        {
 165            CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm;
 166            u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff);
 167            netInterface_priv_t *interfacePriv;
 168            CSR_MA_PACKET_REQUEST *req;
 169            CsrWifiMacAddress peerMacAddress;
 170
 171            if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
 172            {
 173                unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag);
 174                func_exit();
 175                return;
 176            }
 177
 178            unifi_trace(priv,UDBG1,"MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus);
 179
 180            interfacePriv = priv->interfacePriv[interfaceTag];
 181#ifdef CSR_SUPPORT_SME
 182            if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
 183                 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
 184
 185                if(cfm->HostTag == interfacePriv->multicastPduHostTag){
 186                    uf_process_ma_pkt_cfm_for_ap(priv ,interfaceTag, cfm);
 187                }
 188            }
 189#endif
 190
 191            req = &interfacePriv->m4_signal.u.MaPacketRequest;
 192
 193            if(cfm->HostTag & 0x80000000)
 194            {
 195                if (cfm->TransmissionStatus != CSR_TX_SUCCESSFUL)
 196                {
 197                    result = CSR_RESULT_FAILURE;
 198                }
 199#ifdef CSR_SUPPORT_SME
 200                memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN);
 201                /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/
 202                if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag))
 203                {
 204                    unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__);
 205                    CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
 206                            interfaceTag,
 207                            peerMacAddress,
 208                            result);
 209                    interfacePriv->m4_sent = FALSE;
 210                    interfacePriv->m4_hostTag = 0xffffffff;
 211                }
 212#endif
 213                /* If EAPOL was requested via router APIs then send cfm else ignore*/
 214                if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) {
 215                    CsrWifiRouterMaPacketCfmSend((u16)signal[2],
 216                        cfm->VirtualInterfaceIdentifier,
 217                        result,
 218                        (cfm->HostTag & 0x3fffffff), cfm->Rate);
 219                } else {
 220                    unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__);
 221                }
 222                func_exit();
 223                return;
 224            }
 225        }
 226    }
 227
 228    mlmeCommand.length = signal_len;
 229    mlmeCommand.data = (u8*)signal;
 230
 231    dataref1.length = bulkdata->d[0].data_length;
 232    if (dataref1.length > 0) {
 233        dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr;
 234    } else
 235    {
 236        dataref1.data = NULL;
 237    }
 238
 239    dataref2.length = bulkdata->d[1].data_length;
 240    if (dataref2.length > 0) {
 241        dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr;
 242    } else
 243    {
 244        dataref2.data = NULL;
 245    }
 246
 247    CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data,
 248            dataref1.length, dataref1.data,
 249            dataref2.length, dataref2.data);
 250
 251    func_exit();
 252} /* sme_log_event() */
 253
 254
 255/*
 256 * ---------------------------------------------------------------------------
 257 * uf_sme_port_state
 258 *
 259 *      Return the state of the controlled port.
 260 *
 261 * Arguments:
 262 *      priv            Pointer to device private context struct
 263 *      address    Pointer to the destination for tx or sender for rx address
 264 *      queue           Controlled or uncontrolled queue
 265 *
 266 * Returns:
 267 *      An unifi_ControlledPortAction value.
 268 * ---------------------------------------------------------------------------
 269 */
 270CsrWifiRouterCtrlPortAction
 271uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
 272{
 273    int i;
 274    unifi_port_config_t *port;
 275    netInterface_priv_t *interfacePriv;
 276
 277    if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
 278        unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n");
 279        return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
 280    }
 281
 282    interfacePriv = priv->interfacePriv[interfaceTag];
 283
 284    if (queue == UF_CONTROLLED_PORT_Q) {
 285        port = &interfacePriv->controlled_data_port;
 286    } else {
 287        port = &interfacePriv->uncontrolled_data_port;
 288    }
 289
 290    if (!port->entries_in_use) {
 291        unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
 292        return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
 293    }
 294
 295    /* If the port configuration is common for all destinations, return it. */
 296    if (port->overide_action == UF_DATA_PORT_OVERIDE) {
 297        unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
 298                port->port_cfg[0].port_action);
 299        return port->port_cfg[0].port_action;
 300    }
 301
 302    unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use);
 303
 304    /* If multiple configurations exist.. */
 305    for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
 306        /* .. go through the list and match the destination address. */
 307        if (port->port_cfg[i].in_use &&
 308            memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
 309            /* Return the desired action. */
 310            return port->port_cfg[i].port_action;
 311        }
 312    }
 313
 314    /* Could not find any information, return Open. */
 315    unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n");
 316    return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN;
 317} /* uf_sme_port_state() */
 318
 319/*
 320 * ---------------------------------------------------------------------------
 321 * uf_sme_port_config_handle
 322 *
 323 *      Return the port config handle of the controlled/uncontrolled port.
 324 *
 325 * Arguments:
 326 *      priv            Pointer to device private context struct
 327 *      address    Pointer to the destination for tx or sender for rx address
 328 *      queue           Controlled or uncontrolled queue
 329 *
 330 * Returns:
 331 *      An  unifi_port_cfg_t* .
 332 * ---------------------------------------------------------------------------
 333 */
 334unifi_port_cfg_t*
 335uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
 336{
 337    int i;
 338    unifi_port_config_t *port;
 339    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
 340
 341    if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
 342        unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n");
 343        return NULL;
 344    }
 345
 346    if (queue == UF_CONTROLLED_PORT_Q) {
 347        port = &interfacePriv->controlled_data_port;
 348    } else {
 349        port = &interfacePriv->uncontrolled_data_port;
 350    }
 351
 352    if (!port->entries_in_use) {
 353        unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
 354        return NULL;
 355    }
 356
 357    /* If the port configuration is common for all destinations, return it. */
 358    if (port->overide_action == UF_DATA_PORT_OVERIDE) {
 359        unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
 360                port->port_cfg[0].port_action);
 361        if (address) {
 362            unifi_trace(priv, UDBG5, "addr[0] = %x, addr[1] = %x, addr[2] = %x, addr[3] = %x\n", address[0], address[1], address[2], address[3]);
 363        }
 364        return &port->port_cfg[0];
 365    }
 366
 367    unifi_trace(priv, UDBG5, "Multiple port configurations.\n");
 368
 369    /* If multiple configurations exist.. */
 370    for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
 371        /* .. go through the list and match the destination address. */
 372        if (port->port_cfg[i].in_use &&
 373            memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
 374            /* Return the desired action. */
 375            return &port->port_cfg[i];
 376        }
 377    }
 378
 379    /* Could not find any information, return Open. */
 380    unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n");
 381    return NULL;
 382} /* uf_sme_port_config_handle */
 383
 384void
 385uf_multicast_list_wq(struct work_struct *work)
 386{
 387    unifi_priv_t *priv = container_of(work, unifi_priv_t,
 388            multicast_list_task);
 389    int i;
 390    u16 interfaceTag = 0;
 391    CsrWifiMacAddress* multicast_address_list = NULL;
 392    int mc_count;
 393    u8 *mc_list;
 394    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
 395
 396    if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
 397        unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n");
 398        return;
 399    }
 400
 401    unifi_trace(priv, UDBG5,
 402            "uf_multicast_list_wq: list count = %d\n",
 403            interfacePriv->mc_list_count);
 404
 405    /* Flush the current list */
 406    CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL);
 407
 408    mc_count = interfacePriv->mc_list_count;
 409    mc_list = interfacePriv->mc_list;
 410    /*
 411     * Allocate a new list, need to free it later
 412     * in unifi_mgt_multicast_address_cfm().
 413     */
 414    multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL);
 415
 416    if (multicast_address_list == NULL) {
 417        return;
 418    }
 419
 420    for (i = 0; i < mc_count; i++) {
 421        memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN);
 422        mc_list += ETH_ALEN;
 423    }
 424
 425    if (priv->smepriv == NULL) {
 426        kfree(multicast_address_list);
 427        return;
 428    }
 429
 430    CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
 431            interfaceTag,
 432            CSR_WIFI_SME_LIST_ACTION_ADD,
 433            mc_count, multicast_address_list);
 434
 435    /* The SME will take a copy of the addreses*/
 436    kfree(multicast_address_list);
 437}
 438
 439
 440int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
 441{
 442    unifi_cfg_power_t cfg_power;
 443    int rc;
 444    int wol;
 445
 446    if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
 447        unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
 448        return -EFAULT;
 449    }
 450
 451    switch (cfg_power) {
 452        case UNIFI_CFG_POWER_OFF:
 453            priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
 454            rc = sme_sys_suspend(priv);
 455            if (rc) {
 456                return rc;
 457            }
 458            break;
 459        case UNIFI_CFG_POWER_ON:
 460            wol = priv->wol_suspend;
 461            rc = sme_sys_resume(priv);
 462            if (rc) {
 463                return rc;
 464            }
 465            if (wol) {
 466                /* Kick the BH to ensure pending transfers are handled when
 467                 * a suspend happened with card powered.
 468                 */
 469                unifi_send_signal(priv->card, NULL, 0, NULL);
 470            }
 471            break;
 472        default:
 473            unifi_error(priv, "WIFI POWER: Unknown value.\n");
 474            return -EINVAL;
 475    }
 476
 477    return 0;
 478}
 479
 480
 481int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg)
 482{
 483    unifi_cfg_powersave_t cfg_power_save;
 484    CsrWifiSmePowerConfig powerConfig;
 485    int rc;
 486
 487    if (get_user(cfg_power_save, (unifi_cfg_powersave_t*)(((unifi_cfg_command_t*)arg) + 1))) {
 488        unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
 489        return -EFAULT;
 490    }
 491
 492    /* Get the coex info from the SME */
 493    rc = sme_mgt_power_config_get(priv, &powerConfig);
 494    if (rc) {
 495        unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
 496        return rc;
 497    }
 498
 499    switch (cfg_power_save) {
 500        case UNIFI_CFG_POWERSAVE_NONE:
 501            powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
 502            break;
 503        case UNIFI_CFG_POWERSAVE_FAST:
 504            powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED;
 505            break;
 506        case UNIFI_CFG_POWERSAVE_FULL:
 507            powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
 508            break;
 509        case UNIFI_CFG_POWERSAVE_AUTO:
 510            powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO;
 511            break;
 512        default:
 513            unifi_error(priv, "POWERSAVE: Unknown value.\n");
 514            return -EINVAL;
 515    }
 516
 517    rc = sme_mgt_power_config_set(priv, &powerConfig);
 518
 519    if (rc) {
 520        unifi_error(priv, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n");
 521    }
 522
 523    return rc;
 524}
 525
 526
 527int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg)
 528{
 529    unifi_cfg_powersupply_t cfg_power_supply;
 530    CsrWifiSmeHostConfig hostConfig;
 531    int rc;
 532
 533    if (get_user(cfg_power_supply, (unifi_cfg_powersupply_t*)(((unifi_cfg_command_t*)arg) + 1))) {
 534        unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
 535        return -EFAULT;
 536    }
 537
 538    /* Get the coex info from the SME */
 539    rc = sme_mgt_host_config_get(priv, &hostConfig);
 540    if (rc) {
 541        unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
 542        return rc;
 543    }
 544
 545    switch (cfg_power_supply) {
 546        case UNIFI_CFG_POWERSUPPLY_MAINS:
 547            hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE;
 548            break;
 549        case UNIFI_CFG_POWERSUPPLY_BATTERIES:
 550            hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE;
 551            break;
 552        default:
 553            unifi_error(priv, "POWERSUPPLY: Unknown value.\n");
 554            return -EINVAL;
 555    }
 556
 557    rc = sme_mgt_host_config_set(priv, &hostConfig);
 558    if (rc) {
 559        unifi_error(priv, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n");
 560    }
 561
 562    return rc;
 563}
 564
 565
 566int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg)
 567{
 568    unsigned char *tclas_buffer;
 569    unsigned int tclas_buffer_length;
 570    tclas_t *dhcp_tclas;
 571    int rc;
 572
 573    /* Free any TCLASs previously allocated */
 574    if (priv->packet_filters.tclas_ies_length) {
 575        kfree(priv->filter_tclas_ies);
 576        priv->filter_tclas_ies = NULL;
 577    }
 578
 579    tclas_buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
 580    if (copy_from_user(&priv->packet_filters, (void*)tclas_buffer,
 581                sizeof(uf_cfg_bcast_packet_filter_t))) {
 582        unifi_error(priv, "UNIFI_CFG: Failed to get the filter struct\n");
 583        return -EFAULT;
 584    }
 585
 586    tclas_buffer_length = priv->packet_filters.tclas_ies_length;
 587
 588    /* Allocate TCLASs if necessary */
 589    if (priv->packet_filters.dhcp_filter) {
 590        priv->packet_filters.tclas_ies_length += sizeof(tclas_t);
 591    }
 592    if (priv->packet_filters.tclas_ies_length > 0) {
 593        priv->filter_tclas_ies = kmalloc(priv->packet_filters.tclas_ies_length, GFP_KERNEL);
 594        if (priv->filter_tclas_ies == NULL) {
 595            return -ENOMEM;
 596        }
 597        if (tclas_buffer_length) {
 598            tclas_buffer += sizeof(uf_cfg_bcast_packet_filter_t) - sizeof(unsigned char*);
 599            if (copy_from_user(priv->filter_tclas_ies,
 600                        tclas_buffer,
 601                        tclas_buffer_length)) {
 602                unifi_error(priv, "UNIFI_CFG: Failed to get the TCLAS buffer\n");
 603                return -EFAULT;
 604            }
 605        }
 606    }
 607
 608    if(priv->packet_filters.dhcp_filter)
 609    {
 610        /* Append the DHCP tclas IE */
 611        dhcp_tclas = (tclas_t*)(priv->filter_tclas_ies + tclas_buffer_length);
 612        memset(dhcp_tclas, 0, sizeof(tclas_t));
 613        dhcp_tclas->element_id = 14;
 614        dhcp_tclas->length = sizeof(tcpip_clsfr_t) + 1;
 615        dhcp_tclas->user_priority = 0;
 616        dhcp_tclas->tcp_ip_cls_fr.cls_fr_type = 1;
 617        dhcp_tclas->tcp_ip_cls_fr.version = 4;
 618        ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[0] = 0x00;
 619        ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[1] = 0x44;
 620        ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[0] = 0x00;
 621        ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[1] = 0x43;
 622        dhcp_tclas->tcp_ip_cls_fr.protocol = 0x11;
 623        dhcp_tclas->tcp_ip_cls_fr.cls_fr_mask = 0x58; //bits: 3,4,6
 624    }
 625
 626    rc = sme_mgt_packet_filter_set(priv);
 627
 628    return rc;
 629}
 630
 631
 632int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg)
 633{
 634    u8 wmm_qos_info;
 635    int rc = 0;
 636
 637    if (get_user(wmm_qos_info, (u8*)(((unifi_cfg_command_t*)arg) + 1))) {
 638        unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
 639        return -EFAULT;
 640    }
 641
 642    /* Store the value in the connection info */
 643    priv->connection_config.wmmQosInfo = wmm_qos_info;
 644
 645    return rc;
 646}
 647
 648
 649int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg)
 650{
 651    u32 addts_tid;
 652    u8 addts_ie_length;
 653    u8 *addts_ie;
 654    u8 *addts_params;
 655    CsrWifiSmeDataBlock tspec;
 656    CsrWifiSmeDataBlock tclas;
 657    int rc;
 658
 659    addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
 660    if (get_user(addts_tid, (u32*)addts_params)) {
 661        unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
 662        return -EFAULT;
 663    }
 664
 665    addts_params += sizeof(u32);
 666    if (get_user(addts_ie_length, (u8*)addts_params)) {
 667        unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
 668        return -EFAULT;
 669    }
 670
 671    unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n",
 672            addts_tid, addts_ie_length);
 673
 674    addts_ie = kmalloc(addts_ie_length, GFP_KERNEL);
 675    if (addts_ie == NULL) {
 676        unifi_error(priv,
 677                "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n",
 678                addts_ie_length);
 679        return -ENOMEM;
 680    }
 681
 682    addts_params += sizeof(u8);
 683    rc = copy_from_user(addts_ie, addts_params, addts_ie_length);
 684    if (rc) {
 685        unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n");
 686        kfree(addts_ie);
 687        return -EFAULT;
 688    }
 689
 690    tspec.data = addts_ie;
 691    tspec.length = addts_ie_length;
 692    tclas.data = NULL;
 693    tclas.length = 0;
 694
 695    rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid,
 696            &tspec, &tclas);
 697
 698    kfree(addts_ie);
 699    return rc;
 700}
 701
 702
 703int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg)
 704{
 705    u32 delts_tid;
 706    u8 *delts_params;
 707    CsrWifiSmeDataBlock tspec;
 708    CsrWifiSmeDataBlock tclas;
 709    int rc;
 710
 711    delts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
 712    if (get_user(delts_tid, (u32*)delts_params)) {
 713        unifi_error(priv, "unifi_cfg_wmm_delts: Failed to get the argument\n");
 714        return -EFAULT;
 715    }
 716
 717    unifi_trace(priv, UDBG4, "delts: tid = 0x%x\n", delts_tid);
 718
 719    tspec.data = tclas.data = NULL;
 720    tspec.length = tclas.length = 0;
 721
 722    rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_REMOVE, delts_tid,
 723            &tspec, &tclas);
 724
 725    return rc;
 726}
 727
 728int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg)
 729{
 730    u8 strict_draft_n;
 731    u8 *strict_draft_n_params;
 732    int rc;
 733
 734    CsrWifiSmeStaConfig  staConfig;
 735    CsrWifiSmeDeviceConfig  deviceConfig;
 736
 737    strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
 738    if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) {
 739        unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n");
 740        return -EFAULT;
 741    }
 742
 743    unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no"));
 744
 745    rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
 746
 747    if (rc) {
 748        unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
 749        return -EFAULT;
 750    }
 751
 752    deviceConfig.enableStrictDraftN = strict_draft_n;
 753
 754    rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
 755    if (rc) {
 756        unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
 757        rc = -EFAULT;
 758    }
 759
 760    return rc;
 761}
 762
 763
 764int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg)
 765{
 766    u8 enable_okc;
 767    u8 *enable_okc_params;
 768    int rc;
 769
 770    CsrWifiSmeStaConfig staConfig;
 771    CsrWifiSmeDeviceConfig deviceConfig;
 772
 773    enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
 774    if (get_user(enable_okc, (u8*)enable_okc_params)) {
 775        unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n");
 776        return -EFAULT;
 777    }
 778
 779    unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no"));
 780
 781    rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
 782    if (rc) {
 783        unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
 784        return -EFAULT;
 785    }
 786
 787    staConfig.enableOpportunisticKeyCaching = enable_okc;
 788
 789    rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
 790    if (rc) {
 791        unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
 792        rc = -EFAULT;
 793    }
 794
 795    return rc;
 796}
 797
 798
 799int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg)
 800{
 801    unifi_cfg_get_t get_cmd;
 802    char inst_name[IFNAMSIZ];
 803    int rc;
 804
 805    if (get_user(get_cmd, (unifi_cfg_get_t*)(((unifi_cfg_command_t*)arg) + 1))) {
 806        unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
 807        return -EFAULT;
 808    }
 809
 810    switch (get_cmd) {
 811        case UNIFI_CFG_GET_COEX:
 812            {
 813                CsrWifiSmeCoexInfo coexInfo;
 814                /* Get the coex info from the SME */
 815                rc = sme_mgt_coex_info_get(priv, &coexInfo);
 816                if (rc) {
 817                    unifi_error(priv, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n");
 818                    return rc;
 819                }
 820
 821                /* Copy the info to the out buffer */
 822                if (copy_to_user((void*)arg,
 823                            &coexInfo,
 824                            sizeof(CsrWifiSmeCoexInfo))) {
 825                    unifi_error(priv, "UNIFI_CFG: Failed to copy the coex info\n");
 826                    return -EFAULT;
 827                }
 828                break;
 829            }
 830        case UNIFI_CFG_GET_POWER_MODE:
 831            {
 832                CsrWifiSmePowerConfig powerConfig;
 833                rc = sme_mgt_power_config_get(priv, &powerConfig);
 834                if (rc) {
 835                    unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
 836                    return rc;
 837                }
 838
 839                /* Copy the info to the out buffer */
 840                if (copy_to_user((void*)arg,
 841                            &powerConfig.powerSaveLevel,
 842                            sizeof(CsrWifiSmePowerSaveLevel))) {
 843                    unifi_error(priv, "UNIFI_CFG: Failed to copy the power save info\n");
 844                    return -EFAULT;
 845                }
 846                break;
 847            }
 848        case UNIFI_CFG_GET_POWER_SUPPLY:
 849            {
 850                CsrWifiSmeHostConfig hostConfig;
 851                rc = sme_mgt_host_config_get(priv, &hostConfig);
 852                if (rc) {
 853                    unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
 854                    return rc;
 855                }
 856
 857                /* Copy the info to the out buffer */
 858                if (copy_to_user((void*)arg,
 859                            &hostConfig.powerMode,
 860                            sizeof(CsrWifiSmeHostPowerMode))) {
 861                    unifi_error(priv, "UNIFI_CFG: Failed to copy the host power mode\n");
 862                    return -EFAULT;
 863                }
 864                break;
 865            }
 866        case UNIFI_CFG_GET_VERSIONS:
 867            break;
 868        case UNIFI_CFG_GET_INSTANCE:
 869            {
 870                u16 InterfaceId=0;
 871                uf_net_get_name(priv->netdev[InterfaceId], &inst_name[0], sizeof(inst_name));
 872
 873                /* Copy the info to the out buffer */
 874                if (copy_to_user((void*)arg,
 875                            &inst_name[0],
 876                            sizeof(inst_name))) {
 877                    unifi_error(priv, "UNIFI_CFG: Failed to copy the instance name\n");
 878                    return -EFAULT;
 879                }
 880            }
 881            break;
 882
 883        case UNIFI_CFG_GET_AP_CONFIG:
 884            {
 885#ifdef CSR_SUPPORT_WEXT_AP
 886                uf_cfg_ap_config_t cfg_ap_config;
 887                cfg_ap_config.channel = priv->ap_config.channel;
 888                cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval;
 889                cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled;
 890                cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod;
 891                cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap;
 892                if (copy_to_user((void*)arg,
 893                            &cfg_ap_config,
 894                            sizeof(uf_cfg_ap_config_t))) {
 895                    unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n");
 896                    return -EFAULT;
 897                }
 898#else
 899                   return -EPERM;
 900#endif
 901            }
 902            break;
 903
 904
 905        default:
 906            unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n");
 907            return -EINVAL;
 908    }
 909
 910    return 0;
 911}
 912#ifdef CSR_SUPPORT_WEXT_AP
 913int
 914 uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap)
 915{
 916    int i=0;
 917    u8 b=FALSE, g = FALSE, n = FALSE;
 918    b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B;
 919    n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N;
 920    g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G;
 921    if(b || g) {
 922        supportedRates[i++]=0x82;
 923        supportedRates[i++]=0x84;
 924        supportedRates[i++]=0x8b;
 925        supportedRates[i++]=0x96;
 926    } else if(n) {
 927        /* For some strange reasons WiFi stack needs both b and g rates*/
 928        supportedRates[i++]=0x02;
 929        supportedRates[i++]=0x04;
 930        supportedRates[i++]=0x0b;
 931        supportedRates[i++]=0x16;
 932        supportedRates[i++]=0x0c;
 933        supportedRates[i++]=0x12;
 934        supportedRates[i++]=0x18;
 935        supportedRates[i++]=0x24;
 936        supportedRates[i++]=0x30;
 937        supportedRates[i++]=0x48;
 938        supportedRates[i++]=0x60;
 939        supportedRates[i++]=0x6c;
 940    }
 941    if(g) {
 942        if(!b) {
 943            supportedRates[i++]=0x8c;
 944            supportedRates[i++]=0x98;
 945            supportedRates[i++]=0xb0;
 946        } else {
 947            supportedRates[i++]=0x0c;
 948            supportedRates[i++]=0x18;
 949            supportedRates[i++]=0x30;
 950        }
 951        supportedRates[i++]=0x48;
 952        supportedRates[i++]=0x12;
 953        supportedRates[i++]=0x24;
 954        supportedRates[i++]=0x60;
 955        supportedRates[i++]=0x6c;
 956    }
 957    return i;
 958}
 959int unifi_cfg_set_ap_config(unifi_priv_t * priv,unsigned char* arg)
 960{
 961    uf_cfg_ap_config_t cfg_ap_config;
 962    char *buffer;
 963
 964    buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
 965    if (copy_from_user(&cfg_ap_config, (void*)buffer,
 966                sizeof(uf_cfg_ap_config_t))) {
 967        unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n");
 968        return -EFAULT;
 969    }
 970    priv->ap_config.channel = cfg_ap_config.channel;
 971    priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod;
 972    priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval;
 973    priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout;
 974    priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled;
 975    priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout;
 976    priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout;
 977    priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit;
 978
 979    priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled;
 980    priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType;
 981
 982    priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled;
 983
 984    priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc;
 985    priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed;
 986
 987    priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap;
 988    priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval;
 989
 990    priv->ap_mac_config.supportedRatesCount=     uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap);
 991
 992    return 0;
 993}
 994
 995#endif
 996#ifdef CSR_SUPPORT_WEXT
 997
 998    void
 999uf_sme_config_wq(struct work_struct *work)
1000{
1001    CsrWifiSmeStaConfig  staConfig;
1002    CsrWifiSmeDeviceConfig  deviceConfig;
1003    unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);
1004
1005    /* Register to receive indications from the SME */
1006    CsrWifiSmeEventMaskSetReqSend(0,
1007            CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY |
1008            CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE);
1009
1010    if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) {
1011        unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1012        return;
1013    }
1014
1015    if (priv->if_index == CSR_INDEX_5G) {
1016        staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0;
1017    } else {
1018        staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4;
1019    }
1020
1021    deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d;
1022    if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) {
1023        unifi_warning(priv,
1024                "SME config for 802.11d Trust Level and Radio Band failed.\n");
1025        return;
1026    }
1027
1028} /* uf_sme_config_wq() */
1029
1030#endif /* CSR_SUPPORT_WEXT */
1031
1032
1033/*
1034 * ---------------------------------------------------------------------------
1035 *  uf_ta_ind_wq
1036 *
1037 *      Deferred work queue function to send Traffic Analysis protocols
1038 *      indications to the SME.
1039 *      These are done in a deferred work queue for two reasons:
1040 *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1041 *       - we want to load the main driver data path as lightly as possible
1042 *
1043 *      The TA classifications already come from a workqueue.
1044 *
1045 *  Arguments:
1046 *      work    Pointer to work queue item.
1047 *
1048 *  Returns:
1049 *      None.
1050 * ---------------------------------------------------------------------------
1051 */
1052    void
1053uf_ta_ind_wq(struct work_struct *work)
1054{
1055    struct ta_ind *ind = container_of(work, struct ta_ind, task);
1056    unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work);
1057    u16 interfaceTag = 0;
1058
1059
1060    CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
1061            interfaceTag,
1062            ind->packet_type,
1063            ind->direction,
1064            ind->src_addr);
1065    ind->in_use = 0;
1066
1067} /* uf_ta_ind_wq() */
1068
1069
1070/*
1071 * ---------------------------------------------------------------------------
1072 *  uf_ta_sample_ind_wq
1073 *
1074 *      Deferred work queue function to send Traffic Analysis sample
1075 *      indications to the SME.
1076 *      These are done in a deferred work queue for two reasons:
1077 *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1078 *       - we want to load the main driver data path as lightly as possible
1079 *
1080 *      The TA classifications already come from a workqueue.
1081 *
1082 *  Arguments:
1083 *      work    Pointer to work queue item.
1084 *
1085 *  Returns:
1086 *      None.
1087 * ---------------------------------------------------------------------------
1088 */
1089    void
1090uf_ta_sample_ind_wq(struct work_struct *work)
1091{
1092    struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task);
1093    unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work);
1094    u16 interfaceTag = 0;
1095
1096     unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n",
1097        priv->rxTcpThroughput,
1098        priv->txTcpThroughput,
1099        priv->rxUdpThroughput,
1100        priv->txUdpThroughput,
1101        priv->bh_thread.prio);
1102
1103    if(priv->rxTcpThroughput > 1000)
1104    {
1105        if (bh_priority == -1 && priv->bh_thread.prio != 1)
1106        {
1107            struct sched_param param;
1108            priv->bh_thread.prio = 1;
1109            unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n",
1110                        priv->bh_thread.name, priv->bh_thread.prio);
1111            param.sched_priority = priv->bh_thread.prio;
1112            sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, &param);
1113        }
1114    } else
1115    {
1116        if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO)
1117        {
1118            struct sched_param param;
1119            param.sched_priority = 0;
1120            sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, &param);
1121            priv->bh_thread.prio = DEFAULT_PRIO;
1122            unifi_trace(priv, UDBG1, "%s new thread priority = %d\n",
1123                        priv->bh_thread.name, priv->bh_thread.prio);
1124            set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio));
1125        }
1126    }
1127
1128    CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, ind->stats);
1129
1130    ind->in_use = 0;
1131
1132} /* uf_ta_sample_ind_wq() */
1133
1134
1135/*
1136 * ---------------------------------------------------------------------------
1137 *  uf_send_m4_ready_wq
1138 *
1139 *      Deferred work queue function to send M4 ReadyToSend inds to the SME.
1140 *      These are done in a deferred work queue for two reasons:
1141 *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1142 *       - we want to load the main driver data path as lightly as possible
1143 *
1144 *  Arguments:
1145 *      work    Pointer to work queue item.
1146 *
1147 *  Returns:
1148 *      None.
1149 * ---------------------------------------------------------------------------
1150 */
1151void
1152uf_send_m4_ready_wq(struct work_struct *work)
1153{
1154    netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task);
1155    u16 iface = InterfacePriv->InterfaceTag;
1156    unifi_priv_t *priv = InterfacePriv->privPtr;
1157    CSR_MA_PACKET_REQUEST *req = &InterfacePriv->m4_signal.u.MaPacketRequest;
1158    CsrWifiMacAddress peer;
1159    unsigned long flags;
1160
1161    func_enter();
1162
1163    /* The peer address was stored in the signal */
1164    spin_lock_irqsave(&priv->m4_lock, flags);
1165    memcpy(peer.a, req->Ra.x, sizeof(peer.a));
1166    spin_unlock_irqrestore(&priv->m4_lock, flags);
1167
1168    /* Send a signal to SME */
1169    CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer);
1170
1171        unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
1172                peer.a);
1173
1174    func_exit();
1175
1176} /* uf_send_m4_ready_wq() */
1177
1178#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1179/*
1180 * ---------------------------------------------------------------------------
1181 *  uf_send_pkt_to_encrypt
1182 *
1183 *      Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
1184 *      These are done in a deferred work queue for two reasons:
1185 *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1186 *       - we want to load the main driver data path as lightly as possible
1187 *
1188 *  Arguments:
1189 *      work    Pointer to work queue item.
1190 *
1191 *  Returns:
1192 *      None.
1193 * ---------------------------------------------------------------------------
1194 */
1195void uf_send_pkt_to_encrypt(struct work_struct *work)
1196{
1197    netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
1198    u16 interfaceTag = interfacePriv->InterfaceTag;
1199    unifi_priv_t *priv = interfacePriv->privPtr;
1200
1201    u32 pktBulkDataLength;
1202    u8 *pktBulkData;
1203    unsigned long flags;
1204
1205    if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
1206
1207        func_enter();
1208
1209        pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
1210
1211        if (pktBulkDataLength > 0) {
1212                    pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
1213                    memset(pktBulkData, 0, pktBulkDataLength);
1214            } else {
1215                    unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1216                    return;
1217            }
1218
1219        spin_lock_irqsave(&priv->wapi_lock, flags);
1220        /* Copy over the MA PKT REQ bulk data */
1221        memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
1222        /* Free any bulk data buffers allocated for the WAPI Data pkt */
1223        unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
1224        interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
1225        interfacePriv->wapi_unicast_bulk_data.data_length = 0;
1226        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
1227        spin_unlock_irqrestore(&priv->wapi_lock, flags);
1228
1229        CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
1230        unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
1231
1232        kfree(pktBulkData); /* Would have been copied over by the SME Handler */
1233
1234        func_exit();
1235    } else {
1236            unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
1237    }
1238}/* uf_send_pkt_to_encrypt() */
1239#endif
1240