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"
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
;
82 /* Just a sanity check */
83 if ((signal
== NULL
) || (signal_len
<= 0)) {
88 priv
= uf_find_instance(pcli
->instance
);
90 unifi_error(priv
, "sme_log_event: invalid priv\n");
95 if (priv
->smepriv
== NULL
) {
96 unifi_error(priv
, "sme_log_event: invalid smepriv\n");
101 unifi_trace(priv
, UDBG3
,
102 "sme_log_event: Process signal 0x%.4X\n",
103 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal
));
106 /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */
107 r
= read_unpack_signal(signal
, &unpacked_signal
);
108 if (r
== CSR_RESULT_SUCCESS
) {
109 if ((unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_DEBUG_STRING_INDICATION_ID
) ||
110 (unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_DEBUG_WORD16_INDICATION_ID
))
115 if (unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_MA_PACKET_INDICATION_ID
)
118 u8 unicastPdu
= TRUE
;
120 u8
*raddr
= NULL
, *taddr
= NULL
;
121 CsrWifiMacAddress peerMacAddress
;
122 /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
123 CSR_MA_PACKET_INDICATION
*ind
= &unpacked_signal
.u
.MaPacketIndication
;
125 macHdrLocation
= (u8
*) bulkdata
->d
[0].os_data_ptr
;
126 /* Fetch the frame control value from mac header */
127 frmCtrl
= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation
);
129 /* Point to the addresses */
130 raddr
= macHdrLocation
+ MAC_HEADER_ADDR1_OFFSET
;
131 taddr
= macHdrLocation
+ MAC_HEADER_ADDR2_OFFSET
;
133 memcpy(peerMacAddress
.a
, taddr
, ETH_ALEN
);
135 if(ind
->ReceptionStatus
== CSR_MICHAEL_MIC_ERROR
)
140 CsrWifiRouterCtrlMicFailureIndSend (priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
141 (ind
->VirtualInterfaceIdentifier
& 0xff),peerMacAddress
,
147 if(ind
->ReceptionStatus
== CSR_RX_SUCCESS
)
149 u8 pmBit
= (frmCtrl
& 0x1000)?0x01:0x00;
150 u16 interfaceTag
= (ind
->VirtualInterfaceIdentifier
& 0xff);
151 CsrWifiRouterCtrlStaInfo_t
*srcStaInfo
= CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv
,taddr
,interfaceTag
);
152 if((srcStaInfo
!= NULL
) && (uf_check_broadcast_bssid(priv
, bulkdata
)== FALSE
))
154 uf_process_pm_bit_for_peer(priv
,srcStaInfo
,pmBit
,interfaceTag
);
156 /* Update station last activity flag */
157 srcStaInfo
->activity_flag
= TRUE
;
163 if (unpacked_signal
.SignalPrimitiveHeader
.SignalId
== CSR_MA_PACKET_CONFIRM_ID
)
165 CSR_MA_PACKET_CONFIRM
*cfm
= &unpacked_signal
.u
.MaPacketConfirm
;
166 u16 interfaceTag
= (cfm
->VirtualInterfaceIdentifier
& 0xff);
167 netInterface_priv_t
*interfacePriv
;
168 CSR_MA_PACKET_REQUEST
*req
;
169 CsrWifiMacAddress peerMacAddress
;
171 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
)
173 unifi_error(priv
, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag
);
178 unifi_trace(priv
,UDBG1
,"MA-PACKET Confirm (%x, %x)\n", cfm
->HostTag
, cfm
->TransmissionStatus
);
180 interfacePriv
= priv
->interfacePriv
[interfaceTag
];
181 #ifdef CSR_SUPPORT_SME
182 if(interfacePriv
->interfaceMode
== CSR_WIFI_ROUTER_CTRL_MODE_AP
||
183 interfacePriv
->interfaceMode
== CSR_WIFI_ROUTER_CTRL_MODE_P2PGO
) {
185 if(cfm
->HostTag
== interfacePriv
->multicastPduHostTag
){
186 uf_process_ma_pkt_cfm_for_ap(priv
,interfaceTag
, cfm
);
191 req
= &interfacePriv
->m4_signal
.u
.MaPacketRequest
;
193 if(cfm
->HostTag
& 0x80000000)
195 if (cfm
->TransmissionStatus
!= CSR_TX_SUCCESSFUL
)
197 result
= CSR_RESULT_FAILURE
;
199 #ifdef CSR_SUPPORT_SME
200 memcpy(peerMacAddress
.a
, req
->Ra
.x
, ETH_ALEN
);
201 /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/
202 if (interfacePriv
->m4_sent
&& (cfm
->HostTag
== interfacePriv
->m4_hostTag
))
204 unifi_trace(priv
, UDBG1
, "%s: Sending M4 Transmit CFM\n", __FUNCTION__
);
205 CsrWifiRouterCtrlM4TransmittedIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0,
209 interfacePriv
->m4_sent
= FALSE
;
210 interfacePriv
->m4_hostTag
= 0xffffffff;
213 /* If EAPOL was requested via router APIs then send cfm else ignore*/
214 if((cfm
->HostTag
& 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG
) {
215 CsrWifiRouterMaPacketCfmSend((u16
)signal
[2],
216 cfm
->VirtualInterfaceIdentifier
,
218 (cfm
->HostTag
& 0x3fffffff), cfm
->Rate
);
220 unifi_trace(priv
, UDBG1
, "%s: M4 received from netdevice\n", __FUNCTION__
);
228 mlmeCommand
.length
= signal_len
;
229 mlmeCommand
.data
= (u8
*)signal
;
231 dataref1
.length
= bulkdata
->d
[0].data_length
;
232 if (dataref1
.length
> 0) {
233 dataref1
.data
= (u8
*) bulkdata
->d
[0].os_data_ptr
;
236 dataref1
.data
= NULL
;
239 dataref2
.length
= bulkdata
->d
[1].data_length
;
240 if (dataref2
.length
> 0) {
241 dataref2
.data
= (u8
*) bulkdata
->d
[1].os_data_ptr
;
244 dataref2
.data
= NULL
;
247 CsrWifiRouterCtrlHipIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, mlmeCommand
.length
, mlmeCommand
.data
,
248 dataref1
.length
, dataref1
.data
,
249 dataref2
.length
, dataref2
.data
);
252 } /* sme_log_event() */
256 * ---------------------------------------------------------------------------
259 * Return the state of the controlled port.
262 * priv Pointer to device private context struct
263 * address Pointer to the destination for tx or sender for rx address
264 * queue Controlled or uncontrolled queue
267 * An unifi_ControlledPortAction value.
268 * ---------------------------------------------------------------------------
270 CsrWifiRouterCtrlPortAction
271 uf_sme_port_state(unifi_priv_t
*priv
, unsigned char *address
, int queue
, u16 interfaceTag
)
274 unifi_port_config_t
*port
;
275 netInterface_priv_t
*interfacePriv
;
277 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
) {
278 unifi_error(priv
, "uf_sme_port_state: bad interfaceTag\n");
279 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD
;
282 interfacePriv
= priv
->interfacePriv
[interfaceTag
];
284 if (queue
== UF_CONTROLLED_PORT_Q
) {
285 port
= &interfacePriv
->controlled_data_port
;
287 port
= &interfacePriv
->uncontrolled_data_port
;
290 if (!port
->entries_in_use
) {
291 unifi_trace(priv
, UDBG5
, "No port configurations, return Discard.\n");
292 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD
;
295 /* If the port configuration is common for all destinations, return it. */
296 if (port
->overide_action
== UF_DATA_PORT_OVERIDE
) {
297 unifi_trace(priv
, UDBG5
, "Single port configuration (%d).\n",
298 port
->port_cfg
[0].port_action
);
299 return port
->port_cfg
[0].port_action
;
302 unifi_trace(priv
, UDBG5
, "Multiple (%d) port configurations.\n", port
->entries_in_use
);
304 /* If multiple configurations exist.. */
305 for (i
= 0; i
< UNIFI_MAX_CONNECTIONS
; i
++) {
306 /* .. go through the list and match the destination address. */
307 if (port
->port_cfg
[i
].in_use
&&
308 memcmp(address
, port
->port_cfg
[i
].mac_address
.a
, ETH_ALEN
) == 0) {
309 /* Return the desired action. */
310 return port
->port_cfg
[i
].port_action
;
314 /* Could not find any information, return Open. */
315 unifi_trace(priv
, UDBG5
, "port configuration not found, return Open.\n");
316 return CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN
;
317 } /* uf_sme_port_state() */
320 * ---------------------------------------------------------------------------
321 * uf_sme_port_config_handle
323 * Return the port config handle of the controlled/uncontrolled port.
326 * priv Pointer to device private context struct
327 * address Pointer to the destination for tx or sender for rx address
328 * queue Controlled or uncontrolled queue
331 * An unifi_port_cfg_t* .
332 * ---------------------------------------------------------------------------
335 uf_sme_port_config_handle(unifi_priv_t
*priv
, unsigned char *address
, int queue
, u16 interfaceTag
)
338 unifi_port_config_t
*port
;
339 netInterface_priv_t
*interfacePriv
= priv
->interfacePriv
[interfaceTag
];
341 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
) {
342 unifi_error(priv
, "uf_sme_port_config_handle: bad interfaceTag\n");
346 if (queue
== UF_CONTROLLED_PORT_Q
) {
347 port
= &interfacePriv
->controlled_data_port
;
349 port
= &interfacePriv
->uncontrolled_data_port
;
352 if (!port
->entries_in_use
) {
353 unifi_trace(priv
, UDBG5
, "No port configurations, return Discard.\n");
357 /* If the port configuration is common for all destinations, return it. */
358 if (port
->overide_action
== UF_DATA_PORT_OVERIDE
) {
359 unifi_trace(priv
, UDBG5
, "Single port configuration (%d).\n",
360 port
->port_cfg
[0].port_action
);
362 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]);
364 return &port
->port_cfg
[0];
367 unifi_trace(priv
, UDBG5
, "Multiple port configurations.\n");
369 /* If multiple configurations exist.. */
370 for (i
= 0; i
< UNIFI_MAX_CONNECTIONS
; i
++) {
371 /* .. go through the list and match the destination address. */
372 if (port
->port_cfg
[i
].in_use
&&
373 memcmp(address
, port
->port_cfg
[i
].mac_address
.a
, ETH_ALEN
) == 0) {
374 /* Return the desired action. */
375 return &port
->port_cfg
[i
];
379 /* Could not find any information, return Open. */
380 unifi_trace(priv
, UDBG5
, "port configuration not found, returning NULL (debug).\n");
382 } /* uf_sme_port_config_handle */
385 uf_multicast_list_wq(struct work_struct
*work
)
387 unifi_priv_t
*priv
= container_of(work
, unifi_priv_t
,
388 multicast_list_task
);
390 u16 interfaceTag
= 0;
391 CsrWifiMacAddress
* multicast_address_list
= NULL
;
394 netInterface_priv_t
*interfacePriv
= priv
->interfacePriv
[interfaceTag
];
396 if (interfaceTag
>= CSR_WIFI_NUM_INTERFACES
) {
397 unifi_error(priv
, "uf_multicast_list_wq: bad interfaceTag\n");
401 unifi_trace(priv
, UDBG5
,
402 "uf_multicast_list_wq: list count = %d\n",
403 interfacePriv
->mc_list_count
);
405 /* Flush the current list */
406 CsrWifiRouterCtrlMulticastAddressIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
,0, interfaceTag
, CSR_WIFI_SME_LIST_ACTION_FLUSH
, 0, NULL
);
408 mc_count
= interfacePriv
->mc_list_count
;
409 mc_list
= interfacePriv
->mc_list
;
411 * Allocate a new list, need to free it later
412 * in unifi_mgt_multicast_address_cfm().
414 multicast_address_list
= kmalloc(mc_count
* sizeof(CsrWifiMacAddress
), GFP_KERNEL
);
416 if (multicast_address_list
== NULL
) {
420 for (i
= 0; i
< mc_count
; i
++) {
421 memcpy(multicast_address_list
[i
].a
, mc_list
, ETH_ALEN
);
425 if (priv
->smepriv
== NULL
) {
426 kfree(multicast_address_list
);
430 CsrWifiRouterCtrlMulticastAddressIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
,0,
432 CSR_WIFI_SME_LIST_ACTION_ADD
,
433 mc_count
, multicast_address_list
);
435 /* The SME will take a copy of the addreses*/
436 kfree(multicast_address_list
);
440 int unifi_cfg_power(unifi_priv_t
*priv
, unsigned char *arg
)
442 unifi_cfg_power_t cfg_power
;
446 if (get_user(cfg_power
, (unifi_cfg_power_t
*)(((unifi_cfg_command_t
*)arg
) + 1))) {
447 unifi_error(priv
, "UNIFI_CFG: Failed to get the argument\n");
452 case UNIFI_CFG_POWER_OFF
:
453 priv
->wol_suspend
= (enable_wol
== UNIFI_WOL_OFF
) ? FALSE
: TRUE
;
454 rc
= sme_sys_suspend(priv
);
459 case UNIFI_CFG_POWER_ON
:
460 wol
= priv
->wol_suspend
;
461 rc
= sme_sys_resume(priv
);
466 /* Kick the BH to ensure pending transfers are handled when
467 * a suspend happened with card powered.
469 unifi_send_signal(priv
->card
, NULL
, 0, NULL
);
473 unifi_error(priv
, "WIFI POWER: Unknown value.\n");
481 int unifi_cfg_power_save(unifi_priv_t
*priv
, unsigned char *arg
)
483 unifi_cfg_powersave_t cfg_power_save
;
484 CsrWifiSmePowerConfig powerConfig
;
487 if (get_user(cfg_power_save
, (unifi_cfg_powersave_t
*)(((unifi_cfg_command_t
*)arg
) + 1))) {
488 unifi_error(priv
, "UNIFI_CFG: Failed to get the argument\n");
492 /* Get the coex info from the SME */
493 rc
= sme_mgt_power_config_get(priv
, &powerConfig
);
495 unifi_error(priv
, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
499 switch (cfg_power_save
) {
500 case UNIFI_CFG_POWERSAVE_NONE
:
501 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_LOW
;
503 case UNIFI_CFG_POWERSAVE_FAST
:
504 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_MED
;
506 case UNIFI_CFG_POWERSAVE_FULL
:
507 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_HIGH
;
509 case UNIFI_CFG_POWERSAVE_AUTO
:
510 powerConfig
.powerSaveLevel
= CSR_WIFI_SME_POWER_SAVE_LEVEL_AUTO
;
513 unifi_error(priv
, "POWERSAVE: Unknown value.\n");
517 rc
= sme_mgt_power_config_set(priv
, &powerConfig
);
520 unifi_error(priv
, "UNIFI_CFG: Set unifi_PowerConfigValue failed.\n");
527 int unifi_cfg_power_supply(unifi_priv_t
*priv
, unsigned char *arg
)
529 unifi_cfg_powersupply_t cfg_power_supply
;
530 CsrWifiSmeHostConfig hostConfig
;
533 if (get_user(cfg_power_supply
, (unifi_cfg_powersupply_t
*)(((unifi_cfg_command_t
*)arg
) + 1))) {
534 unifi_error(priv
, "UNIFI_CFG: Failed to get the argument\n");
538 /* Get the coex info from the SME */
539 rc
= sme_mgt_host_config_get(priv
, &hostConfig
);
541 unifi_error(priv
, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
545 switch (cfg_power_supply
) {
546 case UNIFI_CFG_POWERSUPPLY_MAINS
:
547 hostConfig
.powerMode
= CSR_WIFI_SME_HOST_POWER_MODE_ACTIVE
;
549 case UNIFI_CFG_POWERSUPPLY_BATTERIES
:
550 hostConfig
.powerMode
= CSR_WIFI_SME_HOST_POWER_MODE_POWER_SAVE
;
553 unifi_error(priv
, "POWERSUPPLY: Unknown value.\n");
557 rc
= sme_mgt_host_config_set(priv
, &hostConfig
);
559 unifi_error(priv
, "UNIFI_CFG: Set unifi_HostConfigValue failed.\n");
566 int unifi_cfg_packet_filters(unifi_priv_t
*priv
, unsigned char *arg
)
568 unsigned char *tclas_buffer
;
569 unsigned int tclas_buffer_length
;
573 /* Free any TCLASs previously allocated */
574 if (priv
->packet_filters
.tclas_ies_length
) {
575 kfree(priv
->filter_tclas_ies
);
576 priv
->filter_tclas_ies
= NULL
;
579 tclas_buffer
= ((unsigned char*)arg
) + sizeof(unifi_cfg_command_t
) + sizeof(unsigned int);
580 if (copy_from_user(&priv
->packet_filters
, (void*)tclas_buffer
,
581 sizeof(uf_cfg_bcast_packet_filter_t
))) {
582 unifi_error(priv
, "UNIFI_CFG: Failed to get the filter struct\n");
586 tclas_buffer_length
= priv
->packet_filters
.tclas_ies_length
;
588 /* Allocate TCLASs if necessary */
589 if (priv
->packet_filters
.dhcp_filter
) {
590 priv
->packet_filters
.tclas_ies_length
+= sizeof(tclas_t
);
592 if (priv
->packet_filters
.tclas_ies_length
> 0) {
593 priv
->filter_tclas_ies
= kmalloc(priv
->packet_filters
.tclas_ies_length
, GFP_KERNEL
);
594 if (priv
->filter_tclas_ies
== NULL
) {
597 if (tclas_buffer_length
) {
598 tclas_buffer
+= sizeof(uf_cfg_bcast_packet_filter_t
) - sizeof(unsigned char*);
599 if (copy_from_user(priv
->filter_tclas_ies
,
601 tclas_buffer_length
)) {
602 unifi_error(priv
, "UNIFI_CFG: Failed to get the TCLAS buffer\n");
608 if(priv
->packet_filters
.dhcp_filter
)
610 /* Append the DHCP tclas IE */
611 dhcp_tclas
= (tclas_t
*)(priv
->filter_tclas_ies
+ tclas_buffer_length
);
612 memset(dhcp_tclas
, 0, sizeof(tclas_t
));
613 dhcp_tclas
->element_id
= 14;
614 dhcp_tclas
->length
= sizeof(tcpip_clsfr_t
) + 1;
615 dhcp_tclas
->user_priority
= 0;
616 dhcp_tclas
->tcp_ip_cls_fr
.cls_fr_type
= 1;
617 dhcp_tclas
->tcp_ip_cls_fr
.version
= 4;
618 ((u8
*)(&dhcp_tclas
->tcp_ip_cls_fr
.source_port
))[0] = 0x00;
619 ((u8
*)(&dhcp_tclas
->tcp_ip_cls_fr
.source_port
))[1] = 0x44;
620 ((u8
*)(&dhcp_tclas
->tcp_ip_cls_fr
.dest_port
))[0] = 0x00;
621 ((u8
*)(&dhcp_tclas
->tcp_ip_cls_fr
.dest_port
))[1] = 0x43;
622 dhcp_tclas
->tcp_ip_cls_fr
.protocol
= 0x11;
623 dhcp_tclas
->tcp_ip_cls_fr
.cls_fr_mask
= 0x58; //bits: 3,4,6
626 rc
= sme_mgt_packet_filter_set(priv
);
632 int unifi_cfg_wmm_qos_info(unifi_priv_t
*priv
, unsigned char *arg
)
637 if (get_user(wmm_qos_info
, (u8
*)(((unifi_cfg_command_t
*)arg
) + 1))) {
638 unifi_error(priv
, "UNIFI_CFG: Failed to get the argument\n");
642 /* Store the value in the connection info */
643 priv
->connection_config
.wmmQosInfo
= wmm_qos_info
;
649 int unifi_cfg_wmm_addts(unifi_priv_t
*priv
, unsigned char *arg
)
655 CsrWifiSmeDataBlock tspec
;
656 CsrWifiSmeDataBlock tclas
;
659 addts_params
= (u8
*)(((unifi_cfg_command_t
*)arg
) + 1);
660 if (get_user(addts_tid
, (u32
*)addts_params
)) {
661 unifi_error(priv
, "unifi_cfg_wmm_addts: Failed to get the argument\n");
665 addts_params
+= sizeof(u32
);
666 if (get_user(addts_ie_length
, (u8
*)addts_params
)) {
667 unifi_error(priv
, "unifi_cfg_wmm_addts: Failed to get the argument\n");
671 unifi_trace(priv
, UDBG4
, "addts: tid = 0x%x ie_length = %d\n",
672 addts_tid
, addts_ie_length
);
674 addts_ie
= kmalloc(addts_ie_length
, GFP_KERNEL
);
675 if (addts_ie
== NULL
) {
677 "unifi_cfg_wmm_addts: Failed to malloc %d bytes for addts_ie buffer\n",
682 addts_params
+= sizeof(u8
);
683 rc
= copy_from_user(addts_ie
, addts_params
, addts_ie_length
);
685 unifi_error(priv
, "unifi_cfg_wmm_addts: Failed to get the addts buffer\n");
690 tspec
.data
= addts_ie
;
691 tspec
.length
= addts_ie_length
;
695 rc
= sme_mgt_tspec(priv
, CSR_WIFI_SME_LIST_ACTION_ADD
, addts_tid
,
703 int unifi_cfg_wmm_delts(unifi_priv_t
*priv
, unsigned char *arg
)
707 CsrWifiSmeDataBlock tspec
;
708 CsrWifiSmeDataBlock tclas
;
711 delts_params
= (u8
*)(((unifi_cfg_command_t
*)arg
) + 1);
712 if (get_user(delts_tid
, (u32
*)delts_params
)) {
713 unifi_error(priv
, "unifi_cfg_wmm_delts: Failed to get the argument\n");
717 unifi_trace(priv
, UDBG4
, "delts: tid = 0x%x\n", delts_tid
);
719 tspec
.data
= tclas
.data
= NULL
;
720 tspec
.length
= tclas
.length
= 0;
722 rc
= sme_mgt_tspec(priv
, CSR_WIFI_SME_LIST_ACTION_REMOVE
, delts_tid
,
728 int unifi_cfg_strict_draft_n(unifi_priv_t
*priv
, unsigned char *arg
)
731 u8
*strict_draft_n_params
;
734 CsrWifiSmeStaConfig staConfig
;
735 CsrWifiSmeDeviceConfig deviceConfig
;
737 strict_draft_n_params
= (u8
*)(((unifi_cfg_command_t
*)arg
) + 1);
738 if (get_user(strict_draft_n
, (u8
*)strict_draft_n_params
)) {
739 unifi_error(priv
, "unifi_cfg_strict_draft_n: Failed to get the argument\n");
743 unifi_trace(priv
, UDBG4
, "strict_draft_n: = %s\n", ((strict_draft_n
) ? "yes":"no"));
745 rc
= sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
);
748 unifi_warning(priv
, "unifi_cfg_strict_draft_n: Get unifi_SMEConfigValue failed.\n");
752 deviceConfig
.enableStrictDraftN
= strict_draft_n
;
754 rc
= sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
);
756 unifi_warning(priv
, "unifi_cfg_strict_draft_n: Set unifi_SMEConfigValue failed.\n");
764 int unifi_cfg_enable_okc(unifi_priv_t
*priv
, unsigned char *arg
)
767 u8
*enable_okc_params
;
770 CsrWifiSmeStaConfig staConfig
;
771 CsrWifiSmeDeviceConfig deviceConfig
;
773 enable_okc_params
= (u8
*)(((unifi_cfg_command_t
*)arg
) + 1);
774 if (get_user(enable_okc
, (u8
*)enable_okc_params
)) {
775 unifi_error(priv
, "unifi_cfg_enable_okc: Failed to get the argument\n");
779 unifi_trace(priv
, UDBG4
, "enable_okc: = %s\n", ((enable_okc
) ? "yes":"no"));
781 rc
= sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
);
783 unifi_warning(priv
, "unifi_cfg_enable_okc: Get unifi_SMEConfigValue failed.\n");
787 staConfig
.enableOpportunisticKeyCaching
= enable_okc
;
789 rc
= sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
);
791 unifi_warning(priv
, "unifi_cfg_enable_okc: Set unifi_SMEConfigValue failed.\n");
799 int unifi_cfg_get_info(unifi_priv_t
*priv
, unsigned char *arg
)
801 unifi_cfg_get_t get_cmd
;
802 char inst_name
[IFNAMSIZ
];
805 if (get_user(get_cmd
, (unifi_cfg_get_t
*)(((unifi_cfg_command_t
*)arg
) + 1))) {
806 unifi_error(priv
, "UNIFI_CFG: Failed to get the argument\n");
811 case UNIFI_CFG_GET_COEX
:
813 CsrWifiSmeCoexInfo coexInfo
;
814 /* Get the coex info from the SME */
815 rc
= sme_mgt_coex_info_get(priv
, &coexInfo
);
817 unifi_error(priv
, "UNIFI_CFG: Get unifi_CoexInfoValue failed.\n");
821 /* Copy the info to the out buffer */
822 if (copy_to_user((void*)arg
,
824 sizeof(CsrWifiSmeCoexInfo
))) {
825 unifi_error(priv
, "UNIFI_CFG: Failed to copy the coex info\n");
830 case UNIFI_CFG_GET_POWER_MODE
:
832 CsrWifiSmePowerConfig powerConfig
;
833 rc
= sme_mgt_power_config_get(priv
, &powerConfig
);
835 unifi_error(priv
, "UNIFI_CFG: Get unifi_PowerConfigValue failed.\n");
839 /* Copy the info to the out buffer */
840 if (copy_to_user((void*)arg
,
841 &powerConfig
.powerSaveLevel
,
842 sizeof(CsrWifiSmePowerSaveLevel
))) {
843 unifi_error(priv
, "UNIFI_CFG: Failed to copy the power save info\n");
848 case UNIFI_CFG_GET_POWER_SUPPLY
:
850 CsrWifiSmeHostConfig hostConfig
;
851 rc
= sme_mgt_host_config_get(priv
, &hostConfig
);
853 unifi_error(priv
, "UNIFI_CFG: Get unifi_HostConfigValue failed.\n");
857 /* Copy the info to the out buffer */
858 if (copy_to_user((void*)arg
,
859 &hostConfig
.powerMode
,
860 sizeof(CsrWifiSmeHostPowerMode
))) {
861 unifi_error(priv
, "UNIFI_CFG: Failed to copy the host power mode\n");
866 case UNIFI_CFG_GET_VERSIONS
:
868 case UNIFI_CFG_GET_INSTANCE
:
871 uf_net_get_name(priv
->netdev
[InterfaceId
], &inst_name
[0], sizeof(inst_name
));
873 /* Copy the info to the out buffer */
874 if (copy_to_user((void*)arg
,
876 sizeof(inst_name
))) {
877 unifi_error(priv
, "UNIFI_CFG: Failed to copy the instance name\n");
883 case UNIFI_CFG_GET_AP_CONFIG
:
885 #ifdef CSR_SUPPORT_WEXT_AP
886 uf_cfg_ap_config_t cfg_ap_config
;
887 cfg_ap_config
.channel
= priv
->ap_config
.channel
;
888 cfg_ap_config
.beaconInterval
= priv
->ap_mac_config
.beaconInterval
;
889 cfg_ap_config
.wmmEnabled
= priv
->ap_mac_config
.wmmEnabled
;
890 cfg_ap_config
.dtimPeriod
= priv
->ap_mac_config
.dtimPeriod
;
891 cfg_ap_config
.phySupportedBitmap
= priv
->ap_mac_config
.phySupportedBitmap
;
892 if (copy_to_user((void*)arg
,
894 sizeof(uf_cfg_ap_config_t
))) {
895 unifi_error(priv
, "UNIFI_CFG: Failed to copy the AP configuration\n");
906 unifi_error(priv
, "unifi_cfg_get_info: Unknown value.\n");
912 #ifdef CSR_SUPPORT_WEXT_AP
914 uf_configure_supported_rates(u8
* supportedRates
, u8 phySupportedBitmap
)
917 u8 b
=FALSE
, g
= FALSE
, n
= FALSE
;
918 b
= phySupportedBitmap
& CSR_WIFI_SME_AP_PHY_SUPPORT_B
;
919 n
= phySupportedBitmap
& CSR_WIFI_SME_AP_PHY_SUPPORT_N
;
920 g
= phySupportedBitmap
& CSR_WIFI_SME_AP_PHY_SUPPORT_G
;
922 supportedRates
[i
++]=0x82;
923 supportedRates
[i
++]=0x84;
924 supportedRates
[i
++]=0x8b;
925 supportedRates
[i
++]=0x96;
927 /* For some strange reasons WiFi stack needs both b and g rates*/
928 supportedRates
[i
++]=0x02;
929 supportedRates
[i
++]=0x04;
930 supportedRates
[i
++]=0x0b;
931 supportedRates
[i
++]=0x16;
932 supportedRates
[i
++]=0x0c;
933 supportedRates
[i
++]=0x12;
934 supportedRates
[i
++]=0x18;
935 supportedRates
[i
++]=0x24;
936 supportedRates
[i
++]=0x30;
937 supportedRates
[i
++]=0x48;
938 supportedRates
[i
++]=0x60;
939 supportedRates
[i
++]=0x6c;
943 supportedRates
[i
++]=0x8c;
944 supportedRates
[i
++]=0x98;
945 supportedRates
[i
++]=0xb0;
947 supportedRates
[i
++]=0x0c;
948 supportedRates
[i
++]=0x18;
949 supportedRates
[i
++]=0x30;
951 supportedRates
[i
++]=0x48;
952 supportedRates
[i
++]=0x12;
953 supportedRates
[i
++]=0x24;
954 supportedRates
[i
++]=0x60;
955 supportedRates
[i
++]=0x6c;
959 int unifi_cfg_set_ap_config(unifi_priv_t
* priv
,unsigned char* arg
)
961 uf_cfg_ap_config_t cfg_ap_config
;
964 buffer
= ((unsigned char*)arg
) + sizeof(unifi_cfg_command_t
) + sizeof(unsigned int);
965 if (copy_from_user(&cfg_ap_config
, (void*)buffer
,
966 sizeof(uf_cfg_ap_config_t
))) {
967 unifi_error(priv
, "UNIFI_CFG: Failed to get the ap config struct\n");
970 priv
->ap_config
.channel
= cfg_ap_config
.channel
;
971 priv
->ap_mac_config
.dtimPeriod
= cfg_ap_config
.dtimPeriod
;
972 priv
->ap_mac_config
.beaconInterval
= cfg_ap_config
.beaconInterval
;
973 priv
->group_sec_config
.apGroupkeyTimeout
= cfg_ap_config
.groupkeyTimeout
;
974 priv
->group_sec_config
.apStrictGtkRekey
= cfg_ap_config
.strictGtkRekeyEnabled
;
975 priv
->group_sec_config
.apGmkTimeout
= cfg_ap_config
.gmkTimeout
;
976 priv
->group_sec_config
.apResponseTimeout
= cfg_ap_config
.responseTimeout
;
977 priv
->group_sec_config
.apRetransLimit
= cfg_ap_config
.retransLimit
;
979 priv
->ap_mac_config
.shortSlotTimeEnabled
= cfg_ap_config
.shortSlotTimeEnabled
;
980 priv
->ap_mac_config
.ctsProtectionType
=cfg_ap_config
.ctsProtectionType
;
982 priv
->ap_mac_config
.wmmEnabled
= cfg_ap_config
.wmmEnabled
;
984 priv
->ap_mac_config
.apHtParams
.rxStbc
=cfg_ap_config
.rxStbc
;
985 priv
->ap_mac_config
.apHtParams
.rifsModeAllowed
=cfg_ap_config
.rifsModeAllowed
;
987 priv
->ap_mac_config
.phySupportedBitmap
= cfg_ap_config
.phySupportedBitmap
;
988 priv
->ap_mac_config
.maxListenInterval
=cfg_ap_config
.maxListenInterval
;
990 priv
->ap_mac_config
.supportedRatesCount
= uf_configure_supported_rates(priv
->ap_mac_config
.supportedRates
,priv
->ap_mac_config
.phySupportedBitmap
);
996 #ifdef CSR_SUPPORT_WEXT
999 uf_sme_config_wq(struct work_struct
*work
)
1001 CsrWifiSmeStaConfig staConfig
;
1002 CsrWifiSmeDeviceConfig deviceConfig
;
1003 unifi_priv_t
*priv
= container_of(work
, unifi_priv_t
, sme_config_task
);
1005 /* Register to receive indications from the SME */
1006 CsrWifiSmeEventMaskSetReqSend(0,
1007 CSR_WIFI_SME_INDICATIONS_WIFIOFF
| CSR_WIFI_SME_INDICATIONS_CONNECTIONQUALITY
|
1008 CSR_WIFI_SME_INDICATIONS_MEDIASTATUS
| CSR_WIFI_SME_INDICATIONS_MICFAILURE
);
1010 if (sme_mgt_sme_config_get(priv
, &staConfig
, &deviceConfig
)) {
1011 unifi_warning(priv
, "uf_sme_config_wq: Get unifi_SMEConfigValue failed.\n");
1015 if (priv
->if_index
== CSR_INDEX_5G
) {
1016 staConfig
.ifIndex
= CSR_WIFI_SME_RADIO_IF_GHZ_5_0
;
1018 staConfig
.ifIndex
= CSR_WIFI_SME_RADIO_IF_GHZ_2_4
;
1021 deviceConfig
.trustLevel
= (CsrWifiSme80211dTrustLevel
)tl_80211d
;
1022 if (sme_mgt_sme_config_set(priv
, &staConfig
, &deviceConfig
)) {
1024 "SME config for 802.11d Trust Level and Radio Band failed.\n");
1028 } /* uf_sme_config_wq() */
1030 #endif /* CSR_SUPPORT_WEXT */
1034 * ---------------------------------------------------------------------------
1037 * Deferred work queue function to send Traffic Analysis protocols
1038 * indications to the SME.
1039 * These are done in a deferred work queue for two reasons:
1040 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1041 * - we want to load the main driver data path as lightly as possible
1043 * The TA classifications already come from a workqueue.
1046 * work Pointer to work queue item.
1050 * ---------------------------------------------------------------------------
1053 uf_ta_ind_wq(struct work_struct
*work
)
1055 struct ta_ind
*ind
= container_of(work
, struct ta_ind
, task
);
1056 unifi_priv_t
*priv
= container_of(ind
, unifi_priv_t
, ta_ind_work
);
1057 u16 interfaceTag
= 0;
1060 CsrWifiRouterCtrlTrafficProtocolIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
,0,
1067 } /* uf_ta_ind_wq() */
1071 * ---------------------------------------------------------------------------
1072 * uf_ta_sample_ind_wq
1074 * Deferred work queue function to send Traffic Analysis sample
1075 * indications to the SME.
1076 * These are done in a deferred work queue for two reasons:
1077 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1078 * - we want to load the main driver data path as lightly as possible
1080 * The TA classifications already come from a workqueue.
1083 * work Pointer to work queue item.
1087 * ---------------------------------------------------------------------------
1090 uf_ta_sample_ind_wq(struct work_struct
*work
)
1092 struct ta_sample_ind
*ind
= container_of(work
, struct ta_sample_ind
, task
);
1093 unifi_priv_t
*priv
= container_of(ind
, unifi_priv_t
, ta_sample_ind_work
);
1094 u16 interfaceTag
= 0;
1096 unifi_trace(priv
, UDBG5
, "rxtcp %d txtcp %d rxudp %d txudp %d prio %d\n",
1097 priv
->rxTcpThroughput
,
1098 priv
->txTcpThroughput
,
1099 priv
->rxUdpThroughput
,
1100 priv
->txUdpThroughput
,
1101 priv
->bh_thread
.prio
);
1103 if(priv
->rxTcpThroughput
> 1000)
1105 if (bh_priority
== -1 && priv
->bh_thread
.prio
!= 1)
1107 struct sched_param param
;
1108 priv
->bh_thread
.prio
= 1;
1109 unifi_trace(priv
, UDBG1
, "%s new thread (RT) priority = %d\n",
1110 priv
->bh_thread
.name
, priv
->bh_thread
.prio
);
1111 param
.sched_priority
= priv
->bh_thread
.prio
;
1112 sched_setscheduler(priv
->bh_thread
.thread_task
, SCHED_FIFO
, ¶m
);
1116 if (bh_priority
== -1 && priv
->bh_thread
.prio
!= DEFAULT_PRIO
)
1118 struct sched_param param
;
1119 param
.sched_priority
= 0;
1120 sched_setscheduler(priv
->bh_thread
.thread_task
, SCHED_NORMAL
, ¶m
);
1121 priv
->bh_thread
.prio
= DEFAULT_PRIO
;
1122 unifi_trace(priv
, UDBG1
, "%s new thread priority = %d\n",
1123 priv
->bh_thread
.name
, priv
->bh_thread
.prio
);
1124 set_user_nice(priv
->bh_thread
.thread_task
, PRIO_TO_NICE(priv
->bh_thread
.prio
));
1128 CsrWifiRouterCtrlTrafficSampleIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
,0, interfaceTag
, ind
->stats
);
1132 } /* uf_ta_sample_ind_wq() */
1136 * ---------------------------------------------------------------------------
1137 * uf_send_m4_ready_wq
1139 * Deferred work queue function to send M4 ReadyToSend inds to the SME.
1140 * These are done in a deferred work queue for two reasons:
1141 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1142 * - we want to load the main driver data path as lightly as possible
1145 * work Pointer to work queue item.
1149 * ---------------------------------------------------------------------------
1152 uf_send_m4_ready_wq(struct work_struct
*work
)
1154 netInterface_priv_t
*InterfacePriv
= container_of(work
, netInterface_priv_t
, send_m4_ready_task
);
1155 u16 iface
= InterfacePriv
->InterfaceTag
;
1156 unifi_priv_t
*priv
= InterfacePriv
->privPtr
;
1157 CSR_MA_PACKET_REQUEST
*req
= &InterfacePriv
->m4_signal
.u
.MaPacketRequest
;
1158 CsrWifiMacAddress peer
;
1159 unsigned long flags
;
1163 /* The peer address was stored in the signal */
1164 spin_lock_irqsave(&priv
->m4_lock
, flags
);
1165 memcpy(peer
.a
, req
->Ra
.x
, sizeof(peer
.a
));
1166 spin_unlock_irqrestore(&priv
->m4_lock
, flags
);
1168 /* Send a signal to SME */
1169 CsrWifiRouterCtrlM4ReadyToSendIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, iface
, peer
);
1171 unifi_trace(priv
, UDBG1
, "M4ReadyToSendInd sent for peer %pMF\n",
1176 } /* uf_send_m4_ready_wq() */
1178 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
1180 * ---------------------------------------------------------------------------
1181 * uf_send_pkt_to_encrypt
1183 * Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
1184 * These are done in a deferred work queue for two reasons:
1185 * - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
1186 * - we want to load the main driver data path as lightly as possible
1189 * work Pointer to work queue item.
1193 * ---------------------------------------------------------------------------
1195 void uf_send_pkt_to_encrypt(struct work_struct
*work
)
1197 netInterface_priv_t
*interfacePriv
= container_of(work
, netInterface_priv_t
, send_pkt_to_encrypt
);
1198 u16 interfaceTag
= interfacePriv
->InterfaceTag
;
1199 unifi_priv_t
*priv
= interfacePriv
->privPtr
;
1201 u32 pktBulkDataLength
;
1203 unsigned long flags
;
1205 if (interfacePriv
->interfaceMode
== CSR_WIFI_ROUTER_CTRL_MODE_STA
) {
1209 pktBulkDataLength
= interfacePriv
->wapi_unicast_bulk_data
.data_length
;
1211 if (pktBulkDataLength
> 0) {
1212 pktBulkData
= kmalloc(pktBulkDataLength
, GFP_KERNEL
);
1213 memset(pktBulkData
, 0, pktBulkDataLength
);
1215 unifi_error(priv
, "uf_send_pkt_to_encrypt() : invalid buffer\n");
1219 spin_lock_irqsave(&priv
->wapi_lock
, flags
);
1220 /* Copy over the MA PKT REQ bulk data */
1221 memcpy(pktBulkData
, (u8
*)interfacePriv
->wapi_unicast_bulk_data
.os_data_ptr
, pktBulkDataLength
);
1222 /* Free any bulk data buffers allocated for the WAPI Data pkt */
1223 unifi_net_data_free(priv
, &interfacePriv
->wapi_unicast_bulk_data
);
1224 interfacePriv
->wapi_unicast_bulk_data
.net_buf_length
= 0;
1225 interfacePriv
->wapi_unicast_bulk_data
.data_length
= 0;
1226 interfacePriv
->wapi_unicast_bulk_data
.os_data_ptr
= interfacePriv
->wapi_unicast_bulk_data
.os_net_buf_ptr
= NULL
;
1227 spin_unlock_irqrestore(&priv
->wapi_lock
, flags
);
1229 CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv
->CSR_WIFI_SME_IFACEQUEUE
, 0, interfaceTag
, pktBulkDataLength
, pktBulkData
);
1230 unifi_trace(priv
, UDBG1
, "WapiUnicastTxEncryptInd sent to SME\n");
1232 kfree(pktBulkData
); /* Would have been copied over by the SME Handler */
1236 unifi_warning(priv
, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv
->interfaceMode
);
1238 }/* uf_send_pkt_to_encrypt() */