/* ***************************************************************************** * * FILE : unifi_priv.h * * PURPOSE : Private header file for unifi driver. * * UDI = UniFi Debug Interface * * Copyright (C) 2005-2009 by Cambridge Silicon Radio Ltd. * * Refer to LICENSE.txt included with this source code for details on * the license terms. * ***************************************************************************** */ #ifndef __LINUX_UNIFI_PRIV_H__ #define __LINUX_UNIFI_PRIV_H__ 1 #include <linux/module.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/netdevice.h> #include <linux/wireless.h> #include <linux/cdev.h> #include <linux/kthread.h> #include <linux/freezer.h> #ifdef CSR_WIFI_SUPPORT_MMC_DRIVER #include <linux/mmc/core.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> #include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_ids.h> #include <linux/mmc/sdio.h> #endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ #include <linux/fs.h> #ifdef ANDROID_BUILD #include <linux/wakelock.h> #endif #include "csr_wifi_hip_unifi.h" #include "csr_wifi_hip_unifi_udi.h" #include "csr_wifi_router_lib.h" #include "unifiio.h" #ifndef CSR_WIFI_HIP_TA_DISABLE #include "csr_wifi_vif_utils.h" #endif /* Define the unifi_priv_t before include the unifi_native.h */ struct unifi_priv; typedef struct unifi_priv unifi_priv_t; #ifdef CSR_SUPPORT_WEXT_AP struct CsrWifiSmeApConfig; typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t; #endif #ifdef CSR_SUPPORT_WEXT #include "unifi_wext.h" #endif #ifdef ANDROID_BUILD extern struct wake_lock unifi_sdio_wake_lock; #endif #include "unifi_clients.h" #ifdef CSR_NATIVE_LINUX #include "sme_native/unifi_native.h" #else #include "unifi_sme.h" #endif /* The device major number to use when registering the udi driver */ #define UNIFI_NAME "unifi" /* * MAX_UNIFI_DEVS defines the maximum number of UniFi devices that can be present. * This number should be set to the number of SDIO slots supported by the SDIO * host controller on the platform. * Note: If MAX_UNIFI_DEVS value changes, fw_init[] needs to be corrected in drv.c */ #define MAX_UNIFI_DEVS 2 /* 802.11 Mac header offsets */ #define MAC_HEADER_SIZE 24 #define QOS_CONTROL_HEADER_SIZE 2 #define HT_CONTROL_HEADER_SIZE 4 #define QOS_DATA 0x8 #define QOS_DATA_NULL 0xc #define DATA_NULL 0x04 #define FRAME_CONTROL_ORDER_BIT 0x8000 #define FRAME_CONTROL_TYPE_FIELD_OFFSET 2 #define FRAME_CONTROL_SUBTYPE_FIELD_OFFSET 4 #define IEEE802_11_FRAMETYPE_DATA 0x02 #define IEEE802_11_FRAMETYPE_CONTROL 0x01 #define IEEE802_11_FRAMETYPE_MANAGEMENT 0x00 #define IEEE802_11_FRAMETYPE_RESERVED 0x03 /* octet offset from start of mac header for certain fields */ #define IEEE802_11_ADDR3_OFFSET 16 #define IEEE802_11_SEQUENCE_CONTROL_OFFSET 22 #define IEEE802_11_MAX_DATA_LEN 2304 /* frame control (FC) masks, for frame control as 16 bit integer */ #define IEEE802_11_FC_TO_DS_MASK 0x100 #define IEEE802_11_FC_FROM_DS_MASK 0x200 #define IEEE802_11_FC_MOREDATA_MASK 0x2000 #define IEEE802_11_FC_PROTECTED_MASK 0x4000 #define IEEE80211_FC_ORDER_MASK 0x8000 #define IEEE80211_FC_SUBTYPE_MASK 0x00f0 #define IEEE80211_FC_TYPE_MASK 0x000c #define IEEE80211_FC_PROTO_VERSION_MASK 0x0003 /* selected type and subtype combinations as in 7.1.3.1 table 1 For frame control as 16 bit integer, or for ls octet */ #define IEEE802_11_FC_TYPE_DATA 0x08 #define IEEE802_11_FC_TYPE_NULL 0x48 #define IEEE802_11_FC_TYPE_QOS_NULL 0xc8 #define IEEE802_11_FC_TYPE_QOS_DATA 0x88 #define IEEE802_11_FC_TYPE_DATA_SUBTYPE_RESERVED 0x0D /* qos control (QC) masks for qos control as 16 bit integer, or for ls octet */ #define IEEE802_11_QC_TID_MASK 0x0f #define IEEE802_11_QC_A_MSDU_PRESENT 0x80 #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND)) #define IEEE802_11_QC_NON_TID_BITS_MASK 0xFFF0 #endif #define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36 #define MAX_ACCESS_CATOGORY 4 /* Time in us to check for inactivity of stations 5 mins */ #define INACTIVITY_CHECK_INTERVAL 300000000 /* Time in us before a station is flagged as inactive */ #define MAX_INACTIVITY_INTERVAL 300000000 /* Define for maximum BA session */ #define MAX_SUPPORTED_BA_SESSIONS_TX 1 #define MAX_SUPPORTED_BA_SESSIONS_RX 4 #define MAX_BA_WIND_SIZE 64 #define MAC_HEADER_ADDR1_OFFSET 4 #define MAC_HEADER_ADDR2_OFFSET 10 /* Define for age (in us) value for frames in MPDU reorder buffer */ #define CSR_WIFI_BA_MPDU_FRAME_AGE_TIMEOUT 30000 /* 30 milli seconds */ /* This macro used in prepare_and_add_macheader*/ #define ADDRESS_ONE_OFFSET 20 /* Defines for STA inactivity detection */ #define STA_INACTIVE_DETECTION_TRIGGER_THRESHOLD 1 /* in number of stations */ #define STA_INACTIVE_DETECTION_TIMER_INTERVAL 30 /* in seconds */ #define STA_INACTIVE_TIMEOUT_VAL 120*1000*1000 /* 120 seconds */ /* Test for modes requiring AP firmware patch */ #define CSR_WIFI_HIP_IS_AP_FW(mode) ((((mode) == CSR_WIFI_ROUTER_CTRL_MODE_AP) || \ ((mode) == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) ? TRUE : FALSE) /* Defines used in beacon filtering in case of P2P */ #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH 0x7 #define CSR_WIFI_80211_FRAME_SUBTYPE_BEACON 0x8 #define CSR_WIFI_BEACON_FIXED_LENGTH 12 #define CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET 4 #define CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK ((u8)(0xF << CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET)) #define CSR_WIFI_80211_GET_FRAME_SUBTYPE(frameBuffer) \ ((u8)(((u8 *)frameBuffer)[0] & CSR_WIFI_80211_FRAME_SUBTYPE_BIT_MASK) >> CSR_WIFI_FRAME_SUBTYPE_BIT_OFFSET) /* For M4 request received via netdev*/ typedef u8 CsrWifiPacketType; #define CSR_WIFI_UNICAST_PDU ((CsrWifiPacketType) 0x00) #define CSR_WIFI_MULTICAST_PDU ((CsrWifiPacketType) 0x1) #define CSR_WIFI_BROADCAST_PDU ((CsrWifiPacketType) 0x2) #define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) /* Module parameter variables */ extern int buswidth; extern int sdio_clock; extern int use_5g; extern int disable_hw_reset; extern int disable_power_control; extern int enable_wol; extern int sme_debug; extern int fw_init[MAX_UNIFI_DEVS]; extern int tl_80211d; extern int sdio_byte_mode; extern int sdio_block_size; extern int coredump_max; extern int run_bh_once; extern int bh_priority; #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE extern int log_hip_signals; #endif struct dlpriv { const unsigned char *dl_data; int dl_len; void *fw_desc; }; struct uf_thread { struct task_struct *thread_task; /* wait_queue for waking the unifi_thread kernel thread */ wait_queue_head_t wakeup_q; unsigned int wakeup_flag; /* * Use it to block the I/O thread when * an error occurs or UniFi is reinitialised. */ int block_thread; char name[16]; int prio; }; /* * Link list to hold the received packets for the period the port * remains closed. */ typedef struct rx_buffered_packets { /* List link structure */ struct list_head q; /* Packet to indicate when the port reopens */ struct sk_buff *skb; /* Bulkdata to free in case the port closes and need to discard the packet */ bulk_data_param_t bulkdata; /* The source address of the packet */ CsrWifiMacAddress sa; /* The destination address of the packet */ CsrWifiMacAddress da; /* Corresponding signal */ CSR_SIGNAL signal; } rx_buffered_packets_t; typedef u8 CsrWifiAcPowersaveMode; #define CSR_WIFI_AC_TRIGGER_ONLY_ENABLED 0x00 #define CSR_WIFI_AC_DELIVERY_ONLY_ENABLE 0X01 #define CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED 0X03 #define CSR_WIFI_AC_LEGACY_POWER_SAVE 0X02 #define IS_DELIVERY_ENABLED(mode) (mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)? 1: 0 #define IS_DELIVERY_AND_TRIGGER_ENABLED(mode) ((mode & CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)||(mode & CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))? 1: 0 #define IS_DTIM_ACTIVE(flag,hostTag) ((flag == TRUE || hostTag != INVALID_HOST_TAG)) #define INVALID_HOST_TAG 0xFFFFFFFF #define UNIFI_TRAFFIC_Q_CONTENTION UNIFI_TRAFFIC_Q_BE /* Queue to be used for contention priority */ /* * Link list to hold the tx packets for the period the peer * powersave/free slots in unifi */ typedef struct tx_buffered_packets { /* List link structure */ struct list_head q; u16 interfaceTag; CSR_CLIENT_TAG hostTag; CSR_PROCESS_ID leSenderProcessId; CSR_TRANSMISSION_CONTROL transmissionControl; CSR_RATE rate; /* Bulkdata to free in case the port closes and need to discard the packet */ bulk_data_desc_t bulkdata; /* The source address of the packet */ CsrWifiMacAddress peerMacAddress; CSR_PRIORITY priority; } tx_buffered_packets_t; /* station record has this data structure */ typedef struct CsrWifiRouterCtrlStaInfo_t { /* Sme sends these parameters */ CsrWifiMacAddress peerMacAddress; u32 assignedHandle; u8 wmmOrQosEnabled; CsrWifiAcPowersaveMode powersaveMode[MAX_ACCESS_CATOGORY]; u16 maxSpLength; u8 uapsdActive; u16 noOfSpFramesSent; /* Router/Driver database */ #ifdef CSR_SUPPORT_SME unifi_port_cfg_t *peerControlledPort; unifi_port_cfg_t *peerUnControlledPort; /* Inactivity feature parameters */ struct netInterface_priv *interfacePriv; struct work_struct send_disconnected_ind_task; u8 activity_flag; u16 listenIntervalInTus; CSR_CLIENT_TAG nullDataHostTag; /* Activity timestamps for the station */ u32 lastActivity; /* during m/c transmission sp suspended */ u8 uspSuspend; CSR_PRIORITY triggerFramePriority; #endif CsrWifiRouterCtrlPeerStatus currentPeerState; struct list_head dataPdu[MAX_ACCESS_CATOGORY]; struct list_head mgtFrames; u8 spStatus; u8 prevFrmType; u8 prevFrmAccessCatogory; u8 protection; u16 aid; u8 txSuspend; u8 timSet; /* Dont change the value of below macro for SET & RESET */ #define CSR_WIFI_TIM_RESET 0 #define CSR_WIFI_TIM_SET 1 #define CSR_WIFI_TIM_RESETTING 2 #define CSR_WIFI_TIM_SETTING 3 u8 timRequestPendingFlag; u8 updateTimReqQueued; u16 noOfPktQueued; }CsrWifiRouterCtrlStaInfo_t; #ifdef CSR_SUPPORT_WEXT_AP struct CsrWifiSmeApConfig { CsrWifiSsid ssid; u16 channel; CsrWifiNmeApCredentials credentials; u8 max_connections; u8 if_index; }; #endif #ifdef CSR_WIFI_RX_PATH_SPLIT /* This is a test code and may be removed later*/ #define CSR_WIFI_RX_SIGNAL_BUFFER_SIZE (60+1) typedef struct { u8 *bufptr; /* Signal Primitive */ bulk_data_param_t data_ptrs; /* Bulk Data pointers */ u16 sig_len; }rx_buff_struct_t; typedef struct { u8 writePointer; /**< write pointer */ u8 readPointer; /**< read pointer */ u8 size; /**< size of circular buffer */ rx_buff_struct_t rx_buff[CSR_WIFI_RX_SIGNAL_BUFFER_SIZE]; /**< Element of ciruclar buffer */ } rxCircularBuffer_t; void rx_wq_handler(struct work_struct *work); #endif struct unifi_priv { card_t *card; CsrSdioFunction *sdio; /* Index into Unifi_instances[] for this device. */ int instance; /* Reference count for this instance */ int ref_count; /* Firmware images */ struct dlpriv fw_sta; struct dlpriv fw_conv; /* used for conversion of production test image */ /* Char device related structures */ struct cdev unifi_cdev; struct cdev unifiudi_cdev; struct device *unifi_device; /* Which wireless interface to use (1 - 2.4GHz, 2 - 5GHz) */ CSR_IFINTERFACE if_index; /* For multiple interface support */ struct net_device *netdev[CSR_WIFI_NUM_INTERFACES]; struct netInterface_priv *interfacePriv[CSR_WIFI_NUM_INTERFACES]; u8 totalInterfaceCount; int prev_queue; /* Name of node under /proc */ char proc_entry_name[64]; /* * Flags: * drop_unencrypted * - Not used? * netdev_registered * - whether the netdev has been registered. */ unsigned int drop_unencrypted : 1; /* Our list of unifi linux clients. */ ul_client_t ul_clients[MAX_UDI_CLIENTS]; /* Mutex to protect using the logging hook after UDI client is gone */ struct semaphore udi_logging_mutex; /* Pointer to the ul_clients[] array */ ul_client_t *logging_client; /* A ul_client_t* used to send the netdev related MIB requests. */ ul_client_t *netdev_client; /* The SME ul_client_t pointer. */ ul_client_t *sme_cli; /* The AMP ul_client_t pointer. */ ul_client_t *amp_client; /* * Semaphore for locking the top-half to one user process. * This is necessary to prevent multiple processes calling driver * operations. This can happen because the network driver entry points * can be called from multiple processes. */ #ifdef USE_DRIVER_LOCK struct semaphore lock; #endif /* USE_DRIVER_LOCK */ /* Flag to say that an operation was aborted */ int io_aborted; struct uf_thread bh_thread; #define UNIFI_INIT_NONE 0x00 #define UNIFI_INIT_IN_PROGRESS 0x01 #define UNIFI_INIT_FW_DOWNLOADED 0x02 #define UNIFI_INIT_COMPLETED 0x04 unsigned char init_progress; int sme_is_present; /* The WMM features that UniFi uses in the current BSS */ unsigned int sta_wmm_capabilities; /* Debug only */ char last_debug_string[256]; unsigned short last_debug_word16[16]; #ifdef CSR_SUPPORT_SME /* lock to protect the tx queues list */ spinlock_t tx_q_lock; u8 allPeerDozing; u8 pausedStaHandle[MAX_ACCESS_CATOGORY]; /* Max packet the driver can queue, irrespective of interface number */ u16 noOfPktQueuedInDriver; #define CSR_WIFI_DRIVER_SUPPORT_FOR_MAX_PKT_QUEUEING 512 #define CSR_WIFI_DRIVER_MAX_PKT_QUEUING_THRESHOLD_PER_PEER 64 #define CSR_WIFI_DRIVER_MINIMUM_BROADCAST_PKT_THRESHOLD 3 u8 routerBufferEnable[MAX_ACCESS_CATOGORY]; /* lock to protect stainfo members and priv members*/ spinlock_t staRecord_lock; #endif #ifdef CSR_NATIVE_LINUX #ifdef CSR_SUPPORT_WEXT /* wireless config */ struct wext_config wext_conf; #endif /* Mutex to protect the MLME blocking requests */ struct semaphore mlme_blocking_mutex; /* The ul_client that provides the blocking API for WEXT calls */ ul_client_t *wext_client; #endif /* CSR_NATIVE_LINUX */ #ifdef CSR_SUPPORT_SME wait_queue_head_t sme_request_wq; /* Semaphore to protect the SME blocking requests */ struct semaphore sme_sem; /* Structure to hold the SME blocking requests data*/ sme_reply_t sme_reply; /* Structure to hold a traffic protocol indication */ struct ta_ind { struct work_struct task; CsrWifiRouterCtrlTrafficPacketType packet_type; CsrWifiRouterCtrlProtocolDirection direction; CsrWifiMacAddress src_addr; int in_use; } ta_ind_work; struct ta_sample_ind { struct work_struct task; CsrWifiRouterCtrlTrafficStats stats; int in_use; } ta_sample_ind_work; __be32 sta_ip_address; CsrWifiRouterCtrlSmeVersions sme_versions; /* * Flag to reflect state of unifi_sys_wifi_on_*() progress. * This indicates whether we are in an "wifi on" state when we are * allowed to indication errors with unifi_mgt_wifi_off_ind() */ enum { wifi_on_unspecified = -1, wifi_on_in_progress = 0, wifi_on_done = 1, } wifi_on_state; /* Userspace TaskId for the SME Set when a wifi on req is received */ CsrSchedQid CSR_WIFI_SME_IFACEQUEUE; struct work_struct multicast_list_task; /* * The SME installs filters to ask for specific MA-UNITDATA.req * to be passed to different SME components. */ #define MAX_MA_UNIDATA_IND_FILTERS 8 sme_ma_unidata_ind_filter_t sme_unidata_ind_filters[MAX_MA_UNIDATA_IND_FILTERS]; /* UNIFI_CFG related parameters */ uf_cfg_bcast_packet_filter_t packet_filters; unsigned char *filter_tclas_ies; /* The structure that holds all the connection configuration. */ CsrWifiSmeConnectionConfig connection_config; #ifdef CSR_SUPPORT_WEXT int ignore_bssid_join; struct iw_statistics wext_wireless_stats; /* The MIB and MAC address files contents, read from userspace */ CsrWifiSmeDataBlock mib_data; CsrWifiMacAddress sta_mac_address; int wep_tx_key_index; wep_key_t wep_keys[NUM_WEPKEYS]; #ifdef CSR_SUPPORT_WEXT_AP CsrWifiSmeApMacConfig ap_mac_config; CsrWifiNmeApConfig group_sec_config; CsrWifiSmeApConfig_t ap_config; #endif struct work_struct sme_config_task; #endif /* CSR_SUPPORT_WEXT */ #endif /* CSR_SUPPORT_SME */ #ifdef CSR_SME_USERSPACE void *smepriv; #endif /* CSR_SME_USERSPACE */ card_info_t card_info; /* Mutex to protect unifi_send_signal() */ spinlock_t send_signal_lock; /* * The workqueue to offload the TA run * and the multicast addresses list set */ struct workqueue_struct *unifi_workqueue; unsigned char *mib_cfm_buffer; unsigned int mib_cfm_buffer_length; int ptest_mode; /* Set when in production test mode */ int coredump_mode; /* Set when SME has requested a coredump */ u8 wol_suspend; /* Set when suspending with UniFi powered */ #define UF_UNCONTROLLED_PORT_Q 0 #define UF_CONTROLLED_PORT_Q 1 /* Semaphore to protect the rx queues list */ struct semaphore rx_q_sem; /* Spinlock to protect M4 data */ spinlock_t m4_lock; /* Mutex to protect BA RX data */ struct semaphore ba_mutex; #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) /* Spinlock to protect the WAPI data */ spinlock_t wapi_lock; #endif /* Array to indicate if a particular Tx queue is paused, this may not be * required in a multiqueue implementation since we can directly stop kernel * queues */ u8 tx_q_paused_flag[UNIFI_TRAFFIC_Q_MAX]; #ifdef CSR_WIFI_RX_PATH_SPLIT struct workqueue_struct *rx_workqueue; struct work_struct rx_work_struct; rxCircularBuffer_t rxSignalBuffer; #endif u32 rxTcpThroughput; u32 txTcpThroughput; u32 rxUdpThroughput; u32 txUdpThroughput; #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE /*Set if multicast KeyID = 1*/ u8 wapi_multicast_filter; /*Set if unicast KeyID = 1*/ u8 wapi_unicast_filter; u8 wapi_unicast_queued_pkt_filter; #ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND u8 isWapiConnection; #endif #endif #ifdef CSR_WIFI_SPLIT_PATCH CsrWifiRouterCtrlModeSetReq pending_mode_set; #endif u8 cmanrTestMode; CSR_RATE cmanrTestModeTransmitRate; }; typedef struct { u16 queue_length[4]; u8 os_queue_paused; } unifi_OsQosInfo; typedef struct { u8 active; bulk_data_param_t bulkdata; CSR_SIGNAL signal; u16 sn; u32 recv_time; } frame_desc_struct; typedef struct { frame_desc_struct *buffer; u16 wind_size; u16 occupied_slots; struct timer_list timer; u16 timeout; u16 expected_sn; u16 start_sn; u8 trigger_ba_after_ssn; struct netInterface_priv *interfacePriv; u16 tID; CsrWifiMacAddress macAddress; struct work_struct send_ba_err_task; } ba_session_rx_struct; typedef struct { struct netInterface_priv *interfacePriv; u16 tID; CsrWifiMacAddress macAddress; } ba_session_tx_struct; typedef struct netInterface_priv { u16 InterfaceTag; struct unifi_priv *privPtr; ba_session_tx_struct *ba_session_tx[MAX_SUPPORTED_BA_SESSIONS_TX]; ba_session_rx_struct *ba_session_rx[MAX_SUPPORTED_BA_SESSIONS_RX]; frame_desc_struct ba_complete[MAX_BA_WIND_SIZE]; u8 ba_complete_index; u8 queueEnabled[UNIFI_NO_OF_TX_QS]; struct work_struct send_m4_ready_task; #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE struct work_struct send_pkt_to_encrypt; #endif struct net_device_stats stats; u8 interfaceMode; u8 protect; CsrWifiMacAddress bssid; /* * Flag to reflect state of CONNECTED indication signal. * This indicates whether we are "joined" an Access Point (i.e. have * nominated an AP and are receiving beacons) but give no indication * of whether we are authenticated and/or associated. */ enum { UnifiConnectedUnknown = -1, UnifiNotConnected = 0, UnifiConnected = 1, } connected; #ifdef CSR_SUPPORT_WEXT /* Tracks when we are waiting for a netdevice state change callback */ u8 wait_netdev_change; /* True if we have successfully registered for netdev callbacks */ u8 netdev_callback_registered; #endif /* CSR_SUPPORT_WEXT */ unsigned int netdev_registered; #define UNIFI_MAX_MULTICAST_ADDRESSES 10 /* The multicast addresses list that the thread needs to set. */ u8 mc_list[UNIFI_MAX_MULTICAST_ADDRESSES*ETH_ALEN]; /* The multicast addresses count that the thread needs to set. */ int mc_list_count; u32 tag; #ifdef CSR_SUPPORT_SME /* (un)controlled port configuration */ unifi_port_config_t controlled_data_port; unifi_port_config_t uncontrolled_data_port; /* station record maintenance related data structures */ u8 num_stations_joined; CsrWifiRouterCtrlStaInfo_t *(staInfo)[UNIFI_MAX_CONNECTIONS]; struct list_head genericMgtFrames; struct list_head genericMulticastOrBroadCastFrames; struct list_head genericMulticastOrBroadCastMgtFrames; /* Timer for detecting station inactivity */ struct timer_list sta_activity_check_timer; u8 sta_activity_check_enabled; /* Timestamp when the last inactivity check was done */ u32 last_inactivity_check; /*number of multicast or borad cast packets queued*/ u16 noOfbroadcastPktQueued; #endif /* A list to hold the buffered uncontrolled port packets */ struct list_head rx_uncontrolled_list; /* A list to hold the buffered controlled port packets */ struct list_head rx_controlled_list; /* Buffered M4 signal to take care of WPA race condition */ CSR_SIGNAL m4_signal; bulk_data_desc_t m4_bulk_data; #if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION)) /* Buffered WAPI Unicast MA Packet Request for encryption in Sme */ CSR_SIGNAL wapi_unicast_ma_pkt_sig; bulk_data_desc_t wapi_unicast_bulk_data; #endif /* This should be removed and m4_hostTag should be used for checking*/ u8 m4_sent; CSR_CLIENT_TAG m4_hostTag; u8 dtimActive; u8 intraBssEnabled; u32 multicastPduHostTag; /* Used to set the tim after getting a confirm for it */ u8 bcTimSet; u8 bcTimSetReqPendingFlag; u8 bcTimSetReqQueued; } netInterface_priv_t; #ifdef CSR_SUPPORT_SME #define routerStartBuffering(priv,queue) priv->routerBufferEnable[(queue)] = TRUE; #define routerStopBuffering(priv,queue) priv->routerBufferEnable[(queue)] = FALSE; #define isRouterBufferEnabled(priv,queue) priv->routerBufferEnable[(queue)] #endif #ifdef USE_DRIVER_LOCK #define LOCK_DRIVER(_p) down_interruptible(&(_p)->lock) #define UNLOCK_DRIVER(_p) up(&(_p)->lock) #else #define LOCK_DRIVER(_p) (void)(_p); /* as nothing */ #define UNLOCK_DRIVER(_p) (void)(_p); /* as nothing */ #endif /* USE_DRIVER_LOCK */ s32 CsrHipResultToStatus(CsrResult csrResult); /* * SDIO related functions and callbacks */ int uf_sdio_load(void); void uf_sdio_unload(void); unifi_priv_t *uf_find_instance(int inst); int uf_find_priv(unifi_priv_t *priv); int uf_find_netdev_priv(netInterface_priv_t *priv); unifi_priv_t *uf_get_instance(int inst); void uf_put_instance(int inst); int csr_sdio_linux_install_irq(CsrSdioFunction *sdio); int csr_sdio_linux_remove_irq(CsrSdioFunction *sdio); void uf_add_os_device(int bus_id, struct device *os_device); void uf_remove_os_device(int bus_id); /* * Claim/release SDIO * * For multifunction cards, we cannot grub the SDIO lock around the unifi_bh() * as this prevents other functions using SDIO. * Since some of CSR SDIO API is used regardless of trying to lock unifi_bh() * we have followed this scheme: * 1. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is defined * then we call CsrSdioClaim/CsrSdioRelease(). * 2. If a function needs protection only when CSR_WIFI_SINGLE_FUNCTION is not defined * then we call _sdio_claim_host/_sdio_claim_host(). Use of this should be restricted * to the SDIO glue layer only (e.g. sdio_mmc.c). * 3. If a function needs protection, regardless of the CSR_WIFI_SINGLE_FUNCTION * then we call directly the sdio_claim_host/sdio_release_host(). * Use of this must be restricted to the SDIO glue layer only (e.g. sdio_mmc.c). * * Note: The _func and function pointers are _not_ the same. * The former is the (struct sdio_func*) context, which restricts the use to the SDIO glue layer. * The latter is the (CsrSdioFunction*) context, which allows calls from all layers. */ #ifdef CSR_WIFI_SUPPORT_MMC_DRIVER #ifdef CSR_WIFI_SINGLE_FUNCTION #define CsrSdioClaim(function) sdio_claim_host((function)->priv); #define CsrSdioRelease(function) sdio_release_host((function)->priv); #define _sdio_claim_host(_func) #define _sdio_release_host(_func) #else #define CsrSdioClaim(function) #define CsrSdioRelease(function) #define _sdio_claim_host(_func) sdio_claim_host(_func) #define _sdio_release_host(_func) sdio_release_host(_func) #endif /* CSR_WIFI_SINGLE_FUNCTION */ #else #define _sdio_claim_host(_func) #define _sdio_release_host(_func) #define CsrSdioClaim(function) #define CsrSdioRelease(function) #endif /* CSR_WIFI_SUPPORT_MMC_DRIVER */ /* * Functions to allocate and free an ethernet device. */ unifi_priv_t *uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id); int uf_free_netdevice(unifi_priv_t *priv); /* Allocating function for other interfaces */ u8 uf_alloc_netdevice_for_other_interfaces(unifi_priv_t *priv, u16 interfaceTag); /* * Firmware download related functions. */ int uf_run_unifihelper(unifi_priv_t *priv); int uf_request_firmware_files(unifi_priv_t *priv, int is_fw); int uf_release_firmware_files(unifi_priv_t *priv); int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free); /* * Functions to create and delete the device nodes. */ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id); void uf_destroy_device_nodes(unifi_priv_t *priv); /* * Upper Edge Initialisation functions */ int uf_init_bh(unifi_priv_t *priv); int uf_init_hw(unifi_priv_t *priv); /* Thread related helper functions */ int uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *)); void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread); void uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread); /* * Unifi Linux functions */ void ul_init_clients(unifi_priv_t *priv); /* Configuration flags */ #define CLI_USING_WIRE_FORMAT 0x0002 #define CLI_SME_USERSPACE 0x0020 ul_client_t *ul_register_client(unifi_priv_t *priv, unsigned int configuration, udi_event_t udi_event_clbk); int ul_deregister_client(ul_client_t *pcli); int ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr, bulk_data_param_t *bulkdata); int ul_send_signal_raw(unifi_priv_t *priv, unsigned char *sigptr, int siglen, bulk_data_param_t *bulkdata); void ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len); /* * Data plane operations */ /* * data_tx.c */ int uf_verify_m4(unifi_priv_t *priv, const unsigned char *packet, unsigned int length); #ifdef CSR_SUPPORT_SME u8 uf_check_broadcast_bssid(unifi_priv_t *priv, const bulk_data_param_t *bulkdata); u8 uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo,u8 pmBit,u16 interfaceTag); void uf_process_ps_poll(unifi_priv_t *priv,u8* sa,u8* da,u8 pmBit,u16 interfaceTag); int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb, struct ethhdr *ehdr, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, const CSR_SIGNAL *signal, bulk_data_param_t *bulkdata, u8 macHeaderLengthInBytes); u8 uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord); void uf_process_wmm_deliver_ac_uapsd ( unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t * srcStaInfo, u16 qosControl, u16 interfaceTag); void uf_send_buffered_data_from_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, u8 queue, struct list_head *txList); void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo, u8 queue, struct list_head *txList); void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo); void uf_send_qos_null(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); void uf_send_nulldata(unifi_priv_t * priv,u16 interfaceTag, const u8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo); #endif CsrResult uf_process_ma_packet_req(unifi_priv_t *priv, u8 *peerMacAddress, CSR_CLIENT_TAG hostTag, u16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, CSR_RATE TransmitRate, CSR_PRIORITY priority, CSR_PROCESS_ID senderId, bulk_data_param_t *bulkdata); void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,u8 *sigdata, u32 siglen); #ifdef CSR_SUPPORT_SME void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue queue); int uf_process_station_records_for_sending_data(unifi_priv_t *priv,u16 interfaceTag, CsrWifiRouterCtrlStaInfo_t *srcStaInfo, CsrWifiRouterCtrlStaInfo_t *dstStaInfo); void uf_prepare_send_cfm_list_for_queued_pkts(unifi_priv_t * priv, struct list_head *frames_need_cfm_list, struct list_head * list); void send_auto_ma_packet_confirm(unifi_priv_t *priv, netInterface_priv_t *interfacePriv, struct list_head *buffered_frames_list); void uf_flush_list(unifi_priv_t * priv, struct list_head * list); tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList); void resume_unicast_buffered_frames(unifi_priv_t *priv, u16 interfaceTag); void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,u16 interfaceTag); void resume_suspended_uapsd(unifi_priv_t* priv,u16 interfaceTag); #endif /* * netdev.c */ #ifndef P80211_OUI_LEN #define P80211_OUI_LEN 3 #endif typedef struct { u8 dsap; /* always 0xAA */ u8 ssap; /* always 0xAA */ u8 ctrl; /* always 0x03 */ u8 oui[P80211_OUI_LEN]; /* organizational universal id */ u16 protocol; } __attribute__ ((packed)) llc_snap_hdr_t; int skb_add_llc_snap(struct net_device *dev, struct sk_buff *skb, int proto); int skb_80211_to_ether(unifi_priv_t *priv, struct sk_buff *skb, const unsigned char *daddr, const unsigned char *saddr, const CSR_SIGNAL *signal, bulk_data_param_t *bulkdata); const char *result_code_str(int result); /* prepares & appends the Mac header for the payload */ int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk_buff *newSkb, CSR_PRIORITY priority, bulk_data_param_t *bulkdata, u16 interfaceTag, const u8 *daddr, const u8 *saddr, u8 protection); CSR_PRIORITY get_packet_priority(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr *ehdr, netInterface_priv_t *interfacePriv); void unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority, CSR_RATE TransmitRate, CSR_CLIENT_TAG hostTag, u16 interfaceTag, CSR_TRANSMISSION_CONTROL transmissionControl, CSR_PROCESS_ID leSenderProcessId, u8 *peerMacAddress, CSR_SIGNAL *signal); /* Pack the LSB to include station handle & status of tim set */ #define CSR_WIFI_PACK_SENDER_ID_LSB_FOR_TIM_REQ(handle, timState) ((handle << 2) | timState) /* get the station record handle from the sender ID */ #define CSR_WIFI_GET_STATION_HANDLE_FROM_RECEIVER_ID(receiverProcessId) (u8) ((receiverProcessId & 0xff) >> 2) /* get the timSet status from the sender ID */ #define CSR_WIFI_GET_TIMSET_STATE_FROM_RECEIVER_ID(receiverProcessId) (u8) (receiverProcessId & 0x03) /* handle is 6 bits to accomodate in senderId LSB (only 64 station can be associated) */ #define CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE 0x3F void update_tim(unifi_priv_t * priv, u16 aid, u8 setTim, u16 interfaceTag, u32 handle); void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, u16 senderProcessId); /* Clear the Peer station Record, in case of wifioff/unexpected card removal */ void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, u16 interfaceTag); void scroll_ba_window(unifi_priv_t *priv, netInterface_priv_t *interfacePriv, ba_session_rx_struct *ba_session, u16 sn); u8 blockack_session_stop(unifi_priv_t *priv, u16 interfaceTag, CsrWifiRouterCtrlBlockAckRole role, u16 tID, CsrWifiMacAddress macAddress); #ifdef CSR_SUPPORT_SME /* Fetch the protection information from interface Mode */ s8 uf_get_protection_bit_from_interfacemode(unifi_priv_t *priv, u16 interfaceTag, const u8 *daddr); #endif /* Fetch the station record handler from data base for matching Mac address */ #ifdef CSR_SUPPORT_SME CsrWifiRouterCtrlStaInfo_t *CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(unifi_priv_t *priv, const u8 *peerMacAddress, u16 interfaceTag); /* Fetch the station record handler from data base for matching handle */ CsrWifiRouterCtrlStaInfo_t * CsrWifiRouterCtrlGetStationRecordFromHandle(unifi_priv_t *priv, u32 handle, u16 interfaceTag); void uf_update_sta_activity(unifi_priv_t *priv, u16 interfaceTag, const u8 *peerMacAddress); void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,u16 interfaceTag, const CSR_MA_PACKET_CONFIRM *pkt_cfm); #endif void uf_resume_data_plane(unifi_priv_t *priv, int queue, CsrWifiMacAddress peer_address, u16 interfaceTag); void uf_free_pending_rx_packets(unifi_priv_t *priv, int queue, CsrWifiMacAddress peer_address,u16 interfaceTag); int uf_register_netdev(unifi_priv_t *priv, int numOfInterface); void uf_unregister_netdev(unifi_priv_t *priv); void uf_net_get_name(struct net_device *dev, char *name, int len); void uf_send_queue_info(unifi_priv_t *priv); u16 uf_get_vif_identifier(CsrWifiRouterCtrlMode mode, u16 tag); void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue, CsrWifiMacAddress source_address, int indicate, u16 interfaceTag); #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE int uf_register_hip_offline_debug(unifi_priv_t *priv); int uf_unregister_hip_offline_debug(unifi_priv_t *priv); #endif /* * inet.c */ void uf_register_inet_notifier(void); void uf_unregister_inet_notifier(void); /* * Suspend / Resume handlers */ void unifi_resume(void *ospriv); void unifi_suspend(void *ospriv); #define QOS_CAPABILITY_WMM_ENABLED 0x0001 #define QOS_CAPABILITY_WMM_UAPSD 0x0002 #define QOS_CAPABILITY_ACM_BE_ENABLED 0x0010 #define QOS_CAPABILITY_ACM_BK_ENABLED 0x0020 #define QOS_CAPABILITY_ACM_VI_ENABLED 0x0040 #define QOS_CAPABILITY_ACM_VO_ENABLED 0x0080 #define QOS_CAPABILITY_TS_BE_ENABLED 0x0100 #define QOS_CAPABILITY_TS_BK_ENABLED 0x0200 #define QOS_CAPABILITY_TS_VI_ENABLED 0x0400 #define QOS_CAPABILITY_TS_VO_ENABLED 0x0800 /* EAPOL PDUS */ #ifndef ETH_P_PAE #define ETH_P_PAE 0x888e #endif #ifndef ETH_P_WAI #define ETH_P_WAI 0x88b4 #endif /* * unifi_dbg.c */ void debug_string_indication(unifi_priv_t *priv, const unsigned char *extra, unsigned int extralen); void debug_word16_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); void debug_generic_indication(unifi_priv_t *priv, const CSR_SIGNAL *sigptr); /* * putest.c */ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg); int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg); #endif /* __LINUX_UNIFI_PRIV_H__ */