Merge tag 'staging-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[pandora-kernel.git] / drivers / staging / csr / unifi_sme.c
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"
18 #include <linux/sched/rt.h>
19
20
21
22     int
23 convert_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
68 sme_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
81     /* Just a sanity check */
82     if ((signal == NULL) || (signal_len <= 0)) {
83         return;
84     }
85
86     priv = uf_find_instance(pcli->instance);
87     if (!priv) {
88         unifi_error(priv, "sme_log_event: invalid priv\n");
89         return;
90     }
91
92     if (priv->smepriv == NULL) {
93         unifi_error(priv, "sme_log_event: invalid smepriv\n");
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         {
108             return;
109         }
110         if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID)
111         {
112             u16 frmCtrl;
113             u8 unicastPdu = TRUE;
114             u8 *macHdrLocation;
115             u8 *raddr = NULL, *taddr = NULL;
116             CsrWifiMacAddress peerMacAddress;
117             /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
118             CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication;
119
120             macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
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
128             memcpy(peerMacAddress.a, taddr, ETH_ALEN);
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                 {
144                     u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00;
145                     u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff);
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;
161             u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff);
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);
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) {
209                     CsrWifiRouterMaPacketCfmSend((u16)signal[2],
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                 }
216                 return;
217             }
218         }
219     }
220
221     mlmeCommand.length = signal_len;
222     mlmeCommand.data = (u8*)signal;
223
224     dataref1.length = bulkdata->d[0].data_length;
225     if (dataref1.length > 0) {
226         dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr;
227     } else
228     {
229         dataref1.data = NULL;
230     }
231
232     dataref2.length = bulkdata->d[1].data_length;
233     if (dataref2.length > 0) {
234         dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr;
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
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  */
262 CsrWifiRouterCtrlPortAction
263 uf_sme_port_state(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
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  */
326 unifi_port_cfg_t*
327 uf_sme_port_config_handle(unifi_priv_t *priv, unsigned char *address, int queue, u16 interfaceTag)
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
376 void
377 uf_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;
382     u16 interfaceTag = 0;
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      */
406     multicast_address_list = kmalloc(mc_count * sizeof(CsrWifiMacAddress), GFP_KERNEL);
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) {
418         kfree(multicast_address_list);
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*/
428     kfree(multicast_address_list);
429 }
430
431
432 int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
433 {
434     unifi_cfg_power_t cfg_power;
435     int rc;
436     int wol;
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:
445             priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
446             rc = sme_sys_suspend(priv);
447             if (rc) {
448                 return rc;
449             }
450             break;
451         case UNIFI_CFG_POWER_ON:
452             wol = priv->wol_suspend;
453             rc = sme_sys_resume(priv);
454             if (rc) {
455                 return rc;
456             }
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             }
463             break;
464         default:
465             unifi_error(priv, "WIFI POWER: Unknown value.\n");
466             return -EINVAL;
467     }
468
469     return 0;
470 }
471
472
473 int 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
519 int 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
558 int 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) {
567         kfree(priv->filter_tclas_ies);
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) {
585         priv->filter_tclas_ies = kmalloc(priv->packet_filters.tclas_ies_length, GFP_KERNEL);
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;
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;
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
624 int unifi_cfg_wmm_qos_info(unifi_priv_t *priv, unsigned char *arg)
625 {
626     u8 wmm_qos_info;
627     int rc = 0;
628
629     if (get_user(wmm_qos_info, (u8*)(((unifi_cfg_command_t*)arg) + 1))) {
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
641 int unifi_cfg_wmm_addts(unifi_priv_t *priv, unsigned char *arg)
642 {
643     u32 addts_tid;
644     u8 addts_ie_length;
645     u8 *addts_ie;
646     u8 *addts_params;
647     CsrWifiSmeDataBlock tspec;
648     CsrWifiSmeDataBlock tclas;
649     int rc;
650
651     addts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
652     if (get_user(addts_tid, (u32*)addts_params)) {
653         unifi_error(priv, "unifi_cfg_wmm_addts: Failed to get the argument\n");
654         return -EFAULT;
655     }
656
657     addts_params += sizeof(u32);
658     if (get_user(addts_ie_length, (u8*)addts_params)) {
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
666     addts_ie = kmalloc(addts_ie_length, GFP_KERNEL);
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
674     addts_params += sizeof(u8);
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");
678         kfree(addts_ie);
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
690     kfree(addts_ie);
691     return rc;
692 }
693
694
695 int unifi_cfg_wmm_delts(unifi_priv_t *priv, unsigned char *arg)
696 {
697     u32 delts_tid;
698     u8 *delts_params;
699     CsrWifiSmeDataBlock tspec;
700     CsrWifiSmeDataBlock tclas;
701     int rc;
702
703     delts_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
704     if (get_user(delts_tid, (u32*)delts_params)) {
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
720 int unifi_cfg_strict_draft_n(unifi_priv_t *priv, unsigned char *arg)
721 {
722     u8 strict_draft_n;
723     u8 *strict_draft_n_params;
724     int rc;
725
726     CsrWifiSmeStaConfig  staConfig;
727     CsrWifiSmeDeviceConfig  deviceConfig;
728
729     strict_draft_n_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
730     if (get_user(strict_draft_n, (u8*)strict_draft_n_params)) {
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
756 int unifi_cfg_enable_okc(unifi_priv_t *priv, unsigned char *arg)
757 {
758     u8 enable_okc;
759     u8 *enable_okc_params;
760     int rc;
761
762     CsrWifiSmeStaConfig staConfig;
763     CsrWifiSmeDeviceConfig deviceConfig;
764
765     enable_okc_params = (u8*)(((unifi_cfg_command_t*)arg) + 1);
766     if (get_user(enable_okc, (u8*)enable_okc_params)) {
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
791 int 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             {
862                 u16 InterfaceId=0;
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
905 int
906  uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap)
907 {
908     int i=0;
909     u8 b=FALSE, g = FALSE, n = FALSE;
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) {
919         /* For some strange reasons WiFi stack needs both b and g rates*/
920         supportedRates[i++]=0x02;
921         supportedRates[i++]=0x04;
922         supportedRates[i++]=0x0b;
923         supportedRates[i++]=0x16;
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;
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 }
951 int 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
991 uf_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
1045 uf_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);
1049     u16 interfaceTag = 0;
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
1082 uf_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);
1086     u16 interfaceTag = 0;
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  */
1143 void
1144 uf_send_m4_ready_wq(struct work_struct *work)
1145 {
1146     netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task);
1147     u16 iface = InterfacePriv->InterfaceTag;
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
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
1161         unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
1162                 peer.a);
1163
1164 } /* uf_send_m4_ready_wq() */
1165
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  */
1183 void 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);
1186     u16 interfaceTag = interfacePriv->InterfaceTag;
1187     unifi_priv_t *priv = interfacePriv->privPtr;
1188
1189     u32 pktBulkDataLength;
1190     u8 *pktBulkData;
1191     unsigned long flags;
1192
1193     if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
1194
1195         pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
1196
1197         if (pktBulkDataLength > 0) {
1198                     pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
1199             } else {
1200                     unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1201                     return;
1202             }
1203
1204         spin_lock_irqsave(&priv->wapi_lock, flags);
1205         /* Copy over the MA PKT REQ bulk data */
1206         memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
1207         /* Free any bulk data buffers allocated for the WAPI Data pkt */
1208         unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
1209         interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
1210         interfacePriv->wapi_unicast_bulk_data.data_length = 0;
1211         interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
1212         spin_unlock_irqrestore(&priv->wapi_lock, flags);
1213
1214         CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
1215         unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
1216
1217         kfree(pktBulkData); /* Would have been copied over by the SME Handler */
1218
1219     } else {
1220             unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
1221     }
1222 }/* uf_send_pkt_to_encrypt() */
1223 #endif