ACPI / dock: fix error return code in dock_add()
[firefly-linux-kernel-4.4.55.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
880                 memset(&cfg_ap_config, 0, sizeof(cfg_ap_config));
881                 cfg_ap_config.channel = priv->ap_config.channel;
882                 cfg_ap_config.beaconInterval = priv->ap_mac_config.beaconInterval;
883                 cfg_ap_config.wmmEnabled = priv->ap_mac_config.wmmEnabled;
884                 cfg_ap_config.dtimPeriod = priv->ap_mac_config.dtimPeriod;
885                 cfg_ap_config.phySupportedBitmap = priv->ap_mac_config.phySupportedBitmap;
886                 if (copy_to_user((void*)arg,
887                             &cfg_ap_config,
888                             sizeof(uf_cfg_ap_config_t))) {
889                     unifi_error(priv, "UNIFI_CFG: Failed to copy the AP configuration\n");
890                     return -EFAULT;
891                 }
892 #else
893                    return -EPERM;
894 #endif
895             }
896             break;
897
898
899         default:
900             unifi_error(priv, "unifi_cfg_get_info: Unknown value.\n");
901             return -EINVAL;
902     }
903
904     return 0;
905 }
906 #ifdef CSR_SUPPORT_WEXT_AP
907 int
908  uf_configure_supported_rates(u8 * supportedRates, u8 phySupportedBitmap)
909 {
910     int i=0;
911     u8 b=FALSE, g = FALSE, n = FALSE;
912     b = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_B;
913     n = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_N;
914     g = phySupportedBitmap & CSR_WIFI_SME_AP_PHY_SUPPORT_G;
915     if(b || g) {
916         supportedRates[i++]=0x82;
917         supportedRates[i++]=0x84;
918         supportedRates[i++]=0x8b;
919         supportedRates[i++]=0x96;
920     } else if(n) {
921         /* For some strange reasons WiFi stack needs both b and g rates*/
922         supportedRates[i++]=0x02;
923         supportedRates[i++]=0x04;
924         supportedRates[i++]=0x0b;
925         supportedRates[i++]=0x16;
926         supportedRates[i++]=0x0c;
927         supportedRates[i++]=0x12;
928         supportedRates[i++]=0x18;
929         supportedRates[i++]=0x24;
930         supportedRates[i++]=0x30;
931         supportedRates[i++]=0x48;
932         supportedRates[i++]=0x60;
933         supportedRates[i++]=0x6c;
934     }
935     if(g) {
936         if(!b) {
937             supportedRates[i++]=0x8c;
938             supportedRates[i++]=0x98;
939             supportedRates[i++]=0xb0;
940         } else {
941             supportedRates[i++]=0x0c;
942             supportedRates[i++]=0x18;
943             supportedRates[i++]=0x30;
944         }
945         supportedRates[i++]=0x48;
946         supportedRates[i++]=0x12;
947         supportedRates[i++]=0x24;
948         supportedRates[i++]=0x60;
949         supportedRates[i++]=0x6c;
950     }
951     return i;
952 }
953 int unifi_cfg_set_ap_config(unifi_priv_t * priv, unsigned char* arg)
954 {
955     uf_cfg_ap_config_t cfg_ap_config;
956     char *buffer;
957
958     buffer = ((unsigned char*)arg) + sizeof(unifi_cfg_command_t) + sizeof(unsigned int);
959     if (copy_from_user(&cfg_ap_config, (void*)buffer,
960                 sizeof(uf_cfg_ap_config_t))) {
961         unifi_error(priv, "UNIFI_CFG: Failed to get the ap config struct\n");
962         return -EFAULT;
963     }
964     priv->ap_config.channel = cfg_ap_config.channel;
965     priv->ap_mac_config.dtimPeriod = cfg_ap_config.dtimPeriod;
966     priv->ap_mac_config.beaconInterval = cfg_ap_config.beaconInterval;
967     priv->group_sec_config.apGroupkeyTimeout = cfg_ap_config.groupkeyTimeout;
968     priv->group_sec_config.apStrictGtkRekey = cfg_ap_config.strictGtkRekeyEnabled;
969     priv->group_sec_config.apGmkTimeout = cfg_ap_config.gmkTimeout;
970     priv->group_sec_config.apResponseTimeout = cfg_ap_config.responseTimeout;
971     priv->group_sec_config.apRetransLimit = cfg_ap_config.retransLimit;
972
973     priv->ap_mac_config.shortSlotTimeEnabled = cfg_ap_config.shortSlotTimeEnabled;
974     priv->ap_mac_config.ctsProtectionType=cfg_ap_config.ctsProtectionType;
975
976     priv->ap_mac_config.wmmEnabled = cfg_ap_config.wmmEnabled;
977
978     priv->ap_mac_config.apHtParams.rxStbc=cfg_ap_config.rxStbc;
979     priv->ap_mac_config.apHtParams.rifsModeAllowed=cfg_ap_config.rifsModeAllowed;
980
981     priv->ap_mac_config.phySupportedBitmap = cfg_ap_config.phySupportedBitmap;
982     priv->ap_mac_config.maxListenInterval=cfg_ap_config.maxListenInterval;
983
984     priv->ap_mac_config.supportedRatesCount=     uf_configure_supported_rates(priv->ap_mac_config.supportedRates, priv->ap_mac_config.phySupportedBitmap);
985
986     return 0;
987 }
988
989 #endif
990 #ifdef CSR_SUPPORT_WEXT
991
992     void
993 uf_sme_config_wq(struct work_struct *work)
994 {
995     CsrWifiSmeStaConfig  staConfig;
996     CsrWifiSmeDeviceConfig  deviceConfig;
997     unifi_priv_t *priv = container_of(work, unifi_priv_t, sme_config_task);
998
999     /* Register to receive indications from the SME */
1000     CsrWifiSmeEventMaskSetReqSend(0,
1001             CSR_WIFI_SME_INDICATIONS_WIFIOFF | CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY |
1002             CSR_WIFI_SME_INDICATIONS_MEDIASTATUS | CSR_WIFI_SME_INDICATIONS_MICFAILURE);
1003
1004     if (sme_mgt_sme_config_get(priv, &staConfig, &deviceConfig)) {
1005         unifi_warning(priv, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1006         return;
1007     }
1008
1009     if (priv->if_index == CSR_INDEX_5G) {
1010         staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_5_0;
1011     } else {
1012         staConfig.ifIndex = CSR_WIFI_SME_RADIO_IF_GHZ_2_4;
1013     }
1014
1015     deviceConfig.trustLevel = (CsrWifiSme80211dTrustLevel)tl_80211d;
1016     if (sme_mgt_sme_config_set(priv, &staConfig, &deviceConfig)) {
1017         unifi_warning(priv,
1018                 "SME config for 802.11d Trust Level and Radio Band failed.\n");
1019         return;
1020     }
1021
1022 } /* uf_sme_config_wq() */
1023
1024 #endif /* CSR_SUPPORT_WEXT */
1025
1026
1027 /*
1028  * ---------------------------------------------------------------------------
1029  *  uf_ta_ind_wq
1030  *
1031  *      Deferred work queue function to send Traffic Analysis protocols
1032  *      indications to the SME.
1033  *      These are done in a deferred work queue for two reasons:
1034  *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1035  *       - we want to load the main driver data path as lightly as possible
1036  *
1037  *      The TA classifications already come from a workqueue.
1038  *
1039  *  Arguments:
1040  *      work    Pointer to work queue item.
1041  *
1042  *  Returns:
1043  *      None.
1044  * ---------------------------------------------------------------------------
1045  */
1046     void
1047 uf_ta_ind_wq(struct work_struct *work)
1048 {
1049     struct ta_ind *ind = container_of(work, struct ta_ind, task);
1050     unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_ind_work);
1051     u16 interfaceTag = 0;
1052
1053
1054     CsrWifiRouterCtrlTrafficProtocolIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
1055             interfaceTag,
1056             ind->packet_type,
1057             ind->direction,
1058             ind->src_addr);
1059     ind->in_use = 0;
1060
1061 } /* uf_ta_ind_wq() */
1062
1063
1064 /*
1065  * ---------------------------------------------------------------------------
1066  *  uf_ta_sample_ind_wq
1067  *
1068  *      Deferred work queue function to send Traffic Analysis sample
1069  *      indications to the SME.
1070  *      These are done in a deferred work queue for two reasons:
1071  *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1072  *       - we want to load the main driver data path as lightly as possible
1073  *
1074  *      The TA classifications already come from a workqueue.
1075  *
1076  *  Arguments:
1077  *      work    Pointer to work queue item.
1078  *
1079  *  Returns:
1080  *      None.
1081  * ---------------------------------------------------------------------------
1082  */
1083     void
1084 uf_ta_sample_ind_wq(struct work_struct *work)
1085 {
1086     struct ta_sample_ind *ind = container_of(work, struct ta_sample_ind, task);
1087     unifi_priv_t *priv = container_of(ind, unifi_priv_t, ta_sample_ind_work);
1088     u16 interfaceTag = 0;
1089
1090      unifi_trace(priv, UDBG5, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n",
1091         priv->rxTcpThroughput,
1092         priv->txTcpThroughput,
1093         priv->rxUdpThroughput,
1094         priv->txUdpThroughput,
1095         priv->bh_thread.prio);
1096
1097     if(priv->rxTcpThroughput > 1000)
1098     {
1099         if (bh_priority == -1 && priv->bh_thread.prio != 1)
1100         {
1101             struct sched_param param;
1102             priv->bh_thread.prio = 1;
1103             unifi_trace(priv, UDBG1, "%s new thread (RT) priority = %d\n",
1104                         priv->bh_thread.name, priv->bh_thread.prio);
1105             param.sched_priority = priv->bh_thread.prio;
1106             sched_setscheduler(priv->bh_thread.thread_task, SCHED_FIFO, &param);
1107         }
1108     } else
1109     {
1110         if (bh_priority == -1 && priv->bh_thread.prio != DEFAULT_PRIO)
1111         {
1112             struct sched_param param;
1113             param.sched_priority = 0;
1114             sched_setscheduler(priv->bh_thread.thread_task, SCHED_NORMAL, &param);
1115             priv->bh_thread.prio = DEFAULT_PRIO;
1116             unifi_trace(priv, UDBG1, "%s new thread priority = %d\n",
1117                         priv->bh_thread.name, priv->bh_thread.prio);
1118             set_user_nice(priv->bh_thread.thread_task, PRIO_TO_NICE(priv->bh_thread.prio));
1119         }
1120     }
1121
1122     CsrWifiRouterCtrlTrafficSampleIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, ind->stats);
1123
1124     ind->in_use = 0;
1125
1126 } /* uf_ta_sample_ind_wq() */
1127
1128
1129 /*
1130  * ---------------------------------------------------------------------------
1131  *  uf_send_m4_ready_wq
1132  *
1133  *      Deferred work queue function to send M4 ReadyToSend inds to the SME.
1134  *      These are done in a deferred work queue for two reasons:
1135  *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1136  *       - we want to load the main driver data path as lightly as possible
1137  *
1138  *  Arguments:
1139  *      work    Pointer to work queue item.
1140  *
1141  *  Returns:
1142  *      None.
1143  * ---------------------------------------------------------------------------
1144  */
1145 void
1146 uf_send_m4_ready_wq(struct work_struct *work)
1147 {
1148     netInterface_priv_t *InterfacePriv = container_of(work, netInterface_priv_t, send_m4_ready_task);
1149     u16 iface = InterfacePriv->InterfaceTag;
1150     unifi_priv_t *priv = InterfacePriv->privPtr;
1151     CSR_MA_PACKET_REQUEST *req = &InterfacePriv->m4_signal.u.MaPacketRequest;
1152     CsrWifiMacAddress peer;
1153     unsigned long flags;
1154
1155     /* The peer address was stored in the signal */
1156     spin_lock_irqsave(&priv->m4_lock, flags);
1157     memcpy(peer.a, req->Ra.x, sizeof(peer.a));
1158     spin_unlock_irqrestore(&priv->m4_lock, flags);
1159
1160     /* Send a signal to SME */
1161     CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, iface, peer);
1162
1163         unifi_trace(priv, UDBG1, "M4ReadyToSendInd sent for peer %pMF\n",
1164                 peer.a);
1165
1166 } /* uf_send_m4_ready_wq() */
1167
1168 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1169 /*
1170  * ---------------------------------------------------------------------------
1171  *  uf_send_pkt_to_encrypt
1172  *
1173  *      Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
1174  *      These are done in a deferred work queue for two reasons:
1175  *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1176  *       - we want to load the main driver data path as lightly as possible
1177  *
1178  *  Arguments:
1179  *      work    Pointer to work queue item.
1180  *
1181  *  Returns:
1182  *      None.
1183  * ---------------------------------------------------------------------------
1184  */
1185 void uf_send_pkt_to_encrypt(struct work_struct *work)
1186 {
1187     netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
1188     u16 interfaceTag = interfacePriv->InterfaceTag;
1189     unifi_priv_t *priv = interfacePriv->privPtr;
1190
1191     u32 pktBulkDataLength;
1192     u8 *pktBulkData;
1193     unsigned long flags;
1194
1195     if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
1196
1197         pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
1198
1199         if (pktBulkDataLength > 0) {
1200                     pktBulkData = kmalloc(pktBulkDataLength, GFP_KERNEL);
1201             } else {
1202                     unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1203                     return;
1204             }
1205
1206         spin_lock_irqsave(&priv->wapi_lock, flags);
1207         /* Copy over the MA PKT REQ bulk data */
1208         memcpy(pktBulkData, (u8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
1209         /* Free any bulk data buffers allocated for the WAPI Data pkt */
1210         unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
1211         interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
1212         interfacePriv->wapi_unicast_bulk_data.data_length = 0;
1213         interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
1214         spin_unlock_irqrestore(&priv->wapi_lock, flags);
1215
1216         CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
1217         unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
1218
1219         kfree(pktBulkData); /* Would have been copied over by the SME Handler */
1220
1221     } else {
1222             unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n", interfacePriv->interfaceMode);
1223     }
1224 }/* uf_send_pkt_to_encrypt() */
1225 #endif