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() */