提交 8317e204 编写于 作者: D David S. Miller
...@@ -42,7 +42,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o ...@@ -42,7 +42,7 @@ obj-$(CONFIG_ADM8211) += adm8211.o
obj-$(CONFIG_MWL8K) += mwl8k.o obj-$(CONFIG_MWL8K) += mwl8k.o
obj-$(CONFIG_IWLWIFI) += iwlwifi/ obj-$(CONFIG_IWLWIFI) += iwlwifi/
obj-$(CONFIG_IWLWIFI_LEGACY) += iwlegacy/ obj-$(CONFIG_IWLEGACY) += iwlegacy/
obj-$(CONFIG_RT2X00) += rt2x00/ obj-$(CONFIG_RT2X00) += rt2x00/
obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_P54_COMMON) += p54/
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
obj-$(CONFIG_ATH6KL) := ath6kl.o obj-$(CONFIG_ATH6KL) := ath6kl.o
ath6kl-y += debug.o ath6kl-y += debug.o
ath6kl-y += htc_hif.o ath6kl-y += hif.o
ath6kl-y += htc.o ath6kl-y += htc.o
ath6kl-y += bmi.o ath6kl-y += bmi.o
ath6kl-y += cfg80211.o ath6kl-y += cfg80211.o
......
...@@ -196,8 +196,6 @@ int ath6kl_bmi_done(struct ath6kl *ar) ...@@ -196,8 +196,6 @@ int ath6kl_bmi_done(struct ath6kl *ar)
return ret; return ret;
} }
ath6kl_bmi_cleanup(ar);
return 0; return 0;
} }
...@@ -672,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len) ...@@ -672,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
return ret; return ret;
} }
void ath6kl_bmi_reset(struct ath6kl *ar)
{
ar->bmi.done_sent = false;
}
int ath6kl_bmi_init(struct ath6kl *ar) int ath6kl_bmi_init(struct ath6kl *ar)
{ {
ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC); ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
......
...@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info { ...@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info {
int ath6kl_bmi_init(struct ath6kl *ar); int ath6kl_bmi_init(struct ath6kl *ar);
void ath6kl_bmi_cleanup(struct ath6kl *ar); void ath6kl_bmi_cleanup(struct ath6kl *ar);
void ath6kl_bmi_reset(struct ath6kl *ar);
int ath6kl_bmi_done(struct ath6kl *ar); int ath6kl_bmi_done(struct ath6kl *ar);
int ath6kl_bmi_get_target_info(struct ath6kl *ar, int ath6kl_bmi_get_target_info(struct ath6kl *ar,
struct ath6kl_bmi_target_info *targ_info); struct ath6kl_bmi_target_info *targ_info);
......
...@@ -17,23 +17,41 @@ ...@@ -17,23 +17,41 @@
#ifndef ATH6KL_CFG80211_H #ifndef ATH6KL_CFG80211_H
#define ATH6KL_CFG80211_H #define ATH6KL_CFG80211_H
struct wireless_dev *ath6kl_cfg80211_init(struct device *dev); enum ath6kl_cfg_suspend_mode {
void ath6kl_cfg80211_deinit(struct ath6kl *ar); ATH6KL_CFG_SUSPEND_DEEPSLEEP,
ATH6KL_CFG_SUSPEND_CUTPOWER,
ATH6KL_CFG_SUSPEND_WOW
};
void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status); struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type,
u8 fw_vif_idx, u8 nw_type);
int ath6kl_register_ieee80211_hw(struct ath6kl *ar);
struct ath6kl *ath6kl_core_alloc(struct device *dev);
void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar);
void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel, void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
u8 *bssid, u16 listen_intvl, u8 *bssid, u16 listen_intvl,
u16 beacon_intvl, u16 beacon_intvl,
enum network_type nw_type, enum network_type nw_type,
u8 beacon_ie_len, u8 assoc_req_len, u8 beacon_ie_len, u8 assoc_req_len,
u8 assoc_resp_len, u8 *assoc_info); u8 assoc_resp_len, u8 *assoc_info);
void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason, void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
u8 *bssid, u8 assoc_resp_len, u8 *bssid, u8 assoc_resp_len,
u8 *assoc_info, u16 proto_reason); u8 *assoc_info, u16 proto_reason);
void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid, void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid,
bool ismcast); bool ismcast);
int ath6kl_cfg80211_suspend(struct ath6kl *ar,
enum ath6kl_cfg_suspend_mode mode,
struct cfg80211_wowlan *wow);
int ath6kl_cfg80211_resume(struct ath6kl *ar);
void ath6kl_cfg80211_stop(struct ath6kl *ar);
#endif /* ATH6KL_CFG80211_H */ #endif /* ATH6KL_CFG80211_H */
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
extern int ath6kl_printk(const char *level, const char *fmt, ...); extern int ath6kl_printk(const char *level, const char *fmt, ...);
#define A_CACHE_LINE_PAD 128
/* /*
* Reflects the version of binary interface exposed by ATH6KL target * Reflects the version of binary interface exposed by ATH6KL target
* firmware. Needs to be incremented by 1 for any change in the firmware * firmware. Needs to be incremented by 1 for any change in the firmware
...@@ -78,20 +76,10 @@ enum crypto_type { ...@@ -78,20 +76,10 @@ enum crypto_type {
struct htc_endpoint_credit_dist; struct htc_endpoint_credit_dist;
struct ath6kl; struct ath6kl;
enum htc_credit_dist_reason; enum htc_credit_dist_reason;
struct htc_credit_state_info; struct ath6kl_htc_credit_info;
int ath6k_setup_credit_dist(void *htc_handle,
struct htc_credit_state_info *cred_info);
void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf,
struct list_head *epdist_list,
enum htc_credit_dist_reason reason);
void ath6k_credit_init(struct htc_credit_state_info *cred_inf,
struct list_head *ep_list,
int tot_credits);
void ath6k_seek_credits(struct htc_credit_state_info *cred_inf,
struct htc_endpoint_credit_dist *ep_dist);
struct ath6kl *ath6kl_core_alloc(struct device *sdev); struct ath6kl *ath6kl_core_alloc(struct device *sdev);
int ath6kl_core_init(struct ath6kl *ar); int ath6kl_core_init(struct ath6kl *ar);
int ath6kl_unavail_ev(struct ath6kl *ar); void ath6kl_core_cleanup(struct ath6kl *ar);
struct sk_buff *ath6kl_buf_alloc(int size); struct sk_buff *ath6kl_buf_alloc(int size);
#endif /* COMMON_H */ #endif /* COMMON_H */
...@@ -166,6 +166,7 @@ struct ath6kl_fw_ie { ...@@ -166,6 +166,7 @@ struct ath6kl_fw_ie {
#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1) #define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1)
#define ATH6KL_CONF_ENABLE_11N BIT(2) #define ATH6KL_CONF_ENABLE_11N BIT(2)
#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3)
#define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4)
enum wlan_low_pwr_state { enum wlan_low_pwr_state {
WLAN_POWER_STATE_ON, WLAN_POWER_STATE_ON,
...@@ -380,40 +381,33 @@ struct ath6kl_req_key { ...@@ -380,40 +381,33 @@ struct ath6kl_req_key {
u8 key_len; u8 key_len;
}; };
/* Flag info */ #define MAX_NUM_VIF 1
#define WMI_ENABLED 0
#define WMI_READY 1 /* vif flags info */
#define CONNECTED 2 enum ath6kl_vif_state {
#define STATS_UPDATE_PEND 3 CONNECTED,
#define CONNECT_PEND 4 CONNECT_PEND,
#define WMM_ENABLED 5 WMM_ENABLED,
#define NETQ_STOPPED 6 NETQ_STOPPED,
#define WMI_CTRL_EP_FULL 7 DTIM_EXPIRED,
#define DTIM_EXPIRED 8 NETDEV_REGISTERED,
#define DESTROY_IN_PROGRESS 9 CLEAR_BSSFILTER_ON_BEACON,
#define NETDEV_REGISTERED 10 DTIM_PERIOD_AVAIL,
#define SKIP_SCAN 11 WLAN_ENABLED,
#define WLAN_ENABLED 12 STATS_UPDATE_PEND,
#define TESTMODE 13 };
#define CLEAR_BSSFILTER_ON_BEACON 14
#define DTIM_PERIOD_AVAIL 15
struct ath6kl { struct ath6kl_vif {
struct device *dev; struct list_head list;
struct net_device *net_dev; struct wireless_dev wdev;
struct ath6kl_bmi bmi; struct net_device *ndev;
const struct ath6kl_hif_ops *hif_ops; struct ath6kl *ar;
struct wmi *wmi; /* Lock to protect vif specific net_stats and flags */
int tx_pending[ENDPOINT_MAX]; spinlock_t if_lock;
int total_tx_data_pend; u8 fw_vif_idx;
struct htc_target *htc_target; unsigned long flags;
void *hif_priv;
spinlock_t lock;
struct semaphore sem;
int ssid_len; int ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN]; u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 next_mode;
u8 nw_type;
u8 dot11_auth_mode; u8 dot11_auth_mode;
u8 auth_mode; u8 auth_mode;
u8 prwise_crypto; u8 prwise_crypto;
...@@ -421,21 +415,83 @@ struct ath6kl { ...@@ -421,21 +415,83 @@ struct ath6kl {
u8 grp_crypto; u8 grp_crypto;
u8 grp_crypto_len; u8 grp_crypto_len;
u8 def_txkey_index; u8 def_txkey_index;
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; u8 next_mode;
u8 nw_type;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
u8 req_bssid[ETH_ALEN]; u8 req_bssid[ETH_ALEN];
u16 ch_hint; u16 ch_hint;
u16 bss_ch; u16 bss_ch;
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
struct aggr_info *aggr_cntxt;
struct timer_list disconnect_timer;
struct cfg80211_scan_request *scan_req;
enum sme_state sme_state;
int reconnect_flag;
u32 last_roc_id;
u32 last_cancel_roc_id;
u32 send_action_id;
bool probe_req_report;
u16 next_chan;
u16 assoc_bss_beacon_int;
u8 assoc_bss_dtim_period;
struct net_device_stats net_stats;
struct target_stats target_stats;
};
#define WOW_LIST_ID 0
#define WOW_HOST_REQ_DELAY 500 /* ms */
/* Flag info */
enum ath6kl_dev_state {
WMI_ENABLED,
WMI_READY,
WMI_CTRL_EP_FULL,
TESTMODE,
DESTROY_IN_PROGRESS,
SKIP_SCAN,
ROAM_TBL_PEND,
FIRST_BOOT,
};
enum ath6kl_state {
ATH6KL_STATE_OFF,
ATH6KL_STATE_ON,
ATH6KL_STATE_DEEPSLEEP,
ATH6KL_STATE_CUTPOWER,
ATH6KL_STATE_WOW,
};
struct ath6kl {
struct device *dev;
struct wiphy *wiphy;
enum ath6kl_state state;
struct ath6kl_bmi bmi;
const struct ath6kl_hif_ops *hif_ops;
struct wmi *wmi;
int tx_pending[ENDPOINT_MAX];
int total_tx_data_pend;
struct htc_target *htc_target;
void *hif_priv;
struct list_head vif_list;
/* Lock to avoid race in vif_list entries among add/del/traverse */
spinlock_t list_lock;
u8 num_vif;
u8 max_norm_iface;
u8 avail_idx_map;
spinlock_t lock;
struct semaphore sem;
u16 listen_intvl_b; u16 listen_intvl_b;
u16 listen_intvl_t; u16 listen_intvl_t;
u8 lrssi_roam_threshold; u8 lrssi_roam_threshold;
struct ath6kl_version version; struct ath6kl_version version;
u32 target_type; u32 target_type;
u8 tx_pwr; u8 tx_pwr;
struct net_device_stats net_stats;
struct target_stats target_stats;
struct ath6kl_node_mapping node_map[MAX_NODE_NUM]; struct ath6kl_node_mapping node_map[MAX_NODE_NUM];
u8 ibss_ps_enable; u8 ibss_ps_enable;
bool ibss_if_active;
u8 node_num; u8 node_num;
u8 next_ep_id; u8 next_ep_id;
struct ath6kl_cookie *cookie_list; struct ath6kl_cookie *cookie_list;
...@@ -446,7 +502,7 @@ struct ath6kl { ...@@ -446,7 +502,7 @@ struct ath6kl {
u8 hiac_stream_active_pri; u8 hiac_stream_active_pri;
u8 ep2ac_map[ENDPOINT_MAX]; u8 ep2ac_map[ENDPOINT_MAX];
enum htc_endpoint_id ctrl_ep; enum htc_endpoint_id ctrl_ep;
struct htc_credit_state_info credit_state_info; struct ath6kl_htc_credit_info credit_state_info;
u32 connect_ctrl_flags; u32 connect_ctrl_flags;
u32 user_key_ctrl; u32 user_key_ctrl;
u8 usr_bss_filter; u8 usr_bss_filter;
...@@ -456,18 +512,13 @@ struct ath6kl { ...@@ -456,18 +512,13 @@ struct ath6kl {
struct sk_buff_head mcastpsq; struct sk_buff_head mcastpsq;
spinlock_t mcastpsq_lock; spinlock_t mcastpsq_lock;
u8 intra_bss; u8 intra_bss;
struct aggr_info *aggr_cntxt;
struct wmi_ap_mode_stat ap_stats; struct wmi_ap_mode_stat ap_stats;
u8 ap_country_code[3]; u8 ap_country_code[3];
struct list_head amsdu_rx_buffer_queue; struct list_head amsdu_rx_buffer_queue;
struct timer_list disconnect_timer;
u8 rx_meta_ver; u8 rx_meta_ver;
struct wireless_dev *wdev;
struct cfg80211_scan_request *scan_req;
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
enum sme_state sme_state;
enum wlan_low_pwr_state wlan_pwr_state; enum wlan_low_pwr_state wlan_pwr_state;
struct wmi_scan_params_cmd sc_params; struct wmi_scan_params_cmd sc_params;
u8 mac_addr[ETH_ALEN];
#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4 #define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
struct { struct {
void *rx_report; void *rx_report;
...@@ -487,7 +538,6 @@ struct ath6kl { ...@@ -487,7 +538,6 @@ struct ath6kl {
struct ath6kl_mbox_info mbox_info; struct ath6kl_mbox_info mbox_info;
struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM]; struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM];
int reconnect_flag;
unsigned long flag; unsigned long flag;
u8 *fw_board; u8 *fw_board;
...@@ -508,13 +558,7 @@ struct ath6kl { ...@@ -508,13 +558,7 @@ struct ath6kl {
struct dentry *debugfs_phy; struct dentry *debugfs_phy;
u32 send_action_id;
bool probe_req_report;
u16 next_chan;
bool p2p; bool p2p;
u16 assoc_bss_beacon_int;
u8 assoc_bss_dtim_period;
#ifdef CONFIG_ATH6KL_DEBUG #ifdef CONFIG_ATH6KL_DEBUG
struct { struct {
...@@ -529,23 +573,19 @@ struct ath6kl { ...@@ -529,23 +573,19 @@ struct ath6kl {
struct { struct {
unsigned int invalid_rate; unsigned int invalid_rate;
} war_stats; } war_stats;
u8 *roam_tbl;
unsigned int roam_tbl_len;
u8 keepalive;
u8 disc_timeout;
} debug; } debug;
#endif /* CONFIG_ATH6KL_DEBUG */ #endif /* CONFIG_ATH6KL_DEBUG */
}; };
static inline void *ath6kl_priv(struct net_device *dev) static inline void *ath6kl_priv(struct net_device *dev)
{ {
return wdev_priv(dev->ieee80211_ptr); return ((struct ath6kl_vif *) netdev_priv(dev))->ar;
}
static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
*cred_info,
struct htc_endpoint_credit_dist
*ep_dist, int credits)
{
ep_dist->credits += credits;
ep_dist->cred_assngd += credits;
cred_info->cur_free_credits -= credits;
} }
static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
...@@ -561,7 +601,6 @@ static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar, ...@@ -561,7 +601,6 @@ static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
return addr; return addr;
} }
void ath6kl_destroy(struct net_device *dev, unsigned int unregister);
int ath6kl_configure_target(struct ath6kl *ar); int ath6kl_configure_target(struct ath6kl *ar);
void ath6kl_detect_error(unsigned long ptr); void ath6kl_detect_error(unsigned long ptr);
void disconnect_timer_handler(unsigned long ptr); void disconnect_timer_handler(unsigned long ptr);
...@@ -579,10 +618,8 @@ int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length); ...@@ -579,10 +618,8 @@ int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length);
int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value); int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value);
int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length); int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length);
int ath6kl_read_fwlogs(struct ath6kl *ar); int ath6kl_read_fwlogs(struct ath6kl *ar);
void ath6kl_init_profile_info(struct ath6kl *ar); void ath6kl_init_profile_info(struct ath6kl_vif *vif);
void ath6kl_tx_data_cleanup(struct ath6kl *ar); void ath6kl_tx_data_cleanup(struct ath6kl *ar);
void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
bool get_dbglogs);
struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar);
void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
...@@ -598,40 +635,49 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target, ...@@ -598,40 +635,49 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
void aggr_module_destroy(struct aggr_info *aggr_info); void aggr_module_destroy(struct aggr_info *aggr_info);
void aggr_reset_state(struct aggr_info *aggr_info); void aggr_reset_state(struct aggr_info *aggr_info);
struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 * node_addr); struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr);
struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver); void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver);
int ath6kl_control_tx(void *devt, struct sk_buff *skb, int ath6kl_control_tx(void *devt, struct sk_buff *skb,
enum htc_endpoint_id eid); enum htc_endpoint_id eid);
void ath6kl_connect_event(struct ath6kl *ar, u16 channel, void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel,
u8 *bssid, u16 listen_int, u8 *bssid, u16 listen_int,
u16 beacon_int, enum network_type net_type, u16 beacon_int, enum network_type net_type,
u8 beacon_ie_len, u8 assoc_req_len, u8 beacon_ie_len, u8 assoc_req_len,
u8 assoc_resp_len, u8 *assoc_info); u8 assoc_resp_len, u8 *assoc_info);
void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel); void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel);
void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr, void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
u8 keymgmt, u8 ucipher, u8 auth, u8 keymgmt, u8 ucipher, u8 auth,
u8 assoc_req_len, u8 *assoc_info); u8 assoc_req_len, u8 *assoc_info);
void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason,
u8 *bssid, u8 assoc_resp_len, u8 *bssid, u8 assoc_resp_len,
u8 *assoc_info, u16 prot_reason_status); u8 *assoc_info, u16 prot_reason_status);
void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast); void ath6kl_tkip_micerr_event(struct ath6kl_vif *vif, u8 keyid, bool ismcast);
void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr); void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr);
void ath6kl_scan_complete_evt(struct ath6kl *ar, int status); void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status);
void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len); void ath6kl_tgt_stats_event(struct ath6kl_vif *vif, u8 *ptr, u32 len);
void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active); void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active);
enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac); enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac);
void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid); void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid);
void ath6kl_dtimexpiry_event(struct ath6kl *ar); void ath6kl_dtimexpiry_event(struct ath6kl_vif *vif);
void ath6kl_disconnect(struct ath6kl *ar); void ath6kl_disconnect(struct ath6kl_vif *vif);
void ath6kl_deep_sleep_enable(struct ath6kl *ar); void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid);
void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid); void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no,
u8 win_sz); u8 win_sz);
void ath6kl_wakeup_event(void *dev); void ath6kl_wakeup_event(void *dev);
void ath6kl_target_failure(struct ath6kl *ar);
void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
bool wait_fot_compltn, bool cold_reset);
void ath6kl_init_control_info(struct ath6kl_vif *vif);
void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
void ath6kl_core_free(struct ath6kl *ar);
struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
int ath6kl_init_hw_start(struct ath6kl *ar);
int ath6kl_init_hw_stop(struct ath6kl *ar);
void ath6kl_check_wow_status(struct ath6kl *ar);
#endif /* CORE_H */ #endif /* CORE_H */
...@@ -17,19 +17,19 @@ ...@@ -17,19 +17,19 @@
#ifndef DEBUG_H #ifndef DEBUG_H
#define DEBUG_H #define DEBUG_H
#include "htc_hif.h" #include "hif.h"
enum ATH6K_DEBUG_MASK { enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_WLAN_CONNECT = BIT(0), /* wlan connect */ ATH6KL_DBG_CREDIT = BIT(0),
ATH6KL_DBG_WLAN_SCAN = BIT(1), /* wlan scan */ /* hole */
ATH6KL_DBG_WLAN_TX = BIT(2), /* wlan tx */ ATH6KL_DBG_WLAN_TX = BIT(2), /* wlan tx */
ATH6KL_DBG_WLAN_RX = BIT(3), /* wlan rx */ ATH6KL_DBG_WLAN_RX = BIT(3), /* wlan rx */
ATH6KL_DBG_BMI = BIT(4), /* bmi tracing */ ATH6KL_DBG_BMI = BIT(4), /* bmi tracing */
ATH6KL_DBG_HTC_SEND = BIT(5), /* htc send */ ATH6KL_DBG_HTC = BIT(5),
ATH6KL_DBG_HTC_RECV = BIT(6), /* htc recv */ ATH6KL_DBG_HIF = BIT(6),
ATH6KL_DBG_IRQ = BIT(7), /* interrupt processing */ ATH6KL_DBG_IRQ = BIT(7), /* interrupt processing */
ATH6KL_DBG_PM = BIT(8), /* power management */ /* hole */
ATH6KL_DBG_WLAN_NODE = BIT(9), /* general wlan node tracing */ /* hole */
ATH6KL_DBG_WMI = BIT(10), /* wmi tracing */ ATH6KL_DBG_WMI = BIT(10), /* wmi tracing */
ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */ ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */
ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */ ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */
...@@ -40,6 +40,7 @@ enum ATH6K_DEBUG_MASK { ...@@ -40,6 +40,7 @@ enum ATH6K_DEBUG_MASK {
ATH6KL_DBG_SDIO_DUMP = BIT(17), ATH6KL_DBG_SDIO_DUMP = BIT(17),
ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */
ATH6KL_DBG_WMI_DUMP = BIT(19), ATH6KL_DBG_WMI_DUMP = BIT(19),
ATH6KL_DBG_SUSPEND = BIT(20),
ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
}; };
...@@ -90,6 +91,10 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, ...@@ -90,6 +91,10 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
void dump_cred_dist_stats(struct htc_target *target); void dump_cred_dist_stats(struct htc_target *target);
void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len); void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len);
void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war); void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war);
int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
size_t len);
void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive);
void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout);
int ath6kl_debug_init(struct ath6kl *ar); int ath6kl_debug_init(struct ath6kl *ar);
void ath6kl_debug_cleanup(struct ath6kl *ar); void ath6kl_debug_cleanup(struct ath6kl *ar);
...@@ -125,6 +130,21 @@ static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war) ...@@ -125,6 +130,21 @@ static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
{ {
} }
static inline int ath6kl_debug_roam_tbl_event(struct ath6kl *ar,
const void *buf, size_t len)
{
return 0;
}
static inline void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive)
{
}
static inline void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar,
u8 timeout)
{
}
static inline int ath6kl_debug_init(struct ath6kl *ar) static inline int ath6kl_debug_init(struct ath6kl *ar)
{ {
return 0; return 0;
......
...@@ -18,10 +18,16 @@ ...@@ -18,10 +18,16 @@
#define HIF_OPS_H #define HIF_OPS_H
#include "hif.h" #include "hif.h"
#include "debug.h"
static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf, static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
u32 len, u32 request) u32 len, u32 request)
{ {
ath6kl_dbg(ATH6KL_DBG_HIF,
"hif %s sync addr 0x%x buf 0x%p len %d request 0x%x\n",
(request & HIF_WRITE) ? "write" : "read",
addr, buf, len, request);
return ar->hif_ops->read_write_sync(ar, addr, buf, len, request); return ar->hif_ops->read_write_sync(ar, addr, buf, len, request);
} }
...@@ -29,16 +35,24 @@ static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer, ...@@ -29,16 +35,24 @@ static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
u32 length, u32 request, u32 length, u32 request,
struct htc_packet *packet) struct htc_packet *packet)
{ {
ath6kl_dbg(ATH6KL_DBG_HIF,
"hif write async addr 0x%x buf 0x%p len %d request 0x%x\n",
address, buffer, length, request);
return ar->hif_ops->write_async(ar, address, buffer, length, return ar->hif_ops->write_async(ar, address, buffer, length,
request, packet); request, packet);
} }
static inline void ath6kl_hif_irq_enable(struct ath6kl *ar) static inline void ath6kl_hif_irq_enable(struct ath6kl *ar)
{ {
ath6kl_dbg(ATH6KL_DBG_HIF, "hif irq enable\n");
return ar->hif_ops->irq_enable(ar); return ar->hif_ops->irq_enable(ar);
} }
static inline void ath6kl_hif_irq_disable(struct ath6kl *ar) static inline void ath6kl_hif_irq_disable(struct ath6kl *ar)
{ {
ath6kl_dbg(ATH6KL_DBG_HIF, "hif irq disable\n");
return ar->hif_ops->irq_disable(ar); return ar->hif_ops->irq_disable(ar);
} }
...@@ -69,9 +83,40 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar) ...@@ -69,9 +83,40 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
return ar->hif_ops->cleanup_scatter(ar); return ar->hif_ops->cleanup_scatter(ar);
} }
static inline int ath6kl_hif_suspend(struct ath6kl *ar) static inline int ath6kl_hif_suspend(struct ath6kl *ar,
struct cfg80211_wowlan *wow)
{ {
return ar->hif_ops->suspend(ar); ath6kl_dbg(ATH6KL_DBG_HIF, "hif suspend\n");
return ar->hif_ops->suspend(ar, wow);
}
static inline int ath6kl_hif_resume(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_HIF, "hif resume\n");
return ar->hif_ops->resume(ar);
}
static inline int ath6kl_hif_power_on(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_HIF, "hif power on\n");
return ar->hif_ops->power_on(ar);
}
static inline int ath6kl_hif_power_off(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_HIF, "hif power off\n");
return ar->hif_ops->power_off(ar);
}
static inline void ath6kl_hif_stop(struct ath6kl *ar)
{
ath6kl_dbg(ATH6KL_DBG_HIF, "hif stop\n");
ar->hif_ops->stop(ar);
} }
#endif #endif
...@@ -13,18 +13,19 @@ ...@@ -13,18 +13,19 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "hif.h"
#include "core.h" #include "core.h"
#include "target.h" #include "target.h"
#include "hif-ops.h" #include "hif-ops.h"
#include "htc_hif.h"
#include "debug.h" #include "debug.h"
#define MAILBOX_FOR_BLOCK_SIZE 1 #define MAILBOX_FOR_BLOCK_SIZE 1
#define ATH6KL_TIME_QUANTUM 10 /* in ms */ #define ATH6KL_TIME_QUANTUM 10 /* in ms */
static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma) static int ath6kl_hif_cp_scat_dma_buf(struct hif_scatter_req *req,
bool from_dma)
{ {
u8 *buf; u8 *buf;
int i; int i;
...@@ -46,12 +47,11 @@ static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma) ...@@ -46,12 +47,11 @@ static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma)
return 0; return 0;
} }
int ath6kldev_rw_comp_handler(void *context, int status) int ath6kl_hif_rw_comp_handler(void *context, int status)
{ {
struct htc_packet *packet = context; struct htc_packet *packet = context;
ath6kl_dbg(ATH6KL_DBG_HTC_RECV, ath6kl_dbg(ATH6KL_DBG_HIF, "hif rw completion pkt 0x%p status %d\n",
"ath6kldev_rw_comp_handler (pkt:0x%p , status: %d\n",
packet, status); packet, status);
packet->status = status; packet->status = status;
...@@ -59,30 +59,83 @@ int ath6kldev_rw_comp_handler(void *context, int status) ...@@ -59,30 +59,83 @@ int ath6kldev_rw_comp_handler(void *context, int status)
return 0; return 0;
} }
#define REG_DUMP_COUNT_AR6003 60
#define REGISTER_DUMP_LEN_MAX 60
static int ath6kldev_proc_dbg_intr(struct ath6kl_device *dev) static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
{ {
u32 dummy; __le32 regdump_val[REGISTER_DUMP_LEN_MAX];
int status; u32 i, address, regdump_addr = 0;
int ret;
if (ar->target_type != TARGET_TYPE_AR6003)
return;
/* the reg dump pointer is copied to the host interest area */
address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
address = TARG_VTOP(ar->target_type, address);
/* read RAM location through diagnostic window */
ret = ath6kl_diag_read32(ar, address, &regdump_addr);
if (ret || !regdump_addr) {
ath6kl_warn("failed to get ptr to register dump area: %d\n",
ret);
return;
}
ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
regdump_addr);
regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
/* fetch register dump data */
ret = ath6kl_diag_read(ar, regdump_addr, (u8 *)&regdump_val[0],
REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
if (ret) {
ath6kl_warn("failed to get register dump: %d\n", ret);
return;
}
ath6kl_info("crash dump:\n");
ath6kl_info("hw 0x%x fw %s\n", ar->wiphy->hw_version,
ar->wiphy->fw_version);
BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
ath6kl_err("target debug interrupt\n"); for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
4 * i,
le32_to_cpu(regdump_val[i]),
le32_to_cpu(regdump_val[i + 1]),
le32_to_cpu(regdump_val[i + 2]),
le32_to_cpu(regdump_val[i + 3]));
}
}
static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
{
u32 dummy;
int ret;
ath6kl_target_failure(dev->ar); ath6kl_warn("firmware crashed\n");
/* /*
* read counter to clear the interrupt, the debug error interrupt is * read counter to clear the interrupt, the debug error interrupt is
* counter 0. * counter 0.
*/ */
status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS, ret = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
(u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC); (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
if (status) if (ret)
WARN_ON(1); ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
return status; ath6kl_hif_dump_fw_crash(dev->ar);
return ret;
} }
/* mailbox recv message polling */ /* mailbox recv message polling */
int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
int timeout) int timeout)
{ {
struct ath6kl_irq_proc_registers *rg; struct ath6kl_irq_proc_registers *rg;
...@@ -118,7 +171,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, ...@@ -118,7 +171,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
/* delay a little */ /* delay a little */
mdelay(ATH6KL_TIME_QUANTUM); mdelay(ATH6KL_TIME_QUANTUM);
ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "retry mbox poll : %d\n", i); ath6kl_dbg(ATH6KL_DBG_HIF, "hif retry mbox poll try %d\n", i);
} }
if (i == 0) { if (i == 0) {
...@@ -131,7 +184,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, ...@@ -131,7 +184,7 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
* Target failure handler will be called in case of * Target failure handler will be called in case of
* an assert. * an assert.
*/ */
ath6kldev_proc_dbg_intr(dev); ath6kl_hif_proc_dbg_intr(dev);
} }
return status; return status;
...@@ -141,11 +194,14 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd, ...@@ -141,11 +194,14 @@ int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
* Disable packet reception (used in case the host runs out of buffers) * Disable packet reception (used in case the host runs out of buffers)
* using the interrupt enable registers through the host I/F * using the interrupt enable registers through the host I/F
*/ */
int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx) int ath6kl_hif_rx_control(struct ath6kl_device *dev, bool enable_rx)
{ {
struct ath6kl_irq_enable_reg regs; struct ath6kl_irq_enable_reg regs;
int status = 0; int status = 0;
ath6kl_dbg(ATH6KL_DBG_HIF, "hif rx %s\n",
enable_rx ? "enable" : "disable");
/* take the lock to protect interrupt enable shadows */ /* take the lock to protect interrupt enable shadows */
spin_lock_bh(&dev->lock); spin_lock_bh(&dev->lock);
...@@ -168,7 +224,7 @@ int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx) ...@@ -168,7 +224,7 @@ int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx)
return status; return status;
} }
int ath6kldev_submit_scat_req(struct ath6kl_device *dev, int ath6kl_hif_submit_scat_req(struct ath6kl_device *dev,
struct hif_scatter_req *scat_req, bool read) struct hif_scatter_req *scat_req, bool read)
{ {
int status = 0; int status = 0;
...@@ -185,14 +241,14 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev, ...@@ -185,14 +241,14 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
dev->ar->mbox_info.htc_addr; dev->ar->mbox_info.htc_addr;
} }
ath6kl_dbg((ATH6KL_DBG_HTC_RECV | ATH6KL_DBG_HTC_SEND), ath6kl_dbg(ATH6KL_DBG_HIF,
"ath6kldev_submit_scat_req, entries: %d, total len: %d mbox:0x%X (mode: %s : %s)\n", "hif submit scatter request entries %d len %d mbox 0x%x %s %s\n",
scat_req->scat_entries, scat_req->len, scat_req->scat_entries, scat_req->len,
scat_req->addr, !read ? "async" : "sync", scat_req->addr, !read ? "async" : "sync",
(read) ? "rd" : "wr"); (read) ? "rd" : "wr");
if (!read && scat_req->virt_scat) { if (!read && scat_req->virt_scat) {
status = ath6kldev_cp_scat_dma_buf(scat_req, false); status = ath6kl_hif_cp_scat_dma_buf(scat_req, false);
if (status) { if (status) {
scat_req->status = status; scat_req->status = status;
scat_req->complete(dev->ar->htc_target, scat_req); scat_req->complete(dev->ar->htc_target, scat_req);
...@@ -207,13 +263,13 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev, ...@@ -207,13 +263,13 @@ int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
scat_req->status = status; scat_req->status = status;
if (!status && scat_req->virt_scat) if (!status && scat_req->virt_scat)
scat_req->status = scat_req->status =
ath6kldev_cp_scat_dma_buf(scat_req, true); ath6kl_hif_cp_scat_dma_buf(scat_req, true);
} }
return status; return status;
} }
static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev) static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev)
{ {
u8 counter_int_status; u8 counter_int_status;
...@@ -232,12 +288,12 @@ static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev) ...@@ -232,12 +288,12 @@ static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev)
* the debug assertion counter interrupt. * the debug assertion counter interrupt.
*/ */
if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK) if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK)
return ath6kldev_proc_dbg_intr(dev); return ath6kl_hif_proc_dbg_intr(dev);
return 0; return 0;
} }
static int ath6kldev_proc_err_intr(struct ath6kl_device *dev) static int ath6kl_hif_proc_err_intr(struct ath6kl_device *dev)
{ {
int status; int status;
u8 error_int_status; u8 error_int_status;
...@@ -282,7 +338,7 @@ static int ath6kldev_proc_err_intr(struct ath6kl_device *dev) ...@@ -282,7 +338,7 @@ static int ath6kldev_proc_err_intr(struct ath6kl_device *dev)
return status; return status;
} }
static int ath6kldev_proc_cpu_intr(struct ath6kl_device *dev) static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
{ {
int status; int status;
u8 cpu_int_status; u8 cpu_int_status;
...@@ -417,7 +473,7 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) ...@@ -417,7 +473,7 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
* we rapidly pull packets. * we rapidly pull packets.
*/ */
status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt, status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt,
&lk_ahd, &fetched); lk_ahd, &fetched);
if (status) if (status)
goto out; goto out;
...@@ -436,21 +492,21 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) ...@@ -436,21 +492,21 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
if (MS(HOST_INT_STATUS_CPU, host_int_status)) { if (MS(HOST_INT_STATUS_CPU, host_int_status)) {
/* CPU Interrupt */ /* CPU Interrupt */
status = ath6kldev_proc_cpu_intr(dev); status = ath6kl_hif_proc_cpu_intr(dev);
if (status) if (status)
goto out; goto out;
} }
if (MS(HOST_INT_STATUS_ERROR, host_int_status)) { if (MS(HOST_INT_STATUS_ERROR, host_int_status)) {
/* Error Interrupt */ /* Error Interrupt */
status = ath6kldev_proc_err_intr(dev); status = ath6kl_hif_proc_err_intr(dev);
if (status) if (status)
goto out; goto out;
} }
if (MS(HOST_INT_STATUS_COUNTER, host_int_status)) if (MS(HOST_INT_STATUS_COUNTER, host_int_status))
/* Counter Interrupt */ /* Counter Interrupt */
status = ath6kldev_proc_counter_intr(dev); status = ath6kl_hif_proc_counter_intr(dev);
out: out:
/* /*
...@@ -479,9 +535,10 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) ...@@ -479,9 +535,10 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
} }
/* interrupt handler, kicks off all interrupt processing */ /* interrupt handler, kicks off all interrupt processing */
int ath6kldev_intr_bh_handler(struct ath6kl *ar) int ath6kl_hif_intr_bh_handler(struct ath6kl *ar)
{ {
struct ath6kl_device *dev = ar->htc_target->dev; struct ath6kl_device *dev = ar->htc_target->dev;
unsigned long timeout;
int status = 0; int status = 0;
bool done = false; bool done = false;
...@@ -495,7 +552,8 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar) ...@@ -495,7 +552,8 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar)
* IRQ processing is synchronous, interrupt status registers can be * IRQ processing is synchronous, interrupt status registers can be
* re-read. * re-read.
*/ */
while (!done) { timeout = jiffies + msecs_to_jiffies(ATH6KL_HIF_COMMUNICATION_TIMEOUT);
while (time_before(jiffies, timeout) && !done) {
status = proc_pending_irqs(dev, &done); status = proc_pending_irqs(dev, &done);
if (status) if (status)
break; break;
...@@ -504,7 +562,7 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar) ...@@ -504,7 +562,7 @@ int ath6kldev_intr_bh_handler(struct ath6kl *ar)
return status; return status;
} }
static int ath6kldev_enable_intrs(struct ath6kl_device *dev) static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev)
{ {
struct ath6kl_irq_enable_reg regs; struct ath6kl_irq_enable_reg regs;
int status; int status;
...@@ -552,7 +610,7 @@ static int ath6kldev_enable_intrs(struct ath6kl_device *dev) ...@@ -552,7 +610,7 @@ static int ath6kldev_enable_intrs(struct ath6kl_device *dev)
return status; return status;
} }
int ath6kldev_disable_intrs(struct ath6kl_device *dev) int ath6kl_hif_disable_intrs(struct ath6kl_device *dev)
{ {
struct ath6kl_irq_enable_reg regs; struct ath6kl_irq_enable_reg regs;
...@@ -571,7 +629,7 @@ int ath6kldev_disable_intrs(struct ath6kl_device *dev) ...@@ -571,7 +629,7 @@ int ath6kldev_disable_intrs(struct ath6kl_device *dev)
} }
/* enable device interrupts */ /* enable device interrupts */
int ath6kldev_unmask_intrs(struct ath6kl_device *dev) int ath6kl_hif_unmask_intrs(struct ath6kl_device *dev)
{ {
int status = 0; int status = 0;
...@@ -583,29 +641,29 @@ int ath6kldev_unmask_intrs(struct ath6kl_device *dev) ...@@ -583,29 +641,29 @@ int ath6kldev_unmask_intrs(struct ath6kl_device *dev)
* target "soft" resets. The ATH6KL interrupt enables reset back to an * target "soft" resets. The ATH6KL interrupt enables reset back to an
* "enabled" state when this happens. * "enabled" state when this happens.
*/ */
ath6kldev_disable_intrs(dev); ath6kl_hif_disable_intrs(dev);
/* unmask the host controller interrupts */ /* unmask the host controller interrupts */
ath6kl_hif_irq_enable(dev->ar); ath6kl_hif_irq_enable(dev->ar);
status = ath6kldev_enable_intrs(dev); status = ath6kl_hif_enable_intrs(dev);
return status; return status;
} }
/* disable all device interrupts */ /* disable all device interrupts */
int ath6kldev_mask_intrs(struct ath6kl_device *dev) int ath6kl_hif_mask_intrs(struct ath6kl_device *dev)
{ {
/* /*
* Mask the interrupt at the HIF layer to avoid any stray interrupt * Mask the interrupt at the HIF layer to avoid any stray interrupt
* taken while we zero out our shadow registers in * taken while we zero out our shadow registers in
* ath6kldev_disable_intrs(). * ath6kl_hif_disable_intrs().
*/ */
ath6kl_hif_irq_disable(dev->ar); ath6kl_hif_irq_disable(dev->ar);
return ath6kldev_disable_intrs(dev); return ath6kl_hif_disable_intrs(dev);
} }
int ath6kldev_setup(struct ath6kl_device *dev) int ath6kl_hif_setup(struct ath6kl_device *dev)
{ {
int status = 0; int status = 0;
...@@ -621,19 +679,17 @@ int ath6kldev_setup(struct ath6kl_device *dev) ...@@ -621,19 +679,17 @@ int ath6kldev_setup(struct ath6kl_device *dev)
/* must be a power of 2 */ /* must be a power of 2 */
if ((dev->htc_cnxt->block_sz & (dev->htc_cnxt->block_sz - 1)) != 0) { if ((dev->htc_cnxt->block_sz & (dev->htc_cnxt->block_sz - 1)) != 0) {
WARN_ON(1); WARN_ON(1);
status = -EINVAL;
goto fail_setup; goto fail_setup;
} }
/* assemble mask, used for padding to a block */ /* assemble mask, used for padding to a block */
dev->htc_cnxt->block_mask = dev->htc_cnxt->block_sz - 1; dev->htc_cnxt->block_mask = dev->htc_cnxt->block_sz - 1;
ath6kl_dbg(ATH6KL_DBG_TRC, "block size: %d, mbox addr:0x%X\n", ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
ath6kl_dbg(ATH6KL_DBG_TRC, status = ath6kl_hif_disable_intrs(dev);
"hif interrupt processing is sync only\n");
status = ath6kldev_disable_intrs(dev);
fail_setup: fail_setup:
return status; return status;
......
...@@ -59,6 +59,18 @@ ...@@ -59,6 +59,18 @@
/* mode to enable special 4-bit interrupt assertion without clock */ /* mode to enable special 4-bit interrupt assertion without clock */
#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0) #define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0)
/* HTC runs over mailbox 0 */
#define HTC_MAILBOX 0
#define ATH6KL_TARGET_DEBUG_INTR_MASK 0x01
/* FIXME: are these duplicates with MAX_SCATTER_ values in hif.h? */
#define ATH6KL_SCATTER_ENTRIES_PER_REQ 16
#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER (16 * 1024)
#define ATH6KL_SCATTER_REQS 4
#define ATH6KL_HIF_COMMUNICATION_TIMEOUT 1000
struct bus_request { struct bus_request {
struct list_head list; struct list_head list;
...@@ -186,6 +198,34 @@ struct hif_scatter_req { ...@@ -186,6 +198,34 @@ struct hif_scatter_req {
struct hif_scatter_item scat_list[1]; struct hif_scatter_item scat_list[1];
}; };
struct ath6kl_irq_proc_registers {
u8 host_int_status;
u8 cpu_int_status;
u8 error_int_status;
u8 counter_int_status;
u8 mbox_frame;
u8 rx_lkahd_valid;
u8 host_int_status2;
u8 gmbox_rx_avail;
__le32 rx_lkahd[2];
__le32 rx_gmbox_lkahd_alias[2];
} __packed;
struct ath6kl_irq_enable_reg {
u8 int_status_en;
u8 cpu_int_status_en;
u8 err_int_status_en;
u8 cntr_int_status_en;
} __packed;
struct ath6kl_device {
spinlock_t lock;
struct ath6kl_irq_proc_registers irq_proc_reg;
struct ath6kl_irq_enable_reg irq_en_reg;
struct htc_target *htc_cnxt;
struct ath6kl *ar;
};
struct ath6kl_hif_ops { struct ath6kl_hif_ops {
int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf, int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf,
u32 len, u32 request); u32 len, u32 request);
...@@ -202,7 +242,26 @@ struct ath6kl_hif_ops { ...@@ -202,7 +242,26 @@ struct ath6kl_hif_ops {
int (*scat_req_rw) (struct ath6kl *ar, int (*scat_req_rw) (struct ath6kl *ar,
struct hif_scatter_req *scat_req); struct hif_scatter_req *scat_req);
void (*cleanup_scatter)(struct ath6kl *ar); void (*cleanup_scatter)(struct ath6kl *ar);
int (*suspend)(struct ath6kl *ar); int (*suspend)(struct ath6kl *ar, struct cfg80211_wowlan *wow);
int (*resume)(struct ath6kl *ar);
int (*power_on)(struct ath6kl *ar);
int (*power_off)(struct ath6kl *ar);
void (*stop)(struct ath6kl *ar);
}; };
int ath6kl_hif_setup(struct ath6kl_device *dev);
int ath6kl_hif_unmask_intrs(struct ath6kl_device *dev);
int ath6kl_hif_mask_intrs(struct ath6kl_device *dev);
int ath6kl_hif_poll_mboxmsg_rx(struct ath6kl_device *dev,
u32 *lk_ahd, int timeout);
int ath6kl_hif_rx_control(struct ath6kl_device *dev, bool enable_rx);
int ath6kl_hif_disable_intrs(struct ath6kl_device *dev);
int ath6kl_hif_rw_comp_handler(void *context, int status);
int ath6kl_hif_intr_bh_handler(struct ath6kl *ar);
/* Scatter Function and Definitions */
int ath6kl_hif_submit_scat_req(struct ath6kl_device *dev,
struct hif_scatter_req *scat_req, bool read);
#endif #endif
...@@ -393,7 +393,7 @@ struct htc_endpoint_credit_dist { ...@@ -393,7 +393,7 @@ struct htc_endpoint_credit_dist {
int cred_per_msg; int cred_per_msg;
/* reserved for HTC use */ /* reserved for HTC use */
void *htc_rsvd; struct htc_endpoint *htc_ep;
/* /*
* current depth of TX queue , i.e. messages waiting for credits * current depth of TX queue , i.e. messages waiting for credits
...@@ -414,9 +414,11 @@ enum htc_credit_dist_reason { ...@@ -414,9 +414,11 @@ enum htc_credit_dist_reason {
HTC_CREDIT_DIST_SEEK_CREDITS, HTC_CREDIT_DIST_SEEK_CREDITS,
}; };
struct htc_credit_state_info { struct ath6kl_htc_credit_info {
int total_avail_credits; int total_avail_credits;
int cur_free_credits; int cur_free_credits;
/* list of lowest priority endpoints */
struct list_head lowestpri_ep_dist; struct list_head lowestpri_ep_dist;
}; };
...@@ -508,10 +510,13 @@ struct ath6kl_device; ...@@ -508,10 +510,13 @@ struct ath6kl_device;
/* our HTC target state */ /* our HTC target state */
struct htc_target { struct htc_target {
struct htc_endpoint endpoint[ENDPOINT_MAX]; struct htc_endpoint endpoint[ENDPOINT_MAX];
/* contains struct htc_endpoint_credit_dist */
struct list_head cred_dist_list; struct list_head cred_dist_list;
struct list_head free_ctrl_txbuf; struct list_head free_ctrl_txbuf;
struct list_head free_ctrl_rxbuf; struct list_head free_ctrl_rxbuf;
struct htc_credit_state_info *cred_dist_cntxt; struct ath6kl_htc_credit_info *credit_info;
int tgt_creds; int tgt_creds;
unsigned int tgt_cred_sz; unsigned int tgt_cred_sz;
spinlock_t htc_lock; spinlock_t htc_lock;
...@@ -542,7 +547,7 @@ struct htc_target { ...@@ -542,7 +547,7 @@ struct htc_target {
void *ath6kl_htc_create(struct ath6kl *ar); void *ath6kl_htc_create(struct ath6kl *ar);
void ath6kl_htc_set_credit_dist(struct htc_target *target, void ath6kl_htc_set_credit_dist(struct htc_target *target,
struct htc_credit_state_info *cred_info, struct ath6kl_htc_credit_info *cred_info,
u16 svc_pri_order[], int len); u16 svc_pri_order[], int len);
int ath6kl_htc_wait_target(struct htc_target *target); int ath6kl_htc_wait_target(struct htc_target *target);
int ath6kl_htc_start(struct htc_target *target); int ath6kl_htc_start(struct htc_target *target);
...@@ -563,7 +568,10 @@ int ath6kl_htc_get_rxbuf_num(struct htc_target *target, ...@@ -563,7 +568,10 @@ int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target, int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
struct list_head *pktq); struct list_head *pktq);
int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
u32 msg_look_ahead[], int *n_pkts); u32 msg_look_ahead, int *n_pkts);
int ath6kl_credit_setup(void *htc_handle,
struct ath6kl_htc_credit_info *cred_info);
static inline void set_htc_pkt_info(struct htc_packet *packet, void *context, static inline void set_htc_pkt_info(struct htc_packet *packet, void *context,
u8 *buf, unsigned int len, u8 *buf, unsigned int len,
......
/*
* Copyright (c) 2007-2011 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef HTC_HIF_H
#define HTC_HIF_H
#include "htc.h"
#include "hif.h"
#define ATH6KL_MAILBOXES 4
/* HTC runs over mailbox 0 */
#define HTC_MAILBOX 0
#define ATH6KL_TARGET_DEBUG_INTR_MASK 0x01
#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
INT_STATUS_ENABLE_CPU_MASK | \
INT_STATUS_ENABLE_COUNTER_MASK)
#define ATH6KL_REG_IO_BUFFER_SIZE 32
#define ATH6KL_MAX_REG_IO_BUFFERS 8
#define ATH6KL_SCATTER_ENTRIES_PER_REQ 16
#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER (16 * 1024)
#define ATH6KL_SCATTER_REQS 4
#ifndef A_CACHE_LINE_PAD
#define A_CACHE_LINE_PAD 128
#endif
#define ATH6KL_MIN_SCATTER_ENTRIES_PER_REQ 2
#define ATH6KL_MIN_TRANSFER_SIZE_PER_SCATTER (4 * 1024)
struct ath6kl_irq_proc_registers {
u8 host_int_status;
u8 cpu_int_status;
u8 error_int_status;
u8 counter_int_status;
u8 mbox_frame;
u8 rx_lkahd_valid;
u8 host_int_status2;
u8 gmbox_rx_avail;
__le32 rx_lkahd[2];
__le32 rx_gmbox_lkahd_alias[2];
} __packed;
struct ath6kl_irq_enable_reg {
u8 int_status_en;
u8 cpu_int_status_en;
u8 err_int_status_en;
u8 cntr_int_status_en;
} __packed;
struct ath6kl_device {
spinlock_t lock;
u8 pad1[A_CACHE_LINE_PAD];
struct ath6kl_irq_proc_registers irq_proc_reg;
u8 pad2[A_CACHE_LINE_PAD];
struct ath6kl_irq_enable_reg irq_en_reg;
u8 pad3[A_CACHE_LINE_PAD];
struct htc_target *htc_cnxt;
struct ath6kl *ar;
};
int ath6kldev_setup(struct ath6kl_device *dev);
int ath6kldev_unmask_intrs(struct ath6kl_device *dev);
int ath6kldev_mask_intrs(struct ath6kl_device *dev);
int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev,
u32 *lk_ahd, int timeout);
int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx);
int ath6kldev_disable_intrs(struct ath6kl_device *dev);
int ath6kldev_rw_comp_handler(void *context, int status);
int ath6kldev_intr_bh_handler(struct ath6kl *ar);
/* Scatter Function and Definitions */
int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
struct hif_scatter_req *scat_req, bool read);
#endif /*ATH6KL_H_ */
...@@ -320,7 +320,10 @@ struct host_interest { ...@@ -320,7 +320,10 @@ struct host_interest {
| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2)
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|
*/ */
#define HI_OPTION_FW_MODE_BITS 0x2
#define HI_OPTION_FW_MODE_SHIFT 0xC #define HI_OPTION_FW_MODE_SHIFT 0xC
#define HI_OPTION_FW_SUBMODE_BITS 0x2
#define HI_OPTION_FW_SUBMODE_SHIFT 0x14 #define HI_OPTION_FW_SUBMODE_SHIFT 0x14
/* Convert a Target virtual address into a Target physical address */ /* Convert a Target virtual address into a Target physical address */
......
...@@ -77,12 +77,13 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, ...@@ -77,12 +77,13 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
return ar->node_map[ep_map].ep_id; return ar->node_map[ep_map].ep_id;
} }
static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb,
bool *more_data) bool *more_data)
{ {
struct ethhdr *datap = (struct ethhdr *) skb->data; struct ethhdr *datap = (struct ethhdr *) skb->data;
struct ath6kl_sta *conn = NULL; struct ath6kl_sta *conn = NULL;
bool ps_queued = false, is_psq_empty = false; bool ps_queued = false, is_psq_empty = false;
struct ath6kl *ar = vif->ar;
if (is_multicast_ether_addr(datap->h_dest)) { if (is_multicast_ether_addr(datap->h_dest)) {
u8 ctr = 0; u8 ctr = 0;
...@@ -100,7 +101,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, ...@@ -100,7 +101,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
* If this transmit is not because of a Dtim Expiry * If this transmit is not because of a Dtim Expiry
* q it. * q it.
*/ */
if (!test_bit(DTIM_EXPIRED, &ar->flag)) { if (!test_bit(DTIM_EXPIRED, &vif->flags)) {
bool is_mcastq_empty = false; bool is_mcastq_empty = false;
spin_lock_bh(&ar->mcastpsq_lock); spin_lock_bh(&ar->mcastpsq_lock);
...@@ -116,6 +117,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, ...@@ -116,6 +117,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
*/ */
if (is_mcastq_empty) if (is_mcastq_empty)
ath6kl_wmi_set_pvb_cmd(ar->wmi, ath6kl_wmi_set_pvb_cmd(ar->wmi,
vif->fw_vif_idx,
MCAST_AID, 1); MCAST_AID, 1);
ps_queued = true; ps_queued = true;
...@@ -131,7 +133,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, ...@@ -131,7 +133,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
} }
} }
} else { } else {
conn = ath6kl_find_sta(ar, datap->h_dest); conn = ath6kl_find_sta(vif, datap->h_dest);
if (!conn) { if (!conn) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -154,6 +156,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb, ...@@ -154,6 +156,7 @@ static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
*/ */
if (is_psq_empty) if (is_psq_empty)
ath6kl_wmi_set_pvb_cmd(ar->wmi, ath6kl_wmi_set_pvb_cmd(ar->wmi,
vif->fw_vif_idx,
conn->aid, 1); conn->aid, 1);
ps_queued = true; ps_queued = true;
...@@ -235,6 +238,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -235,6 +238,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_cookie *cookie = NULL; struct ath6kl_cookie *cookie = NULL;
enum htc_endpoint_id eid = ENDPOINT_UNUSED; enum htc_endpoint_id eid = ENDPOINT_UNUSED;
struct ath6kl_vif *vif = netdev_priv(dev);
u32 map_no = 0; u32 map_no = 0;
u16 htc_tag = ATH6KL_DATA_PKT_TAG; u16 htc_tag = ATH6KL_DATA_PKT_TAG;
u8 ac = 99 ; /* initialize to unmapped ac */ u8 ac = 99 ; /* initialize to unmapped ac */
...@@ -246,7 +250,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -246,7 +250,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
skb, skb->data, skb->len); skb, skb->data, skb->len);
/* If target is not associated */ /* If target is not associated */
if (!test_bit(CONNECTED, &ar->flag)) { if (!test_bit(CONNECTED, &vif->flags)) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; return 0;
} }
...@@ -255,15 +259,21 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -255,15 +259,21 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
goto fail_tx; goto fail_tx;
/* AP mode Power saving processing */ /* AP mode Power saving processing */
if (ar->nw_type == AP_NETWORK) { if (vif->nw_type == AP_NETWORK) {
if (ath6kl_powersave_ap(ar, skb, &more_data)) if (ath6kl_powersave_ap(vif, skb, &more_data))
return 0; return 0;
} }
if (test_bit(WMI_ENABLED, &ar->flag)) { if (test_bit(WMI_ENABLED, &ar->flag)) {
if (skb_headroom(skb) < dev->needed_headroom) { if (skb_headroom(skb) < dev->needed_headroom) {
WARN_ON(1); struct sk_buff *tmp_skb = skb;
goto fail_tx;
skb = skb_realloc_headroom(skb, dev->needed_headroom);
kfree_skb(tmp_skb);
if (skb == NULL) {
vif->net_stats.tx_dropped++;
return 0;
}
} }
if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) { if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
...@@ -272,18 +282,20 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -272,18 +282,20 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
} }
if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE, if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE,
more_data, 0, 0, NULL)) { more_data, 0, 0, NULL,
vif->fw_vif_idx)) {
ath6kl_err("wmi_data_hdr_add failed\n"); ath6kl_err("wmi_data_hdr_add failed\n");
goto fail_tx; goto fail_tx;
} }
if ((ar->nw_type == ADHOC_NETWORK) && if ((vif->nw_type == ADHOC_NETWORK) &&
ar->ibss_ps_enable && test_bit(CONNECTED, &ar->flag)) ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags))
chk_adhoc_ps_mapping = true; chk_adhoc_ps_mapping = true;
else { else {
/* get the stream mapping */ /* get the stream mapping */
ret = ath6kl_wmi_implicit_create_pstream(ar->wmi, skb, ret = ath6kl_wmi_implicit_create_pstream(ar->wmi,
0, test_bit(WMM_ENABLED, &ar->flag), &ac); vif->fw_vif_idx, skb,
0, test_bit(WMM_ENABLED, &vif->flags), &ac);
if (ret) if (ret)
goto fail_tx; goto fail_tx;
} }
...@@ -354,8 +366,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -354,8 +366,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
fail_tx: fail_tx:
dev_kfree_skb(skb); dev_kfree_skb(skb);
ar->net_stats.tx_dropped++; vif->net_stats.tx_dropped++;
ar->net_stats.tx_aborted_errors++; vif->net_stats.tx_aborted_errors++;
return 0; return 0;
} }
...@@ -426,7 +438,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -426,7 +438,9 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
struct htc_packet *packet) struct htc_packet *packet)
{ {
struct ath6kl *ar = target->dev->ar; struct ath6kl *ar = target->dev->ar;
struct ath6kl_vif *vif;
enum htc_endpoint_id endpoint = packet->endpoint; enum htc_endpoint_id endpoint = packet->endpoint;
enum htc_send_full_action action = HTC_SEND_FULL_KEEP;
if (endpoint == ar->ctrl_ep) { if (endpoint == ar->ctrl_ep) {
/* /*
...@@ -439,19 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -439,19 +453,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
set_bit(WMI_CTRL_EP_FULL, &ar->flag); set_bit(WMI_CTRL_EP_FULL, &ar->flag);
spin_unlock_bh(&ar->lock); spin_unlock_bh(&ar->lock);
ath6kl_err("wmi ctrl ep is full\n"); ath6kl_err("wmi ctrl ep is full\n");
return HTC_SEND_FULL_KEEP; goto stop_adhoc_netq;
} }
if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG) if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
return HTC_SEND_FULL_KEEP; goto stop_adhoc_netq;
if (ar->nw_type == ADHOC_NETWORK)
/*
* In adhoc mode, we cannot differentiate traffic
* priorities so there is no need to continue, however we
* should stop the network.
*/
goto stop_net_queues;
/* /*
* The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
...@@ -459,29 +465,43 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -459,29 +465,43 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
*/ */
if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
ar->hiac_stream_active_pri && ar->hiac_stream_active_pri &&
ar->cookie_count <= MAX_HI_COOKIE_NUM) ar->cookie_count <= MAX_HI_COOKIE_NUM) {
/* /*
* Give preference to the highest priority stream by * Give preference to the highest priority stream by
* dropping the packets which overflowed. * dropping the packets which overflowed.
*/ */
return HTC_SEND_FULL_DROP; action = HTC_SEND_FULL_DROP;
goto stop_adhoc_netq;
}
stop_net_queues: stop_adhoc_netq:
spin_lock_bh(&ar->lock); /* FIXME: Locking */
set_bit(NETQ_STOPPED, &ar->flag); spin_lock_bh(&ar->list_lock);
spin_unlock_bh(&ar->lock); list_for_each_entry(vif, &ar->vif_list, list) {
netif_stop_queue(ar->net_dev); if (vif->nw_type == ADHOC_NETWORK) {
spin_unlock_bh(&ar->list_lock);
return HTC_SEND_FULL_KEEP; spin_lock_bh(&vif->if_lock);
set_bit(NETQ_STOPPED, &vif->flags);
spin_unlock_bh(&vif->if_lock);
netif_stop_queue(vif->ndev);
return action;
}
}
spin_unlock_bh(&ar->list_lock);
return action;
} }
/* TODO this needs to be looked at */ /* TODO this needs to be looked at */
static void ath6kl_tx_clear_node_map(struct ath6kl *ar, static void ath6kl_tx_clear_node_map(struct ath6kl_vif *vif,
enum htc_endpoint_id eid, u32 map_no) enum htc_endpoint_id eid, u32 map_no)
{ {
struct ath6kl *ar = vif->ar;
u32 i; u32 i;
if (ar->nw_type != ADHOC_NETWORK) if (vif->nw_type != ADHOC_NETWORK)
return; return;
if (!ar->ibss_ps_enable) if (!ar->ibss_ps_enable)
...@@ -523,7 +543,9 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -523,7 +543,9 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
int status; int status;
enum htc_endpoint_id eid; enum htc_endpoint_id eid;
bool wake_event = false; bool wake_event = false;
bool flushing = false; bool flushing[MAX_NUM_VIF] = {false};
u8 if_idx;
struct ath6kl_vif *vif;
skb_queue_head_init(&skb_queue); skb_queue_head_init(&skb_queue);
...@@ -569,15 +591,30 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -569,15 +591,30 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
wake_event = true; wake_event = true;
} }
if (eid == ar->ctrl_ep) {
if_idx = wmi_cmd_hdr_get_if_idx(
(struct wmi_cmd_hdr *) skb->data);
} else {
if_idx = wmi_data_hdr_get_if_idx(
(struct wmi_data_hdr *) skb->data);
}
vif = ath6kl_get_vif_by_index(ar, if_idx);
if (!vif) {
ath6kl_free_cookie(ar, ath6kl_cookie);
continue;
}
if (status) { if (status) {
if (status == -ECANCELED) if (status == -ECANCELED)
/* a packet was flushed */ /* a packet was flushed */
flushing = true; flushing[if_idx] = true;
vif->net_stats.tx_errors++;
ar->net_stats.tx_errors++; if (status != -ENOSPC && status != -ECANCELED)
ath6kl_warn("tx complete error: %d\n", status);
if (status != -ENOSPC)
ath6kl_err("tx error, status: 0x%x\n", status);
ath6kl_dbg(ATH6KL_DBG_WLAN_TX, ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
"%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n", "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
__func__, skb, packet->buf, packet->act_len, __func__, skb, packet->buf, packet->act_len,
...@@ -588,27 +625,34 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -588,27 +625,34 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
__func__, skb, packet->buf, packet->act_len, __func__, skb, packet->buf, packet->act_len,
eid, "OK"); eid, "OK");
flushing = false; flushing[if_idx] = false;
ar->net_stats.tx_packets++; vif->net_stats.tx_packets++;
ar->net_stats.tx_bytes += skb->len; vif->net_stats.tx_bytes += skb->len;
} }
ath6kl_tx_clear_node_map(ar, eid, map_no); ath6kl_tx_clear_node_map(vif, eid, map_no);
ath6kl_free_cookie(ar, ath6kl_cookie); ath6kl_free_cookie(ar, ath6kl_cookie);
if (test_bit(NETQ_STOPPED, &ar->flag)) if (test_bit(NETQ_STOPPED, &vif->flags))
clear_bit(NETQ_STOPPED, &ar->flag); clear_bit(NETQ_STOPPED, &vif->flags);
} }
spin_unlock_bh(&ar->lock); spin_unlock_bh(&ar->lock);
__skb_queue_purge(&skb_queue); __skb_queue_purge(&skb_queue);
if (test_bit(CONNECTED, &ar->flag)) { /* FIXME: Locking */
if (!flushing) spin_lock_bh(&ar->list_lock);
netif_wake_queue(ar->net_dev); list_for_each_entry(vif, &ar->vif_list, list) {
if (test_bit(CONNECTED, &vif->flags) &&
!flushing[vif->fw_vif_idx]) {
spin_unlock_bh(&ar->list_lock);
netif_wake_queue(vif->ndev);
spin_lock_bh(&ar->list_lock);
}
} }
spin_unlock_bh(&ar->list_lock);
if (wake_event) if (wake_event)
wake_up(&ar->event_wq); wake_up(&ar->event_wq);
...@@ -1041,8 +1085,9 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1041,8 +1085,9 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
struct ath6kl_sta *conn = NULL; struct ath6kl_sta *conn = NULL;
struct sk_buff *skb1 = NULL; struct sk_buff *skb1 = NULL;
struct ethhdr *datap = NULL; struct ethhdr *datap = NULL;
struct ath6kl_vif *vif;
u16 seq_no, offset; u16 seq_no, offset;
u8 tid; u8 tid, if_idx;
ath6kl_dbg(ATH6KL_DBG_WLAN_RX, ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
"%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d", "%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d",
...@@ -1050,7 +1095,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1050,7 +1095,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
packet->act_len, status); packet->act_len, status);
if (status || !(skb->data + HTC_HDR_LENGTH)) { if (status || !(skb->data + HTC_HDR_LENGTH)) {
ar->net_stats.rx_errors++; dev_kfree_skb(skb);
return;
}
skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
skb_pull(skb, HTC_HDR_LENGTH);
if (ept == ar->ctrl_ep) {
if_idx =
wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data);
} else {
if_idx =
wmi_data_hdr_get_if_idx((struct wmi_data_hdr *) skb->data);
}
vif = ath6kl_get_vif_by_index(ar, if_idx);
if (!vif) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
return; return;
} }
...@@ -1059,28 +1120,28 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1059,28 +1120,28 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
* Take lock to protect buffer counts and adaptive power throughput * Take lock to protect buffer counts and adaptive power throughput
* state. * state.
*/ */
spin_lock_bh(&ar->lock); spin_lock_bh(&vif->if_lock);
ar->net_stats.rx_packets++; vif->net_stats.rx_packets++;
ar->net_stats.rx_bytes += packet->act_len; vif->net_stats.rx_bytes += packet->act_len;
spin_unlock_bh(&ar->lock); spin_unlock_bh(&vif->if_lock);
skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
skb_pull(skb, HTC_HDR_LENGTH);
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ", ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
skb->data, skb->len); skb->data, skb->len);
skb->dev = ar->net_dev; skb->dev = vif->ndev;
if (!test_bit(WMI_ENABLED, &ar->flag)) { if (!test_bit(WMI_ENABLED, &ar->flag)) {
if (EPPING_ALIGNMENT_PAD > 0) if (EPPING_ALIGNMENT_PAD > 0)
skb_pull(skb, EPPING_ALIGNMENT_PAD); skb_pull(skb, EPPING_ALIGNMENT_PAD);
ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
return; return;
} }
ath6kl_check_wow_status(ar);
if (ept == ar->ctrl_ep) { if (ept == ar->ctrl_ep) {
ath6kl_wmi_control_rx(ar->wmi, skb); ath6kl_wmi_control_rx(ar->wmi, skb);
return; return;
...@@ -1096,18 +1157,18 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1096,18 +1157,18 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
* that do not have LLC hdr. They are 16 bytes in size. * that do not have LLC hdr. They are 16 bytes in size.
* Allow these frames in the AP mode. * Allow these frames in the AP mode.
*/ */
if (ar->nw_type != AP_NETWORK && if (vif->nw_type != AP_NETWORK &&
((packet->act_len < min_hdr_len) || ((packet->act_len < min_hdr_len) ||
(packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) { (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) {
ath6kl_info("frame len is too short or too long\n"); ath6kl_info("frame len is too short or too long\n");
ar->net_stats.rx_errors++; vif->net_stats.rx_errors++;
ar->net_stats.rx_length_errors++; vif->net_stats.rx_length_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
return; return;
} }
/* Get the Power save state of the STA */ /* Get the Power save state of the STA */
if (ar->nw_type == AP_NETWORK) { if (vif->nw_type == AP_NETWORK) {
meta_type = wmi_data_hdr_get_meta(dhdr); meta_type = wmi_data_hdr_get_meta(dhdr);
ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) & ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) &
...@@ -1129,7 +1190,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1129,7 +1190,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
} }
datap = (struct ethhdr *) (skb->data + offset); datap = (struct ethhdr *) (skb->data + offset);
conn = ath6kl_find_sta(ar, datap->h_source); conn = ath6kl_find_sta(vif, datap->h_source);
if (!conn) { if (!conn) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -1160,12 +1221,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1160,12 +1221,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
while ((skbuff = skb_dequeue(&conn->psq)) while ((skbuff = skb_dequeue(&conn->psq))
!= NULL) { != NULL) {
spin_unlock_bh(&conn->psq_lock); spin_unlock_bh(&conn->psq_lock);
ath6kl_data_tx(skbuff, ar->net_dev); ath6kl_data_tx(skbuff, vif->ndev);
spin_lock_bh(&conn->psq_lock); spin_lock_bh(&conn->psq_lock);
} }
spin_unlock_bh(&conn->psq_lock); spin_unlock_bh(&conn->psq_lock);
/* Clear the PVB for this STA */ /* Clear the PVB for this STA */
ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0); ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
conn->aid, 0);
} }
} }
...@@ -1215,12 +1277,12 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1215,12 +1277,12 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
return; return;
} }
if (!(ar->net_dev->flags & IFF_UP)) { if (!(vif->ndev->flags & IFF_UP)) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
return; return;
} }
if (ar->nw_type == AP_NETWORK) { if (vif->nw_type == AP_NETWORK) {
datap = (struct ethhdr *) skb->data; datap = (struct ethhdr *) skb->data;
if (is_multicast_ether_addr(datap->h_dest)) if (is_multicast_ether_addr(datap->h_dest))
/* /*
...@@ -1235,8 +1297,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1235,8 +1297,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
* frame to it on the air else send the * frame to it on the air else send the
* frame up the stack. * frame up the stack.
*/ */
struct ath6kl_sta *conn = NULL; conn = ath6kl_find_sta(vif, datap->h_dest);
conn = ath6kl_find_sta(ar, datap->h_dest);
if (conn && ar->intra_bss) { if (conn && ar->intra_bss) {
skb1 = skb; skb1 = skb;
...@@ -1247,18 +1308,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ...@@ -1247,18 +1308,23 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
} }
} }
if (skb1) if (skb1)
ath6kl_data_tx(skb1, ar->net_dev); ath6kl_data_tx(skb1, vif->ndev);
if (skb == NULL) {
/* nothing to deliver up the stack */
return;
}
} }
datap = (struct ethhdr *) skb->data; datap = (struct ethhdr *) skb->data;
if (is_unicast_ether_addr(datap->h_dest) && if (is_unicast_ether_addr(datap->h_dest) &&
aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no, aggr_process_recv_frm(vif->aggr_cntxt, tid, seq_no,
is_amsdu, skb)) is_amsdu, skb))
/* aggregation code will handle the skb */ /* aggregation code will handle the skb */
return; return;
ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb); ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb);
} }
static void aggr_timeout(unsigned long arg) static void aggr_timeout(unsigned long arg)
...@@ -1336,9 +1402,10 @@ static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid) ...@@ -1336,9 +1402,10 @@ static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
memset(stats, 0, sizeof(struct rxtid_stats)); memset(stats, 0, sizeof(struct rxtid_stats));
} }
void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz) void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
u8 win_sz)
{ {
struct aggr_info *p_aggr = ar->aggr_cntxt; struct aggr_info *p_aggr = vif->aggr_cntxt;
struct rxtid *rxtid; struct rxtid *rxtid;
struct rxtid_stats *stats; struct rxtid_stats *stats;
u16 hold_q_size; u16 hold_q_size;
...@@ -1405,9 +1472,9 @@ struct aggr_info *aggr_init(struct net_device *dev) ...@@ -1405,9 +1472,9 @@ struct aggr_info *aggr_init(struct net_device *dev)
return p_aggr; return p_aggr;
} }
void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid) void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid)
{ {
struct aggr_info *p_aggr = ar->aggr_cntxt; struct aggr_info *p_aggr = vif->aggr_cntxt;
struct rxtid *rxtid; struct rxtid *rxtid;
if (!p_aggr) if (!p_aggr)
......
...@@ -36,18 +36,22 @@ ...@@ -36,18 +36,22 @@
#define ATH_BT_CNT_THRESHOLD 3 #define ATH_BT_CNT_THRESHOLD 3
#define ATH_BT_CNT_SCAN_THRESHOLD 15 #define ATH_BT_CNT_SCAN_THRESHOLD 15
#define AR9300_NUM_BT_WEIGHTS 4
#define AR9300_NUM_WLAN_WEIGHTS 4
/* Defines the BT AR_BT_COEX_WGHT used */ /* Defines the BT AR_BT_COEX_WGHT used */
enum ath_stomp_type { enum ath_stomp_type {
ATH_BTCOEX_NO_STOMP,
ATH_BTCOEX_STOMP_ALL, ATH_BTCOEX_STOMP_ALL,
ATH_BTCOEX_STOMP_LOW, ATH_BTCOEX_STOMP_LOW,
ATH_BTCOEX_STOMP_NONE ATH_BTCOEX_STOMP_NONE,
ATH_BTCOEX_STOMP_LOW_FTP,
ATH_BTCOEX_STOMP_MAX
}; };
enum ath_btcoex_scheme { enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE, ATH_BTCOEX_CFG_NONE,
ATH_BTCOEX_CFG_2WIRE, ATH_BTCOEX_CFG_2WIRE,
ATH_BTCOEX_CFG_3WIRE, ATH_BTCOEX_CFG_3WIRE,
ATH_BTCOEX_CFG_MCI,
}; };
struct ath_btcoex_hw { struct ath_btcoex_hw {
...@@ -59,6 +63,8 @@ struct ath_btcoex_hw { ...@@ -59,6 +63,8 @@ struct ath_btcoex_hw {
u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
}; };
void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
......
...@@ -198,6 +198,7 @@ static void ath_btcoex_period_timer(unsigned long data) ...@@ -198,6 +198,7 @@ static void ath_btcoex_period_timer(unsigned long data)
ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
btcoex->bt_stomp_type); btcoex->bt_stomp_type);
ath9k_hw_btcoex_enable(ah);
spin_unlock_bh(&btcoex->btcoex_lock); spin_unlock_bh(&btcoex->btcoex_lock);
if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
...@@ -240,6 +241,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) ...@@ -240,6 +241,7 @@ static void ath_btcoex_no_stomp_timer(void *arg)
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
ath9k_hw_btcoex_enable(ah);
spin_unlock_bh(&btcoex->btcoex_lock); spin_unlock_bh(&btcoex->btcoex_lock);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
......
...@@ -80,6 +80,7 @@ static void ath_btcoex_period_work(struct work_struct *work) ...@@ -80,6 +80,7 @@ static void ath_btcoex_period_work(struct work_struct *work)
ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
btcoex->bt_stomp_type); btcoex->bt_stomp_type);
ath9k_hw_btcoex_enable(priv->ah);
timer_period = is_btscan ? btcoex->btscan_no_stomp : timer_period = is_btscan ? btcoex->btscan_no_stomp :
btcoex->btcoex_no_stomp; btcoex->btcoex_no_stomp;
ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work,
...@@ -108,6 +109,7 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work) ...@@ -108,6 +109,7 @@ static void ath_btcoex_duty_cycle_work(struct work_struct *work)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
ath9k_hw_btcoex_enable(priv->ah);
} }
void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
......
...@@ -59,9 +59,6 @@ ...@@ -59,9 +59,6 @@
#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
#define AR9300_NUM_BT_WEIGHTS 4
#define AR9300_NUM_WLAN_WEIGHTS 4
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
#define ATH_DEFAULT_NOISE_FLOOR -95 #define ATH_DEFAULT_NOISE_FLOOR -95
...@@ -802,8 +799,6 @@ struct ath_hw { ...@@ -802,8 +799,6 @@ struct ath_hw {
/* Bluetooth coexistance */ /* Bluetooth coexistance */
struct ath_btcoex_hw btcoex_hw; struct ath_btcoex_hw btcoex_hw;
u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS];
u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
u32 intr_txqs; u32 intr_txqs;
u8 txchainmask; u8 txchainmask;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册