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

Commit 9b5186b4 authored by John W. Linville's avatar John W. Linville
Browse files

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



Kalle Valo <kvalo@qca.qualcomm.com> says:

"One ath6kl patch and rest for ath10k, but nothing really major which
stands out. Most notable:

o fix resume (Bartosz)

o firmware restart is now faster and more reliable (Michal)

o it's now possible to test hardware restart functionality without
  crashing the firmware using hw-restart parameter with
  simulate_fw_crash debugfs file (Michal)"

Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents a15c7068 9de8f26f
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -558,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,

		/* sanity */
		dest_ring->per_transfer_context[sw_index] = NULL;
		desc->nbytes = 0;

		/* Update sw_index */
		sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -835,8 +836,8 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,

	nentries = roundup_pow_of_two(attr->src_nentries);

	memset(src_ring->per_transfer_context, 0,
	       nentries * sizeof(*src_ring->per_transfer_context));
	memset(src_ring->base_addr_owner_space, 0,
	       nentries * sizeof(struct ce_desc));

	src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
	src_ring->sw_index &= src_ring->nentries_mask;
@@ -872,8 +873,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,

	nentries = roundup_pow_of_two(attr->dest_nentries);

	memset(dest_ring->per_transfer_context, 0,
	       nentries * sizeof(*dest_ring->per_transfer_context));
	memset(dest_ring->base_addr_owner_space, 0,
	       nentries * sizeof(struct ce_desc));

	dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
	dest_ring->sw_index &= dest_ring->nentries_mask;
+29 −1
Original line number Diff line number Diff line
@@ -31,12 +31,17 @@
unsigned int ath10k_debug_mask;
static bool uart_print;
static unsigned int ath10k_p2p;
static bool skip_otp;

module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
module_param_named(p2p, ath10k_p2p, uint, 0644);
module_param(skip_otp, bool, 0644);

MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");

static const struct ath10k_hw_params ath10k_hw_params_list[] = {
	{
@@ -280,7 +285,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);

	if (result != 0) {
	if (!skip_otp && result != 0) {
		ath10k_err(ar, "otp calibration failed: %d", result);
		return -EINVAL;
	}
@@ -744,6 +749,25 @@ static void ath10k_core_restart(struct work_struct *work)
{
	struct ath10k *ar = container_of(work, struct ath10k, restart_work);

	set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);

	/* Place a barrier to make sure the compiler doesn't reorder
	 * CRASH_FLUSH and calling other functions.
	 */
	barrier();

	ieee80211_stop_queues(ar->hw);
	ath10k_drain_tx(ar);
	complete_all(&ar->scan.started);
	complete_all(&ar->scan.completed);
	complete_all(&ar->scan.on_channel);
	complete_all(&ar->offchan_tx_completed);
	complete_all(&ar->install_key_done);
	complete_all(&ar->vdev_setup_done);
	wake_up(&ar->htt.empty_tx_wq);
	wake_up(&ar->wmi.tx_credits_wq);
	wake_up(&ar->peer_mapping_wq);

	mutex_lock(&ar->conf_mutex);

	switch (ar->state) {
@@ -781,6 +805,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)

	lockdep_assert_held(&ar->conf_mutex);

	clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);

	ath10k_bmi_start(ar);

	if (ath10k_init_configure_target(ar)) {
@@ -1185,6 +1211,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,

	INIT_LIST_HEAD(&ar->peers);
	init_waitqueue_head(&ar->peer_mapping_wq);
	init_waitqueue_head(&ar->htt.empty_tx_wq);
	init_waitqueue_head(&ar->wmi.tx_credits_wq);

	init_completion(&ar->offchan_tx_completed);
	INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
+5 −0
Original line number Diff line number Diff line
@@ -386,6 +386,11 @@ enum ath10k_dev_flags {
	/* Indicates that ath10k device is during CAC phase of DFS */
	ATH10K_CAC_RUNNING,
	ATH10K_FLAG_CORE_REGISTERED,

	/* Device has crashed and needs to restart. This indicates any pending
	 * waiters should immediately cancel instead of waiting for a time out.
	 */
	ATH10K_FLAG_CRASH_FLUSH,
};

enum ath10k_cal_mode {
+6 −1
Original line number Diff line number Diff line
@@ -695,7 +695,8 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
		"To simulate firmware crash write one of the keywords to this file:\n"
		"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
		"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
		"`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";

	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
@@ -748,6 +749,10 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
	} else if (!strcmp(buf, "assert")) {
		ath10k_info(ar, "simulating firmware assert crash\n");
		ret = ath10k_debug_fw_assert(ar);
	} else if (!strcmp(buf, "hw-restart")) {
		ath10k_info(ar, "user requested hw restart\n");
		queue_work(ar->workqueue, &ar->restart_work);
		ret = 0;
	} else {
		ret = -EINVAL;
		goto exit;
+42 −57
Original line number Diff line number Diff line
@@ -291,8 +291,12 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
	htt->rx_ring.sw_rd_idx.msdu_payld = idx;
	htt->rx_ring.fill_cnt--;

	trace_ath10k_htt_rx_pop_msdu(ar, msdu->data, msdu->len +
				     skb_tailroom(msdu));
	dma_unmap_single(htt->ar->dev,
			 ATH10K_SKB_CB(msdu)->paddr,
			 msdu->len + skb_tailroom(msdu),
			 DMA_FROM_DEVICE);
	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
			msdu->data, msdu->len + skb_tailroom(msdu));

	return msdu;
}
@@ -319,7 +323,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
	int msdu_len, msdu_chaining = 0;
	struct sk_buff *msdu, *next;
	struct htt_rx_desc *rx_desc;
	u32 tsf;

	lockdep_assert_held(&htt->rx_ring.lock);

@@ -332,14 +335,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
	while (msdu) {
		int last_msdu, msdu_len_invalid, msdu_chained;

		dma_unmap_single(htt->ar->dev,
				 ATH10K_SKB_CB(msdu)->paddr,
				 msdu->len + skb_tailroom(msdu),
				 DMA_FROM_DEVICE);

		ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
				msdu->data, msdu->len + skb_tailroom(msdu));

		rx_desc = (struct htt_rx_desc *)msdu->data;

		/* FIXME: we must report msdu payload since this is what caller
@@ -430,14 +425,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
		while (msdu_chained--) {
			struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);

			dma_unmap_single(htt->ar->dev,
					 ATH10K_SKB_CB(next)->paddr,
					 next->len + skb_tailroom(next),
					 DMA_FROM_DEVICE);

			ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
					"htt rx chained: ", next->data,
					next->len + skb_tailroom(next));
			if (!next) {
				ath10k_warn(ar, "failed to pop chained msdu\n");
				ath10k_htt_rx_free_msdu_chain(*head_msdu);
				*head_msdu = NULL;
				msdu = NULL;
				htt->rx_confused = true;
				break;
			}

			skb_trim(next, 0);
			skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE));
@@ -451,8 +446,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
		last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
				RX_MSDU_END_INFO0_LAST_MSDU;

		tsf = __le32_to_cpu(rx_desc->ppdu_end.tsf_timestamp);
		trace_ath10k_htt_rx_desc(ar, tsf, &rx_desc->attention,
		trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
					 sizeof(*rx_desc) - sizeof(u32));
		if (last_msdu) {
			msdu->next = NULL;
@@ -499,6 +493,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
	size_t size;
	struct timer_list *timer = &htt->rx_ring.refill_retry_timer;

	htt->rx_confused = false;

	htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
	if (!is_power_of_2(htt->rx_ring.size)) {
		ath10k_warn(ar, "htt rx ring size is not power of 2\n");
@@ -588,41 +584,47 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
					  enum htt_rx_mpdu_encrypt_type type)
{
	switch (type) {
	case HTT_RX_MPDU_ENCRYPT_NONE:
		return 0;
	case HTT_RX_MPDU_ENCRYPT_WEP40:
	case HTT_RX_MPDU_ENCRYPT_WEP104:
		return 4;
		return IEEE80211_WEP_IV_LEN;
	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
	case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */
	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
	case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */
		return IEEE80211_TKIP_IV_LEN;
	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
		return 8;
	case HTT_RX_MPDU_ENCRYPT_NONE:
		return 0;
		return IEEE80211_CCMP_HDR_LEN;
	case HTT_RX_MPDU_ENCRYPT_WEP128:
	case HTT_RX_MPDU_ENCRYPT_WAPI:
		break;
	}

	ath10k_warn(ar, "unknown encryption type %d\n", type);
	ath10k_warn(ar, "unsupported encryption type %d\n", type);
	return 0;
}

#define MICHAEL_MIC_LEN 8

static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
					 enum htt_rx_mpdu_encrypt_type type)
{
	switch (type) {
	case HTT_RX_MPDU_ENCRYPT_NONE:
		return 0;
	case HTT_RX_MPDU_ENCRYPT_WEP40:
	case HTT_RX_MPDU_ENCRYPT_WEP104:
	case HTT_RX_MPDU_ENCRYPT_WEP128:
	case HTT_RX_MPDU_ENCRYPT_WAPI:
		return 0;
		return IEEE80211_WEP_ICV_LEN;
	case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
	case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
		return 4;
		return IEEE80211_TKIP_ICV_LEN;
	case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
		return 8;
		return IEEE80211_CCMP_MIC_LEN;
	case HTT_RX_MPDU_ENCRYPT_WEP128:
	case HTT_RX_MPDU_ENCRYPT_WAPI:
		break;
	}

	ath10k_warn(ar, "unknown encryption type %d\n", type);
	ath10k_warn(ar, "unsupported encryption type %d\n", type);
	return 0;
}

@@ -899,6 +901,8 @@ static void ath10k_process_rx(struct ath10k *ar,
		   !!(status->flag & RX_FLAG_AMSDU_MORE));
	ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
			skb->data, skb->len);
	trace_ath10k_rx_hdr(ar, skb->data, skb->len);
	trace_ath10k_rx_payload(ar, skb->data, skb->len);

	ieee80211_rx(ar->hw, skb);
}
@@ -1176,7 +1180,6 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head)

static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
					struct sk_buff *head,
					enum htt_rx_mpdu_status status,
					bool channel_set,
					u32 attention)
{
@@ -1200,22 +1203,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
	}

	/* Skip mgmt frames while we handle this in WMI */
	if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
	    attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
	if (attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
		return false;
	}

	if (status != HTT_RX_IND_MPDU_STATUS_OK &&
	    status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
	    status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
	    !htt->ar->monitor_started) {
		ath10k_dbg(ar, ATH10K_DBG_HTT,
			   "htt rx ignoring frame w/ status %d\n",
			   status);
		return false;
	}

	if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
		ath10k_dbg(ar, ATH10K_DBG_HTT,
			   "htt rx CAC running\n");
@@ -1231,8 +1223,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
	struct ath10k *ar = htt->ar;
	struct ieee80211_rx_status *rx_status = &htt->rx_status;
	struct htt_rx_indication_mpdu_range *mpdu_ranges;
	struct htt_rx_desc *rxd;
	enum htt_rx_mpdu_status status;
	struct ieee80211_hdr *hdr;
	int num_mpdu_ranges;
	u32 attention;
@@ -1280,8 +1270,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
				num_mpdu_ranges));

	for (i = 0; i < num_mpdu_ranges; i++) {
		status = mpdu_ranges[i].mpdu_range_status;

		for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
			struct sk_buff *msdu_head, *msdu_tail;

@@ -1302,12 +1290,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
				continue;
			}

			rxd = container_of((void *)msdu_head->data,
					   struct htt_rx_desc,
					   msdu_payload);

			if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
							 status,
							 channel_set,
							 attention)) {
				ath10k_htt_rx_free_msdu_chain(msdu_head);
@@ -1372,6 +1355,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
				      &attention);
	spin_unlock_bh(&htt->rx_ring.lock);

	tasklet_schedule(&htt->rx_replenish_task);

	ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");

	if (ret) {
@@ -1433,7 +1418,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
	/* last fragment of TKIP frags has MIC */
	if (!ieee80211_has_morefrags(hdr->frame_control) &&
	    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
		trim += 8;
		trim += MICHAEL_MIC_LEN;

	if (trim > msdu_head->len) {
		ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
Loading