Commit ce77903c authored by John W. Linville's avatar John W. Linville

Merge branch 'for-linville' of git://github.com/kvalo/ath6kl

parents daf67ce8 d987dd13
This diff is collapsed.
...@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar); ...@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);
struct ath6kl *ath6kl_cfg80211_create(void); struct ath6kl *ath6kl_cfg80211_create(void);
void ath6kl_cfg80211_destroy(struct ath6kl *ar); void ath6kl_cfg80211_destroy(struct ath6kl *ar);
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);
#endif /* ATH6KL_CFG80211_H */ #endif /* ATH6KL_CFG80211_H */
...@@ -100,6 +100,21 @@ enum ath6kl_fw_capability { ...@@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
/* Firmware has support to override rsn cap of rsn ie */ /* Firmware has support to override rsn cap of rsn ie */
ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
/*
* Multicast support in WOW and host awake mode.
* Allow all multicast in host awake mode.
* Apply multicast filter in WOW mode.
*/
ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
/* Firmware supports enhanced bmiss detection */
ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
/*
* FW supports matching of ssid in schedule scan
*/
ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
/* this needs to be last */ /* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX, ATH6KL_FW_CAPABILITY_MAX,
}; };
...@@ -112,6 +127,10 @@ struct ath6kl_fw_ie { ...@@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
u8 data[0]; u8 data[0];
}; };
enum ath6kl_hw_flags {
ATH6KL_HW_FLAG_64BIT_RATES = BIT(0),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin" #define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin" #define ATH6KL_FW_API3_FILE "fw-3.bin"
...@@ -196,7 +215,7 @@ struct ath6kl_fw_ie { ...@@ -196,7 +215,7 @@ struct ath6kl_fw_ie {
#define AGGR_NUM_OF_FREE_NETBUFS 16 #define AGGR_NUM_OF_FREE_NETBUFS 16
#define AGGR_RX_TIMEOUT 400 /* in ms */ #define AGGR_RX_TIMEOUT 100 /* in ms */
#define WMI_TIMEOUT (2 * HZ) #define WMI_TIMEOUT (2 * HZ)
...@@ -245,7 +264,6 @@ struct skb_hold_q { ...@@ -245,7 +264,6 @@ struct skb_hold_q {
struct rxtid { struct rxtid {
bool aggr; bool aggr;
bool progress;
bool timer_mon; bool timer_mon;
u16 win_sz; u16 win_sz;
u16 seq_next; u16 seq_next;
...@@ -254,9 +272,15 @@ struct rxtid { ...@@ -254,9 +272,15 @@ struct rxtid {
struct sk_buff_head q; struct sk_buff_head q;
/* /*
* FIXME: No clue what this should protect. Apparently it should * lock mainly protects seq_next and hold_q. Movement of seq_next
* protect some of the fields above but they are also accessed * needs to be protected between aggr_timeout() and
* without taking the lock. * aggr_process_recv_frm(). hold_q will be holding the pending
* reorder frames and it's access should also be protected.
* Some of the other fields like hold_q_sz, win_sz and aggr are
* initialized/reset when receiving addba/delba req, also while
* deleting aggr state all the pending buffers are flushed before
* resetting these fields, so there should not be any race in accessing
* these fields.
*/ */
spinlock_t lock; spinlock_t lock;
}; };
...@@ -541,7 +565,7 @@ struct ath6kl_vif { ...@@ -541,7 +565,7 @@ struct ath6kl_vif {
struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1]; struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
struct aggr_info *aggr_cntxt; struct aggr_info *aggr_cntxt;
struct ath6kl_htcap htcap; struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];
struct timer_list disconnect_timer; struct timer_list disconnect_timer;
struct timer_list sched_scan_timer; struct timer_list sched_scan_timer;
...@@ -684,6 +708,8 @@ struct ath6kl { ...@@ -684,6 +708,8 @@ struct ath6kl {
u32 testscript_addr; u32 testscript_addr;
enum wmi_phy_cap cap; enum wmi_phy_cap cap;
u32 flags;
struct ath6kl_hw_fw { struct ath6kl_hw_fw {
const char *dir; const char *dir;
const char *otp; const char *otp;
......
...@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target, ...@@ -1309,7 +1309,7 @@ static int ath6kl_htc_rx_packet(struct htc_target *target,
} }
ath6kl_dbg(ATH6KL_DBG_HTC, ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx 0x%p hdr x%x len %d mbox 0x%x\n", "htc rx 0x%p hdr 0x%x len %d mbox 0x%x\n",
packet, packet->info.rx.exp_hdr, packet, packet->info.rx.exp_hdr,
padded_len, dev->ar->mbox_info.htc_addr); padded_len, dev->ar->mbox_info.htc_addr);
......
...@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -42,6 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
.reserved_ram_size = 6912, .reserved_ram_size = 6912,
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 8, .uarttx_pin = 8,
.flags = 0,
/* hw2.0 needs override address hardcoded */ /* hw2.0 needs override address hardcoded */
.app_start_override_addr = 0x944C00, .app_start_override_addr = 0x944C00,
...@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -67,6 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 8, .uarttx_pin = 8,
.testscript_addr = 0x57ef74, .testscript_addr = 0x57ef74,
.flags = 0,
.fw = { .fw = {
.dir = AR6003_HW_2_1_1_FW_DIR, .dir = AR6003_HW_2_1_1_FW_DIR,
...@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -91,6 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900, .board_addr = 0x433900,
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_0_FW_DIR, .dir = AR6004_HW_1_0_FW_DIR,
...@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -110,6 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400, .board_addr = 0x43d400,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_1_FW_DIR, .dir = AR6004_HW_1_1_FW_DIR,
...@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -129,6 +133,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00, .board_addr = 0x435c00,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_FLAG_64BIT_RATES,
.fw = { .fw = {
.dir = AR6004_HW_1_2_FW_DIR, .dir = AR6004_HW_1_2_FW_DIR,
...@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -938,6 +943,14 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
} }
switch (ie_id) { switch (ie_id) {
case ATH6KL_FW_IE_FW_VERSION:
strlcpy(ar->wiphy->fw_version, data,
sizeof(ar->wiphy->fw_version));
ath6kl_dbg(ATH6KL_DBG_BOOT,
"found fw version %s\n",
ar->wiphy->fw_version);
break;
case ATH6KL_FW_IE_OTP_IMAGE: case ATH6KL_FW_IE_OTP_IMAGE:
ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
ie_len); ie_len);
...@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -991,9 +1004,6 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->hw.reserved_ram_size); ar->hw.reserved_ram_size);
break; break;
case ATH6KL_FW_IE_CAPABILITIES: case ATH6KL_FW_IE_CAPABILITIES:
if (ie_len < DIV_ROUND_UP(ATH6KL_FW_CAPABILITY_MAX, 8))
break;
ath6kl_dbg(ATH6KL_DBG_BOOT, ath6kl_dbg(ATH6KL_DBG_BOOT,
"found firmware capabilities ie (%zd B)\n", "found firmware capabilities ie (%zd B)\n",
ie_len); ie_len);
...@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -1002,6 +1012,9 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
index = i / 8; index = i / 8;
bit = i % 8; bit = i % 8;
if (index == ie_len)
break;
if (data[index] & (1 << bit)) if (data[index] & (1 << bit))
__set_bit(i, ar->fw_capabilities); __set_bit(i, ar->fw_capabilities);
} }
...@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar) ...@@ -1392,6 +1405,12 @@ static int ath6kl_init_upload(struct ath6kl *ar)
ar->version.target_ver == AR6003_HW_2_1_1_VERSION) { ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
ath6kl_err("temporary war to avoid sdio crc error\n"); ath6kl_err("temporary war to avoid sdio crc error\n");
param = 0x28;
address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
status = ath6kl_bmi_reg_write(ar, address, param);
if (status)
return status;
param = 0x20; param = 0x20;
address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS; address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
...@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) ...@@ -1659,6 +1678,9 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
cfg80211_scan_done(vif->scan_req, true); cfg80211_scan_done(vif->scan_req, true);
vif->scan_req = NULL; vif->scan_req = NULL;
} }
/* need to clean up enhanced bmiss detection fw state */
ath6kl_cfg80211_sta_bmiss_enhance(vif, false);
} }
void ath6kl_stop_txrx(struct ath6kl *ar) void ath6kl_stop_txrx(struct ath6kl *ar)
......
...@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, ...@@ -554,20 +554,24 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver,
struct ath6kl *ar = devt; struct ath6kl *ar = devt;
memcpy(ar->mac_addr, datap, ETH_ALEN); memcpy(ar->mac_addr, datap, ETH_ALEN);
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
__func__, ar->mac_addr); ath6kl_dbg(ATH6KL_DBG_BOOT,
"ready event mac addr %pM sw_ver 0x%x abi_ver 0x%x cap 0x%x\n",
ar->mac_addr, sw_ver, abi_ver, cap);
ar->version.wlan_ver = sw_ver; ar->version.wlan_ver = sw_ver;
ar->version.abi_ver = abi_ver; ar->version.abi_ver = abi_ver;
ar->hw.cap = cap; ar->hw.cap = cap;
snprintf(ar->wiphy->fw_version, if (strlen(ar->wiphy->fw_version) == 0) {
sizeof(ar->wiphy->fw_version), snprintf(ar->wiphy->fw_version,
"%u.%u.%u.%u", sizeof(ar->wiphy->fw_version),
(ar->version.wlan_ver & 0xf0000000) >> 28, "%u.%u.%u.%u",
(ar->version.wlan_ver & 0x0f000000) >> 24, (ar->version.wlan_ver & 0xf0000000) >> 28,
(ar->version.wlan_ver & 0x00ff0000) >> 16, (ar->version.wlan_ver & 0x0f000000) >> 24,
(ar->version.wlan_ver & 0x0000ffff)); (ar->version.wlan_ver & 0x00ff0000) >> 16,
(ar->version.wlan_ver & 0x0000ffff));
}
/* indicate to the waiting thread that the ready event was received */ /* indicate to the waiting thread that the ready event was received */
set_bit(WMI_READY, &ar->flag); set_bit(WMI_READY, &ar->flag);
...@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) ...@@ -1166,7 +1170,10 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
else else
clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags);
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); if (test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
vif->ar->fw_capabilities)) {
mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON);
}
if (!(ndev->flags & IFF_MULTICAST)) { if (!(ndev->flags & IFF_MULTICAST)) {
mc_all_on = false; mc_all_on = false;
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#define LPO_CAL_ENABLE_S 20 #define LPO_CAL_ENABLE_S 20
#define LPO_CAL_ENABLE 0x00100000 #define LPO_CAL_ENABLE 0x00100000
#define GPIO_PIN9_ADDRESS 0x0000004c
#define GPIO_PIN10_ADDRESS 0x00000050 #define GPIO_PIN10_ADDRESS 0x00000050
#define GPIO_PIN11_ADDRESS 0x00000054 #define GPIO_PIN11_ADDRESS 0x00000054
#define GPIO_PIN12_ADDRESS 0x00000058 #define GPIO_PIN12_ADDRESS 0x00000058
......
...@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1036,6 +1036,7 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
rxtid = &agg_conn->rx_tid[tid]; rxtid = &agg_conn->rx_tid[tid];
stats = &agg_conn->stat[tid]; stats = &agg_conn->stat[tid];
spin_lock_bh(&rxtid->lock);
idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz); idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
/* /*
...@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1054,8 +1055,6 @@ static void aggr_deque_frms(struct aggr_info_conn *agg_conn, u8 tid,
seq_end = seq_no ? seq_no : rxtid->seq_next; seq_end = seq_no ? seq_no : rxtid->seq_next;
idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz); idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
spin_lock_bh(&rxtid->lock);
do { do {
node = &rxtid->hold_q[idx]; node = &rxtid->hold_q[idx];
if ((order == 1) && (!node->skb)) if ((order == 1) && (!node->skb))
...@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1127,11 +1126,13 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
((end > extended_end) && (cur > extended_end) && ((end > extended_end) && (cur > extended_end) &&
(cur < end))) { (cur < end))) {
aggr_deque_frms(agg_conn, tid, 0, 0); aggr_deque_frms(agg_conn, tid, 0, 0);
spin_lock_bh(&rxtid->lock);
if (cur >= rxtid->hold_q_sz - 1) if (cur >= rxtid->hold_q_sz - 1)
rxtid->seq_next = cur - (rxtid->hold_q_sz - 1); rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
else else
rxtid->seq_next = ATH6KL_MAX_SEQ_NO - rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
(rxtid->hold_q_sz - 2 - cur); (rxtid->hold_q_sz - 2 - cur);
spin_unlock_bh(&rxtid->lock);
} else { } else {
/* /*
* Dequeue only those frames that are outside the * Dequeue only those frames that are outside the
...@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid, ...@@ -1185,25 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
aggr_deque_frms(agg_conn, tid, 0, 1); aggr_deque_frms(agg_conn, tid, 0, 1);
if (agg_conn->timer_scheduled) if (agg_conn->timer_scheduled)
rxtid->progress = true; return is_queued;
else
for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { spin_lock_bh(&rxtid->lock);
if (rxtid->hold_q[idx].skb) { for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
/* if (rxtid->hold_q[idx].skb) {
* There is a frame in the queue and no /*
* timer so start a timer to ensure that * There is a frame in the queue and no
* the frame doesn't remain stuck * timer so start a timer to ensure that
* forever. * the frame doesn't remain stuck
*/ * forever.
agg_conn->timer_scheduled = true; */
mod_timer(&agg_conn->timer, agg_conn->timer_scheduled = true;
(jiffies + mod_timer(&agg_conn->timer,
HZ * (AGGR_RX_TIMEOUT) / 1000)); (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
rxtid->progress = false; rxtid->timer_mon = true;
rxtid->timer_mon = true; break;
break;
}
} }
}
spin_unlock_bh(&rxtid->lock);
return is_queued; return is_queued;
} }
...@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg) ...@@ -1608,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
stats = &aggr_conn->stat[i]; stats = &aggr_conn->stat[i];
if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) if (!rxtid->aggr || !rxtid->timer_mon)
continue; continue;
stats->num_timeouts++; stats->num_timeouts++;
...@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg) ...@@ -1626,14 +1627,15 @@ static void aggr_timeout(unsigned long arg)
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
if (rxtid->aggr && rxtid->hold_q) { if (rxtid->aggr && rxtid->hold_q) {
spin_lock_bh(&rxtid->lock);
for (j = 0; j < rxtid->hold_q_sz; j++) { for (j = 0; j < rxtid->hold_q_sz; j++) {
if (rxtid->hold_q[j].skb) { if (rxtid->hold_q[j].skb) {
aggr_conn->timer_scheduled = true; aggr_conn->timer_scheduled = true;
rxtid->timer_mon = true; rxtid->timer_mon = true;
rxtid->progress = false;
break; break;
} }
} }
spin_unlock_bh(&rxtid->lock);
if (j >= rxtid->hold_q_sz) if (j >= rxtid->hold_q_sz)
rxtid->timer_mon = false; rxtid->timer_mon = false;
...@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid) ...@@ -1660,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
aggr_deque_frms(aggr_conn, tid, 0, 0); aggr_deque_frms(aggr_conn, tid, 0, 0);
rxtid->aggr = false; rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false; rxtid->timer_mon = false;
rxtid->win_sz = 0; rxtid->win_sz = 0;
rxtid->seq_next = 0; rxtid->seq_next = 0;
...@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, ...@@ -1739,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
for (i = 0; i < NUM_OF_TIDS; i++) { for (i = 0; i < NUM_OF_TIDS; i++) {
rxtid = &aggr_conn->rx_tid[i]; rxtid = &aggr_conn->rx_tid[i];
rxtid->aggr = false; rxtid->aggr = false;
rxtid->progress = false;
rxtid->timer_mon = false; rxtid->timer_mon = false;
skb_queue_head_init(&rxtid->q); skb_queue_head_init(&rxtid->q);
spin_lock_init(&rxtid->lock); spin_lock_init(&rxtid->lock);
......
...@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) ...@@ -743,7 +743,6 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
return -ENOMEM; return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data; cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
memcpy(cmd->info.bssid, bssid, ETH_ALEN); memcpy(cmd->info.bssid, bssid, ETH_ALEN);
cmd->roam_ctrl = WMI_FORCE_ROAM; cmd->roam_ctrl = WMI_FORCE_ROAM;
...@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid) ...@@ -753,6 +752,22 @@ int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid)
NO_SYNC_WMIFLAG); NO_SYNC_WMIFLAG);
} }
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period)
{
struct sk_buff *skb;
struct set_dtim_cmd *cmd;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct set_dtim_cmd *) skb->data;
cmd->dtim_period = cpu_to_le32(dtim_period);
return ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_AP_SET_DTIM_CMDID, NO_SYNC_WMIFLAG);
}
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode) ...@@ -763,7 +778,6 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode)
return -ENOMEM; return -ENOMEM;
cmd = (struct roam_ctrl_cmd *) skb->data; cmd = (struct roam_ctrl_cmd *) skb->data;
memset(cmd, 0, sizeof(*cmd));
cmd->info.roam_mode = mode; cmd->info.roam_mode = mode;
cmd->roam_ctrl = WMI_SET_ROAM_MODE; cmd->roam_ctrl = WMI_SET_ROAM_MODE;
...@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag, ...@@ -1995,7 +2009,7 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
struct wmi_probed_ssid_cmd *cmd; struct wmi_probed_ssid_cmd *cmd;
int ret; int ret;
if (index > MAX_PROBED_SSID_INDEX) if (index >= MAX_PROBED_SSIDS)
return -EINVAL; return -EINVAL;
if (ssid_len > sizeof(cmd->ssid)) if (ssid_len > sizeof(cmd->ssid))
...@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi) ...@@ -2599,6 +2613,115 @@ static void ath6kl_wmi_relinquish_implicit_pstream_credits(struct wmi *wmi)
spin_unlock_bh(&wmi->lock); spin_unlock_bh(&wmi->lock);
} }
static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u64 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates64_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[1];
mcsrate <<= 8;
mcsrate |= mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 28;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 64 bit: 2.4:%llx 5:%llx\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates64_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le64(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct sk_buff *skb;
int ret, mode, band;
u32 mcsrate, ratemask[IEEE80211_NUM_BANDS];
struct wmi_set_tx_select_rates32_cmd *cmd;
memset(&ratemask, 0, sizeof(ratemask));
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
/* copy legacy rate mask */
ratemask[band] = mask->control[band].legacy;
if (band == IEEE80211_BAND_5GHZ)
ratemask[band] =
mask->control[band].legacy << 4;
/* copy mcs rate mask */
mcsrate = mask->control[band].mcs[0];
ratemask[band] |= mcsrate << 12;
ratemask[band] |= mcsrate << 20;
}
ath6kl_dbg(ATH6KL_DBG_WMI,
"Ratemask 32 bit: 2.4:%x 5:%x\n",
ratemask[0], ratemask[1]);
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd) * WMI_RATES_MODE_MAX);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_set_tx_select_rates32_cmd *) skb->data;
for (mode = 0; mode < WMI_RATES_MODE_MAX; mode++) {
/* A mode operate in 5GHZ band */
if (mode == WMI_RATES_MODE_11A ||
mode == WMI_RATES_MODE_11A_HT20 ||
mode == WMI_RATES_MODE_11A_HT40)
band = IEEE80211_BAND_5GHZ;
else
band = IEEE80211_BAND_2GHZ;
cmd->ratemask[mode] = cpu_to_le32(ratemask[band]);
}
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_SET_TX_SELECT_RATES_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask)
{
struct ath6kl *ar = wmi->parent_dev;
if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES)
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
}
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode) enum ath6kl_host_mode host_mode)
{ {
...@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2997,6 +3120,25 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
return ret; return ret;
} }
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
{
struct sk_buff *skb;
struct wmi_sta_bmiss_enhance_cmd *cmd;
int ret;
skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_sta_bmiss_enhance_cmd *) skb->data;
cmd->enable = enhance ? 1 : 0;
ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
WMI_STA_BMISS_ENHANCE_CMDID,
NO_SYNC_WMIFLAG);
return ret;
}
s32 ath6kl_wmi_get_rate(s8 rate_index) s32 ath6kl_wmi_get_rate(s8 rate_index)
{ {
if (rate_index == RATE_AUTO) if (rate_index == RATE_AUTO)
......
...@@ -624,6 +624,10 @@ enum wmi_cmd_id { ...@@ -624,6 +624,10 @@ enum wmi_cmd_id {
WMI_SEND_MGMT_CMDID, WMI_SEND_MGMT_CMDID,
WMI_BEGIN_SCAN_CMDID, WMI_BEGIN_SCAN_CMDID,
WMI_SET_BLACK_LIST,
WMI_SET_MCASTRATE,
WMI_STA_BMISS_ENHANCE_CMDID,
}; };
enum wmi_mgmt_frame_type { enum wmi_mgmt_frame_type {
...@@ -960,6 +964,9 @@ enum wmi_bss_filter { ...@@ -960,6 +964,9 @@ enum wmi_bss_filter {
/* beacons matching probed ssid */ /* beacons matching probed ssid */
PROBED_SSID_FILTER, PROBED_SSID_FILTER,
/* beacons matching matched ssid */
MATCHED_SSID_FILTER,
/* marker only */ /* marker only */
LAST_BSS_FILTER, LAST_BSS_FILTER,
}; };
...@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd { ...@@ -978,7 +985,7 @@ struct wmi_bss_filter_cmd {
} __packed; } __packed;
/* WMI_SET_PROBED_SSID_CMDID */ /* WMI_SET_PROBED_SSID_CMDID */
#define MAX_PROBED_SSID_INDEX 9 #define MAX_PROBED_SSIDS 16
enum wmi_ssid_flag { enum wmi_ssid_flag {
/* disables entry */ /* disables entry */
...@@ -989,10 +996,13 @@ enum wmi_ssid_flag { ...@@ -989,10 +996,13 @@ enum wmi_ssid_flag {
/* probes for any ssid */ /* probes for any ssid */
ANY_SSID_FLAG = 0x02, ANY_SSID_FLAG = 0x02,
/* match for ssid */
MATCH_SSID_FLAG = 0x08,
}; };
struct wmi_probed_ssid_cmd { struct wmi_probed_ssid_cmd {
/* 0 to MAX_PROBED_SSID_INDEX */ /* 0 to MAX_PROBED_SSIDS - 1 */
u8 entry_index; u8 entry_index;
/* see, enum wmi_ssid_flg */ /* see, enum wmi_ssid_flg */
...@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd { ...@@ -1017,6 +1027,11 @@ struct wmi_bmiss_time_cmd {
__le16 num_beacons; __le16 num_beacons;
}; };
/* WMI_STA_ENHANCE_BMISS_CMDID */
struct wmi_sta_bmiss_enhance_cmd {
u8 enable;
} __packed;
/* WMI_SET_POWER_MODE_CMDID */ /* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode { enum wmi_power_mode {
REC_POWER = 0x01, REC_POWER = 0x01,
...@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd { ...@@ -1048,6 +1063,36 @@ struct wmi_power_params_cmd {
__le16 ps_fail_event_policy; __le16 ps_fail_event_policy;
} __packed; } __packed;
/*
* Ratemask for below modes should be passed
* to WMI_SET_TX_SELECT_RATES_CMDID.
* AR6003 has 32 bit mask for each modes.
* First 12 bits for legacy rates, 13 to 20
* bits for HT 20 rates and 21 to 28 bits for
* HT 40 rates
*/
enum wmi_mode_phy {
WMI_RATES_MODE_11A = 0,
WMI_RATES_MODE_11G,
WMI_RATES_MODE_11B,
WMI_RATES_MODE_11GONLY,
WMI_RATES_MODE_11A_HT20,
WMI_RATES_MODE_11G_HT20,
WMI_RATES_MODE_11A_HT40,
WMI_RATES_MODE_11G_HT40,
WMI_RATES_MODE_MAX
};
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates32_cmd {
__le32 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_TX_SELECT_RATES_CMDID */
struct wmi_set_tx_select_rates64_cmd {
__le64 ratemask[WMI_RATES_MODE_MAX];
} __packed;
/* WMI_SET_DISC_TIMEOUT_CMDID */ /* WMI_SET_DISC_TIMEOUT_CMDID */
struct wmi_disc_timeout_cmd { struct wmi_disc_timeout_cmd {
/* seconds */ /* seconds */
...@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd { ...@@ -1572,6 +1617,10 @@ struct roam_ctrl_cmd {
u8 roam_ctrl; u8 roam_ctrl;
} __packed; } __packed;
struct set_dtim_cmd {
__le32 dtim_period;
} __packed;
/* BSS INFO HDR version 2.0 */ /* BSS INFO HDR version 2.0 */
struct wmi_bss_info_hdr2 { struct wmi_bss_info_hdr2 {
__le16 ch; /* frequency in MHz */ __le16 ch; /* frequency in MHz */
...@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2532,6 +2581,8 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1); __be32 ips0, __be32 ips1);
int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_host_mode host_mode); enum ath6kl_host_mode host_mode);
int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
const struct cfg80211_bitrate_mask *mask);
int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
enum ath6kl_wow_mode wow_mode, enum ath6kl_wow_mode wow_mode,
u32 filter, u16 host_req_delay); u32 filter, u16 host_req_delay);
...@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2542,11 +2593,14 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
u16 list_id, u16 filter_id); u16 list_id, u16 filter_id);
int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode);
int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
u8 *filter, bool add_filter); u8 *filter, bool add_filter);
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
/* AP mode uAPSD */ /* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment