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
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;
29 uf_sme_init(unifi_priv_t
*priv
)
33 CsrWifiRouterTransportInit(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
);
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
;
115 } /* uf_sme_init() */
119 uf_sme_deinit(unifi_priv_t
*priv
)
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
];
145 blockack_session_stop(priv
,
147 CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT
,
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
];
155 blockack_session_stop(priv
,
157 CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR
,
159 ba_session_tx
->macAddress
);
164 interfacePriv
= priv
->interfacePriv
[i
];
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
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.
206 * We defer the actual sending to a background workqueue,
207 * see uf_ta_ind_wq().
208 * ---------------------------------------------------------------------------
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
) {
220 "unifi_ta_indicate_protocol: workqueue item still in use, not sending\n");
224 if (CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_RX
== direction
)
226 u16 interfaceTag
= 0;
227 CsrWifiRouterCtrlTrafficProtocolIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
,0,
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.
252 * drv_priv The device context pointer passed to ta_init.
253 * stats The TA sampling data to send.
257 * ---------------------------------------------------------------------------
260 unifi_ta_indicate_sampling(void *ospriv
, CsrWifiRouterCtrlTrafficStats
*stats
)
262 unifi_priv_t
*priv
= (unifi_priv_t
*)ospriv
;
268 if (priv
->ta_sample_ind_work
.in_use
) {
270 "unifi_ta_indicate_sampling: workqueue item still in use, not sending\n");
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.
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
296 * ---------------------------------------------------------------------------
299 unifi_ta_indicate_l4stats(void *ospriv
,
305 unifi_priv_t
*priv
= (unifi_priv_t
*)ospriv
;
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() */