Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sme_userspace.c
Go to the documentation of this file.
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  */
25 #ifdef CSR_SUPPORT_WEXT_AP
27 #endif
28 int
30 {
31  int i, j;
32 
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 
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++) {
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 
118 void
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;
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) {
146  i,
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) {
156  i,
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  }
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  */
210 void
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 
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  */
259 void
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  */
298 void
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() */
315 } /* unifi_ta_indicate_l4stats() */