]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/csr/unifi_sme.c
sched/rt: Move rt specific bits into new header file
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / csr / unifi_sme.c
CommitLineData
635d2b00
GKH
1/*
2 * ***************************************************************************
3 * FILE: unifi_sme.c
4 *
5 * PURPOSE: SME related functions.
6 *
7 * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
8 *
9 * Refer to LICENSE.txt included with this source code for details on
10 * the license terms.
11 *
12 * ***************************************************************************
13 */
14
15#include "unifi_priv.h"
16#include "csr_wifi_hip_unifi.h"
17#include "csr_wifi_hip_conversions.h"
8bd75c77 18#include <linux/sched/rt.h>
635d2b00
GKH
19
20
21
22 int
23convert_sme_error(CsrResult error)
24{
25 switch (error) {
26 case CSR_RESULT_SUCCESS:
27 return 0;
28 case CSR_RESULT_FAILURE:
29 case CSR_WIFI_RESULT_NOT_FOUND:
30 case CSR_WIFI_RESULT_TIMED_OUT:
31 case CSR_WIFI_RESULT_CANCELLED:
32 case CSR_WIFI_RESULT_UNAVAILABLE:
33 return -EIO;
34 case CSR_WIFI_RESULT_NO_ROOM:
35 return -EBUSY;
36 case CSR_WIFI_RESULT_INVALID_PARAMETER:
37 return -EINVAL;
38 case CSR_WIFI_RESULT_UNSUPPORTED:
39 return -EOPNOTSUPP;
40 default:
41 return -EIO;
42 }
43}
44
45
46/*
47 * ---------------------------------------------------------------------------
48 * sme_log_event
49 *
50 * Callback function to be registered as the SME event callback.
51 * Copies the signal content into a new udi_log_t struct and adds
52 * it to the read queue for the SME client.
53 *
54 * Arguments:
55 * arg This is the value given to unifi_add_udi_hook, in
56 * this case a pointer to the client instance.
57 * signal Pointer to the received signal.
58 * signal_len Size of the signal structure in bytes.
59 * bulkdata Pointers to any associated bulk data.
60 * dir Direction of the signal. Zero means from host,
61 * non-zero means to host.
62 *
63 * Returns:
64 * None.
65 * ---------------------------------------------------------------------------
66 */
67 void
68sme_log_event(ul_client_t *pcli,
69 const u8 *signal, int signal_len,
70 const bulk_data_param_t *bulkdata,
71 int dir)
72{
73 unifi_priv_t *priv;
74 CSR_SIGNAL unpacked_signal;
75 CsrWifiSmeDataBlock mlmeCommand;
76 CsrWifiSmeDataBlock dataref1;
77 CsrWifiSmeDataBlock dataref2;
78 CsrResult result = CSR_RESULT_SUCCESS;
79 int r;
80
635d2b00
GKH
81 /* Just a sanity check */
82 if ((signal == NULL) || (signal_len <= 0)) {
635d2b00
GKH
83 return;
84 }
85
86 priv = uf_find_instance(pcli->instance);
87 if (!priv) {
88 unifi_error(priv, "sme_log_event: invalid priv\n");
635d2b00
GKH
89 return;
90 }
91
92 if (priv->smepriv == NULL) {
93 unifi_error(priv, "sme_log_event: invalid smepriv\n");
635d2b00
GKH
94 return;
95 }
96
97 unifi_trace(priv, UDBG3,
98 "sme_log_event: Process signal 0x%.4X\n",
99 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal));
100
101
102 /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */
103 r = read_unpack_signal(signal, &unpacked_signal);
104 if (r == CSR_RESULT_SUCCESS) {
105 if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) ||
106 (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID))
107 {
635d2b00
GKH
108 return;
109 }
110 if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID)
111 {
8c87f69a 112 u16 frmCtrl;
5379b13d 113 u8 unicastPdu = TRUE;
7e6f5794
GKH
114 u8 *macHdrLocation;
115 u8 *raddr = NULL, *taddr = NULL;
635d2b00
GKH
116 CsrWifiMacAddress peerMacAddress;
117 /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
118 CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication;
119
7e6f5794 120 macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
635d2b00
GKH
121 /* Fetch the frame control value from mac header */
122 frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);
123
124 /* Point to the addresses */
125 raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET;
126 taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET;
127
25aebdb1 128 memcpy(peerMacAddress.a, taddr, ETH_ALEN);
635d2b00
GKH
129
130 if(ind->ReceptionStatus == CSR_MICHAEL_MIC_ERROR)
131 {
132 if (*raddr & 0x1)
133 unicastPdu = FALSE;
134
135 CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0,
136 (ind->VirtualInterfaceIdentifier & 0xff),peerMacAddress,
137 unicastPdu);
138 return;
139 }
140 else
141 {
142 if(ind->ReceptionStatus == CSR_RX_SUCCESS)
143 {
7e6f5794 144 u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00;
8c87f69a 145 u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff);
635d2b00
GKH
146 CsrWifiRouterCtrlStaInfo_t *srcStaInfo = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,taddr,interfaceTag);
147 if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE))
148 {
149 uf_process_pm_bit_for_peer(priv,srcStaInfo,pmBit,interfaceTag);
150
151 /* Update station last activity flag */
152 srcStaInfo->activity_flag = TRUE;
153 }
154 }
155 }
156 }
157
158 if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_CONFIRM_ID)
159 {
160 CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm;
8c87f69a 161 u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff);
635d2b00
GKH
162 netInterface_priv_t *interfacePriv;
163 CSR_MA_PACKET_REQUEST *req;
164 CsrWifiMacAddress peerMacAddress;
165
166 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
167 {
168 unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag);
635d2b00
GKH
169 return;
170 }
171
172 unifi_trace(priv,UDBG1,"MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus);
173
174 interfacePriv = priv->interfacePriv[interfaceTag];
175#ifdef CSR_SUPPORT_SME
176 if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
177 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
178
179 if(cfm->HostTag == interfacePriv->multicastPduHostTag){
180 uf_process_ma_pkt_cfm_for_ap(priv ,interfaceTag, cfm);
181 }
182 }
183#endif
184
185 req = &interfacePriv->m4_signal.u.MaPacketRequest;
186
187 if(cfm->HostTag & 0x80000000)
188 {
189 if (cfm->TransmissionStatus != CSR_TX_SUCCESSFUL)
190 {
191 result = CSR_RESULT_FAILURE;
192 }
193#ifdef CSR_SUPPORT_SME
194 memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN);
195 /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/
196 if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag))
197 {
198 unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__);
199 CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
200 interfaceTag,
201 peerMacAddress,
202 result);
203 interfacePriv->m4_sent = FALSE;
204 interfacePriv->m4_hostTag = 0xffffffff;
205 }
206#endif
207 /* If EAPOL was requested via router APIs then send cfm else ignore*/
208 if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) {
8c87f69a 209 CsrWifiRouterMaPacketCfmSend((u16)signal[2],
635d2b00
GKH
210 cfm->VirtualInterfaceIdentifier,
211 result,
212 (cfm->HostTag & 0x3fffffff), cfm->Rate);
213 } else {
214 unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__);
215 }
635d2b00
GKH
216 return;
217 }
218 }
219 }
220
221 mlmeCommand.length = signal_len;
7e6f5794 222 mlmeCommand.data = (u8*)signal;
635d2b00
GKH
223
224 dataref1.length = bulkdata->d[0].data_length;
225 if (dataref1.length > 0) {
7e6f5794 226 dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr;
635d2b00
GKH
227 } else
228 {
229 dataref1.data = NULL;
230 }
231
232 dataref2.length = bulkdata->d[1].data_length;
233 if (dataref2.length > 0) {
7e6f5794 234 dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr;
635d2b00
GKH
235 } else
236 {
237 dataref2.data = NULL;
238 }
239
240 CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data,
241 dataref1.length, dataref1.data,
242 dataref2.length, dataref2.data);
243
635d2b00
GKH
244} /* sme_log_event() */
245
246
247/*
248 * ---------------------------------------------------------------------------
249 * uf_sme_port_state
250 *
251 * Return the state of the controlled port.
252 *
253 * Arguments:
254 * priv Pointer to device private context struct
255 * address Pointer to the destination for tx or sender for rx address
256 * queue Controlled or uncontrolled queue
257 *
258 * Returns:
259 * An unifi_ControlledPortAction value.
260 * ---------------------------------------------------------------------------
261 */
262CsrWifiRouterCtrlPortAction
8c87f69a 263uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
635d2b00
GKH
264{
265 int i;
266 unifi_port_config_t *port;
267 netInterface_priv_t *interfacePriv;
268
269 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
270 unifi_error(priv, "uf_sme_port_state: bad interfaceTag\n");
271 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
272 }
273
274 interfacePriv = priv->interfacePriv[interfaceTag];
275
276 if (queue == UF_CONTROLLED_PORT_Q) {
277 port = &interfacePriv->controlled_data_port;
278 } else {
279 port = &interfacePriv->uncontrolled_data_port;
280 }
281
282 if (!port->entries_in_use) {
283 unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
284 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD;
285 }
286
287 /* If the port configuration is common for all destinations, return it. */
288 if (port->overide_action == UF_DATA_PORT_OVERIDE) {
289 unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
290 port->port_cfg[0].port_action);
291 return port->port_cfg[0].port_action;
292 }
293
294 unifi_trace(priv, UDBG5, "Multiple (%d) port configurations.\n", port->entries_in_use);
295
296 /* If multiple configurations exist.. */
297 for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
298 /* .. go through the list and match the destination address. */
299 if (port->port_cfg[i].in_use &&
300 memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
301 /* Return the desired action. */
302 return port->port_cfg[i].port_action;
303 }
304 }
305
306 /* Could not find any information, return Open. */
307 unifi_trace(priv, UDBG5, "port configuration not found, return Open.\n");
308 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN;
309} /* uf_sme_port_state() */
310
311/*
312 * ---------------------------------------------------------------------------
313 * uf_sme_port_config_handle
314 *
315 * Return the port config handle of the controlled/uncontrolled port.
316 *
317 * Arguments:
318 * priv Pointer to device private context struct
319 * address Pointer to the destination for tx or sender for rx address
320 * queue Controlled or uncontrolled queue
321 *
322 * Returns:
323 * An unifi_port_cfg_t* .
324 * ---------------------------------------------------------------------------
325 */
326unifi_port_cfg_t*
8c87f69a 327uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
635d2b00
GKH
328{
329 int i;
330 unifi_port_config_t *port;
331 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
332
333 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
334 unifi_error(priv, "uf_sme_port_config_handle: bad interfaceTag\n");
335 return NULL;
336 }
337
338 if (queue == UF_CONTROLLED_PORT_Q) {
339 port = &interfacePriv->controlled_data_port;
340 } else {
341 port = &interfacePriv->uncontrolled_data_port;
342 }
343
344 if (!port->entries_in_use) {
345 unifi_trace(priv, UDBG5, "No port configurations, return Discard.\n");
346 return NULL;
347 }
348
349 /* If the port configuration is common for all destinations, return it. */
350 if (port->overide_action == UF_DATA_PORT_OVERIDE) {
351 unifi_trace(priv, UDBG5, "Single port configuration (%d).\n",
352 port->port_cfg[0].port_action);
353 if (address) {
354 unifi_trace(priv, UDBG5, "addr[0] = %x, addr[1] = %x, addr[2] = %x, addr[3] = %x\n", address[0], address[1], address[2], address[3]);
355 }
356 return &port->port_cfg[0];
357 }
358
359 unifi_trace(priv, UDBG5, "Multiple port configurations.\n");
360
361 /* If multiple configurations exist.. */
362 for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) {
363 /* .. go through the list and match the destination address. */
364 if (port->port_cfg[i].in_use &&
365 memcmp(address, port->port_cfg[i].mac_address.a, ETH_ALEN) == 0) {
366 /* Return the desired action. */
367 return &port->port_cfg[i];
368 }
369 }
370
371 /* Could not find any information, return Open. */
372 unifi_trace(priv, UDBG5, "port configuration not found, returning NULL (debug).\n");
373 return NULL;
374} /* uf_sme_port_config_handle */
375
376void
377uf_multicast_list_wq(struct work_struct *work)
378{
379 unifi_priv_t *priv = container_of(work, unifi_priv_t,
380 multicast_list_task);
381 int i;
8c87f69a 382 u16 interfaceTag = 0;
635d2b00
GKH
383 CsrWifiMacAddress* multicast_address_list = NULL;
384 int mc_count;
385 u8 *mc_list;
386 netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
387
388 if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) {
389 unifi_error(priv, "uf_multicast_list_wq: bad interfaceTag\n");
390 return;
391 }
392
393 unifi_trace(priv, UDBG5,
394 "uf_multicast_list_wq: list count = %d\n",
395 interfacePriv->mc_list_count);
396
397 /* Flush the current list */
398 CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, CSR_WIFI_SME_LIST_ACTION_FLUSH, 0, NULL);
399
400 mc_count = interfacePriv->mc_list_count;
401 mc_list = interfacePriv->mc_list;
402 /*
403 * Allocate a new list, need to free it later
404 * in unifi_mgt_multicast_address_cfm().
405 */
786eeeb3 406 multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL);
635d2b00
GKH
407
408 if (multicast_address_list == NULL) {
409 return;
410 }
411
412 for (i = 0; i < mc_count; i++) {
413 memcpy(multicast_address_list[i].a, mc_list, ETH_ALEN);
414 mc_list += ETH_ALEN;
415 }
416
417 if (priv->smepriv == NULL) {
55a27055 418 kfree(multicast_address_list);
635d2b00
GKH
419 return;
420 }
421
422 CsrWifiRouterCtrlMulticastAddressIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
423 interfaceTag,
424 CSR_WIFI_SME_LIST_ACTION_ADD,
425 mc_count, multicast_address_list);
426
427 /* The SME will take a copy of the addreses*/
55a27055 428 kfree(multicast_address_list);
635d2b00
GKH
429}
430
431
432int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
433{
434 unifi_cfg_power_t cfg_power;
435 int rc;
95edd09e 436 int wol;
635d2b00
GKH
437
438 if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
439 unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
440 return -EFAULT;
441 }
442
443 switch (cfg_power) {
444 case UNIFI_CFG_POWER_OFF:
95edd09e 445 priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
635d2b00
GKH
446 rc = sme_sys_suspend(priv);
447 if (rc) {
448 return rc;
449 }
450 break;
451 case UNIFI_CFG_POWER_ON:
95edd09e 452 wol = priv->wol_suspend;
635d2b00
GKH
453 rc = sme_sys_resume(priv);
454 if (rc) {
455 return rc;
456 }
95edd09e
GKH
457 if (wol) {
458 /* Kick the BH to ensure pending transfers are handled when
459 * a suspend happened with card powered.
460 */
461 unifi_send_signal(priv->card, NULL, 0, NULL);
462 }
635d2b00
GKH
463 break;
464 default:
465 unifi_error(priv, "WIFI POWER: Unknown value.\n");
466 return -EINVAL;
467 }
468
469 return 0;
470}
471
472
473int unifi_cfg_power_save(unifi_priv_t *priv, unsigned char *arg)
474{
475 unifi_cfg_powersave_t cfg_power_save;
476 CsrWifiSmePowerConfig powerConfig;
477 int rc;
478
479 if (get_user(cfg_power_save, (unifi_cfg_powersave_t*)(((unifi_cfg_command_t*)arg) + 1))) {
480 unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
481 return -EFAULT;
482 }
483
484 /* Get the coex info from the SME */
485 rc = sme_mgt_power_config_get(priv, &powerConfig);
486 if (rc) {
487 unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
488 return rc;
489 }
490
491 switch (cfg_power_save) {
492 case UNIFI_CFG_POWERSAVE_NONE:
493 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW;
494 break;
495 case UNIFI_CFG_POWERSAVE_FAST:
496 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_MED;
497 break;
498 case UNIFI_CFG_POWERSAVE_FULL:
499 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH;
500 break;
501 case UNIFI_CFG_POWERSAVE_AUTO:
502 powerConfig.powerSaveLevel = CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO;
503 break;
504 default:
505 unifi_error(priv, "POWERSAVE: Unknown value.\n");
506 return -EINVAL;
507 }
508
509 rc = sme_mgt_power_config_set(priv, &powerConfig);
510
511 if (rc) {
512 unifi_error(priv, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n");
513 }
514
515 return rc;
516}
517
518
519int unifi_cfg_power_supply(unifi_priv_t *priv, unsigned char *arg)
520{
521 unifi_cfg_powersupply_t cfg_power_supply;
522 CsrWifiSmeHostConfig hostConfig;
523 int rc;
524
525 if (get_user(cfg_power_supply, (unifi_cfg_powersupply_t*)(((unifi_cfg_command_t*)arg) + 1))) {
526 unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
527 return -EFAULT;
528 }
529
530 /* Get the coex info from the SME */
531 rc = sme_mgt_host_config_get(priv, &hostConfig);
532 if (rc) {
533 unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
534 return rc;
535 }
536
537 switch (cfg_power_supply) {
538 case UNIFI_CFG_POWERSUPPLY_MAINS:
539 hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE;
540 break;
541 case UNIFI_CFG_POWERSUPPLY_BATTERIES:
542 hostConfig.powerMode = CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE;
543 break;
544 default:
545 unifi_error(priv, "POWERSUPPLY: Unknown value.\n");
546 return -EINVAL;
547 }
548
549 rc = sme_mgt_host_config_set(priv, &hostConfig);
550 if (rc) {
551 unifi_error(priv, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n");
552 }
553
554 return rc;
555}
556
557
558int unifi_cfg_packet_filters(unifi_priv_t *priv, unsigned char *arg)
559{
560 unsigned char *tclas_buffer;
561 unsigned int tclas_buffer_length;
562 tclas_t *dhcp_tclas;
563 int rc;
564
565 /* Free any TCLASs previously allocated */
566 if (priv->packet_filters.tclas_ies_length) {
55a27055 567 kfree(priv->filter_tclas_ies);
635d2b00
GKH
568 priv->filter_tclas_ies = NULL;
569 }
570
571 tclas_buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
572 if (copy_from_user(&priv->packet_filters, (void*)tclas_buffer,
573 sizeof(uf_cfg_bcast_packet_filter_t))) {
574 unifi_error(priv, "UNIFI_CFG: Failed to get the filter struct\n");
575 return -EFAULT;
576 }
577
578 tclas_buffer_length = priv->packet_filters.tclas_ies_length;
579
580 /* Allocate TCLASs if necessary */
581 if (priv->packet_filters.dhcp_filter) {
582 priv->packet_filters.tclas_ies_length += sizeof(tclas_t);
583 }
584 if (priv->packet_filters.tclas_ies_length > 0) {
786eeeb3 585 priv->filter_tclas_ies = kmalloc(priv->packet_filters.tclas_ies_length, GFP_KERNEL);
635d2b00
GKH
586 if (priv->filter_tclas_ies == NULL) {
587 return -ENOMEM;
588 }
589 if (tclas_buffer_length) {
590 tclas_buffer += sizeof(uf_cfg_bcast_packet_filter_t) - sizeof(unsigned char*);
591 if (copy_from_user(priv->filter_tclas_ies,
592 tclas_buffer,
593 tclas_buffer_length)) {
594 unifi_error(priv, "UNIFI_CFG: Failed to get the TCLAS buffer\n");
595 return -EFAULT;
596 }
597 }
598 }
599
600 if(priv->packet_filters.dhcp_filter)
601 {
602 /* Append the DHCP tclas IE */
603 dhcp_tclas = (tclas_t*)(priv->filter_tclas_ies + tclas_buffer_length);
604 memset(dhcp_tclas, 0, sizeof(tclas_t));
605 dhcp_tclas->element_id = 14;
606 dhcp_tclas->length = sizeof(tcpip_clsfr_t) + 1;
607 dhcp_tclas->user_priority = 0;
608 dhcp_tclas->tcp_ip_cls_fr.cls_fr_type = 1;
609 dhcp_tclas->tcp_ip_cls_fr.version = 4;
7e6f5794
GKH
610 ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[0] = 0x00;
611 ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.source_port))[1] = 0x44;
612 ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[0] = 0x00;
613 ((u8*)(&dhcp_tclas->tcp_ip_cls_fr.dest_port))[1] = 0x43;
635d2b00
GKH
614 dhcp_tclas->tcp_ip_cls_fr.protocol = 0x11;
615 dhcp_tclas->tcp_ip_cls_fr.cls_fr_mask = 0x58; //bits: 3,4,6
616 }
617
618 rc = sme_mgt_packet_filter_set(priv);
619
620 return rc;
621}
622
623
624int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg)
625{
7e6f5794 626 u8 wmm_qos_info;
635d2b00
GKH
627 int rc = 0;
628
7e6f5794 629 if (get_user(wmm_qos_info, (u8*)(((unifi_cfg_command_t*)arg) + 1))) {
635d2b00
GKH
630 unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
631 return -EFAULT;
632 }
633
634 /* Store the value in the connection info */
635 priv->connection_config.wmmQosInfo = wmm_qos_info;
636
637 return rc;
638}
639
640
641int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg)
642{
26a6b2e1 643 u32 addts_tid;
7e6f5794
GKH
644 u8 addts_ie_length;
645 u8 *addts_ie;
646 u8 *addts_params;
635d2b00
GKH
647 CsrWifiSmeDataBlock tspec;
648 CsrWifiSmeDataBlock tclas;
649 int rc;
650
7e6f5794 651 addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
26a6b2e1 652 if (get_user(addts_tid, (u32*)addts_params)) {
635d2b00
GKH
653 unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
654 return -EFAULT;
655 }
656
26a6b2e1 657 addts_params += sizeof(u32);
7e6f5794 658 if (get_user(addts_ie_length, (u8*)addts_params)) {
635d2b00
GKH
659 unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
660 return -EFAULT;
661 }
662
663 unifi_trace(priv, UDBG4, "addts: tid = 0x%x ie_length = %d\n",
664 addts_tid, addts_ie_length);
665
786eeeb3 666 addts_ie = kmalloc(addts_ie_length, GFP_KERNEL);
635d2b00
GKH
667 if (addts_ie == NULL) {
668 unifi_error(priv,
669 "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n",
670 addts_ie_length);
671 return -ENOMEM;
672 }
673
7e6f5794 674 addts_params += sizeof(u8);
635d2b00
GKH
675 rc = copy_from_user(addts_ie, addts_params, addts_ie_length);
676 if (rc) {
677 unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n");
55a27055 678 kfree(addts_ie);
635d2b00
GKH
679 return -EFAULT;
680 }
681
682 tspec.data = addts_ie;
683 tspec.length = addts_ie_length;
684 tclas.data = NULL;
685 tclas.length = 0;
686
687 rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_ADD, addts_tid,
688 &tspec, &tclas);
689
55a27055 690 kfree(addts_ie);
635d2b00
GKH
691 return rc;
692}
693
694
695int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg)
696{
26a6b2e1 697 u32 delts_tid;
7e6f5794 698 u8 *delts_params;
635d2b00
GKH
699 CsrWifiSmeDataBlock tspec;
700 CsrWifiSmeDataBlock tclas;
701 int rc;
702
7e6f5794 703 delts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
26a6b2e1 704 if (get_user(delts_tid, (u32*)delts_params)) {
635d2b00
GKH
705 unifi_error(priv, "unifi_cfg_wmm_delts: Failed to get the argument\n");
706 return -EFAULT;
707 }
708
709 unifi_trace(priv, UDBG4, "delts: tid = 0x%x\n", delts_tid);
710
711 tspec.data = tclas.data = NULL;
712 tspec.length = tclas.length = 0;
713
714 rc = sme_mgt_tspec(priv, CSR_WIFI_SME_LIST_ACTION_REMOVE, delts_tid,
715 &tspec, &tclas);
716
717 return rc;
718}
719
720int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg)
721{
5379b13d 722 u8 strict_draft_n;
7e6f5794 723 u8 *strict_draft_n_params;
635d2b00
GKH
724 int rc;
725
726 CsrWifiSmeStaConfig staConfig;
727 CsrWifiSmeDeviceConfig deviceConfig;
728
7e6f5794 729 strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
5379b13d 730 if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) {
635d2b00
GKH
731 unifi_error(priv, "unifi_cfg_strict_draft_n: Failed to get the argument\n");
732 return -EFAULT;
733 }
734
735 unifi_trace(priv, UDBG4, "strict_draft_n: = %s\n", ((strict_draft_n) ? "yes":"no"));
736
737 rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
738
739 if (rc) {
740 unifi_warning(priv, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
741 return -EFAULT;
742 }
743
744 deviceConfig.enableStrictDraftN = strict_draft_n;
745
746 rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
747 if (rc) {
748 unifi_warning(priv, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
749 rc = -EFAULT;
750 }
751
752 return rc;
753}
754
755
756int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg)
757{
5379b13d 758 u8 enable_okc;
7e6f5794 759 u8 *enable_okc_params;
635d2b00
GKH
760 int rc;
761
762 CsrWifiSmeStaConfig staConfig;
763 CsrWifiSmeDeviceConfig deviceConfig;
764
7e6f5794 765 enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
5379b13d 766 if (get_user(enable_okc, (u8*)enable_okc_params)) {
635d2b00
GKH
767 unifi_error(priv, "unifi_cfg_enable_okc: Failed to get the argument\n");
768 return -EFAULT;
769 }
770
771 unifi_trace(priv, UDBG4, "enable_okc: = %s\n", ((enable_okc) ? "yes":"no"));
772
773 rc = sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig);
774 if (rc) {
775 unifi_warning(priv, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
776 return -EFAULT;
777 }
778
779 staConfig.enableOpportunisticKeyCaching = enable_okc;
780
781 rc = sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig);
782 if (rc) {
783 unifi_warning(priv, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
784 rc = -EFAULT;
785 }
786
787 return rc;
788}
789
790
791int unifi_cfg_get_info(unifi_priv_t *priv, unsigned char *arg)
792{
793 unifi_cfg_get_t get_cmd;
794 char inst_name[IFNAMSIZ];
795 int rc;
796
797 if (get_user(get_cmd, (unifi_cfg_get_t*)(((unifi_cfg_command_t*)arg) + 1))) {
798 unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
799 return -EFAULT;
800 }
801
802 switch (get_cmd) {
803 case UNIFI_CFG_GET_COEX:
804 {
805 CsrWifiSmeCoexInfo coexInfo;
806 /* Get the coex info from the SME */
807 rc = sme_mgt_coex_info_get(priv, &coexInfo);
808 if (rc) {
809 unifi_error(priv, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n");
810 return rc;
811 }
812
813 /* Copy the info to the out buffer */
814 if (copy_to_user((void*)arg,
815 &coexInfo,
816 sizeof(CsrWifiSmeCoexInfo))) {
817 unifi_error(priv, "UNIFI_CFG: Failed to copy the coex info\n");
818 return -EFAULT;
819 }
820 break;
821 }
822 case UNIFI_CFG_GET_POWER_MODE:
823 {
824 CsrWifiSmePowerConfig powerConfig;
825 rc = sme_mgt_power_config_get(priv, &powerConfig);
826 if (rc) {
827 unifi_error(priv, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
828 return rc;
829 }
830
831 /* Copy the info to the out buffer */
832 if (copy_to_user((void*)arg,
833 &powerConfig.powerSaveLevel,
834 sizeof(CsrWifiSmePowerSaveLevel))) {
835 unifi_error(priv, "UNIFI_CFG: Failed to copy the power save info\n");
836 return -EFAULT;
837 }
838 break;
839 }
840 case UNIFI_CFG_GET_POWER_SUPPLY:
841 {
842 CsrWifiSmeHostConfig hostConfig;
843 rc = sme_mgt_host_config_get(priv, &hostConfig);
844 if (rc) {
845 unifi_error(priv, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
846 return rc;
847 }
848
849 /* Copy the info to the out buffer */
850 if (copy_to_user((void*)arg,
851 &hostConfig.powerMode,
852 sizeof(CsrWifiSmeHostPowerMode))) {
853 unifi_error(priv, "UNIFI_CFG: Failed to copy the host power mode\n");
854 return -EFAULT;
855 }
856 break;
857 }
858 case UNIFI_CFG_GET_VERSIONS:
859 break;
860 case UNIFI_CFG_GET_INSTANCE:
861 {
8c87f69a 862 u16 InterfaceId=0;
635d2b00
GKH
863 uf_net_get_name(priv->netdev[InterfaceId], &inst_name[0], sizeof(inst_name));
864
865 /* Copy the info to the out buffer */
866 if (copy_to_user((void*)arg,
867 &inst_name[0],
868 sizeof(inst_name))) {
869 unifi_error(priv, "UNIFI_CFG: Failed to copy the instance name\n");
870 return -EFAULT;
871 }
872 }
873 break;
874
875 case UNIFI_CFG_GET_AP_CONFIG:
876 {
877#ifdef CSR_SUPPORT_WEXT_AP
878 uf_cfg_ap_config_t cfg_ap_config;
879 cfg_ap_config.channel = priv->ap_config.channel;
880 cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval;
881 cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled;
882 cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod;
883 cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap;
884 if (copy_to_user((void*)arg,
885 &cfg_ap_config,
886 sizeof(uf_cfg_ap_config_t))) {
887 unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n");
888 return -EFAULT;
889 }
890#else
891 return -EPERM;
892#endif
893 }
894 break;
895
896
897 default:
898 unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n");
899 return -EINVAL;
900 }
901
902 return 0;
903}
904#ifdef CSR_SUPPORT_WEXT_AP
905int
7e6f5794 906 uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap)
635d2b00
GKH
907{
908 int i=0;
5379b13d 909 u8 b=FALSE, g = FALSE, n = FALSE;
635d2b00
GKH
910 b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B;
911 n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N;
912 g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G;
913 if(b || g) {
914 supportedRates[i++]=0x82;
915 supportedRates[i++]=0x84;
916 supportedRates[i++]=0x8b;
917 supportedRates[i++]=0x96;
918 } else if(n) {
95edd09e 919 /* For some strange reasons WiFi stack needs both b and g rates*/
635d2b00
GKH
920 supportedRates[i++]=0x02;
921 supportedRates[i++]=0x04;
922 supportedRates[i++]=0x0b;
923 supportedRates[i++]=0x16;
95edd09e
GKH
924 supportedRates[i++]=0x0c;
925 supportedRates[i++]=0x12;
926 supportedRates[i++]=0x18;
927 supportedRates[i++]=0x24;
928 supportedRates[i++]=0x30;
929 supportedRates[i++]=0x48;
930 supportedRates[i++]=0x60;
931 supportedRates[i++]=0x6c;
635d2b00
GKH
932 }
933 if(g) {
934 if(!b) {
935 supportedRates[i++]=0x8c;
936 supportedRates[i++]=0x98;
937 supportedRates[i++]=0xb0;
938 } else {
939 supportedRates[i++]=0x0c;
940 supportedRates[i++]=0x18;
941 supportedRates[i++]=0x30;
942 }
943 supportedRates[i++]=0x48;
944 supportedRates[i++]=0x12;
945 supportedRates[i++]=0x24;
946 supportedRates[i++]=0x60;
947 supportedRates[i++]=0x6c;
948 }
949 return i;
950}
951int unifi_cfg_set_ap_config(unifi_priv_t * priv,unsigned char* arg)
952{
953 uf_cfg_ap_config_t cfg_ap_config;
954 char *buffer;
955
956 buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
957 if (copy_from_user(&cfg_ap_config, (void*)buffer,
958 sizeof(uf_cfg_ap_config_t))) {
959 unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n");
960 return -EFAULT;
961 }
962 priv->ap_config.channel = cfg_ap_config.channel;
963 priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod;
964 priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval;
965 priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout;
966 priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled;
967 priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout;
968 priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout;
969 priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit;
970
971 priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled;
972 priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType;
973
974 priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled;
975
976 priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc;
977 priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed;
978
979 priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap;
980 priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval;
981
982 priv->ap_mac_config.supportedRatesCount= uf_configure_supported_rates(priv->ap_mac_config.supportedRates,priv->ap_mac_config.phySupportedBitmap);
983
984 return 0;
985}
986
987#endif
988#ifdef CSR_SUPPORT_WEXT
989
990 void
991uf_sme_config_wq(struct work_struct *work)
992{
993 CsrWifiSmeStaConfig staConfig;
994 CsrWifiSmeDeviceConfig deviceConfig;
995 unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);
996
997 /* Register to receive indications from the SME */
998 CsrWifiSmeEventMaskSetReqSend(0,
999 CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY |
1000 CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE);
1001
1002 if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) {
1003 unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1004 return;
1005 }
1006
1007 if (priv->if_index == CSR_INDEX_5G) {
1008 staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0;
1009 } else {
1010 staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4;
1011 }
1012
1013 deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d;
1014 if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) {
1015 unifi_warning(priv,
1016 "SME config for 802.11d Trust Level and Radio Band failed.\n");
1017 return;
1018 }
1019
1020} /* uf_sme_config_wq() */
1021
1022#endif /* CSR_SUPPORT_WEXT */
1023
1024
1025/*
1026 * ---------------------------------------------------------------------------
1027 * uf_ta_ind_wq
1028 *
1029 * Deferred work queue function to send Traffic Analysis protocols
1030 * indications to the SME.
1031 * These are done in a deferred work queue for two reasons:
1032 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1033 * - we want to load the main driver data path as lightly as possible
1034 *
1035 * The TA classifications already come from a workqueue.
1036 *
1037 * Arguments:
1038 * work Pointer to work queue item.
1039 *
1040 * Returns:
1041 * None.
1042 * ---------------------------------------------------------------------------
1043 */
1044 void
1045uf_ta_ind_wq(struct work_struct *work)
1046{
1047 struct ta_ind *ind = container_of(work, struct ta_ind, task);
1048 unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work);
8c87f69a 1049 u16 interfaceTag = 0;
635d2b00
GKH
1050
1051
1052 CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0,
1053 interfaceTag,
1054 ind->packet_type,
1055 ind->direction,
1056 ind->src_addr);
1057 ind->in_use = 0;
1058
1059} /* uf_ta_ind_wq() */
1060
1061
1062/*
1063 * ---------------------------------------------------------------------------
1064 * uf_ta_sample_ind_wq
1065 *
1066 * Deferred work queue function to send Traffic Analysis sample
1067 * indications to the SME.
1068 * These are done in a deferred work queue for two reasons:
1069 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1070 * - we want to load the main driver data path as lightly as possible
1071 *
1072 * The TA classifications already come from a workqueue.
1073 *
1074 * Arguments:
1075 * work Pointer to work queue item.
1076 *
1077 * Returns:
1078 * None.
1079 * ---------------------------------------------------------------------------
1080 */
1081 void
1082uf_ta_sample_ind_wq(struct work_struct *work)
1083{
1084 struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task);
1085 unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work);
8c87f69a 1086 u16 interfaceTag = 0;
635d2b00
GKH
1087
1088 unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n",
1089 priv->rxTcpThroughput,
1090 priv->txTcpThroughput,
1091 priv->rxUdpThroughput,
1092 priv->txUdpThroughput,
1093 priv->bh_thread.prio);
1094
1095 if(priv->rxTcpThroughput > 1000)
1096 {
1097 if (bh_priority == -1 && priv->bh_thread.prio != 1)
1098 {
1099 struct sched_param param;
1100 priv->bh_thread.prio = 1;
1101 unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n",
1102 priv->bh_thread.name, priv->bh_thread.prio);
1103 param.sched_priority = priv->bh_thread.prio;
1104 sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, &param);
1105 }
1106 } else
1107 {
1108 if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO)
1109 {
1110 struct sched_param param;
1111 param.sched_priority = 0;
1112 sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, &param);
1113 priv->bh_thread.prio = DEFAULT_PRIO;
1114 unifi_trace(priv, UDBG1, "%s new thread priority = %d\n",
1115 priv->bh_thread.name, priv->bh_thread.prio);
1116 set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio));
1117 }
1118 }
1119
1120 CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, interfaceTag, ind->stats);
1121
1122 ind->in_use = 0;
1123
1124} /* uf_ta_sample_ind_wq() */
1125
1126
1127/*
1128 * ---------------------------------------------------------------------------
1129 * uf_send_m4_ready_wq
1130 *
1131 * Deferred work queue function to send M4 ReadyToSend inds to the SME.
1132 * These are done in a deferred work queue for two reasons:
1133 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1134 * - we want to load the main driver data path as lightly as possible
1135 *
1136 * Arguments:
1137 * work Pointer to work queue item.
1138 *
1139 * Returns:
1140 * None.
1141 * ---------------------------------------------------------------------------
1142 */
1143void
1144uf_send_m4_ready_wq(struct work_struct *work)
1145{
1146 netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task);
8c87f69a 1147 u16 iface = InterfacePriv->InterfaceTag;
635d2b00
GKH
1148 unifi_priv_t *priv = InterfacePriv->privPtr;
1149 CSR_MA_PACKET_REQUEST *req = &InterfacePriv->m4_signal.u.MaPacketRequest;
1150 CsrWifiMacAddress peer;
1151 unsigned long flags;
1152
635d2b00
GKH
1153 /* The peer address was stored in the signal */
1154 spin_lock_irqsave(&priv->m4_lock, flags);
1155 memcpy(peer.a, req->Ra.x, sizeof(peer.a));
1156 spin_unlock_irqrestore(&priv->m4_lock, flags);
1157
1158 /* Send a signal to SME */
1159 CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer);
1160
a6737c73
AS
1161 unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
1162 peer.a);
635d2b00 1163
635d2b00
GKH
1164} /* uf_send_m4_ready_wq() */
1165
95edd09e
GKH
1166#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1167/*
1168 * ---------------------------------------------------------------------------
1169 * uf_send_pkt_to_encrypt
1170 *
1171 * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
1172 * These are done in a deferred work queue for two reasons:
1173 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1174 * - we want to load the main driver data path as lightly as possible
1175 *
1176 * Arguments:
1177 * work Pointer to work queue item.
1178 *
1179 * Returns:
1180 * None.
1181 * ---------------------------------------------------------------------------
1182 */
1183void uf_send_pkt_to_encrypt(struct work_struct *work)
1184{
1185 netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
8c87f69a 1186 u16 interfaceTag = interfacePriv->InterfaceTag;
95edd09e
GKH
1187 unifi_priv_t *priv = interfacePriv->privPtr;
1188
26a6b2e1 1189 u32 pktBulkDataLength;
7e6f5794 1190 u8 *pktBulkData;
95edd09e
GKH
1191 unsigned long flags;
1192
1193 if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
1194
95edd09e
GKH
1195 pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
1196
1197 if (pktBulkDataLength > 0) {
786eeeb3 1198 pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
b7244a31 1199 memset(pktBulkData, 0, pktBulkDataLength);
95edd09e
GKH
1200 } else {
1201 unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1202 return;
1203 }
1204
1205 spin_lock_irqsave(&priv->wapi_lock, flags);
1206 /* Copy over the MA PKT REQ bulk data */
25aebdb1 1207 memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
95edd09e
GKH
1208 /* Free any bulk data buffers allocated for the WAPI Data pkt */
1209 unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
1210 interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
1211 interfacePriv->wapi_unicast_bulk_data.data_length = 0;
1212 interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
1213 spin_unlock_irqrestore(&priv->wapi_lock, flags);
1214
1215 CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
1216 unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
1217
55a27055 1218 kfree(pktBulkData); /* Would have been copied over by the SME Handler */
95edd09e 1219
95edd09e
GKH
1220 } else {
1221 unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
1222 }
1223}/* uf_send_pkt_to_encrypt() */
1224#endif