Linux wireless drivers development
 help / color / mirror / Atom feed
* [RFC 09/10] ath10k: htt: High latency TX support
From: Erik Stromdahl @ 2017-01-13 21:35 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1484343309-6327-1-git-send-email-erik.stromdahl@gmail.com>

Add HTT TX function for HL interfaces.
Intended for SDIO and USB.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/htt.h    |  9 ++--
 drivers/net/wireless/ath/ath10k/htt_tx.c | 72 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/mac.c    |  5 ++-
 3 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index dd9e582..d40b3a0 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1826,9 +1826,12 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
 void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
-int ath10k_htt_tx(struct ath10k_htt *htt,
-		  enum ath10k_hw_txrx_mode txmode,
-		  struct sk_buff *msdu);
+int ath10k_htt_tx_ll(struct ath10k_htt *htt,
+		     enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu);
+int ath10k_htt_tx_hl(struct ath10k_htt *htt,
+		     enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu);
 void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
 					     struct sk_buff *skb);
 int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 505d3ed..e64c249 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -945,8 +945,76 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 	return res;
 }
 
-int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
-		  struct sk_buff *msdu)
+#define HTT_TX_HL_NEEDED_HEADROOM \
+	(unsigned int)(sizeof(struct htt_cmd_hdr) + \
+	sizeof(struct htt_data_tx_desc) + \
+	sizeof(struct ath10k_htc_hdr))
+
+int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu)
+{
+	struct ath10k *ar = htt->ar;
+	int res, data_len;
+	struct htt_cmd_hdr *cmd_hdr;
+	struct htt_data_tx_desc *tx_desc;
+	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
+	u8 flags0;
+	u16 flags1 = 0;
+
+	data_len = msdu->len;
+	flags0 = SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+
+	if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
+		flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+
+	if (msdu->ip_summed == CHECKSUM_PARTIAL &&
+	    !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
+		flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
+	}
+
+	/* Prepend the HTT header and TX desc struct to the data message
+	 * and realloc the skb if it does not have enough headroom.
+	 */
+	if (skb_headroom(msdu) < HTT_TX_HL_NEEDED_HEADROOM) {
+		struct sk_buff *tmp_skb = msdu;
+
+		ath10k_dbg(htt->ar, ATH10K_DBG_HTT,
+			   "Not enough headroom in skb. Current headroom: %u, needed: %u. Reallocating...\n",
+			   skb_headroom(msdu), HTT_TX_HL_NEEDED_HEADROOM);
+		msdu = skb_realloc_headroom(msdu, HTT_TX_HL_NEEDED_HEADROOM);
+		kfree_skb(tmp_skb);
+		if (!msdu) {
+			ath10k_warn(htt->ar, "htt hl tx: Unable to realloc skb!\n");
+			res = -ENOMEM;
+			goto out;
+		}
+	}
+
+	skb_push(msdu, sizeof(*cmd_hdr));
+	skb_push(msdu, sizeof(*tx_desc));
+	cmd_hdr = (struct htt_cmd_hdr *)msdu->data;
+	tx_desc = (struct htt_data_tx_desc *)(msdu->data + sizeof(*cmd_hdr));
+
+	cmd_hdr->msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
+	tx_desc->flags0 = flags0;
+	tx_desc->flags1 = __cpu_to_le16(flags1);
+	tx_desc->len = __cpu_to_le16(data_len);
+	tx_desc->id = 0;
+	tx_desc->frags_paddr = 0; /* always zero */
+	/* Initialize peer_id to INVALID_PEER because this is NOT
+	 * Reinjection path
+	 */
+	tx_desc->peerid = __cpu_to_le16(HTT_INVALID_PEERID);
+
+	res = ath10k_htc_send(&htt->ar->htc, htt->eid, msdu);
+
+out:
+	return res;
+}
+
+int ath10k_htt_tx_ll(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+		     struct sk_buff *msdu)
 {
 	struct ath10k *ar = htt->ar;
 	struct device *dev = ar->dev;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 28bf199..477e170 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3531,7 +3531,10 @@ static int ath10k_mac_tx_submit(struct ath10k *ar,
 
 	switch (txpath) {
 	case ATH10K_MAC_TX_HTT:
-		ret = ath10k_htt_tx(htt, txmode, skb);
+		if (ar->is_high_latency)
+			ret = ath10k_htt_tx_hl(htt, txmode, skb);
+		else
+			ret = ath10k_htt_tx_ll(htt, txmode, skb);
 		break;
 	case ATH10K_MAC_TX_HTT_MGMT:
 		ret = ath10k_htt_mgmt_tx(htt, skb);
-- 
2.7.4

^ permalink raw reply related

* [RFC 08/10] ath10k: add start_once support
From: Erik Stromdahl @ 2017-01-13 21:35 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1484343309-6327-1-git-send-email-erik.stromdahl@gmail.com>

Add possibility to configure the driver to only start target once.
This can reduce startup time of SDIO devices significantly since
loading the firmware can take a substantial amount of time.

The patch is also necessary for high latency devices in general
since it does not seem to be possible to rerun the BMI phase
(fw upload) without power-cycling the device.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/core.c | 20 ++++++++++++++++----
 drivers/net/wireless/ath/ath10k/core.h |  2 ++
 drivers/net/wireless/ath/ath10k/hw.h   |  6 ++++++
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 31a9471..250e32b 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -302,6 +302,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
 		.max_num_peers = TARGET_QCA9377_HL_NUM_PEERS,
 		.is_high_latency = true,
 		.bus = ATH10K_BUS_USB,
+		.start_once = true,
 	},
 	{
 		.id = QCA4019_HW_1_0_DEV_VERSION,
@@ -1841,6 +1842,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 	int status;
 	u32 val;
 
+	if (ar->is_started && ar->hw_params.start_once)
+		return 0;
+
 	lockdep_assert_held(&ar->conf_mutex);
 
 	clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -2053,6 +2057,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 	if (status)
 		goto err_hif_stop;
 
+	ar->is_started = true;
 	return 0;
 
 err_hif_stop:
@@ -2105,6 +2110,7 @@ void ath10k_core_stop(struct ath10k *ar)
 	ath10k_htt_tx_stop(&ar->htt);
 	ath10k_htt_rx_free(&ar->htt);
 	ath10k_wmi_detach(ar);
+	ar->is_started = false;
 }
 EXPORT_SYMBOL(ath10k_core_stop);
 
@@ -2202,12 +2208,18 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 		goto err_unlock;
 	}
 
-	ath10k_debug_print_boot_info(ar);
-	ath10k_core_stop(ar);
+	/* Leave target running if hw_params.start_once is set */
+	if (ar->hw_params.start_once) {
+		mutex_unlock(&ar->conf_mutex);
+	} else {
+		ath10k_debug_print_boot_info(ar);
+		ath10k_core_stop(ar);
 
-	mutex_unlock(&ar->conf_mutex);
+		mutex_unlock(&ar->conf_mutex);
+
+		ath10k_hif_power_down(ar);
+	}
 
-	ath10k_hif_power_down(ar);
 	return 0;
 
 err_unlock:
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index d9d7805..800f058 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -746,6 +746,8 @@ struct ath10k {
 
 	bool is_high_latency;
 
+	bool is_started;
+
 	struct {
 		enum ath10k_bus bus;
 		const struct ath10k_hif_ops *ops;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 33186be..04ae66d 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -436,6 +436,12 @@ struct ath10k_hw_params {
 	bool is_high_latency;
 
 	enum ath10k_bus bus;
+
+	/* Specifies whether or not the device should be started once.
+	 * If set, the device will be started once by the early fw probe
+	 * and it will not be terminated afterwards.
+	 */
+	bool start_once;
 };
 
 struct htt_rx_desc;
-- 
2.7.4

^ permalink raw reply related

* [RFC 10/10] ath10k: htt: High latency RX support
From: Erik Stromdahl @ 2017-01-13 21:35 UTC (permalink / raw)
  To: kvalo, linux-wireless, ath10k; +Cc: Erik Stromdahl
In-Reply-To: <1484343309-6327-1-git-send-email-erik.stromdahl@gmail.com>

Special HTT RX handling for high latency interfaces.

Since no DMA physical addresses are used in the RX ring
config message (this is not supported by the high latency
devices), no RX ring is allocated.
All RX skb's are allocated by the driver and passed directly
to mac80211 in the HTT RX indication handler.

A nice side effect of this is that no huge buffer will be
allocated with dma_alloc_coherent. On embedded systems with
limited memory resources, the allocation of the RX ring is
prone to fail.

Some tweaks made to "make it work":

Removal of protected bit in 802.11 header frame control field.
The chipset seems to do hw decryption but the frame_control
protected bit is still set.

This is necessary for mac80211 not to drop the frame.

Signed-off-by: Erik Stromdahl <erik.stromdahl@gmail.com>
---
 drivers/net/wireless/ath/ath10k/core.c    | 38 ++++++++-----
 drivers/net/wireless/ath/ath10k/htt.h     | 47 +++++++++++++++
 drivers/net/wireless/ath/ath10k/htt_rx.c  | 95 ++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/rx_desc.h | 15 +++++
 4 files changed, 177 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 250e32b..41a1ca6 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1917,10 +1917,12 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 		goto err_wmi_detach;
 	}
 
-	status = ath10k_htt_rx_alloc(&ar->htt);
-	if (status) {
-		ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
-		goto err_htt_tx_detach;
+	if (!ar->is_high_latency) {
+		status = ath10k_htt_rx_alloc(&ar->htt);
+		if (status) {
+			ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
+			goto err_htt_tx_detach;
+		}
 	}
 
 	status = ath10k_hif_start(ar);
@@ -2025,16 +2027,20 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 		goto err_hif_stop;
 	}
 
-	/* If firmware indicates Full Rx Reorder support it must be used in a
-	 * slightly different manner. Let HTT code know.
-	 */
-	ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
-						ar->wmi.svc_map));
+	if (!ar->is_high_latency) {
+		/* If firmware indicates Full Rx Reorder support it must be
+		 * used in a slightly different manner. Let HTT code know.
+		 */
+		ar->htt.rx_ring.in_ord_rx =
+			!!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
+				    ar->wmi.svc_map));
 
-	status = ath10k_htt_rx_ring_refill(ar);
-	if (status) {
-		ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);
-		goto err_hif_stop;
+		status = ath10k_htt_rx_ring_refill(ar);
+		if (status) {
+			ath10k_err(ar, "failed to refill htt rx ring: %d\n",
+				   status);
+			goto err_hif_stop;
+		}
 	}
 
 	if (ar->max_num_vdevs >= 64)
@@ -2063,7 +2069,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 err_hif_stop:
 	ath10k_hif_stop(ar);
 err_htt_rx_detach:
-	ath10k_htt_rx_free(&ar->htt);
+	if (!ar->is_high_latency)
+		ath10k_htt_rx_free(&ar->htt);
 err_htt_tx_detach:
 	ath10k_htt_tx_free(&ar->htt);
 err_wmi_detach:
@@ -2108,7 +2115,8 @@ void ath10k_core_stop(struct ath10k *ar)
 
 	ath10k_hif_stop(ar);
 	ath10k_htt_tx_stop(&ar->htt);
-	ath10k_htt_rx_free(&ar->htt);
+	if (!ar->is_high_latency)
+		ath10k_htt_rx_free(&ar->htt);
 	ath10k_wmi_detach(ar);
 	ar->is_started = false;
 }
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index d40b3a0..a51bf57 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -645,6 +645,15 @@ struct htt_rx_indication {
 	struct htt_rx_indication_mpdu_range mpdu_ranges[0];
 } __packed;
 
+/* High latency version of the RX indication */
+struct htt_rx_indication_hl {
+	struct htt_rx_indication_hdr hdr;
+	struct htt_rx_indication_ppdu ppdu;
+	struct htt_rx_indication_prefix prefix;
+	struct fw_rx_desc_hl fw_desc;
+	struct htt_rx_indication_mpdu_range mpdu_ranges[0];
+} __packed;
+
 static inline struct htt_rx_indication_mpdu_range *
 		htt_rx_ind_get_mpdu_ranges(struct htt_rx_indication *rx_ind)
 {
@@ -657,6 +666,18 @@ static inline struct htt_rx_indication_mpdu_range *
 	return ptr;
 }
 
+static inline struct htt_rx_indication_mpdu_range *
+	htt_rx_ind_get_mpdu_ranges_hl(struct htt_rx_indication_hl *rx_ind)
+{
+	void *ptr = rx_ind;
+
+	ptr += sizeof(rx_ind->hdr)
+	     + sizeof(rx_ind->ppdu)
+	     + sizeof(rx_ind->prefix)
+	     + sizeof(rx_ind->fw_desc);
+	return ptr;
+}
+
 enum htt_rx_flush_mpdu_status {
 	HTT_RX_FLUSH_MPDU_DISCARD = 0,
 	HTT_RX_FLUSH_MPDU_REORDER = 1,
@@ -1527,6 +1548,7 @@ struct htt_resp {
 		struct htt_mgmt_tx_completion mgmt_tx_completion;
 		struct htt_data_tx_completion data_tx_completion;
 		struct htt_rx_indication rx_ind;
+		struct htt_rx_indication_hl rx_ind_hl;
 		struct htt_rx_fragment_indication rx_frag_ind;
 		struct htt_rx_peer_map peer_map;
 		struct htt_rx_peer_unmap peer_unmap;
@@ -1747,6 +1769,31 @@ struct htt_rx_desc {
 	u8 msdu_payload[0];
 };
 
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_MASK           0x00000fff
+#define HTT_RX_DESC_HL_INFO_SEQ_NUM_LSB            0
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_MASK         0x00001000
+#define HTT_RX_DESC_HL_INFO_ENCRYPTED_LSB          12
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_MASK 0x00002000
+#define HTT_RX_DESC_HL_INFO_CHAN_INFO_PRESENT_LSB  13
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_MASK       0x00008000
+#define HTT_RX_DESC_HL_INFO_MCAST_BCAST_LSB        15
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_MASK          0x00010000
+#define HTT_RX_DESC_HL_INFO_FRAGMENT_LSB           16
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_MASK        0x01fe0000
+#define HTT_RX_DESC_HL_INFO_KEY_ID_OCT_LSB         17
+
+struct htt_rx_desc_base_hl {
+	__le32 info; /* HTT_RX_DESC_HL_INFO_ */
+};
+
+struct htt_rx_chan_info {
+	__le16 primary_chan_center_freq_mhz;
+	__le16 contig_chan1_center_freq_mhz;
+	__le16 contig_chan2_center_freq_mhz;
+	u8 phy_mode;
+	u8 reserved;
+} __packed;
+
 #define HTT_RX_DESC_ALIGN 8
 
 #define HTT_MAC_ADDR_LEN 6
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 3d72265..be46044 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1568,8 +1568,92 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
 	return num_msdus;
 }
 
-static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
-				      struct htt_rx_indication *rx)
+static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
+					 struct htt_rx_indication_hl *rx,
+					 struct sk_buff *skb)
+{
+	struct ath10k *ar = htt->ar;
+	struct ath10k_peer *peer;
+	struct htt_rx_indication_mpdu_range *mpdu_ranges;
+	struct fw_rx_desc_hl *fw_desc;
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_rx_status *rx_status;
+	u16 peer_id;
+	u8 rx_desc_len;
+	int num_mpdu_ranges;
+	size_t tot_hdr_len;
+
+	peer_id = __le16_to_cpu(rx->hdr.peer_id);
+
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer)
+		ath10k_warn(ar, "Got RX ind from invalid peer: %u\n", peer_id);
+
+	num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
+			     HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
+	mpdu_ranges = htt_rx_ind_get_mpdu_ranges_hl(rx);
+	fw_desc = &rx->fw_desc;
+	rx_desc_len = fw_desc->len;
+
+	/* I have not yet seen any case where num_mpdu_ranges > 1.
+	 * qcacld does not seem handle that case either, so we introduce the
+	 * same limitiation here as well.
+	 */
+	if (num_mpdu_ranges > 1)
+		ath10k_warn(ar,
+			    "Unsupported number of MPDU ranges: %d, ignoring all but the first\n",
+			    num_mpdu_ranges);
+
+	if (mpdu_ranges->mpdu_range_status !=
+	    HTT_RX_IND_MPDU_STATUS_OK) {
+		ath10k_warn(ar, "MPDU range status: %d\n",
+			    mpdu_ranges->mpdu_range_status);
+		goto err;
+	}
+
+	/* Strip off all headers before the MAC header before delivery to
+	 * mac80211
+	 */
+	tot_hdr_len = sizeof(struct htt_resp_hdr) + sizeof(rx->hdr) +
+		      sizeof(rx->ppdu) + sizeof(rx->prefix) +
+		      sizeof(rx->fw_desc) + sizeof(*mpdu_ranges) + rx_desc_len;
+	skb_pull(skb, tot_hdr_len);
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	rx_status = IEEE80211_SKB_RXCB(skb);
+	rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
+			    rx->ppdu.combined_rssi;
+	rx_status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
+
+	/* Not entirely sure about this, but all frames from the chipset has
+	 * the protected flag set even though they have already been decrypted.
+	 * Unmasking this flag is necessary in order for mac80211 not to drop
+	 * the frame.
+	 * TODO: Verify this is always the case or find out a way to check
+	 * if there has been hw decryption.
+	 */
+	if (ieee80211_has_protected(hdr->frame_control)) {
+		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+		rx_status->flag |= RX_FLAG_DECRYPTED |
+				   RX_FLAG_IV_STRIPPED |
+				   RX_FLAG_MMIC_STRIPPED;
+	}
+
+	ieee80211_rx(ar->hw, skb);
+
+	/* We have delivered the skb to the upper layers (mac80211) so we
+	 * must not free it.
+	 */
+	return false;
+err:
+	/* Tell the caller that it must free the skb since we have not
+	 * consumed it
+	 */
+	return true;
+}
+
+static void ath10k_htt_rx_proc_rx_ind_ll(struct ath10k_htt *htt,
+					 struct htt_rx_indication *rx)
 {
 	struct ath10k *ar = htt->ar;
 	struct htt_rx_indication_mpdu_range *mpdu_ranges;
@@ -2349,7 +2433,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		break;
 	}
 	case HTT_T2H_MSG_TYPE_RX_IND:
-		ath10k_htt_rx_proc_rx_ind(htt, &resp->rx_ind);
+		if (ar->is_high_latency)
+			return ath10k_htt_rx_proc_rx_ind_hl(htt,
+							    &resp->rx_ind_hl,
+							    skb);
+		else
+			ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);
 		break;
 	case HTT_T2H_MSG_TYPE_PEER_MAP: {
 		struct htt_peer_map_event ev = {
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 034e7a5..0e625cf 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -1219,4 +1219,19 @@ struct fw_rx_desc_base {
 	u8 info0;
 } __packed;
 
+#define FW_RX_DESC_FLAGS_FIRST_MSDU (1 << 0)
+#define FW_RX_DESC_FLAGS_LAST_MSDU  (1 << 1)
+#define FW_RX_DESC_C3_FAILED        (1 << 2)
+#define FW_RX_DESC_C4_FAILED        (1 << 3)
+#define FW_RX_DESC_IPV6             (1 << 4)
+#define FW_RX_DESC_TCP              (1 << 5)
+#define FW_RX_DESC_UDP              (1 << 6)
+
+struct fw_rx_desc_hl {
+	u8 info0;
+	u8 version;
+	u8 len;
+	u8 flags;
+} __packed;
+
 #endif /* _RX_DESC_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH 14/40] rt2x00: rt2800lib: add MAC register initialization for RT3883
From: Daniel Golle @ 2017-01-13 21:25 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 7c5061d5328d..cf9a8cfd4fbc 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -5020,6 +5020,12 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 			rt2800_register_write(rt2x00dev, TX_SW_CFG2,
 					      0x00000000);
 		}
+	} else if (rt2x00_rt(rt2x00dev, RT3883)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
+		rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
+		rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
 		   rt2x00_rt(rt2x00dev, RT5392)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
@@ -5053,7 +5059,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
 	rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
-	if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
+	if (rt2x00_rt(rt2x00dev, RT3883)) {
+		drv_data->max_psdu = 3;
+		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 3);
+	} else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
 	    rt2x00_rt(rt2x00dev, RT2883) ||
 	    rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) {
 		drv_data->max_psdu = 2;
@@ -5211,6 +5220,11 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
 	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
 
+	if (rt2x00_rt(rt2x00dev, RT3883)) {
+		rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
+		rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
+	}
+
 	rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
 	rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
 	rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
-- 
2.11.0

^ permalink raw reply related

* [PATCH 12/40] rt2x00: rt2800lib: add channel configuration function for RF3853
From: Daniel Golle @ 2017-01-13 21:24 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
[daniel@makrotopia.org: replaced udelay with usleep_range]
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++
 1 file changed, 208 insertions(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index 15bcad1156d9..eda886648daf 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -2661,6 +2661,211 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
+static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr;
+	u8 bbp;
+	u8 pwr1, pwr2, pwr3;
+
+	const bool txbf_enabled = false; /* TODO */
+
+	/* TODO: add band selection */
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+	else if (rf->channel < 132)
+		rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
+
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
+
+	rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+
+	switch (rt2x00dev->default_ant.tx_chain_num) {
+	case 3:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
+		/* fallthrough */
+	case 2:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
+		/* fallthrough */
+	case 1:
+		rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+		break;
+	}
+
+	switch (rt2x00dev->default_ant.rx_chain_num) {
+	case 3:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
+		/* fallthrough */
+	case 2:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
+		/* fallthrough */
+	case 1:
+		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+		break;
+	}
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	rt2800_adjust_freq_offset(rt2x00dev);
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	if (!conf_is_ht40(conf))
+		rfcsr &= ~(0x06);
+	else
+		rfcsr |= 0x06;
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+
+	if (conf_is_ht40(conf))
+		rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
+
+	/* loopback RF_BS */
+	rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr);
+	if (rf->channel <= 14)
+		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
+	rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
+
+	if (rf->channel <= 14)
+		rfcsr = 0x23;
+	else if (rf->channel < 100)
+		rfcsr = 0x36;
+	else if (rf->channel < 132)
+		rfcsr = 0x32;
+	else
+		rfcsr = 0x30;
+
+	if (txbf_enabled)
+		rfcsr |= 0x40;
+
+	rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
+
+	if (rf->channel <= 14)
+		rfcsr = 0xbb;
+	else if (rf->channel < 100)
+		rfcsr = 0xeb;
+	else if (rf->channel < 132)
+		rfcsr = 0xb3;
+	else
+		rfcsr = 0x9b;
+	rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
+
+	if (rf->channel <= 14)
+		rfcsr = 0x8e;
+	else
+		rfcsr = 0x8a;
+
+	if (txbf_enabled)
+		rfcsr |= 0x20;
+
+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+	rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
+
+	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr);
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
+
+	rt2800_rfcsr_read(rt2x00dev, 52, &rfcsr);
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
+
+	if (rf->channel <= 14) {
+		pwr1 = info->default_power1 & 0x1f;
+		pwr2 = info->default_power2 & 0x1f;
+		pwr3 = info->default_power3 & 0x1f;
+	} else {
+		pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
+			(info->default_power1 & 0x7);
+		pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
+			(info->default_power2 & 0x7);
+		pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
+			(info->default_power3 & 0x7);
+	}
+
+	rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
+	rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
+	rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
+
+	rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
+		   rf->channel, pwr1, pwr2, pwr3);
+
+	bbp = (info->default_power1 >> 5) |
+	      ((info->default_power2 & 0xe0) >> 1);
+	rt2800_bbp_write(rt2x00dev, 109, bbp);
+
+	rt2800_bbp_read(rt2x00dev, 110, &bbp);
+	bbp &= 0x0f;
+	bbp |= (info->default_power3 & 0xe0) >> 1;
+	rt2800_bbp_write(rt2x00dev, 110, bbp);
+
+	rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr);
+	if (rf->channel <= 14)
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
+	else
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
+
+	/* Enable RF tuning */
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+
+	usleep_range(2000, 2500);
+
+	rt2800_bbp_read(rt2x00dev, 49, &bbp);
+	/* clear update flag */
+	rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
+	rt2800_bbp_write(rt2x00dev, 49, bbp);
+
+	/* TODO: add calibration for TxBF */
+}
+
 #define POWER_BOUND		0x27
 #define POWER_BOUND_5G		0x2b
 
@@ -3273,6 +3478,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	case RF3322:
 		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
 		break;
+	case RF3853:
+		rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
+		break;
 	case RF3070:
 	case RF5360:
 	case RF5362:
-- 
2.11.0

^ permalink raw reply related

* [PATCH 13/40] rt2x00: rt2800lib: enable RF3853 support
From: Daniel Golle @ 2017-01-13 21:24 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Stanislaw Gruszka, roman, michel.stempin,
	c.mignanti, evaxige, Kalle Valo, Felix Fietkau, John Crispin,
	Gabor Juhos

From: Gabor Juhos <juhosg@openwrt.org>

Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
---
 drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
index eda886648daf..7c5061d5328d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -7447,6 +7447,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	case RF3290:
 	case RF3320:
 	case RF3322:
+	case RF3853:
 	case RF5360:
 	case RF5362:
 	case RF5370:
-- 
2.11.0

^ permalink raw reply related

* Re: [OpenWrt-Devel] [RFC] [PULL REQUEST] rt2x00 patches from OpenWrt.org
From: Daniel Golle @ 2017-01-13 22:17 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Stanislaw Gruszka, roman, lede-dev, linux-wireless,
	michel.stempin, c.mignanti, openwrt-devel, evaxige, Kalle Valo
In-Reply-To: <20170113161722.GH2332@makrotopia.org>

On Fri, Jan 13, 2017 at 05:17:23PM +0100, Daniel Golle wrote:
> On Fri, Jan 13, 2017 at 04:59:59PM +0100, Johannes Berg wrote:
> > 
> > > The advantage of pull requests is that author information can be
> > > preserved more easily. Running git format-patch results in most
> > > patches
> > > having wrong SMTP sender information due to the assumption that the
> > > patch author is the same person also submitting the patch.
> > > So in practise, this would either require changing the From: (and
> > > thus
> > > Author) to myself or having most mails eaten by anti-spam measures
> > > due
> > > to non-matching SPF which prohibits my SMTP to send mail on behalf of
> > > the original authors of the patches.
> > > 
> > 
> > This is completely untrue. If the first line of the *body* of the email
> > is "From: ..." then this is preserved as the author information by git
> > am, and doing so is also the default in git format-patch/send-email
> > when the author doesn't match the email configuration.
> 
> Thanks for the clarification, I'll then submit the patches via
> git format-patch.

I posted all patches on the mailing list and bundled them up on
patchwork.
https://patchwork.kernel.org/bundle/dangole/rt2x00-from-openwrt/

Cheers


Daniel

^ permalink raw reply

* Re: [PATCH 1/2] mwifiex: pcie: use posted write to wake up firmware
From: Brian Norris @ 2017-01-13 22:49 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo
In-Reply-To: <20170112210232.18554-1-briannorris@chromium.org>

On Thu, Jan 12, 2017 at 01:02:31PM -0800, Brian Norris wrote:
> Depending on system factors (e.g., the PCIe link PM state), the first
> read to wake up the Wifi firmware can take a long time. There is no
> reason to use a (blocking, non-posted) read at this point, so let's just
> use a write instead. Write vs. read doesn't matter functionality-wise --
> it's just a dummy operation.
> 
> This has been shown to decrease the time spent blocking in this function
> on a Rockchip RK3399 SoC.
> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
>  drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++----
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 66226c615be0..435ba879ef29 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -458,7 +458,6 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
>  /* This function wakes up the card by reading fw_status register. */
>  static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
>  {
> -	u32 fw_status;
>  	struct pcie_service_card *card = adapter->card;
>  	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
>  
> @@ -468,10 +467,10 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
>  	if (reg->sleep_cookie)
>  		mwifiex_pcie_dev_wakeup_delay(adapter);
>  
> -	/* Reading fw_status register will wakeup device */
> -	if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
> +	/* Accessing fw_status register will wakeup device */
> +	if (mwifiex_write_reg(adapter, reg->fw_status, 0)) {

As Amit noted to me elsewhere, the firmware only writes this status once
at FW init time to FIRMWARE_READY_PCIE, and we later check it in a few
places. So I noticed that this actually breaks re-probing the adapter
(e.g., 'rmmod mwifiex_pcie; modprobe mwifiex_pcie'); the second time,
we'll fail to find the FIRMWARE_READY_PCIE signature, and so we'll
abort.

I'll resend this patch with s/0/FIRMWARE_READY_PCIE/ instead.

Brian

>  		mwifiex_dbg(adapter, ERROR,
> -			    "Reading fw_status register failed\n");
> +			    "Writing fw_status register failed\n");
>  		return -1;
>  	}
>  
> -- 
> 2.11.0.390.gc69c2f50cf-goog
> 

^ permalink raw reply

* Re: [PATCH 2/2] mwifiex: pcie: don't delay for sleep cookie when not required
From: Brian Norris @ 2017-01-13 22:54 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo
In-Reply-To: <20170112210232.18554-2-briannorris@chromium.org>

On Thu, Jan 12, 2017 at 01:02:32PM -0800, Brian Norris wrote:
> Wifi modules like 8997 don't support the "sleep cookie", and so most of
> the time, we just time out in the mwifiex_delay_for_sleep_cookie()
> function ("max count reached while accessing sleep cookie"). This is a
> waste of time, and we should skip it for modules without the sleep
> cookie flag.
> 
> Additionally, this delay is sometimes counterproductive. For instance,
> when PCIe ASPM is enabled, this extra delay can leave the link idle for
> long enough to re-enter a low-power state even while we are trying to
> wake the module, compounding an additional delay when it comes time to
> read the next register (e.g., the interrupt status). On some systems,
> this is detrimental to overall system latency.
> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
> Tested on Marvell 8997, but would be good to get confirmation from Marvell.

It would still be good to get comment from Marvell here, but elsewhere,
they've told me that this breaks the expected handshake procedure. I'm
still not quite sure how that is true, considering that we time out in
the mwifiex_delay_for_sleep_cookie() all the time anyway (so what's the
point of waiting then?)...

But anyway I think I have discovered a proper root cause [1] that is
causing my latency problems above. I'll post a v2 which replaces the
current patch with something else.

Brian

[1] The short version: re-reading the interrupt status register from the
card after we've sent it to sleep takes a long time. We shouldn't do
that.

>  drivers/net/wireless/marvell/mwifiex/pcie.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 435ba879ef29..11e0673617c7 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -1712,11 +1712,13 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
>  					    "Write register failed\n");
>  				return -1;
>  			}
> -			mwifiex_delay_for_sleep_cookie(adapter,
> -						       MWIFIEX_MAX_DELAY_COUNT);
> -			while (reg->sleep_cookie && (count++ < 10) &&
> -			       mwifiex_pcie_ok_to_access_hw(adapter))
> -				usleep_range(50, 60);
> +			if (reg->sleep_cookie) {
> +				mwifiex_delay_for_sleep_cookie(adapter,
> +							       MWIFIEX_MAX_DELAY_COUNT);
> +				while ((count++ < 10) &&
> +				       mwifiex_pcie_ok_to_access_hw(adapter))
> +					usleep_range(50, 60);
> +			}
>  			mwifiex_pcie_enable_host_int(adapter);
>  			mwifiex_process_sleep_confirm_resp(adapter, skb->data,
>  							   skb->len);
> -- 
> 2.11.0.390.gc69c2f50cf-goog
> 

^ permalink raw reply

* [PATCH v2 1/3] mwifiex: pcie: use posted write to wake up firmware
From: Brian Norris @ 2017-01-13 23:35 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo,
	Dmitry Torokhov, Brian Norris

Depending on system factors (e.g., the PCIe link PM state), the first
read to wake up the Wifi firmware can take a long time. There is no
reason to use a (blocking, non-posted) read at this point, so let's just
use a write instead. Write vs. read doesn't matter functionality-wise --
it's just a dummy operation. But let's make sure to re-write with the
correct "ready" signature, since we check for that in other parts of the
driver.

This has been shown to decrease the time spent blocking in this function
on RK3399.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
v2:
 * write FIRMWARE_READY_PCIE instead of 0
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 66226c615be0..3f4cda2d3b61 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -458,7 +458,6 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
 /* This function wakes up the card by reading fw_status register. */
 static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
-	u32 fw_status;
 	struct pcie_service_card *card = adapter->card;
 	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -468,10 +467,10 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 	if (reg->sleep_cookie)
 		mwifiex_pcie_dev_wakeup_delay(adapter);
 
-	/* Reading fw_status register will wakeup device */
-	if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) {
+	/* Accessing fw_status register will wakeup device */
+	if (mwifiex_write_reg(adapter, reg->fw_status, FIRMWARE_READY_PCIE)) {
 		mwifiex_dbg(adapter, ERROR,
-			    "Reading fw_status register failed\n");
+			    "Writing fw_status register failed\n");
 		return -1;
 	}
 
-- 
2.11.0.483.g087da7b7c-goog

^ permalink raw reply related

* [PATCH v2 2/3] mwifiex: pcie: don't loop/retry interrupt status checks
From: Brian Norris @ 2017-01-13 23:35 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo,
	Dmitry Torokhov, Brian Norris
In-Reply-To: <20170113233538.36196-1-briannorris@chromium.org>

The following sequence occurs when using IEEE power-save on 8997:
(a) driver sees SLEEP event
(b) driver issues SLEEP CONFIRM
(c) driver recevies CMD interrupt; within the interrupt processing loop,
    we do (d) and (e):
(d) wait for FW sleep cookie (and often time out; it takes a while), FW
    is putting card into low power mode
(e) re-check PCIE_HOST_INT_STATUS register; quit loop with 0 value

But at (e), no one actually signaled an interrupt (i.e., we didn't check
adapter->int_status). And what's more, because the card is going to
sleep, this register read appears to take a very long time in some cases
-- 3 milliseconds in my case!

Now, I propose that (e) is completely unnecessary. If there were any
additional interrupts signaled after the start of this loop, then the
interrupt handler would have set adapter->int_status to non-zero and
queued more work for the main loop -- and we'd catch it on the next
iteration of the main loop.

So this patch drops all the looping/re-reading of PCIE_HOST_INT_STATUS,
which avoids the problematic (and slow) register read in step (e).

Incidentally, this is a very similar issue to the one fixed in commit
ec815dd2a5f1 ("mwifiex: prevent register accesses after host is
sleeping"), except that the register read is just very slow instead of
fatal in this case.

Tested on 8997 in both MSI and (though not technically supported at the
moment) MSI-X mode.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
v2:
 * new in v2, replacing an attempt to mess with step (d) above
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 102 +++++++++-------------------
 1 file changed, 32 insertions(+), 70 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 3f4cda2d3b61..194e0e04c3b1 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2332,79 +2332,41 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
 			}
 		}
 	}
-	while (pcie_ireg & HOST_INTR_MASK) {
-		if (pcie_ireg & HOST_INTR_DNLD_DONE) {
-			pcie_ireg &= ~HOST_INTR_DNLD_DONE;
-			mwifiex_dbg(adapter, INTR,
-				    "info: TX DNLD Done\n");
-			ret = mwifiex_pcie_send_data_complete(adapter);
-			if (ret)
-				return ret;
-		}
-		if (pcie_ireg & HOST_INTR_UPLD_RDY) {
-			pcie_ireg &= ~HOST_INTR_UPLD_RDY;
-			mwifiex_dbg(adapter, INTR,
-				    "info: Rx DATA\n");
-			ret = mwifiex_pcie_process_recv_data(adapter);
-			if (ret)
-				return ret;
-		}
-		if (pcie_ireg & HOST_INTR_EVENT_RDY) {
-			pcie_ireg &= ~HOST_INTR_EVENT_RDY;
-			mwifiex_dbg(adapter, INTR,
-				    "info: Rx EVENT\n");
-			ret = mwifiex_pcie_process_event_ready(adapter);
-			if (ret)
-				return ret;
-		}
-
-		if (pcie_ireg & HOST_INTR_CMD_DONE) {
-			pcie_ireg &= ~HOST_INTR_CMD_DONE;
-			if (adapter->cmd_sent) {
-				mwifiex_dbg(adapter, INTR,
-					    "info: CMD sent Interrupt\n");
-				adapter->cmd_sent = false;
-			}
-			/* Handle command response */
-			ret = mwifiex_pcie_process_cmd_complete(adapter);
-			if (ret)
-				return ret;
-			if (adapter->hs_activated)
-				return ret;
-		}
-
-		if (card->msi_enable) {
-			spin_lock_irqsave(&adapter->int_lock, flags);
-			adapter->int_status = 0;
-			spin_unlock_irqrestore(&adapter->int_lock, flags);
-		}
-
-		if (mwifiex_pcie_ok_to_access_hw(adapter)) {
-			if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
-					     &pcie_ireg)) {
-				mwifiex_dbg(adapter, ERROR,
-					    "Read register failed\n");
-				return -1;
-			}
 
-			if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
-				if (mwifiex_write_reg(adapter,
-						      PCIE_HOST_INT_STATUS,
-						      ~pcie_ireg)) {
-					mwifiex_dbg(adapter, ERROR,
-						    "Write register failed\n");
-					return -1;
-				}
-			}
-
-		}
-		if (!card->msi_enable) {
-			spin_lock_irqsave(&adapter->int_lock, flags);
-			pcie_ireg |= adapter->int_status;
-			adapter->int_status = 0;
-			spin_unlock_irqrestore(&adapter->int_lock, flags);
+	if (pcie_ireg & HOST_INTR_DNLD_DONE) {
+		pcie_ireg &= ~HOST_INTR_DNLD_DONE;
+		mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n");
+		ret = mwifiex_pcie_send_data_complete(adapter);
+		if (ret)
+			return ret;
+	}
+	if (pcie_ireg & HOST_INTR_UPLD_RDY) {
+		pcie_ireg &= ~HOST_INTR_UPLD_RDY;
+		mwifiex_dbg(adapter, INTR, "info: Rx DATA\n");
+		ret = mwifiex_pcie_process_recv_data(adapter);
+		if (ret)
+			return ret;
+	}
+	if (pcie_ireg & HOST_INTR_EVENT_RDY) {
+		pcie_ireg &= ~HOST_INTR_EVENT_RDY;
+		mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n");
+		ret = mwifiex_pcie_process_event_ready(adapter);
+		if (ret)
+			return ret;
+	}
+	if (pcie_ireg & HOST_INTR_CMD_DONE) {
+		pcie_ireg &= ~HOST_INTR_CMD_DONE;
+		if (adapter->cmd_sent) {
+			mwifiex_dbg(adapter, INTR,
+				    "info: CMD sent Interrupt\n");
+			adapter->cmd_sent = false;
 		}
+		/* Handle command response */
+		ret = mwifiex_pcie_process_cmd_complete(adapter);
+		if (ret)
+			return ret;
 	}
+
 	mwifiex_dbg(adapter, INTR,
 		    "info: cmd_sent=%d data_sent=%d\n",
 		    adapter->cmd_sent, adapter->data_sent);
-- 
2.11.0.483.g087da7b7c-goog

^ permalink raw reply related

* [PATCH v2 3/3] mwifiex: pcie: read FROMDEVICE DMA-able memory with READ_ONCE()
From: Brian Norris @ 2017-01-13 23:35 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo,
	Dmitry Torokhov, Brian Norris
In-Reply-To: <20170113233538.36196-1-briannorris@chromium.org>

In mwifiex_delay_for_sleep_cookie(), we're looping and waiting for the
PCIe endpoint to write a magic value back to memory, to signal that it
has finished going to sleep. We're not letting the compiler know that
this might change underneath our feet though. Let's do that, for good
hygiene.

I'm not aware of this fixing any concrete problems. I also give no
guarantee that this loop is actually correct in any other way, but at
least this looks like an improvement to me.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
v2: new in v2
---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 194e0e04c3b1..c2511f212502 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -440,7 +440,7 @@ static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter,
 
 	for (count = 0; count < max_delay_loop_cnt; count++) {
 		buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN;
-		sleep_cookie = *(u32 *)buffer;
+		sleep_cookie = READ_ONCE(*(u32 *)buffer);
 
 		if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) {
 			mwifiex_dbg(adapter, INFO,
-- 
2.11.0.483.g087da7b7c-goog

^ permalink raw reply related

* [PATCH] mwifiex: don't complain about 'unknown event id: 0x63'
From: Brian Norris @ 2017-01-14  2:16 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam
  Cc: linux-kernel, Kalle Valo, linux-wireless, Cathy Luo, Brian Norris

Marvell folks tell me this is a debugging event that the driver doesn't
need to handle, but on 8997 w/ firmware 16.68.1.p97, I see several of
these sorts of messages at (for instance) boot time:

[   13.825848] mwifiex_pcie 0000:01:00.0: event: unknown event id: 0x63
[   14.838561] mwifiex_pcie 0000:01:00.0: event: unknown event id: 0x63
[   14.850397] mwifiex_pcie 0000:01:00.0: event: unknown event id: 0x63
[   32.529923] mwifiex_pcie 0000:01:00.0: event: unknown event id: 0x63

Let's handle this "event" with a much lower verbosity.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/net/wireless/marvell/mwifiex/fw.h        | 1 +
 drivers/net/wireless/marvell/mwifiex/sta_event.c | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 55db158fd156..cb6a1a81d44e 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -550,6 +550,7 @@ enum mwifiex_channel_flags {
 #define EVENT_TX_DATA_PAUSE             0x00000055
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_RXBA_SYNC                 0x00000059
+#define EVENT_UNKNOWN_DEBUG             0x00000063
 #define EVENT_BG_SCAN_STOPPED           0x00000065
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
 #define EVENT_MULTI_CHAN_INFO           0x0000006a
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c
index 9df0c4dc06ed..96503d3d053f 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -1009,6 +1009,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 					    adapter->event_skb->len -
 					    sizeof(eventcause));
 		break;
+	/* Debugging event; not used, but let's not print an ERROR for it. */
+	case EVENT_UNKNOWN_DEBUG:
+		mwifiex_dbg(adapter, EVENT, "event: debug\n");
+		break;
 	default:
 		mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
 			    eventcause);
-- 
2.11.0.483.g087da7b7c-goog

^ permalink raw reply related

* Re: Searching new home for ath[59]k-devel mailing lists
From: Michael Renzmann @ 2017-01-14  6:48 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, ath5k-devel, ath9k-devel
In-Reply-To: <87y3yfi78t.fsf@purkki.adurom.net>

Hi Kalle.

Thanks for your response.

Kalle Valo wrote:
> So feel free to close both of the lists and thanks for the heads up.

Ok. I will send a shutdown notice to both lists during the next few days,
then unsubscribe all subscribers, and close the lists for new
subscriptions. I intend to keep the mailing list archives online, for
reference purpose.

> Are you planning to update the MAINTAINERS file or should I?

It would be great if you could take care of that.

Someone should also update the "Mailing list" section of [1] accordingly.
I guess one needs to have a valid user account for that to do, and I don't
have one atm.

[1] https://wireless.wiki.kernel.org/en/users/Drivers/ath9k

Bye, Mike

^ permalink raw reply

* Re: linux driver bcm4311 failure
From: Arend Van Spriel @ 2017-01-14 11:53 UTC (permalink / raw)
  To: message, brcm80211-dev-list.pdl, arch-general, linux-wireless
In-Reply-To: <851aa49795494ec407c4783f8579437e@openmailbox.org>

On 14-1-2017 11:15, message wrote:
> On 2017-01-02 20:04, Arend van Spriel wrote:
>> On 02-01-17 15:33, message wrote:
>>> On 2016-12-30 19:46, message wrote:
>>>> On 2016-09-17 08:11, message wrote:
>>>>> On 2016-09-09 07:57, Arend Van Spriel wrote:
>>>>>>
>>>>>> The device is claimed by b43-pci-bridge so I would suggest:
>>>>>>
>>>>>> blacklist b43-pci-bridge
>>>>>>
>>>
>>> The wifi card indicator now appears to start after computer switch on
>>> (twice in a row now!)
>>>
>>> Neither networkmanager or wicd are accepting the password.
>>>
>>> Even:
>>>
>>> wicd-cli --wireless -c [wifihotspotname]
>>> done!
>>>
>>> is false and internet access not found.
>>>
>>> wpa_supplicant continues to report 'conn_failed' error.
>>>
>>> Connection to same network is successful using debian on chromebook
>>> (crouton)
>>
>> I am confused by all your messages. In the previous one you did a
>> 'modprobe b43'. So what driver do you intend to use here. b43 is not a
>> driver maintained by broadcom. You should ask for help on the b43
>> mailing list [1] if you want to use that driver.
>>
>> Regards,
>> Arend
>>
>> [1] http://lists.infradead.org/mailman/listinfo/b43-dev
> 
> After system upgrade, wifi card fails to be recognised.
> 
> For the benefit of other users: save your time and avoid broadcom
> products; they are terrible.

Why sending these types of messages hiding in anonymity without
responding to any of the questions in my email responses. Again what
driver are you using. If it is b43 you want you should not blacklist
b43-pci-bridge. Whether or not b43 supports your device can be found
here [2]. Supposedly it is. If not you might try your luck at the b43
mailing list I gave you in earlier email.

Regards,
Arend

[2] https://wireless.wiki.kernel.org/en/users/drivers/b43#list_of_hardware

^ permalink raw reply

* Re: [RFC] [PULL REQUEST] rt2x00 patches from OpenWrt.org
From: Kalle Valo @ 2017-01-14 16:48 UTC (permalink / raw)
  To: Stanislaw Gruszka
  Cc: Daniel Golle, linux-wireless, lede-dev, openwrt-devel, john, nbd,
	roman, evaxige, c.mignanti, michel.stempin, vasilugin,
	Helmut Schaa
In-Reply-To: <20170113141554.GA8018@redhat.com>

Stanislaw Gruszka <sgruszka@redhat.com> writes:

> Hi
>
> On Fri, Jan 13, 2017 at 04:50:32AM +0100, Daniel Golle wrote:
>> Please review and comment, so we can get those patches merged!
>
> As already pointed by Kalle posting patches to mailing list is better
> way for review. Posing patches is easy with git-format-patch and
> git-send-email. Ideally patch series should not be long, let say no more
> than 30 patches - I suggest to split this into two series: second one
> for RT3853 support and first one for other patches.

Even 30 patches in a set is quite a lot. I think the pain point is
somewhere about 10-12 patches, anything longer than that and most people
lost interest looking at the patches in detail.

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH 04/40] rt2x00: rt2800lib: fix beacon generation on RT3593
From: Kalle Valo @ 2017-01-14 17:00 UTC (permalink / raw)
  To: Daniel Golle
  Cc: linux-wireless, Johannes Berg, Stanislaw Gruszka, roman,
	michel.stempin, c.mignanti, evaxige, Felix Fietkau, John Crispin,
	Gabor Juhos
In-Reply-To: <20170113212027.GA3372@makrotopia.org>

Daniel Golle <daniel@makrotopia.org> writes:

> From: Gabor Juhos <juhosg@openwrt.org>
>
> On the RT3593 chipset, the beacon registers are located
> in the high 8KB part of the shared memory.
>
> The high part of the shared memory is only accessible
> if it is explicitly selected. Add a helper function
> in order to be able to control the SHR_MSEL bit in
> the PBF_SYS_CTRL register. Also add a few more helper
> functions and use those to select the correct part of
> the shared memory before and after accessing the beacon
> registers.
>
> The base addresses of the beacon registers are also
> different from the actually used values, so fix the
> 'rt2800_hw_beacon_base' function to return the correct
> values.
>
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>

Daniel, as you are submitting these patches you should add your
Signed-off-by after the author's line. Documentation/SubmittingPatches
contains more info about that and what Signed-off-by means. And also
take a look at how Luca does it:

http://www.spinics.net/lists/linux-wireless/msg158064.html

-- 
Kalle Valo

^ permalink raw reply

* Re: pull-request: mac80211-next 2017-01-13
From: David Miller @ 2017-01-14 17:04 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20170113102933.8246-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Fri, 13 Jan 2017 11:29:32 +0100

> This is my first pull request for net-next, and it seems a bit
> bigger than the past few releases. Detailed information below,
> as usual.
> 
> Please pull and let me know if there's any problem.

Pulled, thanks Johannes.

^ permalink raw reply

* Re: [PATCH] ath10k: Search SMBIOS for OEM board file extension
From: kbuild test robot @ 2017-01-14 18:09 UTC (permalink / raw)
  To: Waldemar Rymarkiewicz
  Cc: kbuild-all, kvalo, ath10k, bartosz.markowski, rwchang, alanliu,
	linux-wireless, Waldemar Rymarkiewicz
In-Reply-To: <20170113111022.5570-1-ext.waldemar.rymarkiewicz@tieto.com>

[-- Attachment #1: Type: text/plain, Size: 2182 bytes --]

Hi Waldemar,

[auto build test WARNING on ath6kl/ath-next]
[also build test WARNING on v4.10-rc3 next-20170113]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Waldemar-Rymarkiewicz/ath10k-Search-SMBIOS-for-OEM-board-file-extension/20170115-005232
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git ath-next
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=xtensa 

All warnings (new ones prefixed by >>):

   drivers/net/wireless/ath/ath10k/core.c: In function 'ath10k_core_check_bdfext':
>> drivers/net/wireless/ath/ath10k/core.c:754:2: warning: ignoring return value of 'strscpy', declared with attribute warn_unused_result [-Wunused-result]
     strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
     ^

vim +/strscpy +754 drivers/net/wireless/ath/ath10k/core.c

   738	
   739		if (memcmp(bdf_ext, magic, strlen(magic)) != 0) {
   740			ath10k_dbg(ar, ATH10K_DBG_BOOT,
   741				   "bdf variant magic does not match.\n");
   742			return;
   743		}
   744	
   745		for (i = 0; i < strlen(bdf_ext); i++) {
   746			if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) {
   747				ath10k_dbg(ar, ATH10K_DBG_BOOT,
   748					   "bdf variant name contains non ascii chars.\n");
   749				return;
   750			}
   751		}
   752	
   753		/* Copy extension name without magic suffix */
 > 754		strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
   755			sizeof(ar->id.bdf_ext));
   756	
   757		ath10k_dbg(ar, ATH10K_DBG_BOOT,
   758			   "found and validated bdf variant smbios_type 0x%x bdf %s\n",
   759			   ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext);
   760	}
   761	
   762	static int ath10k_core_check_smbios(struct ath10k *ar)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 48158 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: kbuild test robot @ 2017-01-14 21:37 UTC (permalink / raw)
  To: Matt Ranostay
  Cc: kbuild-all, linux-wireless, linux-kernel, linux-mmc, devicetree,
	tony, Matt Ranostay, Ulf Hansson
In-Reply-To: <20170113052218.10534-3-matt@ranostay.consulting>

[-- Attachment #1: Type: text/plain, Size: 895 bytes --]

Hi Matt,

[auto build test ERROR on linus/master]
[also build test ERROR on v4.10-rc3 next-20170113]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Matt-Ranostay/mmc-pwrseq-add-support-for-Marvell-SD8787-chip/20170115-030459
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

>> make[4]: *** No rule to make target 'drivers/mmc/core/pwrseq_sd8787.c', needed by 'drivers/mmc/core/pwrseq_sd8787.o'.
   make[4]: Target '__build' not remade because of errors.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 57927 bytes --]

^ permalink raw reply

* support for Ampak AP6255 (bcm43455c0 with SDIO device ID 0xa9bf)
From: Martin Blumenstingl @ 2017-01-14 23:18 UTC (permalink / raw)
  To: brcm80211-dev-list.pdl; +Cc: arend.vanspriel, hante.meuleman, linux-wireless

[-- Attachment #1: Type: text/plain, Size: 2343 bytes --]

Hello,

I recently got a "Khadas VIM Pro" (see [0] for more information)
The "Pro" version comes with an AP6255 wifi chipset.
Looking at the vendor firmware this seems to be a bcm43455 device: [1]

To my surprise brcmfmac from a mainline 4.10-rc3 kernel did not pick
this device up.
So I started investigating:
$ grep "" /sys/class/mmc_host/mmc2/mmc2\:0001/mmc2\:0001\:*/{class,device,vendor}
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/class:0x00
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/class:0x00
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/class:0x02
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/device:0xa9bf
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:1/vendor:0x02d0
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/vendor:0x02d0
/sys/class/mmc_host/mmc2/mmc2:0001/mmc2:0001:3/vendor:0x02d0

I then went ahead and added the device ID to
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c (sample
patch attached)
as a result of that the device is now being detected.
it boots fine with the firmware found in linux-firmware: [2] (plus the
nvram.txt from the vendor repo [1] renamed to brcmfmac43455-sdio.txt)

$ cat /sys/kernel/debug/brcmfmac/mmc2\:0001\:1/revinfo
vendorid: 0x14e4
deviceid: 0x43ab
radiorev: 0.88.3.11
chipnum: 17221 (4345)
chiprev: 6
chippkg: 2
corerev: 54
boardid: 0x06e4
boardvendor: 0x14e4
boardrev: P304
driverrev: 7.45.18
ucoderev: 0
bus: 0
phytype: 11
phyrev: 20
anarev: 0
nvramrev: 00079ac5

downloading a random 100MB file from the internet using curl confirms this.
There are no hangs, connection drops, other devices are also working fine.

the problem I'm facing is very simply (but unfortunately a very common
development problem): naming things (the SDIO_DEVICE_ID_BROADCOM_TODO
constant)!
there's already a definition for SDIO_DEVICE_ID_BROADCOM_4345 with
value 0x4345, does that mean 0xa9bf should be
SDIO_DEVICE_ID_BROADCOM_43455?


Regards,
Martin


[0] http://khadas.com/vim/
[1] https://github.com/khadas/android_hardware_amlogic_wifi/tree/b6709758755568e4a0ff6e80993be0fc64c77fb9/bcm_ampak/config/6255
[2] https://git.kernel.org/cgit/linux/kernel/git/firmware/linux-firmware.git/commit/brcm/brcmfmac43455-sdio.bin?id=b9a38d041d38ac6cf47274e9933f8083e12fc601

[-- Attachment #2: brmcfmac-sdio-0xa9bf.patch --]
[-- Type: text/x-patch, Size: 638 bytes --]

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 72139b579b18..7206bb1f9908 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -1106,6 +1106,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
 	BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
+	BRCMF_SDIO_DEVICE(0xa9bf),
 	{ /* end: all zeroes */ }
 };
 MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);


^ permalink raw reply related

* Re: [PATCH 14/40] rt2x00: rt2800lib: add MAC register initialization for RT3883
From: kbuild test robot @ 2017-01-15  6:49 UTC (permalink / raw)
  To: Daniel Golle
  Cc: kbuild-all, linux-wireless, Johannes Berg, Stanislaw Gruszka,
	roman, michel.stempin, c.mignanti, evaxige, Kalle Valo,
	Felix Fietkau, John Crispin, Gabor Juhos
In-Reply-To: <20170113212510.GA3447@makrotopia.org>

[-- Attachment #1: Type: text/plain, Size: 14398 bytes --]

Hi Gabor,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on next-20170113]
[cannot apply to v4.10-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Daniel-Golle/rt2x00-patches-form-OpenWrt-org/20170115-102250
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: x86_64-allyesdebian (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

Note: the linux-review/Daniel-Golle/rt2x00-patches-form-OpenWrt-org/20170115-102250 HEAD 849367246e2b54e086e272ee2bd32b9983bc30fb builds fine.
      It only hurts bisectibility.

All errors (new ones prefixed by >>):

   drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_config_channel_rf3853':
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c:2734:2: error: implicit declaration of function 'rt2800_adjust_freq_offset' [-Werror=implicit-function-declaration]
     rt2800_adjust_freq_offset(rt2x00dev);
     ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c: In function 'rt2800_init_registers':
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5027:36: error: 'TX_TXBF_CFG_0' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
                                       ^~~~~~~~~~~~~
   drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5027:36: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5028:36: error: 'TX_TXBF_CFG_3' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
                                       ^~~~~~~~~~~~~
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5224:36: error: 'TX_FBK_CFG_3S_0' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
                                       ^~~~~~~~~~~~~~~
>> drivers/net/wireless/ralink/rt2x00/rt2800lib.c:5225:36: error: 'TX_FBK_CFG_3S_1' undeclared (first use in this function)
      rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
                                       ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/TX_TXBF_CFG_0 +5027 drivers/net/wireless/ralink/rt2x00/rt2800lib.c

  5021						      0x00000000);
  5022			}
  5023		} else if (rt2x00_rt(rt2x00dev, RT3883)) {
  5024			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
  5025			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
  5026			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
> 5027			rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
> 5028			rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
  5029		} else if (rt2x00_rt(rt2x00dev, RT5390) ||
  5030			   rt2x00_rt(rt2x00dev, RT5392)) {
  5031			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
  5032			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
  5033			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
  5034		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
  5035			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
  5036			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
  5037			rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
  5038		} else {
  5039			rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
  5040			rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
  5041		}
  5042	
  5043		rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
  5044		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
  5045		rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
  5046		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
  5047		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
  5048		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
  5049		rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
  5050		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
  5051		rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
  5052		rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
  5053	
  5054		rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
  5055		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
  5056		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32);
  5057		rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
  5058		rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
  5059	
  5060		rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
  5061		rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
  5062		if (rt2x00_rt(rt2x00dev, RT3883)) {
  5063			drv_data->max_psdu = 3;
  5064			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 3);
  5065		} else if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) ||
  5066		    rt2x00_rt(rt2x00dev, RT2883) ||
  5067		    rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) {
  5068			drv_data->max_psdu = 2;
  5069			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
  5070		} else {
  5071			drv_data->max_psdu = 1;
  5072			rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
  5073		}
  5074		rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 10);
  5075		rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 10);
  5076		rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
  5077	
  5078		rt2800_register_read(rt2x00dev, LED_CFG, &reg);
  5079		rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, 70);
  5080		rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, 30);
  5081		rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
  5082		rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
  5083		rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 3);
  5084		rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
  5085		rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
  5086		rt2800_register_write(rt2x00dev, LED_CFG, reg);
  5087	
  5088		rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
  5089	
  5090		rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
  5091		rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT, 15);
  5092		rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT, 31);
  5093		rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
  5094		rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
  5095		rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
  5096		rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
  5097		rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
  5098	
  5099		rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
  5100		rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
  5101		rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY, 1);
  5102		rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 1);
  5103		rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
  5104		rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE, 0);
  5105		rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
  5106		rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
  5107		rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
  5108	
  5109		rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
  5110		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
  5111		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
  5112		rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5113		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
  5114		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5115		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5116		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5117		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5118		rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5119		rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, 1);
  5120		rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
  5121	
  5122		rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
  5123		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
  5124		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
  5125		rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5126		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
  5127		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5128		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5129		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5130		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5131		rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5132		rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, 1);
  5133		rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
  5134	
  5135		rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
  5136		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
  5137		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 1);
  5138		rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5139		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5140		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5141		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5142		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5143		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5144		rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5145		rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, 0);
  5146		rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
  5147	
  5148		rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
  5149		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
  5150		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 1);
  5151		rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5152		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5153		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5154		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5155		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
  5156		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5157		rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
  5158		rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, 0);
  5159		rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
  5160	
  5161		rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
  5162		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
  5163		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 1);
  5164		rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5165		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5166		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5167		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5168		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
  5169		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5170		rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
  5171		rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, 0);
  5172		rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
  5173	
  5174		rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
  5175		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
  5176		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 1);
  5177		rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
  5178		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 0);
  5179		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
  5180		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
  5181		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
  5182		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
  5183		rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
  5184		rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, 0);
  5185		rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
  5186	
  5187		if (rt2x00_is_usb(rt2x00dev)) {
  5188			rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
  5189	
  5190			rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
  5191			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
  5192			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
  5193			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
  5194			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
  5195			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
  5196			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
  5197			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
  5198			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
  5199			rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
  5200			rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
  5201		}
  5202	
  5203		/*
  5204		 * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
  5205		 * although it is reserved.
  5206		 */
  5207		rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
  5208		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
  5209		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
  5210		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
  5211		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
  5212		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
  5213		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
  5214		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
  5215		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
  5216		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
  5217		rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
  5218		rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
  5219	
  5220		reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
  5221		rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
  5222	
  5223		if (rt2x00_rt(rt2x00dev, RT3883)) {
> 5224			rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
> 5225			rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
  5226		}
  5227	
  5228		rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 38065 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Matt Ranostay @ 2017-01-15 21:41 UTC (permalink / raw)
  To: Shawn Lin
  Cc: linux-wireless, Linux Kernel, linux-mmc, devicetree,
	Tony Lindgren, Ulf Hansson
In-Reply-To: <cd669d08-0db4-57e4-478b-2b200ccef6f1@rock-chips.com>

On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin@rock-chips.com> wrote:
> On 2017/1/13 13:29, Matt Ranostay wrote:
>>
>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>> This can be abstracted to other chipsets if needed in the future.
>>
>> Cc: Tony Lindgren <tony@atomide.com>
>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>> ---
>>  drivers/mmc/core/Kconfig         |  10 ++++
>>  drivers/mmc/core/Makefile        |   1 +
>>  drivers/mmc/core/pwrseq_sd8787.c | 117
>> +++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 128 insertions(+)
>>  create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>
>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>> --- a/drivers/mmc/core/Kconfig
>> +++ b/drivers/mmc/core/Kconfig
>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>           This driver can also be built as a module. If so, the module
>>           will be called pwrseq_emmc.
>>
>> +config PWRSEQ_SD8787
>> +       tristate "HW reset support for SD8787 BT + Wifi module"
>> +       depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>> +       help
>> +         This selects hardware reset support for the SD8787 BT + Wifi
>> +         module. By default this option is set to n.
>> +
>> +         This driver can also be built as a module. If so, the module
>> +         will be called pwrseq_sd8787.
>> +
>
>
> I don't like this way, as we have a chance to list lots
> configure options here. wifi A,B,C,D...Z, all of them need a
> new section here if needed?
>
> Instead, could you just extent pwrseq_simple.c and add you
> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?

You mean all the chipset pwrseqs linked into the pwrseq-simple module?

Ulf your thoughts on this?

>
>
>
>>  config PWRSEQ_SIMPLE
>>         tristate "Simple HW reset support for MMC"
>>         default y
>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>> index b2a257dc644f..0f81464fa824 100644
>> --- a/drivers/mmc/core/Makefile
>> +++ b/drivers/mmc/core/Makefile
>> @@ -10,6 +10,7 @@ mmc_core-y                    := core.o bus.o host.o \
>>                                    quirks.o slot-gpio.o
>>  mmc_core-$(CONFIG_OF)          += pwrseq.o
>>  obj-$(CONFIG_PWRSEQ_SIMPLE)    += pwrseq_simple.o
>> +obj-$(CONFIG_PWRSEQ_SD8787)    += pwrseq_sd8787.o
>>  obj-$(CONFIG_PWRSEQ_EMMC)      += pwrseq_emmc.o
>>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>> diff --git a/drivers/mmc/core/pwrseq_sd8787.c
>> b/drivers/mmc/core/pwrseq_sd8787.c
>> new file mode 100644
>> index 000000000000..f4080fe6439e
>> --- /dev/null
>> +++ b/drivers/mmc/core/pwrseq_sd8787.c
>> @@ -0,0 +1,117 @@
>> +/*
>> + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi
>> chip
>> + *
>> + * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
>> + *
>> + * Based on the original work pwrseq_simple.c
>> + *  Copyright (C) 2014 Linaro Ltd
>> + *  Author: Ulf Hansson <ulf.hansson@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/gpio/consumer.h>
>> +
>> +#include <linux/mmc/host.h>
>> +
>> +#include "pwrseq.h"
>> +
>> +struct mmc_pwrseq_sd8787 {
>> +       struct mmc_pwrseq pwrseq;
>> +       struct gpio_desc *reset_gpio;
>> +       struct gpio_desc *pwrdn_gpio;
>> +};
>> +
>> +#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787,
>> pwrseq)
>> +
>> +static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>> +
>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
>> +
>> +       msleep(300);
>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
>> +}
>> +
>> +static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>> +
>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
>> +}
>> +
>> +static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
>> +       .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
>> +       .power_off = mmc_pwrseq_sd8787_power_off,
>> +};
>> +
>> +static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
>> +       { .compatible = "mmc-pwrseq-sd8787",},
>> +       {/* sentinel */},
>> +};
>> +MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
>> +
>> +static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq;
>> +       struct device *dev = &pdev->dev;
>> +
>> +       pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
>> +       if (!pwrseq)
>> +               return -ENOMEM;
>> +
>> +       pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "pwrdn", GPIOD_OUT_LOW);
>> +       if (IS_ERR(pwrseq->pwrdn_gpio))
>> +               return PTR_ERR(pwrseq->pwrdn_gpio);
>> +
>> +       pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
>> +       if (IS_ERR(pwrseq->reset_gpio))
>> +               return PTR_ERR(pwrseq->reset_gpio);
>> +
>> +       pwrseq->pwrseq.dev = dev;
>> +       pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
>> +       pwrseq->pwrseq.owner = THIS_MODULE;
>> +       platform_set_drvdata(pdev, pwrseq);
>> +
>> +       return mmc_pwrseq_register(&pwrseq->pwrseq);
>> +}
>> +
>> +static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
>> +{
>> +       struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
>> +
>> +       mmc_pwrseq_unregister(&pwrseq->pwrseq);
>> +
>> +       return 0;
>> +}
>> +
>> +static struct platform_driver mmc_pwrseq_sd8787_driver = {
>> +       .probe = mmc_pwrseq_sd8787_probe,
>> +       .remove = mmc_pwrseq_sd8787_remove,
>> +       .driver = {
>> +               .name = "pwrseq_sd8787",
>> +               .of_match_table = mmc_pwrseq_sd8787_of_match,
>> +       },
>> +};
>> +
>> +module_platform_driver(mmc_pwrseq_sd8787_driver);
>> +MODULE_LICENSE("GPL v2");
>>
>
>
> --
> Best Regards
> Shawn Lin
>

^ permalink raw reply

* Re: [PATCH v2 2/3] mwifiex: pcie: don't loop/retry interrupt status checks
From: Dmitry Torokhov @ 2017-01-16  0:54 UTC (permalink / raw)
  To: Brian Norris
  Cc: Amitkumar Karwar, Nishant Sarmukadam, linux-kernel, Kalle Valo,
	linux-wireless, Cathy Luo
In-Reply-To: <20170113233538.36196-2-briannorris@chromium.org>

On Fri, Jan 13, 2017 at 03:35:37PM -0800, Brian Norris wrote:
> The following sequence occurs when using IEEE power-save on 8997:
> (a) driver sees SLEEP event
> (b) driver issues SLEEP CONFIRM
> (c) driver recevies CMD interrupt; within the interrupt processing loop,
>     we do (d) and (e):
> (d) wait for FW sleep cookie (and often time out; it takes a while), FW
>     is putting card into low power mode
> (e) re-check PCIE_HOST_INT_STATUS register; quit loop with 0 value
> 
> But at (e), no one actually signaled an interrupt (i.e., we didn't check
> adapter->int_status). And what's more, because the card is going to
> sleep, this register read appears to take a very long time in some cases
> -- 3 milliseconds in my case!
> 
> Now, I propose that (e) is completely unnecessary. If there were any
> additional interrupts signaled after the start of this loop, then the
> interrupt handler would have set adapter->int_status to non-zero and
> queued more work for the main loop -- and we'd catch it on the next
> iteration of the main loop.
> 
> So this patch drops all the looping/re-reading of PCIE_HOST_INT_STATUS,
> which avoids the problematic (and slow) register read in step (e).
> 
> Incidentally, this is a very similar issue to the one fixed in commit
> ec815dd2a5f1 ("mwifiex: prevent register accesses after host is
> sleeping"), except that the register read is just very slow instead of
> fatal in this case.
> 
> Tested on 8997 in both MSI and (though not technically supported at the
> moment) MSI-X mode.

Well, that kills interrupt mitigation and with PCIE that might be
somewhat important (SDIO is too slow to be important I think) and might
cost you throughput.

OTOH maybe Marvell should convert PICE to NAPI to make this more
obvious and probably more correct.

> 
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
> v2:
>  * new in v2, replacing an attempt to mess with step (d) above
> ---
>  drivers/net/wireless/marvell/mwifiex/pcie.c | 102 +++++++++-------------------
>  1 file changed, 32 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
> index 3f4cda2d3b61..194e0e04c3b1 100644
> --- a/drivers/net/wireless/marvell/mwifiex/pcie.c
> +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
> @@ -2332,79 +2332,41 @@ static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter)
>  			}
>  		}
>  	}
> -	while (pcie_ireg & HOST_INTR_MASK) {
> -		if (pcie_ireg & HOST_INTR_DNLD_DONE) {
> -			pcie_ireg &= ~HOST_INTR_DNLD_DONE;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: TX DNLD Done\n");
> -			ret = mwifiex_pcie_send_data_complete(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -		if (pcie_ireg & HOST_INTR_UPLD_RDY) {
> -			pcie_ireg &= ~HOST_INTR_UPLD_RDY;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: Rx DATA\n");
> -			ret = mwifiex_pcie_process_recv_data(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -		if (pcie_ireg & HOST_INTR_EVENT_RDY) {
> -			pcie_ireg &= ~HOST_INTR_EVENT_RDY;
> -			mwifiex_dbg(adapter, INTR,
> -				    "info: Rx EVENT\n");
> -			ret = mwifiex_pcie_process_event_ready(adapter);
> -			if (ret)
> -				return ret;
> -		}
> -
> -		if (pcie_ireg & HOST_INTR_CMD_DONE) {
> -			pcie_ireg &= ~HOST_INTR_CMD_DONE;
> -			if (adapter->cmd_sent) {
> -				mwifiex_dbg(adapter, INTR,
> -					    "info: CMD sent Interrupt\n");
> -				adapter->cmd_sent = false;
> -			}
> -			/* Handle command response */
> -			ret = mwifiex_pcie_process_cmd_complete(adapter);
> -			if (ret)
> -				return ret;
> -			if (adapter->hs_activated)
> -				return ret;
> -		}
> -
> -		if (card->msi_enable) {
> -			spin_lock_irqsave(&adapter->int_lock, flags);
> -			adapter->int_status = 0;
> -			spin_unlock_irqrestore(&adapter->int_lock, flags);
> -		}
> -
> -		if (mwifiex_pcie_ok_to_access_hw(adapter)) {
> -			if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
> -					     &pcie_ireg)) {
> -				mwifiex_dbg(adapter, ERROR,
> -					    "Read register failed\n");
> -				return -1;
> -			}
>  
> -			if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
> -				if (mwifiex_write_reg(adapter,
> -						      PCIE_HOST_INT_STATUS,
> -						      ~pcie_ireg)) {
> -					mwifiex_dbg(adapter, ERROR,
> -						    "Write register failed\n");
> -					return -1;
> -				}
> -			}
> -
> -		}
> -		if (!card->msi_enable) {
> -			spin_lock_irqsave(&adapter->int_lock, flags);
> -			pcie_ireg |= adapter->int_status;
> -			adapter->int_status = 0;
> -			spin_unlock_irqrestore(&adapter->int_lock, flags);
> +	if (pcie_ireg & HOST_INTR_DNLD_DONE) {
> +		pcie_ireg &= ~HOST_INTR_DNLD_DONE;
> +		mwifiex_dbg(adapter, INTR, "info: TX DNLD Done\n");
> +		ret = mwifiex_pcie_send_data_complete(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_UPLD_RDY) {
> +		pcie_ireg &= ~HOST_INTR_UPLD_RDY;
> +		mwifiex_dbg(adapter, INTR, "info: Rx DATA\n");
> +		ret = mwifiex_pcie_process_recv_data(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_EVENT_RDY) {
> +		pcie_ireg &= ~HOST_INTR_EVENT_RDY;
> +		mwifiex_dbg(adapter, INTR, "info: Rx EVENT\n");
> +		ret = mwifiex_pcie_process_event_ready(adapter);
> +		if (ret)
> +			return ret;
> +	}
> +	if (pcie_ireg & HOST_INTR_CMD_DONE) {
> +		pcie_ireg &= ~HOST_INTR_CMD_DONE;
> +		if (adapter->cmd_sent) {
> +			mwifiex_dbg(adapter, INTR,
> +				    "info: CMD sent Interrupt\n");
> +			adapter->cmd_sent = false;
>  		}
> +		/* Handle command response */
> +		ret = mwifiex_pcie_process_cmd_complete(adapter);
> +		if (ret)
> +			return ret;
>  	}
> +
>  	mwifiex_dbg(adapter, INTR,
>  		    "info: cmd_sent=%d data_sent=%d\n",
>  		    adapter->cmd_sent, adapter->data_sent);
> -- 
> 2.11.0.483.g087da7b7c-goog
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Shawn Lin @ 2017-01-16  2:35 UTC (permalink / raw)
  To: Matt Ranostay
  Cc: shawn.lin, linux-wireless, Linux Kernel, linux-mmc, devicetree,
	Tony Lindgren, Ulf Hansson
In-Reply-To: <CAJ_EiSQtPUwv9K7CbM5e_wnre6=qR=+hgtq-oVFub2phijvXgA@mail.gmail.com>

On 2017/1/16 5:41, Matt Ranostay wrote:
> On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin@rock-chips.com> wrote:
>> On 2017/1/13 13:29, Matt Ranostay wrote:
>>>
>>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>>> This can be abstracted to other chipsets if needed in the future.
>>>
>>> Cc: Tony Lindgren <tony@atomide.com>
>>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>> ---
>>>  drivers/mmc/core/Kconfig         |  10 ++++
>>>  drivers/mmc/core/Makefile        |   1 +
>>>  drivers/mmc/core/pwrseq_sd8787.c | 117
>>> +++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 128 insertions(+)
>>>  create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>>
>>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>>> --- a/drivers/mmc/core/Kconfig
>>> +++ b/drivers/mmc/core/Kconfig
>>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>>           This driver can also be built as a module. If so, the module
>>>           will be called pwrseq_emmc.
>>>
>>> +config PWRSEQ_SD8787
>>> +       tristate "HW reset support for SD8787 BT + Wifi module"
>>> +       depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>>> +       help
>>> +         This selects hardware reset support for the SD8787 BT + Wifi
>>> +         module. By default this option is set to n.
>>> +
>>> +         This driver can also be built as a module. If so, the module
>>> +         will be called pwrseq_sd8787.
>>> +
>>
>>
>> I don't like this way, as we have a chance to list lots
>> configure options here. wifi A,B,C,D...Z, all of them need a
>> new section here if needed?
>>
>> Instead, could you just extent pwrseq_simple.c and add you
>> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?
>
> You mean all the chipset pwrseqs linked into the pwrseq-simple module?

What I mean was if you just extent the pwrseq-simple a bit, you could
just add your chipset pwrseqs linked into the pwrseq-simple. But if you
need a different *pattern* of pwrseqs, you should need a new name, for
instance, pwrseq-sdio.c etc... But please don't use the name of
sd8787? So if I use a wifi named ABC but using the same pwrseq pattenr,
should I include your "mmc-pwrseq- sd8787" for that or I need a new
mmc-pwrseq-ABC.c?

>
> Ulf your thoughts on this?
>
>>
>>
>>
>>>  config PWRSEQ_SIMPLE
>>>         tristate "Simple HW reset support for MMC"
>>>         default y
>>> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
>>> index b2a257dc644f..0f81464fa824 100644
>>> --- a/drivers/mmc/core/Makefile
>>> +++ b/drivers/mmc/core/Makefile
>>> @@ -10,6 +10,7 @@ mmc_core-y                    := core.o bus.o host.o \
>>>                                    quirks.o slot-gpio.o
>>>  mmc_core-$(CONFIG_OF)          += pwrseq.o
>>>  obj-$(CONFIG_PWRSEQ_SIMPLE)    += pwrseq_simple.o
>>> +obj-$(CONFIG_PWRSEQ_SD8787)    += pwrseq_sd8787.o
>>>  obj-$(CONFIG_PWRSEQ_EMMC)      += pwrseq_emmc.o
>>>  mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
>>>  obj-$(CONFIG_MMC_BLOCK)                += mmc_block.o
>>> diff --git a/drivers/mmc/core/pwrseq_sd8787.c
>>> b/drivers/mmc/core/pwrseq_sd8787.c
>>> new file mode 100644
>>> index 000000000000..f4080fe6439e
>>> --- /dev/null
>>> +++ b/drivers/mmc/core/pwrseq_sd8787.c
>>> @@ -0,0 +1,117 @@
>>> +/*
>>> + * pwrseq_sd8787.c - power sequence support for Marvell SD8787 BT + Wifi
>>> chip
>>> + *
>>> + * Copyright (C) 2016 Matt Ranostay <matt@ranostay.consulting>
>>> + *
>>> + * Based on the original work pwrseq_simple.c
>>> + *  Copyright (C) 2014 Linaro Ltd
>>> + *  Author: Ulf Hansson <ulf.hansson@linaro.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/init.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/module.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/device.h>
>>> +#include <linux/err.h>
>>> +#include <linux/gpio/consumer.h>
>>> +
>>> +#include <linux/mmc/host.h>
>>> +
>>> +#include "pwrseq.h"
>>> +
>>> +struct mmc_pwrseq_sd8787 {
>>> +       struct mmc_pwrseq pwrseq;
>>> +       struct gpio_desc *reset_gpio;
>>> +       struct gpio_desc *pwrdn_gpio;
>>> +};
>>> +
>>> +#define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787,
>>> pwrseq)
>>> +
>>> +static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>>> +
>>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 1);
>>> +
>>> +       msleep(300);
>>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1);
>>> +}
>>> +
>>> +static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq);
>>> +
>>> +       gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0);
>>> +       gpiod_set_value_cansleep(pwrseq->reset_gpio, 0);
>>> +}
>>> +
>>> +static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = {
>>> +       .pre_power_on = mmc_pwrseq_sd8787_pre_power_on,
>>> +       .power_off = mmc_pwrseq_sd8787_power_off,
>>> +};
>>> +
>>> +static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = {
>>> +       { .compatible = "mmc-pwrseq-sd8787",},
>>> +       {/* sentinel */},
>>> +};
>>> +MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match);
>>> +
>>> +static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq;
>>> +       struct device *dev = &pdev->dev;
>>> +
>>> +       pwrseq = devm_kzalloc(dev, sizeof(*pwrseq), GFP_KERNEL);
>>> +       if (!pwrseq)
>>> +               return -ENOMEM;
>>> +
>>> +       pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "pwrdn", GPIOD_OUT_LOW);
>>> +       if (IS_ERR(pwrseq->pwrdn_gpio))
>>> +               return PTR_ERR(pwrseq->pwrdn_gpio);
>>> +
>>> +       pwrseq->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
>>> +       if (IS_ERR(pwrseq->reset_gpio))
>>> +               return PTR_ERR(pwrseq->reset_gpio);
>>> +
>>> +       pwrseq->pwrseq.dev = dev;
>>> +       pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops;
>>> +       pwrseq->pwrseq.owner = THIS_MODULE;
>>> +       platform_set_drvdata(pdev, pwrseq);
>>> +
>>> +       return mmc_pwrseq_register(&pwrseq->pwrseq);
>>> +}
>>> +
>>> +static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev)
>>> +{
>>> +       struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev);
>>> +
>>> +       mmc_pwrseq_unregister(&pwrseq->pwrseq);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static struct platform_driver mmc_pwrseq_sd8787_driver = {
>>> +       .probe = mmc_pwrseq_sd8787_probe,
>>> +       .remove = mmc_pwrseq_sd8787_remove,
>>> +       .driver = {
>>> +               .name = "pwrseq_sd8787",
>>> +               .of_match_table = mmc_pwrseq_sd8787_of_match,
>>> +       },
>>> +};
>>> +
>>> +module_platform_driver(mmc_pwrseq_sd8787_driver);
>>> +MODULE_LICENSE("GPL v2");
>>>
>>
>>
>> --
>> Best Regards
>> Shawn Lin
>>
>
>
>


-- 
Best Regards
Shawn Lin

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox