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

Commit 490f0dc4 authored by John W. Linville's avatar John W. Linville
Browse files

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

Conflicts:
	drivers/net/wireless/ath/wil6210/wil6210.h
parents 61ed53de 84cbf3a7
Loading
Loading
Loading
Loading
+42 −41
Original line number Diff line number Diff line
@@ -443,7 +443,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
 * Guts of ath10k_ce_completed_recv_next.
 * The caller takes responsibility for any necessary locking.
 */
static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
					 void **per_transfer_contextp,
					 u32 *bufferp,
					 unsigned int *nbytesp,
@@ -576,7 +576,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
 * Guts of ath10k_ce_completed_send_next.
 * The caller takes responsibility for any necessary locking.
 */
static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
					 void **per_transfer_contextp,
					 u32 *bufferp,
					 unsigned int *nbytesp,
@@ -817,7 +817,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar)
	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
	int ce_id;

	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
	/* Skip the last copy engine, CE7 the diagnostic window, as that
	 * uses polling and isn't initialized for interrupts.
	 */
	for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
		ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
}

@@ -1020,37 +1023,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
 * initialized by software/firmware.
 */
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
			const struct ce_attr *attr,
			void (*send_cb)(struct ath10k_ce_pipe *),
			void (*recv_cb)(struct ath10k_ce_pipe *))
			const struct ce_attr *attr)
{
	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[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(2*TARGET_NUM_MSDU_DESC >
		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));

	spin_lock_bh(&ar_pci->ce_lock);
	ce_state->ar = ar;
	ce_state->id = ce_id;
	ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
	ce_state->attr_flags = attr->flags;
	ce_state->src_sz_max = attr->src_sz_max;
	if (attr->src_nentries)
		ce_state->send_cb = send_cb;
	if (attr->dest_nentries)
		ce_state->recv_cb = recv_cb;
	spin_unlock_bh(&ar_pci->ce_lock);

	if (attr->src_nentries) {
		ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
		if (ret) {
@@ -1098,12 +1074,37 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
}

int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
			 const struct ce_attr *attr)
			 const struct ce_attr *attr,
			 void (*send_cb)(struct ath10k_ce_pipe *),
			 void (*recv_cb)(struct ath10k_ce_pipe *))
{
	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
	struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[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(2*TARGET_NUM_MSDU_DESC >
		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
	BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
		     (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));

	ce_state->ar = ar;
	ce_state->id = ce_id;
	ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
	ce_state->attr_flags = attr->flags;
	ce_state->src_sz_max = attr->src_sz_max;

	if (attr->src_nentries)
		ce_state->send_cb = send_cb;

	if (attr->dest_nentries)
		ce_state->recv_cb = recv_cb;

	if (attr->src_nentries) {
		ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
		if (IS_ERR(ce_state->src_ring)) {
+17 −4
Original line number Diff line number Diff line
@@ -192,15 +192,21 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
				  unsigned int *nbytesp,
				  unsigned int *transfer_idp);

int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
					 void **per_transfer_contextp,
					 u32 *bufferp,
					 unsigned int *nbytesp,
					 unsigned int *transfer_idp);

/*==================CE Engine Initialization=======================*/

int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
			const struct ce_attr *attr);
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
			 const struct ce_attr *attr,
			 void (*send_cb)(struct ath10k_ce_pipe *),
			 void (*recv_cb)(struct ath10k_ce_pipe *));
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
			 const struct ce_attr *attr);
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);

/*==================CE Engine Shutdown=======================*/
@@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
			       void **per_transfer_contextp,
			       u32 *bufferp);

int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
					 void **per_transfer_contextp,
					 u32 *bufferp,
					 unsigned int *nbytesp,
					 unsigned int *transfer_idp,
					 unsigned int *flagsp);

/*
 * Support clean shutdown by allowing the caller to cancel
 * pending sends.  Target DMA must be stopped before using
+88 −23
Original line number Diff line number Diff line
@@ -138,7 +138,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
	return fw;
}

static int ath10k_push_board_ext_data(struct ath10k *ar)
static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
				      size_t data_len)
{
	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
	u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
@@ -159,14 +160,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
	if (board_ext_data_addr == 0)
		return 0;

	if (ar->board_len != (board_data_size + board_ext_data_size)) {
	if (data_len != (board_data_size + board_ext_data_size)) {
		ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
			   ar->board_len, board_data_size, board_ext_data_size);
			   data_len, board_data_size, board_ext_data_size);
		return -EINVAL;
	}

	ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
				      ar->board_data + board_data_size,
				      data + board_data_size,
				      board_ext_data_size);
	if (ret) {
		ath10k_err(ar, "could not write board ext data (%d)\n", ret);
@@ -184,13 +185,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
	return 0;
}

static int ath10k_download_board_data(struct ath10k *ar)
static int ath10k_download_board_data(struct ath10k *ar, const void *data,
				      size_t data_len)
{
	u32 board_data_size = QCA988X_BOARD_DATA_SZ;
	u32 address;
	int ret;

	ret = ath10k_push_board_ext_data(ar);
	ret = ath10k_push_board_ext_data(ar, data, data_len);
	if (ret) {
		ath10k_err(ar, "could not push board ext data (%d)\n", ret);
		goto exit;
@@ -202,9 +204,9 @@ static int ath10k_download_board_data(struct ath10k *ar)
		goto exit;
	}

	ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
	ret = ath10k_bmi_write_memory(ar, address, data,
				      min_t(u32, board_data_size,
					    ar->board_len));
					    data_len));
	if (ret) {
		ath10k_err(ar, "could not write board data (%d)\n", ret);
		goto exit;
@@ -220,11 +222,39 @@ static int ath10k_download_board_data(struct ath10k *ar)
	return ret;
}

static int ath10k_download_cal_file(struct ath10k *ar)
{
	int ret;

	if (!ar->cal_file)
		return -ENOENT;

	if (IS_ERR(ar->cal_file))
		return PTR_ERR(ar->cal_file);

	ret = ath10k_download_board_data(ar, ar->cal_file->data,
					 ar->cal_file->size);
	if (ret) {
		ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
		return ret;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");

	return 0;
}

static int ath10k_download_and_run_otp(struct ath10k *ar)
{
	u32 result, address = ar->hw_params.patch_load_addr;
	int ret;

	ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
	if (ret) {
		ath10k_err(ar, "failed to download board data: %d\n", ret);
		return ret;
	}

	/* OTP is optional */

	if (!ar->otp_data || !ar->otp_len) {
@@ -308,6 +338,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
	if (ar->firmware && !IS_ERR(ar->firmware))
		release_firmware(ar->firmware);

	if (ar->cal_file && !IS_ERR(ar->cal_file))
		release_firmware(ar->cal_file);

	ar->board = NULL;
	ar->board_data = NULL;
	ar->board_len = 0;
@@ -319,6 +352,27 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
	ar->firmware = NULL;
	ar->firmware_data = NULL;
	ar->firmware_len = 0;

	ar->cal_file = NULL;
}

static int ath10k_fetch_cal_file(struct ath10k *ar)
{
	char filename[100];

	/* cal-<bus>-<id>.bin */
	scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
		  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));

	ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
	if (IS_ERR(ar->cal_file))
		/* calibration file is optional, don't print any warnings */
		return PTR_ERR(ar->cal_file);

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
		   ATH10K_FW_DIR, filename);

	return 0;
}

static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
@@ -562,6 +616,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
{
	int ret;

	/* calibration file is optional, don't check for any errors */
	ath10k_fetch_cal_file(ar);

	ar->fw_api = 3;
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);

@@ -589,30 +646,32 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
	return 0;
}

static int ath10k_init_download_firmware(struct ath10k *ar,
					 enum ath10k_firmware_mode mode)
static int ath10k_download_cal_data(struct ath10k *ar)
{
	int ret;

	ret = ath10k_download_board_data(ar);
	if (ret) {
		ath10k_err(ar, "failed to download board data: %d\n", ret);
		return ret;
	ret = ath10k_download_cal_file(ar);
	if (ret == 0) {
		ar->cal_mode = ATH10K_CAL_MODE_FILE;
		goto done;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot did not find a calibration file, try OTP next: %d\n",
		   ret);

	ret = ath10k_download_and_run_otp(ar);
	if (ret) {
		ath10k_err(ar, "failed to run otp: %d\n", ret);
		return ret;
	}

	ret = ath10k_download_fw(ar, mode);
	if (ret) {
		ath10k_err(ar, "failed to download firmware: %d\n", ret);
		return ret;
	}
	ar->cal_mode = ATH10K_CAL_MODE_OTP;

	return ret;
done:
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
		   ath10k_cal_mode_str(ar->cal_mode));
	return 0;
}

static int ath10k_init_uart(struct ath10k *ar)
@@ -729,7 +788,11 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
		goto err;
	}

	status = ath10k_init_download_firmware(ar, mode);
	status = ath10k_download_cal_data(ar);
	if (status)
		goto err;

	status = ath10k_download_fw(ar, mode);
	if (status)
		goto err;

@@ -846,9 +909,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
		goto err_hif_stop;

	if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
		ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
		ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
	else
		ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
		ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;

	INIT_LIST_HEAD(&ar->arvifs);

@@ -1084,6 +1147,7 @@ void ath10k_core_unregister(struct ath10k *ar)
EXPORT_SYMBOL(ath10k_core_unregister);

struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
				  enum ath10k_bus bus,
				  const struct ath10k_hif_ops *hif_ops)
{
	struct ath10k *ar;
@@ -1100,6 +1164,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
	ar->dev = dev;

	ar->hif.ops = hif_ops;
	ar->hif.bus = bus;

	init_completion(&ar->scan.started);
	init_completion(&ar->scan.completed);
+63 −17
Original line number Diff line number Diff line
@@ -63,6 +63,20 @@

struct ath10k;

enum ath10k_bus {
	ATH10K_BUS_PCI,
};

static inline const char *ath10k_bus_str(enum ath10k_bus bus)
{
	switch (bus) {
	case ATH10K_BUS_PCI:
		return "pci";
	}

	return "unknown";
}

struct ath10k_skb_cb {
	dma_addr_t paddr;
	u8 vdev_id;
@@ -96,8 +110,6 @@ struct ath10k_bmi {
	bool done_sent;
};

#define ATH10K_MAX_MEM_REQS 16

struct ath10k_mem_chunk {
	void *vaddr;
	dma_addr_t paddr;
@@ -115,17 +127,21 @@ struct ath10k_wmi {
	struct wmi_pdev_param_map *pdev_param;

	u32 num_mem_chunks;
	struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
	struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
};

struct ath10k_peer_stat {
struct ath10k_fw_stats_peer {
	struct list_head list;

	u8 peer_macaddr[ETH_ALEN];
	u32 peer_rssi;
	u32 peer_tx_rate;
	u32 peer_rx_rate; /* 10x only */
};

struct ath10k_target_stats {
struct ath10k_fw_stats_pdev {
	struct list_head list;

	/* PDEV stats */
	s32 ch_noise_floor;
	u32 tx_frame_count;
@@ -180,15 +196,11 @@ struct ath10k_target_stats {
	s32 phy_errs;
	s32 phy_err_drop;
	s32 mpdu_errs;
};

	/* VDEV STATS */

	/* PEER STATS */
	u8 peers;
	struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];

	/* TODO: Beacon filter stats */

struct ath10k_fw_stats {
	struct list_head pdevs;
	struct list_head peers;
};

struct ath10k_dfs_stats {
@@ -234,6 +246,8 @@ struct ath10k_vif {
	struct sk_buff *beacon;
	/* protected by data_lock */
	bool beacon_sent;
	void *beacon_buf;
	dma_addr_t beacon_paddr;

	struct ath10k *ar;
	struct ieee80211_vif *vif;
@@ -273,6 +287,7 @@ struct ath10k_vif {
	u8 force_sgi;
	bool use_cts_prot;
	int num_legacy_stations;
	int txpower;
};

struct ath10k_vif_iter {
@@ -292,17 +307,19 @@ struct ath10k_fw_crash_data {
struct ath10k_debug {
	struct dentry *debugfs_phy;

	struct ath10k_target_stats target_stats;
	struct ath10k_fw_stats fw_stats;
	struct completion fw_stats_complete;
	bool fw_stats_done;
	DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);

	struct completion event_stats_compl;

	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;

	/* protected by conf_mutex */
	u32 fw_dbglog_mask;
	u32 pktlog_filter;

	u8 htt_max_amsdu;
	u8 htt_max_ampdu;
@@ -371,6 +388,23 @@ enum ath10k_dev_flags {
	ATH10K_FLAG_CORE_REGISTERED,
};

enum ath10k_cal_mode {
	ATH10K_CAL_MODE_FILE,
	ATH10K_CAL_MODE_OTP,
};

static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
{
	switch (mode) {
	case ATH10K_CAL_MODE_FILE:
		return "file";
	case ATH10K_CAL_MODE_OTP:
		return "otp";
	}

	return "unknown";
}

enum ath10k_scan_state {
	ATH10K_SCAN_IDLE,
	ATH10K_SCAN_STARTING,
@@ -421,6 +455,7 @@ struct ath10k {
	bool p2p;

	struct {
		enum ath10k_bus bus;
		const struct ath10k_hif_ops *ops;
	} hif;

@@ -456,7 +491,10 @@ struct ath10k {
	const void *firmware_data;
	size_t firmware_len;

	const struct firmware *cal_file;

	int fw_api;
	enum ath10k_cal_mode cal_mode;

	struct {
		struct completion started;
@@ -482,7 +520,7 @@ struct ath10k {
	/* current operating channel definition */
	struct cfg80211_chan_def chandef;

	int free_vdev_map;
	unsigned long long free_vdev_map;
	bool monitor;
	int monitor_vdev_id;
	bool monitor_started;
@@ -563,11 +601,19 @@ struct ath10k {
		bool utf_monitor;
	} testmode;

	struct {
		/* protected by data_lock */
		u32 fw_crash_counter;
		u32 fw_warm_reset_counter;
		u32 fw_cold_reset_counter;
	} stats;

	/* must be last */
	u8 drv_priv[0] __aligned(sizeof(void *));
};

struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
				  enum ath10k_bus bus,
				  const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);

+670 −221

File changed.

Preview size limit exceeded, changes collapsed.

Loading