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