linux/drivers/staging/csr/sme_userspace.c
<<
>>
Prefs
   1/*
   2 *****************************************************************************
   3 *
   4 * FILE : sme_userspace.c
   5 *
   6 * PURPOSE : Support functions for userspace SME helper application.
   7 *
   8 *
   9 * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd.
  10 *
  11 * Refer to LICENSE.txt included with this source code for details on
  12 * the license terms.
  13 *
  14 *****************************************************************************
  15 */
  16
  17#include "unifi_priv.h"
  18
  19/*
  20 * Fix Me..... These need to be the correct values...
  21 * Dynamic from the user space.
  22 */
  23CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE   = 0xFFFF;
  24CsrSchedQid CSR_WIFI_SME_IFACEQUEUE      = 0xFFFF;
  25#ifdef CSR_SUPPORT_WEXT_AP
  26CsrSchedQid CSR_WIFI_NME_IFACEQUEUE      = 0xFFFF;
  27#endif
  28int
  29uf_sme_init(unifi_priv_t *priv)
  30{
  31    int i, j;
  32
  33    CsrWifiRouterTransportInit(priv);
  34
  35    priv->smepriv = priv;
  36
  37    init_waitqueue_head(&priv->sme_request_wq);
  38
  39    priv->filter_tclas_ies = NULL;
  40    memset(&priv->packet_filters, 0, sizeof(uf_cfg_bcast_packet_filter_t));
  41
  42#ifdef CSR_SUPPORT_WEXT
  43    priv->ignore_bssid_join = FALSE;
  44    priv->mib_data.length = 0;
  45
  46    uf_sme_wext_set_defaults(priv);
  47#endif /* CSR_SUPPORT_WEXT*/
  48
  49    priv->sta_ip_address = 0xFFFFFFFF;
  50
  51    priv->wifi_on_state = wifi_on_unspecified;
  52
  53    sema_init(&priv->sme_sem, 1);
  54    memset(&priv->sme_reply, 0, sizeof(sme_reply_t));
  55
  56    priv->ta_ind_work.in_use = 0;
  57    priv->ta_sample_ind_work.in_use = 0;
  58
  59    priv->CSR_WIFI_SME_IFACEQUEUE = 0xFFFF;
  60
  61    for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) {
  62        priv->sme_unidata_ind_filters[i].in_use = 0;
  63    }
  64
  65    /* Create a work queue item for Traffic Analysis indications to SME */
  66    INIT_WORK(&priv->ta_ind_work.task, uf_ta_ind_wq);
  67    INIT_WORK(&priv->ta_sample_ind_work.task, uf_ta_sample_ind_wq);
  68#ifdef CSR_SUPPORT_WEXT
  69    INIT_WORK(&priv->sme_config_task, uf_sme_config_wq);
  70#endif
  71
  72    for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
  73        netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
  74        interfacePriv->m4_sent = FALSE;
  75        interfacePriv->m4_bulk_data.net_buf_length = 0;
  76        interfacePriv->m4_bulk_data.data_length = 0;
  77        interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL;
  78
  79        memset(&interfacePriv->controlled_data_port, 0, sizeof(unifi_port_config_t));
  80        interfacePriv->controlled_data_port.entries_in_use = 1;
  81        interfacePriv->controlled_data_port.port_cfg[0].in_use = TRUE;
  82        interfacePriv->controlled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
  83        interfacePriv->controlled_data_port.overide_action = UF_DATA_PORT_OVERIDE;
  84
  85        memset(&interfacePriv->uncontrolled_data_port, 0, sizeof(unifi_port_config_t));
  86        interfacePriv->uncontrolled_data_port.entries_in_use = 1;
  87        interfacePriv->uncontrolled_data_port.port_cfg[0].in_use = TRUE;
  88        interfacePriv->uncontrolled_data_port.port_cfg[0].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
  89        interfacePriv->uncontrolled_data_port.overide_action = UF_DATA_PORT_OVERIDE;
  90
  91        /* Mark the remainder of the port config table as unallocated */
  92        for(j = 1; j < UNIFI_MAX_CONNECTIONS; j++) {
  93            interfacePriv->controlled_data_port.port_cfg[j].in_use = FALSE;
  94            interfacePriv->controlled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
  95
  96            interfacePriv->uncontrolled_data_port.port_cfg[j].in_use = FALSE;
  97            interfacePriv->uncontrolled_data_port.port_cfg[j].port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
  98        }
  99
 100        /* intializing the lists */
 101        INIT_LIST_HEAD(&interfacePriv->genericMgtFrames);
 102        INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames);
 103        INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
 104
 105        for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
 106            interfacePriv->staInfo[j] = NULL;
 107        }
 108
 109        interfacePriv->num_stations_joined = 0;
 110        interfacePriv->sta_activity_check_enabled = FALSE;
 111    }
 112
 113
 114    return 0;
 115} /* uf_sme_init() */
 116
 117
 118void
 119uf_sme_deinit(unifi_priv_t *priv)
 120{
 121    int i,j;
 122    u8 ba_session_idx;
 123    ba_session_rx_struct *ba_session_rx = NULL;
 124    ba_session_tx_struct *ba_session_tx = NULL;
 125    CsrWifiRouterCtrlStaInfo_t *staInfo = NULL;
 126    netInterface_priv_t *interfacePriv = NULL;
 127
 128    /* Free any TCLASs previously allocated */
 129    if (priv->packet_filters.tclas_ies_length) {
 130        priv->packet_filters.tclas_ies_length = 0;
 131        kfree(priv->filter_tclas_ies);
 132        priv->filter_tclas_ies = NULL;
 133    }
 134
 135    for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) {
 136        priv->sme_unidata_ind_filters[i].in_use = 0;
 137    }
 138
 139    /* Remove all the Peer database, before going down */
 140    for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
 141        down(&priv->ba_mutex);
 142        for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
 143            ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx];
 144            if(ba_session_rx) {
 145                blockack_session_stop(priv,
 146                                    i,
 147                                    CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT,
 148                                    ba_session_rx->tID,
 149                                    ba_session_rx->macAddress);
 150            }
 151        }
 152        for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){
 153            ba_session_tx = priv->interfacePriv[i]->ba_session_tx[ba_session_idx];
 154            if(ba_session_tx) {
 155                blockack_session_stop(priv,
 156                                    i,
 157                                    CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR,
 158                                    ba_session_tx->tID,
 159                                    ba_session_tx->macAddress);
 160            }
 161        }
 162
 163        up(&priv->ba_mutex);
 164        interfacePriv = priv->interfacePriv[i];
 165        if(interfacePriv){
 166            for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
 167                if ((staInfo=interfacePriv->staInfo[j]) != NULL) {
 168                    /* Clear the STA activity parameters before freeing station Record */
 169                    unifi_trace(priv, UDBG1, "uf_sme_deinit: Canceling work queue for STA with AID: %d\n", staInfo->aid);
 170                    cancel_work_sync(&staInfo->send_disconnected_ind_task);
 171                    staInfo->nullDataHostTag = INVALID_HOST_TAG;
 172                }
 173            }
 174            if (interfacePriv->sta_activity_check_enabled){
 175                interfacePriv->sta_activity_check_enabled = FALSE;
 176                del_timer_sync(&interfacePriv->sta_activity_check_timer);
 177            }
 178        }
 179        CsrWifiRouterCtrlInterfaceReset(priv, i);
 180        priv->interfacePriv[i]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_NONE;
 181    }
 182
 183
 184} /* uf_sme_deinit() */
 185
 186
 187
 188
 189
 190/*
 191 * ---------------------------------------------------------------------------
 192 *  unifi_ta_indicate_protocol
 193 *
 194 *      Report that a packet of a particular type has been seen
 195 *
 196 *  Arguments:
 197 *      drv_priv        The device context pointer passed to ta_init.
 198 *      protocol        The protocol type enum value.
 199 *      direction       Whether the packet was a tx or rx.
 200 *      src_addr        The source MAC address from the data packet.
 201 *
 202 *  Returns:
 203 *      None.
 204 *
 205 *  Notes:
 206 *      We defer the actual sending to a background workqueue,
 207 *      see uf_ta_ind_wq().
 208 * ---------------------------------------------------------------------------
 209 */
 210void
 211unifi_ta_indicate_protocol(void *ospriv,
 212                           CsrWifiRouterCtrlTrafficPacketType packet_type,
 213                           CsrWifiRouterCtrlProtocolDirection direction,
 214                           const CsrWifiMacAddress *src_addr)
 215{
 216    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
 217
 218    if (priv->ta_ind_work.in_use) {
 219        unifi_warning(priv,
 220                "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n");
 221        return;
 222    }
 223
 224    if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX == direction)
 225    {
 226        u16 interfaceTag = 0;
 227        CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
 228                interfaceTag,
 229                packet_type,
 230                direction,
 231                *src_addr);
 232    }
 233    else
 234    {
 235        priv->ta_ind_work.packet_type = packet_type;
 236        priv->ta_ind_work.direction = direction;
 237        priv->ta_ind_work.src_addr = *src_addr;
 238
 239        queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task);
 240    }
 241
 242} /* unifi_ta_indicate_protocol() */
 243
 244
 245/*
 246 * ---------------------------------------------------------------------------
 247 * unifi_ta_indicate_sampling
 248 *
 249 *      Send the TA sampling information to the SME.
 250 *
 251 *  Arguments:
 252 *      drv_priv        The device context pointer passed to ta_init.
 253 *      stats   The TA sampling data to send.
 254 *
 255 *  Returns:
 256 *      None.
 257 * ---------------------------------------------------------------------------
 258 */
 259void
 260unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats)
 261{
 262    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
 263
 264    if (!priv) {
 265        return;
 266    }
 267
 268    if (priv->ta_sample_ind_work.in_use) {
 269        unifi_warning(priv,
 270                     "unifi_ta_indicate_sampling: workqueue item still in use, not sending\n");
 271        return;
 272    }
 273
 274    priv->ta_sample_ind_work.stats = *stats;
 275
 276    queue_work(priv->unifi_workqueue, &priv->ta_sample_ind_work.task);
 277
 278} /* unifi_ta_indicate_sampling() */
 279
 280
 281/*
 282 * ---------------------------------------------------------------------------
 283 * unifi_ta_indicate_l4stats
 284 *
 285 *      Send the TA TCP/UDP throughput information to the driver.
 286 *
 287 *  Arguments:
 288 *    drv_priv        The device context pointer passed to ta_init.
 289 *    rxTcpThroughput TCP RX throughput in KiloBytes
 290 *    txTcpThroughput TCP TX throughput in KiloBytes
 291 *    rxUdpThroughput UDP RX throughput in KiloBytes
 292 *    txUdpThroughput UDP TX throughput in KiloBytes
 293 *
 294 *  Returns:
 295 *      None.
 296 * ---------------------------------------------------------------------------
 297 */
 298void
 299unifi_ta_indicate_l4stats(void *ospriv,
 300                          u32 rxTcpThroughput,
 301                          u32 txTcpThroughput,
 302                          u32 rxUdpThroughput,
 303                          u32 txUdpThroughput)
 304{
 305    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
 306
 307    if (!priv) {
 308        return;
 309    }
 310    /* Save the info. The actual action will be taken in unifi_ta_indicate_sampling() */
 311    priv->rxTcpThroughput = rxTcpThroughput;
 312    priv->txTcpThroughput = txTcpThroughput;
 313    priv->rxUdpThroughput = rxUdpThroughput;
 314    priv->txUdpThroughput = txUdpThroughput;
 315} /* unifi_ta_indicate_l4stats() */
 316