diff options
Diffstat (limited to 'drivers/staging/csr/sme_sys.c')
-rw-r--r-- | drivers/staging/csr/sme_sys.c | 3260 |
1 files changed, 0 insertions, 3260 deletions
diff --git a/drivers/staging/csr/sme_sys.c b/drivers/staging/csr/sme_sys.c deleted file mode 100644 index b5258d71d25..00000000000 --- a/drivers/staging/csr/sme_sys.c +++ /dev/null @@ -1,3260 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * FILE: sme_sys.c - * - * PURPOSE: - * Driver specific implementation of the SME SYS SAP. - * It is part of the porting exercise. - * - * Copyright (C) 2008-2011 by Cambridge Silicon Radio Ltd. - * - * Refer to LICENSE.txt included with this source code for details on - * the license terms. - * - * --------------------------------------------------------------------------- - */ - -#include "csr_wifi_hip_unifiversion.h" -#include "unifi_priv.h" -#include "csr_wifi_hip_conversions.h" -#ifdef CSR_SUPPORT_WEXT_AP -#include "csr_wifi_sme_sef.h" -#endif - -/* - * This file implements the SME SYS API and contains the following functions: - * CsrWifiRouterCtrlMediaStatusReqHandler() - * CsrWifiRouterCtrlHipReqHandler() - * CsrWifiRouterCtrlPortConfigureReqHandler() - * CsrWifiRouterCtrlWifiOnReqHandler() - * CsrWifiRouterCtrlWifiOffReqHandler() - * CsrWifiRouterCtrlSuspendResHandler() - * CsrWifiRouterCtrlResumeResHandler() - * CsrWifiRouterCtrlQosControlReqHandler() - * CsrWifiRouterCtrlConfigurePowerModeReqHandler() - * CsrWifiRouterCtrlWifiOnResHandler() - * CsrWifiRouterCtrlWifiOffRspHandler() - * CsrWifiRouterCtrlMulticastAddressResHandler() - * CsrWifiRouterCtrlTrafficConfigReqHandler() - * CsrWifiRouterCtrlTrafficClassificationReqHandler() - * CsrWifiRouterCtrlTclasAddReqHandler() - * CsrWifiRouterCtrlTclasDelReqHandler() - * CsrWifiRouterCtrlSetModeReqHandler() - * CsrWifiRouterCtrlWapiMulticastFilterReqHandler() - * CsrWifiRouterCtrlWapiUnicastFilterReqHandler() - * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler() - * CsrWifiRouterCtrlWapiRxPktReqHandler() - * CsrWifiRouterCtrlWapiFilterReqHandler() - */ - -#ifdef CSR_SUPPORT_SME -static void check_inactivity_timer_expire_func(unsigned long data); -void uf_send_disconnected_ind_wq(struct work_struct *work); -#endif - -void send_auto_ma_packet_confirm(unifi_priv_t *priv, - netInterface_priv_t *interfacePriv, - struct list_head *buffered_frames_list) -{ - tx_buffered_packets_t *buffered_frame_item = NULL; - struct list_head *listHead; - struct list_head *placeHolder; - int client_id; - - CSR_SIGNAL unpacked_signal; - u8 sigbuf[UNIFI_PACKED_SIGBUF_SIZE]; - u16 packed_siglen; - - - list_for_each_safe(listHead, placeHolder, buffered_frames_list) - { - buffered_frame_item = list_entry(listHead, tx_buffered_packets_t, q); - - if(!buffered_frame_item) { - unifi_error(priv, "Entry should exist, otherwise it is a (BUG)\n"); - continue; - } - - if ((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_NONE) && - (priv->wifi_on_state == wifi_on_done)) - { - - unifi_warning(priv, "Send MA_PACKET_CONFIRM to SenderProcessId = %x for (HostTag = %x TransmissionControl = %x)\n", - (buffered_frame_item->leSenderProcessId), - buffered_frame_item->hostTag, - buffered_frame_item->transmissionControl); - - client_id = buffered_frame_item->leSenderProcessId & 0xFF00; - - if (client_id == priv->sme_cli->sender_id) - { - /* construct a MA-PACKET.confirm message for SME */ - memset(&unpacked_signal, 0, sizeof(unpacked_signal)); - unpacked_signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_CONFIRM_ID; - unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId = buffered_frame_item->leSenderProcessId; - unpacked_signal.SignalPrimitiveHeader.SenderProcessId = CSR_WIFI_ROUTER_IFACEQUEUE; - - unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, - interfacePriv->InterfaceTag); - unpacked_signal.u.MaPacketConfirm.TransmissionStatus = CSR_RESULT_FAILURE; - unpacked_signal.u.MaPacketConfirm.RetryCount = 0; - unpacked_signal.u.MaPacketConfirm.Rate = buffered_frame_item->rate; - unpacked_signal.u.MaPacketConfirm.HostTag = buffered_frame_item->hostTag; - - write_pack(&unpacked_signal, sigbuf, &packed_siglen); - unifi_warning(priv, "MA_PACKET_CONFIRM for SME (0x%x, 0x%x, 0x%x, 0x%x)\n", - unpacked_signal.SignalPrimitiveHeader.ReceiverProcessId, - unpacked_signal.SignalPrimitiveHeader.SenderProcessId, - unpacked_signal.u.MaPacketConfirm.VirtualInterfaceIdentifier, - unpacked_signal.u.MaPacketConfirm.HostTag); - - CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - packed_siglen, - (u8 *)sigbuf, - 0, NULL, - 0, NULL); - } - else if((buffered_frame_item->hostTag & 0x80000000)) - { - /* construct a MA-PACKET.confirm message for NME */ - unifi_warning(priv, "MA_PACKET_CONFIRM for NME (0x%x, 0x%x, 0x%x, 0x%x)\n", - buffered_frame_item->leSenderProcessId, - buffered_frame_item->interfaceTag, - buffered_frame_item->transmissionControl, - (buffered_frame_item->hostTag & 0x3FFFFFFF)); - - CsrWifiRouterMaPacketCfmSend((buffered_frame_item->leSenderProcessId & 0xFF), - buffered_frame_item->interfaceTag, - CSR_RESULT_FAILURE, - (buffered_frame_item->hostTag & 0x3FFFFFFF), - buffered_frame_item->rate); - - } - else - { - unifi_warning(priv, "Buffered packet dropped without sending a confirm\n"); - } - - } - - list_del(listHead); - kfree(buffered_frame_item); - buffered_frame_item = NULL; - } -} - -void CsrWifiRouterCtrlMediaStatusReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlMediaStatusReq* req = (CsrWifiRouterCtrlMediaStatusReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - unsigned long flags; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid smepriv\n"); - return; - } - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlMediaStatusReqHandler: invalid interfaceTag\n"); - return; - } - unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlMediaStatusReqHandler: Mode = %d req->mediaStatus = %d\n", interfacePriv->interfaceMode, req->mediaStatus); - if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_AMP) { - bulk_data_desc_t bulk_data; - - bulk_data.data_length = 0; - - spin_lock_irqsave(&priv->m4_lock, flags); - if (interfacePriv->m4_bulk_data.data_length > 0) { - bulk_data = interfacePriv->m4_bulk_data; - interfacePriv->m4_bulk_data.net_buf_length = 0; - interfacePriv->m4_bulk_data.data_length = 0; - interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; - } - spin_unlock_irqrestore(&priv->m4_lock, flags); - - if (bulk_data.data_length != 0) { - unifi_trace(priv, UDBG5, "CsrWifiRouterCtrlMediaStatusReqHandler: free M4\n"); - unifi_net_data_free(priv, &bulk_data); - } - - if ((req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) && - (interfacePriv->connected != UnifiConnected)) { - - switch(interfacePriv->interfaceMode){ - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - interfacePriv->connected = UnifiConnected; - netif_carrier_on(priv->netdev[req->interfaceTag]); -#ifdef CSR_SUPPORT_WEXT - wext_send_started_event(priv); -#endif - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: AP/P2PGO setting netif_carrier_on\n"); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); - break; - - default: -#ifdef CSR_SUPPORT_WEXT - /* In the WEXT builds (sme and native), the userspace is not ready - * to process any EAPOL or WAPI packets, until it has been informed - * of the NETDEV_CHANGE. - */ - if (interfacePriv->netdev_callback_registered && (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI)) { - interfacePriv->wait_netdev_change = TRUE; - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: waiting for NETDEV_CHANGE\n"); - /* - * Carrier can go to on, only after wait_netdev_change is set to TRUE. - * Otherwise there can be a race in uf_netdev_event(). - */ - netif_carrier_on(priv->netdev[req->interfaceTag]); - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlMediaStatusReqHandler: STA/P2PCLI setting netif_carrier_on\n"); - } - else -#endif - { - /* In the NME build, the userspace does not wait for the NETDEV_CHANGE - * so it is ready to process all the EAPOL or WAPI packets. - * At this point, we enable all the Tx queues, and we indicate any packets - * that are queued (and the respective port is opened). - */ - static const CsrWifiMacAddress broadcast_address = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; - interfacePriv->connected = UnifiConnected; - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: UnifiConnected && netif_carrier_on\n"); - netif_carrier_on(priv->netdev[req->interfaceTag]); - netif_tx_wake_all_queues(priv->netdev[req->interfaceTag]); - uf_process_rx_pending_queue(priv, UF_UNCONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - uf_process_rx_pending_queue(priv, UF_CONTROLLED_PORT_Q, broadcast_address, 1, interfacePriv->InterfaceTag); - } - break; - } - } - - if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_DISCONNECTED) { -#ifdef CSR_SUPPORT_WEXT - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: cancel waiting for NETDEV_CHANGE\n"); - interfacePriv->wait_netdev_change = FALSE; -#endif - unifi_trace(priv, UDBG1, - "CsrWifiRouterMediaStatusReqHandler: setting netif_carrier_off\n"); - netif_carrier_off(priv->netdev[req->interfaceTag]); -#ifdef CSR_SUPPORT_WEXT - switch(interfacePriv->interfaceMode){ - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - wext_send_started_event(priv); - break; - default: - break; - } -#endif - interfacePriv->connected = UnifiNotConnected; - } - } else { - /* For AMP, just update the L2 connected flag */ - if (req->mediaStatus == CSR_WIFI_SME_MEDIA_STATUS_CONNECTED) { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP connected\n"); - interfacePriv->connected = UnifiConnected; - } else { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlMediaStatusReqHandler: AMP disconnected\n"); - interfacePriv->connected = UnifiNotConnected; - } - } -} - - -void CsrWifiRouterCtrlHipReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlHipReq* hipreq = (CsrWifiRouterCtrlHipReq*)msg; - bulk_data_param_t bulkdata; - u8 *signal_ptr; - int signal_length; - int r=0; - void *dest; - CsrResult csrResult; - CSR_SIGNAL *signal; - u16 interfaceTag = 0; - CSR_MA_PACKET_REQUEST *req; - netInterface_priv_t *interfacePriv; - - if (priv == NULL) { - return; - } - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid smepriv\n"); - return; - } - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Initialize bulkdata to avoid os_net_buf is garbage */ - memset(&bulkdata, 0, sizeof(bulk_data_param_t)); - - signal = (CSR_SIGNAL *)hipreq->mlmeCommand; - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: 0x04%X ---->\n", - *((u16*)hipreq->mlmeCommand)); - - /* Construct the signal. */ - signal_ptr = (u8*)hipreq->mlmeCommand; - signal_length = hipreq->mlmeCommandLength; - - /* - * The MSB of the sender ID needs to be set to the client ID. - * The LSB is controlled by the SME. - */ - signal_ptr[5] = (priv->sme_cli->sender_id >> 8) & 0xff; - - /* Allocate buffers for the bulk data. */ - if (hipreq->dataRef1Length) { - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], hipreq->dataRef1Length); - if (csrResult == CSR_RESULT_SUCCESS) { - dest = (void*)bulkdata.d[0].os_data_ptr; - memcpy(dest, hipreq->dataRef1, hipreq->dataRef1Length); - bulkdata.d[0].data_length = hipreq->dataRef1Length; - } else { - unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); - return; - } - } else { - bulkdata.d[0].os_data_ptr = NULL; - bulkdata.d[0].data_length = 0; - } - if (hipreq->dataRef2Length) { - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[1], hipreq->dataRef2Length); - if (csrResult == CSR_RESULT_SUCCESS) { - dest = (void*)bulkdata.d[1].os_data_ptr; - memcpy(dest, hipreq->dataRef2, hipreq->dataRef2Length); - bulkdata.d[1].data_length = hipreq->dataRef2Length; - } else { - if (bulkdata.d[0].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[0]); - } - unifi_warning(priv, "signal not sent down, allocation failed in CsrWifiRouterCtrlHipReqHandler\n"); - return; - } - } else { - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - } - - unifi_trace(priv, UDBG3, "SME SEND: Signal 0x%.4X \n", - *((u16*)signal_ptr)); - if (signal->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) - { - CSR_SIGNAL unpacked_signal; - read_unpack_signal((u8 *) signal, &unpacked_signal); - req = &unpacked_signal.u.MaPacketRequest; - interfaceTag = req->VirtualInterfaceIdentifier & 0xff; - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_NONE: - unifi_error(priv, "CsrWifiRouterCtrlHipReqHandler: invalid mode: NONE \n"); - break; - default: - unifi_trace(priv, UDBG5, "mode is %x\n", interfacePriv->interfaceMode); - } - /* While sending ensure that first 2 bits b31 and b30 are 00. These are used for local routing*/ - r = uf_process_ma_packet_req(priv, req->Ra.x, (req->HostTag & 0x3FFFFFFF), interfaceTag, - req->TransmissionControl, req->TransmitRate, - req->Priority, signal->SignalPrimitiveHeader.SenderProcessId, - &bulkdata); - if (r) - { - if (bulkdata.d[0].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[0]); - } - if (bulkdata.d[1].data_length) - { - unifi_net_data_free(priv, &bulkdata.d[1]); - } - } - } else { - /* ul_send_signal_raw frees the bulk data if it fails */ - r = ul_send_signal_raw(priv, signal_ptr, signal_length, &bulkdata); - } - - if (r) { - unifi_error(priv, - "CsrWifiRouterCtrlHipReqHandler: Failed to send signal (0x%.4X - %u)\n", - *((u16*)signal_ptr), r); - CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, CSR_WIFI_SME_CONTROL_INDICATION_ERROR); - } - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlHipReqHandler: <----\n"); -} - -#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP -static void -uf_send_gratuitous_arp(unifi_priv_t *priv, u16 interfaceTag) -{ - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - CSR_PRIORITY priority; - CSR_SIGNAL signal; - bulk_data_param_t bulkdata; - CsrResult csrResult; - struct sk_buff *skb, *newSkb = NULL; - s8 protection; - int r; - static const u8 arp_req[36] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, - 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, - 0x00, 0x02, 0x5f, 0x20, 0x2f, 0x02, - 0xc0, 0xa8, 0x00, 0x02, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0xa8, 0x00, 0x02}; - - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], sizeof(arp_req)); - if (csrResult != CSR_RESULT_SUCCESS) - { - unifi_error(priv, "Failed to allocate bulk data in CsrWifiSmeRoamCompleteIndHandler()\n"); - return; - } - skb = (struct sk_buff *)(bulkdata.d[0].os_net_buf_ptr); - skb->len = bulkdata.d[0].data_length; - - memcpy(skb->data, arp_req, sizeof(arp_req)); - /* add MAC and IP address */ - memcpy(skb->data + 16, priv->netdev[interfaceTag]->dev_addr, ETH_ALEN); - skb->data[22] = (priv->sta_ip_address ) & 0xFF; - skb->data[23] = (priv->sta_ip_address >> 8) & 0xFF; - skb->data[24] = (priv->sta_ip_address >> 16) & 0xFF; - skb->data[25] = (priv->sta_ip_address >> 24) & 0xFF; - skb->data[32] = (priv->sta_ip_address ) & 0xFF; - skb->data[33] = (priv->sta_ip_address >> 8) & 0xFF; - skb->data[34] = (priv->sta_ip_address >> 16) & 0xFF; - skb->data[35] = (priv->sta_ip_address >> 24) & 0xFF; - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].net_buf_length = bulkdata.d[1].data_length = 0; - - if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, &arp_req[26])) < 0) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: Failed to determine protection mode\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - - if ((priv->sta_wmm_capabilities & QOS_CAPABILITY_WMM_ENABLED) == 1) - { - priority = CSR_QOS_UP0; - } - else - { - priority = CSR_CONTENTION; - } - - if (prepare_and_add_macheader(priv, skb, newSkb, priority, &bulkdata, - interfaceTag, &arp_req[26], - priv->netdev[interfaceTag]->dev_addr, protection)) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - bulkdata.d[0].os_data_ptr = skb->data; - bulkdata.d[0].os_net_buf_ptr = skb; - bulkdata.d[0].data_length = skb->len; - - unifi_frame_ma_packet_req(priv, priority, 0, 0xffffffff, interfaceTag, - CSR_NO_CONFIRM_REQUIRED, priv->netdev_client->sender_id, - interfacePriv->bssid.a, &signal); - - r = ul_send_signal_unpacked(priv, &signal, &bulkdata); - if (r) - { - unifi_error(priv, "CsrWifiSmeRoamCompleteIndHandler: failed to send QOS data null packet result: %d\n", r); - unifi_net_data_free(priv, &bulkdata.d[0]); - return; - } - -} -#endif /* CSR_WIFI_SEND_GRATUITOUS_ARP */ - -/* - * --------------------------------------------------------------------------- - * configure_data_port - * - * Store the new controlled port configuration. - * - * Arguments: - * priv Pointer to device private context struct - * port_cfg Pointer to the port configuration - * - * Returns: - * An unifi_ControlledPortAction value. - * --------------------------------------------------------------------------- - */ -static int -configure_data_port(unifi_priv_t *priv, - CsrWifiRouterCtrlPortAction port_action, - const CsrWifiMacAddress *macAddress, - const int queue, - u16 interfaceTag) -{ - const u8 broadcast_mac_address[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - unifi_port_config_t *port; - netInterface_priv_t *interfacePriv; - int i; - const char* controlled_string; /* cosmetic "controlled"/"uncontrolled" for trace */ - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "configure_data_port: bad interfaceTag\n"); - return -EFAULT; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if (queue == UF_CONTROLLED_PORT_Q) { - port = &interfacePriv->controlled_data_port; - controlled_string = "controlled"; - } else { - port = &interfacePriv->uncontrolled_data_port; - controlled_string = "uncontrolled"; - } - - unifi_trace(priv, UDBG2, - "port config request %pM %s with port_action %d.\n", - macAddress->a, controlled_string, port_action); - - /* If the new configuration has the broadcast MAC address or if we are in infrastructure mode then clear the list first and set port overide mode */ - if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode || - interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI) || - !memcmp(macAddress->a, broadcast_mac_address, ETH_ALEN)) { - - port->port_cfg[0].port_action = port_action; - port->port_cfg[0].mac_address = *macAddress; - port->port_cfg[0].in_use = TRUE; - port->entries_in_use = 1; - port->overide_action = UF_DATA_PORT_OVERIDE; - - unifi_trace(priv, UDBG2, "%s port override on\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - - /* Discard the remaining entries in the port config table */ - for (i = 1; i < UNIFI_MAX_CONNECTIONS; i++) { - port->port_cfg[i].in_use = FALSE; - } - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - unifi_trace(priv, UDBG1, "%s port broadcast set to open.\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - - /* - * Ask stack to schedule for transmission any packets queued - * while controlled port was not open. - * Use netif_schedule() instead of netif_wake_queue() because - * transmission should be already enabled at this point. If it - * is not, probably the interface is down and should remain as is. - */ - uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); - -#ifdef CSR_WIFI_SEND_GRATUITOUS_ARP - if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && - (queue == UF_CONTROLLED_PORT_Q) && (priv->sta_ip_address != 0xFFFFFFFF)) - { - uf_send_gratuitous_arp(priv, interfaceTag); - } -#endif - } else { - unifi_trace(priv, UDBG1, "%s port broadcast set to %s.\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled", - (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) ? "discard": "closed"); - - /* If port is closed, discard all the pending Rx packets */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - uf_free_pending_rx_packets(priv, queue, *macAddress, interfaceTag); - } - } - } else { - /* store the new configuration, either in the entry with matching mac address (if already present), - * otherwise in a new entry - */ - - int found_entry_flag; - int first_free_slot = -1; - - /* If leaving override mode, free the port entry used for override */ - if (port->overide_action == UF_DATA_PORT_OVERIDE) { - port->port_cfg[0].in_use = FALSE; - port->entries_in_use = 0; - port->overide_action = UF_DATA_PORT_NOT_OVERIDE; - - unifi_trace(priv, UDBG2, "%s port override off\n", - (queue == UF_CONTROLLED_PORT_Q) ? "Controlled" : "Uncontrolled"); - } - - found_entry_flag = 0; - for (i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if (port->port_cfg[i].in_use) { - if (!memcmp(&port->port_cfg[i].mac_address.a, macAddress->a, ETH_ALEN)) { - /* We've seen this address before, reconfigure it */ - port->port_cfg[i].port_action = port_action; - found_entry_flag = 1; - break; - } - } else if (first_free_slot == -1) { - /* Remember the first free slot on the way past so it can be claimed - * if this turns out to be a new MAC address (to save walking the list again). - */ - first_free_slot = i; - } - } - - /* At this point we found an existing entry and have updated it, or need to - * add a new entry. If all slots are allocated, give up and return an error. - */ - if (!found_entry_flag) { - if (first_free_slot == -1) { - unifi_error(priv, "no free slot found in port config array (%d used)\n", port->entries_in_use); - return -EFAULT; - } else { - port->entries_in_use++; - } - - unifi_trace(priv, UDBG3, "port config index assigned in config_data_port = %d\n", first_free_slot); - port->port_cfg[first_free_slot].in_use = TRUE; - port->port_cfg[first_free_slot].port_action = port_action; - port->port_cfg[first_free_slot].mac_address = *macAddress; - } - - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - /* - * Ask stack to schedule for transmission any packets queued - * while controlled port was not open. - * Use netif_schedule() instead of netif_wake_queue() because - * transmission should be already enabled at this point. If it - * is not, probably the interface is down and should remain as is. - */ - uf_resume_data_plane(priv, queue, *macAddress, interfaceTag); - } - - /* - * If port is closed, discard all the pending Rx packets - * coming from the peer station. - */ - if (port_action == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD) { - uf_free_pending_rx_packets(priv, queue, *macAddress, interfaceTag); - } - - unifi_trace(priv, UDBG2, - "port config %pM with port_action %d.\n", - macAddress->a, port_action); - } - return 0; -} /* configure_data_port() */ - - -void CsrWifiRouterCtrlPortConfigureReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlPortConfigureReq* req = (CsrWifiRouterCtrlPortConfigureReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - unifi_trace(priv, UDBG3, "entering CsrWifiRouterCtrlPortConfigureReqHandler\n"); - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlPortConfigureReqHandler: invalid smepriv\n"); - return; - } - - /* To update the protection status of the peer/station */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - /* Since for Unifi as a station, the station record not maintained & interfaceID is - * only needed to update the peer protection status - */ - interfacePriv->protect = req->setProtection; - break; - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - { - u8 i; - CsrWifiRouterCtrlStaInfo_t *staRecord; - /* Ifscontrolled port is open means, The peer has been added to station record - * so that the protection corresponding to the peer is valid in this req - */ - if (req->controlledPortAction == CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) { - for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) { - staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]); - if (staRecord) { - /* Find the matching station record & set the protection type */ - if (!memcmp(req->macAddress.a, staRecord->peerMacAddress.a, ETH_ALEN)) { - staRecord->protection = req->setProtection; - break; - } - } - } - } - } - break; - default: - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlPortConfigureReqHandler(0x%.4X) Uncaught mode %d\n", - msg->source, interfacePriv->interfaceMode); - } - - configure_data_port(priv, req->uncontrolledPortAction, (const CsrWifiMacAddress *)&req->macAddress, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - configure_data_port(priv, req->controlledPortAction, (const CsrWifiMacAddress *)&req->macAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - - CsrWifiRouterCtrlPortConfigureCfmSend(msg->source, req->clientData, req->interfaceTag, - CSR_RESULT_SUCCESS, req->macAddress); - unifi_trace(priv, UDBG3, "leaving CsrWifiRouterCtrlPortConfigureReqHandler\n"); -} - - -void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlVersions versions; - CsrWifiRouterCtrlWifiOnReq* req = (CsrWifiRouterCtrlWifiOnReq*)msg; - int r, i; - CsrResult csrResult; - - if (priv == NULL) { - return; - } - if( priv->wol_suspend ) { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Don't reset mode\n"); - } else { -#ifdef ANDROID_BUILD - /* Take the wakelock while Wi-Fi On is in progress */ - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: take wake lock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) { - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Setting interface %d to NONE\n", i ); - - priv->interfacePriv[i]->interfaceMode = 0; - } - } - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X) req->dataLength=%d req->data=0x%x\n", msg->source, req->dataLength, req->data); - - if(req->dataLength==3 && req->data && req->data[0]==0 && req->data[1]==1 && req->data[2]==1) - { - priv->cmanrTestMode = TRUE; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: cmanrTestMode=%d\n", priv->cmanrTestMode); - } - else - { - priv->cmanrTestMode = FALSE; - } - - /* - * The request to initialise UniFi might come while UniFi is running. - * We need to block all I/O activity until the reset completes, otherwise - * an SDIO error might occur resulting an indication to the SME which - * makes it think that the initialisation has failed. - */ - priv->bh_thread.block_thread = 1; - - /* Update the wifi_on state */ - priv->wifi_on_state = wifi_on_in_progress; - - /* If UniFi was unpowered, acquire the firmware for download to chip */ - if (!priv->wol_suspend) { - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - } else { - unifi_trace(priv, UDBG1, "Don't need firmware\n"); - } - - /* Power on UniFi (which may not necessarily have been off) */ - CsrSdioClaim(priv->sdio); - csrResult = CsrSdioPowerOn(priv->sdio); - CsrSdioRelease(priv->sdio); - if (csrResult != CSR_RESULT_SUCCESS && csrResult != CSR_SDIO_RESULT_NOT_RESET) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to power on UniFi\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - - /* If CsrSdioPowerOn() returns CSR_RESULT_SUCCESS, it means that we need to initialise UniFi */ - if (csrResult == CSR_RESULT_SUCCESS && !priv->wol_suspend) { - /* Initialise UniFi hardware */ - r = uf_init_hw(priv); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - } else { - unifi_trace(priv, UDBG1, "UniFi already initialised\n"); - } - - /* Completed handling of wake up from suspend with UniFi powered */ - priv->wol_suspend = FALSE; - - /* Re-enable the I/O thread */ - priv->bh_thread.block_thread = 0; - - /* - * Start the I/O thread. The thread might be already running. - * This fine, just carry on with the request. - */ - r = uf_init_bh(priv); - if (r) { - CsrSdioClaim(priv->sdio); - CsrSdioPowerOff(priv->sdio); - CsrSdioRelease(priv->sdio); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE); - return; - } - - /* Get the version information from the core */ - unifi_card_info(priv->card, &priv->card_info); - - /* Set the sme queue id */ - priv->CSR_WIFI_SME_IFACEQUEUE = msg->source; - CSR_WIFI_SME_IFACEQUEUE = msg->source; - - - /* Copy to the unifiio_card_info structure. */ - versions.chipId = priv->card_info.chip_id; - versions.chipVersion = priv->card_info.chip_version; - versions.firmwareBuild = priv->card_info.fw_build; - versions.firmwareHip = priv->card_info.fw_hip_version; - versions.routerBuild = (char*)CSR_WIFI_VERSION; - versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; - - CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); - - /* Update the wifi_on state */ - priv->wifi_on_state = wifi_on_done; -} - - -/* - * wifi_off: - * Common code for CsrWifiRouterCtrlWifiOffReqHandler() and - * CsrWifiRouterCtrlWifiOffRspHandler(). - */ -static void -wifi_off(unifi_priv_t *priv) -{ - int power_off; - int priv_instance; - int i; - CsrResult csrResult; - - - /* Already off? */ - if (priv->wifi_on_state == wifi_on_unspecified) { - unifi_trace(priv, UDBG1, "wifi_off already\n"); - return; - } - - unifi_trace(priv, UDBG1, "wifi_off\n"); - - /* Destroy the Traffic Analysis Module */ - cancel_work_sync(&priv->ta_ind_work.task); - cancel_work_sync(&priv->ta_sample_ind_work.task); -#ifdef CSR_SUPPORT_WEXT - cancel_work_sync(&priv->sme_config_task); - wext_send_disassoc_event(priv); -#endif - - /* Cancel pending M4 stuff */ - for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) { - if (priv->netdev[i]) { - netInterface_priv_t *netpriv = (netInterface_priv_t *) netdev_priv(priv->netdev[i]); - cancel_work_sync(&netpriv->send_m4_ready_task); - } - } - flush_workqueue(priv->unifi_workqueue); - - /* fw_init parameter can prevent power off UniFi, for debugging */ - priv_instance = uf_find_priv(priv); - if (priv_instance == -1) { - unifi_warning(priv, - "CsrWifiRouterCtrlStopReqHandler: Unknown priv instance, will power off card.\n"); - power_off = 1; - } else { - power_off = (fw_init[priv_instance] > 0) ? 0 : 1; - } - - /* Production test mode requires power to the chip, too */ - if (priv->ptest_mode) { - power_off = 0; - } - - /* Stop the bh_thread */ - uf_stop_thread(priv, &priv->bh_thread); - - /* Read the f/w panic codes, if any. Protect against second wifi_off() call, - * which may happen if SME requests a wifi_off and closes the char device */ - if (priv->init_progress != UNIFI_INIT_NONE) { - CsrSdioClaim(priv->sdio); - unifi_capture_panic(priv->card); - CsrSdioRelease(priv->sdio); - } - - /* Unregister the interrupt handler */ - if (csr_sdio_linux_remove_irq(priv->sdio)) { - unifi_notice(priv, - "csr_sdio_linux_remove_irq failed to talk to card.\n"); - } - - if (power_off) { - unifi_trace(priv, UDBG2, - "Force low power and try to power off\n"); - /* Put UniFi to deep sleep, in case we can not power it off */ - CsrSdioClaim(priv->sdio); - csrResult = unifi_force_low_power_mode(priv->card); - CsrSdioRelease(priv->sdio); - - CsrSdioPowerOff(priv->sdio); - } - - /* Consider UniFi to be uninitialised */ - priv->init_progress = UNIFI_INIT_NONE; - priv->wifi_on_state = wifi_on_unspecified; - - -} /* wifi_off() */ - - -void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg; - int i = 0; - - if (priv == NULL) { - return; - } - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOffReqHandler(0x%.4X)\n", msg->source); - - /* Stop the network traffic on all interfaces before freeing the core. */ - for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - if (interfacePriv->netdev_registered == 1) { - netif_carrier_off(priv->netdev[i]); - netif_tx_stop_all_queues(priv->netdev[i]); - interfacePriv->connected = UnifiConnectedUnknown; - } - interfacePriv->interfaceMode = 0; - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - } - wifi_off(priv); - - CsrWifiRouterCtrlWifiOffCfmSend(msg->source, req->clientData); - - /* If this is called in response to closing the character device, the - * caller must use uf_sme_cancel_request() to terminate any pending SME - * blocking request or there will be a delay while the operation times out. - */ -} - - -void CsrWifiRouterCtrlQosControlReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlQosControlReq* req = (CsrWifiRouterCtrlQosControlReq*)msg; - netInterface_priv_t *interfacePriv; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: invalid smepriv\n"); - return; - } - - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlQosControlReqHandler:scontrol = %d", req->control); - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlQosControlReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return; - } - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (req->control == CSR_WIFI_ROUTER_CTRL_QOS_CONTROL_WMM_ON) { - priv->sta_wmm_capabilities |= QOS_CAPABILITY_WMM_ENABLED; - unifi_trace(priv, UDBG1, "WMM enabled\n"); - - unifi_trace(priv, UDBG1, "Queue Config %x\n", req->queueConfig); - - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BK] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BK_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_BE] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_BE_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VI] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VI_ENABLE)?1:0; - interfacePriv->queueEnabled[UNIFI_TRAFFIC_Q_VO] = (req->queueConfig & CSR_WIFI_ROUTER_CTRL_QUEUE_VO_ENABLE)?1:0; - - } else { - priv->sta_wmm_capabilities = 0; - unifi_trace(priv, UDBG1, "WMM disabled\n"); - } -} - - -void CsrWifiRouterCtrlTclasAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTclasAddReq* req = (CsrWifiRouterCtrlTclasAddReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTclasAddReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlTclasAddCfmSend(msg->source, req->clientData, req->interfaceTag , CSR_RESULT_SUCCESS); -} - -void CsrWifiRouterCtrlTclasDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTclasDelReq* req = (CsrWifiRouterCtrlTclasDelReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTclasDelReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlTclasDelCfmSend(msg->source, req->clientData, req->interfaceTag, CSR_RESULT_SUCCESS); -} - - -void CsrWifiRouterCtrlConfigurePowerModeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlConfigurePowerModeReq* req = (CsrWifiRouterCtrlConfigurePowerModeReq*)msg; - enum unifi_low_power_mode pm; - CsrResult csrResult; - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlConfigurePowerModeReqHandler: invalid smepriv\n"); - return; - } - - if (req->mode == CSR_WIFI_ROUTER_CTRL_LOW_POWER_MODE_DISABLED) { - pm = UNIFI_LOW_POWER_DISABLED; - } else { - pm = UNIFI_LOW_POWER_ENABLED; - } - - unifi_trace(priv, UDBG2, - "CsrWifiRouterCtrlConfigurePowerModeReqHandler (mode=%d, wake=%d)\n", - req->mode, req->wakeHost); - csrResult = unifi_configure_low_power_mode(priv->card, pm, - (req->wakeHost ? UNIFI_PERIODIC_WAKE_HOST_ENABLED : UNIFI_PERIODIC_WAKE_HOST_DISABLED)); -} - - -void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWifiOnRes* res = (CsrWifiRouterCtrlWifiOnRes*)msg; - - if (priv == NULL) { - unifi_error(NULL, "CsrWifiRouterCtrlWifiOnResHandler: Invalid ospriv.\n"); - return; - } - - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlWifiOnResHandler: status %d (patch %u)\n", res->status, res->smeVersions.firmwarePatch); - - if (res->smeVersions.firmwarePatch != 0) { - unifi_info(priv, "Firmware patch %d\n", res->smeVersions.firmwarePatch); - } - - if (res->numInterfaceAddress > CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "WifiOnResHandler bad numInterfaceAddress %d\n", res->numInterfaceAddress); - return; - } - - /* UniFi is now initialised, complete the init. */ - if (res->status == CSR_RESULT_SUCCESS) - { - int i; /* used as a loop counter */ - u32 intmode = CSR_WIFI_INTMODE_DEFAULT; -#ifdef CSR_WIFI_SPLIT_PATCH - u8 switching_ap_fw = FALSE; -#endif - /* Register the UniFi device with the OS network manager */ - unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n"); - - /* Store the MAC address in the netdev */ - for(i=0;i<res->numInterfaceAddress;i++) - { - memcpy(priv->netdev[i]->dev_addr, res->stationMacAddress[i].a, ETH_ALEN); - } - - /* Copy version structure into the private versions field */ - priv->sme_versions = res->smeVersions; - - unifi_trace(priv, UDBG2, "network interfaces count = %d\n", - res->numInterfaceAddress); - - /* Register the netdevs for each interface. */ - for(i=0;i<res->numInterfaceAddress;i++) - { - netInterface_priv_t *interfacePriv = priv->interfacePriv[i]; - if(!interfacePriv->netdev_registered) - { - int r; - unifi_trace(priv, UDBG3, "registering net device %d\n", i); - r = uf_register_netdev(priv, i); - if (r) - { - /* unregister the net_device that are registered in the previous iterations */ - uf_unregister_netdev(priv); - unifi_error(priv, "Failed to register the network device.\n"); - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); - return; - } - } -#ifdef CSR_WIFI_SPLIT_PATCH - else - { - /* If a netdev is already registered, we have received this WifiOnRes - * in response to switching AP/STA firmware in a ModeSetReq. - * Rememeber this in order to send a ModeSetCfm once - */ - switching_ap_fw = TRUE; - } -#endif - } - priv->totalInterfaceCount = res->numInterfaceAddress; - - /* If the MIB has selected f/w scheduled interrupt mode, apply it now - * but let module param override. - */ - if (run_bh_once != -1) { - intmode = (u32)run_bh_once; - } else if (res->scheduledInterrupt) { - intmode = CSR_WIFI_INTMODE_RUN_BH_ONCE; - } - unifi_set_interrupt_mode(priv->card, intmode); - - priv->init_progress = UNIFI_INIT_COMPLETED; - - /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS); - -#ifdef CSR_WIFI_SPLIT_PATCH - if (switching_ap_fw && (priv->pending_mode_set.common.destination != 0xaaaa)) { - unifi_info(priv, "Completed firmware reload with %s patch\n", - CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode) ? "AP" : "STA"); - - /* Confirm the ModeSetReq that requested the AP/STA patch switch */ - CsrWifiRouterCtrlModeSetCfmSend(priv->pending_mode_set.common.source, - priv->pending_mode_set.clientData, - priv->pending_mode_set.interfaceTag, - priv->pending_mode_set.mode, - CSR_RESULT_SUCCESS); - priv->pending_mode_set.common.destination = 0xaaaa; - } -#endif - unifi_info(priv, "UniFi ready\n"); - -#ifdef ANDROID_BUILD - /* Release the wakelock */ - unifi_trace(priv, UDBG1, "ready: release wake lock\n"); - wake_unlock(&unifi_sdio_wake_lock); -#endif - /* Firmware initialisation is complete, so let the SDIO bus - * clock be raised when convienent to the core. - */ - unifi_request_max_sdio_clock(priv->card); - -#ifdef CSR_SUPPORT_WEXT - /* Notify the Android wpa_supplicant that we are ready */ - wext_send_started_event(priv); - - queue_work(priv->unifi_workqueue, &priv->sme_config_task); -#endif - - } else { - /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */ - CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_FAILURE); - } -} - - -void CsrWifiRouterCtrlWifiOffResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiRouterCtrlMulticastAddressResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - - -void CsrWifiRouterMaPacketSubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketSubscribeReq* req = (CsrWifiRouterMaPacketSubscribeReq*)msg; - u8 i; - CsrResult result; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterMaPacketSubscribeReqHandler: invalid priv\n"); - return; - } - - /* Look for an unused filter */ - - result = CSR_WIFI_RESULT_NO_ROOM; - for (i = 0; i < MAX_MA_UNIDATA_IND_FILTERS; i++) { - - if (!priv->sme_unidata_ind_filters[i].in_use) { - - priv->sme_unidata_ind_filters[i].in_use = 1; - priv->sme_unidata_ind_filters[i].appHandle = msg->source; - priv->sme_unidata_ind_filters[i].encapsulation = req->encapsulation; - priv->sme_unidata_ind_filters[i].protocol = req->protocol; - - priv->sme_unidata_ind_filters[i].oui[2] = (u8) (req->oui & 0xFF); - priv->sme_unidata_ind_filters[i].oui[1] = (u8) ((req->oui >> 8) & 0xFF); - priv->sme_unidata_ind_filters[i].oui[0] = (u8) ((req->oui >> 16) & 0xFF); - - result = CSR_RESULT_SUCCESS; - break; - } - } - - unifi_trace(priv, UDBG1, - "subscribe_req: encap=%d, handle=%d, result=%d\n", - req->encapsulation, i, result); - CsrWifiRouterMaPacketSubscribeCfmSend(msg->source, req->interfaceTag, i, result, 0); -} - - -void CsrWifiRouterMaPacketUnsubscribeReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketUnsubscribeReq* req = (CsrWifiRouterMaPacketUnsubscribeReq*)msg; - CsrResult result; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterMaPacketUnsubscribeReqHandler: invalid priv\n"); - return; - } - - result = CSR_WIFI_RESULT_NOT_FOUND; - - if (req->subscriptionHandle < MAX_MA_UNIDATA_IND_FILTERS) { - if (priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use) { - priv->sme_unidata_ind_filters[req->subscriptionHandle].in_use = 0; - result = CSR_RESULT_SUCCESS; - } else { - result = CSR_WIFI_RESULT_NOT_FOUND; - } - } - - unifi_trace(priv, UDBG1, - "unsubscribe_req: handle=%d, result=%d\n", - req->subscriptionHandle, result); - CsrWifiRouterMaPacketUnsubscribeCfmSend(msg->source, req->interfaceTag, result); -} - - -void CsrWifiRouterCtrlCapabilitiesReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlCapabilitiesReq* req = (CsrWifiRouterCtrlCapabilitiesReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlCapabilitiesReqHandler: invalid priv\n"); - return; - } - - CsrWifiRouterCtrlCapabilitiesCfmSend(msg->source, req->clientData, - UNIFI_SOFT_COMMAND_Q_LENGTH - 1, - UNIFI_SOFT_TRAFFIC_Q_LENGTH - 1); -} - - -void CsrWifiRouterCtrlSuspendResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlSuspendRes* res = (CsrWifiRouterCtrlSuspendRes*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlSuspendResHandler: invalid priv\n"); - return; - } - - sme_complete_request(priv, res->status); -} - - -void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlResumeRes* res = (CsrWifiRouterCtrlResumeRes*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlResumeResHandler: invalid priv\n"); - return; - } - - sme_complete_request(priv, res->status); -} - - -void CsrWifiRouterCtrlTrafficConfigReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTrafficConfigReq* req = (CsrWifiRouterCtrlTrafficConfigReq*)msg; - CsrResult csrResult; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTrafficConfigReqHandler: invalid smepriv\n"); - return; - } - if (req->trafficConfigType == CSR_WIFI_ROUTER_CTRL_TRAFFIC_CONFIG_TYPE_FILTER) - { - req->config.packetFilter |= CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_CUSTOM; - } - csrResult = unifi_ta_configure(priv->card, req->trafficConfigType, (const CsrWifiRouterCtrlTrafficConfig *)&req->config); -} - -void CsrWifiRouterCtrlTrafficClassificationReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlTrafficClassificationReq* req = (CsrWifiRouterCtrlTrafficClassificationReq*)msg; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlTrafficClassificationReqHandler: invalid smepriv\n"); - return; - } - - unifi_ta_classification(priv->card, req->trafficType, req->period); -} - -static int -_sys_packet_req(unifi_priv_t *priv, const CSR_SIGNAL *signal, - u8 subscriptionHandle, - u16 frameLength, u8 *frame, - int proto) -{ - int r; - const sme_ma_unidata_ind_filter_t *subs; - bulk_data_param_t bulkdata; - CSR_MA_PACKET_REQUEST req = signal->u.MaPacketRequest; - struct sk_buff *skb, *newSkb = NULL; - CsrWifiMacAddress peerMacAddress; - CsrResult csrResult; - u16 interfaceTag = req.VirtualInterfaceIdentifier & 0xff; - u8 eapolStore = FALSE; - s8 protection = 0; - netInterface_priv_t *interfacePriv; - unsigned long flags; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "_sys_packet_req: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return -EINVAL; - } - interfacePriv = priv->interfacePriv[interfaceTag]; - if (!priv->sme_unidata_ind_filters[subscriptionHandle].in_use) { - unifi_error(priv, "_sys_packet_req: unknown subscription.\n"); - return -EINVAL; - } - - subs = &priv->sme_unidata_ind_filters[subscriptionHandle]; - unifi_trace(priv, UDBG1, - "_sys_packet_req: handle=%d, subs=%p, encap=%d\n", - subscriptionHandle, subs, subs->encapsulation); - - csrResult = unifi_net_data_malloc(priv, &bulkdata.d[0], frameLength); - if (csrResult != CSR_RESULT_SUCCESS) { - unifi_error(priv, "_sys_packet_req: failed to allocate bulkdata.\n"); - return (int)CsrHipResultToStatus(csrResult); - } - - /* get the peer Mac address */ - memcpy(&peerMacAddress, frame, ETH_ALEN); - - /* Determine if we need to add encapsulation header */ - if (subs->encapsulation == CSR_WIFI_ROUTER_ENCAPSULATION_ETHERNET) { - memcpy((void*)bulkdata.d[0].os_data_ptr, frame, frameLength); - - /* The translation is performed on the skb */ - skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; - - unifi_trace(priv, UDBG1, - "_sys_packet_req: skb_add_llc_snap -->\n"); - r = skb_add_llc_snap(priv->netdev[interfaceTag], skb, proto); - unifi_trace(priv, UDBG1, - "_sys_packet_req: skb_add_llc_snap <--\n"); - if (r) { - unifi_error(priv, - "_sys_packet_req: failed to translate eth frame.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return r; - } - - bulkdata.d[0].data_length = skb->len; - } else { - /* Crop the MAC addresses from the packet */ - memcpy((void*)bulkdata.d[0].os_data_ptr, frame + 2*ETH_ALEN, frameLength - 2*ETH_ALEN); - bulkdata.d[0].data_length = frameLength - 2*ETH_ALEN; - skb = (struct sk_buff*)bulkdata.d[0].os_net_buf_ptr; - skb->len = bulkdata.d[0].data_length; - - } - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].os_net_buf_ptr = NULL; - bulkdata.d[1].data_length = 0; - - /* check for m4 detection */ - if (0 == uf_verify_m4(priv, bulkdata.d[0].os_data_ptr, bulkdata.d[0].data_length)) { - eapolStore = TRUE; - } - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - if (proto == ETH_P_WAI) - { - protection = 0; /*WAI packets always sent unencrypted*/ - } - else - { -#endif - -#ifdef CSR_SUPPORT_SME - if ((protection = uf_get_protection_bit_from_interfacemode(priv, interfaceTag, peerMacAddress.a)) < 0) { - unifi_error(priv, "unicast address, but destination not in station record database\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } -#else - protection = 0; -#endif - -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - } -#endif - - /* add Mac header */ - if (prepare_and_add_macheader(priv, skb, newSkb, req.Priority, &bulkdata, interfaceTag, frame, frame + ETH_ALEN, protection)) { - unifi_error(priv, "failed to create MAC header\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return -1; - } - - if (eapolStore) { - spin_lock_irqsave(&priv->m4_lock, flags); - /* Store the EAPOL M4 packet for later */ - interfacePriv->m4_signal = *signal; - interfacePriv->m4_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length; - interfacePriv->m4_bulk_data.data_length = bulkdata.d[0].data_length; - interfacePriv->m4_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr; - interfacePriv->m4_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr; - spin_unlock_irqrestore(&priv->m4_lock, flags); - /* Send a signal to SME */ - unifi_trace(priv, UDBG1, "_sys_packet_req: Sending CsrWifiRouterCtrlM4ReadyToSendInd\n"); - CsrWifiRouterCtrlM4ReadyToSendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, peerMacAddress); - return 0; - } - - /* Send the signal to UniFi */ - /* Set the B31 to 1 for local routing*/ - r= uf_process_ma_packet_req(priv, peerMacAddress.a, (req.HostTag | 0x80000000), interfaceTag, 0, - (CSR_RATE)0, req.Priority, signal->SignalPrimitiveHeader.SenderProcessId, &bulkdata); - if (r) { - unifi_error(priv, - "_sys_packet_req: failed to send signal.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - return r; - } - /* The final CsrWifiRouterMaPacketCfmSend() will called when the actual MA-PACKET.cfm is received from the chip */ - - return 0; -} - -void CsrWifiRouterMaPacketReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - int r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterMaPacketReq* mareq = (CsrWifiRouterMaPacketReq*)msg; - llc_snap_hdr_t *snap; - u16 snap_protocol; - CSR_SIGNAL signal; - CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest; - CsrWifiRouterCtrlPortAction controlPortaction; - u8 *daddr, *saddr; - u16 interfaceTag = mareq->interfaceTag & 0x00ff; - int queue; - netInterface_priv_t *interfacePriv; - - if (!mareq->frame || !priv || !priv->smepriv) - { - unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: invalid frame/priv/priv->smepriv\n"); - return; - } - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterMaPacketReqHandler: interfaceID >= CSR_WIFI_NUM_INTERFACES.\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - /* get a pointer to dest & source Mac address */ - daddr = mareq->frame; - saddr = (mareq->frame + ETH_ALEN); - /* point to the proper position of frame, since frame has MAC header */ - snap = (llc_snap_hdr_t *) (mareq->frame + 2 * ETH_ALEN); - snap_protocol = ntohs(snap->protocol); - if((snap_protocol == ETH_P_PAE) -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - || (snap_protocol == ETH_P_WAI) -#endif - ) - { - queue = UF_UNCONTROLLED_PORT_Q; - } - else - { - queue = UF_CONTROLLED_PORT_Q; - } - - /* Controlled port restrictions apply to the packets */ - controlPortaction = uf_sme_port_state(priv, daddr, queue, interfaceTag); - if (controlPortaction != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN) - { - unifi_warning(priv, "CsrWifiRouterMaPacketReqHandler: (%s)controlled port is closed.\n", (queue == UF_CONTROLLED_PORT_Q)?"":"un"); - if(mareq->cfmRequested) - { - CsrWifiRouterMaPacketCfmSend(msg->source, - interfaceTag, - CSR_RESULT_FAILURE, - mareq->hostTag, 0); - } - return; - } - - signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID; - /* Store the appHandle in the LSB of the SenderId. */ - CSR_COPY_UINT16_TO_LITTLE_ENDIAN(((priv->sme_cli->sender_id & 0xff00) | (unsigned int)msg->source), - (u8*)&signal.SignalPrimitiveHeader.SenderProcessId); - signal.SignalPrimitiveHeader.ReceiverProcessId = 0; - - /* Fill in the MA-PACKET.req signal */ - memcpy(req->Ra.x, daddr, ETH_ALEN); - req->Priority = mareq->priority; - req->TransmitRate = 0; /* Let firmware select the rate*/ - req->VirtualInterfaceIdentifier = uf_get_vif_identifier(interfacePriv->interfaceMode, interfaceTag); - req->HostTag = mareq->hostTag; - - if(mareq->cfmRequested) - req->TransmissionControl = 0; - else - req->TransmissionControl = CSR_NO_CONFIRM_REQUIRED; - - r = _sys_packet_req(priv, &signal, mareq->subscriptionHandle, - mareq->frameLength, mareq->frame, snap_protocol); - - if (r && mareq->cfmRequested) - { - CsrWifiRouterMaPacketCfmSend(msg->source, interfaceTag, - CSR_RESULT_FAILURE, - mareq->hostTag, 0); - } - return; -} - -void CsrWifiRouterMaPacketCancelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -void CsrWifiRouterCtrlM4TransmitReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlM4TransmitReq* req = (CsrWifiRouterCtrlM4TransmitReq*)msg; - int r; - bulk_data_param_t bulkdata; - netInterface_priv_t *interfacePriv; - CSR_SIGNAL m4_signal; - unsigned long flags; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid smepriv\n"); - return; - } - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "M4TransmitReqHandler: interfaceTag >= CSR_WIFI_NUM_INTERFACES\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - spin_lock_irqsave(&priv->m4_lock, flags); - if (interfacePriv->m4_bulk_data.data_length == 0) { - spin_unlock_irqrestore(&priv->m4_lock, flags); - unifi_error(priv, "CsrWifiRouterCtrlM4TransmitReqHandler: invalid buffer\n"); - return; - } - - memcpy(&bulkdata.d[0], &interfacePriv->m4_bulk_data, sizeof(bulk_data_desc_t)); - - interfacePriv->m4_bulk_data.net_buf_length = 0; - interfacePriv->m4_bulk_data.data_length = 0; - interfacePriv->m4_bulk_data.os_data_ptr = interfacePriv->m4_bulk_data.os_net_buf_ptr = NULL; - m4_signal = interfacePriv->m4_signal; - spin_unlock_irqrestore(&priv->m4_lock, flags); - - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - - interfacePriv->m4_sent = TRUE; - m4_signal.u.MaPacketRequest.HostTag |= 0x80000000; - /* Store the hostTag for later varification */ - interfacePriv->m4_hostTag = m4_signal.u.MaPacketRequest.HostTag; - r = ul_send_signal_unpacked(priv, &m4_signal, &bulkdata); - unifi_trace(priv, UDBG1, - "CsrWifiRouterCtrlM4TransmitReqHandler: sent\n"); - if (r) { - unifi_error(priv, - "CsrWifiRouterCtrlM4TransmitReqHandler: failed to send signal.\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - } -} - -/* reset the station records when the mode is set as CSR_WIFI_ROUTER_CTRL_MODE_NONE */ -static void CsrWifiRouterCtrlResetStationRecordList(unifi_priv_t *priv, u16 interfaceTag) -{ - u8 i, j; - CsrWifiRouterCtrlStaInfo_t *staInfo=NULL; - netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag]; - unsigned long lock_flags; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlResetStationRecordList: bad interfaceTag\n"); - return; - } - - INIT_LIST_HEAD(&send_cfm_list); - - /* Reset the station record to NULL if mode is NONE */ - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if ((staInfo=interfacePriv->staInfo[i]) != NULL) { - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - uf_flush_list(priv, &(staInfo->mgtFrames)); - for(j=0;j<MAX_ACCESS_CATOGORY;j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->dataPdu[j])); - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Removing station record information from port config array */ - memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerControlledPort->in_use = FALSE; - interfacePriv->controlled_data_port.entries_in_use--; - - memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerUnControlledPort->in_use = FALSE; - interfacePriv->uncontrolled_data_port.entries_in_use--; - - kfree(interfacePriv->staInfo[i]); - interfacePriv->staInfo[i] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - } - } - /* after the critical region process the list of frames that requested cfm - * and send cfm to requestor one by one - */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - -#ifdef CSR_SUPPORT_SME - /* Interface Independent, no of packet queued, incase of mode is None or AP set to 0 */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - case CSR_WIFI_ROUTER_CTRL_MODE_NONE: - if (priv->noOfPktQueuedInDriver) { - unifi_warning(priv, "After reset the noOfPktQueuedInDriver = %x\n", priv->noOfPktQueuedInDriver); - spin_lock_irqsave(&priv->tx_q_lock, lock_flags); - priv->noOfPktQueuedInDriver = 0; - spin_unlock_irqrestore(&priv->tx_q_lock, lock_flags); - } - break; - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - break; - default: - unifi_error(priv, "interfacemode is not correct in CsrWifiRouterCtrlResetStationRecordList: debug\n"); - } -#endif - - if (((interfacePriv->controlled_data_port.entries_in_use != 0) || (interfacePriv->uncontrolled_data_port.entries_in_use != 0)) - && (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_NONE)) { - /* Print in case if the value of entries goes to -ve/+ve (apart from 0) - * we expect the entries should be zero here if mode is set as NONE - */ - unifi_trace(priv, UDBG3, "In %s controlled port entries = %d, uncontrolled port entries = %d\n", - __FUNCTION__, interfacePriv->controlled_data_port.entries_in_use, - interfacePriv->uncontrolled_data_port.entries_in_use); - } -} - -void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, u16 interfaceTag) -{ - netInterface_priv_t *interfacePriv; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "CsrWifiRouterCtrlInterfaceReset: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - INIT_LIST_HEAD(&send_cfm_list); - - /* Enable all queues by default */ - interfacePriv->queueEnabled[0] = 1; - interfacePriv->queueEnabled[1] = 1; - interfacePriv->queueEnabled[2] = 1; - interfacePriv->queueEnabled[3] = 1; - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMgtFrames)); - uf_flush_list(priv, &(interfacePriv->genericMgtFrames)); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMulticastOrBroadCastMgtFrames)); - uf_flush_list(priv, &(interfacePriv->genericMulticastOrBroadCastMgtFrames)); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(interfacePriv->genericMulticastOrBroadCastFrames)); - - uf_flush_list(priv, &(interfacePriv->genericMulticastOrBroadCastFrames)); - - /* process the list of frames that requested cfm - and send cfm to requestor one by one */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - - /* Reset the station record to NULL if mode is tried to set as NONE */ - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - case CSR_WIFI_ROUTER_CTRL_MODE_MONITOR: - case CSR_WIFI_ROUTER_CTRL_MODE_AMP: - /* station records not available in these modes */ - break; - default: - CsrWifiRouterCtrlResetStationRecordList(priv, interfaceTag); - } - - interfacePriv->num_stations_joined = 0; - interfacePriv->sta_activity_check_enabled = FALSE; -} - - -void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlModeSetReq* req = (CsrWifiRouterCtrlModeSetReq*)msg; - - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES) - { - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; -#ifdef CSR_WIFI_SPLIT_PATCH - u8 old_mode = interfacePriv->interfaceMode; -#endif - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n", - interfacePriv->interfaceMode); - - interfacePriv->interfaceMode = req->mode; - -#ifdef CSR_WIFI_SPLIT_PATCH - /* Detect a change in mode that requires a switch to/from the AP firmware patch. - * This should only happen when transitioning in/out of AP modes. - */ - if (CSR_WIFI_HIP_IS_AP_FW(req->mode) != CSR_WIFI_HIP_IS_AP_FW(old_mode)) - { - CsrWifiRouterCtrlVersions versions; - int r; - -#ifdef ANDROID_BUILD - /* Take the wakelock while switching patch */ - unifi_trace(priv, UDBG1, "patch switch: take wake lock\n"); - wake_lock(&unifi_sdio_wake_lock); -#endif - unifi_info(priv, "Resetting UniFi with %s patch\n", CSR_WIFI_HIP_IS_AP_FW(req->mode) ? "AP" : "STA"); - - r = uf_request_firmware_files(priv, UNIFI_FW_STA); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: Failed to get f/w\n"); - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_FAILURE); - return; - } - - /* Block the I/O thread */ - priv->bh_thread.block_thread = 1; - - /* Reset and download the new patch */ - r = uf_init_hw(priv); - if (r) { - unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r); - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_FAILURE); - return; - } - - /* Re-enable the I/O thread */ - priv->bh_thread.block_thread = 0; - - /* Get the version information from the core */ - unifi_card_info(priv->card, &priv->card_info); - - /* Copy to the unifiio_card_info structure. */ - versions.chipId = priv->card_info.chip_id; - versions.chipVersion = priv->card_info.chip_version; - versions.firmwareBuild = priv->card_info.fw_build; - versions.firmwareHip = priv->card_info.fw_hip_version; - versions.routerBuild = (char*)CSR_WIFI_VERSION; - versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION; - - /* Now that new firmware is running, send a WifiOnInd to the NME. This will - * cause it to retransfer the MIB. - */ - CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions); - - /* Store the request so we know where to send the ModeSetCfm */ - priv->pending_mode_set = *req; - } - else -#endif - { - /* No patch switch, confirm straightaway */ - CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag, - req->mode, CSR_RESULT_SUCCESS); - } - - interfacePriv->bssid = req->bssid; - /* For modes other than AP/P2PGO, set below member FALSE */ - interfacePriv->intraBssEnabled = FALSE; - /* Initialise the variable bcTimSet with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - interfacePriv->bcTimSet = 0xFF; - interfacePriv->bcTimSetReqPendingFlag = FALSE; - /* Initialise the variable bcTimSetReqQueued with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - interfacePriv->bcTimSetReqQueued =0xFF; - CsrWifiRouterCtrlInterfaceReset(priv, req->interfaceTag); - - if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP || - req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) { - interfacePriv->protect = req->protection; - interfacePriv->dtimActive=FALSE; - interfacePriv->multicastPduHostTag = 0xffffffff; - /* For AP/P2PGO mode SME sending intraBssDistEnabled - * i.e. for AP: intraBssDistEnabled = TRUE, for P2PGO - * intraBssDistEnabled = TRUE/FALSE on requirement - */ - interfacePriv->intraBssEnabled = req->intraBssDistEnabled; - unifi_trace(priv, UDBG3, "CsrWifiRouterCtrlModeSetReqHandler: IntraBssDisEnabled = %d\n", - req->intraBssDistEnabled); - } else if (req->mode == CSR_WIFI_ROUTER_CTRL_MODE_NONE) { - netif_carrier_off(priv->netdev[req->interfaceTag]); - interfacePriv->connected = UnifiConnectedUnknown; - } - } - else { - unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: invalid interfaceTag :%d\n", req->interfaceTag); - } -} - -void CsrWifiRouterMaPacketResHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -} - -/* delete the station record from the station record data base */ -static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *req) -{ - u8 j; - CsrWifiRouterCtrlStaInfo_t *staInfo = NULL; - unifi_port_config_t *controlledPort; - unifi_port_config_t *unControlledPort; - netInterface_priv_t *interfacePriv; - - u8 ba_session_idx = 0; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - - /* create a list for sending confirms of un-delivered packets */ - struct list_head send_cfm_list; - - unsigned long lock_flags; - - if ((req->peerRecordHandle >= UNIFI_MAX_CONNECTIONS) || (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES)) { - unifi_error(priv, "handle/interfaceTag is not proper, handle = %d, interfaceTag = %d\n", req->peerRecordHandle, req->interfaceTag); - return CSR_RESULT_FAILURE; - } - - INIT_LIST_HEAD(&send_cfm_list); - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - /* remove the station record & make it NULL */ - if ((staInfo=interfacePriv->staInfo[req->peerRecordHandle])!=NULL) { - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - - uf_flush_list(priv, &(staInfo->mgtFrames)); - for(j=0;j<MAX_ACCESS_CATOGORY;j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->dataPdu[j])); - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* clear the port configure array info, for the corresponding peer entry */ - controlledPort = &interfacePriv->controlled_data_port; - unControlledPort = &interfacePriv->uncontrolled_data_port; - - unifi_trace(priv, UDBG1, "peer_delete_record: Peer found handle = %d, port in use: cont(%d), unCont(%d)\n", - req->peerRecordHandle, controlledPort->entries_in_use, unControlledPort->entries_in_use); - - memset(staInfo->peerControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerControlledPort->in_use = FALSE; - if (controlledPort->entries_in_use) { - controlledPort->entries_in_use--; - } else { - unifi_warning(priv, "number of controlled port entries is zero, trying to decrement: debug\n"); - } - - memset(staInfo->peerUnControlledPort, 0, sizeof(unifi_port_cfg_t)); - staInfo->peerUnControlledPort->port_action = CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD; - staInfo->peerUnControlledPort->in_use = FALSE; - if (unControlledPort->entries_in_use) { - unControlledPort->entries_in_use--; - } else { - unifi_warning(priv, "number of uncontrolled port entries is zero, trying to decrement: debug\n"); - } - - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - /* update the TIM with zero */ - if (interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS && - staInfo->timSet == CSR_WIFI_TIM_SET) { - unifi_trace(priv, UDBG3, "peer is deleted so TIM updated to 0, in firmware\n"); - update_tim(priv, staInfo->aid, 0, req->interfaceTag, req->peerRecordHandle); - } - - - /* Stop BA session if it is active, for this peer address all BA sessions - (per tID per role) are closed */ - - down(&priv->ba_mutex); - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx]; - if(ba_session_rx) { - if(!memcmp(ba_session_rx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ - blockack_session_stop(priv, - req->interfaceTag, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT, - ba_session_rx->tID, - ba_session_rx->macAddress); - } - } - } - - for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = priv->interfacePriv[req->interfaceTag]->ba_session_tx[ba_session_idx]; - if(ba_session_tx) { - if(!memcmp(ba_session_tx->macAddress.a, staInfo->peerMacAddress.a, ETH_ALEN)){ - blockack_session_stop(priv, - req->interfaceTag, - CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR, - ba_session_tx->tID, - ba_session_tx->macAddress); - } - } - } - - up(&priv->ba_mutex); - -#ifdef CSR_SUPPORT_SME - unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid); - cancel_work_sync(&staInfo->send_disconnected_ind_task); -#endif - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); -#ifdef CSR_SUPPORT_SME - interfacePriv->num_stations_joined--; - - staInfo->nullDataHostTag = INVALID_HOST_TAG; - - if ((interfacePriv->sta_activity_check_enabled) && - (interfacePriv->num_stations_joined < STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)) - { - unifi_trace(priv, UDBG1, "STOPPING the Inactivity Timer (num of stations = %d)\n", interfacePriv->num_stations_joined); - interfacePriv->sta_activity_check_enabled = FALSE; - del_timer_sync(&interfacePriv->sta_activity_check_timer); - } -#endif - - /* Free the station record for corresponding peer */ - kfree(interfacePriv->staInfo[req->peerRecordHandle]); - interfacePriv->staInfo[req->peerRecordHandle] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - /* after the critical region process the list of frames that requested cfm - and send cfm to requestor one by one */ - send_auto_ma_packet_confirm(priv, interfacePriv, &send_cfm_list); - - - } - else - { - unifi_trace(priv, UDBG3, " peer not found: Delete request Peer handle[%d]\n", req->peerRecordHandle); - } - - return CSR_RESULT_SUCCESS; -} - -void CsrWifiRouterCtrlPeerDelReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerDelReq* req = (CsrWifiRouterCtrlPeerDelReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerDelReqHandler\n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerDelReqHandler: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - /* remove the station from station record data base */ - status = peer_delete_record(priv, req); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - default: - /* No station record to maintain in these modes */ - break; - } - - CsrWifiRouterCtrlPeerDelCfmSend(msg->source, req->clientData, req->interfaceTag, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerDelReqHandler \n"); -} - -/* Add the new station to the station record data base */ -static int peer_add_new_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerAddReq *req, u32 *handle) -{ - u8 i, powerModeTemp = 0; - u8 freeSlotFound = FALSE; - CsrWifiRouterCtrlStaInfo_t *newRecord = NULL; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - u32 currentTime, currentTimeHi; - unsigned long lock_flags; - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "peer_add_new_record: bad interfaceTag\n"); - return CSR_RESULT_FAILURE; - } - - currentTime = CsrTimeGet(¤tTimeHi); - - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if(interfacePriv->staInfo[i] == NULL) { - /* Slot is empty, so can be used for station record */ - freeSlotFound = TRUE; - *handle = i; - - /* Allocate for the new station record , to avoid race condition would happen between ADD_PEER & - * DEL_PEER the allocation made atomic memory rather than kernel memory - */ - newRecord = kmalloc(sizeof(CsrWifiRouterCtrlStaInfo_t), GFP_ATOMIC); - if (!newRecord) { - unifi_error(priv, "failed to allocate the %d bytes of mem for station record\n", - sizeof(CsrWifiRouterCtrlStaInfo_t)); - return CSR_RESULT_FAILURE; - } - - unifi_trace(priv, UDBG1, "peer_add_new_record: handle = %d AID = %d addr = %x:%x:%x:%x:%x:%x LI=%u\n", - *handle, req->associationId, req->peerMacAddress.a[0], req->peerMacAddress.a[1], req->peerMacAddress.a[2], - req->peerMacAddress.a[3], req->peerMacAddress.a[4], req->peerMacAddress.a[5], - req->staInfo.listenIntervalInTus); - - /* disable the preemption until station record updated */ - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - - interfacePriv->staInfo[i] = newRecord; - /* Initialize the record*/ - memset(newRecord, 0, sizeof(CsrWifiRouterCtrlStaInfo_t)); - /* update the station record */ - memcpy(newRecord->peerMacAddress.a, req->peerMacAddress.a, ETH_ALEN); - newRecord->wmmOrQosEnabled = req->staInfo.wmmOrQosEnabled; - - /* maxSpLength is bit map in qosInfo field, so converting accordingly */ - newRecord->maxSpLength = req->staInfo.maxSpLength * 2; - - /*Max SP 0 mean any number of packets. since we buffer only 512 - packets we are hard coding this to zero for the moment */ - - if(newRecord->maxSpLength == 0) - newRecord->maxSpLength=512; - - newRecord->assignedHandle = i; - - /* copy power save mode of all access catagory (Trigger/Delivery/both enabled/disabled) */ - powerModeTemp = (u8) ((req->staInfo.powersaveMode >> 4) & 0xff); - - if(!(req->staInfo.powersaveMode & 0x0001)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BK]= powerModeTemp & 0x03; - - if(!(req->staInfo.powersaveMode & 0x0002)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_BE]= ((powerModeTemp & 0x0C)>> 2); - - if(!(req->staInfo.powersaveMode & 0x0004)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VI]= ((powerModeTemp & 0x30)>> 4); - - if(!(req->staInfo.powersaveMode & 0x0008)) - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= CSR_WIFI_AC_LEGACY_POWER_SAVE; - else - newRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]= ((powerModeTemp & 0xC0)>> 6); - - { - u8 k; - for(k=0; k< MAX_ACCESS_CATOGORY ;k++) - unifi_trace(priv, UDBG2, "peer_add_new_record: WMM : %d ,AC %d, powersaveMode %x \n", - req->staInfo.wmmOrQosEnabled, k, newRecord->powersaveMode[k]); - } - - unifi_trace(priv, UDBG3, "newRecord->wmmOrQosEnabled : %d , MAX SP : %d\n", - newRecord->wmmOrQosEnabled, newRecord->maxSpLength); - - /* Initialize the mgtFrames & data Pdu list */ - { - u8 j; - INIT_LIST_HEAD(&newRecord->mgtFrames); - for(j = 0; j < MAX_ACCESS_CATOGORY; j++) { - INIT_LIST_HEAD(&newRecord->dataPdu[j]); - } - } - - newRecord->lastActivity = currentTime; - newRecord->activity_flag = TRUE; - - /* enable the preemption as station record updated */ - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - - /* First time port actions are set for the peer with below information */ - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN, &newRecord->peerMacAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - } else { - configure_data_port(priv, CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_CLOSED_DISCARD, &newRecord->peerMacAddress, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - } - - - spin_lock_irqsave(&priv->staRecord_lock, lock_flags); - /* Port status must be already set before calling the Add Peer request */ - newRecord->peerControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, - UF_CONTROLLED_PORT_Q, req->interfaceTag); - newRecord->peerUnControlledPort = uf_sme_port_config_handle(priv, newRecord->peerMacAddress.a, - UF_UNCONTROLLED_PORT_Q, req->interfaceTag); - - if (!newRecord->peerControlledPort || !newRecord->peerUnControlledPort) { - /* enable the preemption as station record failed to update */ - unifi_warning(priv, "Un/ControlledPort record not found in port configuration array index = %d\n", i); - kfree(interfacePriv->staInfo[i]); - interfacePriv->staInfo[i] = NULL; - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - return CSR_RESULT_FAILURE; - } - - newRecord->currentPeerState = CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE; - - /* changes done during block ack handling */ - newRecord->txSuspend = FALSE; - - /*U-APSD related data structure*/ - newRecord->timRequestPendingFlag = FALSE; - - /* Initialise the variable updateTimReqQueued with a value - * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value - */ - newRecord->updateTimReqQueued = 0xFF; - newRecord->timSet = CSR_WIFI_TIM_RESET; - newRecord->uapsdActive = FALSE; - newRecord->noOfSpFramesSent =0; - newRecord->triggerFramePriority = CSR_QOS_UP0; - - /* The protection bit is updated once the port opens for corresponding peer in - * routerPortConfigure request */ - - /* update the association ID */ - newRecord->aid = req->associationId; - -#ifdef CSR_SUPPORT_SME - interfacePriv->num_stations_joined++; - newRecord->interfacePriv = interfacePriv; - newRecord->listenIntervalInTus = req->staInfo.listenIntervalInTus; - newRecord->nullDataHostTag = INVALID_HOST_TAG; - - INIT_WORK(&newRecord->send_disconnected_ind_task, uf_send_disconnected_ind_wq); - - if(!(interfacePriv->sta_activity_check_enabled) && - (interfacePriv->num_stations_joined >= STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD)){ - unifi_trace(priv, UDBG1, - "peer_add_new_record: STARTING the Inactivity Timer (num of stations = %d)", - interfacePriv->num_stations_joined); - - interfacePriv->sta_activity_check_enabled = TRUE; - interfacePriv->sta_activity_check_timer.function = check_inactivity_timer_expire_func; - interfacePriv->sta_activity_check_timer.data = (unsigned long)interfacePriv; - - init_timer(&interfacePriv->sta_activity_check_timer); - mod_timer(&interfacePriv->sta_activity_check_timer, - (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); - - } -#endif - spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags); - break; - } - } - - if(!freeSlotFound) { - unifi_error(priv, "Limited connectivity, Free slot not found for station record addition\n"); - return CSR_RESULT_FAILURE; - } - return CSR_RESULT_SUCCESS; -} - -#ifdef CSR_SUPPORT_SME -static void check_inactivity_timer_expire_func(unsigned long data) -{ - struct unifi_priv *priv; - CsrWifiRouterCtrlStaInfo_t *sta_record = NULL; - u8 i = 0; - u32 now; - u32 inactive_time; - netInterface_priv_t *interfacePriv = (netInterface_priv_t *) data; - - if (!interfacePriv) - { - return; - } - - priv = interfacePriv->privPtr; - - if (interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "check_inactivity_timer_expire_func: Invalid interfaceTag\n"); - return; - } - - /* RUN Algorithm to check inactivity for each connected station */ - now = CsrTimeGet(NULL); - - for(i = 0; i < UNIFI_MAX_CONNECTIONS; i++) { - if(interfacePriv->staInfo[i] != NULL) { - sta_record = interfacePriv->staInfo[i]; - - if (sta_record->activity_flag == TRUE){ - sta_record->activity_flag = FALSE; - sta_record->lastActivity = now; - continue; - } - - if (sta_record->lastActivity > now) - { - /* simple timer wrap (for 1 wrap) */ - inactive_time = CsrTimeAdd((u32)CsrTimeSub(CSR_SCHED_TIME_MAX, sta_record->lastActivity), now); - } - else - { - inactive_time = (u32)CsrTimeSub(now, sta_record->lastActivity); - } - - if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL) - { - unifi_trace(priv, UDBG1, "STA is Inactive - AID = %d inactive_time = %d\n", - sta_record->aid, - inactive_time); - - /* station is in-active, if it is in active mode send a null frame - * and the station should acknowledge the null frame, if acknowledgement - * is not received throw out the station. - * If the station is in Power Save, update TIM for the station so - * that it wakes up and register some activity through PS-Poll or - * trigger frame. - */ - if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE) - { - unifi_trace(priv, UDBG1, "STA power save state - Active, send a NULL frame to check if it is ALIVE\n"); - uf_send_nulldata ( priv, - sta_record->interfacePriv->InterfaceTag, - sta_record->peerMacAddress.a, - CSR_CONTENTION, - sta_record); - } - else if (sta_record->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) - { - if((sta_record->timSet == CSR_WIFI_TIM_SET) || - (sta_record->timSet == CSR_WIFI_TIM_SETTING)) - { - unifi_trace(priv, UDBG1, "STA power save state - PS, TIM is already SET\n"); - - /* If TIM is set and we do not have any activity for - * more than 3 listen intervals then send a disconnected - * indication to SME, to delete the station from station - * record list. - * The inactivity is already more than STA_INACTIVE_TIMEOUT_VAL - * and this check ensures if the listen interval is a larger - * value than STA_INACTIVE_TIMEOUT_VAL. - */ - if (inactive_time > (3 * (sta_record->listenIntervalInTus * 1024))) - { - unifi_trace(priv, UDBG1, "STA is inactive for more than 3 listen intervals\n"); - queue_work( priv->unifi_workqueue, - &sta_record->send_disconnected_ind_task); - } - - } - else - { - unifi_trace(priv, UDBG1, "STA power save state - PS, update TIM to see if it is ALIVE\n"); - update_tim(priv, - sta_record->aid, - CSR_WIFI_TIM_SET, - interfacePriv->InterfaceTag, - sta_record->assignedHandle); - } - } - } - } - } - - /* re-run the timer interrupt */ - mod_timer(&interfacePriv->sta_activity_check_timer, - (jiffies + usecs_to_jiffies(STA_INACTIVE_DETECTION_TIMER_INTERVAL * 1000 * 1000))); - -} - - -void uf_send_disconnected_ind_wq(struct work_struct *work) -{ - - CsrWifiRouterCtrlStaInfo_t *staInfo = container_of(work, CsrWifiRouterCtrlStaInfo_t, send_disconnected_ind_task); - unifi_priv_t *priv; - u16 interfaceTag; - struct list_head send_cfm_list; - u8 j; - - if(!staInfo) { - return; - } - - if(!staInfo->interfacePriv) { - return; - } - - priv = staInfo->interfacePriv->privPtr; - interfaceTag = staInfo->interfacePriv->InterfaceTag; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "uf_send_disconnected_ind_wq: invalid interfaceTag\n"); - return; - } - - /* The SME/NME may be waiting for confirmation for requested frames to this station. - * So loop through buffered frames for this station and if confirmation is - * requested, send auto confirmation with failure status. Also flush the frames so - * that these are not processed again in PEER_DEL_REQ handler. - */ - INIT_LIST_HEAD(&send_cfm_list); - - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->mgtFrames)); - - uf_flush_list(priv, &(staInfo->mgtFrames)); - - for(j = 0; j < MAX_ACCESS_CATOGORY; j++){ - uf_prepare_send_cfm_list_for_queued_pkts(priv, - &send_cfm_list, - &(staInfo->dataPdu[j])); - - uf_flush_list(priv, &(staInfo->dataPdu[j])); - } - - send_auto_ma_packet_confirm(priv, staInfo->interfacePriv, &send_cfm_list); - - unifi_warning(priv, "uf_send_disconnected_ind_wq: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n", - staInfo->peerMacAddress.a[0], - staInfo->peerMacAddress.a[1], - staInfo->peerMacAddress.a[2], - staInfo->peerMacAddress.a[3], - staInfo->peerMacAddress.a[4], - staInfo->peerMacAddress.a[5]); - - CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - staInfo->interfacePriv->InterfaceTag, - staInfo->peerMacAddress, - CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED); - - - return; -} - - -#endif -void CsrWifiRouterCtrlPeerAddReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerAddReq* req = (CsrWifiRouterCtrlPeerAddReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - u32 handle = 0; - netInterface_priv_t *interfacePriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerAddReqHandler \n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: invalid smepriv\n"); - return; - } - - if (req->interfaceTag >= CSR_WIFI_NUM_INTERFACES) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerAddReqHandler: bad interfaceTag\n"); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - switch(interfacePriv->interfaceMode) - { - case CSR_WIFI_ROUTER_CTRL_MODE_AP: - case CSR_WIFI_ROUTER_CTRL_MODE_IBSS: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PGO: - /* Add station record */ - status = peer_add_new_record(priv, req, &handle); - break; - case CSR_WIFI_ROUTER_CTRL_MODE_STA: - case CSR_WIFI_ROUTER_CTRL_MODE_P2PCLI: - default: - /* No station record to maintain in these modes */ - break; - } - - CsrWifiRouterCtrlPeerAddCfmSend(msg->source, req->clientData, req->interfaceTag, req->peerMacAddress, handle, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerAddReqHandler \n"); -} - -void CsrWifiRouterCtrlPeerUpdateReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlPeerUpdateReq* req = (CsrWifiRouterCtrlPeerUpdateReq*)msg; - CsrResult status = CSR_RESULT_SUCCESS; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG2, "entering CsrWifiRouterCtrlPeerUpdateReqHandler \n"); - if (priv == NULL) - { - unifi_error(priv, "CsrWifiRouterCtrlPeerUpdateReqHandler: invalid smepriv\n"); - return; - } - - CsrWifiRouterCtrlPeerUpdateCfmSend(msg->source, req->clientData, req->interfaceTag, status); - unifi_trace(priv, UDBG2, "leaving CsrWifiRouterCtrlPeerUpdateReqHandler \n"); -} - - - void CsrWifiRouterCtrlRawSdioDeinitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - /* This will never be called as it is intercepted in the Userspace */ -} - -void CsrWifiRouterCtrlRawSdioInitialiseReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - /* This will never be called as it is intercepted in the Userspace */ -} - -void -uf_send_ba_err_wq(struct work_struct *work) -{ - ba_session_rx_struct *ba_session = container_of(work, ba_session_rx_struct, send_ba_err_task); - unifi_priv_t *priv; - - if(!ba_session) { - return; - } - - if(!ba_session->interfacePriv) { - return; - } - - priv = ba_session->interfacePriv->privPtr; - - if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); - return; - } - - unifi_warning(priv, "%s: Calling CsrWifiRouterCtrlBlockAckErrorIndSend(%d, %d, %d, %d, %x:%x:%x:%x:%x:%x, %d)\n", - __FUNCTION__, - priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - ba_session->interfacePriv->InterfaceTag, - ba_session->tID, - ba_session->macAddress.a[0], - ba_session->macAddress.a[1], - ba_session->macAddress.a[2], - ba_session->macAddress.a[3], - ba_session->macAddress.a[4], - ba_session->macAddress.a[5], - CSR_RESULT_SUCCESS - ); - CsrWifiRouterCtrlBlockAckErrorIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, - 0, - ba_session->interfacePriv->InterfaceTag, - ba_session->tID, - ba_session->macAddress, - CSR_RESULT_SUCCESS); -} - - -static void ba_session_terminate_timer_func(unsigned long data) -{ - ba_session_rx_struct *ba_session = (ba_session_rx_struct*)data; - struct unifi_priv *priv; - - if(!ba_session) { - return; - } - - if(!ba_session->interfacePriv) { - return; - } - - priv = ba_session->interfacePriv->privPtr; - - if (ba_session->interfacePriv->InterfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: invalid interfaceTag\n", __FUNCTION__); - return; - } - - queue_work(priv->unifi_workqueue, &ba_session->send_ba_err_task); -} - - -u8 blockack_session_stop(unifi_priv_t *priv, - u16 interfaceTag, - CsrWifiRouterCtrlBlockAckRole role, - u16 tID, - CsrWifiMacAddress macAddress) -{ - netInterface_priv_t *interfacePriv; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - u8 ba_session_idx = 0; - int i; - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); - return FALSE; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if(!interfacePriv) { - unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); - return FALSE; - } - - if(tID > 15) { - unifi_error(priv, "%s: bad tID = %d\n", __FUNCTION__, tID); - return FALSE; - } - - if((role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR) && - (role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT)) { - unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); - return FALSE; - } - - unifi_warning(priv, - "%s: stopping ba_session for peer = %pM role = %d tID = %d\n", - __func__, macAddress.a, role, tID); - - /* find out the appropriate ba session (/station /tid /role) for which stop is requested */ - if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - - ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; - - if(ba_session_rx){ - if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ - break; - } - } - } - - if (!ba_session_rx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX)) { - unifi_error(priv, "%s: bad ba_session for Rx [tID=%d]\n", __FUNCTION__, tID); - return FALSE; - } - - - if(ba_session_rx->timeout) { - del_timer_sync(&ba_session_rx->timer); - } - cancel_work_sync(&ba_session_rx->send_ba_err_task); - for (i = 0; i < ba_session_rx->wind_size; i++) { - if(ba_session_rx->buffer[i].active) { - frame_desc_struct *frame_desc = &ba_session_rx->buffer[i]; - unifi_net_data_free(priv, &frame_desc->bulkdata.d[0]); - } - } - kfree(ba_session_rx->buffer); - - interfacePriv->ba_session_rx[ba_session_idx] = NULL; - kfree(ba_session_rx); - }else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; - if(ba_session_tx){ - if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ - break; - } - } - } - - if (!ba_session_tx || (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX)) { - unifi_error(priv, "%s: bad ba_session for Tx [tID=%d]\n", __FUNCTION__, tID); - return FALSE; - } - interfacePriv->ba_session_tx[ba_session_idx] = NULL; - kfree(ba_session_tx); - - } - - return TRUE; -} - - -void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlBlockAckDisableReq* req = (CsrWifiRouterCtrlBlockAckDisableReq*)msg; - u8 r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__); - - down(&priv->ba_mutex); - r = blockack_session_stop(priv, - req->interfaceTag, - req->role, - req->trafficStreamID, - req->macAddress); - up(&priv->ba_mutex); - - CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source, - req->clientData, - req->interfaceTag, - r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); - - unifi_trace(priv, UDBG6, "%s: out ok\n", __FUNCTION__); -} - - -u8 blockack_session_start(unifi_priv_t *priv, - u16 interfaceTag, - u16 tID, - u16 timeout, - CsrWifiRouterCtrlBlockAckRole role, - u16 wind_size, - u16 start_sn, - CsrWifiMacAddress macAddress - ) -{ - netInterface_priv_t *interfacePriv; - ba_session_rx_struct *ba_session_rx = NULL; - ba_session_tx_struct *ba_session_tx = NULL; - u8 ba_session_idx = 0; - - - if (interfaceTag >= CSR_WIFI_NUM_INTERFACES) { - unifi_error(priv, "%s: bad interfaceTag = %d\n", __FUNCTION__, interfaceTag); - return FALSE; - } - - interfacePriv = priv->interfacePriv[interfaceTag]; - - if(!interfacePriv) { - unifi_error(priv, "%s: bad interfacePriv\n", __FUNCTION__); - return FALSE; - } - - if(tID > 15) - { - unifi_error(priv, "%s: bad tID=%d\n", __FUNCTION__, tID); - return FALSE; - } - - if(wind_size > MAX_BA_WIND_SIZE) { - unifi_error(priv, "%s: bad wind_size = %d\n", __FUNCTION__, wind_size); - return FALSE; - } - - if(role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR && - role != CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT) { - unifi_error(priv, "%s: bad role = %d\n", __FUNCTION__, role); - return FALSE; - } - - unifi_warning(priv, - "%s: ba session with peer= (%pM)\n", __func__, - macAddress.a); - - unifi_warning(priv, "%s: ba session for tID=%d timeout=%d role=%d wind_size=%d start_sn=%d\n", __FUNCTION__, - tID, - timeout, - role, - wind_size, - start_sn); - - /* Check if BA session exists for per station, per TID, per role or not. - if BA session exists update parameters and if it does not exist - create a new BA session */ - if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ORIGINATOR){ - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX; ba_session_idx++){ - ba_session_tx = interfacePriv->ba_session_tx[ba_session_idx]; - if (ba_session_tx) { - if ((!memcmp(ba_session_tx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_tx->tID == tID)){ - unifi_warning(priv, "%s: ba_session for Tx already exists\n", __FUNCTION__); - return TRUE; - } - } - } - - /* we have to create new ba_session_tx struct */ - ba_session_tx = NULL; - - /* loop through until an empty BA session slot is there and save the session there */ - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_TX ; ba_session_idx++){ - if (!(interfacePriv->ba_session_tx[ba_session_idx])){ - break; - } - } - if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_TX){ - unifi_error(priv, "%s: All ba_session used for Tx, NO free session available\n", __FUNCTION__); - return FALSE; - } - - /* create and populate the new BA session structure */ - ba_session_tx = kzalloc(sizeof(ba_session_tx_struct), GFP_KERNEL); - if (!ba_session_tx) { - unifi_error(priv, "%s: kmalloc failed for ba_session_tx\n", __FUNCTION__); - return FALSE; - } - - ba_session_tx->interfacePriv = interfacePriv; - ba_session_tx->tID = tID; - ba_session_tx->macAddress = macAddress; - - interfacePriv->ba_session_tx[ba_session_idx] = ba_session_tx; - - } else if (role == CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_RECIPIENT){ - - for (ba_session_idx =0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){ - ba_session_rx = interfacePriv->ba_session_rx[ba_session_idx]; - if (ba_session_rx) { - if ((!memcmp(ba_session_rx->macAddress.a, macAddress.a, ETH_ALEN)) && (ba_session_rx->tID == tID)){ - unifi_warning(priv, "%s: ba_session for Rx[tID = %d] already exists\n", __FUNCTION__, tID); - - if(ba_session_rx->wind_size == wind_size && - ba_session_rx->timeout == timeout && - ba_session_rx->expected_sn == start_sn) { - return TRUE; - } - - if(ba_session_rx->timeout) { - del_timer_sync(&ba_session_rx->timer); - ba_session_rx->timeout = 0; - } - - if(ba_session_rx->wind_size != wind_size) { - blockack_session_stop(priv, interfaceTag, role, tID, macAddress); - } else { - if (timeout) { - ba_session_rx->timeout = timeout; - ba_session_rx->timer.function = ba_session_terminate_timer_func; - ba_session_rx->timer.data = (unsigned long)ba_session_rx; - init_timer(&ba_session_rx->timer); - mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); - } - /* - * The starting sequence number shall remain same if the BA - * enable request is issued to update BA parameters only. If - * it is not same, then we scroll our window to the new starting - * sequence number. This could happen if the DELBA frame from - * originator is lost and then we receive ADDBA frame with new SSN. - */ - if(ba_session_rx->start_sn != start_sn) { - scroll_ba_window(priv, interfacePriv, ba_session_rx, start_sn); - } - return TRUE; - } - } - } - } - - /* we could have a valid BA session pointer here or un-initialized - ba session pointer. but in any case we have to create a new session. - so re-initialize the ba_session pointer */ - ba_session_rx = NULL; - - /* loop through until an empty BA session slot is there and save the session there */ - for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX ; ba_session_idx++){ - if (!(interfacePriv->ba_session_rx[ba_session_idx])){ - break; - } - } - if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){ - unifi_error(priv, "%s: All ba_session used for Rx, NO free session available\n", __FUNCTION__); - return FALSE; - } - - /* It is observed that with some devices there is a race between - * EAPOL exchanges and BA session establishment. This results in - * some EAPOL authentication packets getting stuck in BA reorder - * buffer and hence the conection cannot be established. To avoid - * this we check here if the EAPOL authentication is complete and - * if so then only allow the BA session to establish. - * - * It is verified that the peers normally re-establish - * the BA session after the initial rejection. - */ - if (CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN != uf_sme_port_state(priv, macAddress.a, UF_CONTROLLED_PORT_Q, interfacePriv->InterfaceTag)) - { - unifi_warning(priv, "blockack_session_start: Controlled port not opened, Reject BA request\n"); - return FALSE; - } - - ba_session_rx = kzalloc(sizeof(ba_session_rx_struct), GFP_KERNEL); - if (!ba_session_rx) { - unifi_error(priv, "%s: kmalloc failed for ba_session_rx\n", __FUNCTION__); - return FALSE; - } - - ba_session_rx->wind_size = wind_size; - ba_session_rx->start_sn = ba_session_rx->expected_sn = start_sn; - ba_session_rx->trigger_ba_after_ssn = FALSE; - - ba_session_rx->buffer = kzalloc(ba_session_rx->wind_size*sizeof(frame_desc_struct), GFP_KERNEL); - if (!ba_session_rx->buffer) { - kfree(ba_session_rx); - unifi_error(priv, "%s: kmalloc failed for buffer\n", __FUNCTION__); - return FALSE; - } - - INIT_WORK(&ba_session_rx->send_ba_err_task, uf_send_ba_err_wq); - if (timeout) { - ba_session_rx->timeout = timeout; - ba_session_rx->timer.function = ba_session_terminate_timer_func; - ba_session_rx->timer.data = (unsigned long)ba_session_rx; - init_timer(&ba_session_rx->timer); - mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024))); - } - - ba_session_rx->interfacePriv = interfacePriv; - ba_session_rx->tID = tID; - ba_session_rx->macAddress = macAddress; - - interfacePriv->ba_session_rx[ba_session_idx] = ba_session_rx; - } - return TRUE; -} - -void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ - CsrWifiRouterCtrlBlockAckEnableReq* req = (CsrWifiRouterCtrlBlockAckEnableReq*)msg; - u8 r; - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - down(&priv->ba_mutex); - r = blockack_session_start(priv, - req->interfaceTag, - req->trafficStreamID, - req->timeout, - req->role, - req->bufferSize, - req->ssn, - req->macAddress - ); - up(&priv->ba_mutex); - - CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source, - req->clientData, - req->interfaceTag, - r?CSR_RESULT_SUCCESS:CSR_RESULT_FAILURE); - unifi_trace(priv, UDBG6, "<<%s: r=%d\n", __FUNCTION__, r); - -} - -void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status); - - /* status 1 - Filter on - * status 0 - Filter off */ - priv->wapi_multicast_filter = req->status; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastFilterReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status); - - if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) { - /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */ - priv->wapi_unicast_queued_pkt_filter = 1; - } - - /* status 1 - Filter ON - * status 0 - Filter OFF */ - priv->wapi_unicast_filter = req->status; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastFilterReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiRxPktReq* req = (CsrWifiRouterCtrlWapiRxPktReq*)msg; - int client_id, receiver_id; - bulk_data_param_t bulkdata; - CsrResult res; - ul_client_t *client; - CSR_SIGNAL signal; - CSR_MA_PACKET_INDICATION *pkt_ind; - netInterface_priv_t *interfacePriv; - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid priv\n", __func__); - return; - } - - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid sme priv\n", __func__); - return; - } - - interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - - if (req->dataLength == 0 || req->data == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: invalid request\n", __FUNCTION__); - return; - } - - res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); - if (res != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: Could not allocate net data\n", __FUNCTION__); - return; - } - - /* This function is expected to be called only when the MIC has been verified by SME to be correct - * So reset the reception status to rx_success */ - res = read_unpack_signal(req->signal, &signal); - if (res) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: Received unknown or corrupted signal.\n"); - return; - } - pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication); - if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) { - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: Unknown signal with reception status = %d\n", pkt_ind->ReceptionStatus); - return; - } else { - unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiRxPktReqHandler: MIC verified , RX_SUCCESS \n", __FUNCTION__); - pkt_ind->ReceptionStatus = CSR_RX_SUCCESS; - write_pack(&signal, req->signal, &(req->signalLength)); - } - - memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); - - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(s16)) & 0xFFF0; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; - - client = &priv->ul_clients[client_id]; - - if (client && client->event_hook) { - unifi_trace(priv, UDBG3, - "CsrWifiRouterCtrlWapiRxPktReq: " - "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n", - client->client_id, client->sender_id, receiver_id, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal)); - - client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST); - } else { - unifi_trace(priv, UDBG4, "No client to give the packet to\n"); - unifi_net_data_free(priv, &bulkdata.d[0]); - } - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReqHandler: called when WAPI isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) - - unifi_priv_t *priv = (unifi_priv_t*) drvpriv; - CsrWifiRouterCtrlWapiUnicastTxPktReq *req = (CsrWifiRouterCtrlWapiUnicastTxPktReq*) msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - bulk_data_param_t bulkdata; - u8 macHeaderLengthInBytes = MAC_HEADER_SIZE; - /*KeyID, Reserved, PN, MIC*/ - u8 appendedCryptoFields = 1 + 1 + 16 + 16; - CsrResult result; - /* Retrieve the MA PACKET REQ fields from the Signal retained from send_ma_pkt_request() */ - CSR_MA_PACKET_REQUEST *storedSignalMAPktReq = &interfacePriv->wapi_unicast_ma_pkt_sig.u.MaPacketRequest; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - if (priv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid priv\n", __FUNCTION__); - return; - } - if (priv->smepriv == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid sme priv\n", __FUNCTION__); - return; - } - if (req->data == NULL) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid request\n", __FUNCTION__); - return; - } else { - /* If it is QoS data (type = data subtype = QoS), frame header contains QoS control field */ - if ((req->data[0] & 0x88) == 0x88) { - macHeaderLengthInBytes = macHeaderLengthInBytes + QOS_CONTROL_HEADER_SIZE; - } - } - if ( !(req->dataLength>(macHeaderLengthInBytes+appendedCryptoFields)) ) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid dataLength\n", __FUNCTION__); - return; - } - - /* Encrypted DATA Packet contained in (req->data) - * ------------------------------------------------------------------- - * |MAC Header| KeyId | Reserved | PN | xxDataxx | xxMICxxx | - * ------------------------------------------------------------------- - * (<-----Encrypted----->) - * ------------------------------------------------------------------- - * |24/26(QoS)| 1 | 1 | 16 | x | 16 | - * ------------------------------------------------------------------- - */ - result = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength); - if (result != CSR_RESULT_SUCCESS) { - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: Could not allocate net data\n", __FUNCTION__); - return; - } - memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength); - bulkdata.d[0].data_length = req->dataLength; - bulkdata.d[1].os_data_ptr = NULL; - bulkdata.d[1].data_length = 0; - - /* Send UniFi msg */ - /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */ - result = uf_process_ma_packet_req(priv, - storedSignalMAPktReq->Ra.x, - storedSignalMAPktReq->HostTag,/* Ask for a new HostTag */ - req->interfaceTag, - storedSignalMAPktReq->TransmissionControl, - storedSignalMAPktReq->TransmitRate, - storedSignalMAPktReq->Priority, /* Retained value */ - interfacePriv->wapi_unicast_ma_pkt_sig.SignalPrimitiveHeader.SenderProcessId, /*FIXME AP: VALIDATE ???*/ - &bulkdata); - - if (result == NETDEV_TX_OK) { - (priv->netdev[req->interfaceTag])->trans_start = jiffies; - /* Should really count tx stats in the UNITDATA.status signal but - * that doesn't have the length. - */ - interfacePriv->stats.tx_packets++; - - /* count only the packet payload */ - interfacePriv->stats.tx_bytes += req->dataLength - macHeaderLengthInBytes - appendedCryptoFields; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Sent), sent count = %x\n", interfacePriv->stats.tx_packets); - } else { - /* Failed to send: fh queue was full, and the skb was discarded*/ - unifi_trace(priv, UDBG1, "(HIP validation failure) Result = %d\n", result); - unifi_net_data_free(priv, &bulkdata.d[0]); - - interfacePriv->stats.tx_dropped++; - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped); - } - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: called when WAPI SW ENCRYPTION isn't enabled\n"); -#endif -} - -void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg) -{ -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - -#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - CsrWifiRouterCtrlWapiFilterReq* req = (CsrWifiRouterCtrlWapiFilterReq*)msg; - netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag]; - - if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) { - - unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__); - - unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiFilterReq: req->isWapiConnected [0/1] = %d \n", req->isWapiConnected); - - priv->isWapiConnection = req->isWapiConnected; - - unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__); - } else { - - unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__, interfacePriv->interfaceMode); - - } -#endif - -#elif defined(UNIFI_DEBUG) - /*WAPI Disabled*/ - unifi_priv_t *priv = (unifi_priv_t*)drvpriv; - unifi_error(priv, "CsrWifiRouterCtrlWapiFilterReq: called when WAPI isn't enabled\n"); -#endif -} |