Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+37 −16
Original line number Diff line number Diff line
@@ -243,6 +243,16 @@ static inline void ath10k_ce_error_intr_enable(struct ath10k *ar,
			   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,
						     u32 ce_ctrl_addr,
						     unsigned int mask)
@@ -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)
{
	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
	int ce_id, ret;
	u32 intr_summary;

@@ -741,7 +750,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *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))
			intr_summary &= ~(1 << ce_id);
		else
@@ -783,22 +792,25 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
	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;

	ret = ath10k_pci_wake(ar);
	if (ret)
		return;
		return ret;

	for (ce_id = 0; ce_id < ar_pci->ce_count; ce_id++) {
		struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
		u32 ctrl_addr = ce_state->ctrl_addr;
	for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
		u32 ctrl_addr = ath10k_ce_base_address(ce_id);

		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);

	return 0;
}

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,
				const struct ce_attr *attr)
{
	struct ath10k_ce_pipe *ce_state;
	u32 ctrl_addr = ath10k_ce_base_address(ce_id);
	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);
	if (ret)
		return NULL;
@@ -1057,7 +1079,7 @@ struct ath10k_ce_pipe *ath10k_ce_init(struct ath10k *ar,
	ce_state = ath10k_ce_init_state(ar, ce_id, attr);
	if (!ce_state) {
		ath10k_err("Failed to initialize CE state for ID: %d\n", ce_id);
		return NULL;
		goto out;
	}

	if (attr->src_nentries) {
@@ -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",
				   ce_id, ret);
			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,
			ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
				   ce_id, ret);
			ath10k_ce_deinit(ce_state);
			return NULL;
			ce_state = NULL;
			goto out;
		}
	}

	/* Enable CE error interrupts */
	ath10k_ce_error_intr_enable(ar, ctrl_addr);

out:
	ath10k_pci_sleep(ar);

	return ce_state;
}

+1 −1
Original line number Diff line number Diff line
@@ -234,7 +234,7 @@ void ath10k_ce_deinit(struct ath10k_ce_pipe *ce_state);
/*==================CE Interrupt Handlers====================*/
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_disable_interrupts(struct ath10k *ar);
int ath10k_ce_disable_interrupts(struct ath10k *ar);

/* ce_attr.flags values */
/* Use NonSnooping PCIe accesses? */
+31 −12
Original line number Diff line number Diff line
@@ -597,10 +597,8 @@ static int ath10k_init_uart(struct ath10k *ar)
		return ret;
	}

	if (!uart_print) {
		ath10k_info("UART prints disabled\n");
	if (!uart_print)
		return 0;
	}

	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
	if (ret) {
@@ -645,7 +643,7 @@ static int ath10k_init_hw_params(struct ath10k *ar)

	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);

	return 0;
@@ -664,7 +662,8 @@ static void ath10k_core_restart(struct work_struct *work)
		ieee80211_restart_hw(ar->hw);
		break;
	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");
		break;
	case ATH10K_STATE_RESTARTING:
@@ -737,8 +736,6 @@ EXPORT_SYMBOL(ath10k_core_create);

void ath10k_core_destroy(struct ath10k *ar)
{
	ath10k_debug_destroy(ar);

	flush_workqueue(ar->workqueue);
	destroy_workqueue(ar->workqueue);

@@ -786,21 +783,30 @@ int ath10k_core_start(struct ath10k *ar)
		goto err;
	}

	status = ath10k_htc_wait_target(&ar->htc);
	if (status)
	status = ath10k_hif_start(ar);
	if (status) {
		ath10k_err("could not start HIF: %d\n", status);
		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);
	if (status) {
		ath10k_err("could not attach htt (%d)\n", status);
		goto err_wmi_detach;
		goto err_hif_stop;
	}

	status = ath10k_init_connect_htc(ar);
	if (status)
		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);
	if (status) {
@@ -826,12 +832,23 @@ int ath10k_core_start(struct ath10k *ar)
	ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
	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;

err_disconnect_htc:
	ath10k_htc_stop(&ar->htc);
err_htt_detach:
	ath10k_htt_detach(&ar->htt);
err_hif_stop:
	ath10k_hif_stop(ar);
err_wmi_detach:
	ath10k_wmi_detach(ar);
err:
@@ -985,6 +1002,8 @@ void ath10k_core_unregister(struct ath10k *ar)
	ath10k_mac_unregister(ar);

	ath10k_core_free_firmware_files(ar);

	ath10k_debug_destroy(ar);
}
EXPORT_SYMBOL(ath10k_core_unregister);

+22 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "wmi.h"
#include "../ath.h"
#include "../regd.h"
#include "../dfs_pattern_detector.h"

#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -43,7 +44,7 @@
/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95

#define ATH10K_MAX_NUM_MGMT_PENDING 16
#define ATH10K_MAX_NUM_MGMT_PENDING 128

struct ath10k;

@@ -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 */

struct ath10k_peer {
@@ -261,6 +270,8 @@ struct ath10k_debug {

	unsigned long htt_stats_mask;
	struct delayed_work htt_stats_dwork;
	struct ath10k_dfs_stats dfs_stats;
	struct ath_dfs_pool_stats dfs_pool_stats;
};

enum ath10k_state {
@@ -299,6 +310,12 @@ enum ath10k_fw_features {
	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 ath_common ath_common;
	struct ieee80211_hw *hw;
@@ -392,6 +409,8 @@ struct ath10k {
	bool monitor_enabled;
	bool monitor_present;
	unsigned int filter_flags;
	unsigned long dev_flags;
	u32 dfs_block_radar_events;

	struct wmi_pdev_set_wmm_params_arg wmm_params;
	struct completion install_key_done;
@@ -428,6 +447,8 @@ struct ath10k {
	u32 survey_last_cycle_count;
	struct survey_info survey[ATH10K_NUM_CHANS];

	struct dfs_pattern_detector *dfs_detector;

#ifdef CONFIG_ATH10K_DEBUGFS
	struct ath10k_debug debug;
#endif
+94 −0
Original line number Diff line number Diff line
@@ -639,6 +639,86 @@ void ath10k_debug_stop(struct ath10k *ar)
		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)
{
	ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
@@ -667,6 +747,20 @@ int ath10k_debug_create(struct ath10k *ar)
	debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
			    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;
}

Loading