/* * Common private data for ST-Ericsson CW1200 drivers * * Copyright (c) 2010, ST-Ericsson * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no> * * Based on the mac80211 Prism54 code, which is * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> * * Based on the islsm (softmac prism54) driver, which is: * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #ifndef CW1200_H #define CW1200_H #include <linux/wait.h> #include <linux/mutex.h> #include <linux/workqueue.h> #include <net/mac80211.h> #include "queue.h" #include "wsm.h" #include "scan.h" #include "txrx.h" #include "pm.h" /* Forward declarations */ struct hwbus_ops; struct task_struct; struct cw1200_debug_priv; struct firmware; #define CW1200_MAX_CTRL_FRAME_LEN (0x1000) #define CW1200_MAX_STA_IN_AP_MODE (5) #define CW1200_LINK_ID_AFTER_DTIM (CW1200_MAX_STA_IN_AP_MODE + 1) #define CW1200_LINK_ID_UAPSD (CW1200_MAX_STA_IN_AP_MODE + 2) #define CW1200_LINK_ID_MAX (CW1200_MAX_STA_IN_AP_MODE + 3) #define CW1200_MAX_REQUEUE_ATTEMPTS (5) #define CW1200_MAX_TID (8) #define CW1200_BLOCK_ACK_CNT (30) #define CW1200_BLOCK_ACK_THLD (800) #define CW1200_BLOCK_ACK_HIST (3) #define CW1200_BLOCK_ACK_INTERVAL (1 * HZ / CW1200_BLOCK_ACK_HIST) #define CW1200_JOIN_TIMEOUT (1 * HZ) #define CW1200_AUTH_TIMEOUT (5 * HZ) struct cw1200_ht_info { struct ieee80211_sta_ht_cap ht_cap; enum nl80211_channel_type channel_type; u16 operation_mode; }; /* Please keep order */ enum cw1200_join_status { CW1200_JOIN_STATUS_PASSIVE = 0, CW1200_JOIN_STATUS_MONITOR, CW1200_JOIN_STATUS_JOINING, CW1200_JOIN_STATUS_PRE_STA, CW1200_JOIN_STATUS_STA, CW1200_JOIN_STATUS_IBSS, CW1200_JOIN_STATUS_AP, }; enum cw1200_link_status { CW1200_LINK_OFF, CW1200_LINK_RESERVE, CW1200_LINK_SOFT, CW1200_LINK_HARD, CW1200_LINK_RESET, CW1200_LINK_RESET_REMAP, }; extern int cw1200_power_mode; extern const char * const cw1200_fw_types[]; struct cw1200_link_entry { unsigned long timestamp; enum cw1200_link_status status; enum cw1200_link_status prev_status; u8 mac[ETH_ALEN]; u8 buffered[CW1200_MAX_TID]; struct sk_buff_head rx_queue; }; struct cw1200_common { /* interfaces to the rest of the stack */ struct ieee80211_hw *hw; struct ieee80211_vif *vif; struct device *pdev; /* Statistics */ struct ieee80211_low_level_stats stats; /* Our macaddr */ u8 mac_addr[ETH_ALEN]; /* Hardware interface */ const struct hwbus_ops *hwbus_ops; struct hwbus_priv *hwbus_priv; /* Hardware information */ enum { HIF_9000_SILICON_VERSATILE = 0, HIF_8601_VERSATILE, HIF_8601_SILICON, } hw_type; enum { CW1200_HW_REV_CUT10 = 10, CW1200_HW_REV_CUT11 = 11, CW1200_HW_REV_CUT20 = 20, CW1200_HW_REV_CUT22 = 22, CW1X60_HW_REV = 40, } hw_revision; int hw_refclk; bool hw_have_5ghz; const struct firmware *sdd; char *sdd_path; struct cw1200_debug_priv *debug; struct workqueue_struct *workqueue; struct mutex conf_mutex; struct cw1200_queue tx_queue[4]; struct cw1200_queue_stats tx_queue_stats; int tx_burst_idx; /* firmware/hardware info */ unsigned int tx_hdr_len; /* Radio data */ int output_power; /* BBP/MAC state */ struct ieee80211_rate *rates; struct ieee80211_rate *mcs_rates; struct ieee80211_channel *channel; struct wsm_edca_params edca; struct wsm_tx_queue_params tx_queue_params; struct wsm_mib_association_mode association_mode; struct wsm_set_bss_params bss_params; struct cw1200_ht_info ht_info; struct wsm_set_pm powersave_mode; struct wsm_set_pm firmware_ps_mode; int cqm_rssi_thold; unsigned cqm_rssi_hyst; bool cqm_use_rssi; int cqm_beacon_loss_count; int channel_switch_in_progress; wait_queue_head_t channel_switch_done; u8 long_frame_max_tx_count; u8 short_frame_max_tx_count; int mode; bool enable_beacon; int beacon_int; bool listening; struct wsm_rx_filter rx_filter; struct wsm_mib_multicast_filter multicast_filter; bool has_multicast_subscription; bool disable_beacon_filter; struct work_struct update_filtering_work; struct work_struct set_beacon_wakeup_period_work; u8 ba_rx_tid_mask; u8 ba_tx_tid_mask; struct cw1200_pm_state pm_state; struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo; struct wsm_uapsd_info uapsd_info; bool setbssparams_done; bool bt_present; u8 conf_listen_interval; u32 listen_interval; u32 erp_info; u32 rts_threshold; /* BH */ atomic_t bh_rx; atomic_t bh_tx; atomic_t bh_term; atomic_t bh_suspend; struct workqueue_struct *bh_workqueue; struct work_struct bh_work; int bh_error; wait_queue_head_t bh_wq; wait_queue_head_t bh_evt_wq; u8 buf_id_tx; u8 buf_id_rx; u8 wsm_rx_seq; u8 wsm_tx_seq; int hw_bufs_used; bool powersave_enabled; bool device_can_sleep; /* Scan status */ struct cw1200_scan scan; /* Keep cw1200 awake (WUP = 1) 1 second after each scan to avoid * FW issue with sleeping/waking up. */ atomic_t recent_scan; struct delayed_work clear_recent_scan_work; /* WSM */ struct wsm_startup_ind wsm_caps; struct mutex wsm_cmd_mux; struct wsm_buf wsm_cmd_buf; struct wsm_cmd wsm_cmd; wait_queue_head_t wsm_cmd_wq; wait_queue_head_t wsm_startup_done; int firmware_ready; atomic_t tx_lock; /* WSM debug */ int wsm_enable_wsm_dumps; /* WSM Join */ enum cw1200_join_status join_status; u32 pending_frame_id; bool join_pending; struct delayed_work join_timeout; struct work_struct unjoin_work; struct work_struct join_complete_work; int join_complete_status; int join_dtim_period; bool delayed_unjoin; /* TX/RX and security */ s8 wep_default_key_id; struct work_struct wep_key_work; u32 key_map; struct wsm_add_key keys[WSM_KEY_MAX_INDEX + 1]; /* AP powersave */ u32 link_id_map; struct cw1200_link_entry link_id_db[CW1200_MAX_STA_IN_AP_MODE]; struct work_struct link_id_work; struct delayed_work link_id_gc_work; u32 sta_asleep_mask; u32 pspoll_mask; bool aid0_bit_set; spinlock_t ps_state_lock; /* Protect power save state */ bool buffered_multicasts; bool tx_multicast; struct work_struct set_tim_work; struct work_struct set_cts_work; struct work_struct multicast_start_work; struct work_struct multicast_stop_work; struct timer_list mcast_timeout; /* WSM events and CQM implementation */ spinlock_t event_queue_lock; /* Protect event queue */ struct list_head event_queue; struct work_struct event_handler; struct delayed_work bss_loss_work; spinlock_t bss_loss_lock; /* Protect BSS loss state */ int bss_loss_state; u32 bss_loss_confirm_id; int delayed_link_loss; struct work_struct bss_params_work; /* TX rate policy cache */ struct tx_policy_cache tx_policy_cache; struct work_struct tx_policy_upload_work; /* legacy PS mode switch in suspend */ int ps_mode_switch_in_progress; wait_queue_head_t ps_mode_switch_done; /* Workaround for WFD testcase 6.1.10*/ struct work_struct linkid_reset_work; u8 action_frame_sa[ETH_ALEN]; u8 action_linkid; }; struct cw1200_sta_priv { int link_id; }; /* interfaces for the drivers */ int cw1200_core_probe(const struct hwbus_ops *hwbus_ops, struct hwbus_priv *hwbus, struct device *pdev, struct cw1200_common **pself, int ref_clk, const u8 *macaddr, const char *sdd_path, bool have_5ghz); void cw1200_core_release(struct cw1200_common *self); #define FWLOAD_BLOCK_SIZE (1024) static inline int cw1200_is_ht(const struct cw1200_ht_info *ht_info) { return ht_info->channel_type != NL80211_CHAN_NO_HT; } static inline int cw1200_ht_greenfield(const struct cw1200_ht_info *ht_info) { return cw1200_is_ht(ht_info) && (ht_info->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && !(ht_info->operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); } static inline int cw1200_ht_ampdu_density(const struct cw1200_ht_info *ht_info) { if (!cw1200_is_ht(ht_info)) return 0; return ht_info->ht_cap.ampdu_density; } #endif /* CW1200_H */