Root/drivers/staging/csr/sme_userspace.c

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

Archive Download this file



interactive