Commit 145babc6 authored by John W. Linville's avatar John W. Linville

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

Conflicts:
	drivers/net/wireless/ath/ath10k/htc.c
	drivers/net/wireless/ath/ath10k/mac.c
parents e08fd975 cfb27d29
...@@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, ...@@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
misc_ie_addr | CE_ERROR_MASK); misc_ie_addr | CE_ERROR_MASK);
} }
static inline void ath10k_ce_error_intr_disable(struct ath10k *ar,
u32 ce_ctrl_addr)
{
u32 misc_ie_addr = ath10k_pci_read32(ar,
ce_ctrl_addr + MISC_IE_ADDRESS);
ath10k_pci_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS,
misc_ie_addr & ~CE_ERROR_MASK);
}
static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
u32 ce_ctrl_addr, u32 ce_ctrl_addr,
unsigned int mask) unsigned int mask)
...@@ -731,7 +741,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) ...@@ -731,7 +741,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
void ath10k_ce_per_engine_service_any(struct ath10k *ar) void ath10k_ce_per_engine_service_any(struct ath10k *ar)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ce_id, ret; int ce_id, ret;
u32 intr_summary; u32 intr_summary;
...@@ -741,7 +750,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) ...@@ -741,7 +750,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
intr_summary = CE_INTERRUPT_SUMMARY(ar); intr_summary = CE_INTERRUPT_SUMMARY(ar);
for (ce_id = 0; intr_summary && (ce_id < ar_pci->ce_count); ce_id++) { for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
if (intr_summary & (1 << ce_id)) if (intr_summary & (1 << ce_id))
intr_summary &= ~(1 << ce_id); intr_summary &= ~(1 << ce_id);
else else
...@@ -783,22 +792,25 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, ...@@ -783,22 +792,25 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
} }
void ath10k_ce_disable_interrupts(struct ath10k *ar) int ath10k_ce_disable_interrupts(struct ath10k *ar)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ce_id, ret; int ce_id, ret;
ret = ath10k_pci_wake(ar); ret = ath10k_pci_wake(ar);
if (ret) if (ret)
return; return ret;
for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) { for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; u32 ctrl_addr = ath10k_ce_base_address(ce_id);
u32 ctrl_addr = ce_state->ctrl_addr;
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
ath10k_ce_error_intr_disable(ar, ctrl_addr);
ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
} }
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
return 0;
} }
void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
...@@ -1047,9 +1059,19 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ...@@ -1047,9 +1059,19 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
const struct ce_attr *attr) const struct ce_attr *attr)
{ {
struct ath10k_ce_pipe *ce_state; struct ath10k_ce_pipe *ce_state;
u32 ctrl_addr = ath10k_ce_base_address(ce_id);
int ret; int ret;
/*
* Make sure there's enough CE ringbuffer entries for HTT TX to avoid
* additional TX locking checks.
*
* For the lack of a better place do the check here.
*/
BUILD_BUG_ON(TARGET_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
BUILD_BUG_ON(TARGET_10X_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
ret = ath10k_pci_wake(ar); ret = ath10k_pci_wake(ar);
if (ret) if (ret)
return NULL; return NULL;
...@@ -1057,7 +1079,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ...@@ -1057,7 +1079,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
ce_state = ath10k_ce_init_state(ar, ce_id, attr); ce_state = ath10k_ce_init_state(ar, ce_id, attr);
if (!ce_state) { if (!ce_state) {
ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id); ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id);
return NULL; goto out;
} }
if (attr->src_nentries) { if (attr->src_nentries) {
...@@ -1066,7 +1088,8 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ...@@ -1066,7 +1088,8 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n", ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
ce_id, ret); ce_id, ret);
ath10k_ce_deinit(ce_state); ath10k_ce_deinit(ce_state);
return NULL; ce_state = NULL;
goto out;
} }
} }
...@@ -1076,15 +1099,13 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar, ...@@ -1076,15 +1099,13 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n", ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
ce_id, ret); ce_id, ret);
ath10k_ce_deinit(ce_state); ath10k_ce_deinit(ce_state);
return NULL; ce_state = NULL;
goto out;
} }
} }
/* Enable CE error interrupts */ out:
ath10k_ce_error_intr_enable(ar, ctrl_addr);
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
return ce_state; return ce_state;
} }
......
...@@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state); ...@@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state);
/*==================CE Interrupt Handlers====================*/ /*==================CE Interrupt Handlers====================*/
void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service_any(struct ath10k *ar);
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
void ath10k_ce_disable_interrupts(struct ath10k *ar); int ath10k_ce_disable_interrupts(struct ath10k *ar);
/* ce_attr.flags values */ /* ce_attr.flags values */
/* Use NonSnooping PCIe accesses? */ /* Use NonSnooping PCIe accesses? */
......
...@@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar) ...@@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar)
return ret; return ret;
} }
if (!uart_print) { if (!uart_print)
ath10k_info("UART prints disabled\n");
return 0; return 0;
}
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7); ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
if (ret) { if (ret) {
...@@ -645,7 +643,7 @@ static int ath10k_init_hw_params(struct ath10k *ar) ...@@ -645,7 +643,7 @@ static int ath10k_init_hw_params(struct ath10k *ar)
ar->hw_params = *hw_params; ar->hw_params = *hw_params;
ath10k_info("Hardware name %s version 0x%x\n", ath10k_dbg(ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
ar->hw_params.name, ar->target_version); ar->hw_params.name, ar->target_version);
return 0; return 0;
...@@ -664,7 +662,8 @@ static void ath10k_core_restart(struct work_struct *work) ...@@ -664,7 +662,8 @@ static void ath10k_core_restart(struct work_struct *work)
ieee80211_restart_hw(ar->hw); ieee80211_restart_hw(ar->hw);
break; break;
case ATH10K_STATE_OFF: case ATH10K_STATE_OFF:
/* this can happen if driver is being unloaded */ /* this can happen if driver is being unloaded
* or if the crash happens during FW probing */
ath10k_warn("cannot restart a device that hasn't been started\n"); ath10k_warn("cannot restart a device that hasn't been started\n");
break; break;
case ATH10K_STATE_RESTARTING: case ATH10K_STATE_RESTARTING:
...@@ -737,8 +736,6 @@ EXPORT_SYMBOL(ath10k_core_create); ...@@ -737,8 +736,6 @@ EXPORT_SYMBOL(ath10k_core_create);
void ath10k_core_destroy(struct ath10k *ar) void ath10k_core_destroy(struct ath10k *ar)
{ {
ath10k_debug_destroy(ar);
flush_workqueue(ar->workqueue); flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue); destroy_workqueue(ar->workqueue);
...@@ -786,21 +783,30 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -786,21 +783,30 @@ int ath10k_core_start(struct ath10k *ar)
goto err; goto err;
} }
status = ath10k_htc_wait_target(&ar->htc); status = ath10k_hif_start(ar);
if (status) if (status) {
ath10k_err("could not start HIF: %d\n", status);
goto err_wmi_detach; goto err_wmi_detach;
}
status = ath10k_htc_wait_target(&ar->htc);
if (status) {
ath10k_err("failed to connect to HTC: %d\n", status);
goto err_hif_stop;
}
status = ath10k_htt_attach(ar); status = ath10k_htt_attach(ar);
if (status) { if (status) {
ath10k_err("could not attach htt (%d)\n", status); ath10k_err("could not attach htt (%d)\n", status);
goto err_wmi_detach; goto err_hif_stop;
} }
status = ath10k_init_connect_htc(ar); status = ath10k_init_connect_htc(ar);
if (status) if (status)
goto err_htt_detach; goto err_htt_detach;
ath10k_info("firmware %s booted\n", ar->hw->wiphy->fw_version); ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version);
status = ath10k_wmi_cmd_init(ar); status = ath10k_wmi_cmd_init(ar);
if (status) { if (status) {
...@@ -826,12 +832,23 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -826,12 +832,23 @@ int ath10k_core_start(struct ath10k *ar)
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs); INIT_LIST_HEAD(&ar->arvifs);
if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
ath10k_info("%s (0x%x) fw %s api %d htt %d.%d\n",
ar->hw_params.name, ar->target_version,
ar->hw->wiphy->fw_version, ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor);
__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
return 0; return 0;
err_disconnect_htc: err_disconnect_htc:
ath10k_htc_stop(&ar->htc); ath10k_htc_stop(&ar->htc);
err_htt_detach: err_htt_detach:
ath10k_htt_detach(&ar->htt); ath10k_htt_detach(&ar->htt);
err_hif_stop:
ath10k_hif_stop(ar);
err_wmi_detach: err_wmi_detach:
ath10k_wmi_detach(ar); ath10k_wmi_detach(ar);
err: err:
...@@ -985,6 +1002,8 @@ void ath10k_core_unregister(struct ath10k *ar) ...@@ -985,6 +1002,8 @@ void ath10k_core_unregister(struct ath10k *ar)
ath10k_mac_unregister(ar); ath10k_mac_unregister(ar);
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
ath10k_debug_destroy(ar);
} }
EXPORT_SYMBOL(ath10k_core_unregister); EXPORT_SYMBOL(ath10k_core_unregister);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "wmi.h" #include "wmi.h"
#include "../ath.h" #include "../ath.h"
#include "../regd.h" #include "../regd.h"
#include "../dfs_pattern_detector.h"
#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
...@@ -43,7 +44,7 @@ ...@@ -43,7 +44,7 @@
/* Antenna noise floor */ /* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95 #define ATH10K_DEFAULT_NOISE_FLOOR -95
#define ATH10K_MAX_NUM_MGMT_PENDING 16 #define ATH10K_MAX_NUM_MGMT_PENDING 128
struct ath10k; struct ath10k;
...@@ -192,6 +193,14 @@ struct ath10k_target_stats { ...@@ -192,6 +193,14 @@ struct ath10k_target_stats {
}; };
struct ath10k_dfs_stats {
u32 phy_errors;
u32 pulses_total;
u32 pulses_detected;
u32 pulses_discarded;
u32 radar_detected;
};
#define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */ #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
struct ath10k_peer { struct ath10k_peer {
...@@ -261,6 +270,8 @@ struct ath10k_debug { ...@@ -261,6 +270,8 @@ struct ath10k_debug {
unsigned long htt_stats_mask; unsigned long htt_stats_mask;
struct delayed_work htt_stats_dwork; struct delayed_work htt_stats_dwork;
struct ath10k_dfs_stats dfs_stats;
struct ath_dfs_pool_stats dfs_pool_stats;
}; };
enum ath10k_state { enum ath10k_state {
...@@ -299,6 +310,12 @@ enum ath10k_fw_features { ...@@ -299,6 +310,12 @@ enum ath10k_fw_features {
ATH10K_FW_FEATURE_COUNT, ATH10K_FW_FEATURE_COUNT,
}; };
enum ath10k_dev_flags {
/* Indicates that ath10k device is during CAC phase of DFS */
ATH10K_CAC_RUNNING,
ATH10K_FLAG_FIRST_BOOT_DONE,
};
struct ath10k { struct ath10k {
struct ath_common ath_common; struct ath_common ath_common;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
...@@ -392,6 +409,8 @@ struct ath10k { ...@@ -392,6 +409,8 @@ struct ath10k {
bool monitor_enabled; bool monitor_enabled;
bool monitor_present; bool monitor_present;
unsigned int filter_flags; unsigned int filter_flags;
unsigned long dev_flags;
u32 dfs_block_radar_events;
struct wmi_pdev_set_wmm_params_arg wmm_params; struct wmi_pdev_set_wmm_params_arg wmm_params;
struct completion install_key_done; struct completion install_key_done;
...@@ -428,6 +447,8 @@ struct ath10k { ...@@ -428,6 +447,8 @@ struct ath10k {
u32 survey_last_cycle_count; u32 survey_last_cycle_count;
struct survey_info survey[ATH10K_NUM_CHANS]; struct survey_info survey[ATH10K_NUM_CHANS];
struct dfs_pattern_detector *dfs_detector;
#ifdef CONFIG_ATH10K_DEBUGFS #ifdef CONFIG_ATH10K_DEBUGFS
struct ath10k_debug debug; struct ath10k_debug debug;
#endif #endif
......
...@@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar) ...@@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar)
cancel_delayed_work(&ar->debug.htt_stats_dwork); cancel_delayed_work(&ar->debug.htt_stats_dwork);
} }
static ssize_t ath10k_write_simulate_radar(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
ieee80211_radar_detected(ar->hw);
return count;
}
static const struct file_operations fops_simulate_radar = {
.write = ath10k_write_simulate_radar,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
#define ATH10K_DFS_STAT(s, p) (\
len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
ar->debug.dfs_stats.p))
#define ATH10K_DFS_POOL_STAT(s, p) (\
len += scnprintf(buf + len, size - len, "%-28s : %10u\n", s, \
ar->debug.dfs_pool_stats.p))
static ssize_t ath10k_read_dfs_stats(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
int retval = 0, len = 0;
const int size = 8000;
struct ath10k *ar = file->private_data;
char *buf;
buf = kzalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
if (!ar->dfs_detector) {
len += scnprintf(buf + len, size - len, "DFS not enabled\n");
goto exit;
}
ar->debug.dfs_pool_stats =
ar->dfs_detector->get_stats(ar->dfs_detector);
len += scnprintf(buf + len, size - len, "Pulse detector statistics:\n");
ATH10K_DFS_STAT("reported phy errors", phy_errors);
ATH10K_DFS_STAT("pulse events reported", pulses_total);
ATH10K_DFS_STAT("DFS pulses detected", pulses_detected);
ATH10K_DFS_STAT("DFS pulses discarded", pulses_discarded);
ATH10K_DFS_STAT("Radars detected", radar_detected);
len += scnprintf(buf + len, size - len, "Global Pool statistics:\n");
ATH10K_DFS_POOL_STAT("Pool references", pool_reference);
ATH10K_DFS_POOL_STAT("Pulses allocated", pulse_allocated);
ATH10K_DFS_POOL_STAT("Pulses alloc error", pulse_alloc_error);
ATH10K_DFS_POOL_STAT("Pulses in use", pulse_used);
ATH10K_DFS_POOL_STAT("Seqs. allocated", pseq_allocated);
ATH10K_DFS_POOL_STAT("Seqs. alloc error", pseq_alloc_error);
ATH10K_DFS_POOL_STAT("Seqs. in use", pseq_used);
exit:
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_dfs_stats = {
.read = ath10k_read_dfs_stats,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int ath10k_debug_create(struct ath10k *ar) int ath10k_debug_create(struct ath10k *ar)
{ {
ar->debug.debugfs_phy = debugfs_create_dir("ath10k", ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
...@@ -667,6 +747,20 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -667,6 +747,20 @@ 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);
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_simulate_radar);
debugfs_create_bool("dfs_block_radar_events", S_IWUSR,
ar->debug.debugfs_phy,
&ar->dfs_block_radar_events);
debugfs_create_file("dfs_stats", S_IRUSR,
ar->debug.debugfs_phy, ar,
&fops_dfs_stats);
}
return 0; return 0;
} }
......
...@@ -33,6 +33,7 @@ enum ath10k_debug_mask { ...@@ -33,6 +33,7 @@ enum ath10k_debug_mask {
ATH10K_DBG_MGMT = 0x00000100, ATH10K_DBG_MGMT = 0x00000100,
ATH10K_DBG_DATA = 0x00000200, ATH10K_DBG_DATA = 0x00000200,
ATH10K_DBG_BMI = 0x00000400, ATH10K_DBG_BMI = 0x00000400,
ATH10K_DBG_REGULATORY = 0x00000800,
ATH10K_DBG_ANY = 0xffffffff, ATH10K_DBG_ANY = 0xffffffff,
}; };
...@@ -53,6 +54,8 @@ void ath10k_debug_read_service_map(struct ath10k *ar, ...@@ -53,6 +54,8 @@ void ath10k_debug_read_service_map(struct ath10k *ar,
void ath10k_debug_read_target_stats(struct ath10k *ar, void ath10k_debug_read_target_stats(struct ath10k *ar,
struct wmi_stats_event *ev); struct wmi_stats_event *ev);
#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
#else #else
static inline int ath10k_debug_start(struct ath10k *ar) static inline int ath10k_debug_start(struct ath10k *ar)
{ {
...@@ -82,6 +85,9 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar, ...@@ -82,6 +85,9 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
struct wmi_stats_event *ev) struct wmi_stats_event *ev)
{ {
} }
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#endif /* CONFIG_ATH10K_DEBUGFS */ #endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG #ifdef CONFIG_ATH10K_DEBUG
......
...@@ -191,6 +191,11 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar, ...@@ -191,6 +191,11 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
struct ath10k_htc *htc = &ar->htc; struct ath10k_htc *htc = &ar->htc;
struct ath10k_htc_ep *ep = &htc->endpoint[eid]; struct ath10k_htc_ep *ep = &htc->endpoint[eid];
if (!skb) {
ath10k_warn("invalid sk_buff completion - NULL pointer. firmware crashed?\n");
return 0;
}
ath10k_htc_notify_tx_completion(ep, skb); ath10k_htc_notify_tx_completion(ep, skb);
/* the skb now belongs to the completion handler */ /* the skb now belongs to the completion handler */
...@@ -534,14 +539,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -534,14 +539,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
u16 credit_count; u16 credit_count;
u16 credit_size; u16 credit_size;
reinit_completion(&htc->ctl_resp);
status = ath10k_hif_start(htc->ar);
if (status) {
ath10k_err("could not start HIF (%d)\n", status);
goto err_start;
}
status = wait_for_completion_timeout(&htc->ctl_resp, status = wait_for_completion_timeout(&htc->ctl_resp,
ATH10K_HTC_WAIT_TIMEOUT_HZ); ATH10K_HTC_WAIT_TIMEOUT_HZ);
if (status <= 0) { if (status <= 0) {
...@@ -549,15 +546,13 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -549,15 +546,13 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
status = -ETIMEDOUT; status = -ETIMEDOUT;
ath10k_err("ctl_resp never came in (%d)\n", status); ath10k_err("ctl_resp never came in (%d)\n", status);
goto err_target; return status;
} }
if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
ath10k_err("Invalid HTC ready msg len:%d\n", ath10k_err("Invalid HTC ready msg len:%d\n",
htc->control_resp_len); htc->control_resp_len);
return -ECOMM;
status = -ECOMM;
goto err_target;
} }
msg = (struct ath10k_htc_msg *)htc->control_resp_buffer; msg = (struct ath10k_htc_msg *)htc->control_resp_buffer;
...@@ -567,8 +562,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -567,8 +562,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
if (message_id != ATH10K_HTC_MSG_READY_ID) { if (message_id != ATH10K_HTC_MSG_READY_ID) {
ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id); ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id);
status = -ECOMM; return -ECOMM;
goto err_target;
} }
htc->total_transmit_credits = credit_count; htc->total_transmit_credits = credit_count;
...@@ -581,9 +575,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -581,9 +575,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
if ((htc->total_transmit_credits == 0) || if ((htc->total_transmit_credits == 0) ||
(htc->target_credit_size == 0)) { (htc->target_credit_size == 0)) {
status = -ECOMM;
ath10k_err("Invalid credit size received\n"); ath10k_err("Invalid credit size received\n");
goto err_target; return -ECOMM;
} }
ath10k_htc_setup_target_buffer_assignments(htc); ath10k_htc_setup_target_buffer_assignments(htc);
...@@ -600,14 +593,10 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -600,14 +593,10 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
if (status) { if (status) {
ath10k_err("could not connect to htc service (%d)\n", status); ath10k_err("could not connect to htc service (%d)\n", status);
goto err_target; return status;
} }
return 0; return 0;
err_target:
ath10k_hif_stop(htc->ar);
err_start:
return status;
} }
int ath10k_htc_connect_service(struct ath10k_htc *htc, int ath10k_htc_connect_service(struct ath10k_htc *htc,
......
...@@ -104,7 +104,7 @@ int ath10k_htt_attach(struct ath10k *ar) ...@@ -104,7 +104,7 @@ int ath10k_htt_attach(struct ath10k *ar)
static int ath10k_htt_verify_version(struct ath10k_htt *htt) static int ath10k_htt_verify_version(struct ath10k_htt *htt)
{ {
ath10k_info("htt target version %d.%d\n", ath10k_dbg(ATH10K_DBG_BOOT, "htt target version %d.%d\n",
htt->target_version_major, htt->target_version_minor); htt->target_version_major, htt->target_version_minor);
if (htt->target_version_major != 2 && if (htt->target_version_major != 2 &&
......
...@@ -1182,6 +1182,7 @@ struct htt_rx_info { ...@@ -1182,6 +1182,7 @@ struct htt_rx_info {
u32 info2; u32 info2;
} rate; } rate;
bool fcs_err; bool fcs_err;
bool amsdu_more;
}; };
struct ath10k_htt { struct ath10k_htt {
......
...@@ -659,23 +659,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -659,23 +659,6 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
memcpy(hdr_buf, hdr, hdr_len); memcpy(hdr_buf, hdr, hdr_len);
hdr = (struct ieee80211_hdr *)hdr_buf; hdr = (struct ieee80211_hdr *)hdr_buf;
/* FIXME: Hopefully this is a temporary measure.
*
* Reporting individual A-MSDU subframes means each reported frame
* shares the same sequence number.
*
* mac80211 drops frames it recognizes as duplicates, i.e.
* retransmission flag is set and sequence number matches sequence
* number from a previous frame (as per IEEE 802.11-2012: 9.3.2.10
* "Duplicate detection and recovery")
*
* To avoid frames being dropped clear retransmission flag for all
* received A-MSDUs.
*
* Worst case: actual duplicate frames will be reported but this should
* still be handled gracefully by other OSI/ISO layers. */
hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_RETRY);
first = skb; first = skb;
while (skb) { while (skb) {
void *decap_hdr; void *decap_hdr;
...@@ -746,6 +729,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -746,6 +729,9 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
skb = skb->next; skb = skb->next;
info->skb->next = NULL; info->skb->next = NULL;
if (skb)
info->amsdu_more = true;
ath10k_process_rx(htt->ar, info); ath10k_process_rx(htt->ar, info);
} }
...@@ -959,6 +945,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -959,6 +945,11 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
continue; continue;
} }
if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
ath10k_htt_rx_free_msdu_chain(msdu_head);
continue;
}
/* FIXME: we do not support chaining yet. /* FIXME: we do not support chaining yet.
* this needs investigation */ * this needs investigation */
if (msdu_chaining) { if (msdu_chaining) {
......
...@@ -85,16 +85,13 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) ...@@ -85,16 +85,13 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
int ath10k_htt_tx_attach(struct ath10k_htt *htt) int ath10k_htt_tx_attach(struct ath10k_htt *htt)
{ {
u8 pipe;
spin_lock_init(&htt->tx_lock); spin_lock_init(&htt->tx_lock);
init_waitqueue_head(&htt->empty_tx_wq); init_waitqueue_head(&htt->empty_tx_wq);
/* At the beginning free queue number should hint us the maximum if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
* queue length */ htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id; else
htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar, htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
pipe);
ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
htt->max_num_pending_tx); htt->max_num_pending_tx);
......
...@@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode { ...@@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode {
#define CORE_CTRL_CPU_INTR_MASK 0x00002000 #define CORE_CTRL_CPU_INTR_MASK 0x00002000
#define CORE_CTRL_ADDRESS 0x0000 #define CORE_CTRL_ADDRESS 0x0000
#define PCIE_INTR_ENABLE_ADDRESS 0x0008 #define PCIE_INTR_ENABLE_ADDRESS 0x0008
#define PCIE_INTR_CAUSE_ADDRESS 0x000c
#define PCIE_INTR_CLR_ADDRESS 0x0014 #define PCIE_INTR_CLR_ADDRESS 0x0014
#define SCRATCH_3_ADDRESS 0x0030 #define SCRATCH_3_ADDRESS 0x0030
......
This diff is collapsed.
This diff is collapsed.
...@@ -198,9 +198,7 @@ struct ath10k_pci { ...@@ -198,9 +198,7 @@ struct ath10k_pci {
struct tasklet_struct intr_tq; struct tasklet_struct intr_tq;
struct tasklet_struct msi_fw_err; struct tasklet_struct msi_fw_err;
struct tasklet_struct early_irq_tasklet;
/* Number of Copy Engines supported */
unsigned int ce_count;
int started; int started;
...@@ -318,6 +316,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) ...@@ -318,6 +316,16 @@ static inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
return ioread32(ar_pci->mem + offset); return ioread32(ar_pci->mem + offset);
} }
static inline u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr)
{
return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr);
}
static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
{
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
}
int ath10k_do_pci_wake(struct ath10k *ar); int ath10k_do_pci_wake(struct ath10k *ar);
void ath10k_do_pci_sleep(struct ath10k *ar); void ath10k_do_pci_sleep(struct ath10k *ar);
......
...@@ -75,6 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -75,6 +75,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
ath10k_report_offchan_tx(htt->ar, msdu); ath10k_report_offchan_tx(htt->ar, msdu);
info = IEEE80211_SKB_CB(msdu); info = IEEE80211_SKB_CB(msdu);
memset(&info->status, 0, sizeof(info->status));
if (tx_done->discard) { if (tx_done->discard) {
ieee80211_free_txskb(htt->ar->hw, msdu); ieee80211_free_txskb(htt->ar->hw, msdu);
...@@ -183,7 +184,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info, ...@@ -183,7 +184,7 @@ static void process_rx_rates(struct ath10k *ar, struct htt_rx_info *info,
/* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2 /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
TODO check this */ TODO check this */
mcs = (info2 >> 4) & 0x0F; mcs = (info2 >> 4) & 0x0F;
nss = (info1 >> 10) & 0x07; nss = ((info1 >> 10) & 0x07) + 1;
bw = info1 & 3; bw = info1 & 3;
sgi = info2 & 1; sgi = info2 & 1;
...@@ -236,6 +237,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info) ...@@ -236,6 +237,9 @@ void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info)
if (info->fcs_err) if (info->fcs_err)
status->flag |= RX_FLAG_FAILED_FCS_CRC; status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (info->amsdu_more)
status->flag |= RX_FLAG_AMSDU_MORE;
status->signal = info->signal; status->signal = info->signal;
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
......
This diff is collapsed.
...@@ -893,6 +893,7 @@ struct wmi_channel { ...@@ -893,6 +893,7 @@ struct wmi_channel {
union { union {
__le32 reginfo0; __le32 reginfo0;
struct { struct {
/* note: power unit is 0.5 dBm */
u8 min_power; u8 min_power;
u8 max_power; u8 max_power;
u8 reg_power; u8 reg_power;
...@@ -915,7 +916,8 @@ struct wmi_channel_arg { ...@@ -915,7 +916,8 @@ struct wmi_channel_arg {
bool allow_ht; bool allow_ht;
bool allow_vht; bool allow_vht;
bool ht40plus; bool ht40plus;
/* note: power unit is 1/4th of dBm */ bool chan_radar;
/* note: power unit is 0.5 dBm */
u32 min_power; u32 min_power;
u32 max_power; u32 max_power;
u32 max_reg_power; u32 max_reg_power;
...@@ -1977,6 +1979,10 @@ struct wmi_mgmt_rx_event_v2 { ...@@ -1977,6 +1979,10 @@ struct wmi_mgmt_rx_event_v2 {
#define WMI_RX_STATUS_ERR_MIC 0x10 #define WMI_RX_STATUS_ERR_MIC 0x10
#define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20
#define PHY_ERROR_SPECTRAL_SCAN 0x26
#define PHY_ERROR_FALSE_RADAR_EXT 0x24
#define PHY_ERROR_RADAR 0x05
struct wmi_single_phyerr_rx_hdr { struct wmi_single_phyerr_rx_hdr {
/* TSF timestamp */ /* TSF timestamp */
__le32 tsf_timestamp; __le32 tsf_timestamp;
...@@ -2068,6 +2074,87 @@ struct wmi_comb_phyerr_rx_event { ...@@ -2068,6 +2074,87 @@ struct wmi_comb_phyerr_rx_event {
u8 bufp[0]; u8 bufp[0];
} __packed; } __packed;
#define PHYERR_TLV_SIG 0xBB
#define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB
#define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8
struct phyerr_radar_report {
__le32 reg0; /* RADAR_REPORT_REG0_* */
__le32 reg1; /* REDAR_REPORT_REG1_* */
} __packed;
#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_MASK 0x80000000
#define RADAR_REPORT_REG0_PULSE_IS_CHIRP_LSB 31
#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_MASK 0x40000000
#define RADAR_REPORT_REG0_PULSE_IS_MAX_WIDTH_LSB 30
#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_MASK 0x3FF00000
#define RADAR_REPORT_REG0_AGC_TOTAL_GAIN_LSB 20
#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_MASK 0x000F0000
#define RADAR_REPORT_REG0_PULSE_DELTA_DIFF_LSB 16
#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_MASK 0x0000FC00
#define RADAR_REPORT_REG0_PULSE_DELTA_PEAK_LSB 10
#define RADAR_REPORT_REG0_PULSE_SIDX_MASK 0x000003FF
#define RADAR_REPORT_REG0_PULSE_SIDX_LSB 0
#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_MASK 0x80000000
#define RADAR_REPORT_REG1_PULSE_SRCH_FFT_VALID_LSB 31
#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_MASK 0x7F000000
#define RADAR_REPORT_REG1_PULSE_AGC_MB_GAIN_LSB 24
#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_MASK 0x00FF0000
#define RADAR_REPORT_REG1_PULSE_SUBCHAN_MASK_LSB 16
#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_MASK 0x0000FF00
#define RADAR_REPORT_REG1_PULSE_TSF_OFFSET_LSB 8
#define RADAR_REPORT_REG1_PULSE_DUR_MASK 0x000000FF
#define RADAR_REPORT_REG1_PULSE_DUR_LSB 0
struct phyerr_fft_report {
__le32 reg0; /* SEARCH_FFT_REPORT_REG0_ * */
__le32 reg1; /* SEARCH_FFT_REPORT_REG1_ * */
} __packed;
#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_MASK 0xFF800000
#define SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB_LSB 23
#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_MASK 0x007FC000
#define SEARCH_FFT_REPORT_REG0_BASE_PWR_DB_LSB 14
#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_MASK 0x00003000
#define SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX_LSB 12
#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_MASK 0x00000FFF
#define SEARCH_FFT_REPORT_REG0_PEAK_SIDX_LSB 0
#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_MASK 0xFC000000
#define SEARCH_FFT_REPORT_REG1_RELPWR_DB_LSB 26
#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_MASK 0x03FC0000
#define SEARCH_FFT_REPORT_REG1_AVGPWR_DB_LSB 18
#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_MASK 0x0003FF00
#define SEARCH_FFT_REPORT_REG1_PEAK_MAG_LSB 8
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK 0x000000FF
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB 0
struct phyerr_tlv {
__le16 len;
u8 tag;
u8 sig;
} __packed;
#define DFS_RSSI_POSSIBLY_FALSE 50
#define DFS_PEAK_MAG_THOLD_POSSIBLY_FALSE 40
struct wmi_mgmt_tx_hdr { struct wmi_mgmt_tx_hdr {
__le32 vdev_id; __le32 vdev_id;
struct wmi_mac_addr peer_macaddr; struct wmi_mac_addr peer_macaddr;
...@@ -2233,7 +2320,12 @@ enum wmi_pdev_param { ...@@ -2233,7 +2320,12 @@ enum wmi_pdev_param {
* 0: no protection 1:use CTS-to-self 2: use RTS/CTS * 0: no protection 1:use CTS-to-self 2: use RTS/CTS
*/ */
WMI_PDEV_PARAM_PROTECTION_MODE, WMI_PDEV_PARAM_PROTECTION_MODE,
/* Dynamic bandwidth 0: disable 1: enable */ /*
* Dynamic bandwidth - 0: disable, 1: enable
*
* When enabled HW rate control tries different bandwidths when
* retransmitting frames.
*/
WMI_PDEV_PARAM_DYNAMIC_BW, WMI_PDEV_PARAM_DYNAMIC_BW,
/* Non aggregrate/ 11g sw retry threshold.0-disable */ /* Non aggregrate/ 11g sw retry threshold.0-disable */
WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH, WMI_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
......
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