343 lines · c
1/*2 * Copyright (c) 2013 Eugene Krasnikov <k.eugene.e@gmail.com>3 *4 * Permission to use, copy, modify, and/or distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16 17#ifndef _WCN36XX_H_18#define _WCN36XX_H_19 20#include <linux/completion.h>21#include <linux/in6.h>22#include <linux/printk.h>23#include <linux/spinlock.h>24#include <net/mac80211.h>25 26#include "hal.h"27#include "smd.h"28#include "txrx.h"29#include "dxe.h"30#include "pmc.h"31#include "debug.h"32 33#define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"34#define WCN36XX_AGGR_BUFFER_SIZE 6435 36extern unsigned int wcn36xx_dbg_mask;37 38enum wcn36xx_debug_mask {39 WCN36XX_DBG_DXE = 0x00000001,40 WCN36XX_DBG_DXE_DUMP = 0x00000002,41 WCN36XX_DBG_SMD = 0x00000004,42 WCN36XX_DBG_SMD_DUMP = 0x00000008,43 WCN36XX_DBG_RX = 0x00000010,44 WCN36XX_DBG_RX_DUMP = 0x00000020,45 WCN36XX_DBG_TX = 0x00000040,46 WCN36XX_DBG_TX_DUMP = 0x00000080,47 WCN36XX_DBG_HAL = 0x00000100,48 WCN36XX_DBG_HAL_DUMP = 0x00000200,49 WCN36XX_DBG_MAC = 0x00000400,50 WCN36XX_DBG_BEACON = 0x00000800,51 WCN36XX_DBG_BEACON_DUMP = 0x00001000,52 WCN36XX_DBG_PMC = 0x00002000,53 WCN36XX_DBG_PMC_DUMP = 0x00004000,54 WCN36XX_DBG_TESTMODE = 0x00008000,55 WCN36XX_DBG_TESTMODE_DUMP = 0x00010000,56 WCN36XX_DBG_ANY = 0xffffffff,57};58 59#define wcn36xx_err(fmt, arg...) \60 printk(KERN_ERR pr_fmt("ERROR " fmt), ##arg)61 62#define wcn36xx_warn(fmt, arg...) \63 printk(KERN_WARNING pr_fmt("WARNING " fmt), ##arg)64 65#define wcn36xx_info(fmt, arg...) \66 printk(KERN_INFO pr_fmt(fmt), ##arg)67 68#define wcn36xx_dbg(mask, fmt, arg...) do { \69 if (wcn36xx_dbg_mask & mask) \70 printk(KERN_DEBUG pr_fmt(fmt), ##arg); \71} while (0)72 73#define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do { \74 if (wcn36xx_dbg_mask & mask) \75 print_hex_dump(KERN_DEBUG, pr_fmt(prefix_str), \76 DUMP_PREFIX_OFFSET, 32, 1, \77 buf, len, false); \78} while (0)79 80enum wcn36xx_ampdu_state {81 WCN36XX_AMPDU_NONE,82 WCN36XX_AMPDU_INIT,83 WCN36XX_AMPDU_START,84 WCN36XX_AMPDU_OPERATIONAL,85};86 87#define HW_VALUE_PHY_SHIFT 888#define HW_VALUE_PHY(hw_value) ((hw_value) >> HW_VALUE_PHY_SHIFT)89#define HW_VALUE_CHANNEL(hw_value) ((hw_value) & 0xFF)90#define WCN36XX_HW_CHANNEL(__wcn)\91 HW_VALUE_CHANNEL(__wcn->hw->conf.chandef.chan->hw_value)92#define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band)93#define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq)94#define WCN36XX_LISTEN_INTERVAL(__wcn) (__wcn->hw->conf.listen_interval)95#define WCN36XX_FLAGS(__wcn) (__wcn->hw->flags)96#define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power)97 98#define RF_UNKNOWN 0x000099#define RF_IRIS_WCN3620 0x3620100#define RF_IRIS_WCN3660 0x3660101#define RF_IRIS_WCN3680 0x3680102 103static inline void buff_to_be(void *buf, size_t len)104{105 __be32 *to = buf;106 u32 *from = buf;107 int i;108 109 for (i = 0; i < len; i++)110 to[i] = cpu_to_be32(from[i]);111}112 113struct nv_data {114 int is_valid;115 u8 table;116};117 118/**119 * struct wcn36xx_vif - holds VIF related fields120 *121 * @bss_index: bss_index is initially set to 0xFF. bss_index is received from122 * HW after first config_bss call and must be used in delete_bss and123 * enter/exit_bmps.124 */125struct wcn36xx_vif {126 struct list_head list;127 u8 dtim_period;128 enum ani_ed_type encrypt_type;129 bool is_joining;130 bool sta_assoc;131 struct wcn36xx_hal_mac_ssid ssid;132 enum wcn36xx_hal_bss_type bss_type;133 134 /* Power management */135 enum wcn36xx_power_state pw_state;136 137 u8 bss_index;138 /* Returned from WCN36XX_HAL_ADD_STA_SELF_RSP */139 u8 self_sta_index;140 u8 self_dpu_desc_index;141 u8 self_ucast_dpu_sign;142 143#if IS_ENABLED(CONFIG_IPV6)144 /* IPv6 addresses for WoWLAN */145 struct in6_addr target_ipv6_addrs[WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX];146 unsigned long tentative_addrs[BITS_TO_LONGS(WCN36XX_HAL_IPV6_OFFLOAD_ADDR_MAX)];147 int num_target_ipv6_addrs;148#endif149 /* WoWLAN GTK rekey data */150 struct {151 u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];152 __le64 replay_ctr;153 bool valid;154 } rekey_data;155 156 struct list_head sta_list;157 158 int bmps_fail_ct;159};160 161/**162 * struct wcn36xx_sta - holds STA related fields163 *164 * @tid: traffic ID that is used during AMPDU and in TX BD.165 * @sta_index: STA index is returned from HW after config_sta call and is166 * used in both SMD channel and TX BD.167 * @dpu_desc_index: DPU descriptor index is returned from HW after config_sta168 * call and is used in TX BD.169 * @bss_sta_index: STA index is returned from HW after config_bss call and is170 * used in both SMD channel and TX BD. See table bellow when it is used.171 * @bss_dpu_desc_index: DPU descriptor index is returned from HW after172 * config_bss call and is used in TX BD.173 * ______________________________________________174 * | | STA | AP |175 * |______________|_____________|_______________|176 * | TX BD |bss_sta_index| sta_index |177 * |______________|_____________|_______________|178 * |all SMD calls |bss_sta_index| sta_index |179 * |______________|_____________|_______________|180 * |smd_delete_sta| sta_index | sta_index |181 * |______________|_____________|_______________|182 */183struct wcn36xx_sta {184 struct list_head list;185 struct wcn36xx_vif *vif;186 u16 aid;187 u16 tid;188 u8 sta_index;189 u8 dpu_desc_index;190 u8 ucast_dpu_sign;191 u8 bss_sta_index;192 u8 bss_dpu_desc_index;193 bool is_data_encrypted;194 /* Rates */195 struct wcn36xx_hal_supported_rates_v1 supported_rates;196 197 spinlock_t ampdu_lock; /* protects next two fields */198 enum wcn36xx_ampdu_state ampdu_state[16];199 int non_agg_frame_ct;200};201 202struct wcn36xx_dxe_ch;203 204struct wcn36xx_chan_survey {205 s8 rssi;206 u8 snr;207};208 209struct wcn36xx {210 struct ieee80211_hw *hw;211 struct device *dev;212 struct list_head vif_list;213 214 const char *nv_file;215 const struct firmware *nv;216 217 u8 fw_revision;218 u8 fw_version;219 u8 fw_minor;220 u8 fw_major;221 u32 fw_feat_caps[WCN36XX_HAL_CAPS_SIZE];222 bool is_pronto;223 bool is_pronto_v3;224 225 /* extra byte for the NULL termination */226 u8 crm_version[WCN36XX_HAL_VERSION_LENGTH + 1];227 u8 wlan_version[WCN36XX_HAL_VERSION_LENGTH + 1];228 229 bool first_boot;230 231 /* IRQs */232 int tx_irq;233 int rx_irq;234 void __iomem *ccu_base;235 void __iomem *dxe_base;236 237 struct rpmsg_endpoint *smd_channel;238 239 struct qcom_smem_state *tx_enable_state;240 unsigned tx_enable_state_bit;241 struct qcom_smem_state *tx_rings_empty_state;242 unsigned tx_rings_empty_state_bit;243 244 /* prevents concurrent FW reconfiguration */245 struct mutex conf_mutex;246 247 /*248 * smd_buf must be protected with smd_mutex to garantee249 * that all messages are sent one after another250 */251 u8 *hal_buf;252 size_t hal_rsp_len;253 struct mutex hal_mutex;254 struct completion hal_rsp_compl;255 struct workqueue_struct *hal_ind_wq;256 struct work_struct hal_ind_work;257 spinlock_t hal_ind_lock;258 struct list_head hal_ind_queue;259 260 struct cfg80211_scan_request *scan_req;261 bool sw_scan;262 u8 sw_scan_opchannel;263 bool sw_scan_init;264 u8 sw_scan_channel;265 struct ieee80211_vif *sw_scan_vif;266 struct mutex scan_lock;267 bool scan_aborted;268 269 /* DXE channels */270 struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */271 struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */272 struct wcn36xx_dxe_ch dxe_rx_l_ch; /* RX low */273 struct wcn36xx_dxe_ch dxe_rx_h_ch; /* RX high */274 275 /* For synchronization of DXE resources from BH, IRQ and WQ contexts */276 spinlock_t dxe_lock;277 bool queues_stopped;278 279 /* Memory pools */280 struct wcn36xx_dxe_mem_pool mgmt_mem_pool;281 struct wcn36xx_dxe_mem_pool data_mem_pool;282 283 struct sk_buff *tx_ack_skb;284 struct timer_list tx_ack_timer;285 286 /* For A-MSDU re-aggregation */287 struct sk_buff_head amsdu;288 289 /* RF module */290 unsigned rf_id;291 292#ifdef CONFIG_WCN36XX_DEBUGFS293 /* Debug file system entry */294 struct wcn36xx_dfs_entry dfs;295#endif /* CONFIG_WCN36XX_DEBUGFS */296 297 struct ieee80211_supported_band *band;298 struct ieee80211_channel *channel;299 300 spinlock_t survey_lock; /* protects chan_survey */301 struct wcn36xx_chan_survey *chan_survey;302};303 304static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,305 u8 major,306 u8 minor,307 u8 version,308 u8 revision)309{310 return (wcn->fw_major == major &&311 wcn->fw_minor == minor &&312 wcn->fw_version == version &&313 wcn->fw_revision == revision);314}315void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates);316void wcn36xx_set_default_rates_v1(struct wcn36xx_hal_supported_rates_v1 *rates);317 318static inline319struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)320{321 return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv);322}323 324static inline325struct wcn36xx_vif *wcn36xx_vif_to_priv(struct ieee80211_vif *vif)326{327 return (struct wcn36xx_vif *) vif->drv_priv;328}329 330static inline331struct ieee80211_vif *wcn36xx_priv_to_vif(struct wcn36xx_vif *vif_priv)332{333 return container_of((void *) vif_priv, struct ieee80211_vif, drv_priv);334}335 336static inline337struct wcn36xx_sta *wcn36xx_sta_to_priv(struct ieee80211_sta *sta)338{339 return (struct wcn36xx_sta *)sta->drv_priv;340}341 342#endif /* _WCN36XX_H_ */343