Commit 5235cd21 authored by John W. Linville's avatar John W. Linville

Merge tag 'for-linville-20140717' of git://github.com/kvalo/ath

parents fd29d2cd 99361944
...@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
if (ret) if (ret)
return ret; return ret;
src_ring->hw_index = read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); if (read_index == 0xffffffff)
src_ring->hw_index &= nentries_mask; return -ENODEV;
read_index &= nentries_mask;
src_ring->hw_index = read_index;
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
} }
read_index = src_ring->hw_index; read_index = src_ring->hw_index;
if ((read_index == sw_index) || (read_index == 0xffffffff)) if (read_index == sw_index)
return -EIO; return -EIO;
sbase = src_ring->shadow_base; sbase = src_ring->shadow_base;
......
...@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar)
INIT_LIST_HEAD(&ar->arvifs); INIT_LIST_HEAD(&ar->arvifs);
if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name, ar->hw_params.name,
ar->target_version, ar->target_version,
...@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
ar->fw_api, ar->fw_api,
ar->htt.target_version_major, ar->htt.target_version_major,
ar->htt.target_version_minor); ar->htt.target_version_minor);
ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
}
__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags); __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
...@@ -988,7 +994,9 @@ static void ath10k_core_register_work(struct work_struct *work) ...@@ -988,7 +994,9 @@ static void ath10k_core_register_work(struct work_struct *work)
err_release_fw: err_release_fw:
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
err: err:
device_release_driver(ar->dev); /* TODO: It's probably a good idea to release device from the driver
* but calling device_release_driver() here will cause a deadlock.
*/
return; return;
} }
......
...@@ -290,6 +290,9 @@ struct ath10k_debug { ...@@ -290,6 +290,9 @@ struct ath10k_debug {
struct ath_dfs_pool_stats dfs_pool_stats; struct ath_dfs_pool_stats dfs_pool_stats;
u32 fw_dbglog_mask; u32 fw_dbglog_mask;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
}; };
enum ath10k_state { enum ath10k_state {
......
...@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = { ...@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[64];
u8 amsdu = 3, ampdu = 64;
unsigned int len;
mutex_lock(&ar->conf_mutex);
if (ar->debug.htt_max_amsdu)
amsdu = ar->debug.htt_max_amsdu;
if (ar->debug.htt_max_ampdu)
ampdu = ar->debug.htt_max_ampdu;
mutex_unlock(&ar->conf_mutex);
len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
int res;
char buf[64];
unsigned int amsdu, ampdu;
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
/* make sure that buf is null terminated */
buf[sizeof(buf) - 1] = 0;
res = sscanf(buf, "%u %u", &amsdu, &ampdu);
if (res != 2)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
if (res)
goto out;
res = count;
ar->debug.htt_max_amsdu = amsdu;
ar->debug.htt_max_ampdu = ampdu;
out:
mutex_unlock(&ar->conf_mutex);
return res;
}
static const struct file_operations fops_htt_max_amsdu_ampdu = {
.read = ath10k_read_htt_max_amsdu_ampdu,
.write = ath10k_write_htt_max_amsdu_ampdu,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath10k_read_fw_dbglog(struct file *file, static ssize_t ath10k_read_fw_dbglog(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar) ...@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar)
* warning from del_timer(). */ * warning from del_timer(). */
if (ar->debug.htt_stats_mask != 0) if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork); cancel_delayed_work(&ar->debug.htt_stats_dwork);
ar->debug.htt_max_amsdu = 0;
ar->debug.htt_max_ampdu = 0;
} }
static ssize_t ath10k_write_simulate_radar(struct file *file, static ssize_t ath10k_write_simulate_radar(struct file *file,
...@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_htt_stats_mask); ar, &fops_htt_stats_mask);
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_htt_max_amsdu_ampdu);
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog); ar, &fops_fw_dbglog);
......
...@@ -240,16 +240,10 @@ struct htt_oob_sync_req { ...@@ -240,16 +240,10 @@ struct htt_oob_sync_req {
__le16 rsvd0; __le16 rsvd0;
} __packed; } __packed;
#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0
struct htt_aggr_conf { struct htt_aggr_conf {
u8 max_num_ampdu_subframes; u8 max_num_ampdu_subframes;
union { /* amsdu_subframes is limited by 0x1F mask */
/* dont use bitfields; undefined behaviour */ u8 max_num_amsdu_subframes;
u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
u8 max_num_amsdu_subframes:5;
} __packed;
} __packed; } __packed;
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 #define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
...@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); ...@@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt); int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt); int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu);
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt); void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
......
...@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) ...@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
return 0; return 0;
} }
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu)
{
struct htt_aggr_conf *aggr_conf;
struct sk_buff *skb;
struct htt_cmd *cmd;
int len;
int ret;
/* Firmware defaults are: amsdu = 3 and ampdu = 64 */
if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
return -EINVAL;
if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
return -EINVAL;
len = sizeof(cmd->hdr);
len += sizeof(cmd->aggr_conf);
skb = ath10k_htc_alloc_skb(len);
if (!skb)
return -ENOMEM;
skb_put(skb, len);
cmd = (struct htt_cmd *)skb->data;
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
aggr_conf = &cmd->aggr_conf;
aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
aggr_conf->max_num_amsdu_subframes,
aggr_conf->max_num_ampdu_subframes);
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
if (ret) {
dev_kfree_skb_any(skb);
return ret;
}
return 0;
}
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{ {
struct device *dev = htt->ar->dev; struct device *dev = htt->ar->dev;
......
...@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, ...@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr); ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
} }
init_completion(&xfer.done);
ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0); ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
if (ret) if (ret)
goto err_resp; goto err_resp;
...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) ...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
&nbytes, &transfer_id)) &nbytes, &transfer_id))
return; return;
if (xfer->wait_for_resp) xfer->tx_done = true;
return;
complete(&xfer->done);
} }
static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
...@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) ...@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
} }
xfer->resp_len = nbytes; xfer->resp_len = nbytes;
complete(&xfer->done); xfer->rx_done = true;
} }
static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
...@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, ...@@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
ath10k_pci_bmi_send_done(tx_pipe); ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe); ath10k_pci_bmi_recv_data(rx_pipe);
if (completion_done(&xfer->done)) if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
return 0; return 0;
schedule(); schedule();
......
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define DIAG_TRANSFER_LIMIT 2048 #define DIAG_TRANSFER_LIMIT 2048
struct bmi_xfer { struct bmi_xfer {
struct completion done; bool tx_done;
bool rx_done;
bool wait_for_resp; bool wait_for_resp;
u32 resp_len; u32 resp_len;
}; };
......
...@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_cmd_hdr *cmd_hdr; struct wmi_cmd_hdr *cmd_hdr;
enum wmi_event_id id; enum wmi_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
...@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) { switch (id) {
...@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_cmd_hdr *cmd_hdr; struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id; enum wmi_10x_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
...@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) { switch (id) {
......
...@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info { ...@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
(void) (check_type == val); \ (void) (check_type == val); \
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \ addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \ ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
*val = le32_to_cpu(tmp); \ if (!ret) \
*val = le32_to_cpu(tmp); \
ret; \ ret; \
}) })
......
...@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (info->inactivity_timeout) { if (info->inactivity_timeout) {
inactivity_timeout = info->inactivity_timeout; inactivity_timeout = info->inactivity_timeout;
if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS) if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
ar->fw_capabilities))
inactivity_timeout = DIV_ROUND_UP(inactivity_timeout, inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
60); 60);
...@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ...@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.ht_supported = false; ath6kl_band_5ghz.ht_cap.ht_supported = false;
} }
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) { if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities)) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
......
...@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ...@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
/* FIXME: we should free all firmwares in the error cases below */ /* FIXME: we should free all firmwares in the error cases below */
/*
* Backwards compatibility support for older ar6004 firmware images
* which do not set these feature flags.
*/
if (ar->target_type == TARGET_TYPE_AR6004 &&
ar->fw_api <= 4) {
__set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities);
__set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
ar->fw_capabilities);
if (ar->hw.id == AR6004_HW_1_3_VERSION)
__set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities);
}
/* Indicate that WMI is enabled (although not ready yet) */ /* Indicate that WMI is enabled (although not ready yet) */
set_bit(WMI_ENABLED, &ar->flag); set_bit(WMI_ENABLED, &ar->flag);
ar->wmi = ath6kl_wmi_init(ar); ar->wmi = ath6kl_wmi_init(ar);
......
...@@ -136,6 +136,21 @@ enum ath6kl_fw_capability { ...@@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
*/ */
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
/* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */
ATH6KL_FW_CAPABILITY_64BIT_RATES,
/* WMI_AP_CONN_INACT_CMDID uses minutes as units */
ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
/* use low priority endpoint for all data */
ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
/* ratetable is the 2 stream version (max MCS15) */
ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
/* firmare doesn't support IP checksumming */
ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
/* this needs to be last */ /* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX, ATH6KL_FW_CAPABILITY_MAX,
}; };
...@@ -149,15 +164,13 @@ struct ath6kl_fw_ie { ...@@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
}; };
enum ath6kl_hw_flags { enum ath6kl_hw_flags {
ATH6KL_HW_64BIT_RATES = BIT(0),
ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3), ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
}; };
#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"
#define ATH6KL_FW_API4_FILE "fw-4.bin" #define ATH6KL_FW_API4_FILE "fw-4.bin"
#define ATH6KL_FW_API5_FILE "fw-5.bin"
/* AR6003 1.0 definitions */ /* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba #define AR6003_HW_1_0_VERSION 0x300002ba
...@@ -215,8 +228,21 @@ enum ath6kl_hw_flags { ...@@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_3_VERSION 0x31c8088a #define AR6004_HW_1_3_VERSION 0x31c8088a
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3" #define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin" #define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" #define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" #define AR6004_HW_1_3_UTF_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_1_3_TESTSCRIPT_FILE "nullTestFlow.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
/* AR6004 3.0 definitions */
#define AR6004_HW_3_0_VERSION 0x31C809F8
#define AR6004_HW_3_0_FW_DIR "ath6k/AR6004/hw3.0"
#define AR6004_HW_3_0_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_3_0_TCMD_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_3_0_UTF_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_3_0_TESTSCRIPT_FILE "nullTestFlow.bin"
#define AR6004_HW_3_0_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
#define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
/* Per STA data, used in AP mode */ /* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0) #define STA_PS_AWAKE BIT(0)
......
...@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) ...@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
static void htc_rxctrl_complete(struct htc_target *context, static void htc_rxctrl_complete(struct htc_target *context,
struct htc_packet *packet) struct htc_packet *packet)
{ {
/* TODO, can't really receive HTC control messages yet.... */ struct sk_buff *skb = packet->skb;
ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__);
if (packet->endpoint == ENDPOINT_0 &&
packet->status == -ECANCELED &&
skb != NULL)
dev_kfree_skb(skb);
} }
/* htc pipe initialization */ /* htc pipe initialization */
...@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target, ...@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target,
static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target) static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target)
{ {
/* TODO */ struct htc_endpoint *endpoint;
struct htc_packet *packet, *tmp_pkt;
int i;
for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
endpoint = &target->endpoint[i];
spin_lock_bh(&target->rx_lock);
list_for_each_entry_safe(packet, tmp_pkt,
&endpoint->rx_bufq, list) {
list_del(&packet->list);
spin_unlock_bh(&target->rx_lock);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx flush pkt 0x%p len %d ep %d\n",
packet, packet->buf_len,
packet->endpoint);
dev_kfree_skb(packet->pkt_cntxt);
spin_lock_bh(&target->rx_lock);
}
spin_unlock_bh(&target->rx_lock);
}
} }
static int ath6kl_htc_pipe_credit_setup(struct htc_target *target, static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,
......
...@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -93,8 +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_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_0_FW_DIR, .dir = AR6004_HW_1_0_FW_DIR,
...@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -114,8 +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_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_1_FW_DIR, .dir = AR6004_HW_1_1_FW_DIR,
.fw = AR6004_HW_1_1_FIRMWARE_FILE, .fw = AR6004_HW_1_1_FIRMWARE_FILE,
...@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -134,8 +132,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_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_2_FW_DIR, .dir = AR6004_HW_1_2_FW_DIR,
...@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = {
.board_ext_data_addr = 0x437000, .board_ext_data_addr = 0x437000,
.reserved_ram_size = 7168, .reserved_ram_size = 7168,
.board_addr = 0x436400, .board_addr = 0x436400,
.refclk_hz = 40000000, .refclk_hz = 0,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS |
ATH6KL_HW_MAP_LP_ENDPOINT,
.fw = { .fw = {
.dir = AR6004_HW_1_3_FW_DIR, .dir = AR6004_HW_1_3_FW_DIR,
.fw = AR6004_HW_1_3_FIRMWARE_FILE, .fw = AR6004_HW_1_3_FIRMWARE_FILE,
.tcmd = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
.utf = AR6004_HW_1_3_UTF_FIRMWARE_FILE,
.testscript = AR6004_HW_1_3_TESTSCRIPT_FILE,
}, },
.fw_board = AR6004_HW_1_3_BOARD_DATA_FILE, .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE, .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
}, },
{
.id = AR6004_HW_3_0_VERSION,
.name = "ar6004 hw 3.0",
.dataset_patch_addr = 0,
.app_load_addr = 0x1234,
.board_ext_data_addr = 0,
.reserved_ram_size = 7168,
.board_addr = 0x436400,
.testscript_addr = 0,
.flags = 0,
.fw = {
.dir = AR6004_HW_3_0_FW_DIR,
.fw = AR6004_HW_3_0_FIRMWARE_FILE,
.tcmd = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
.utf = AR6004_HW_3_0_UTF_FIRMWARE_FILE,
.testscript = AR6004_HW_3_0_TESTSCRIPT_FILE,
},
.fw_board = AR6004_HW_3_0_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
},
}; };
/* /*
...@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar) ...@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar)
* but possible in theory. * but possible in theory.
*/ */
if (ar->target_type == TARGET_TYPE_AR6003) { if ((ar->target_type == TARGET_TYPE_AR6003) ||
(ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
(ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
param = ar->hw.board_ext_data_addr; param = ar->hw.board_ext_data_addr;
ram_reserved_size = ar->hw.reserved_ram_size; ram_reserved_size = ar->hw.reserved_ram_size;
...@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar) ...@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar)
return status; return status;
/* Configure target refclk_hz */ /* Configure target refclk_hz */
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz); if (ar->hw.refclk_hz != 0) {
if (status) status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
return status; ar->hw.refclk_hz);
if (status)
return status;
}
return 0; return 0;
} }
...@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar) ...@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if (ret) if (ret)
return ret; return ret;
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
if (ret == 0) {
ar->fw_api = 5;
goto out;
}
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE); ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
if (ret == 0) { if (ret == 0) {
ar->fw_api = 4; ar->fw_api = 4;
...@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) ...@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
ath6kl_bmi_write_hi32(ar, hi_board_data, ath6kl_bmi_write_hi32(ar, hi_board_data,
board_address); board_address);
} else { } else {
ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address); ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
if (ret) {
ath6kl_err("Failed to get board file target address.\n");
return ret;
}
} }
/* determine where in target ram to write extended board data */ /* determine where in target ram to write extended board data */
ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address); ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
if (ret) {
ath6kl_err("Failed to get extended board file target address.\n");
return ret;
}
if (ar->target_type == TARGET_TYPE_AR6003 && if (ar->target_type == TARGET_TYPE_AR6003 &&
board_ext_address == 0) { board_ext_address == 0) {
...@@ -1230,7 +1269,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) ...@@ -1230,7 +1269,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
} }
/* record the fact that Board Data IS initialized */ /* record the fact that Board Data IS initialized */
ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1); if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
(ar->version.target_ver == AR6004_HW_3_0_VERSION))
param = board_data_size;
else
param = 1;
ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
return ret; return ret;
} }
...@@ -1361,7 +1406,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar) ...@@ -1361,7 +1406,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
} }
ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address); ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
(ar->version.target_ver != AR6004_HW_3_0_VERSION))
ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1); ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
return 0; return 0;
...@@ -1567,6 +1616,11 @@ static const struct fw_capa_str_map { ...@@ -1567,6 +1616,11 @@ static const struct fw_capa_str_map {
{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
{ ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
{ ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
{ ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
{ ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
{ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
}; };
static const char *ath6kl_init_get_fw_capa_name(unsigned int id) static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
......
...@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) ...@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
struct ath6kl *ar = vif->ar; struct ath6kl *ar = vif->ar;
struct target_stats *stats = &vif->target_stats; struct target_stats *stats = &vif->target_stats;
struct tkip_ccmp_stats *ccmp_stats; struct tkip_ccmp_stats *ccmp_stats;
s32 rate;
u8 ac; u8 ac;
if (len < sizeof(*tgt_stats)) if (len < sizeof(*tgt_stats))
...@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) ...@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt); le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
stats->tx_rts_fail_cnt += stats->tx_rts_fail_cnt +=
le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt); le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
stats->tx_ucast_rate =
ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate)); rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate);
stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt); stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
...@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) ...@@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.rx.key_cache_miss); le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err); stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame); stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
stats->rx_ucast_rate =
ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate)); rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate);
stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats; ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
...@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = { ...@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = {
void init_netdev(struct net_device *dev) void init_netdev(struct net_device *dev)
{ {
struct ath6kl *ar = ath6kl_priv(dev);
dev->netdev_ops = &ath6kl_netdev_ops; dev->netdev_ops = &ath6kl_netdev_ops;
dev->destructor = free_netdev; dev->destructor = free_netdev;
dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
...@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev) ...@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
WMI_MAX_TX_META_SZ + WMI_MAX_TX_META_SZ +
ATH6KL_HTC_ALIGN_BYTES, 4); ATH6KL_HTC_ALIGN_BYTES, 4);
dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
ar->fw_capabilities))
dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
return; return;
} }
...@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, ...@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break; break;
case WMI_DATA_VI_SVC: case WMI_DATA_VI_SVC:
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
...@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, ...@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break; break;
case WMI_DATA_VO_SVC: case WMI_DATA_VO_SVC:
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT) if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
...@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) ...@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
/* table of devices that work with this driver */ /* table of devices that work with this driver */
static struct usb_device_id ath6kl_usb_ids[] = { static struct usb_device_id ath6kl_usb_ids[] = {
{USB_DEVICE(0x0cf3, 0x9375)},
{USB_DEVICE(0x0cf3, 0x9374)}, {USB_DEVICE(0x0cf3, 0x9374)},
{ /* Terminating entry */ }, { /* Terminating entry */ },
}; };
......
...@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = { ...@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
{0, 0} {0, 0}
}; };
static const s32 wmi_rate_tbl_mcs15[][2] = {
/* {W/O SGI, with SGI} */
{1000, 1000},
{2000, 2000},
{5500, 5500},
{11000, 11000},
{6000, 6000},
{9000, 9000},
{12000, 12000},
{18000, 18000},
{24000, 24000},
{36000, 36000},
{48000, 48000},
{54000, 54000},
{6500, 7200}, /* HT 20, MCS 0 */
{13000, 14400},
{19500, 21700},
{26000, 28900},
{39000, 43300},
{52000, 57800},
{58500, 65000},
{65000, 72200},
{13000, 14400}, /* HT 20, MCS 8 */
{26000, 28900},
{39000, 43300},
{52000, 57800},
{78000, 86700},
{104000, 115600},
{117000, 130000},
{130000, 144400}, /* HT 20, MCS 15 */
{13500, 15000}, /*HT 40, MCS 0 */
{27000, 30000},
{40500, 45000},
{54000, 60000},
{81000, 90000},
{108000, 120000},
{121500, 135000},
{135000, 150000},
{27000, 30000}, /*HT 40, MCS 8 */
{54000, 60000},
{81000, 90000},
{108000, 120000},
{162000, 180000},
{216000, 240000},
{243000, 270000},
{270000, 300000}, /*HT 40, MCS 15 */
{0, 0}
};
/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
static const u8 up_to_ac[] = { static const u8 up_to_ac[] = {
WMM_AC_BE, WMM_AC_BE,
...@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, ...@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{ {
struct ath6kl *ar = wmi->parent_dev; struct ath6kl *ar = wmi->parent_dev;
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities))
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
...@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2) ...@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
NO_SYNC_WMIFLAG); NO_SYNC_WMIFLAG);
} }
s32 ath6kl_wmi_get_rate(s8 rate_index) s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index)
{ {
struct ath6kl *ar = wmi->parent_dev;
u8 sgi = 0; u8 sgi = 0;
s32 ret;
if (rate_index == RATE_AUTO) if (rate_index == RATE_AUTO)
return 0; return 0;
...@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index) ...@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
sgi = 1; sgi = 1;
} }
if (WARN_ON(rate_index > RATE_MCS_7_40)) if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
rate_index = RATE_MCS_7_40; ar->fw_capabilities)) {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
return 0;
ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
} else {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
return 0;
return wmi_rate_tbl[(u32) rate_index][sgi]; ret = wmi_rate_tbl[(u32) rate_index][sgi];
}
return ret;
} }
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
......
...@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
struct ath6kl_htcap *htcap); struct ath6kl_htcap *htcap);
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
s32 ath6kl_wmi_get_rate(s8 rate_index); s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index);
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1); __be32 ips0, __be32 ips1);
......
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