162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Common private data for ST-Ericsson CW1200 drivers 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010, ST-Ericsson 662306a36Sopenharmony_ci * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on the mac80211 Prism54 code, which is 962306a36Sopenharmony_ci * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Based on the islsm (softmac prism54) driver, which is: 1262306a36Sopenharmony_ci * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#ifndef CW1200_H 1662306a36Sopenharmony_ci#define CW1200_H 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <linux/wait.h> 1962306a36Sopenharmony_ci#include <linux/mutex.h> 2062306a36Sopenharmony_ci#include <linux/workqueue.h> 2162306a36Sopenharmony_ci#include <net/mac80211.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "queue.h" 2462306a36Sopenharmony_ci#include "wsm.h" 2562306a36Sopenharmony_ci#include "scan.h" 2662306a36Sopenharmony_ci#include "txrx.h" 2762306a36Sopenharmony_ci#include "pm.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Forward declarations */ 3062306a36Sopenharmony_cistruct hwbus_ops; 3162306a36Sopenharmony_cistruct task_struct; 3262306a36Sopenharmony_cistruct cw1200_debug_priv; 3362306a36Sopenharmony_cistruct firmware; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define CW1200_MAX_CTRL_FRAME_LEN (0x1000) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define CW1200_MAX_STA_IN_AP_MODE (5) 3862306a36Sopenharmony_ci#define CW1200_LINK_ID_AFTER_DTIM (CW1200_MAX_STA_IN_AP_MODE + 1) 3962306a36Sopenharmony_ci#define CW1200_LINK_ID_UAPSD (CW1200_MAX_STA_IN_AP_MODE + 2) 4062306a36Sopenharmony_ci#define CW1200_LINK_ID_MAX (CW1200_MAX_STA_IN_AP_MODE + 3) 4162306a36Sopenharmony_ci#define CW1200_MAX_REQUEUE_ATTEMPTS (5) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define CW1200_MAX_TID (8) 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define CW1200_BLOCK_ACK_CNT (30) 4662306a36Sopenharmony_ci#define CW1200_BLOCK_ACK_THLD (800) 4762306a36Sopenharmony_ci#define CW1200_BLOCK_ACK_HIST (3) 4862306a36Sopenharmony_ci#define CW1200_BLOCK_ACK_INTERVAL (1 * HZ / CW1200_BLOCK_ACK_HIST) 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#define CW1200_JOIN_TIMEOUT (1 * HZ) 5162306a36Sopenharmony_ci#define CW1200_AUTH_TIMEOUT (5 * HZ) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct cw1200_ht_info { 5462306a36Sopenharmony_ci struct ieee80211_sta_ht_cap ht_cap; 5562306a36Sopenharmony_ci enum nl80211_channel_type channel_type; 5662306a36Sopenharmony_ci u16 operation_mode; 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* Please keep order */ 6062306a36Sopenharmony_cienum cw1200_join_status { 6162306a36Sopenharmony_ci CW1200_JOIN_STATUS_PASSIVE = 0, 6262306a36Sopenharmony_ci CW1200_JOIN_STATUS_MONITOR, 6362306a36Sopenharmony_ci CW1200_JOIN_STATUS_JOINING, 6462306a36Sopenharmony_ci CW1200_JOIN_STATUS_PRE_STA, 6562306a36Sopenharmony_ci CW1200_JOIN_STATUS_STA, 6662306a36Sopenharmony_ci CW1200_JOIN_STATUS_IBSS, 6762306a36Sopenharmony_ci CW1200_JOIN_STATUS_AP, 6862306a36Sopenharmony_ci}; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cienum cw1200_link_status { 7162306a36Sopenharmony_ci CW1200_LINK_OFF, 7262306a36Sopenharmony_ci CW1200_LINK_RESERVE, 7362306a36Sopenharmony_ci CW1200_LINK_SOFT, 7462306a36Sopenharmony_ci CW1200_LINK_HARD, 7562306a36Sopenharmony_ci CW1200_LINK_RESET, 7662306a36Sopenharmony_ci CW1200_LINK_RESET_REMAP, 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciextern int cw1200_power_mode; 8062306a36Sopenharmony_ciextern const char * const cw1200_fw_types[]; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct cw1200_link_entry { 8362306a36Sopenharmony_ci unsigned long timestamp; 8462306a36Sopenharmony_ci enum cw1200_link_status status; 8562306a36Sopenharmony_ci enum cw1200_link_status prev_status; 8662306a36Sopenharmony_ci u8 mac[ETH_ALEN]; 8762306a36Sopenharmony_ci u8 buffered[CW1200_MAX_TID]; 8862306a36Sopenharmony_ci struct sk_buff_head rx_queue; 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistruct cw1200_common { 9262306a36Sopenharmony_ci /* interfaces to the rest of the stack */ 9362306a36Sopenharmony_ci struct ieee80211_hw *hw; 9462306a36Sopenharmony_ci struct ieee80211_vif *vif; 9562306a36Sopenharmony_ci struct device *pdev; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* Statistics */ 9862306a36Sopenharmony_ci struct ieee80211_low_level_stats stats; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Our macaddr */ 10162306a36Sopenharmony_ci u8 mac_addr[ETH_ALEN]; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* Hardware interface */ 10462306a36Sopenharmony_ci const struct hwbus_ops *hwbus_ops; 10562306a36Sopenharmony_ci struct hwbus_priv *hwbus_priv; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* Hardware information */ 10862306a36Sopenharmony_ci enum { 10962306a36Sopenharmony_ci HIF_9000_SILICON_VERSATILE = 0, 11062306a36Sopenharmony_ci HIF_8601_VERSATILE, 11162306a36Sopenharmony_ci HIF_8601_SILICON, 11262306a36Sopenharmony_ci } hw_type; 11362306a36Sopenharmony_ci enum { 11462306a36Sopenharmony_ci CW1200_HW_REV_CUT10 = 10, 11562306a36Sopenharmony_ci CW1200_HW_REV_CUT11 = 11, 11662306a36Sopenharmony_ci CW1200_HW_REV_CUT20 = 20, 11762306a36Sopenharmony_ci CW1200_HW_REV_CUT22 = 22, 11862306a36Sopenharmony_ci CW1X60_HW_REV = 40, 11962306a36Sopenharmony_ci } hw_revision; 12062306a36Sopenharmony_ci int hw_refclk; 12162306a36Sopenharmony_ci bool hw_have_5ghz; 12262306a36Sopenharmony_ci const struct firmware *sdd; 12362306a36Sopenharmony_ci char *sdd_path; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci struct cw1200_debug_priv *debug; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci struct workqueue_struct *workqueue; 12862306a36Sopenharmony_ci struct mutex conf_mutex; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci struct cw1200_queue tx_queue[4]; 13162306a36Sopenharmony_ci struct cw1200_queue_stats tx_queue_stats; 13262306a36Sopenharmony_ci int tx_burst_idx; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci /* firmware/hardware info */ 13562306a36Sopenharmony_ci unsigned int tx_hdr_len; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Radio data */ 13862306a36Sopenharmony_ci int output_power; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* BBP/MAC state */ 14162306a36Sopenharmony_ci struct ieee80211_rate *rates; 14262306a36Sopenharmony_ci struct ieee80211_rate *mcs_rates; 14362306a36Sopenharmony_ci struct ieee80211_channel *channel; 14462306a36Sopenharmony_ci struct wsm_edca_params edca; 14562306a36Sopenharmony_ci struct wsm_tx_queue_params tx_queue_params; 14662306a36Sopenharmony_ci struct wsm_mib_association_mode association_mode; 14762306a36Sopenharmony_ci struct wsm_set_bss_params bss_params; 14862306a36Sopenharmony_ci struct cw1200_ht_info ht_info; 14962306a36Sopenharmony_ci struct wsm_set_pm powersave_mode; 15062306a36Sopenharmony_ci struct wsm_set_pm firmware_ps_mode; 15162306a36Sopenharmony_ci int cqm_rssi_thold; 15262306a36Sopenharmony_ci unsigned cqm_rssi_hyst; 15362306a36Sopenharmony_ci bool cqm_use_rssi; 15462306a36Sopenharmony_ci int cqm_beacon_loss_count; 15562306a36Sopenharmony_ci int channel_switch_in_progress; 15662306a36Sopenharmony_ci wait_queue_head_t channel_switch_done; 15762306a36Sopenharmony_ci u8 long_frame_max_tx_count; 15862306a36Sopenharmony_ci u8 short_frame_max_tx_count; 15962306a36Sopenharmony_ci int mode; 16062306a36Sopenharmony_ci bool enable_beacon; 16162306a36Sopenharmony_ci int beacon_int; 16262306a36Sopenharmony_ci bool listening; 16362306a36Sopenharmony_ci struct wsm_rx_filter rx_filter; 16462306a36Sopenharmony_ci struct wsm_mib_multicast_filter multicast_filter; 16562306a36Sopenharmony_ci bool has_multicast_subscription; 16662306a36Sopenharmony_ci bool disable_beacon_filter; 16762306a36Sopenharmony_ci struct work_struct update_filtering_work; 16862306a36Sopenharmony_ci struct work_struct set_beacon_wakeup_period_work; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci u8 ba_rx_tid_mask; 17162306a36Sopenharmony_ci u8 ba_tx_tid_mask; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci struct cw1200_pm_state pm_state; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo; 17662306a36Sopenharmony_ci struct wsm_uapsd_info uapsd_info; 17762306a36Sopenharmony_ci bool setbssparams_done; 17862306a36Sopenharmony_ci bool bt_present; 17962306a36Sopenharmony_ci u8 conf_listen_interval; 18062306a36Sopenharmony_ci u32 listen_interval; 18162306a36Sopenharmony_ci u32 erp_info; 18262306a36Sopenharmony_ci u32 rts_threshold; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* BH */ 18562306a36Sopenharmony_ci atomic_t bh_rx; 18662306a36Sopenharmony_ci atomic_t bh_tx; 18762306a36Sopenharmony_ci atomic_t bh_term; 18862306a36Sopenharmony_ci atomic_t bh_suspend; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci struct workqueue_struct *bh_workqueue; 19162306a36Sopenharmony_ci struct work_struct bh_work; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci int bh_error; 19462306a36Sopenharmony_ci wait_queue_head_t bh_wq; 19562306a36Sopenharmony_ci wait_queue_head_t bh_evt_wq; 19662306a36Sopenharmony_ci u8 buf_id_tx; 19762306a36Sopenharmony_ci u8 buf_id_rx; 19862306a36Sopenharmony_ci u8 wsm_rx_seq; 19962306a36Sopenharmony_ci u8 wsm_tx_seq; 20062306a36Sopenharmony_ci int hw_bufs_used; 20162306a36Sopenharmony_ci bool powersave_enabled; 20262306a36Sopenharmony_ci bool device_can_sleep; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* Scan status */ 20562306a36Sopenharmony_ci struct cw1200_scan scan; 20662306a36Sopenharmony_ci /* Keep cw1200 awake (WUP = 1) 1 second after each scan to avoid 20762306a36Sopenharmony_ci * FW issue with sleeping/waking up. 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci atomic_t recent_scan; 21062306a36Sopenharmony_ci struct delayed_work clear_recent_scan_work; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* WSM */ 21362306a36Sopenharmony_ci struct wsm_startup_ind wsm_caps; 21462306a36Sopenharmony_ci struct mutex wsm_cmd_mux; 21562306a36Sopenharmony_ci struct wsm_buf wsm_cmd_buf; 21662306a36Sopenharmony_ci struct wsm_cmd wsm_cmd; 21762306a36Sopenharmony_ci wait_queue_head_t wsm_cmd_wq; 21862306a36Sopenharmony_ci wait_queue_head_t wsm_startup_done; 21962306a36Sopenharmony_ci int firmware_ready; 22062306a36Sopenharmony_ci atomic_t tx_lock; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* WSM debug */ 22362306a36Sopenharmony_ci int wsm_enable_wsm_dumps; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* WSM Join */ 22662306a36Sopenharmony_ci enum cw1200_join_status join_status; 22762306a36Sopenharmony_ci u32 pending_frame_id; 22862306a36Sopenharmony_ci bool join_pending; 22962306a36Sopenharmony_ci struct delayed_work join_timeout; 23062306a36Sopenharmony_ci struct work_struct unjoin_work; 23162306a36Sopenharmony_ci struct work_struct join_complete_work; 23262306a36Sopenharmony_ci int join_complete_status; 23362306a36Sopenharmony_ci int join_dtim_period; 23462306a36Sopenharmony_ci bool delayed_unjoin; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* TX/RX and security */ 23762306a36Sopenharmony_ci s8 wep_default_key_id; 23862306a36Sopenharmony_ci struct work_struct wep_key_work; 23962306a36Sopenharmony_ci u32 key_map; 24062306a36Sopenharmony_ci struct wsm_add_key keys[WSM_KEY_MAX_INDEX + 1]; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* AP powersave */ 24362306a36Sopenharmony_ci u32 link_id_map; 24462306a36Sopenharmony_ci struct cw1200_link_entry link_id_db[CW1200_MAX_STA_IN_AP_MODE]; 24562306a36Sopenharmony_ci struct work_struct link_id_work; 24662306a36Sopenharmony_ci struct delayed_work link_id_gc_work; 24762306a36Sopenharmony_ci u32 sta_asleep_mask; 24862306a36Sopenharmony_ci u32 pspoll_mask; 24962306a36Sopenharmony_ci bool aid0_bit_set; 25062306a36Sopenharmony_ci spinlock_t ps_state_lock; /* Protect power save state */ 25162306a36Sopenharmony_ci bool buffered_multicasts; 25262306a36Sopenharmony_ci bool tx_multicast; 25362306a36Sopenharmony_ci struct work_struct set_tim_work; 25462306a36Sopenharmony_ci struct work_struct set_cts_work; 25562306a36Sopenharmony_ci struct work_struct multicast_start_work; 25662306a36Sopenharmony_ci struct work_struct multicast_stop_work; 25762306a36Sopenharmony_ci struct timer_list mcast_timeout; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* WSM events and CQM implementation */ 26062306a36Sopenharmony_ci spinlock_t event_queue_lock; /* Protect event queue */ 26162306a36Sopenharmony_ci struct list_head event_queue; 26262306a36Sopenharmony_ci struct work_struct event_handler; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci struct delayed_work bss_loss_work; 26562306a36Sopenharmony_ci spinlock_t bss_loss_lock; /* Protect BSS loss state */ 26662306a36Sopenharmony_ci int bss_loss_state; 26762306a36Sopenharmony_ci u32 bss_loss_confirm_id; 26862306a36Sopenharmony_ci int delayed_link_loss; 26962306a36Sopenharmony_ci struct work_struct bss_params_work; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* TX rate policy cache */ 27262306a36Sopenharmony_ci struct tx_policy_cache tx_policy_cache; 27362306a36Sopenharmony_ci struct work_struct tx_policy_upload_work; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci /* legacy PS mode switch in suspend */ 27662306a36Sopenharmony_ci int ps_mode_switch_in_progress; 27762306a36Sopenharmony_ci wait_queue_head_t ps_mode_switch_done; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Workaround for WFD testcase 6.1.10*/ 28062306a36Sopenharmony_ci struct work_struct linkid_reset_work; 28162306a36Sopenharmony_ci u8 action_frame_sa[ETH_ALEN]; 28262306a36Sopenharmony_ci u8 action_linkid; 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistruct cw1200_sta_priv { 28662306a36Sopenharmony_ci int link_id; 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/* interfaces for the drivers */ 29062306a36Sopenharmony_ciint cw1200_core_probe(const struct hwbus_ops *hwbus_ops, 29162306a36Sopenharmony_ci struct hwbus_priv *hwbus, 29262306a36Sopenharmony_ci struct device *pdev, 29362306a36Sopenharmony_ci struct cw1200_common **pself, 29462306a36Sopenharmony_ci int ref_clk, const u8 *macaddr, 29562306a36Sopenharmony_ci const char *sdd_path, bool have_5ghz); 29662306a36Sopenharmony_civoid cw1200_core_release(struct cw1200_common *self); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci#define FWLOAD_BLOCK_SIZE (1024) 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic inline int cw1200_is_ht(const struct cw1200_ht_info *ht_info) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci return ht_info->channel_type != NL80211_CHAN_NO_HT; 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic inline int cw1200_ht_greenfield(const struct cw1200_ht_info *ht_info) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci return cw1200_is_ht(ht_info) && 30862306a36Sopenharmony_ci (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && 30962306a36Sopenharmony_ci !(ht_info->operation_mode & 31062306a36Sopenharmony_ci IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic inline int cw1200_ht_ampdu_density(const struct cw1200_ht_info *ht_info) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci if (!cw1200_is_ht(ht_info)) 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci return ht_info->ht_cap.ampdu_density; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci#endif /* CW1200_H */ 321