Adding support for MOXA ART SoC. Testing port of linux-2.6.32.60-moxart.
[linux-3.6.7-moxart.git] / drivers / staging / csr / sme_userspace.c
blobabcb446fb8c00f7c5a3f354236de3a51ff091b5c
1 /*
2 *****************************************************************************
4 * FILE : sme_userspace.c
6 * PURPOSE : Support functions for userspace SME helper application.
9 * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd.
11 * Refer to LICENSE.txt included with this source code for details on
12 * the license terms.
14 *****************************************************************************
17 #include "unifi_priv.h"
20 * Fix Me..... These need to be the correct values...
21 * Dynamic from the user space.
23 CsrSchedQid CSR_WIFI_ROUTER_IFACEQUEUE = 0xFFFF;
24 CsrSchedQid CSR_WIFI_SME_IFACEQUEUE = 0xFFFF;
25 #ifdef CSR_SUPPORT_WEXT_AP
26 CsrSchedQid CSR_WIFI_NME_IFACEQUEUE = 0xFFFF;
27 #endif
28 int
29 uf_sme_init(unifi_priv_t *priv)
31 int i, j;
33 CsrWifiRouterTransportInit(priv);
35 priv->smepriv = priv;
37 init_waitqueue_head(&priv->sme_request_wq);
39 priv->filter_tclas_ies = NULL;
40 memset(&priv->packet_filters, 0, sizeof(uf_cfg_bcast_packet_filter_t));
42 #ifdef CSR_SUPPORT_WEXT
43 priv->ignore_bssid_join = FALSE;
44 priv->mib_data.length = 0;
46 uf_sme_wext_set_defaults(priv);
47 #endif /* CSR_SUPPORT_WEXT*/
49 priv->sta_ip_address = 0xFFFFFFFF;
51 priv->wifi_on_state = wifi_on_unspecified;
53 sema_init(&priv->sme_sem, 1);
54 memset(&priv->sme_reply, 0, sizeof(sme_reply_t));
56 priv->ta_ind_work.in_use = 0;
57 priv->ta_sample_ind_work.in_use = 0;
59 priv->CSR_WIFI_SME_IFACEQUEUE = 0xFFFF;
61 for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) {
62 priv->sme_unidata_ind_filters[i].in_use = 0;
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
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;
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;
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;
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;
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;
100 /* intializing the lists */
101 INIT_LIST_HEAD(&interfacePriv->genericMgtFrames);
102 INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames);
103 INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
105 for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
106 interfacePriv->staInfo[j] = NULL;
109 interfacePriv->num_stations_joined = 0;
110 interfacePriv->sta_activity_check_enabled = FALSE;
114 return 0;
115 } /* uf_sme_init() */
118 void
119 uf_sme_deinit(unifi_priv_t *priv)
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;
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;
135 for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) {
136 priv->sme_unidata_ind_filters[i].in_use = 0;
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,
147 CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT,
148 ba_session_rx->tID,
149 ba_session_rx->macAddress);
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,
157 CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR,
158 ba_session_tx->tID,
159 ba_session_tx->macAddress);
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;
174 if (interfacePriv->sta_activity_check_enabled){
175 interfacePriv->sta_activity_check_enabled = FALSE;
176 del_timer_sync(&interfacePriv->sta_activity_check_timer);
179 CsrWifiRouterCtrlInterfaceReset(priv, i);
180 priv->interfacePriv[i]->interfaceMode = CSR_WIFI_ROUTER_CTRL_MODE_NONE;
184 } /* uf_sme_deinit() */
191 * ---------------------------------------------------------------------------
192 * unifi_ta_indicate_protocol
194 * Report that a packet of a particular type has been seen
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.
202 * Returns:
203 * None.
205 * Notes:
206 * We defer the actual sending to a background workqueue,
207 * see uf_ta_ind_wq().
208 * ---------------------------------------------------------------------------
210 void
211 unifi_ta_indicate_protocol(void *ospriv,
212 CsrWifiRouterCtrlTrafficPacketType packet_type,
213 CsrWifiRouterCtrlProtocolDirection direction,
214 const CsrWifiMacAddress *src_addr)
216 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
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;
224 if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX == direction)
226 u16 interfaceTag = 0;
227 CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
228 interfaceTag,
229 packet_type,
230 direction,
231 *src_addr);
233 else
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;
239 queue_work(priv->unifi_workqueue, &priv->ta_ind_work.task);
242 } /* unifi_ta_indicate_protocol() */
246 * ---------------------------------------------------------------------------
247 * unifi_ta_indicate_sampling
249 * Send the TA sampling information to the SME.
251 * Arguments:
252 * drv_priv The device context pointer passed to ta_init.
253 * stats The TA sampling data to send.
255 * Returns:
256 * None.
257 * ---------------------------------------------------------------------------
259 void
260 unifi_ta_indicate_sampling(void *ospriv, CsrWifiRouterCtrlTrafficStats *stats)
262 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
264 if (!priv) {
265 return;
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;
274 priv->ta_sample_ind_work.stats = *stats;
276 queue_work(priv->unifi_workqueue, &priv->ta_sample_ind_work.task);
278 } /* unifi_ta_indicate_sampling() */
282 * ---------------------------------------------------------------------------
283 * unifi_ta_indicate_l4stats
285 * Send the TA TCP/UDP throughput information to the driver.
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
294 * Returns:
295 * None.
296 * ---------------------------------------------------------------------------
298 void
299 unifi_ta_indicate_l4stats(void *ospriv,
300 u32 rxTcpThroughput,
301 u32 txTcpThroughput,
302 u32 rxUdpThroughput,
303 u32 txUdpThroughput)
305 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
307 if (!priv) {
308 return;
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() */