| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 1 | /* | 
|  | 2 | * Common private data for ST-Ericsson CW1200 drivers | 
|  | 3 | * | 
|  | 4 | * Copyright (c) 2010, ST-Ericsson | 
|  | 5 | * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no> | 
|  | 6 | * | 
|  | 7 | * Based on the mac80211 Prism54 code, which is | 
|  | 8 | * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> | 
|  | 9 | * | 
|  | 10 | * Based on the islsm (softmac prism54) driver, which is: | 
|  | 11 | * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. | 
|  | 12 | * | 
|  | 13 | * This program is free software; you can redistribute it and/or modify | 
|  | 14 | * it under the terms of the GNU General Public License version 2 as | 
|  | 15 | * published by the Free Software Foundation. | 
|  | 16 | */ | 
|  | 17 |  | 
|  | 18 | #ifndef CW1200_H | 
|  | 19 | #define CW1200_H | 
|  | 20 |  | 
|  | 21 | #include <linux/wait.h> | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 22 | #include <linux/mutex.h> | 
|  | 23 | #include <linux/workqueue.h> | 
|  | 24 | #include <net/mac80211.h> | 
|  | 25 |  | 
|  | 26 | #include "queue.h" | 
|  | 27 | #include "wsm.h" | 
|  | 28 | #include "scan.h" | 
|  | 29 | #include "txrx.h" | 
|  | 30 | #include "pm.h" | 
|  | 31 |  | 
|  | 32 | /* Forward declarations */ | 
| Solomon Peachy | 911373c | 2013-06-01 08:08:42 -0400 | [diff] [blame] | 33 | struct hwbus_ops; | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 34 | struct task_struct; | 
|  | 35 | struct cw1200_debug_priv; | 
|  | 36 | struct firmware; | 
|  | 37 |  | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 38 | #define CW1200_MAX_CTRL_FRAME_LEN	(0x1000) | 
|  | 39 |  | 
|  | 40 | #define CW1200_MAX_STA_IN_AP_MODE	(5) | 
|  | 41 | #define CW1200_LINK_ID_AFTER_DTIM	(CW1200_MAX_STA_IN_AP_MODE + 1) | 
|  | 42 | #define CW1200_LINK_ID_UAPSD		(CW1200_MAX_STA_IN_AP_MODE + 2) | 
|  | 43 | #define CW1200_LINK_ID_MAX		(CW1200_MAX_STA_IN_AP_MODE + 3) | 
|  | 44 | #define CW1200_MAX_REQUEUE_ATTEMPTS	(5) | 
|  | 45 |  | 
|  | 46 | #define CW1200_MAX_TID			(8) | 
|  | 47 |  | 
|  | 48 | #define CW1200_BLOCK_ACK_CNT		(30) | 
|  | 49 | #define CW1200_BLOCK_ACK_THLD		(800) | 
|  | 50 | #define CW1200_BLOCK_ACK_HIST		(3) | 
|  | 51 | #define CW1200_BLOCK_ACK_INTERVAL	(1 * HZ / CW1200_BLOCK_ACK_HIST) | 
|  | 52 |  | 
|  | 53 | #define CW1200_JOIN_TIMEOUT		(1 * HZ) | 
|  | 54 | #define CW1200_AUTH_TIMEOUT		(5 * HZ) | 
|  | 55 |  | 
|  | 56 | struct cw1200_ht_info { | 
|  | 57 | struct ieee80211_sta_ht_cap     ht_cap; | 
|  | 58 | enum nl80211_channel_type       channel_type; | 
|  | 59 | u16                             operation_mode; | 
|  | 60 | }; | 
|  | 61 |  | 
|  | 62 | /* Please keep order */ | 
|  | 63 | enum cw1200_join_status { | 
|  | 64 | CW1200_JOIN_STATUS_PASSIVE = 0, | 
|  | 65 | CW1200_JOIN_STATUS_MONITOR, | 
|  | 66 | CW1200_JOIN_STATUS_JOINING, | 
|  | 67 | CW1200_JOIN_STATUS_PRE_STA, | 
|  | 68 | CW1200_JOIN_STATUS_STA, | 
|  | 69 | CW1200_JOIN_STATUS_IBSS, | 
|  | 70 | CW1200_JOIN_STATUS_AP, | 
|  | 71 | }; | 
|  | 72 |  | 
|  | 73 | enum cw1200_link_status { | 
|  | 74 | CW1200_LINK_OFF, | 
|  | 75 | CW1200_LINK_RESERVE, | 
|  | 76 | CW1200_LINK_SOFT, | 
|  | 77 | CW1200_LINK_HARD, | 
|  | 78 | CW1200_LINK_RESET, | 
|  | 79 | CW1200_LINK_RESET_REMAP, | 
|  | 80 | }; | 
|  | 81 |  | 
|  | 82 | extern int cw1200_power_mode; | 
|  | 83 | extern const char * const cw1200_fw_types[]; | 
|  | 84 |  | 
|  | 85 | struct cw1200_link_entry { | 
|  | 86 | unsigned long			timestamp; | 
|  | 87 | enum cw1200_link_status		status; | 
|  | 88 | enum cw1200_link_status		prev_status; | 
|  | 89 | u8				mac[ETH_ALEN]; | 
|  | 90 | u8				buffered[CW1200_MAX_TID]; | 
|  | 91 | struct sk_buff_head		rx_queue; | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 | struct cw1200_common { | 
|  | 95 | /* interfaces to the rest of the stack */ | 
|  | 96 | struct ieee80211_hw		*hw; | 
|  | 97 | struct ieee80211_vif		*vif; | 
|  | 98 | struct device			*pdev; | 
|  | 99 |  | 
|  | 100 | /* Statistics */ | 
|  | 101 | struct ieee80211_low_level_stats stats; | 
|  | 102 |  | 
|  | 103 | /* Our macaddr */ | 
|  | 104 | u8 mac_addr[ETH_ALEN]; | 
|  | 105 |  | 
|  | 106 | /* Hardware interface */ | 
| Solomon Peachy | 911373c | 2013-06-01 08:08:42 -0400 | [diff] [blame] | 107 | const struct hwbus_ops		*hwbus_ops; | 
|  | 108 | struct hwbus_priv		*hwbus_priv; | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 109 |  | 
|  | 110 | /* Hardware information */ | 
|  | 111 | enum { | 
|  | 112 | HIF_9000_SILICON_VERSATILE = 0, | 
|  | 113 | HIF_8601_VERSATILE, | 
|  | 114 | HIF_8601_SILICON, | 
|  | 115 | } hw_type; | 
|  | 116 | enum { | 
|  | 117 | CW1200_HW_REV_CUT10 = 10, | 
|  | 118 | CW1200_HW_REV_CUT11 = 11, | 
|  | 119 | CW1200_HW_REV_CUT20 = 20, | 
|  | 120 | CW1200_HW_REV_CUT22 = 22, | 
|  | 121 | CW1X60_HW_REV       = 40, | 
|  | 122 | } hw_revision; | 
|  | 123 | int                             hw_refclk; | 
|  | 124 | bool				hw_have_5ghz; | 
|  | 125 | const struct firmware		*sdd; | 
|  | 126 | char                            *sdd_path; | 
|  | 127 |  | 
|  | 128 | struct cw1200_debug_priv	*debug; | 
|  | 129 |  | 
|  | 130 | struct workqueue_struct		*workqueue; | 
|  | 131 | struct mutex			conf_mutex; | 
|  | 132 |  | 
|  | 133 | struct cw1200_queue		tx_queue[4]; | 
|  | 134 | struct cw1200_queue_stats	tx_queue_stats; | 
|  | 135 | int				tx_burst_idx; | 
|  | 136 |  | 
|  | 137 | /* firmware/hardware info */ | 
|  | 138 | unsigned int tx_hdr_len; | 
|  | 139 |  | 
|  | 140 | /* Radio data */ | 
|  | 141 | int output_power; | 
|  | 142 |  | 
|  | 143 | /* BBP/MAC state */ | 
|  | 144 | struct ieee80211_rate		*rates; | 
|  | 145 | struct ieee80211_rate		*mcs_rates; | 
|  | 146 | struct ieee80211_channel	*channel; | 
|  | 147 | struct wsm_edca_params		edca; | 
|  | 148 | struct wsm_tx_queue_params	tx_queue_params; | 
|  | 149 | struct wsm_mib_association_mode	association_mode; | 
|  | 150 | struct wsm_set_bss_params	bss_params; | 
|  | 151 | struct cw1200_ht_info		ht_info; | 
|  | 152 | struct wsm_set_pm		powersave_mode; | 
|  | 153 | struct wsm_set_pm		firmware_ps_mode; | 
|  | 154 | int				cqm_rssi_thold; | 
|  | 155 | unsigned			cqm_rssi_hyst; | 
|  | 156 | bool				cqm_use_rssi; | 
|  | 157 | int				cqm_beacon_loss_count; | 
|  | 158 | int				channel_switch_in_progress; | 
|  | 159 | wait_queue_head_t		channel_switch_done; | 
|  | 160 | u8				long_frame_max_tx_count; | 
|  | 161 | u8				short_frame_max_tx_count; | 
|  | 162 | int				mode; | 
|  | 163 | bool				enable_beacon; | 
|  | 164 | int				beacon_int; | 
|  | 165 | bool				listening; | 
|  | 166 | struct wsm_rx_filter		rx_filter; | 
|  | 167 | struct wsm_mib_multicast_filter multicast_filter; | 
|  | 168 | bool				has_multicast_subscription; | 
|  | 169 | bool				disable_beacon_filter; | 
|  | 170 | struct work_struct		update_filtering_work; | 
|  | 171 | struct work_struct		set_beacon_wakeup_period_work; | 
|  | 172 |  | 
|  | 173 | u8				ba_rx_tid_mask; | 
|  | 174 | u8				ba_tx_tid_mask; | 
|  | 175 |  | 
|  | 176 | struct cw1200_pm_state		pm_state; | 
|  | 177 |  | 
|  | 178 | struct wsm_p2p_ps_modeinfo	p2p_ps_modeinfo; | 
|  | 179 | struct wsm_uapsd_info		uapsd_info; | 
|  | 180 | bool				setbssparams_done; | 
|  | 181 | bool				bt_present; | 
|  | 182 | u8				conf_listen_interval; | 
|  | 183 | u32				listen_interval; | 
|  | 184 | u32				erp_info; | 
|  | 185 | u32				rts_threshold; | 
|  | 186 |  | 
|  | 187 | /* BH */ | 
|  | 188 | atomic_t			bh_rx; | 
|  | 189 | atomic_t			bh_tx; | 
|  | 190 | atomic_t			bh_term; | 
|  | 191 | atomic_t			bh_suspend; | 
|  | 192 |  | 
|  | 193 | struct workqueue_struct         *bh_workqueue; | 
|  | 194 | struct work_struct              bh_work; | 
|  | 195 |  | 
|  | 196 | int				bh_error; | 
|  | 197 | wait_queue_head_t		bh_wq; | 
|  | 198 | wait_queue_head_t		bh_evt_wq; | 
|  | 199 | u8				buf_id_tx; | 
|  | 200 | u8				buf_id_rx; | 
|  | 201 | u8				wsm_rx_seq; | 
|  | 202 | u8				wsm_tx_seq; | 
|  | 203 | int				hw_bufs_used; | 
|  | 204 | bool				powersave_enabled; | 
|  | 205 | bool				device_can_sleep; | 
|  | 206 |  | 
|  | 207 | /* Scan status */ | 
|  | 208 | struct cw1200_scan scan; | 
|  | 209 | /* Keep cw1200 awake (WUP = 1) 1 second after each scan to avoid | 
| Solomon Peachy | 8b3e7be | 2013-06-11 09:49:40 -0400 | [diff] [blame] | 210 | * FW issue with sleeping/waking up. | 
|  | 211 | */ | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 212 | atomic_t			recent_scan; | 
|  | 213 | struct delayed_work		clear_recent_scan_work; | 
|  | 214 |  | 
|  | 215 | /* WSM */ | 
|  | 216 | struct wsm_startup_ind		wsm_caps; | 
|  | 217 | struct mutex			wsm_cmd_mux; | 
|  | 218 | struct wsm_buf			wsm_cmd_buf; | 
|  | 219 | struct wsm_cmd			wsm_cmd; | 
|  | 220 | wait_queue_head_t		wsm_cmd_wq; | 
|  | 221 | wait_queue_head_t		wsm_startup_done; | 
|  | 222 | int                             firmware_ready; | 
|  | 223 | atomic_t			tx_lock; | 
|  | 224 |  | 
|  | 225 | /* WSM debug */ | 
|  | 226 | int				wsm_enable_wsm_dumps; | 
|  | 227 |  | 
|  | 228 | /* WSM Join */ | 
|  | 229 | enum cw1200_join_status	join_status; | 
|  | 230 | u32			pending_frame_id; | 
|  | 231 | bool			join_pending; | 
|  | 232 | struct delayed_work	join_timeout; | 
|  | 233 | struct work_struct	unjoin_work; | 
|  | 234 | struct work_struct	join_complete_work; | 
|  | 235 | int			join_complete_status; | 
|  | 236 | int			join_dtim_period; | 
|  | 237 | bool			delayed_unjoin; | 
|  | 238 |  | 
|  | 239 | /* TX/RX and security */ | 
|  | 240 | s8			wep_default_key_id; | 
|  | 241 | struct work_struct	wep_key_work; | 
|  | 242 | u32			key_map; | 
|  | 243 | struct wsm_add_key	keys[WSM_KEY_MAX_INDEX + 1]; | 
|  | 244 |  | 
|  | 245 | /* AP powersave */ | 
|  | 246 | u32			link_id_map; | 
|  | 247 | struct cw1200_link_entry link_id_db[CW1200_MAX_STA_IN_AP_MODE]; | 
|  | 248 | struct work_struct	link_id_work; | 
|  | 249 | struct delayed_work	link_id_gc_work; | 
|  | 250 | u32			sta_asleep_mask; | 
|  | 251 | u32			pspoll_mask; | 
|  | 252 | bool			aid0_bit_set; | 
|  | 253 | spinlock_t		ps_state_lock; /* Protect power save state */ | 
|  | 254 | bool			buffered_multicasts; | 
|  | 255 | bool			tx_multicast; | 
|  | 256 | struct work_struct	set_tim_work; | 
|  | 257 | struct work_struct	set_cts_work; | 
|  | 258 | struct work_struct	multicast_start_work; | 
|  | 259 | struct work_struct	multicast_stop_work; | 
|  | 260 | struct timer_list	mcast_timeout; | 
|  | 261 |  | 
|  | 262 | /* WSM events and CQM implementation */ | 
|  | 263 | spinlock_t		event_queue_lock; /* Protect event queue */ | 
|  | 264 | struct list_head	event_queue; | 
|  | 265 | struct work_struct	event_handler; | 
|  | 266 |  | 
|  | 267 | struct delayed_work	bss_loss_work; | 
|  | 268 | spinlock_t		bss_loss_lock; /* Protect BSS loss state */ | 
|  | 269 | int                     bss_loss_state; | 
| Solomon Peachy | 7258416 | 2013-06-20 23:03:12 -0400 | [diff] [blame] | 270 | u32                     bss_loss_confirm_id; | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 271 | int			delayed_link_loss; | 
|  | 272 | struct work_struct	bss_params_work; | 
|  | 273 |  | 
|  | 274 | /* TX rate policy cache */ | 
|  | 275 | struct tx_policy_cache tx_policy_cache; | 
|  | 276 | struct work_struct tx_policy_upload_work; | 
|  | 277 |  | 
|  | 278 | /* legacy PS mode switch in suspend */ | 
|  | 279 | int			ps_mode_switch_in_progress; | 
|  | 280 | wait_queue_head_t	ps_mode_switch_done; | 
|  | 281 |  | 
|  | 282 | /* Workaround for WFD testcase 6.1.10*/ | 
|  | 283 | struct work_struct	linkid_reset_work; | 
|  | 284 | u8			action_frame_sa[ETH_ALEN]; | 
|  | 285 | u8			action_linkid; | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 286 | }; | 
|  | 287 |  | 
|  | 288 | struct cw1200_sta_priv { | 
|  | 289 | int link_id; | 
|  | 290 | }; | 
|  | 291 |  | 
|  | 292 | /* interfaces for the drivers */ | 
| Solomon Peachy | 911373c | 2013-06-01 08:08:42 -0400 | [diff] [blame] | 293 | int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, | 
|  | 294 | struct hwbus_priv *hwbus, | 
| Solomon Peachy | a910e4a | 2013-05-24 20:04:38 -0400 | [diff] [blame] | 295 | struct device *pdev, | 
|  | 296 | struct cw1200_common **pself, | 
|  | 297 | int ref_clk, const u8 *macaddr, | 
|  | 298 | const char *sdd_path, bool have_5ghz); | 
|  | 299 | void cw1200_core_release(struct cw1200_common *self); | 
|  | 300 |  | 
|  | 301 | #define FWLOAD_BLOCK_SIZE (1024) | 
|  | 302 |  | 
|  | 303 | static inline int cw1200_is_ht(const struct cw1200_ht_info *ht_info) | 
|  | 304 | { | 
|  | 305 | return ht_info->channel_type != NL80211_CHAN_NO_HT; | 
|  | 306 | } | 
|  | 307 |  | 
|  | 308 | static inline int cw1200_ht_greenfield(const struct cw1200_ht_info *ht_info) | 
|  | 309 | { | 
|  | 310 | return cw1200_is_ht(ht_info) && | 
|  | 311 | (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 
|  | 312 | !(ht_info->operation_mode & | 
|  | 313 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | static inline int cw1200_ht_ampdu_density(const struct cw1200_ht_info *ht_info) | 
|  | 317 | { | 
|  | 318 | if (!cw1200_is_ht(ht_info)) | 
|  | 319 | return 0; | 
|  | 320 | return ht_info->ht_cap.ampdu_density; | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | #endif /* CW1200_H */ |