2 * ***************************************************************************
5 * PURPOSE: SME related functions.
7 * Copyright (C) 2007-2009 by Cambridge Silicon Radio Ltd.
9 * Refer to LICENSE.txt included with this source code for details on
12 * ***************************************************************************
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>
23 convert_sme_error(CsrResult error
)
26 case CSR_RESULT_SUCCESS
:
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
:
34 case CSR_WIFI_RESULT_NO_ROOM
:
36 case CSR_WIFI_RESULT_INVALID_PARAMETER
:
38 case CSR_WIFI_RESULT_UNSUPPORTED
:
47 * ---------------------------------------------------------------------------
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.
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.
65 * ---------------------------------------------------------------------------
68 sme_log_event(ul_client_t
*pcli
,
69 const u8
*signal
, int signal_len
,
70 const bulk_data_param_t
*bulkdata
,
74 CSR_SIGNAL unpacked_signal
;
75 CsrWifiSmeDataBlock mlmeCommand
;
76 CsrWifiSmeDataBlock dataref1
;
77 CsrWifiSmeDataBlock dataref2
;
78 CsrResult result
= CSR_RESULT_SUCCESS
;
81 /* Just a sanity check */
82 if ((signal
== NULL
) || (signal_len
<= 0)) {
86 priv
= uf_find_instance(pcli
->instance
);
88 unifi_error(priv
, "sme_log_event: invalid priv\n");
92 if (priv
->smepriv
== NULL
) {
93 unifi_error(priv
, "sme_log_event: invalid smepriv\n");
97 unifi_trace(priv
, UDBG3
,
98 "sme_log_event: Process signal 0x%.4X\n",
99 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal
));
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
))
110 if (unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_MA_PACKET_INDICATION_ID
)
113 u8 unicastPdu
= TRUE
;
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
;
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
);
124 /* Point to the addresses */
125 raddr
= macHdrLocation
+ MAC_HEADER_ADDR1_OFFSET
;
126 taddr
= macHdrLocation
+ MAC_HEADER_ADDR2_OFFSET
;
128 memcpy(peerMacAddress
.a
, taddr
, ETH_ALEN
);
130 if(ind
->ReceptionStatus
== CSR_MICHAEL_MIC_ERROR
)
135 CsrWifiRouterCtrlMicFailureIndSend (priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
136 (ind
->VirtualInterfaceIdentifier
& 0xff), peerMacAddress
,
142 if(ind
->ReceptionStatus
== CSR_RX_SUCCESS
)
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
))
149 uf_process_pm_bit_for_peer(priv
, srcStaInfo
, pmBit
, interfaceTag
);
151 /* Update station last activity flag */
152 srcStaInfo
->activity_flag
= TRUE
;
158 if (unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_MA_PACKET_CONFIRM_ID
)
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
;
166 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
)
168 unifi_error(priv
, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag
);
172 unifi_trace(priv
, UDBG1
, "MA-PACKET Confirm (%x, %x)\n", cfm
->HostTag
, cfm
->TransmissionStatus
);
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
) {
179 if(cfm
->HostTag
== interfacePriv
->multicastPduHostTag
){
180 uf_process_ma_pkt_cfm_for_ap(priv
, interfaceTag
, cfm
);
185 req
= &interfacePriv
->m4_signal
.u
.MaPacketRequest
;
187 if(cfm
->HostTag
& 0x80000000)
189 if (cfm
->TransmissionStatus
!= CSR_TX_SUCCESSFUL
)
191 result
= CSR_RESULT_FAILURE
;
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
))
198 unifi_trace(priv
, UDBG1
, "%s: Sending M4 Transmit CFM\n", __FUNCTION__
);
199 CsrWifiRouterCtrlM4TransmittedIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
203 interfacePriv
->m4_sent
= FALSE
;
204 interfacePriv
->m4_hostTag
= 0xffffffff;
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
,
212 (cfm
->HostTag
& 0x3fffffff), cfm
->Rate
);
214 unifi_trace(priv
, UDBG1
, "%s: M4 received from netdevice\n", __FUNCTION__
);
221 mlmeCommand
.length
= signal_len
;
222 mlmeCommand
.data
= (u8
*)signal
;
224 dataref1
.length
= bulkdata
->d
[0].data_length
;
225 if (dataref1
.length
> 0) {
226 dataref1
.data
= (u8
*) bulkdata
->d
[0].os_data_ptr
;
229 dataref1
.data
= NULL
;
232 dataref2
.length
= bulkdata
->d
[1].data_length
;
233 if (dataref2
.length
> 0) {
234 dataref2
.data
= (u8
*) bulkdata
->d
[1].os_data_ptr
;
237 dataref2
.data
= NULL
;
240 CsrWifiRouterCtrlHipIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, mlmeCommand
.length
, mlmeCommand
.data
,
241 dataref1
.length
, dataref1
.data
,
242 dataref2
.length
, dataref2
.data
);
244 } /* sme_log_event() */
248 * ---------------------------------------------------------------------------
251 * Return the state of the controlled port.
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
259 * An unifi_ControlledPortAction value.
260 * ---------------------------------------------------------------------------
262 CsrWifiRouterCtrlPortAction
263 uf_sme_port_state(unifi_priv_t
*priv
, unsigned char *address
, int queue
, u16 interfaceTag
)
266 unifi_port_config_t
*port
;
267 netInterface_priv_t
*interfacePriv
;
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
;
274 interfacePriv
= priv
->interfacePriv
[interfaceTag
];
276 if (queue
== UF_CONTROLLED_PORT_Q
) {
277 port
= &interfacePriv
->controlled_data_port
;
279 port
= &interfacePriv
->uncontrolled_data_port
;
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
;
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
;
294 unifi_trace(priv
, UDBG5
, "Multiple (%d) port configurations.\n", port
->entries_in_use
);
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
;
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() */
312 * ---------------------------------------------------------------------------
313 * uf_sme_port_config_handle
315 * Return the port config handle of the controlled/uncontrolled port.
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
323 * An unifi_port_cfg_t* .
324 * ---------------------------------------------------------------------------
327 uf_sme_port_config_handle(unifi_priv_t
*priv
, unsigned char *address
, int queue
, u16 interfaceTag
)
330 unifi_port_config_t
*port
;
331 netInterface_priv_t
*interfacePriv
= priv
->interfacePriv
[interfaceTag
];
333 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
) {
334 unifi_error(priv
, "uf_sme_port_config_handle: bad interfaceTag\n");
338 if (queue
== UF_CONTROLLED_PORT_Q
) {
339 port
= &interfacePriv
->controlled_data_port
;
341 port
= &interfacePriv
->uncontrolled_data_port
;
344 if (!port
->entries_in_use
) {
345 unifi_trace(priv
, UDBG5
, "No port configurations, return Discard.\n");
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
);
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]);
356 return &port
->port_cfg
[0];
359 unifi_trace(priv
, UDBG5
, "Multiple port configurations.\n");
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
];
371 /* Could not find any information, return Open. */
372 unifi_trace(priv
, UDBG5
, "port configuration not found, returning NULL (debug).\n");
374 } /* uf_sme_port_config_handle */
377 uf_multicast_list_wq(struct work_struct
*work
)
379 unifi_priv_t
*priv
= container_of(work
, unifi_priv_t
,
380 multicast_list_task
);
382 u16 interfaceTag
= 0;
383 CsrWifiMacAddress
* multicast_address_list
= NULL
;
386 netInterface_priv_t
*interfacePriv
= priv
->interfacePriv
[interfaceTag
];
388 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
) {
389 unifi_error(priv
, "uf_multicast_list_wq: bad interfaceTag\n");
393 unifi_trace(priv
, UDBG5
,
394 "uf_multicast_list_wq: list count = %d\n",
395 interfacePriv
->mc_list_count
);
397 /* Flush the current list */
398 CsrWifiRouterCtrlMulticastAddressIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, interfaceTag
, CSR_WIFI_SME_LIST_ACTION_FLUSH
, 0, NULL
);
400 mc_count
= interfacePriv
->mc_list_count
;
401 mc_list
= interfacePriv
->mc_list
;
403 * Allocate a new list, need to free it later
404 * in unifi_mgt_multicast_address_cfm().
406 multicast_address_list
= kmalloc(mc_count
* sizeof(CsrWifiMacAddress
), GFP_KERNEL
);
408 if (multicast_address_list
== NULL
) {
412 for (i
= 0; i
< mc_count
; i
++) {
413 memcpy(multicast_address_list
[i
].a
, mc_list
, ETH_ALEN
);
417 if (priv
->smepriv
== NULL
) {
418 kfree(multicast_address_list
);
422 CsrWifiRouterCtrlMulticastAddressIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
424 CSR_WIFI_SME_LIST_ACTION_ADD
,
425 mc_count
, multicast_address_list
);
427 /* The SME will take a copy of the addreses*/
428 kfree(multicast_address_list
);
432 int unifi_cfg_power(unifi_priv_t
*priv
, unsigned char *arg
)
434 unifi_cfg_power_t cfg_power
;
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");
444 case UNIFI_CFG_POWER_OFF
:
445 priv
->wol_suspend
= (enable_wol
== UNIFI_WOL_OFF
) ? FALSE
: TRUE
;
446 rc
= sme_sys_suspend(priv
);
451 case UNIFI_CFG_POWER_ON
:
452 wol
= priv
->wol_suspend
;
453 rc
= sme_sys_resume(priv
);
458 /* Kick the BH to ensure pending transfers are handled when
459 * a suspend happened with card powered.
461 unifi_send_signal(priv
->card
, NULL
, 0, NULL
);
465 unifi_error(priv
, "WIFI POWER: Unknown value.\n");
473 int unifi_cfg_power_save(unifi_priv_t
*priv
, unsigned char *arg
)
475 unifi_cfg_powersave_t cfg_power_save
;
476 CsrWifiSmePowerConfig powerConfig
;
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");
484 /* Get the coex info from the SME */
485 rc
= sme_mgt_power_config_get(priv
, &powerConfig
);
487 unifi_error(priv
, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
491 switch (cfg_power_save
) {
492 case UNIFI_CFG_POWERSAVE_NONE
:
493 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW
;
495 case UNIFI_CFG_POWERSAVE_FAST
:
496 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_MED
;
498 case UNIFI_CFG_POWERSAVE_FULL
:
499 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH
;
501 case UNIFI_CFG_POWERSAVE_AUTO
:
502 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO
;
505 unifi_error(priv
, "POWERSAVE: Unknown value.\n");
509 rc
= sme_mgt_power_config_set(priv
, &powerConfig
);
512 unifi_error(priv
, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n");
519 int unifi_cfg_power_supply(unifi_priv_t
*priv
, unsigned char *arg
)
521 unifi_cfg_powersupply_t cfg_power_supply
;
522 CsrWifiSmeHostConfig hostConfig
;
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");
530 /* Get the coex info from the SME */
531 rc
= sme_mgt_host_config_get(priv
, &hostConfig
);
533 unifi_error(priv
, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
537 switch (cfg_power_supply
) {
538 case UNIFI_CFG_POWERSUPPLY_MAINS
:
539 hostConfig
.powerMode
= CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE
;
541 case UNIFI_CFG_POWERSUPPLY_BATTERIES
:
542 hostConfig
.powerMode
= CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE
;
545 unifi_error(priv
, "POWERSUPPLY: Unknown value.\n");
549 rc
= sme_mgt_host_config_set(priv
, &hostConfig
);
551 unifi_error(priv
, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n");
558 int unifi_cfg_packet_filters(unifi_priv_t
*priv
, unsigned char *arg
)
560 unsigned char *tclas_buffer
;
561 unsigned int tclas_buffer_length
;
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
;
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");
578 tclas_buffer_length
= priv
->packet_filters
.tclas_ies_length
;
580 /* Allocate TCLASs if necessary */
581 if (priv
->packet_filters
.dhcp_filter
) {
582 priv
->packet_filters
.tclas_ies_length
+= sizeof(tclas_t
);
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
) {
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
,
593 tclas_buffer_length
)) {
594 unifi_error(priv
, "UNIFI_CFG: Failed to get the TCLAS buffer\n");
600 if(priv
->packet_filters
.dhcp_filter
)
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
618 rc
= sme_mgt_packet_filter_set(priv
);
624 int unifi_cfg_wmm_qos_info(unifi_priv_t
*priv
, unsigned char *arg
)
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");
634 /* Store the value in the connection info */
635 priv
->connection_config
.wmmQosInfo
= wmm_qos_info
;
641 int unifi_cfg_wmm_addts(unifi_priv_t
*priv
, unsigned char *arg
)
647 CsrWifiSmeDataBlock tspec
;
648 CsrWifiSmeDataBlock tclas
;
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");
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");
663 unifi_trace(priv
, UDBG4
, "addts: tid = 0x%x ie_length = %d\n",
664 addts_tid
, addts_ie_length
);
666 addts_ie
= kmalloc(addts_ie_length
, GFP_KERNEL
);
667 if (addts_ie
== NULL
) {
669 "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n",
674 addts_params
+= sizeof(u8
);
675 rc
= copy_from_user(addts_ie
, addts_params
, addts_ie_length
);
677 unifi_error(priv
, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n");
682 tspec
.data
= addts_ie
;
683 tspec
.length
= addts_ie_length
;
687 rc
= sme_mgt_tspec(priv
, CSR_WIFI_SME_LIST_ACTION_ADD
, addts_tid
,
695 int unifi_cfg_wmm_delts(unifi_priv_t
*priv
, unsigned char *arg
)
699 CsrWifiSmeDataBlock tspec
;
700 CsrWifiSmeDataBlock tclas
;
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");
709 unifi_trace(priv
, UDBG4
, "delts: tid = 0x%x\n", delts_tid
);
711 tspec
.data
= tclas
.data
= NULL
;
712 tspec
.length
= tclas
.length
= 0;
714 rc
= sme_mgt_tspec(priv
, CSR_WIFI_SME_LIST_ACTION_REMOVE
, delts_tid
,
720 int unifi_cfg_strict_draft_n(unifi_priv_t
*priv
, unsigned char *arg
)
723 u8
*strict_draft_n_params
;
726 CsrWifiSmeStaConfig staConfig
;
727 CsrWifiSmeDeviceConfig deviceConfig
;
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");
735 unifi_trace(priv
, UDBG4
, "strict_draft_n: = %s\n", ((strict_draft_n
) ? "yes":"no"));
737 rc
= sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
);
740 unifi_warning(priv
, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
744 deviceConfig
.enableStrictDraftN
= strict_draft_n
;
746 rc
= sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
);
748 unifi_warning(priv
, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
756 int unifi_cfg_enable_okc(unifi_priv_t
*priv
, unsigned char *arg
)
759 u8
*enable_okc_params
;
762 CsrWifiSmeStaConfig staConfig
;
763 CsrWifiSmeDeviceConfig deviceConfig
;
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");
771 unifi_trace(priv
, UDBG4
, "enable_okc: = %s\n", ((enable_okc
) ? "yes":"no"));
773 rc
= sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
);
775 unifi_warning(priv
, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
779 staConfig
.enableOpportunisticKeyCaching
= enable_okc
;
781 rc
= sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
);
783 unifi_warning(priv
, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
791 int unifi_cfg_get_info(unifi_priv_t
*priv
, unsigned char *arg
)
793 unifi_cfg_get_t get_cmd
;
794 char inst_name
[IFNAMSIZ
];
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");
803 case UNIFI_CFG_GET_COEX
:
805 CsrWifiSmeCoexInfo coexInfo
;
806 /* Get the coex info from the SME */
807 rc
= sme_mgt_coex_info_get(priv
, &coexInfo
);
809 unifi_error(priv
, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n");
813 /* Copy the info to the out buffer */
814 if (copy_to_user((void*)arg
,
816 sizeof(CsrWifiSmeCoexInfo
))) {
817 unifi_error(priv
, "UNIFI_CFG: Failed to copy the coex info\n");
822 case UNIFI_CFG_GET_POWER_MODE
:
824 CsrWifiSmePowerConfig powerConfig
;
825 rc
= sme_mgt_power_config_get(priv
, &powerConfig
);
827 unifi_error(priv
, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
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");
840 case UNIFI_CFG_GET_POWER_SUPPLY
:
842 CsrWifiSmeHostConfig hostConfig
;
843 rc
= sme_mgt_host_config_get(priv
, &hostConfig
);
845 unifi_error(priv
, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
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");
858 case UNIFI_CFG_GET_VERSIONS
:
860 case UNIFI_CFG_GET_INSTANCE
:
863 uf_net_get_name(priv
->netdev
[InterfaceId
], &inst_name
[0], sizeof(inst_name
));
865 /* Copy the info to the out buffer */
866 if (copy_to_user((void*)arg
,
868 sizeof(inst_name
))) {
869 unifi_error(priv
, "UNIFI_CFG: Failed to copy the instance name\n");
875 case UNIFI_CFG_GET_AP_CONFIG
:
877 #ifdef CSR_SUPPORT_WEXT_AP
878 uf_cfg_ap_config_t cfg_ap_config
;
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
,
888 sizeof(uf_cfg_ap_config_t
))) {
889 unifi_error(priv
, "UNIFI_CFG: Failed to copy the AP configuration\n");
900 unifi_error(priv
, "unifi_cfg_get_info: Unknown value.\n");
906 #ifdef CSR_SUPPORT_WEXT_AP
908 uf_configure_supported_rates(u8
* supportedRates
, u8 phySupportedBitmap
)
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
;
916 supportedRates
[i
++]=0x82;
917 supportedRates
[i
++]=0x84;
918 supportedRates
[i
++]=0x8b;
919 supportedRates
[i
++]=0x96;
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;
937 supportedRates
[i
++]=0x8c;
938 supportedRates
[i
++]=0x98;
939 supportedRates
[i
++]=0xb0;
941 supportedRates
[i
++]=0x0c;
942 supportedRates
[i
++]=0x18;
943 supportedRates
[i
++]=0x30;
945 supportedRates
[i
++]=0x48;
946 supportedRates
[i
++]=0x12;
947 supportedRates
[i
++]=0x24;
948 supportedRates
[i
++]=0x60;
949 supportedRates
[i
++]=0x6c;
953 int unifi_cfg_set_ap_config(unifi_priv_t
* priv
, unsigned char* arg
)
955 uf_cfg_ap_config_t cfg_ap_config
;
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");
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
;
973 priv
->ap_mac_config
.shortSlotTimeEnabled
= cfg_ap_config
.shortSlotTimeEnabled
;
974 priv
->ap_mac_config
.ctsProtectionType
=cfg_ap_config
.ctsProtectionType
;
976 priv
->ap_mac_config
.wmmEnabled
= cfg_ap_config
.wmmEnabled
;
978 priv
->ap_mac_config
.apHtParams
.rxStbc
=cfg_ap_config
.rxStbc
;
979 priv
->ap_mac_config
.apHtParams
.rifsModeAllowed
=cfg_ap_config
.rifsModeAllowed
;
981 priv
->ap_mac_config
.phySupportedBitmap
= cfg_ap_config
.phySupportedBitmap
;
982 priv
->ap_mac_config
.maxListenInterval
=cfg_ap_config
.maxListenInterval
;
984 priv
->ap_mac_config
.supportedRatesCount
= uf_configure_supported_rates(priv
->ap_mac_config
.supportedRates
, priv
->ap_mac_config
.phySupportedBitmap
);
990 #ifdef CSR_SUPPORT_WEXT
993 uf_sme_config_wq(struct work_struct
*work
)
995 CsrWifiSmeStaConfig staConfig
;
996 CsrWifiSmeDeviceConfig deviceConfig
;
997 unifi_priv_t
*priv
= container_of(work
, unifi_priv_t
, sme_config_task
);
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
);
1004 if (sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
)) {
1005 unifi_warning(priv
, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1009 if (priv
->if_index
== CSR_INDEX_5G
) {
1010 staConfig
.ifIndex
= CSR_WIFI_SME_RADIO_IF_GHZ_5_0
;
1012 staConfig
.ifIndex
= CSR_WIFI_SME_RADIO_IF_GHZ_2_4
;
1015 deviceConfig
.trustLevel
= (CsrWifiSme80211dTrustLevel
)tl_80211d
;
1016 if (sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
)) {
1018 "SME config for 802.11d Trust Level and Radio Band failed.\n");
1022 } /* uf_sme_config_wq() */
1024 #endif /* CSR_SUPPORT_WEXT */
1028 * ---------------------------------------------------------------------------
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
1037 * The TA classifications already come from a workqueue.
1040 * work Pointer to work queue item.
1044 * ---------------------------------------------------------------------------
1047 uf_ta_ind_wq(struct work_struct
*work
)
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;
1054 CsrWifiRouterCtrlTrafficProtocolIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
1061 } /* uf_ta_ind_wq() */
1065 * ---------------------------------------------------------------------------
1066 * uf_ta_sample_ind_wq
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
1074 * The TA classifications already come from a workqueue.
1077 * work Pointer to work queue item.
1081 * ---------------------------------------------------------------------------
1084 uf_ta_sample_ind_wq(struct work_struct
*work
)
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;
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
);
1097 if(priv
->rxTcpThroughput
> 1000)
1099 if (bh_priority
== -1 && priv
->bh_thread
.prio
!= 1)
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
, ¶m
);
1110 if (bh_priority
== -1 && priv
->bh_thread
.prio
!= DEFAULT_PRIO
)
1112 struct sched_param param
;
1113 param
.sched_priority
= 0;
1114 sched_setscheduler(priv
->bh_thread
.thread_task
, SCHED_NORMAL
, ¶m
);
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
));
1122 CsrWifiRouterCtrlTrafficSampleIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, interfaceTag
, ind
->stats
);
1126 } /* uf_ta_sample_ind_wq() */
1130 * ---------------------------------------------------------------------------
1131 * uf_send_m4_ready_wq
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
1139 * work Pointer to work queue item.
1143 * ---------------------------------------------------------------------------
1146 uf_send_m4_ready_wq(struct work_struct
*work
)
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
;
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
);
1160 /* Send a signal to SME */
1161 CsrWifiRouterCtrlM4ReadyToSendIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, iface
, peer
);
1163 unifi_trace(priv
, UDBG1
, "M4ReadyToSendInd sent for peer %pMF\n",
1166 } /* uf_send_m4_ready_wq() */
1168 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1170 * ---------------------------------------------------------------------------
1171 * uf_send_pkt_to_encrypt
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
1179 * work Pointer to work queue item.
1183 * ---------------------------------------------------------------------------
1185 void uf_send_pkt_to_encrypt(struct work_struct
*work
)
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
;
1191 u32 pktBulkDataLength
;
1193 unsigned long flags
;
1195 if (interfacePriv
->interfaceMode
== CSR_WIFI_ROUTER_CTRL_MODE_STA
) {
1197 pktBulkDataLength
= interfacePriv
->wapi_unicast_bulk_data
.data_length
;
1199 if (pktBulkDataLength
> 0) {
1200 pktBulkData
= kmalloc(pktBulkDataLength
, GFP_KERNEL
);
1202 unifi_error(priv
, "uf_send_pkt_to_encrypt() : invalid buffer\n");
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
);
1216 CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, interfaceTag
, pktBulkDataLength
, pktBulkData
);
1217 unifi_trace(priv
, UDBG1
, "WapiUnicastTxEncryptInd sent to SME\n");
1219 kfree(pktBulkData
); /* Would have been copied over by the SME Handler */
1222 unifi_warning(priv
, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n", interfacePriv
->interfaceMode
);
1224 }/* uf_send_pkt_to_encrypt() */