forked from Minki/linux
Merge branch 'for-linville' of git://github.com/kvalo/ath6kl
This commit is contained in:
commit
a5abbcb220
@ -31,5 +31,7 @@ ath6kl-y += init.o
|
||||
ath6kl-y += main.o
|
||||
ath6kl-y += txrx.o
|
||||
ath6kl-y += wmi.o
|
||||
ath6kl-y += node.o
|
||||
ath6kl-y += sdio.o
|
||||
ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -62,14 +62,14 @@ static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar, bool need_timeout)
|
||||
static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar)
|
||||
{
|
||||
unsigned long timeout;
|
||||
u32 rx_word = 0;
|
||||
int ret = 0;
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
|
||||
while ((!need_timeout || time_before(jiffies, timeout)) && !rx_word) {
|
||||
while (time_before(jiffies, timeout) && !rx_word) {
|
||||
ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS,
|
||||
(u8 *)&rx_word, sizeof(rx_word),
|
||||
HIF_RD_SYNC_BYTE_INC);
|
||||
@ -109,8 +109,7 @@ static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath6kl_bmi_recv_buf(struct ath6kl *ar,
|
||||
u8 *buf, u32 len, bool want_timeout)
|
||||
static int ath6kl_bmi_recv_buf(struct ath6kl *ar, u8 *buf, u32 len)
|
||||
{
|
||||
int ret;
|
||||
u32 addr;
|
||||
@ -162,7 +161,7 @@ static int ath6kl_bmi_recv_buf(struct ath6kl *ar,
|
||||
* a function of Host processor speed.
|
||||
*/
|
||||
if (len >= 4) { /* NB: Currently, always true */
|
||||
ret = ath6kl_bmi_get_rx_lkahd(ar, want_timeout);
|
||||
ret = ath6kl_bmi_get_rx_lkahd(ar);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -220,7 +219,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
|
||||
}
|
||||
|
||||
ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version,
|
||||
sizeof(targ_info->version), true);
|
||||
sizeof(targ_info->version));
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to recv target info: %d\n", ret);
|
||||
return ret;
|
||||
@ -230,8 +229,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
|
||||
/* Determine how many bytes are in the Target's targ_info */
|
||||
ret = ath6kl_bmi_recv_buf(ar,
|
||||
(u8 *)&targ_info->byte_count,
|
||||
sizeof(targ_info->byte_count),
|
||||
true);
|
||||
sizeof(targ_info->byte_count));
|
||||
if (ret) {
|
||||
ath6kl_err("unable to read target info byte count: %d\n",
|
||||
ret);
|
||||
@ -252,8 +250,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
|
||||
((u8 *)targ_info) +
|
||||
sizeof(targ_info->byte_count),
|
||||
sizeof(*targ_info) -
|
||||
sizeof(targ_info->byte_count),
|
||||
true);
|
||||
sizeof(targ_info->byte_count));
|
||||
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to read target info (%d bytes): %d\n",
|
||||
@ -311,7 +308,7 @@ int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len, true);
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len);
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to read from the device: %d\n",
|
||||
ret);
|
||||
@ -424,7 +421,7 @@ int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), false);
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to read from the device: %d\n", ret);
|
||||
return ret;
|
||||
@ -504,7 +501,7 @@ int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), true);
|
||||
ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param));
|
||||
if (ret) {
|
||||
ath6kl_err("Unable to read from the device: %d\n", ret);
|
||||
return ret;
|
||||
|
@ -139,8 +139,8 @@
|
||||
*/
|
||||
|
||||
#define TARGET_VERSION_SENTINAL 0xffffffff
|
||||
#define TARGET_TYPE_AR6003 3
|
||||
|
||||
#define TARGET_TYPE_AR6003 3
|
||||
#define TARGET_TYPE_AR6004 5
|
||||
#define BMI_ROMPATCH_INSTALL 9
|
||||
/*
|
||||
* Semantics: Install a ROM Patch.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,94 +75,11 @@ enum crypto_type {
|
||||
AES_CRYPT = 0x08,
|
||||
};
|
||||
|
||||
#define ATH6KL_NODE_HASHSIZE 32
|
||||
/* simple hash is enough for variation of macaddr */
|
||||
#define ATH6KL_NODE_HASH(addr) \
|
||||
(((const u8 *)(addr))[ETH_ALEN - 1] % \
|
||||
ATH6KL_NODE_HASHSIZE)
|
||||
|
||||
/*
|
||||
* Table of ath6kl_node instances. Each ieee80211com
|
||||
* has at least one for holding the scan candidates.
|
||||
* When operating as an access point or in ibss mode there
|
||||
* is a second table for associated stations or neighbors.
|
||||
*/
|
||||
struct ath6kl_node_table {
|
||||
spinlock_t nt_nodelock; /* on node table */
|
||||
struct bss *nt_node_first; /* information of all nodes */
|
||||
struct bss *nt_node_last; /* information of all nodes */
|
||||
struct bss *nt_hash[ATH6KL_NODE_HASHSIZE];
|
||||
const char *nt_name; /* for debugging */
|
||||
u32 nt_node_age; /* node aging time */
|
||||
};
|
||||
|
||||
#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000
|
||||
#define WLAN_NODE_INACT_CNT 4
|
||||
|
||||
struct ath6kl_common_ie {
|
||||
u16 ie_chan;
|
||||
u8 *ie_tstamp;
|
||||
u8 *ie_ssid;
|
||||
u8 *ie_rates;
|
||||
u8 *ie_xrates;
|
||||
u8 *ie_country;
|
||||
u8 *ie_wpa;
|
||||
u8 *ie_rsn;
|
||||
u8 *ie_wmm;
|
||||
u8 *ie_ath;
|
||||
u16 ie_capInfo;
|
||||
u16 ie_beaconInt;
|
||||
u8 *ie_tim;
|
||||
u8 *ie_chswitch;
|
||||
u8 ie_erp;
|
||||
u8 *ie_wsc;
|
||||
u8 *ie_htcap;
|
||||
u8 *ie_htop;
|
||||
};
|
||||
|
||||
struct bss {
|
||||
u8 ni_macaddr[ETH_ALEN];
|
||||
u8 ni_snr;
|
||||
s16 ni_rssi;
|
||||
struct bss *ni_list_next;
|
||||
struct bss *ni_list_prev;
|
||||
struct bss *ni_hash_next;
|
||||
struct bss *ni_hash_prev;
|
||||
struct ath6kl_common_ie ni_cie;
|
||||
u8 *ni_buf;
|
||||
u16 ni_framelen;
|
||||
struct ath6kl_node_table *ni_table;
|
||||
u32 ni_refcnt;
|
||||
|
||||
u32 ni_tstamp;
|
||||
u32 ni_actcnt;
|
||||
};
|
||||
|
||||
struct htc_endpoint_credit_dist;
|
||||
struct ath6kl;
|
||||
enum htc_credit_dist_reason;
|
||||
struct htc_credit_state_info;
|
||||
|
||||
struct bss *wlan_node_alloc(int wh_size);
|
||||
void wlan_node_free(struct bss *ni);
|
||||
void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni,
|
||||
const u8 *mac_addr);
|
||||
struct bss *wlan_find_node(struct ath6kl_node_table *nt,
|
||||
const u8 *mac_addr);
|
||||
void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni);
|
||||
void wlan_free_allnodes(struct ath6kl_node_table *nt);
|
||||
void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg);
|
||||
|
||||
void wlan_node_table_init(struct ath6kl_node_table *nt);
|
||||
void wlan_node_table_cleanup(struct ath6kl_node_table *nt);
|
||||
|
||||
void wlan_refresh_inactive_nodes(struct ath6kl *ar);
|
||||
|
||||
struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 *ssid,
|
||||
u32 ssid_len, bool is_wpa2, bool match_ssid);
|
||||
|
||||
void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni);
|
||||
|
||||
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,
|
||||
|
@ -21,10 +21,12 @@
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
#include "bmi.h"
|
||||
#include "target.h"
|
||||
|
||||
#define MAX_ATH6KL 1
|
||||
#define ATH6KL_MAX_RX_BUFFERS 16
|
||||
@ -42,6 +44,9 @@
|
||||
#define ATH6KL_MAX_ENDPOINTS 4
|
||||
#define MAX_NODE_NUM 15
|
||||
|
||||
/* Extra bytes for htc header alignment */
|
||||
#define ATH6KL_HTC_ALIGN_BYTES 3
|
||||
|
||||
/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
|
||||
#define MAX_DEF_COOKIE_NUM 180
|
||||
#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */
|
||||
@ -53,6 +58,35 @@
|
||||
#define A_DEFAULT_LISTEN_INTERVAL 100
|
||||
#define A_MAX_WOW_LISTEN_INTERVAL 1000
|
||||
|
||||
/* includes also the null byte */
|
||||
#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
|
||||
|
||||
enum ath6kl_fw_ie_type {
|
||||
ATH6KL_FW_IE_FW_VERSION = 0,
|
||||
ATH6KL_FW_IE_TIMESTAMP = 1,
|
||||
ATH6KL_FW_IE_OTP_IMAGE = 2,
|
||||
ATH6KL_FW_IE_FW_IMAGE = 3,
|
||||
ATH6KL_FW_IE_PATCH_IMAGE = 4,
|
||||
ATH6KL_FW_IE_RESERVED_RAM_SIZE = 5,
|
||||
ATH6KL_FW_IE_CAPABILITIES = 6,
|
||||
ATH6KL_FW_IE_PATCH_ADDR = 7,
|
||||
};
|
||||
|
||||
enum ath6kl_fw_capability {
|
||||
ATH6KL_FW_CAPABILITY_HOST_P2P = 0,
|
||||
|
||||
/* this needs to be last */
|
||||
ATH6KL_FW_CAPABILITY_MAX,
|
||||
};
|
||||
|
||||
#define ATH6KL_CAPABILITY_LEN (ALIGN(ATH6KL_FW_CAPABILITY_MAX, 32) / 32)
|
||||
|
||||
struct ath6kl_fw_ie {
|
||||
__le32 id;
|
||||
__le32 len;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
/* AR6003 1.0 definitions */
|
||||
#define AR6003_REV1_VERSION 0x300002ba
|
||||
|
||||
@ -61,7 +95,9 @@
|
||||
#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
|
||||
#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
|
||||
#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
|
||||
#define AR6003_REV2_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin"
|
||||
#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
|
||||
#define AR6003_REV2_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin"
|
||||
#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
|
||||
#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
|
||||
|
||||
@ -69,11 +105,21 @@
|
||||
#define AR6003_REV3_VERSION 0x30000582
|
||||
#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
|
||||
#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
|
||||
#define AR6003_REV3_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin"
|
||||
#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
|
||||
#define AR6003_REV3_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin"
|
||||
#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
|
||||
#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
|
||||
"ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
|
||||
|
||||
/* AR6004 1.0 definitions */
|
||||
#define AR6004_REV1_VERSION 0x30000623
|
||||
#define AR6004_REV1_FIRMWARE_FILE "ath6k/AR6004/hw6.1/fw.ram.bin"
|
||||
#define AR6004_REV1_FIRMWARE_2_FILE "ath6k/AR6004/hw6.1/fw-2.bin"
|
||||
#define AR6004_REV1_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.bin"
|
||||
#define AR6004_REV1_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw6.1/bdata.DB132.bin"
|
||||
#define AR6004_REV1_EPPING_FIRMWARE_FILE "ath6k/AR6004/hw6.1/endpointping.bin"
|
||||
|
||||
/* Per STA data, used in AP mode */
|
||||
#define STA_PS_AWAKE BIT(0)
|
||||
#define STA_PS_SLEEP BIT(1)
|
||||
@ -325,26 +371,13 @@ struct ath6kl_mbox_info {
|
||||
#define ATH6KL_KEY_RECV 0x02
|
||||
#define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */
|
||||
|
||||
/*
|
||||
* WPA/RSN get/set key request. Specify the key/cipher
|
||||
* type and whether the key is to be used for sending and/or
|
||||
* receiving. The key index should be set only when working
|
||||
* with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
|
||||
* Otherwise a unicast/pairwise key is specified by the bssid
|
||||
* (on a station) or mac address (on an ap). They key length
|
||||
* must include any MIC key data; otherwise it should be no
|
||||
* more than ATH6KL_KEYBUF_SIZE.
|
||||
*/
|
||||
/* Initial group key for AP mode */
|
||||
struct ath6kl_req_key {
|
||||
u8 ik_type; /* key/cipher type */
|
||||
u8 ik_pad;
|
||||
u16 ik_keyix; /* key index */
|
||||
u8 ik_keylen; /* key length in bytes */
|
||||
u8 ik_flags;
|
||||
u8 ik_macaddr[ETH_ALEN];
|
||||
u64 ik_keyrsc; /* key receive sequence counter */
|
||||
u64 ik_keytsc; /* key transmit sequence counter */
|
||||
u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE];
|
||||
bool valid;
|
||||
u8 key_index;
|
||||
int key_type;
|
||||
u8 key[WLAN_MAX_KEY_LEN];
|
||||
u8 key_len;
|
||||
};
|
||||
|
||||
/* Flag info */
|
||||
@ -361,6 +394,9 @@ struct ath6kl_req_key {
|
||||
#define NETDEV_REGISTERED 10
|
||||
#define SKIP_SCAN 11
|
||||
#define WLAN_ENABLED 12
|
||||
#define TESTMODE 13
|
||||
#define CLEAR_BSSFILTER_ON_BEACON 14
|
||||
#define DTIM_PERIOD_AVAIL 15
|
||||
|
||||
struct ath6kl {
|
||||
struct device *dev;
|
||||
@ -383,7 +419,7 @@ struct ath6kl {
|
||||
u8 prwise_crypto;
|
||||
u8 prwise_crypto_len;
|
||||
u8 grp_crypto;
|
||||
u8 grp_crpto_len;
|
||||
u8 grp_crypto_len;
|
||||
u8 def_txkey_index;
|
||||
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
|
||||
u8 bssid[ETH_ALEN];
|
||||
@ -392,6 +428,7 @@ struct ath6kl {
|
||||
u16 bss_ch;
|
||||
u16 listen_intvl_b;
|
||||
u16 listen_intvl_t;
|
||||
u8 lrssi_roam_threshold;
|
||||
struct ath6kl_version version;
|
||||
u32 target_type;
|
||||
u8 tx_pwr;
|
||||
@ -432,7 +469,18 @@ struct ath6kl {
|
||||
enum wlan_low_pwr_state wlan_pwr_state;
|
||||
struct wmi_scan_params_cmd sc_params;
|
||||
#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
|
||||
u8 auto_auth_stage;
|
||||
struct {
|
||||
void *rx_report;
|
||||
size_t rx_report_len;
|
||||
} tm;
|
||||
|
||||
struct {
|
||||
u32 dataset_patch_addr;
|
||||
u32 app_load_addr;
|
||||
u32 app_start_override_addr;
|
||||
u32 board_ext_data_addr;
|
||||
u32 reserved_ram_size;
|
||||
} hw;
|
||||
|
||||
u16 conf_flags;
|
||||
wait_queue_head_t event_wq;
|
||||
@ -454,9 +502,35 @@ struct ath6kl {
|
||||
u8 *fw_patch;
|
||||
size_t fw_patch_len;
|
||||
|
||||
unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN];
|
||||
|
||||
struct workqueue_struct *ath6kl_wq;
|
||||
|
||||
struct ath6kl_node_table scan_table;
|
||||
struct dentry *debugfs_phy;
|
||||
|
||||
u32 send_action_id;
|
||||
bool probe_req_report;
|
||||
u16 next_chan;
|
||||
|
||||
bool p2p;
|
||||
u16 assoc_bss_beacon_int;
|
||||
u8 assoc_bss_dtim_period;
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
struct {
|
||||
struct circ_buf fwlog_buf;
|
||||
spinlock_t fwlog_lock;
|
||||
void *fwlog_tmp;
|
||||
u32 fwlog_mask;
|
||||
unsigned int dbgfs_diag_reg;
|
||||
u32 diag_reg_addr_wr;
|
||||
u32 diag_reg_val_wr;
|
||||
|
||||
struct {
|
||||
unsigned int invalid_rate;
|
||||
} war_stats;
|
||||
} debug;
|
||||
#endif /* CONFIG_ATH6KL_DEBUG */
|
||||
};
|
||||
|
||||
static inline void *ath6kl_priv(struct net_device *dev)
|
||||
@ -474,6 +548,19 @@ static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
|
||||
cred_info->cur_free_credits -= credits;
|
||||
}
|
||||
|
||||
static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
|
||||
u32 item_offset)
|
||||
{
|
||||
u32 addr = 0;
|
||||
|
||||
if (ar->target_type == TARGET_TYPE_AR6003)
|
||||
addr = ATH6KL_AR6003_HI_START_ADDR + item_offset;
|
||||
else if (ar->target_type == TARGET_TYPE_AR6004)
|
||||
addr = ATH6KL_AR6004_HI_START_ADDR + item_offset;
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
void ath6kl_destroy(struct net_device *dev, unsigned int unregister);
|
||||
int ath6kl_configure_target(struct ath6kl *ar);
|
||||
void ath6kl_detect_error(unsigned long ptr);
|
||||
@ -487,9 +574,11 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
|
||||
struct htc_packet *packet);
|
||||
void ath6kl_stop_txrx(struct ath6kl *ar);
|
||||
void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar);
|
||||
int ath6kl_access_datadiag(struct ath6kl *ar, u32 address,
|
||||
u8 *data, u32 length, bool read);
|
||||
int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data);
|
||||
int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value);
|
||||
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_read(struct ath6kl *ar, u32 address, void *data, u32 length);
|
||||
int ath6kl_read_fwlogs(struct ath6kl *ar);
|
||||
void ath6kl_init_profile_info(struct ath6kl *ar);
|
||||
void ath6kl_tx_data_cleanup(struct ath6kl *ar);
|
||||
void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
|
||||
@ -520,6 +609,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
|
||||
u16 beacon_int, enum network_type net_type,
|
||||
u8 beacon_ie_len, u8 assoc_req_len,
|
||||
u8 assoc_resp_len, u8 *assoc_info);
|
||||
void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel);
|
||||
void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
|
||||
u8 keymgmt, u8 ucipher, u8 auth,
|
||||
u8 assoc_req_len, u8 *assoc_info);
|
||||
void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
|
||||
u8 *bssid, u8 assoc_resp_len,
|
||||
u8 *assoc_info, u16 prot_reason_status);
|
||||
@ -534,11 +627,11 @@ void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
|
||||
|
||||
void ath6kl_dtimexpiry_event(struct ath6kl *ar);
|
||||
void ath6kl_disconnect(struct ath6kl *ar);
|
||||
void ath6kl_deep_sleep_enable(struct ath6kl *ar);
|
||||
void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid);
|
||||
void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no,
|
||||
u8 win_sz);
|
||||
void ath6kl_wakeup_event(void *dev);
|
||||
void ath6kl_target_failure(struct ath6kl *ar);
|
||||
|
||||
void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni);
|
||||
#endif /* CORE_H */
|
||||
|
@ -15,7 +15,26 @@
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "debug.h"
|
||||
#include "target.h"
|
||||
|
||||
struct ath6kl_fwlog_slot {
|
||||
__le32 timestamp;
|
||||
__le32 length;
|
||||
|
||||
/* max ATH6KL_FWLOG_PAYLOAD_SIZE bytes */
|
||||
u8 payload[0];
|
||||
};
|
||||
|
||||
#define ATH6KL_FWLOG_SIZE 32768
|
||||
#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \
|
||||
ATH6KL_FWLOG_PAYLOAD_SIZE)
|
||||
#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
|
||||
|
||||
int ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
{
|
||||
@ -36,6 +55,27 @@ int ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
|
||||
#define REG_OUTPUT_LEN_PER_LINE 25
|
||||
#define REGTYPE_STR_LEN 100
|
||||
|
||||
struct ath6kl_diag_reg_info {
|
||||
u32 reg_start;
|
||||
u32 reg_end;
|
||||
const char *reg_info;
|
||||
};
|
||||
|
||||
static const struct ath6kl_diag_reg_info diag_reg[] = {
|
||||
{ 0x20000, 0x200fc, "General DMA and Rx registers" },
|
||||
{ 0x28000, 0x28900, "MAC PCU register & keycache" },
|
||||
{ 0x20800, 0x20a40, "QCU" },
|
||||
{ 0x21000, 0x212f0, "DCU" },
|
||||
{ 0x4000, 0x42e4, "RTC" },
|
||||
{ 0x540000, 0x540000 + (256 * 1024), "RAM" },
|
||||
{ 0x29800, 0x2B210, "Base Band" },
|
||||
{ 0x1C000, 0x1C748, "Analog" },
|
||||
};
|
||||
|
||||
void ath6kl_dump_registers(struct ath6kl_device *dev,
|
||||
struct ath6kl_irq_proc_registers *irq_proc_reg,
|
||||
struct ath6kl_irq_enable_reg *irq_enable_reg)
|
||||
@ -147,4 +187,748 @@ void dump_cred_dist_stats(struct htc_target *target)
|
||||
target->cred_dist_cntxt->cur_free_credits);
|
||||
}
|
||||
|
||||
static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
|
||||
{
|
||||
switch (war) {
|
||||
case ATH6KL_WAR_INVALID_RATE:
|
||||
ar->debug.war_stats.invalid_rate++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t read_file_war_stats(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
char *buf;
|
||||
unsigned int len = 0, buf_len = 1500;
|
||||
ssize_t ret_cnt;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"Workaround stats");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
|
||||
"=================");
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10u\n",
|
||||
"Invalid rates", ar->debug.war_stats.invalid_rate);
|
||||
|
||||
if (WARN_ON(len > buf_len))
|
||||
len = buf_len;
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_war_stats = {
|
||||
.read = read_file_war_stats,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
struct circ_buf *fwlog = &ar->debug.fwlog_buf;
|
||||
size_t space;
|
||||
int i;
|
||||
|
||||
/* entries must all be equal size */
|
||||
if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
|
||||
return;
|
||||
|
||||
space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE);
|
||||
if (space < buf_len)
|
||||
/* discard oldest slot */
|
||||
fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
|
||||
(ATH6KL_FWLOG_SIZE - 1);
|
||||
|
||||
for (i = 0; i < buf_len; i += space) {
|
||||
space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail,
|
||||
ATH6KL_FWLOG_SIZE);
|
||||
|
||||
if ((size_t) space > buf_len - i)
|
||||
space = buf_len - i;
|
||||
|
||||
memcpy(&fwlog->buf[fwlog->head], buf, space);
|
||||
fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
|
||||
{
|
||||
struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
|
||||
size_t slot_len;
|
||||
|
||||
if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&ar->debug.fwlog_lock);
|
||||
|
||||
slot->timestamp = cpu_to_le32(jiffies);
|
||||
slot->length = cpu_to_le32(len);
|
||||
memcpy(slot->payload, buf, len);
|
||||
|
||||
slot_len = sizeof(*slot) + len;
|
||||
|
||||
if (slot_len < ATH6KL_FWLOG_SLOT_SIZE)
|
||||
memset(slot->payload + len, 0,
|
||||
ATH6KL_FWLOG_SLOT_SIZE - slot_len);
|
||||
|
||||
ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE);
|
||||
|
||||
spin_unlock_bh(&ar->debug.fwlog_lock);
|
||||
}
|
||||
|
||||
static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar)
|
||||
{
|
||||
return CIRC_CNT(ar->debug.fwlog_buf.head,
|
||||
ar->debug.fwlog_buf.tail,
|
||||
ATH6KL_FWLOG_SLOT_SIZE) == 0;
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
struct circ_buf *fwlog = &ar->debug.fwlog_buf;
|
||||
size_t len = 0, buf_len = count;
|
||||
ssize_t ret_cnt;
|
||||
char *buf;
|
||||
int ccnt;
|
||||
|
||||
buf = vmalloc(buf_len);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/* read undelivered logs from firmware */
|
||||
ath6kl_read_fwlogs(ar);
|
||||
|
||||
spin_lock_bh(&ar->debug.fwlog_lock);
|
||||
|
||||
while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) {
|
||||
ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail,
|
||||
ATH6KL_FWLOG_SIZE);
|
||||
|
||||
if ((size_t) ccnt > buf_len - len)
|
||||
ccnt = buf_len - len;
|
||||
|
||||
memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt);
|
||||
len += ccnt;
|
||||
|
||||
fwlog->tail = (fwlog->tail + ccnt) &
|
||||
(ATH6KL_FWLOG_SIZE - 1);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->debug.fwlog_lock);
|
||||
|
||||
if (WARN_ON(len > buf_len))
|
||||
len = buf_len;
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
vfree(buf);
|
||||
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fwlog = {
|
||||
.open = ath6kl_debugfs_open,
|
||||
.read = ath6kl_fwlog_read,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
char buf[16];
|
||||
int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%x\n", ar->debug.fwlog_mask);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_fwlog_mask_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou32_from_user(user_buf, count, 0, &ar->debug.fwlog_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath6kl_wmi_config_debug_module_cmd(ar->wmi,
|
||||
ATH6KL_FWLOG_VALID_MASK,
|
||||
ar->debug.fwlog_mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fwlog_mask = {
|
||||
.open = ath6kl_debugfs_open,
|
||||
.read = ath6kl_fwlog_mask_read,
|
||||
.write = ath6kl_fwlog_mask_write,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
struct target_stats *tgt_stats = &ar->target_stats;
|
||||
char *buf;
|
||||
unsigned int len = 0, buf_len = 1500;
|
||||
int i;
|
||||
long left;
|
||||
ssize_t ret_cnt;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (down_interruptible(&ar->sem)) {
|
||||
kfree(buf);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
set_bit(STATS_UPDATE_PEND, &ar->flag);
|
||||
|
||||
if (ath6kl_wmi_get_stats_cmd(ar->wmi)) {
|
||||
up(&ar->sem);
|
||||
kfree(buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
left = wait_event_interruptible_timeout(ar->event_wq,
|
||||
!test_bit(STATS_UPDATE_PEND,
|
||||
&ar->flag), WMI_TIMEOUT);
|
||||
|
||||
up(&ar->sem);
|
||||
|
||||
if (left <= 0) {
|
||||
kfree(buf);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"Target Tx stats");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n\n",
|
||||
"=================");
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Ucast packets", tgt_stats->tx_ucast_pkt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Bcast packets", tgt_stats->tx_bcast_pkt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Ucast byte", tgt_stats->tx_ucast_byte);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Bcast byte", tgt_stats->tx_bcast_byte);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Rts success cnt", tgt_stats->tx_rts_success_cnt);
|
||||
for (i = 0; i < 4; i++)
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"%18s %d %10llu\n", "PER on ac",
|
||||
i, tgt_stats->tx_pkt_per_ac[i]);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Error", tgt_stats->tx_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Fail count", tgt_stats->tx_fail_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Retry count", tgt_stats->tx_retry_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Multi retry cnt", tgt_stats->tx_mult_retry_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Rts fail cnt", tgt_stats->tx_rts_fail_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s %10llu\n\n",
|
||||
"TKIP counter measure used",
|
||||
tgt_stats->tkip_cnter_measures_invoked);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"Target Rx stats");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"=================");
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Ucast packets", tgt_stats->rx_ucast_pkt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
|
||||
"Ucast Rate", tgt_stats->rx_ucast_rate);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Bcast packets", tgt_stats->rx_bcast_pkt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Ucast byte", tgt_stats->rx_ucast_byte);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Bcast byte", tgt_stats->rx_bcast_byte);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Fragmented pkt", tgt_stats->rx_frgment_pkt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Error", tgt_stats->rx_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"CRC Err", tgt_stats->rx_crc_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Key chache miss", tgt_stats->rx_key_cache_miss);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Decrypt Err", tgt_stats->rx_decrypt_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Duplicate frame", tgt_stats->rx_dupl_frame);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Tkip Mic failure", tgt_stats->tkip_local_mic_fail);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"TKIP format err", tgt_stats->tkip_fmt_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"CCMP format Err", tgt_stats->ccmp_fmt_err);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n\n",
|
||||
"CCMP Replay Err", tgt_stats->ccmp_replays);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"Misc Target stats");
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s\n",
|
||||
"=================");
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Beacon Miss count", tgt_stats->cs_bmiss_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Num Connects", tgt_stats->cs_connect_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10llu\n",
|
||||
"Num disconnects", tgt_stats->cs_discon_cnt);
|
||||
len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
|
||||
"Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_tgt_stats = {
|
||||
.read = read_file_tgt_stats,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#define print_credit_info(fmt_str, ep_list_field) \
|
||||
(len += scnprintf(buf + len, buf_len - len, fmt_str, \
|
||||
ep_list->ep_list_field))
|
||||
#define CREDIT_INFO_DISPLAY_STRING_LEN 200
|
||||
#define CREDIT_INFO_LEN 128
|
||||
|
||||
static ssize_t read_file_credit_dist_stats(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
struct htc_target *target = ar->htc_target;
|
||||
struct htc_endpoint_credit_dist *ep_list;
|
||||
char *buf;
|
||||
unsigned int buf_len, len = 0;
|
||||
ssize_t ret_cnt;
|
||||
|
||||
buf_len = CREDIT_INFO_DISPLAY_STRING_LEN +
|
||||
get_queue_depth(&target->cred_dist_list) * CREDIT_INFO_LEN;
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
|
||||
"Total Avail Credits: ",
|
||||
target->cred_dist_cntxt->total_avail_credits);
|
||||
len += scnprintf(buf + len, buf_len - len, "%25s%5d\n",
|
||||
"Free credits :",
|
||||
target->cred_dist_cntxt->cur_free_credits);
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
" Epid Flags Cred_norm Cred_min Credits Cred_assngd"
|
||||
" Seek_cred Cred_sz Cred_per_msg Cred_to_dist"
|
||||
" qdepth\n");
|
||||
|
||||
list_for_each_entry(ep_list, &target->cred_dist_list, list) {
|
||||
print_credit_info(" %2d", endpoint);
|
||||
print_credit_info("%10x", dist_flags);
|
||||
print_credit_info("%8d", cred_norm);
|
||||
print_credit_info("%9d", cred_min);
|
||||
print_credit_info("%9d", credits);
|
||||
print_credit_info("%10d", cred_assngd);
|
||||
print_credit_info("%13d", seek_cred);
|
||||
print_credit_info("%12d", cred_sz);
|
||||
print_credit_info("%9d", cred_per_msg);
|
||||
print_credit_info("%14d", cred_to_dist);
|
||||
len += scnprintf(buf + len, buf_len - len, "%12d\n",
|
||||
get_queue_depth(&((struct htc_endpoint *)
|
||||
ep_list->htc_rsvd)->txq));
|
||||
}
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_credit_dist_stats = {
|
||||
.read = read_file_credit_dist_stats,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static unsigned long ath6kl_get_num_reg(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long n_reg = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(diag_reg); i++)
|
||||
n_reg = n_reg +
|
||||
(diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1;
|
||||
|
||||
return n_reg;
|
||||
}
|
||||
|
||||
static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
|
||||
if (reg_addr >= diag_reg[i].reg_start &&
|
||||
reg_addr <= diag_reg[i].reg_end)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
u8 buf[50];
|
||||
unsigned int len = 0;
|
||||
|
||||
if (ar->debug.dbgfs_diag_reg)
|
||||
len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n",
|
||||
ar->debug.dbgfs_diag_reg);
|
||||
else
|
||||
len += scnprintf(buf + len, sizeof(buf) - len,
|
||||
"All diag registers\n");
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_regread_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
u8 buf[50];
|
||||
unsigned int len;
|
||||
unsigned long reg_addr;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
if (strict_strtoul(buf, 0, ®_addr))
|
||||
return -EINVAL;
|
||||
|
||||
if ((reg_addr % 4) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr))
|
||||
return -EINVAL;
|
||||
|
||||
ar->debug.dbgfs_diag_reg = reg_addr;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_diag_reg_read = {
|
||||
.read = ath6kl_regread_read,
|
||||
.write = ath6kl_regread_write,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int ath6kl_regdump_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ath6kl *ar = inode->i_private;
|
||||
u8 *buf;
|
||||
unsigned long int reg_len;
|
||||
unsigned int len = 0, n_reg;
|
||||
u32 addr;
|
||||
__le32 reg_val;
|
||||
int i, status;
|
||||
|
||||
/* Dump all the registers if no register is specified */
|
||||
if (!ar->debug.dbgfs_diag_reg)
|
||||
n_reg = ath6kl_get_num_reg();
|
||||
else
|
||||
n_reg = 1;
|
||||
|
||||
reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE;
|
||||
if (n_reg > 1)
|
||||
reg_len += REGTYPE_STR_LEN;
|
||||
|
||||
buf = vmalloc(reg_len);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (n_reg == 1) {
|
||||
addr = ar->debug.dbgfs_diag_reg;
|
||||
|
||||
status = ath6kl_diag_read32(ar,
|
||||
TARG_VTOP(ar->target_type, addr),
|
||||
(u32 *)®_val);
|
||||
if (status)
|
||||
goto fail_reg_read;
|
||||
|
||||
len += scnprintf(buf + len, reg_len - len,
|
||||
"0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val));
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
|
||||
len += scnprintf(buf + len, reg_len - len,
|
||||
"%s\n", diag_reg[i].reg_info);
|
||||
for (addr = diag_reg[i].reg_start;
|
||||
addr <= diag_reg[i].reg_end; addr += 4) {
|
||||
status = ath6kl_diag_read32(ar,
|
||||
TARG_VTOP(ar->target_type, addr),
|
||||
(u32 *)®_val);
|
||||
if (status)
|
||||
goto fail_reg_read;
|
||||
|
||||
len += scnprintf(buf + len, reg_len - len,
|
||||
"0x%06x 0x%08x\n",
|
||||
addr, le32_to_cpu(reg_val));
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
file->private_data = buf;
|
||||
return 0;
|
||||
|
||||
fail_reg_read:
|
||||
ath6kl_warn("Unable to read memory:%u\n", addr);
|
||||
vfree(buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
u8 *buf = file->private_data;
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
|
||||
}
|
||||
|
||||
static int ath6kl_regdump_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
vfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_reg_dump = {
|
||||
.open = ath6kl_regdump_open,
|
||||
.read = ath6kl_regdump_read,
|
||||
.release = ath6kl_regdump_release,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath6kl_lrssi_roam_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
unsigned long lrssi_roam_threshold;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &lrssi_roam_threshold))
|
||||
return -EINVAL;
|
||||
|
||||
ar->lrssi_roam_threshold = lrssi_roam_threshold;
|
||||
|
||||
ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_lrssi_roam_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%u\n", ar->lrssi_roam_threshold);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_lrssi_roam_threshold = {
|
||||
.read = ath6kl_lrssi_roam_read,
|
||||
.write = ath6kl_lrssi_roam_write,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath6kl_regwrite_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
u8 buf[32];
|
||||
unsigned int len = 0;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "Addr: 0x%x Val: 0x%x\n",
|
||||
ar->debug.diag_reg_addr_wr, ar->debug.diag_reg_val_wr);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t ath6kl_regwrite_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath6kl *ar = file->private_data;
|
||||
char buf[32];
|
||||
char *sptr, *token;
|
||||
unsigned int len = 0;
|
||||
u32 reg_addr, reg_val;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
sptr = buf;
|
||||
|
||||
token = strsep(&sptr, "=");
|
||||
if (!token)
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(token, 0, ®_addr))
|
||||
return -EINVAL;
|
||||
|
||||
if (!ath6kl_dbg_is_diag_reg_valid(reg_addr))
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtou32(sptr, 0, ®_val))
|
||||
return -EINVAL;
|
||||
|
||||
ar->debug.diag_reg_addr_wr = reg_addr;
|
||||
ar->debug.diag_reg_val_wr = reg_val;
|
||||
|
||||
if (ath6kl_diag_write32(ar, ar->debug.diag_reg_addr_wr,
|
||||
cpu_to_le32(ar->debug.diag_reg_val_wr)))
|
||||
return -EIO;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_diag_reg_write = {
|
||||
.read = ath6kl_regwrite_read,
|
||||
.write = ath6kl_regwrite_write,
|
||||
.open = ath6kl_debugfs_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath6kl_debug_init(struct ath6kl *ar)
|
||||
{
|
||||
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
|
||||
if (ar->debug.fwlog_buf.buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
|
||||
if (ar->debug.fwlog_tmp == NULL) {
|
||||
vfree(ar->debug.fwlog_buf.buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_init(&ar->debug.fwlog_lock);
|
||||
|
||||
/*
|
||||
* Actually we are lying here but don't know how to read the mask
|
||||
* value from the firmware.
|
||||
*/
|
||||
ar->debug.fwlog_mask = 0;
|
||||
|
||||
ar->debugfs_phy = debugfs_create_dir("ath6kl",
|
||||
ar->wdev->wiphy->debugfsdir);
|
||||
if (!ar->debugfs_phy) {
|
||||
vfree(ar->debug.fwlog_buf.buf);
|
||||
kfree(ar->debug.fwlog_tmp);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
|
||||
&fops_tgt_stats);
|
||||
|
||||
debugfs_create_file("credit_dist_stats", S_IRUSR, ar->debugfs_phy, ar,
|
||||
&fops_credit_dist_stats);
|
||||
|
||||
debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
|
||||
&fops_fwlog);
|
||||
|
||||
debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
|
||||
ar, &fops_fwlog_mask);
|
||||
|
||||
debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
|
||||
&fops_diag_reg_read);
|
||||
|
||||
debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar,
|
||||
&fops_reg_dump);
|
||||
|
||||
debugfs_create_file("lrssi_roam_threshold", S_IRUSR | S_IWUSR,
|
||||
ar->debugfs_phy, ar, &fops_lrssi_roam_threshold);
|
||||
|
||||
debugfs_create_file("reg_write", S_IRUSR | S_IWUSR,
|
||||
ar->debugfs_phy, ar, &fops_diag_reg_write);
|
||||
|
||||
debugfs_create_file("war_stats", S_IRUSR, ar->debugfs_phy, ar,
|
||||
&fops_war_stats);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath6kl_debug_cleanup(struct ath6kl *ar)
|
||||
{
|
||||
vfree(ar->debug.fwlog_buf.buf);
|
||||
kfree(ar->debug.fwlog_tmp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,8 +34,12 @@ enum ATH6K_DEBUG_MASK {
|
||||
ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */
|
||||
ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */
|
||||
ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */
|
||||
ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx and wmi frames */
|
||||
ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx frames */
|
||||
ATH6KL_DBG_AGGR = BIT(15), /* aggregation */
|
||||
ATH6KL_DBG_SDIO = BIT(16),
|
||||
ATH6KL_DBG_SDIO_DUMP = BIT(17),
|
||||
ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */
|
||||
ATH6KL_DBG_WMI_DUMP = BIT(19),
|
||||
ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
|
||||
};
|
||||
|
||||
@ -52,6 +56,10 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
|
||||
#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask)
|
||||
|
||||
enum ath6kl_war {
|
||||
ATH6KL_WAR_INVALID_RATE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH6KL_DEBUG
|
||||
#define ath6kl_dbg(mask, fmt, ...) \
|
||||
({ \
|
||||
@ -65,12 +73,14 @@ extern int ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
})
|
||||
|
||||
static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
|
||||
const char *msg, const void *buf,
|
||||
size_t len)
|
||||
const char *msg, const char *prefix,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
if (debug_mask & mask) {
|
||||
ath6kl_dbg(mask, "%s\n", msg);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
|
||||
if (msg)
|
||||
ath6kl_dbg(mask, "%s\n", msg);
|
||||
|
||||
print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,6 +88,11 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
|
||||
struct ath6kl_irq_proc_registers *irq_proc_reg,
|
||||
struct ath6kl_irq_enable_reg *irq_en_reg);
|
||||
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_war(struct ath6kl *ar, enum ath6kl_war war);
|
||||
int ath6kl_debug_init(struct ath6kl *ar);
|
||||
void ath6kl_debug_cleanup(struct ath6kl *ar);
|
||||
|
||||
#else
|
||||
static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
|
||||
const char *fmt, ...)
|
||||
@ -86,8 +101,8 @@ static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
|
||||
}
|
||||
|
||||
static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
|
||||
const char *msg, const void *buf,
|
||||
size_t len)
|
||||
const char *msg, const char *prefix,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
}
|
||||
|
||||
@ -100,6 +115,24 @@ static inline void ath6kl_dump_registers(struct ath6kl_device *dev,
|
||||
static inline void dump_cred_dist_stats(struct htc_target *target)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar,
|
||||
const void *buf, size_t len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int ath6kl_debug_init(struct ath6kl *ar)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath6kl_debug_cleanup(struct ath6kl *ar)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -69,4 +69,9 @@ static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
|
||||
return ar->hif_ops->cleanup_scatter(ar);
|
||||
}
|
||||
|
||||
static inline int ath6kl_hif_suspend(struct ath6kl *ar)
|
||||
{
|
||||
return ar->hif_ops->suspend(ar);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -202,6 +202,7 @@ struct ath6kl_hif_ops {
|
||||
int (*scat_req_rw) (struct ath6kl *ar,
|
||||
struct hif_scatter_req *scat_req);
|
||||
void (*cleanup_scatter)(struct ath6kl *ar);
|
||||
int (*suspend)(struct ath6kl *ar);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -22,8 +22,19 @@
|
||||
|
||||
#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
|
||||
|
||||
static void htc_prep_send_pkt(struct htc_packet *packet, u8 flags, int ctrl0,
|
||||
int ctrl1)
|
||||
static void ath6kl_htc_tx_buf_align(u8 **buf, unsigned long len)
|
||||
{
|
||||
u8 *align_addr;
|
||||
|
||||
if (!IS_ALIGNED((unsigned long) *buf, 4)) {
|
||||
align_addr = PTR_ALIGN(*buf - 4, 4);
|
||||
memmove(align_addr, *buf, len);
|
||||
*buf = align_addr;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath6kl_htc_tx_prep_pkt(struct htc_packet *packet, u8 flags,
|
||||
int ctrl0, int ctrl1)
|
||||
{
|
||||
struct htc_frame_hdr *hdr;
|
||||
|
||||
@ -167,7 +178,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
|
||||
htc_tx_complete(endpoint, &tx_compq);
|
||||
}
|
||||
|
||||
static int htc_issue_send(struct htc_target *target, struct htc_packet *packet)
|
||||
static int ath6kl_htc_tx_issue(struct htc_target *target,
|
||||
struct htc_packet *packet)
|
||||
{
|
||||
int status;
|
||||
bool sync = false;
|
||||
@ -196,7 +208,7 @@ static int htc_issue_send(struct htc_target *target, struct htc_packet *packet)
|
||||
HIF_WR_SYNC_BLOCK_INC);
|
||||
|
||||
packet->status = status;
|
||||
packet->buf += HTC_HDR_LENGTH;
|
||||
packet->buf += HTC_HDR_LENGTH;
|
||||
} else
|
||||
status = hif_write_async(target->dev->ar,
|
||||
target->dev->ar->mbox_info.htc_addr,
|
||||
@ -265,9 +277,9 @@ static int htc_check_credits(struct htc_target *target,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void htc_tx_pkts_get(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct list_head *queue)
|
||||
static void ath6kl_htc_tx_pkts_get(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct list_head *queue)
|
||||
{
|
||||
int req_cred;
|
||||
u8 flags;
|
||||
@ -346,11 +358,11 @@ static int htc_get_credit_padding(unsigned int cred_sz, int *len,
|
||||
return cred_pad;
|
||||
}
|
||||
|
||||
static int htc_setup_send_scat_list(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct hif_scatter_req *scat_req,
|
||||
int n_scat,
|
||||
struct list_head *queue)
|
||||
static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct hif_scatter_req *scat_req,
|
||||
int n_scat,
|
||||
struct list_head *queue)
|
||||
{
|
||||
struct htc_packet *packet;
|
||||
int i, len, rem_scat, cred_pad;
|
||||
@ -370,27 +382,23 @@ static int htc_setup_send_scat_list(struct htc_target *target,
|
||||
|
||||
cred_pad = htc_get_credit_padding(target->tgt_cred_sz,
|
||||
&len, endpoint);
|
||||
if (cred_pad < 0) {
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rem_scat < len) {
|
||||
/* exceeds what we can transfer */
|
||||
if (cred_pad < 0 || rem_scat < len) {
|
||||
status = -ENOSPC;
|
||||
break;
|
||||
}
|
||||
|
||||
rem_scat -= len;
|
||||
/* now remove it from the queue */
|
||||
packet = list_first_entry(queue, struct htc_packet, list);
|
||||
list_del(&packet->list);
|
||||
|
||||
scat_req->scat_list[i].packet = packet;
|
||||
/* prepare packet and flag message as part of a send bundle */
|
||||
htc_prep_send_pkt(packet,
|
||||
ath6kl_htc_tx_prep_pkt(packet,
|
||||
packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE,
|
||||
cred_pad, packet->info.tx.seqno);
|
||||
/* Make sure the buffer is 4-byte aligned */
|
||||
ath6kl_htc_tx_buf_align(&packet->buf,
|
||||
packet->act_len + HTC_HDR_LENGTH);
|
||||
scat_req->scat_list[i].buf = packet->buf;
|
||||
scat_req->scat_list[i].len = len;
|
||||
|
||||
@ -402,7 +410,7 @@ static int htc_setup_send_scat_list(struct htc_target *target,
|
||||
}
|
||||
|
||||
/* Roll back scatter setup in case of any failure */
|
||||
if (status || (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
|
||||
if (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE) {
|
||||
for (i = scat_req->scat_entries - 1; i >= 0; i--) {
|
||||
packet = scat_req->scat_list[i].packet;
|
||||
if (packet) {
|
||||
@ -410,31 +418,32 @@ static int htc_setup_send_scat_list(struct htc_target *target,
|
||||
list_add(&packet->list, queue);
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* htc_issue_send_bundle: drain a queue and send as bundles
|
||||
* this function may return without fully draining the queue
|
||||
* when
|
||||
* Drain a queue and send as bundles this function may return without fully
|
||||
* draining the queue when
|
||||
*
|
||||
* 1. scatter resources are exhausted
|
||||
* 2. a message that will consume a partial credit will stop the
|
||||
* bundling process early
|
||||
* 3. we drop below the minimum number of messages for a bundle
|
||||
*/
|
||||
static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
|
||||
struct list_head *queue,
|
||||
int *sent_bundle, int *n_bundle_pkts)
|
||||
static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
|
||||
struct list_head *queue,
|
||||
int *sent_bundle, int *n_bundle_pkts)
|
||||
{
|
||||
struct htc_target *target = endpoint->target;
|
||||
struct hif_scatter_req *scat_req = NULL;
|
||||
int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
|
||||
int status;
|
||||
|
||||
while (true) {
|
||||
status = 0;
|
||||
n_scat = get_queue_depth(queue);
|
||||
n_scat = min(n_scat, target->msg_per_bndl_max);
|
||||
|
||||
@ -457,8 +466,10 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
|
||||
scat_req->len = 0;
|
||||
scat_req->scat_entries = 0;
|
||||
|
||||
if (htc_setup_send_scat_list(target, endpoint, scat_req,
|
||||
n_scat, queue)) {
|
||||
status = ath6kl_htc_tx_setup_scat_list(target, endpoint,
|
||||
scat_req, n_scat,
|
||||
queue);
|
||||
if (status == -EAGAIN) {
|
||||
hif_scatter_req_add(target->dev->ar, scat_req);
|
||||
break;
|
||||
}
|
||||
@ -472,18 +483,21 @@ static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
|
||||
"send scatter total bytes: %d , entries: %d\n",
|
||||
scat_req->len, scat_req->scat_entries);
|
||||
ath6kldev_submit_scat_req(target->dev, scat_req, false);
|
||||
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
|
||||
*sent_bundle = n_sent_bundle;
|
||||
*n_bundle_pkts = tot_pkts_bundle;
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_issue_send_bundle (sent:%d)\n",
|
||||
n_sent_bundle);
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s (sent:%d)\n",
|
||||
__func__, n_sent_bundle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void htc_tx_from_ep_txq(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint)
|
||||
static void ath6kl_htc_tx_from_queue(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint)
|
||||
{
|
||||
struct list_head txq;
|
||||
struct htc_packet *packet;
|
||||
@ -511,7 +525,7 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
|
||||
if (list_empty(&endpoint->txq))
|
||||
break;
|
||||
|
||||
htc_tx_pkts_get(target, endpoint, &txq);
|
||||
ath6kl_htc_tx_pkts_get(target, endpoint, &txq);
|
||||
|
||||
if (list_empty(&txq))
|
||||
break;
|
||||
@ -528,8 +542,8 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
|
||||
HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
|
||||
int temp1 = 0, temp2 = 0;
|
||||
|
||||
htc_issue_send_bundle(endpoint, &txq,
|
||||
&temp1, &temp2);
|
||||
ath6kl_htc_tx_bundle(endpoint, &txq,
|
||||
&temp1, &temp2);
|
||||
bundle_sent += temp1;
|
||||
n_pkts_bundle += temp2;
|
||||
}
|
||||
@ -541,9 +555,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
|
||||
list);
|
||||
list_del(&packet->list);
|
||||
|
||||
htc_prep_send_pkt(packet, packet->info.tx.flags,
|
||||
0, packet->info.tx.seqno);
|
||||
htc_issue_send(target, packet);
|
||||
ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags,
|
||||
0, packet->info.tx.seqno);
|
||||
ath6kl_htc_tx_issue(target, packet);
|
||||
}
|
||||
|
||||
spin_lock_bh(&target->tx_lock);
|
||||
@ -556,9 +570,9 @@ static void htc_tx_from_ep_txq(struct htc_target *target,
|
||||
spin_unlock_bh(&target->tx_lock);
|
||||
}
|
||||
|
||||
static bool htc_try_send(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct htc_packet *tx_pkt)
|
||||
static bool ath6kl_htc_tx_try(struct htc_target *target,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct htc_packet *tx_pkt)
|
||||
{
|
||||
struct htc_ep_callbacks ep_cb;
|
||||
int txq_depth;
|
||||
@ -594,7 +608,7 @@ static bool htc_try_send(struct htc_target *target,
|
||||
list_add_tail(&tx_pkt->list, &endpoint->txq);
|
||||
spin_unlock_bh(&target->tx_lock);
|
||||
|
||||
htc_tx_from_ep_txq(target, endpoint);
|
||||
ath6kl_htc_tx_from_queue(target, endpoint);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -628,7 +642,7 @@ static void htc_chk_ep_txq(struct htc_target *target)
|
||||
* chance to reclaim credits from lower priority
|
||||
* ones.
|
||||
*/
|
||||
htc_tx_from_ep_txq(target, endpoint);
|
||||
ath6kl_htc_tx_from_queue(target, endpoint);
|
||||
spin_lock_bh(&target->tx_lock);
|
||||
}
|
||||
spin_unlock_bh(&target->tx_lock);
|
||||
@ -680,8 +694,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
|
||||
|
||||
/* we want synchronous operation */
|
||||
send_pkt->completion = NULL;
|
||||
htc_prep_send_pkt(send_pkt, 0, 0, 0);
|
||||
status = htc_issue_send(target, send_pkt);
|
||||
ath6kl_htc_tx_prep_pkt(send_pkt, 0, 0, 0);
|
||||
status = ath6kl_htc_tx_issue(target, send_pkt);
|
||||
|
||||
if (send_pkt != NULL)
|
||||
htc_reclaim_txctrl_buf(target, send_pkt);
|
||||
@ -733,7 +747,7 @@ int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
|
||||
|
||||
endpoint = &target->endpoint[packet->endpoint];
|
||||
|
||||
if (!htc_try_send(target, endpoint, packet)) {
|
||||
if (!ath6kl_htc_tx_try(target, endpoint, packet)) {
|
||||
packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ?
|
||||
-ECANCELED : -ENOSPC;
|
||||
INIT_LIST_HEAD(&queue);
|
||||
@ -846,8 +860,8 @@ void ath6kl_htc_indicate_activity_change(struct htc_target *target,
|
||||
|
||||
/* HTC Rx */
|
||||
|
||||
static inline void htc_update_rx_stats(struct htc_endpoint *endpoint,
|
||||
int n_look_ahds)
|
||||
static inline void ath6kl_htc_rx_update_stats(struct htc_endpoint *endpoint,
|
||||
int n_look_ahds)
|
||||
{
|
||||
endpoint->ep_st.rx_pkts++;
|
||||
if (n_look_ahds == 1)
|
||||
@ -894,8 +908,9 @@ static void reclaim_rx_ctrl_buf(struct htc_target *target,
|
||||
spin_unlock_bh(&target->htc_lock);
|
||||
}
|
||||
|
||||
static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet,
|
||||
u32 rx_len)
|
||||
static int ath6kl_htc_rx_packet(struct htc_target *target,
|
||||
struct htc_packet *packet,
|
||||
u32 rx_len)
|
||||
{
|
||||
struct ath6kl_device *dev = target->dev;
|
||||
u32 padded_len;
|
||||
@ -929,9 +944,9 @@ static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet,
|
||||
* "hint" that there are more single-packets to fetch
|
||||
* on this endpoint.
|
||||
*/
|
||||
static void set_rxpkt_indication_flag(u32 lk_ahd,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct htc_packet *packet)
|
||||
static void ath6kl_htc_rx_set_indicate(u32 lk_ahd,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct htc_packet *packet)
|
||||
{
|
||||
struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd;
|
||||
|
||||
@ -942,7 +957,7 @@ static void set_rxpkt_indication_flag(u32 lk_ahd,
|
||||
}
|
||||
}
|
||||
|
||||
static void chk_rx_water_mark(struct htc_endpoint *endpoint)
|
||||
static void ath6kl_htc_rx_chk_water_mark(struct htc_endpoint *endpoint)
|
||||
{
|
||||
struct htc_ep_callbacks ep_cb = endpoint->ep_cb;
|
||||
|
||||
@ -959,8 +974,9 @@ static void chk_rx_water_mark(struct htc_endpoint *endpoint)
|
||||
}
|
||||
|
||||
/* This function is called with rx_lock held */
|
||||
static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep,
|
||||
u32 *lk_ahds, struct list_head *queue, int n_msg)
|
||||
static int ath6kl_htc_rx_setup(struct htc_target *target,
|
||||
struct htc_endpoint *ep,
|
||||
u32 *lk_ahds, struct list_head *queue, int n_msg)
|
||||
{
|
||||
struct htc_packet *packet;
|
||||
/* FIXME: type of lk_ahds can't be right */
|
||||
@ -1060,10 +1076,10 @@ static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep,
|
||||
return status;
|
||||
}
|
||||
|
||||
static int alloc_and_prep_rxpkts(struct htc_target *target,
|
||||
u32 lk_ahds[], int msg,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct list_head *queue)
|
||||
static int ath6kl_htc_rx_alloc(struct htc_target *target,
|
||||
u32 lk_ahds[], int msg,
|
||||
struct htc_endpoint *endpoint,
|
||||
struct list_head *queue)
|
||||
{
|
||||
int status = 0;
|
||||
struct htc_packet *packet, *tmp_pkt;
|
||||
@ -1129,8 +1145,8 @@ static int alloc_and_prep_rxpkts(struct htc_target *target,
|
||||
n_msg = 1;
|
||||
|
||||
/* Setup packet buffers for each message */
|
||||
status = htc_setup_rxpkts(target, endpoint, &lk_ahds[i], queue,
|
||||
n_msg);
|
||||
status = ath6kl_htc_rx_setup(target, endpoint, &lk_ahds[i],
|
||||
queue, n_msg);
|
||||
|
||||
/*
|
||||
* This is due to unavailabilty of buffers to rx entire data.
|
||||
@ -1176,9 +1192,9 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
|
||||
packets->act_len + HTC_HDR_LENGTH);
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
|
||||
"Unexpected ENDPOINT 0 Message",
|
||||
packets->buf - HTC_HDR_LENGTH,
|
||||
packets->act_len + HTC_HDR_LENGTH);
|
||||
"Unexpected ENDPOINT 0 Message", "",
|
||||
packets->buf - HTC_HDR_LENGTH,
|
||||
packets->act_len + HTC_HDR_LENGTH);
|
||||
}
|
||||
|
||||
htc_reclaim_rxbuf(context, packets, &context->endpoint[0]);
|
||||
@ -1312,7 +1328,7 @@ static int htc_parse_trailer(struct htc_target *target,
|
||||
memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4);
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead",
|
||||
next_lk_ahds, 4);
|
||||
"", next_lk_ahds, 4);
|
||||
|
||||
*n_lk_ahds = 1;
|
||||
}
|
||||
@ -1331,7 +1347,7 @@ static int htc_parse_trailer(struct htc_target *target,
|
||||
(struct htc_bundle_lkahd_rpt *) record_buf;
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd",
|
||||
record_buf, record->len);
|
||||
"", record_buf, record->len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
memcpy((u8 *)&next_lk_ahds[i],
|
||||
@ -1364,7 +1380,8 @@ static int htc_proc_trailer(struct htc_target *target,
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len);
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", buf, len);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", "",
|
||||
buf, len);
|
||||
|
||||
orig_buf = buf;
|
||||
orig_len = len;
|
||||
@ -1402,14 +1419,14 @@ static int htc_proc_trailer(struct htc_target *target,
|
||||
|
||||
if (status)
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer",
|
||||
orig_buf, orig_len);
|
||||
"", orig_buf, orig_len);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int htc_proc_rxhdr(struct htc_target *target,
|
||||
struct htc_packet *packet,
|
||||
u32 *next_lkahds, int *n_lkahds)
|
||||
static int ath6kl_htc_rx_process_hdr(struct htc_target *target,
|
||||
struct htc_packet *packet,
|
||||
u32 *next_lkahds, int *n_lkahds)
|
||||
{
|
||||
int status = 0;
|
||||
u16 payload_len;
|
||||
@ -1419,8 +1436,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
|
||||
if (n_lkahds != NULL)
|
||||
*n_lkahds = 0;
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", packet->buf,
|
||||
packet->act_len);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", "htc ",
|
||||
packet->buf, packet->act_len);
|
||||
|
||||
/*
|
||||
* NOTE: we cannot assume the alignment of buf, so we use the safe
|
||||
@ -1461,12 +1478,12 @@ static int htc_proc_rxhdr(struct htc_target *target,
|
||||
}
|
||||
|
||||
if (lk_ahd != packet->info.rx.exp_hdr) {
|
||||
ath6kl_err("htc_proc_rxhdr, lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n",
|
||||
packet, packet->info.rx.rx_flags);
|
||||
ath6kl_err("%s(): lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n",
|
||||
__func__, packet, packet->info.rx.rx_flags);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd",
|
||||
&packet->info.rx.exp_hdr, 4);
|
||||
"", &packet->info.rx.exp_hdr, 4);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header",
|
||||
(u8 *)&lk_ahd, sizeof(lk_ahd));
|
||||
"", (u8 *)&lk_ahd, sizeof(lk_ahd));
|
||||
status = -ENOMEM;
|
||||
goto fail_rx;
|
||||
}
|
||||
@ -1474,8 +1491,8 @@ static int htc_proc_rxhdr(struct htc_target *target,
|
||||
if (htc_hdr->flags & HTC_FLG_RX_TRAILER) {
|
||||
if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) ||
|
||||
htc_hdr->ctrl[0] > payload_len) {
|
||||
ath6kl_err("htc_proc_rxhdr, invalid hdr (payload len should be :%d, CB[0] is:%d)\n",
|
||||
payload_len, htc_hdr->ctrl[0]);
|
||||
ath6kl_err("%s(): invalid hdr (payload len should be :%d, CB[0] is:%d)\n",
|
||||
__func__, payload_len, htc_hdr->ctrl[0]);
|
||||
status = -ENOMEM;
|
||||
goto fail_rx;
|
||||
}
|
||||
@ -1502,20 +1519,20 @@ static int htc_proc_rxhdr(struct htc_target *target,
|
||||
fail_rx:
|
||||
if (status)
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT",
|
||||
packet->buf,
|
||||
"", packet->buf,
|
||||
packet->act_len < 256 ? packet->act_len : 256);
|
||||
else {
|
||||
if (packet->act_len > 0)
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
|
||||
"HTC - Application Msg",
|
||||
"HTC - Application Msg", "",
|
||||
packet->buf, packet->act_len);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void do_rx_completion(struct htc_endpoint *endpoint,
|
||||
struct htc_packet *packet)
|
||||
static void ath6kl_htc_rx_complete(struct htc_endpoint *endpoint,
|
||||
struct htc_packet *packet)
|
||||
{
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
|
||||
"htc calling ep %d recv callback on packet 0x%p\n",
|
||||
@ -1523,10 +1540,10 @@ static void do_rx_completion(struct htc_endpoint *endpoint,
|
||||
endpoint->ep_cb.rx(endpoint->target, packet);
|
||||
}
|
||||
|
||||
static int htc_issue_rxpkt_bundle(struct htc_target *target,
|
||||
struct list_head *rxq,
|
||||
struct list_head *sync_compq,
|
||||
int *n_pkt_fetched, bool part_bundle)
|
||||
static int ath6kl_htc_rx_bundle(struct htc_target *target,
|
||||
struct list_head *rxq,
|
||||
struct list_head *sync_compq,
|
||||
int *n_pkt_fetched, bool part_bundle)
|
||||
{
|
||||
struct hif_scatter_req *scat_req;
|
||||
struct htc_packet *packet;
|
||||
@ -1548,15 +1565,15 @@ static int htc_issue_rxpkt_bundle(struct htc_target *target,
|
||||
* This would only happen if the target ignored our max
|
||||
* bundle limit.
|
||||
*/
|
||||
ath6kl_warn("htc_issue_rxpkt_bundle : partial bundle detected num:%d , %d\n",
|
||||
get_queue_depth(rxq), n_scat_pkt);
|
||||
ath6kl_warn("%s(): partial bundle detected num:%d , %d\n",
|
||||
__func__, get_queue_depth(rxq), n_scat_pkt);
|
||||
}
|
||||
|
||||
len = 0;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
|
||||
"htc_issue_rxpkt_bundle (numpackets: %d , actual : %d)\n",
|
||||
get_queue_depth(rxq), n_scat_pkt);
|
||||
"%s(): (numpackets: %d , actual : %d)\n",
|
||||
__func__, get_queue_depth(rxq), n_scat_pkt);
|
||||
|
||||
scat_req = hif_scatter_req_get(target->dev->ar);
|
||||
|
||||
@ -1616,9 +1633,10 @@ fail_rx_pkt:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int htc_proc_fetched_rxpkts(struct htc_target *target,
|
||||
struct list_head *comp_pktq, u32 lk_ahds[],
|
||||
int *n_lk_ahd)
|
||||
static int ath6kl_htc_rx_process_packets(struct htc_target *target,
|
||||
struct list_head *comp_pktq,
|
||||
u32 lk_ahds[],
|
||||
int *n_lk_ahd)
|
||||
{
|
||||
struct htc_packet *packet, *tmp_pkt;
|
||||
struct htc_endpoint *ep;
|
||||
@ -1629,7 +1647,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
|
||||
ep = &target->endpoint[packet->endpoint];
|
||||
|
||||
/* process header for each of the recv packet */
|
||||
status = htc_proc_rxhdr(target, packet, lk_ahds, n_lk_ahd);
|
||||
status = ath6kl_htc_rx_process_hdr(target, packet, lk_ahds,
|
||||
n_lk_ahd);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@ -1639,8 +1658,8 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
|
||||
* based on the lookahead.
|
||||
*/
|
||||
if (*n_lk_ahd > 0)
|
||||
set_rxpkt_indication_flag(lk_ahds[0],
|
||||
ep, packet);
|
||||
ath6kl_htc_rx_set_indicate(lk_ahds[0],
|
||||
ep, packet);
|
||||
} else
|
||||
/*
|
||||
* Packets in a bundle automatically have
|
||||
@ -1649,20 +1668,20 @@ static int htc_proc_fetched_rxpkts(struct htc_target *target,
|
||||
packet->info.rx.indicat_flags |=
|
||||
HTC_RX_FLAGS_INDICATE_MORE_PKTS;
|
||||
|
||||
htc_update_rx_stats(ep, *n_lk_ahd);
|
||||
ath6kl_htc_rx_update_stats(ep, *n_lk_ahd);
|
||||
|
||||
if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE)
|
||||
ep->ep_st.rx_bundl += 1;
|
||||
|
||||
do_rx_completion(ep, packet);
|
||||
ath6kl_htc_rx_complete(ep, packet);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int htc_fetch_rxpkts(struct htc_target *target,
|
||||
struct list_head *rx_pktq,
|
||||
struct list_head *comp_pktq)
|
||||
static int ath6kl_htc_rx_fetch(struct htc_target *target,
|
||||
struct list_head *rx_pktq,
|
||||
struct list_head *comp_pktq)
|
||||
{
|
||||
int fetched_pkts;
|
||||
bool part_bundle = false;
|
||||
@ -1678,10 +1697,10 @@ static int htc_fetch_rxpkts(struct htc_target *target,
|
||||
* bundle transfer and recv bundling is
|
||||
* allowed.
|
||||
*/
|
||||
status = htc_issue_rxpkt_bundle(target, rx_pktq,
|
||||
comp_pktq,
|
||||
&fetched_pkts,
|
||||
part_bundle);
|
||||
status = ath6kl_htc_rx_bundle(target, rx_pktq,
|
||||
comp_pktq,
|
||||
&fetched_pkts,
|
||||
part_bundle);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@ -1710,7 +1729,8 @@ static int htc_fetch_rxpkts(struct htc_target *target,
|
||||
HTC_RX_PKT_IGNORE_LOOKAHEAD;
|
||||
|
||||
/* go fetch the packet */
|
||||
status = dev_rx_pkt(target, packet, packet->act_len);
|
||||
status = ath6kl_htc_rx_packet(target, packet,
|
||||
packet->act_len);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@ -1764,9 +1784,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
|
||||
* Try to allocate as many HTC RX packets indicated by the
|
||||
* look_aheads.
|
||||
*/
|
||||
status = alloc_and_prep_rxpkts(target, look_aheads,
|
||||
num_look_ahead, endpoint,
|
||||
&rx_pktq);
|
||||
status = ath6kl_htc_rx_alloc(target, look_aheads,
|
||||
num_look_ahead, endpoint,
|
||||
&rx_pktq);
|
||||
if (status)
|
||||
break;
|
||||
|
||||
@ -1781,14 +1801,15 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
|
||||
|
||||
num_look_ahead = 0;
|
||||
|
||||
status = htc_fetch_rxpkts(target, &rx_pktq, &comp_pktq);
|
||||
status = ath6kl_htc_rx_fetch(target, &rx_pktq, &comp_pktq);
|
||||
|
||||
if (!status)
|
||||
chk_rx_water_mark(endpoint);
|
||||
ath6kl_htc_rx_chk_water_mark(endpoint);
|
||||
|
||||
/* Process fetched packets */
|
||||
status = htc_proc_fetched_rxpkts(target, &comp_pktq,
|
||||
look_aheads, &num_look_ahead);
|
||||
status = ath6kl_htc_rx_process_packets(target, &comp_pktq,
|
||||
look_aheads,
|
||||
&num_look_ahead);
|
||||
|
||||
if (!num_look_ahead || status)
|
||||
break;
|
||||
@ -1881,14 +1902,14 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
|
||||
packet->completion = NULL;
|
||||
|
||||
/* get the message from the device, this will block */
|
||||
if (dev_rx_pkt(target, packet, packet->act_len))
|
||||
if (ath6kl_htc_rx_packet(target, packet, packet->act_len))
|
||||
goto fail_ctrl_rx;
|
||||
|
||||
/* process receive header */
|
||||
packet->status = htc_proc_rxhdr(target, packet, NULL, NULL);
|
||||
packet->status = ath6kl_htc_rx_process_hdr(target, packet, NULL, NULL);
|
||||
|
||||
if (packet->status) {
|
||||
ath6kl_err("htc_wait_for_ctrl_msg, htc_proc_rxhdr failed (status = %d)\n",
|
||||
ath6kl_err("htc_wait_for_ctrl_msg, ath6kl_htc_rx_process_hdr failed (status = %d)\n",
|
||||
packet->status);
|
||||
goto fail_ctrl_rx;
|
||||
}
|
||||
@ -1935,7 +1956,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
|
||||
list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) {
|
||||
packet->status = -ECANCELED;
|
||||
list_del(&packet->list);
|
||||
do_rx_completion(endpoint, packet);
|
||||
ath6kl_htc_rx_complete(endpoint, packet);
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -2034,8 +2055,8 @@ int ath6kl_htc_conn_service(struct htc_target *target,
|
||||
|
||||
/* we want synchronous operation */
|
||||
tx_pkt->completion = NULL;
|
||||
htc_prep_send_pkt(tx_pkt, 0, 0, 0);
|
||||
status = htc_issue_send(target, tx_pkt);
|
||||
ath6kl_htc_tx_prep_pkt(tx_pkt, 0, 0, 0);
|
||||
status = ath6kl_htc_tx_issue(target, tx_pkt);
|
||||
|
||||
if (status)
|
||||
goto fail_tx;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,8 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
|
||||
|
||||
sta = &ar->sta_list[free_slot];
|
||||
memcpy(sta->mac, mac, ETH_ALEN);
|
||||
memcpy(sta->wpa_ie, wpaie, ielen);
|
||||
if (ielen <= ATH6KL_MAX_IE)
|
||||
memcpy(sta->wpa_ie, wpaie, ielen);
|
||||
sta->aid = aid;
|
||||
sta->keymgmt = keymgmt;
|
||||
sta->ucipher = ucipher;
|
||||
@ -177,8 +178,8 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
|
||||
static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
|
||||
{
|
||||
int status;
|
||||
u8 addr_val[4];
|
||||
s32 i;
|
||||
__le32 addr_val;
|
||||
|
||||
/*
|
||||
* Write bytes 1,2,3 of the register to set the upper address bytes,
|
||||
@ -188,16 +189,18 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
|
||||
for (i = 1; i <= 3; i++) {
|
||||
/*
|
||||
* Fill the buffer with the address byte value we want to
|
||||
* hit 4 times.
|
||||
* hit 4 times. No need to worry about endianness as the
|
||||
* same byte is copied to all four bytes of addr_val at
|
||||
* any time.
|
||||
*/
|
||||
memset(addr_val, ((u8 *)&addr)[i], 4);
|
||||
memset((u8 *)&addr_val, ((u8 *)&addr)[i], 4);
|
||||
|
||||
/*
|
||||
* Hit each byte of the register address with a 4-byte
|
||||
* write operation to the same address, this is a harmless
|
||||
* operation.
|
||||
*/
|
||||
status = hif_read_write_sync(ar, reg_addr + i, addr_val,
|
||||
status = hif_read_write_sync(ar, reg_addr + i, (u8 *)&addr_val,
|
||||
4, HIF_WR_SYNC_BYTE_FIX);
|
||||
if (status)
|
||||
break;
|
||||
@ -215,7 +218,9 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
|
||||
* cycle to start, the extra 3 byte write to bytes 1,2,3 has no
|
||||
* effect since we are writing the same values again
|
||||
*/
|
||||
status = hif_read_write_sync(ar, reg_addr, (u8 *)(&addr),
|
||||
addr_val = cpu_to_le32(addr);
|
||||
status = hif_read_write_sync(ar, reg_addr,
|
||||
(u8 *)&(addr_val),
|
||||
4, HIF_WR_SYNC_BYTE_INC);
|
||||
|
||||
if (status) {
|
||||
@ -228,90 +233,193 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the ATH6KL through its diagnostic window. No cooperation from
|
||||
* the Target is required for this.
|
||||
* Read from the hardware through its diagnostic window. No cooperation
|
||||
* from the firmware is required for this.
|
||||
*/
|
||||
int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data)
|
||||
int ath6kl_diag_read32(struct ath6kl *ar, u32 address, u32 *value)
|
||||
{
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
/* set window register to start read cycle */
|
||||
status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS,
|
||||
*address);
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
ret = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS, address);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read the data */
|
||||
status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data,
|
||||
sizeof(u32), HIF_RD_SYNC_BYTE_INC);
|
||||
if (status) {
|
||||
ath6kl_err("failed to read from window data addr\n");
|
||||
return status;
|
||||
ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) value,
|
||||
sizeof(*value), HIF_RD_SYNC_BYTE_INC);
|
||||
if (ret) {
|
||||
ath6kl_warn("failed to read32 through diagnose window: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write to the ATH6KL through its diagnostic window. No cooperation from
|
||||
* the Target is required for this.
|
||||
*/
|
||||
static int ath6kl_write_reg_diag(struct ath6kl *ar, u32 *address, u32 *data)
|
||||
int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value)
|
||||
{
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
/* set write data */
|
||||
status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data,
|
||||
sizeof(u32), HIF_WR_SYNC_BYTE_INC);
|
||||
if (status) {
|
||||
ath6kl_err("failed to write 0x%x to window data addr\n", *data);
|
||||
return status;
|
||||
ret = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *) &value,
|
||||
sizeof(value), HIF_WR_SYNC_BYTE_INC);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n",
|
||||
address, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set window register, which starts the write cycle */
|
||||
return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS,
|
||||
*address);
|
||||
address);
|
||||
}
|
||||
|
||||
int ath6kl_access_datadiag(struct ath6kl *ar, u32 address,
|
||||
u8 *data, u32 length, bool read)
|
||||
int ath6kl_diag_read(struct ath6kl *ar, u32 address, void *data, u32 length)
|
||||
{
|
||||
u32 count;
|
||||
int status = 0;
|
||||
u32 count, *buf = data;
|
||||
int ret;
|
||||
|
||||
for (count = 0; count < length; count += 4, address += 4) {
|
||||
if (read) {
|
||||
status = ath6kl_read_reg_diag(ar, &address,
|
||||
(u32 *) &data[count]);
|
||||
if (status)
|
||||
break;
|
||||
} else {
|
||||
status = ath6kl_write_reg_diag(ar, &address,
|
||||
(u32 *) &data[count]);
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
if (WARN_ON(length % 4))
|
||||
return -EINVAL;
|
||||
|
||||
for (count = 0; count < length / 4; count++, address += 4) {
|
||||
ret = ath6kl_diag_read32(ar, address, &buf[count]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath6kl_diag_write(struct ath6kl *ar, u32 address, void *data, u32 length)
|
||||
{
|
||||
u32 count;
|
||||
__le32 *buf = data;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(length % 4))
|
||||
return -EINVAL;
|
||||
|
||||
for (count = 0; count < length / 4; count++, address += 4) {
|
||||
ret = ath6kl_diag_write32(ar, address, buf[count]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath6kl_read_fwlogs(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_dbglog_hdr debug_hdr;
|
||||
struct ath6kl_dbglog_buf debug_buf;
|
||||
u32 address, length, dropped, firstbuf, debug_hdr_addr;
|
||||
int ret = 0, loop;
|
||||
u8 *buf;
|
||||
|
||||
buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
ath6kl_get_hi_item_addr(ar,
|
||||
HI_ITEM(hi_dbglog_hdr)));
|
||||
|
||||
ret = ath6kl_diag_read32(ar, address, &debug_hdr_addr);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Get the contents of the ring buffer */
|
||||
if (debug_hdr_addr == 0) {
|
||||
ath6kl_warn("Invalid address for debug_hdr_addr\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
address = TARG_VTOP(ar->target_type, debug_hdr_addr);
|
||||
ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
|
||||
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_hdr.dbuf_addr));
|
||||
firstbuf = address;
|
||||
dropped = le32_to_cpu(debug_hdr.dropped);
|
||||
ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
|
||||
loop = 100;
|
||||
|
||||
do {
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_buf.buffer_addr));
|
||||
length = le32_to_cpu(debug_buf.length);
|
||||
|
||||
if (length != 0 && (le32_to_cpu(debug_buf.length) <=
|
||||
le32_to_cpu(debug_buf.bufsize))) {
|
||||
length = ALIGN(length, 4);
|
||||
|
||||
ret = ath6kl_diag_read(ar, address,
|
||||
buf, length);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ath6kl_debug_fwlog_event(ar, buf, length);
|
||||
}
|
||||
|
||||
address = TARG_VTOP(ar->target_type,
|
||||
le32_to_cpu(debug_buf.next));
|
||||
ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
loop--;
|
||||
|
||||
if (WARN_ON(loop == 0)) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
} while (address != firstbuf);
|
||||
|
||||
out:
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: move to a better place, target.h? */
|
||||
#define AR6003_RESET_CONTROL_ADDRESS 0x00004000
|
||||
#define AR6004_RESET_CONTROL_ADDRESS 0x00004000
|
||||
|
||||
static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
|
||||
bool wait_fot_compltn, bool cold_reset)
|
||||
{
|
||||
int status = 0;
|
||||
u32 address;
|
||||
u32 data;
|
||||
__le32 data;
|
||||
|
||||
if (target_type != TARGET_TYPE_AR6003)
|
||||
if (target_type != TARGET_TYPE_AR6003 &&
|
||||
target_type != TARGET_TYPE_AR6004)
|
||||
return;
|
||||
|
||||
data = cold_reset ? RESET_CONTROL_COLD_RST : RESET_CONTROL_MBOX_RST;
|
||||
data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
|
||||
cpu_to_le32(RESET_CONTROL_MBOX_RST);
|
||||
|
||||
address = RTC_BASE_ADDRESS;
|
||||
status = ath6kl_write_reg_diag(ar, &address, &data);
|
||||
switch (target_type) {
|
||||
case TARGET_TYPE_AR6003:
|
||||
address = AR6003_RESET_CONTROL_ADDRESS;
|
||||
break;
|
||||
case TARGET_TYPE_AR6004:
|
||||
address = AR6004_RESET_CONTROL_ADDRESS;
|
||||
break;
|
||||
default:
|
||||
address = AR6003_RESET_CONTROL_ADDRESS;
|
||||
break;
|
||||
}
|
||||
|
||||
status = ath6kl_diag_write32(ar, address, data);
|
||||
|
||||
if (status)
|
||||
ath6kl_err("failed to reset target\n");
|
||||
@ -411,68 +519,107 @@ static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
|
||||
u16 listen_int, u16 beacon_int,
|
||||
u8 assoc_resp_len, u8 *assoc_info)
|
||||
void ath6kl_connect_ap_mode_bss(struct ath6kl *ar, u16 channel)
|
||||
{
|
||||
struct net_device *dev = ar->net_dev;
|
||||
struct station_info sinfo;
|
||||
struct ath6kl_req_key *ik;
|
||||
enum crypto_type keyType = NONE_CRYPT;
|
||||
int res;
|
||||
u8 key_rsc[ATH6KL_KEY_SEQ_LEN];
|
||||
|
||||
if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) {
|
||||
ik = &ar->ap_mode_bkey;
|
||||
ik = &ar->ap_mode_bkey;
|
||||
|
||||
switch (ar->auth_mode) {
|
||||
case NONE_AUTH:
|
||||
if (ar->prwise_crypto == WEP_CRYPT)
|
||||
ath6kl_install_static_wep_keys(ar);
|
||||
break;
|
||||
case WPA_PSK_AUTH:
|
||||
case WPA2_PSK_AUTH:
|
||||
case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
|
||||
switch (ik->ik_type) {
|
||||
case ATH6KL_CIPHER_TKIP:
|
||||
keyType = TKIP_CRYPT;
|
||||
break;
|
||||
case ATH6KL_CIPHER_AES_CCM:
|
||||
keyType = AES_CRYPT;
|
||||
break;
|
||||
default:
|
||||
goto skip_key;
|
||||
}
|
||||
ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType,
|
||||
GROUP_USAGE, ik->ik_keylen,
|
||||
(u8 *)&ik->ik_keyrsc,
|
||||
ik->ik_keydata,
|
||||
KEY_OP_INIT_VAL, ik->ik_macaddr,
|
||||
SYNC_BOTH_WMIFLAG);
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);
|
||||
|
||||
switch (ar->auth_mode) {
|
||||
case NONE_AUTH:
|
||||
if (ar->prwise_crypto == WEP_CRYPT)
|
||||
ath6kl_install_static_wep_keys(ar);
|
||||
break;
|
||||
case WPA_PSK_AUTH:
|
||||
case WPA2_PSK_AUTH:
|
||||
case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
|
||||
if (!ik->valid)
|
||||
break;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
|
||||
"the initial group key for AP mode\n");
|
||||
memset(key_rsc, 0, sizeof(key_rsc));
|
||||
res = ath6kl_wmi_addkey_cmd(
|
||||
ar->wmi, ik->key_index, ik->key_type,
|
||||
GROUP_USAGE, ik->key_len, key_rsc, ik->key,
|
||||
KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
|
||||
if (res) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
|
||||
"addkey failed: %d\n", res);
|
||||
}
|
||||
skip_key:
|
||||
set_bit(CONNECTED, &ar->flag);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n",
|
||||
bssid, channel);
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
|
||||
set_bit(CONNECTED, &ar->flag);
|
||||
netif_carrier_on(ar->net_dev);
|
||||
}
|
||||
|
||||
ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len,
|
||||
listen_int & 0xFF, beacon_int,
|
||||
(listen_int >> 8) & 0xFF);
|
||||
void ath6kl_connect_ap_mode_sta(struct ath6kl *ar, u16 aid, u8 *mac_addr,
|
||||
u8 keymgmt, u8 ucipher, u8 auth,
|
||||
u8 assoc_req_len, u8 *assoc_info)
|
||||
{
|
||||
u8 *ies = NULL, *wpa_ie = NULL, *pos;
|
||||
size_t ies_len = 0;
|
||||
struct station_info sinfo;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
|
||||
|
||||
if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
|
||||
struct ieee80211_mgmt *mgmt =
|
||||
(struct ieee80211_mgmt *) assoc_info;
|
||||
if (ieee80211_is_assoc_req(mgmt->frame_control) &&
|
||||
assoc_req_len >= sizeof(struct ieee80211_hdr_3addr) +
|
||||
sizeof(mgmt->u.assoc_req)) {
|
||||
ies = mgmt->u.assoc_req.variable;
|
||||
ies_len = assoc_info + assoc_req_len - ies;
|
||||
} else if (ieee80211_is_reassoc_req(mgmt->frame_control) &&
|
||||
assoc_req_len >= sizeof(struct ieee80211_hdr_3addr)
|
||||
+ sizeof(mgmt->u.reassoc_req)) {
|
||||
ies = mgmt->u.reassoc_req.variable;
|
||||
ies_len = assoc_info + assoc_req_len - ies;
|
||||
}
|
||||
}
|
||||
|
||||
pos = ies;
|
||||
while (pos && pos + 1 < ies + ies_len) {
|
||||
if (pos + 2 + pos[1] > ies + ies_len)
|
||||
break;
|
||||
if (pos[0] == WLAN_EID_RSN)
|
||||
wpa_ie = pos; /* RSN IE */
|
||||
else if (pos[0] == WLAN_EID_VENDOR_SPECIFIC &&
|
||||
pos[1] >= 4 &&
|
||||
pos[2] == 0x00 && pos[3] == 0x50 && pos[4] == 0xf2) {
|
||||
if (pos[5] == 0x01)
|
||||
wpa_ie = pos; /* WPA IE */
|
||||
else if (pos[5] == 0x04) {
|
||||
wpa_ie = pos; /* WPS IE */
|
||||
break; /* overrides WPA/RSN IE */
|
||||
}
|
||||
}
|
||||
pos += 2 + pos[1];
|
||||
}
|
||||
|
||||
ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie,
|
||||
wpa_ie ? 2 + wpa_ie[1] : 0,
|
||||
keymgmt, ucipher, auth);
|
||||
|
||||
/* send event to application */
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
|
||||
/* TODO: sinfo.generation */
|
||||
/* TODO: need to deliver (Re)AssocReq IEs somehow.. change in
|
||||
* cfg80211 needed, e.g., by adding those into sinfo
|
||||
*/
|
||||
cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL);
|
||||
|
||||
sinfo.assoc_req_ies = ies;
|
||||
sinfo.assoc_req_ies_len = ies_len;
|
||||
sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
|
||||
|
||||
cfg80211_new_sta(ar->net_dev, mac_addr, &sinfo, GFP_KERNEL);
|
||||
|
||||
netif_wake_queue(ar->net_dev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Functions for Tx credit handling */
|
||||
@ -779,6 +926,41 @@ void ath6kl_disconnect(struct ath6kl *ar)
|
||||
}
|
||||
}
|
||||
|
||||
void ath6kl_deep_sleep_enable(struct ath6kl *ar)
|
||||
{
|
||||
switch (ar->sme_state) {
|
||||
case SME_CONNECTING:
|
||||
cfg80211_connect_result(ar->net_dev, ar->bssid, NULL, 0,
|
||||
NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
GFP_KERNEL);
|
||||
break;
|
||||
case SME_CONNECTED:
|
||||
default:
|
||||
/*
|
||||
* FIXME: oddly enough smeState is in DISCONNECTED during
|
||||
* suspend, why? Need to send disconnected event in that
|
||||
* state.
|
||||
*/
|
||||
cfg80211_disconnected(ar->net_dev, 0, NULL, 0, GFP_KERNEL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (test_bit(CONNECTED, &ar->flag) ||
|
||||
test_bit(CONNECT_PEND, &ar->flag))
|
||||
ath6kl_wmi_disconnect_cmd(ar->wmi);
|
||||
|
||||
ar->sme_state = SME_DISCONNECTED;
|
||||
|
||||
/* disable scanning */
|
||||
if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0) != 0)
|
||||
printk(KERN_WARNING "ath6kl: failed to disable scan "
|
||||
"during suspend\n");
|
||||
|
||||
ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
|
||||
}
|
||||
|
||||
/* WMI Event handlers */
|
||||
|
||||
static const char *get_hw_id_string(u32 id)
|
||||
@ -819,17 +1001,20 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
|
||||
set_bit(WMI_READY, &ar->flag);
|
||||
wake_up(&ar->event_wq);
|
||||
|
||||
ath6kl_info("hw %s fw %s\n",
|
||||
ath6kl_info("hw %s fw %s%s\n",
|
||||
get_hw_id_string(ar->wdev->wiphy->hw_version),
|
||||
ar->wdev->wiphy->fw_version);
|
||||
ar->wdev->wiphy->fw_version,
|
||||
test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
|
||||
}
|
||||
|
||||
void ath6kl_scan_complete_evt(struct ath6kl *ar, int status)
|
||||
{
|
||||
ath6kl_cfg80211_scan_complete_event(ar, status);
|
||||
|
||||
if (!ar->usr_bss_filter)
|
||||
if (!ar->usr_bss_filter) {
|
||||
clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status);
|
||||
}
|
||||
@ -842,13 +1027,6 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (ar->nw_type == AP_NETWORK) {
|
||||
ath6kl_connect_ap_mode(ar, channel, bssid, listen_int,
|
||||
beacon_int, assoc_resp_len,
|
||||
assoc_info);
|
||||
return;
|
||||
}
|
||||
|
||||
ath6kl_cfg80211_connect_event(ar, channel, bssid,
|
||||
listen_int, beacon_int,
|
||||
net_type, beacon_ie_len,
|
||||
@ -880,8 +1058,10 @@ void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
|
||||
ar->next_ep_id = ENDPOINT_2;
|
||||
}
|
||||
|
||||
if (!ar->usr_bss_filter)
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
|
||||
if (!ar->usr_bss_filter) {
|
||||
set_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
|
||||
ath6kl_wmi_bssfilter_cmd(ar->wmi, CURRENT_BSS_FILTER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast)
|
||||
@ -915,26 +1095,11 @@ static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
|
||||
(struct wmi_target_stats *) ptr;
|
||||
struct target_stats *stats = &ar->target_stats;
|
||||
struct tkip_ccmp_stats *ccmp_stats;
|
||||
struct bss *conn_bss = NULL;
|
||||
struct cserv_stats *c_stats;
|
||||
u8 ac;
|
||||
|
||||
if (len < sizeof(*tgt_stats))
|
||||
return;
|
||||
|
||||
/* update the RSSI of the connected bss */
|
||||
if (test_bit(CONNECTED, &ar->flag)) {
|
||||
conn_bss = ath6kl_wmi_find_node(ar->wmi, ar->bssid);
|
||||
if (conn_bss) {
|
||||
c_stats = &tgt_stats->cserv_stats;
|
||||
conn_bss->ni_rssi =
|
||||
a_sle16_to_cpu(c_stats->cs_ave_beacon_rssi);
|
||||
conn_bss->ni_snr =
|
||||
tgt_stats->cserv_stats.cs_ave_beacon_snr;
|
||||
ath6kl_wmi_node_return(ar->wmi, conn_bss);
|
||||
}
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n");
|
||||
|
||||
stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt);
|
||||
@ -1165,7 +1330,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
|
||||
u8 assoc_resp_len, u8 *assoc_info,
|
||||
u16 prot_reason_status)
|
||||
{
|
||||
struct bss *wmi_ssid_node = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
if (ar->nw_type == AP_NETWORK) {
|
||||
@ -1188,7 +1352,10 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
|
||||
cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL);
|
||||
}
|
||||
|
||||
clear_bit(CONNECTED, &ar->flag);
|
||||
if (memcmp(ar->net_dev->dev_addr, bssid, ETH_ALEN) == 0) {
|
||||
memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
|
||||
clear_bit(CONNECTED, &ar->flag);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1222,33 +1389,6 @@ void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
|
||||
}
|
||||
}
|
||||
|
||||
if ((reason == NO_NETWORK_AVAIL) && test_bit(WMI_READY, &ar->flag)) {
|
||||
ath6kl_wmi_node_free(ar->wmi, bssid);
|
||||
|
||||
/*
|
||||
* In case any other same SSID nodes are present remove it,
|
||||
* since those nodes also not available now.
|
||||
*/
|
||||
do {
|
||||
/*
|
||||
* Find the nodes based on SSID and remove it
|
||||
*
|
||||
* Note: This case will not work out for
|
||||
* Hidden-SSID
|
||||
*/
|
||||
wmi_ssid_node = ath6kl_wmi_find_ssid_node(ar->wmi,
|
||||
ar->ssid,
|
||||
ar->ssid_len,
|
||||
false,
|
||||
true);
|
||||
|
||||
if (wmi_ssid_node)
|
||||
ath6kl_wmi_node_free(ar->wmi,
|
||||
wmi_ssid_node->ni_macaddr);
|
||||
|
||||
} while (wmi_ssid_node);
|
||||
}
|
||||
|
||||
/* update connect & link status atomically */
|
||||
spin_lock_irqsave(&ar->lock, flags);
|
||||
clear_bit(CONNECTED, &ar->flag);
|
||||
@ -1331,7 +1471,7 @@ void init_netdev(struct net_device *dev)
|
||||
dev->needed_headroom = ETH_HLEN;
|
||||
dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) +
|
||||
sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
|
||||
+ WMI_MAX_TX_META_SZ;
|
||||
+ WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*/
|
||||
|
||||
#include "htc.h"
|
||||
#include "wmi.h"
|
||||
#include "debug.h"
|
||||
|
||||
struct bss *wlan_node_alloc(int wh_size)
|
||||
{
|
||||
struct bss *ni;
|
||||
|
||||
ni = kzalloc(sizeof(struct bss), GFP_ATOMIC);
|
||||
|
||||
if ((ni != NULL) && wh_size) {
|
||||
ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC);
|
||||
if (ni->ni_buf == NULL) {
|
||||
kfree(ni);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ni;
|
||||
}
|
||||
|
||||
void wlan_node_free(struct bss *ni)
|
||||
{
|
||||
kfree(ni->ni_buf);
|
||||
kfree(ni);
|
||||
}
|
||||
|
||||
void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
int hash;
|
||||
|
||||
memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN);
|
||||
hash = ATH6KL_NODE_HASH(mac_addr);
|
||||
ni->ni_refcnt = 1;
|
||||
|
||||
ni->ni_tstamp = jiffies_to_msecs(jiffies);
|
||||
ni->ni_actcnt = WLAN_NODE_INACT_CNT;
|
||||
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
|
||||
/* insert at the end of the node list */
|
||||
ni->ni_list_next = NULL;
|
||||
ni->ni_list_prev = nt->nt_node_last;
|
||||
if (nt->nt_node_last != NULL)
|
||||
nt->nt_node_last->ni_list_next = ni;
|
||||
|
||||
nt->nt_node_last = ni;
|
||||
if (nt->nt_node_first == NULL)
|
||||
nt->nt_node_first = ni;
|
||||
|
||||
/* insert into the hash list */
|
||||
ni->ni_hash_next = nt->nt_hash[hash];
|
||||
if (ni->ni_hash_next != NULL)
|
||||
nt->nt_hash[hash]->ni_hash_prev = ni;
|
||||
|
||||
ni->ni_hash_prev = NULL;
|
||||
nt->nt_hash[hash] = ni;
|
||||
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
}
|
||||
|
||||
struct bss *wlan_find_node(struct ath6kl_node_table *nt,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
struct bss *ni, *found_ni = NULL;
|
||||
int hash;
|
||||
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
|
||||
hash = ATH6KL_NODE_HASH(mac_addr);
|
||||
for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
|
||||
if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) {
|
||||
ni->ni_refcnt++;
|
||||
found_ni = ni;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
|
||||
return found_ni;
|
||||
}
|
||||
|
||||
void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni)
|
||||
{
|
||||
int hash;
|
||||
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
|
||||
if (ni->ni_list_prev == NULL)
|
||||
/* fix list head */
|
||||
nt->nt_node_first = ni->ni_list_next;
|
||||
else
|
||||
ni->ni_list_prev->ni_list_next = ni->ni_list_next;
|
||||
|
||||
if (ni->ni_list_next == NULL)
|
||||
/* fix list tail */
|
||||
nt->nt_node_last = ni->ni_list_prev;
|
||||
else
|
||||
ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
|
||||
|
||||
if (ni->ni_hash_prev == NULL) {
|
||||
/* first in list so fix the list head */
|
||||
hash = ATH6KL_NODE_HASH(ni->ni_macaddr);
|
||||
nt->nt_hash[hash] = ni->ni_hash_next;
|
||||
} else {
|
||||
ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
|
||||
}
|
||||
|
||||
if (ni->ni_hash_next != NULL)
|
||||
ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
|
||||
|
||||
wlan_node_free(ni);
|
||||
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
}
|
||||
|
||||
static void wlan_node_dec_free(struct bss *ni)
|
||||
{
|
||||
if ((ni->ni_refcnt--) == 1)
|
||||
wlan_node_free(ni);
|
||||
}
|
||||
|
||||
void wlan_free_allnodes(struct ath6kl_node_table *nt)
|
||||
{
|
||||
struct bss *ni;
|
||||
|
||||
while ((ni = nt->nt_node_first) != NULL)
|
||||
wlan_node_reclaim(nt, ni);
|
||||
}
|
||||
|
||||
void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg)
|
||||
{
|
||||
struct bss *ni;
|
||||
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
|
||||
ni->ni_refcnt++;
|
||||
ath6kl_cfg80211_scan_node(arg, ni);
|
||||
wlan_node_dec_free(ni);
|
||||
}
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
}
|
||||
|
||||
void wlan_node_table_init(struct ath6kl_node_table *nt)
|
||||
{
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n",
|
||||
(unsigned long)nt);
|
||||
|
||||
memset(nt, 0, sizeof(struct ath6kl_node_table));
|
||||
|
||||
spin_lock_init(&nt->nt_nodelock);
|
||||
|
||||
nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC;
|
||||
}
|
||||
|
||||
void wlan_refresh_inactive_nodes(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_node_table *nt = &ar->scan_table;
|
||||
struct bss *bss;
|
||||
u32 now;
|
||||
|
||||
now = jiffies_to_msecs(jiffies);
|
||||
bss = nt->nt_node_first;
|
||||
while (bss != NULL) {
|
||||
/* refresh all nodes except the current bss */
|
||||
if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) {
|
||||
if (((now - bss->ni_tstamp) > nt->nt_node_age)
|
||||
|| --bss->ni_actcnt == 0) {
|
||||
wlan_node_reclaim(nt, bss);
|
||||
}
|
||||
}
|
||||
bss = bss->ni_list_next;
|
||||
}
|
||||
}
|
||||
|
||||
void wlan_node_table_cleanup(struct ath6kl_node_table *nt)
|
||||
{
|
||||
wlan_free_allnodes(nt);
|
||||
}
|
||||
|
||||
struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid,
|
||||
u32 ssid_len, bool is_wpa2, bool match_ssid)
|
||||
{
|
||||
struct bss *ni, *found_ni = NULL;
|
||||
u8 *ie_ssid;
|
||||
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
|
||||
for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
|
||||
|
||||
ie_ssid = ni->ni_cie.ie_ssid;
|
||||
|
||||
if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) &&
|
||||
(memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) {
|
||||
|
||||
if (match_ssid ||
|
||||
(is_wpa2 && ni->ni_cie.ie_rsn != NULL) ||
|
||||
(!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) {
|
||||
ni->ni_refcnt++;
|
||||
found_ni = ni;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
|
||||
return found_ni;
|
||||
}
|
||||
|
||||
void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni)
|
||||
{
|
||||
spin_lock_bh(&nt->nt_nodelock);
|
||||
wlan_node_dec_free(ni);
|
||||
spin_unlock_bh(&nt->nt_nodelock);
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
#include "hif-ops.h"
|
||||
#include "target.h"
|
||||
#include "debug.h"
|
||||
#include "cfg80211.h"
|
||||
|
||||
struct ath6kl_sdio {
|
||||
struct sdio_func *func;
|
||||
@ -134,10 +135,12 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
|
||||
int ret = 0;
|
||||
|
||||
if (request & HIF_WRITE) {
|
||||
/* FIXME: looks like ugly workaround for something */
|
||||
if (addr >= HIF_MBOX_BASE_ADDR &&
|
||||
addr <= HIF_MBOX_END_ADDR)
|
||||
addr += (HIF_MBOX_WIDTH - len);
|
||||
|
||||
/* FIXME: this also looks like ugly workaround */
|
||||
if (addr == HIF_MBOX0_EXT_BASE_ADDR)
|
||||
addr += HIF_MBOX0_EXT_WIDTH - len;
|
||||
|
||||
@ -152,6 +155,11 @@ static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
|
||||
ret = sdio_memcpy_fromio(func, buf, addr, len);
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO, "%s addr 0x%x%s buf 0x%p len %d\n",
|
||||
request & HIF_WRITE ? "wr" : "rd", addr,
|
||||
request & HIF_FIXED_ADDRESS ? " (fixed)" : "", buf, len);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_SDIO_DUMP, NULL, "sdio ", buf, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -172,7 +180,8 @@ static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
|
||||
list_del(&bus_req->list);
|
||||
|
||||
spin_unlock_irqrestore(&ar_sdio->lock, flag);
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req);
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
|
||||
__func__, bus_req);
|
||||
|
||||
return bus_req;
|
||||
}
|
||||
@ -182,7 +191,8 @@ static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
|
||||
{
|
||||
unsigned long flag;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req);
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER, "%s: bus request 0x%p\n",
|
||||
__func__, bus_req);
|
||||
|
||||
spin_lock_irqsave(&ar_sdio->lock, flag);
|
||||
list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
|
||||
@ -213,16 +223,6 @@ static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
|
||||
|
||||
/* assemble SG list */
|
||||
for (i = 0; i < scat_req->scat_entries; i++, sg++) {
|
||||
if ((unsigned long)scat_req->scat_list[i].buf & 0x3)
|
||||
/*
|
||||
* Some scatter engines can handle unaligned
|
||||
* buffers, print this as informational only.
|
||||
*/
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER,
|
||||
"(%s) scatter buffer is unaligned 0x%p\n",
|
||||
scat_req->req & HIF_WRITE ? "WR" : "RD",
|
||||
scat_req->scat_list[i].buf);
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n",
|
||||
i, scat_req->scat_list[i].buf,
|
||||
scat_req->scat_list[i].len);
|
||||
@ -447,6 +447,8 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
|
||||
int status;
|
||||
struct ath6kl_sdio *ar_sdio;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
|
||||
|
||||
ar_sdio = sdio_get_drvdata(func);
|
||||
atomic_set(&ar_sdio->irq_handling, 1);
|
||||
|
||||
@ -684,7 +686,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
|
||||
MAX_SCATTER_REQUESTS, virt_scat);
|
||||
|
||||
if (!ret) {
|
||||
ath6kl_dbg(ATH6KL_DBG_ANY,
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER,
|
||||
"hif-scatter enabled: max scatter req : %d entries: %d\n",
|
||||
MAX_SCATTER_REQUESTS,
|
||||
MAX_SCATTER_ENTRIES_PER_REQ);
|
||||
@ -709,7 +711,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_ANY,
|
||||
ath6kl_dbg(ATH6KL_DBG_SCATTER,
|
||||
"Vitual scatter enabled, max_scat_req:%d, entries:%d\n",
|
||||
ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ);
|
||||
|
||||
@ -721,6 +723,34 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_sdio_suspend(struct ath6kl *ar)
|
||||
{
|
||||
struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
|
||||
struct sdio_func *func = ar_sdio->func;
|
||||
mmc_pm_flag_t flags;
|
||||
int ret;
|
||||
|
||||
flags = sdio_get_host_pm_caps(func);
|
||||
|
||||
if (!(flags & MMC_PM_KEEP_POWER))
|
||||
/* as host doesn't support keep power we need to bail out */
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO,
|
||||
"func %d doesn't support MMC_PM_KEEP_POWER\n",
|
||||
func->num);
|
||||
return -EINVAL;
|
||||
|
||||
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "ath6kl: set sdio pm flags failed: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath6kl_deep_sleep_enable(ar);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
|
||||
.read_write_sync = ath6kl_sdio_read_write_sync,
|
||||
.write_async = ath6kl_sdio_write_async,
|
||||
@ -731,6 +761,7 @@ static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
|
||||
.enable_scatter = ath6kl_sdio_enable_scatter,
|
||||
.scat_req_rw = ath6kl_sdio_async_rw_scatter,
|
||||
.cleanup_scatter = ath6kl_sdio_cleanup_scatter,
|
||||
.suspend = ath6kl_sdio_suspend,
|
||||
};
|
||||
|
||||
static int ath6kl_sdio_probe(struct sdio_func *func,
|
||||
@ -741,10 +772,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
|
||||
struct ath6kl *ar;
|
||||
int count;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC,
|
||||
"%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n",
|
||||
__func__, func->num, func->vendor,
|
||||
func->device, func->max_blksize, func->cur_blksize);
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO,
|
||||
"new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
|
||||
func->num, func->vendor, func->device,
|
||||
func->max_blksize, func->cur_blksize);
|
||||
|
||||
ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL);
|
||||
if (!ar_sdio)
|
||||
@ -800,10 +831,10 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
|
||||
ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
|
||||
ret);
|
||||
sdio_release_host(func);
|
||||
goto err_dma;
|
||||
goto err_cfg80211;
|
||||
}
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "4-bit async irq mode enabled\n");
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO, "4-bit async irq mode enabled\n");
|
||||
}
|
||||
|
||||
/* give us some time to enable, in ms */
|
||||
@ -813,7 +844,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
|
||||
|
||||
ret = ath6kl_sdio_power_on(ar_sdio);
|
||||
if (ret)
|
||||
goto err_dma;
|
||||
goto err_cfg80211;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
@ -837,6 +868,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
|
||||
|
||||
err_off:
|
||||
ath6kl_sdio_power_off(ar_sdio);
|
||||
err_cfg80211:
|
||||
ath6kl_cfg80211_deinit(ar_sdio->ar);
|
||||
err_dma:
|
||||
kfree(ar_sdio->dma_buffer);
|
||||
err_hif:
|
||||
@ -849,6 +882,10 @@ static void ath6kl_sdio_remove(struct sdio_func *func)
|
||||
{
|
||||
struct ath6kl_sdio *ar_sdio;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_SDIO,
|
||||
"removed func %d vendor 0x%x device 0x%x\n",
|
||||
func->num, func->vendor, func->device);
|
||||
|
||||
ar_sdio = sdio_get_drvdata(func);
|
||||
|
||||
ath6kl_stop_txrx(ar_sdio->ar);
|
||||
|
@ -20,6 +20,9 @@
|
||||
#define AR6003_BOARD_DATA_SZ 1024
|
||||
#define AR6003_BOARD_EXT_DATA_SZ 768
|
||||
|
||||
#define AR6004_BOARD_DATA_SZ 7168
|
||||
#define AR6004_BOARD_EXT_DATA_SZ 0
|
||||
|
||||
#define RESET_CONTROL_ADDRESS 0x00000000
|
||||
#define RESET_CONTROL_COLD_RST 0x00000100
|
||||
#define RESET_CONTROL_MBOX_RST 0x00000004
|
||||
@ -135,7 +138,8 @@
|
||||
* between the two, and is intended to remain constant (with additions only
|
||||
* at the end).
|
||||
*/
|
||||
#define ATH6KL_HI_START_ADDR 0x00540600
|
||||
#define ATH6KL_AR6003_HI_START_ADDR 0x00540600
|
||||
#define ATH6KL_AR6004_HI_START_ADDR 0x00400800
|
||||
|
||||
/*
|
||||
* These are items that the Host may need to access
|
||||
@ -300,6 +304,11 @@ struct host_interest {
|
||||
#define HI_OPTION_FW_MODE_BSS_STA 0x1
|
||||
#define HI_OPTION_FW_MODE_AP 0x2
|
||||
|
||||
#define HI_OPTION_FW_SUBMODE_NONE 0x0
|
||||
#define HI_OPTION_FW_SUBMODE_P2PDEV 0x1
|
||||
#define HI_OPTION_FW_SUBMODE_P2PCLIENT 0x2
|
||||
#define HI_OPTION_FW_SUBMODE_P2PGO 0x3
|
||||
|
||||
#define HI_OPTION_NUM_DEV_SHIFT 0x9
|
||||
|
||||
#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
|
||||
@ -312,20 +321,44 @@ struct host_interest {
|
||||
|------------------------------------------------------------------------------|
|
||||
*/
|
||||
#define HI_OPTION_FW_MODE_SHIFT 0xC
|
||||
#define HI_OPTION_FW_SUBMODE_SHIFT 0x14
|
||||
|
||||
/* Convert a Target virtual address into a Target physical address */
|
||||
#define TARG_VTOP(vaddr) (vaddr & 0x001fffff)
|
||||
#define AR6003_VTOP(vaddr) ((vaddr) & 0x001fffff)
|
||||
#define AR6004_VTOP(vaddr) (vaddr)
|
||||
|
||||
#define TARG_VTOP(target_type, vaddr) \
|
||||
(((target_type) == TARGET_TYPE_AR6003) ? AR6003_VTOP(vaddr) : \
|
||||
(((target_type) == TARGET_TYPE_AR6004) ? AR6004_VTOP(vaddr) : 0))
|
||||
|
||||
#define AR6003_REV2_APP_START_OVERRIDE 0x944C00
|
||||
#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
|
||||
#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
|
||||
#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
|
||||
#define AR6003_REV2_RAM_RESERVE_SIZE 6912
|
||||
|
||||
#define AR6003_REV3_APP_START_OVERRIDE 0x945d00
|
||||
#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
|
||||
#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
|
||||
#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
|
||||
#define AR6003_REV3_RAM_RESERVE_SIZE 512
|
||||
|
||||
#define AR6004_REV1_BOARD_DATA_ADDRESS 0x435400
|
||||
#define AR6004_REV1_BOARD_EXT_DATA_ADDRESS 0x437000
|
||||
#define AR6004_REV1_RAM_RESERVE_SIZE 11264
|
||||
|
||||
#define ATH6KL_FWLOG_PAYLOAD_SIZE 1500
|
||||
|
||||
struct ath6kl_dbglog_buf {
|
||||
__le32 next;
|
||||
__le32 buffer_addr;
|
||||
__le32 bufsize;
|
||||
__le32 length;
|
||||
__le32 count;
|
||||
__le32 free;
|
||||
} __packed;
|
||||
|
||||
struct ath6kl_dbglog_hdr {
|
||||
__le32 dbuf_addr;
|
||||
__le32 dropped;
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
167
drivers/net/wireless/ath/ath6kl/testmode.c
Normal file
167
drivers/net/wireless/ath/ath6kl/testmode.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2010-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.
|
||||
*/
|
||||
|
||||
#include "testmode.h"
|
||||
|
||||
#include <net/netlink.h>
|
||||
|
||||
enum ath6kl_tm_attr {
|
||||
__ATH6KL_TM_ATTR_INVALID = 0,
|
||||
ATH6KL_TM_ATTR_CMD = 1,
|
||||
ATH6KL_TM_ATTR_DATA = 2,
|
||||
|
||||
/* keep last */
|
||||
__ATH6KL_TM_ATTR_AFTER_LAST,
|
||||
ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum ath6kl_tm_cmd {
|
||||
ATH6KL_TM_CMD_TCMD = 0,
|
||||
ATH6KL_TM_CMD_RX_REPORT = 1,
|
||||
};
|
||||
|
||||
#define ATH6KL_TM_DATA_MAX_LEN 5000
|
||||
|
||||
static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = {
|
||||
[ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 },
|
||||
[ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY,
|
||||
.len = ATH6KL_TM_DATA_MAX_LEN },
|
||||
};
|
||||
|
||||
void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len)
|
||||
{
|
||||
if (down_interruptible(&ar->sem))
|
||||
return;
|
||||
|
||||
kfree(ar->tm.rx_report);
|
||||
|
||||
ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL);
|
||||
ar->tm.rx_report_len = buf_len;
|
||||
|
||||
up(&ar->sem);
|
||||
|
||||
wake_up(&ar->event_wq);
|
||||
}
|
||||
|
||||
static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
long left;
|
||||
|
||||
if (down_interruptible(&ar->sem))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!test_bit(WMI_READY, &ar->flag)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) {
|
||||
up(&ar->sem);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
left = wait_event_interruptible_timeout(ar->event_wq,
|
||||
ar->tm.rx_report != NULL,
|
||||
WMI_TIMEOUT);
|
||||
|
||||
if (left == 0) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
} else if (left < 0) {
|
||||
ret = left;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len,
|
||||
ar->tm.rx_report);
|
||||
|
||||
kfree(ar->tm.rx_report);
|
||||
ar->tm.rx_report = NULL;
|
||||
|
||||
out:
|
||||
up(&ar->sem);
|
||||
|
||||
return ret;
|
||||
|
||||
nla_put_failure:
|
||||
ret = -ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len)
|
||||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1];
|
||||
int err, buf_len, reply_len;
|
||||
struct sk_buff *skb;
|
||||
void *buf;
|
||||
|
||||
err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len,
|
||||
ath6kl_tm_policy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!tb[ATH6KL_TM_ATTR_CMD])
|
||||
return -EINVAL;
|
||||
|
||||
switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) {
|
||||
case ATH6KL_TM_CMD_TCMD:
|
||||
if (!tb[ATH6KL_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
|
||||
buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);
|
||||
|
||||
ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len);
|
||||
|
||||
return 0;
|
||||
|
||||
break;
|
||||
case ATH6KL_TM_CMD_RX_REPORT:
|
||||
if (!tb[ATH6KL_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]);
|
||||
buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]);
|
||||
|
||||
reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN);
|
||||
skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
err = ath6kl_tm_rx_report(ar, buf, buf_len, skb);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
return cfg80211_testmode_reply(skb);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
36
drivers/net/wireless/ath/ath6kl/testmode.h
Normal file
36
drivers/net/wireless/ath/ath6kl/testmode.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2010-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.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
|
||||
void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len);
|
||||
int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len);
|
||||
|
||||
#else
|
||||
|
||||
static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -239,7 +239,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
u16 htc_tag = ATH6KL_DATA_PKT_TAG;
|
||||
u8 ac = 99 ; /* initialize to unmapped ac */
|
||||
bool chk_adhoc_ps_mapping = false, more_data = false;
|
||||
struct wmi_tx_meta_v2 meta_v2;
|
||||
int ret;
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
|
||||
@ -262,8 +261,6 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
if (test_bit(WMI_ENABLED, &ar->flag)) {
|
||||
memset(&meta_v2, 0, sizeof(meta_v2));
|
||||
|
||||
if (skb_headroom(skb) < dev->needed_headroom) {
|
||||
WARN_ON(1);
|
||||
goto fail_tx;
|
||||
@ -320,12 +317,31 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
spin_unlock_bh(&ar->lock);
|
||||
|
||||
if (!IS_ALIGNED((unsigned long) skb->data - HTC_HDR_LENGTH, 4) &&
|
||||
skb_cloned(skb)) {
|
||||
/*
|
||||
* We will touch (move the buffer data to align it. Since the
|
||||
* skb buffer is cloned and not only the header is changed, we
|
||||
* have to copy it to allow the changes. Since we are copying
|
||||
* the data here, we may as well align it by reserving suitable
|
||||
* headroom to avoid the memmove in ath6kl_htc_tx_buf_align().
|
||||
*/
|
||||
struct sk_buff *nskb;
|
||||
|
||||
nskb = skb_copy_expand(skb, HTC_HDR_LENGTH, 0, GFP_ATOMIC);
|
||||
if (nskb == NULL)
|
||||
goto fail_tx;
|
||||
kfree_skb(skb);
|
||||
skb = nskb;
|
||||
}
|
||||
|
||||
cookie->skb = skb;
|
||||
cookie->map_no = map_no;
|
||||
set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len,
|
||||
eid, htc_tag);
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "tx ",
|
||||
skb->data, skb->len);
|
||||
|
||||
/*
|
||||
* HTC interface is asynchronous, if this fails, cleanup will
|
||||
@ -689,6 +705,8 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
|
||||
break;
|
||||
|
||||
packet = (struct htc_packet *) skb->head;
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4))
|
||||
skb->data = PTR_ALIGN(skb->data - 4, 4);
|
||||
set_htc_rxpkt_info(packet, skb, skb->data,
|
||||
ATH6KL_BUFFER_SIZE, endpoint);
|
||||
list_add_tail(&packet->list, &queue);
|
||||
@ -709,6 +727,8 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
|
||||
return;
|
||||
|
||||
packet = (struct htc_packet *) skb->head;
|
||||
if (!IS_ALIGNED((unsigned long) skb->data, 4))
|
||||
skb->data = PTR_ALIGN(skb->data - 4, 4);
|
||||
set_htc_rxpkt_info(packet, skb, skb->data,
|
||||
ATH6KL_AMSDU_BUFFER_SIZE, 0);
|
||||
spin_lock_bh(&ar->lock);
|
||||
@ -812,7 +832,7 @@ static void aggr_slice_amsdu(struct aggr_info *p_aggr,
|
||||
/* Add the length of A-MSDU subframe padding bytes -
|
||||
* Round to nearest word.
|
||||
*/
|
||||
frame_8023_len = ALIGN(frame_8023_len + 3, 3);
|
||||
frame_8023_len = ALIGN(frame_8023_len, 4);
|
||||
|
||||
framep += frame_8023_len;
|
||||
amsdu_len -= frame_8023_len;
|
||||
@ -1044,12 +1064,13 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
ar->net_stats.rx_packets++;
|
||||
ar->net_stats.rx_bytes += packet->act_len;
|
||||
|
||||
spin_unlock_bh(&ar->lock);
|
||||
|
||||
skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
|
||||
skb_pull(skb, HTC_HDR_LENGTH);
|
||||
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len);
|
||||
|
||||
spin_unlock_bh(&ar->lock);
|
||||
ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
|
||||
skb->data, skb->len);
|
||||
|
||||
skb->dev = ar->net_dev;
|
||||
|
||||
@ -1065,9 +1086,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
return;
|
||||
}
|
||||
|
||||
min_hdr_len = sizeof(struct ethhdr);
|
||||
min_hdr_len += sizeof(struct wmi_data_hdr) +
|
||||
sizeof(struct ath6kl_llc_snap_hdr);
|
||||
min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) +
|
||||
sizeof(struct ath6kl_llc_snap_hdr);
|
||||
|
||||
dhdr = (struct wmi_data_hdr *) skb->data;
|
||||
|
||||
@ -1163,8 +1183,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
seq_no = wmi_data_hdr_get_seqno(dhdr);
|
||||
meta_type = wmi_data_hdr_get_meta(dhdr);
|
||||
dot11_hdr = wmi_data_hdr_get_dot11(dhdr);
|
||||
|
||||
ath6kl_wmi_data_hdr_remove(ar->wmi, skb);
|
||||
skb_pull(skb, sizeof(struct wmi_data_hdr));
|
||||
|
||||
switch (meta_type) {
|
||||
case WMI_META_VERSION_1:
|
||||
@ -1231,9 +1250,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
|
||||
ath6kl_data_tx(skb1, ar->net_dev);
|
||||
}
|
||||
|
||||
if (!aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no,
|
||||
is_amsdu, skb))
|
||||
ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
|
||||
datap = (struct ethhdr *) skb->data;
|
||||
|
||||
if (is_unicast_ether_addr(datap->h_dest) &&
|
||||
aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no,
|
||||
is_amsdu, skb))
|
||||
/* aggregation code will handle the skb */
|
||||
return;
|
||||
|
||||
ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
|
||||
}
|
||||
|
||||
static void aggr_timeout(unsigned long arg)
|
||||
@ -1250,10 +1275,6 @@ static void aggr_timeout(unsigned long arg)
|
||||
if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* FIXME: these timeouts happen quite fruently, something
|
||||
* line once within 60 seconds. Investigate why.
|
||||
*/
|
||||
stats->num_timeouts++;
|
||||
ath6kl_dbg(ATH6KL_DBG_AGGR,
|
||||
"aggr timeout (st %d end %d)\n",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -129,6 +129,9 @@ struct wmi {
|
||||
u8 ht_allowed[A_NUM_BANDS];
|
||||
u8 traffic_class;
|
||||
bool is_probe_ssid;
|
||||
|
||||
u8 *last_mgmt_tx_frame;
|
||||
size_t last_mgmt_tx_frame_len;
|
||||
};
|
||||
|
||||
struct host_app_area {
|
||||
@ -490,17 +493,61 @@ enum wmi_cmd_id {
|
||||
WMI_SET_PASSPHRASE_CMDID,
|
||||
WMI_SEND_ASSOC_RES_CMDID,
|
||||
WMI_SET_ASSOC_REQ_RELAY_CMDID,
|
||||
WMI_GET_RFKILL_MODE_CMDID,
|
||||
|
||||
/* ACS command, consists of sub-commands */
|
||||
WMI_ACS_CTRL_CMDID,
|
||||
WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
|
||||
WMI_SET_TBD_TIME_CMDID, /*added for wmiconfig command for TBD */
|
||||
|
||||
/* Pktlog cmds */
|
||||
WMI_PKTLOG_ENABLE_CMDID,
|
||||
WMI_PKTLOG_DISABLE_CMDID,
|
||||
|
||||
/* More P2P Cmds */
|
||||
WMI_P2P_GO_NEG_REQ_RSP_CMDID,
|
||||
WMI_P2P_GRP_INIT_CMDID,
|
||||
WMI_P2P_GRP_FORMATION_DONE_CMDID,
|
||||
WMI_P2P_INVITE_CMDID,
|
||||
WMI_P2P_INVITE_REQ_RSP_CMDID,
|
||||
WMI_P2P_PROV_DISC_REQ_CMDID,
|
||||
WMI_P2P_SET_CMDID,
|
||||
|
||||
WMI_GET_RFKILL_MODE_CMDID,
|
||||
WMI_SET_RFKILL_MODE_CMDID,
|
||||
WMI_AP_SET_APSD_CMDID,
|
||||
WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID,
|
||||
|
||||
WMI_P2P_SDPD_TX_CMDID, /* F05C */
|
||||
WMI_P2P_STOP_SDPD_CMDID,
|
||||
WMI_P2P_CANCEL_CMDID,
|
||||
/* Ultra low power store / recall commands */
|
||||
WMI_STORERECALL_CONFIGURE_CMDID,
|
||||
WMI_STORERECALL_RECALL_CMDID,
|
||||
WMI_STORERECALL_HOST_READY_CMDID,
|
||||
WMI_FORCE_TARGET_ASSERT_CMDID,
|
||||
WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
|
||||
|
||||
WMI_SET_PROBED_SSID_EX_CMDID,
|
||||
WMI_SET_NETWORK_LIST_OFFLOAD_CMDID,
|
||||
WMI_SET_ARP_NS_OFFLOAD_CMDID,
|
||||
WMI_ADD_WOW_EXT_PATTERN_CMDID,
|
||||
WMI_GTK_OFFLOAD_OP_CMDID,
|
||||
WMI_REMAIN_ON_CHNL_CMDID,
|
||||
WMI_CANCEL_REMAIN_ON_CHNL_CMDID,
|
||||
WMI_SEND_ACTION_CMDID,
|
||||
WMI_PROBE_REQ_REPORT_CMDID,
|
||||
WMI_DISABLE_11B_RATES_CMDID,
|
||||
WMI_SEND_PROBE_RESPONSE_CMDID,
|
||||
WMI_GET_P2P_INFO_CMDID,
|
||||
WMI_AP_JOIN_BSS_CMDID,
|
||||
};
|
||||
|
||||
enum wmi_mgmt_frame_type {
|
||||
WMI_FRAME_BEACON = 0,
|
||||
WMI_FRAME_PROBE_REQ,
|
||||
WMI_FRAME_PROBE_RESP,
|
||||
WMI_FRAME_ASSOC_REQ,
|
||||
WMI_FRAME_ASSOC_RESP,
|
||||
WMI_NUM_MGMT_FRAME
|
||||
};
|
||||
|
||||
/* WMI_CONNECT_CMDID */
|
||||
@ -519,11 +566,6 @@ enum dot11_auth_mode {
|
||||
LEAP_AUTH = 0x04,
|
||||
};
|
||||
|
||||
enum {
|
||||
AUTH_IDLE,
|
||||
AUTH_OPEN_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum auth_mode {
|
||||
NONE_AUTH = 0x01,
|
||||
WPA_AUTH = 0x02,
|
||||
@ -1179,15 +1221,26 @@ enum wmi_event_id {
|
||||
WMI_WAC_START_WPS_EVENTID,
|
||||
WMI_WAC_CTRL_REQ_REPLY_EVENTID,
|
||||
|
||||
WMI_REPORT_WMM_PARAMS_EVENTID,
|
||||
WMI_WAC_REJECT_WPS_EVENTID,
|
||||
|
||||
/* More P2P Events */
|
||||
WMI_P2P_GO_NEG_REQ_EVENTID,
|
||||
WMI_P2P_INVITE_REQ_EVENTID,
|
||||
WMI_P2P_INVITE_RCVD_RESULT_EVENTID,
|
||||
WMI_P2P_INVITE_SENT_RESULT_EVENTID,
|
||||
WMI_P2P_PROV_DISC_RESP_EVENTID,
|
||||
WMI_P2P_PROV_DISC_REQ_EVENTID,
|
||||
|
||||
/* RFKILL Events */
|
||||
WMI_RFKILL_STATE_CHANGE_EVENTID,
|
||||
WMI_RFKILL_GET_MODE_CMD_EVENTID,
|
||||
WMI_THIN_RESERVED_START_EVENTID = 0x8000,
|
||||
|
||||
/*
|
||||
* Events in this range are reserved for thinmode
|
||||
* See wmi_thin.h for actual definitions
|
||||
*/
|
||||
WMI_P2P_START_SDPD_EVENTID,
|
||||
WMI_P2P_SDPD_RX_EVENTID,
|
||||
|
||||
WMI_THIN_RESERVED_START_EVENTID = 0x8000,
|
||||
/* Events in this range are reserved for thinmode */
|
||||
WMI_THIN_RESERVED_END_EVENTID = 0x8fff,
|
||||
|
||||
WMI_SET_CHANNEL_EVENTID,
|
||||
@ -1195,7 +1248,17 @@ enum wmi_event_id {
|
||||
|
||||
/* Generic ACS event */
|
||||
WMI_ACS_EVENTID,
|
||||
WMI_REPORT_WMM_PARAMS_EVENTID
|
||||
WMI_STORERECALL_STORE_EVENTID,
|
||||
WMI_WOW_EXT_WAKE_EVENTID,
|
||||
WMI_GTK_OFFLOAD_STATUS_EVENTID,
|
||||
WMI_NETWORK_LIST_OFFLOAD_EVENTID,
|
||||
WMI_REMAIN_ON_CHNL_EVENTID,
|
||||
WMI_CANCEL_REMAIN_ON_CHNL_EVENTID,
|
||||
WMI_TX_STATUS_EVENTID,
|
||||
WMI_RX_PROBE_REQ_EVENTID,
|
||||
WMI_P2P_CAPABILITIES_EVENTID,
|
||||
WMI_RX_ACTION_EVENTID,
|
||||
WMI_P2P_INFO_EVENTID,
|
||||
};
|
||||
|
||||
struct wmi_ready_event_2 {
|
||||
@ -1207,11 +1270,30 @@ struct wmi_ready_event_2 {
|
||||
|
||||
/* Connect Event */
|
||||
struct wmi_connect_event {
|
||||
__le16 ch;
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 listen_intvl;
|
||||
__le16 beacon_intvl;
|
||||
__le32 nw_type;
|
||||
union {
|
||||
struct {
|
||||
__le16 ch;
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 listen_intvl;
|
||||
__le16 beacon_intvl;
|
||||
__le32 nw_type;
|
||||
} sta;
|
||||
struct {
|
||||
u8 phymode;
|
||||
u8 aid;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u8 auth;
|
||||
u8 keymgmt;
|
||||
__le16 cipher;
|
||||
u8 apsd_info;
|
||||
u8 unused[3];
|
||||
} ap_sta;
|
||||
struct {
|
||||
__le16 ch;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 unused[8];
|
||||
} ap_bss;
|
||||
} u;
|
||||
u8 beacon_ie_len;
|
||||
u8 assoc_req_len;
|
||||
u8 assoc_resp_len;
|
||||
@ -1238,6 +1320,12 @@ enum wmi_disconnect_reason {
|
||||
IBSS_MERGE = 0xe,
|
||||
};
|
||||
|
||||
#define ATH6KL_COUNTRY_RD_SHIFT 16
|
||||
|
||||
struct ath6kl_wmi_regdomain {
|
||||
__le32 reg_code;
|
||||
};
|
||||
|
||||
struct wmi_disconnect_event {
|
||||
/* reason code, see 802.11 spec. */
|
||||
__le16 proto_reason_status;
|
||||
@ -1265,33 +1353,54 @@ enum wmi_bi_ftype {
|
||||
PROBEREQ_FTYPE,
|
||||
};
|
||||
|
||||
struct wmi_bss_info_hdr {
|
||||
__le16 ch;
|
||||
#define DEF_LRSSI_SCAN_PERIOD 5
|
||||
#define DEF_LRSSI_ROAM_THRESHOLD 20
|
||||
#define DEF_LRSSI_ROAM_FLOOR 60
|
||||
#define DEF_SCAN_FOR_ROAM_INTVL 2
|
||||
|
||||
/* see, enum wmi_bi_ftype */
|
||||
u8 frame_type;
|
||||
enum wmi_roam_ctrl {
|
||||
WMI_FORCE_ROAM = 1,
|
||||
WMI_SET_ROAM_MODE,
|
||||
WMI_SET_HOST_BIAS,
|
||||
WMI_SET_LRSSI_SCAN_PARAMS,
|
||||
};
|
||||
|
||||
u8 snr;
|
||||
a_sle16 rssi;
|
||||
struct bss_bias {
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le32 ie_mask;
|
||||
u8 bias;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* BSS INFO HDR version 2.0
|
||||
* With 6 bytes HTC header and 6 bytes of WMI header
|
||||
* WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management
|
||||
* header space.
|
||||
* - Reduce the ie_mask to 2 bytes as only two bit flags are used
|
||||
* - Remove rssi and compute it on the host. rssi = snr - 95
|
||||
*/
|
||||
struct bss_bias_info {
|
||||
u8 num_bss;
|
||||
struct bss_bias bss_bias[1];
|
||||
} __packed;
|
||||
|
||||
struct low_rssi_scan_params {
|
||||
__le16 lrssi_scan_period;
|
||||
a_sle16 lrssi_scan_threshold;
|
||||
a_sle16 lrssi_roam_threshold;
|
||||
u8 roam_rssi_floor;
|
||||
u8 reserved[1];
|
||||
} __packed;
|
||||
|
||||
struct roam_ctrl_cmd {
|
||||
union {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 roam_mode;
|
||||
struct bss_bias_info bss;
|
||||
struct low_rssi_scan_params params;
|
||||
} __packed info;
|
||||
u8 roam_ctrl;
|
||||
} __packed;
|
||||
|
||||
/* BSS INFO HDR version 2.0 */
|
||||
struct wmi_bss_info_hdr2 {
|
||||
__le16 ch;
|
||||
__le16 ch; /* frequency in MHz */
|
||||
|
||||
/* see, enum wmi_bi_ftype */
|
||||
u8 frame_type;
|
||||
|
||||
u8 snr;
|
||||
u8 snr; /* note: rssi = snr - 95 dBm */
|
||||
u8 bssid[ETH_ALEN];
|
||||
__le16 ie_mask;
|
||||
} __packed;
|
||||
@ -1330,6 +1439,16 @@ enum wmi_bss_flags {
|
||||
WMI_PMKID_VALID_BSS = 0x02,
|
||||
};
|
||||
|
||||
struct wmi_neighbor_info {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 bss_flags; /* enum wmi_bss_flags */
|
||||
} __packed;
|
||||
|
||||
struct wmi_neighbor_report_event {
|
||||
u8 num_neighbors;
|
||||
struct wmi_neighbor_info neighbor[0];
|
||||
} __packed;
|
||||
|
||||
/* TKIP MIC Error Event */
|
||||
struct wmi_tkip_micerr_event {
|
||||
u8 key_id;
|
||||
@ -1642,6 +1761,12 @@ struct wmi_get_keepalive_cmd {
|
||||
u8 keep_alive_intvl;
|
||||
} __packed;
|
||||
|
||||
struct wmi_set_appie_cmd {
|
||||
u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */
|
||||
u8 ie_len;
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
/* Notify the WSC registration status to the target */
|
||||
#define WSC_REG_ACTIVE 1
|
||||
#define WSC_REG_INACTIVE 0
|
||||
@ -1789,8 +1914,26 @@ struct wmi_tx_complete_event {
|
||||
|
||||
/* Used with WMI_AP_SET_NUM_STA_CMDID */
|
||||
|
||||
/*
|
||||
* Used with WMI_AP_SET_MLME_CMDID
|
||||
*/
|
||||
|
||||
/* MLME Commands */
|
||||
#define WMI_AP_MLME_ASSOC 1 /* associate station */
|
||||
#define WMI_AP_DISASSOC 2 /* disassociate station */
|
||||
#define WMI_AP_DEAUTH 3 /* deauthenticate station */
|
||||
#define WMI_AP_MLME_AUTHORIZE 4 /* authorize station */
|
||||
#define WMI_AP_MLME_UNAUTHORIZE 5 /* unauthorize station */
|
||||
|
||||
struct wmi_ap_set_mlme_cmd {
|
||||
u8 mac[ETH_ALEN];
|
||||
__le16 reason; /* 802.11 reason code */
|
||||
u8 cmd; /* operation to perform (WMI_AP_*) */
|
||||
} __packed;
|
||||
|
||||
struct wmi_ap_set_pvb_cmd {
|
||||
__le32 flag;
|
||||
__le16 rsvd;
|
||||
__le16 aid;
|
||||
} __packed;
|
||||
|
||||
@ -1840,6 +1983,100 @@ struct wmi_ap_mode_stat {
|
||||
|
||||
/* End of AP mode definitions */
|
||||
|
||||
struct wmi_remain_on_chnl_cmd {
|
||||
__le32 freq;
|
||||
__le32 duration;
|
||||
} __packed;
|
||||
|
||||
struct wmi_send_action_cmd {
|
||||
__le32 id;
|
||||
__le32 freq;
|
||||
__le32 wait;
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_tx_status_event {
|
||||
__le32 id;
|
||||
u8 ack_status;
|
||||
} __packed;
|
||||
|
||||
struct wmi_probe_req_report_cmd {
|
||||
u8 enable;
|
||||
} __packed;
|
||||
|
||||
struct wmi_disable_11b_rates_cmd {
|
||||
u8 disable;
|
||||
} __packed;
|
||||
|
||||
struct wmi_set_appie_extended_cmd {
|
||||
u8 role_id;
|
||||
u8 mgmt_frm_type;
|
||||
u8 ie_len;
|
||||
u8 ie_info[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_remain_on_chnl_event {
|
||||
__le32 freq;
|
||||
__le32 duration;
|
||||
} __packed;
|
||||
|
||||
struct wmi_cancel_remain_on_chnl_event {
|
||||
__le32 freq;
|
||||
__le32 duration;
|
||||
u8 status;
|
||||
} __packed;
|
||||
|
||||
struct wmi_rx_action_event {
|
||||
__le32 freq;
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_capabilities_event {
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_rx_probe_req_event {
|
||||
__le32 freq;
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
#define P2P_FLAG_CAPABILITIES_REQ (0x00000001)
|
||||
#define P2P_FLAG_MACADDR_REQ (0x00000002)
|
||||
#define P2P_FLAG_HMODEL_REQ (0x00000002)
|
||||
|
||||
struct wmi_get_p2p_info {
|
||||
__le32 info_req_flags;
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_info_event {
|
||||
__le32 info_req_flags;
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_capabilities {
|
||||
u8 go_power_save;
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_macaddr {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_hmodel {
|
||||
u8 p2p_model;
|
||||
} __packed;
|
||||
|
||||
struct wmi_p2p_probe_response_cmd {
|
||||
__le32 freq;
|
||||
u8 destination_addr[ETH_ALEN];
|
||||
__le16 len;
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
/* Extended WMI (WMIX)
|
||||
*
|
||||
* Extended WMIX commands are encapsulated in a WMI message with
|
||||
@ -1898,6 +2135,11 @@ struct wmix_hb_challenge_resp_cmd {
|
||||
__le32 source;
|
||||
} __packed;
|
||||
|
||||
struct ath6kl_wmix_dbglog_cfg_module_cmd {
|
||||
__le32 valid;
|
||||
__le32 config;
|
||||
} __packed;
|
||||
|
||||
/* End of Extended WMI (WMIX) */
|
||||
|
||||
enum wmi_sync_flag {
|
||||
@ -1925,14 +2167,11 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
|
||||
|
||||
int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
|
||||
int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb);
|
||||
int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
|
||||
int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
|
||||
u32 layer2_priority, bool wmm_enabled,
|
||||
u8 *ac);
|
||||
|
||||
int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb);
|
||||
struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 *mac_addr);
|
||||
void ath6kl_wmi_node_free(struct wmi *wmi, const u8 *mac_addr);
|
||||
|
||||
int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
|
||||
enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag);
|
||||
@ -1978,6 +2217,7 @@ int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
|
||||
u8 preamble_policy);
|
||||
|
||||
int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
|
||||
int ath6kl_wmi_config_debug_module_cmd(struct wmi *wmi, u32 valid, u32 config);
|
||||
|
||||
int ath6kl_wmi_get_stats_cmd(struct wmi *wmi);
|
||||
int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
|
||||
@ -1995,23 +2235,47 @@ int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
|
||||
|
||||
int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
|
||||
int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
|
||||
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
|
||||
|
||||
s32 ath6kl_wmi_get_rate(s8 rate_index);
|
||||
|
||||
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
|
||||
|
||||
struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 *ssid,
|
||||
u32 ssid_len, bool is_wpa2,
|
||||
bool match_ssid);
|
||||
|
||||
void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss);
|
||||
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
|
||||
|
||||
/* AP mode */
|
||||
int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, struct wmi_connect_cmd *p);
|
||||
|
||||
int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 cmd, const u8 *mac, u16 reason);
|
||||
|
||||
int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag);
|
||||
|
||||
int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version,
|
||||
bool rx_dot11_hdr, bool defrag_on_host);
|
||||
|
||||
int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
|
||||
u8 ie_len);
|
||||
|
||||
/* P2P */
|
||||
int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
|
||||
|
||||
int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u32 freq, u32 dur);
|
||||
|
||||
int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u32 id, u32 freq, u32 wait,
|
||||
const u8 *data, u16 data_len);
|
||||
|
||||
int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u32 freq,
|
||||
const u8 *dst,
|
||||
const u8 *data, u16 data_len);
|
||||
|
||||
int ath6kl_wmi_probe_report_req_cmd(struct wmi *wmi, bool enable);
|
||||
|
||||
int ath6kl_wmi_info_req_cmd(struct wmi *wmi, u32 info_req_flags);
|
||||
|
||||
int ath6kl_wmi_cancel_remain_on_chnl_cmd(struct wmi *wmi);
|
||||
|
||||
int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 mgmt_frm_type, const u8 *ie,
|
||||
u8 ie_len);
|
||||
|
||||
void *ath6kl_wmi_init(struct ath6kl *devt);
|
||||
void ath6kl_wmi_shutdown(struct wmi *wmi);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user