Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 1/2] ath10k: Add support for ack rssi value of management tx packets
From: Abhishek Ambure @ 2019-02-12 12:39 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Abhishek Ambure
In-Reply-To: <1549975191-20912-1-git-send-email-aambure@codeaurora.org>

In WCN3990, WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI service Indicates that
the firmware has the capability to send the RSSI value of the ACK for all
data and management packets transmitted.

If WMI_RSRC_CFG_FLAG_TX_ACK_RSSI is set in host capability then firmware
sends RSSI value in "management" tx completion event. Host extracts ack
rssi values of management packets from their tx completion event.

Tested HW: WCN3990
Tested FW: WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1

Signed-off-by: Abhishek Ambure <aambure@codeaurora.org>
V2: Tested HW & Tested FW added
---
 drivers/net/wireless/ath/ath10k/wmi-tlv.c | 26 ++++++++++++++++++--
 drivers/net/wireless/ath/ath10k/wmi-tlv.h | 25 +++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi.c     | 40 +++++++++++++++++++++----------
 drivers/net/wireless/ath/ath10k/wmi.h     | 11 +++++++++
 4 files changed, 88 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 6075daf..b03ed58 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -623,6 +623,10 @@ static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar,
 	arg->desc_id = ev->desc_id;
 	arg->status = ev->status;
 	arg->pdev_id = ev->pdev_id;
+	arg->ppdu_id = ev->ppdu_id;
+
+	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+		arg->ack_rssi = ev->ack_rssi;
 
 	kfree(tb);
 	return 0;
@@ -632,8 +636,12 @@ struct wmi_tlv_tx_bundle_compl_parse {
 	const __le32 *num_reports;
 	const __le32 *desc_ids;
 	const __le32 *status;
+	const __le32 *ppdu_ids;
+	const __le32 *ack_rssi;
 	bool desc_ids_done;
 	bool status_done;
+	bool ppdu_ids_done;
+	bool ack_rssi_done;
 };
 
 static int
@@ -653,6 +661,12 @@ struct wmi_tlv_tx_bundle_compl_parse {
 		} else if (!bundle_tx_compl->status_done) {
 			bundle_tx_compl->status_done = true;
 			bundle_tx_compl->status = ptr;
+		} else if (!bundle_tx_compl->ppdu_ids_done) {
+			bundle_tx_compl->ppdu_ids_done = true;
+			bundle_tx_compl->ppdu_ids = ptr;
+		} else if (!bundle_tx_compl->ack_rssi_done) {
+			bundle_tx_compl->ack_rssi_done = true;
+			bundle_tx_compl->ack_rssi = ptr;
 		}
 		break;
 	default:
@@ -683,6 +697,10 @@ static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev(
 	arg->num_reports = *bundle_tx_compl.num_reports;
 	arg->desc_ids = bundle_tx_compl.desc_ids;
 	arg->status = bundle_tx_compl.status;
+	arg->ppdu_ids = bundle_tx_compl.ppdu_ids;
+
+	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+		arg->ack_rssi = bundle_tx_compl.ack_rssi;
 
 	return 0;
 }
@@ -1619,7 +1637,9 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
 	cfg->num_ocb_vdevs = __cpu_to_le32(0);
 	cfg->num_ocb_channels = __cpu_to_le32(0);
 	cfg->num_ocb_schedules = __cpu_to_le32(0);
-	cfg->host_capab = __cpu_to_le32(0);
+
+	if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+		cfg->host_capab = __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI);
 
 	ath10k_wmi_put_host_mem_chunks(ar, chunks);
 
@@ -2723,7 +2743,9 @@ static void *ath10k_wmi_tlv_put_wmm(void *ptr,
 	arvif = (void *)cb->vif->drv_priv;
 	vdev_id = arvif->vdev_id;
 
-	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
+	if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) &&
+			 (!(ieee80211_is_nullfunc(hdr->frame_control) ||
+			 ieee80211_is_qos_nullfunc(hdr->frame_control)))))
 		return ERR_PTR(-EINVAL);
 
 	len = sizeof(*cmd) + 2 * sizeof(*tlv);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index 7a58c76..4803fca 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -24,6 +24,8 @@
 #define WMI_TLV_VDEV_PARAM_UNSUPPORTED 0
 #define WMI_TLV_MGMT_TX_FRAME_MAX_LEN	64
 
+#define WMI_RSRC_CFG_FLAG_TX_ACK_RSSI		BIT(18)
+
 enum wmi_tlv_grp_id {
 	WMI_TLV_GRP_START = 0x3,
 	WMI_TLV_GRP_SCAN = WMI_TLV_GRP_START,
@@ -1408,6 +1410,25 @@ enum wmi_tlv_service {
 	WMI_TLV_SERVICE_AP_TWT = 153,
 	WMI_TLV_SERVICE_GMAC_OFFLOAD_SUPPORT = 154,
 	WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT = 155,
+	WMI_TLV_SERVICE_PEER_TID_CONFIGS_SUPPORT = 156,
+	WMI_TLV_SERVICE_VDEV_SWRETRY_PER_AC_CONFIG_SUPPORT = 157,
+	WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_SCC_SUPPORT = 158,
+	WMI_TLV_SERVICE_DUAL_BEACON_ON_SINGLE_MAC_MCC_SUPPORT = 159,
+	WMI_TLV_SERVICE_MOTION_DET = 160,
+	WMI_TLV_SERVICE_INFRA_MBSSID = 161,
+	WMI_TLV_SERVICE_OBSS_SPATIAL_REUSE = 162,
+	WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT = 163,
+	WMI_TLV_SERVICE_NAN_DBS_SUPPORT = 164,
+	WMI_TLV_SERVICE_NDI_DBS_SUPPORT = 165,
+	WMI_TLV_SERVICE_NAN_SAP_SUPPORT = 166,
+	WMI_TLV_SERVICE_NDI_SAP_SUPPORT = 167,
+	WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT = 168,
+	WMI_TLV_SERVICE_CFR_CAPTURE_IND_MSG_TYPE_1 = 169,
+	WMI_TLV_SERVICE_ESP_SUPPORT = 170,
+	WMI_TLV_SERVICE_PEER_CHWIDTH_CHANGE = 171,
+	WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
+	WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
+	WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
 
 	WMI_TLV_MAX_EXT_SERVICE = 256,
 };
@@ -1578,6 +1599,8 @@ enum wmi_tlv_service {
 	SVCMAP(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT,
 	       WMI_SERVICE_SPOOF_MAC_SUPPORT,
 	       WMI_TLV_MAX_SERVICE);
+	SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
+	       WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
 }
 
 #undef SVCMAP
@@ -1607,6 +1630,8 @@ struct wmi_tlv_mgmt_tx_compl_ev {
 	__le32 desc_id;
 	__le32 status;
 	__le32 pdev_id;
+	__le32 ppdu_id;
+	__le32 ack_rssi;
 };
 
 #define WMI_TLV_MGMT_RX_NUM_RSSI 4
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 2ba733f..2de8c9b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -2345,8 +2345,8 @@ static bool ath10k_wmi_rx_is_decrypted(struct ath10k *ar,
 	return true;
 }
 
-static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
-				    u32 status)
+static int
+wmi_process_mgmt_tx_comp(struct ath10k *ar, struct mgmt_tx_compl_params *param)
 {
 	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
 	struct ath10k_wmi *wmi = &ar->wmi;
@@ -2356,10 +2356,10 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
 
 	spin_lock_bh(&ar->data_lock);
 
-	pkt_addr = idr_find(&wmi->mgmt_pending_tx, desc_id);
+	pkt_addr = idr_find(&wmi->mgmt_pending_tx, param->desc_id);
 	if (!pkt_addr) {
 		ath10k_warn(ar, "received mgmt tx completion for invalid msdu_id: %d\n",
-			    desc_id);
+			    param->desc_id);
 		ret = -ENOENT;
 		goto out;
 	}
@@ -2369,17 +2369,21 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
 			 msdu->len, DMA_FROM_DEVICE);
 	info = IEEE80211_SKB_CB(msdu);
 
-	if (status)
+	if (param->status) {
 		info->flags &= ~IEEE80211_TX_STAT_ACK;
-	else
+	} else {
 		info->flags |= IEEE80211_TX_STAT_ACK;
+		info->status.ack_signal = ATH10K_DEFAULT_NOISE_FLOOR +
+					  param->ack_rssi;
+		info->status.is_valid_ack_signal = true;
+	}
 
 	ieee80211_tx_status_irqsafe(ar->hw, msdu);
 
 	ret = 0;
 
 out:
-	idr_remove(&wmi->mgmt_pending_tx, desc_id);
+	idr_remove(&wmi->mgmt_pending_tx, param->desc_id);
 	spin_unlock_bh(&ar->data_lock);
 	return ret;
 }
@@ -2387,6 +2391,7 @@ static int wmi_process_mgmt_tx_comp(struct ath10k *ar, u32 desc_id,
 int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_tlv_mgmt_tx_compl_ev_arg arg;
+	struct mgmt_tx_compl_params param;
 	int ret;
 
 	ret = ath10k_wmi_pull_mgmt_tx_compl(ar, skb, &arg);
@@ -2395,8 +2400,12 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
 		return ret;
 	}
 
-	wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_id),
-				 __le32_to_cpu(arg.status));
+	memset(&param, 0, sizeof(struct mgmt_tx_compl_params));
+	param.desc_id = __le32_to_cpu(arg.desc_id);
+	param.status = __le32_to_cpu(arg.status);
+	param.ack_rssi = __le32_to_cpu(arg.ack_rssi);
+
+	wmi_process_mgmt_tx_comp(ar, &param);
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv evnt mgmt tx completion\n");
 
@@ -2406,6 +2415,7 @@ int ath10k_wmi_event_mgmt_tx_compl(struct ath10k *ar, struct sk_buff *skb)
 int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg arg;
+	struct mgmt_tx_compl_params param;
 	u32 num_reports;
 	int i, ret;
 
@@ -2417,9 +2427,15 @@ int ath10k_wmi_event_mgmt_tx_bundle_compl(struct ath10k *ar, struct sk_buff *skb
 
 	num_reports = __le32_to_cpu(arg.num_reports);
 
-	for (i = 0; i < num_reports; i++)
-		wmi_process_mgmt_tx_comp(ar, __le32_to_cpu(arg.desc_ids[i]),
-					 __le32_to_cpu(arg.status[i]));
+	for (i = 0; i < num_reports; i++) {
+		memset(&param, 0, sizeof(struct mgmt_tx_compl_params));
+		param.desc_id = __le32_to_cpu(arg.desc_ids[i]);
+		param.status = __le32_to_cpu(arg.desc_ids[i]);
+
+		if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map))
+			param.ack_rssi = __le32_to_cpu(arg.ack_rssi[i]);
+		wmi_process_mgmt_tx_comp(ar, &param);
+	}
 
 	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv event bundle mgmt tx completion\n");
 
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 25bb04b..7a50ad6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -6708,16 +6708,27 @@ struct wmi_scan_ev_arg {
 	__le32 vdev_id;
 };
 
+struct mgmt_tx_compl_params {
+	u32 desc_id;
+	u32 status;
+	u32 ppdu_id;
+	int ack_rssi;
+};
+
 struct wmi_tlv_mgmt_tx_compl_ev_arg {
 	__le32 desc_id;
 	__le32 status;
 	__le32 pdev_id;
+	__le32 ppdu_id;
+	__le32 ack_rssi;
 };
 
 struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg {
 	__le32 num_reports;
 	const __le32 *desc_ids;
 	const __le32 *status;
+	const __le32 *ppdu_ids;
+	const __le32 *ack_rssi;
 };
 
 struct wmi_mgmt_rx_ev_arg {
-- 
1.9.1


^ permalink raw reply related

* [PATCH v2 2/2] ath10k: Add support for ack rssi value of data tx packets
From: Abhishek Ambure @ 2019-02-12 12:39 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Abhishek Ambure
In-Reply-To: <1549975191-20912-1-git-send-email-aambure@codeaurora.org>

In WCN3990, WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI service Indicates that
the firmware has the capability to send the RSSI value of the ACK for all
data and management packets transmitted.

If WMI_RSRC_CFG_FLAG_TX_ACK_RSSI is set in host capability then firmware
sends RSSI value in "data" tx completion event. Host extracts ack rssi
values of data packets from their tx completion event.

Tested HW: WCN3990
Tested FW: WLAN.HL.2.0-01617-QCAHLSWMTPLZ-1

Signed-off-by: Abhishek Ambure <aambure@codeaurora.org>
V2: Tested HW & Tested FW added
---
 drivers/net/wireless/ath/ath10k/htt.h    | 86 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/htt_rx.c | 12 +++--
 drivers/net/wireless/ath/ath10k/hw.c     | 32 +++++++++++-
 drivers/net/wireless/ath/ath10k/hw.h     | 22 ++++++++
 4 files changed, 146 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 9ae9466..860fb6f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -582,6 +582,10 @@ struct htt_mgmt_tx_completion {
 
 #define HTT_TX_CMPL_FLAG_DATA_RSSI BIT(0)
 
+#define HTT_TX_DATA_RSSI_ENABLE_WCN3990 BIT(3)
+#define HTT_TX_DATA_APPEND_RETRIES BIT(0)
+#define HTT_TX_DATA_APPEND_TIMESTAMP BIT(1)
+
 struct htt_rx_indication_hdr {
 	u8 info0; /* %HTT_RX_INDICATION_INFO0_ */
 	__le16 peer_id;
@@ -835,6 +839,88 @@ enum htt_data_tx_flags {
 
 #define HTT_TX_COMPL_INV_MSDU_ID 0xFFFF
 
+struct htt_append_retries {
+	__le16 msdu_id;
+	u8 tx_retries;
+	u8 flag;
+} __packed;
+
+struct htt_data_tx_completion_ext {
+	struct htt_append_retries a_retries;
+	__le32 t_stamp;
+	__le16 msdus_rssi[0];
+} __packed;
+
+/**
+ * @brief target -> host TX completion indication message definition
+ *
+ * @details
+ * The following diagram shows the format of the TX completion indication sent
+ * from the target to the host
+ *
+ *          |31 28|27|26|25|24|23        16| 15 |14 11|10   8|7          0|
+ *          |-------------------------------------------------------------|
+ * header:  |rsvd |A2|TP|A1|A0|     num    | t_i| tid |status|  msg_type  |
+ *          |-------------------------------------------------------------|
+ * payload: |            MSDU1 ID          |         MSDU0 ID             |
+ *          |-------------------------------------------------------------|
+ *          :            MSDU3 ID          :         MSDU2 ID             :
+ *          |-------------------------------------------------------------|
+ *          |          struct htt_tx_compl_ind_append_retries             |
+ *          |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ *          |          struct htt_tx_compl_ind_append_tx_tstamp           |
+ *          |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ *          |           MSDU1 ACK RSSI     |        MSDU0 ACK RSSI        |
+ *          |-------------------------------------------------------------|
+ *          :           MSDU3 ACK RSSI     :        MSDU2 ACK RSSI        :
+ *          |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
+ *    -msg_type
+ *     Bits 7:0
+ *     Purpose: identifies this as HTT TX completion indication
+ *    -status
+ *     Bits 10:8
+ *     Purpose: the TX completion status of payload fragmentations descriptors
+ *     Value: could be HTT_TX_COMPL_IND_STAT_OK or HTT_TX_COMPL_IND_STAT_DISCARD
+ *    -tid
+ *     Bits 14:11
+ *     Purpose: the tid associated with those fragmentation descriptors. It is
+ *     valid or not, depending on the tid_invalid bit.
+ *     Value: 0 to 15
+ *    -tid_invalid
+ *     Bits 15:15
+ *     Purpose: this bit indicates whether the tid field is valid or not
+ *     Value: 0 indicates valid, 1 indicates invalid
+ *    -num
+ *     Bits 23:16
+ *     Purpose: the number of payload in this indication
+ *     Value: 1 to 255
+ *    -A0 = append
+ *     Bits 24:24
+ *     Purpose: append the struct htt_tx_compl_ind_append_retries which contains
+ *            the number of tx retries for one MSDU at the end of this message
+ *     Value: 0 indicates no appending, 1 indicates appending
+ *    -A1 = append1
+ *     Bits 25:25
+ *     Purpose: Append the struct htt_tx_compl_ind_append_tx_tstamp which
+ *            contains the timestamp info for each TX msdu id in payload.
+ *     Value: 0 indicates no appending, 1 indicates appending
+ *    -TP = MSDU tx power presence
+ *     Bits 26:26
+ *     Purpose: Indicate whether the TX_COMPL_IND includes a tx power report
+ *            for each MSDU referenced by the TX_COMPL_IND message.
+ *            The order of the per-MSDU tx power reports matches the order
+ *            of the MSDU IDs.
+ *     Value: 0 indicates not appending, 1 indicates appending
+ *    -A2 = append2
+ *     Bits 27:27
+ *     Purpose: Indicate whether data ACK RSSI is appended for each MSDU in
+ *            TX_COMP_IND message.  The order of the per-MSDU ACK RSSI report
+ *            matches the order of the MSDU IDs.
+ *            The ACK RSSI values are valid when status is COMPLETE_OK (and
+ *            this append2 bit is set).
+ *     Value: 0 indicates not appending, 1 indicates appending
+ */
+
 struct htt_data_tx_completion {
 	union {
 		u8 flags;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index d6d696a..1380772 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1810,7 +1810,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
 	__le16 msdu_id, *msdus;
 	bool rssi_enabled = false;
 	u8 msdu_count = 0;
-	int i;
+	int i, htt_pad = 0;
 
 	switch (status) {
 	case HTT_DATA_TX_STATUS_NO_ACK:
@@ -1834,9 +1834,11 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
 		   resp->data_tx_completion.num_msdus);
 
 	msdu_count = resp->data_tx_completion.num_msdus;
+	rssi_enabled = ath10k_is_rssi_enable(&ar->hw_params, resp);
 
-	if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI)
-		rssi_enabled = true;
+	if (rssi_enabled)
+		htt_pad = ath10k_tx_data_rssi_get_pad_bytes(&ar->hw_params,
+							    resp);
 
 	for (i = 0; i < msdu_count; i++) {
 		msdus = resp->data_tx_completion.msdus;
@@ -1849,10 +1851,10 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
 			 * last msdu id with 0xffff
 			 */
 			if (msdu_count & 0x01) {
-				msdu_id = msdus[msdu_count +  i + 1];
+				msdu_id = msdus[msdu_count +  i + 1 + htt_pad];
 				tx_done.ack_rssi = __le16_to_cpu(msdu_id);
 			} else {
-				msdu_id = msdus[msdu_count +  i];
+				msdu_id = msdus[msdu_count +  i + htt_pad];
 				tx_done.ack_rssi = __le16_to_cpu(msdu_id);
 			}
 		}
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 6243fbf..6714913 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -1106,6 +1106,32 @@ int ath10k_hw_diag_fast_download(struct ath10k *ar,
 	return ret;
 }
 
+static int ath10k_htt_tx_rssi_enable(struct htt_resp *resp)
+{
+	return (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI);
+}
+
+static int ath10k_htt_tx_rssi_enable_wcn3990(struct htt_resp *resp)
+{
+	return (resp->data_tx_completion.flags2 &
+		HTT_TX_DATA_RSSI_ENABLE_WCN3990);
+}
+
+static int ath10k_get_htt_tx_data_rssi_pad(struct htt_resp *resp)
+{
+	struct htt_data_tx_completion_ext extd;
+	int pad_bytes = 0;
+
+	if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_RETRIES)
+		pad_bytes += sizeof(extd.a_retries) /
+			     sizeof(extd.msdus_rssi[0]);
+
+	if (resp->data_tx_completion.flags2 & HTT_TX_DATA_APPEND_TIMESTAMP)
+		pad_bytes += sizeof(extd.t_stamp) / sizeof(extd.msdus_rssi[0]);
+
+	return pad_bytes;
+}
+
 const struct ath10k_hw_ops qca988x_ops = {
 	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
 };
@@ -1130,6 +1156,10 @@ static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
 const struct ath10k_hw_ops qca6174_ops = {
 	.set_coverage_class = ath10k_hw_qca988x_set_coverage_class,
 	.enable_pll_clk = ath10k_hw_qca6174_enable_pll_clock,
+	.is_rssi_enable = ath10k_htt_tx_rssi_enable,
 };
 
-const struct ath10k_hw_ops wcn3990_ops = {};
+const struct ath10k_hw_ops wcn3990_ops = {
+	.tx_data_rssi_pad_bytes = ath10k_get_htt_tx_data_rssi_pad,
+	.is_rssi_enable = ath10k_htt_tx_rssi_enable_wcn3990,
+};
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 2733b54..567f1b8 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -607,6 +607,8 @@ struct ath10k_hw_params {
 };
 
 struct htt_rx_desc;
+struct htt_resp;
+struct htt_data_tx_completion_ext;
 
 /* Defines needed for Rx descriptor abstraction */
 struct ath10k_hw_ops {
@@ -614,6 +616,8 @@ struct ath10k_hw_ops {
 	void (*set_coverage_class)(struct ath10k *ar, s16 value);
 	int (*enable_pll_clk)(struct ath10k *ar);
 	bool (*rx_desc_get_msdu_limit_error)(struct htt_rx_desc *rxd);
+	int (*tx_data_rssi_pad_bytes)(struct htt_resp *htt);
+	int (*is_rssi_enable)(struct htt_resp *resp);
 };
 
 extern const struct ath10k_hw_ops qca988x_ops;
@@ -641,6 +645,24 @@ struct ath10k_hw_ops {
 	return false;
 }
 
+static inline int
+ath10k_tx_data_rssi_get_pad_bytes(struct ath10k_hw_params *hw,
+				  struct htt_resp *htt)
+{
+	if (hw->hw_ops->tx_data_rssi_pad_bytes)
+		return hw->hw_ops->tx_data_rssi_pad_bytes(htt);
+	return 0;
+}
+
+static inline int
+ath10k_is_rssi_enable(struct ath10k_hw_params *hw,
+		      struct htt_resp *resp)
+{
+	if (hw->hw_ops->is_rssi_enable)
+		return hw->hw_ops->is_rssi_enable(resp);
+	return 0;
+}
+
 /* Target specific defines for MAIN firmware */
 #define TARGET_NUM_VDEVS			8
 #define TARGET_NUM_PEER_AST			2
-- 
1.9.1


^ permalink raw reply related

* Re: [PULL] ath10k firmware 2019-02-01
From: Josh Boyer @ 2019-02-12 12:43 UTC (permalink / raw)
  To: Kalle Valo
  Cc: linux-firmware@kernel.org, ath10k@lists.infradead.org,
	linux-wireless@vger.kernel.org
In-Reply-To: <1549035547599.95403@qca.qualcomm.com>

On Fri, Feb 1, 2019 at 10:41 AM Kalle Valo <kvalo@qca.qualcomm.com> wrote:
>
> Hi,
>
> here are few ath10k firmware updates, please pull.
>
> Kalle
>
> The following changes since commit a8b75cac06f80dc1500ba385680ac5b5c1d1c4f8:
>
>   Merge tag 'add-rpi-fw' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux-firmware (2019-01-18 07:04:02 -0500)
>
> are available in the git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/linux-firmware.git ath10k-20190201
>
> for you to fetch changes up to 6b5e23a113704867df5205f31f02ffbc3ec4453e:
>
>   ath10k: QCA9984 hw1.0: update firmware-5.bin to 10.4-3.9.0.2-00021 (2019-02-01 17:22:55 +0200)
>
> ----------------------------------------------------------------
> Kalle Valo (4):
>       ath10k: QCA6174 hw3.0: update board-2.bin
>       ath10k: QCA9888 hw2.0: update firmware-5.bin to 10.4-3.9.0.2-00024
>       ath10k: QCA988X hw2.0: update firmware-5.bin to 10.2.4-1.0-00043
>       ath10k: QCA9984 hw1.0: update firmware-5.bin to 10.4-3.9.0.2-00021
>
>  WHENCE                              |   6 +++---
>  ath10k/QCA6174/hw3.0/board-2.bin    | Bin 551128 -> 567608 bytes
>  ath10k/QCA9888/hw2.0/firmware-5.bin | Bin 675492 -> 688536 bytes
>  ath10k/QCA988X/hw2.0/firmware-5.bin | Bin 248200 -> 248840 bytes
>  ath10k/QCA9984/hw1.0/firmware-5.bin | Bin 662084 -> 676316 bytes
>  5 files changed, 3 insertions(+), 3 deletions(-)

Pulled and pushed out.  Thanks.

josh

^ permalink raw reply

* Re: pull-request mwifiex-firmware 2019-02-12
From: Josh Boyer @ 2019-02-12 12:46 UTC (permalink / raw)
  To: Ganapathi Bhat
  Cc: linux-firmware@kernel.org, linux-wireless@vger.kernel.org,
	Cathy Luo, James Cao, Prashanth Ranganathan, Rakesh Parmar,
	Zhiyuan Yang
In-Reply-To: <DM5PR18MB12412307A7C6EDD99B522785A0650@DM5PR18MB1241.namprd18.prod.outlook.com>

On Tue, Feb 12, 2019 at 1:17 AM Ganapathi Bhat <gbhat@marvell.com> wrote:
>
> The following changes since commit 63ca64a73c05fa5bcceb687422cbc28185bb6355:
>
>   linux-firmware: update Marvell USB8801 B0 firmware image (2019-01-09 11:24:42 +0530)
>
> are available in the git repository at:
>
>   git://git.marvell.com/mwifiex-firmware.git
>
> for you to fetch changes up to bd72387b8e49b1b7268ee60c97a131419284fb39:
>
>   linux-firmware: update Marvell PCIe-USB8997 firmware image (2019-02-12 11:42:24 +0530)
>
> ----------------------------------------------------------------
> Ganapathi Bhat (3):
>       linux-firmware: add Marvell SD8977 firmware image
>       linux-firmware: update Marvell SD8897-B0 firmware image
>       linux-firmware: update Marvell PCIe-USB8997 firmware image
>
>  WHENCE                        |   7 +++++--
>  mrvl/pcieusb8997_combo_v4.bin | Bin 631012 -> 634228 bytes
>  mrvl/sd8897_uapsta.bin        | Bin 821024 -> 701072 bytes
>  mrvl/sdsd8977_combo_v2.bin    | Bin 0 -> 587052 bytes
>  4 files changed, 5 insertions(+), 2 deletions(-)
>  create mode 100755 mrvl/sdsd8977_combo_v2.bin

Pulled and pushed out.  Thanks.

josh

^ permalink raw reply

* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Stanislaw Gruszka @ 2019-02-12 13:15 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Alan Stern, Stefan Wahren, Felix Fietkau, Doug Anderson,
	Minas Harutyunyan, USB list, linux-wireless
In-Reply-To: <20190212115842.GA24197@localhost.localdomain>

On Tue, Feb 12, 2019 at 12:58:43PM +0100, Lorenzo Bianconi wrote:
> > +	usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len, complete_fn,
> > +			  context);
> > +
> > +	if (udev->bus->sg_tablesize > 0) {
> > +		buf->urb->num_sgs = buf->num_sgs;
> > +	} else {
> > +		WARN_ON_ONCE(buf->num_sgs != 1);
> > +		/* See usb_sg_init() */
> > +		buf->urb->num_sgs = 0;
> > +		if (!PageHighMem(sg_page(buf->urb->sg)))
> > +			buf->urb->transfer_buffer = sg_virt(buf->urb->sg);
> 
> please correct me if I am wrong but doing so we will use transfer_buffer
> for 95% of the use cases, right? If so why not keep it simple and always
> use it when sg_tablesize is 0 (avoiding SG I/O)?
>
> Btw this is what I proposed with the RFC series actually :) (always use
> transfer_buffer in the usb 2.0 case)

Because this way we do not change allocation method (use SG allocation)
what is simpler IMHO than having two buffer allocation methods.

And this way we do not hide problems with SG allocation and test it.

Additionally this patch address actual bug: using wrong urb->num_sgs and
can be easier to backport to older releases than 4 patch series. 

Stanislaw

^ permalink raw reply

* [PATCH RESEND 0/4] do not use sg if not properly supported by usb controller
From: lorenzo @ 2019-02-12 13:42 UTC (permalink / raw)
  To: linux-wireless

From: Lorenzo Bianconi <lorenzo@kernel.org>

Use linear fragment and not a single usb scatter-gather buffer in mt76u
{tx,rx} datapath if the usb controller has sg data length constraints.
Moreover add disable_usb_sg module parameter in order to explicitly
disable scatter-gather. SG I/O is not supported by all host drivers and
some users have reported sg issues on AMD IOMMU.
This series has been tested on AMD IOMMU cpus/motherboards and on rpi3+

Changes since RFC:
- rebased on top of 'fix multiple issues in mt76u error path'
  https://patchwork.kernel.org/cover/10804919/

I am resending the series since the first attempt seems to be rejected by
the ML

Lorenzo Bianconi (4):
  mt76: usb: move mt76u_check_sg in usb.c
  mt76: usb: do not use sg buffers for mcu messages
  mt76: usb: use a linear buffer for tx/rx datapath if sg is not
    supported
  mt76: usb: introduce disable_usb_sg parameter

 drivers/net/wireless/mediatek/mt76/mt76.h     |  14 +-
 .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   2 +-
 .../wireless/mediatek/mt76/mt76x02_usb_mcu.c  |   3 +-
 .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
 drivers/net/wireless/mediatek/mt76/usb.c      | 133 +++++++++++++-----
 drivers/net/wireless/mediatek/mt76/usb_mcu.c  |   5 +-
 6 files changed, 105 insertions(+), 54 deletions(-)

-- 
2.20.1


^ permalink raw reply

* [PATCH RESEND 1/4] mt76: usb: move mt76u_check_sg in usb.c
From: lorenzo @ 2019-02-12 13:42 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <cover.1549977282.git.lorenzo@kernel.org>

From: Lorenzo Bianconi <lorenzo@kernel.org>

Move mt76u_check_sg routine in usb.c and introduce sg_en variable
in mt76_usb in order to check if scatter-gather is supported by
mt76u layer

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h          | 11 +----------
 drivers/net/wireless/mediatek/mt76/mt76x0/usb.c    |  2 +-
 .../net/wireless/mediatek/mt76/mt76x2/usb_init.c   |  2 +-
 drivers/net/wireless/mediatek/mt76/usb.c           | 14 +++++++++++++-
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 13f6febc9b0f..0eb9152c5d18 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -379,6 +379,7 @@ struct mt76_usb {
 	u16 out_max_packet;
 	u8 in_ep[__MT_EP_IN_MAX];
 	u16 in_max_packet;
+	bool sg_en;
 
 	struct mt76u_mcu {
 		struct mutex mutex;
@@ -726,16 +727,6 @@ static inline u8 q2ep(u8 qid)
 	return qid + 1;
 }
 
-static inline bool mt76u_check_sg(struct mt76_dev *dev)
-{
-	struct usb_interface *intf = to_usb_interface(dev->dev);
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	return (udev->bus->sg_tablesize > 0 &&
-		(udev->bus->no_sg_constraint ||
-		 udev->speed == USB_SPEED_WIRELESS));
-}
-
 static inline int
 mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int timeout)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 2f259bc0ad9e..da9d05f6074d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -206,7 +206,7 @@ static int mt76x0u_register_device(struct mt76x02_dev *dev)
 		goto out_err;
 
 	/* check hw sg support in order to enable AMSDU */
-	if (mt76u_check_sg(&dev->mt76))
+	if (dev->mt76.usb.sg_en)
 		hw->max_tx_fragments = MT_SG_MAX_SIZE;
 	else
 		hw->max_tx_fragments = 1;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
index 006e430e374e..090aaf71b3ef 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c
@@ -228,7 +228,7 @@ int mt76x2u_register_device(struct mt76x02_dev *dev)
 		goto fail;
 
 	/* check hw sg support in order to enable AMSDU */
-	if (mt76u_check_sg(&dev->mt76))
+	if (dev->mt76.usb.sg_en)
 		hw->max_tx_fragments = MT_SG_MAX_SIZE;
 	else
 		hw->max_tx_fragments = 1;
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index c7db8a9f6acc..829128a07701 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -241,6 +241,16 @@ mt76u_rd_rp(struct mt76_dev *dev, u32 base,
 		return mt76u_req_rd_rp(dev, base, data, n);
 }
 
+static bool mt76u_check_sg(struct mt76_dev *dev)
+{
+	struct usb_interface *intf = to_usb_interface(dev->dev);
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	return (udev->bus->sg_tablesize > 0 &&
+		(udev->bus->no_sg_constraint ||
+		 udev->speed == USB_SPEED_WIRELESS));
+}
+
 static int
 mt76u_set_endpoints(struct usb_interface *intf,
 		    struct mt76_usb *usb)
@@ -536,7 +546,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
 	if (!q->entry)
 		return -ENOMEM;
 
-	if (mt76u_check_sg(dev)) {
+	if (dev->usb.sg_en) {
 		q->buf_size = MT_RX_BUF_SIZE;
 		nsgs = MT_SG_MAX_SIZE;
 	} else {
@@ -881,6 +891,8 @@ int mt76u_init(struct mt76_dev *dev,
 	dev->bus = &mt76u_ops;
 	dev->queue_ops = &usb_queue_ops;
 
+	usb->sg_en = mt76u_check_sg(dev);
+
 	return mt76u_set_endpoints(intf, usb);
 }
 EXPORT_SYMBOL_GPL(mt76u_init);
-- 
2.20.1


^ permalink raw reply related

* [PATCH RESEND 2/4] mt76: usb: do not use sg buffers for mcu messages
From: lorenzo @ 2019-02-12 13:42 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <cover.1549977282.git.lorenzo@kernel.org>

From: Lorenzo Bianconi <lorenzo@kernel.org>

Do not use scatter-gather buffers for mcu commands.
Introduce mt76u_buf_alloc and mt76u_buf_alloc_sg routines.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/mt76.h     |  3 +-
 .../wireless/mediatek/mt76/mt76x02_usb_mcu.c  |  3 +-
 drivers/net/wireless/mediatek/mt76/usb.c      | 38 +++++++++++++++----
 drivers/net/wireless/mediatek/mt76/usb_mcu.c  |  5 +--
 4 files changed, 36 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 0eb9152c5d18..f55dc621e060 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -87,6 +87,7 @@ struct mt76u_buf {
 	struct mt76_dev *dev;
 	struct urb *urb;
 	size_t len;
+	void *buf;
 	bool done;
 };
 
@@ -748,7 +749,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
 int mt76u_init(struct mt76_dev *dev, struct usb_interface *intf);
 void mt76u_deinit(struct mt76_dev *dev);
 int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
-		    int nsgs, int len, int sglen, gfp_t gfp);
+		    int len, int data_len, gfp_t gfp);
 void mt76u_buf_free(struct mt76u_buf *buf);
 int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
 		     struct mt76u_buf *buf, gfp_t gfp,
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
index 64c777298cee..e469e383cb88 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_usb_mcu.c
@@ -63,9 +63,9 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
 	struct mt76_usb *usb = &dev->usb;
 	struct mt76u_buf *buf = &usb->mcu.res;
 	struct urb *urb = buf->urb;
+	u8 *data = buf->buf;
 	int i, ret;
 	u32 rxfce;
-	u8 *data;
 
 	for (i = 0; i < 5; i++) {
 		if (!wait_for_completion_timeout(&usb->mcu.cmpl,
@@ -75,7 +75,6 @@ static int mt76x02u_mcu_wait_resp(struct mt76_dev *dev, u8 seq)
 		if (urb->status)
 			return -EIO;
 
-		data = sg_virt(&urb->sg[0]);
 		if (usb->mcu.rp)
 			mt76x02u_multiple_mcu_reads(dev, data + 4,
 						    urb->actual_length - 8);
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 829128a07701..66c9451cb6f3 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -319,8 +319,9 @@ mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
 	return i ? : -ENOMEM;
 }
 
-int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
-		    int nsgs, int len, int sglen, gfp_t gfp)
+static int
+mt76u_buf_alloc_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
+		   int nsgs, int len, int sglen, gfp_t gfp)
 {
 	buf->urb = usb_alloc_urb(0, gfp);
 	if (!buf->urb)
@@ -337,6 +338,25 @@ int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
 	return mt76u_fill_rx_sg(dev, buf, nsgs, len, sglen);
 }
 
+int mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf,
+		    int len, int data_len, gfp_t gfp)
+{
+	struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+
+	buf->urb = usb_alloc_urb(0, gfp);
+	if (!buf->urb)
+		return -ENOMEM;
+
+	buf->buf = page_frag_alloc(&q->rx_page, len, gfp);
+	if (!buf->buf)
+		return -ENOMEM;
+
+	buf->len = data_len;
+	buf->dev = dev;
+
+	return 0;
+}
+
 void mt76u_buf_free(struct mt76u_buf *buf)
 {
 	struct urb *urb = buf->urb;
@@ -350,6 +370,9 @@ void mt76u_buf_free(struct mt76u_buf *buf)
 
 		skb_free_frag(sg_virt(sg));
 	}
+	if (buf->buf)
+		skb_free_frag(buf->buf);
+
 	usb_free_urb(buf->urb);
 }
 EXPORT_SYMBOL_GPL(mt76u_buf_free);
@@ -360,6 +383,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
 {
 	struct usb_interface *intf = to_usb_interface(dev->dev);
 	struct usb_device *udev = interface_to_usbdev(intf);
+	u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
 	unsigned int pipe;
 
 	if (dir == USB_DIR_IN)
@@ -367,7 +391,7 @@ int mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
 	else
 		pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
 
-	usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, buf->len,
+	usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len,
 			  complete_fn, context);
 	trace_submit_urb(dev, buf->urb);
 
@@ -556,10 +580,10 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
 
 	q->ndesc = MT_NUM_RX_ENTRIES;
 	for (i = 0; i < q->ndesc; i++) {
-		err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
-				      nsgs, q->buf_size,
-				      SKB_WITH_OVERHEAD(q->buf_size),
-				      GFP_KERNEL);
+		err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
+					 nsgs, q->buf_size,
+					 SKB_WITH_OVERHEAD(q->buf_size),
+					 GFP_KERNEL);
 		if (err < 0)
 			return err;
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/usb_mcu.c b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
index 9527e1216f3d..72c8607da4b4 100644
--- a/drivers/net/wireless/mediatek/mt76/usb_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/usb_mcu.c
@@ -29,9 +29,8 @@ int mt76u_mcu_init_rx(struct mt76_dev *dev)
 	struct mt76_usb *usb = &dev->usb;
 	int err;
 
-	err = mt76u_buf_alloc(dev, &usb->mcu.res, 1,
-			      MCU_RESP_URB_SIZE, MCU_RESP_URB_SIZE,
-			      GFP_KERNEL);
+	err = mt76u_buf_alloc(dev, &usb->mcu.res, MCU_RESP_URB_SIZE,
+			      MCU_RESP_URB_SIZE, GFP_KERNEL);
 	if (err < 0)
 		return err;
 
-- 
2.20.1


^ permalink raw reply related

* [PATCH RESEND 3/4] mt76: usb: use a linear buffer for tx/rx datapath if sg is not supported
From: lorenzo @ 2019-02-12 13:42 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <cover.1549977282.git.lorenzo@kernel.org>

From: Lorenzo Bianconi <lorenzo@kernel.org>

Use linear fragment and not a single usb scatter-gather buffer in mt76u
{tx,rx} datapath if the usb controller has sg data length constraints

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/usb.c | 87 +++++++++++++++---------
 1 file changed, 54 insertions(+), 33 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 66c9451cb6f3..7e7da6b49a88 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -432,10 +432,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
 }
 
 static int
-mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
+mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
 {
 	struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
-	u8 *data = sg_virt(&urb->sg[0]);
+	struct urb *urb = buf->urb;
+	u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
 	int data_len, len, nsgs = 1;
 	struct sk_buff *skb;
 
@@ -446,7 +447,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
 	if (len < 0)
 		return 0;
 
-	data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
+	data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
+	data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN);
 	if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
 		return 0;
 
@@ -458,7 +460,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
 	__skb_put(skb, data_len);
 	len -= data_len;
 
-	while (len > 0) {
+	while (len > 0 && urb->num_sgs) {
 		data_len = min_t(int, len, urb->sg[nsgs].length);
 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 				sg_page(&urb->sg[nsgs]),
@@ -504,12 +506,26 @@ static void mt76u_complete_rx(struct urb *urb)
 	spin_unlock_irqrestore(&q->lock, flags);
 }
 
+static int
+mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
+		struct mt76u_buf *buf, int nsgs)
+{
+	if (dev->usb.sg_en) {
+		return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size,
+					SKB_WITH_OVERHEAD(q->buf_size));
+	} else {
+		buf->buf = page_frag_alloc(&q->rx_page, q->buf_size,
+					   GFP_ATOMIC);
+		return buf->buf ? 0 : -ENOMEM;
+	}
+}
+
 static void mt76u_rx_tasklet(unsigned long data)
 {
 	struct mt76_dev *dev = (struct mt76_dev *)data;
 	struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
-	int err, nsgs, buf_len = q->buf_size;
 	struct mt76u_buf *buf;
+	int err, count;
 
 	rcu_read_lock();
 
@@ -518,11 +534,9 @@ static void mt76u_rx_tasklet(unsigned long data)
 		if (!buf)
 			break;
 
-		nsgs = mt76u_process_rx_entry(dev, buf->urb);
-		if (nsgs > 0) {
-			err = mt76u_fill_rx_sg(dev, buf, nsgs,
-					       buf_len,
-					       SKB_WITH_OVERHEAD(buf_len));
+		count = mt76u_process_rx_entry(dev, buf);
+		if (count > 0) {
+			err = mt76u_refill_rx(dev, q, buf, count);
 			if (err < 0)
 				break;
 		}
@@ -560,7 +574,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers);
 static int mt76u_alloc_rx(struct mt76_dev *dev)
 {
 	struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
-	int i, err, nsgs;
+	int i, err;
 
 	spin_lock_init(&q->rx_page_lock);
 	spin_lock_init(&q->lock);
@@ -570,20 +584,19 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
 	if (!q->entry)
 		return -ENOMEM;
 
-	if (dev->usb.sg_en) {
-		q->buf_size = MT_RX_BUF_SIZE;
-		nsgs = MT_SG_MAX_SIZE;
-	} else {
-		q->buf_size = PAGE_SIZE;
-		nsgs = 1;
-	}
-
+	q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
 	q->ndesc = MT_NUM_RX_ENTRIES;
 	for (i = 0; i < q->ndesc; i++) {
-		err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
-					 nsgs, q->buf_size,
-					 SKB_WITH_OVERHEAD(q->buf_size),
-					 GFP_KERNEL);
+		if (dev->usb.sg_en)
+			err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
+					MT_SG_MAX_SIZE, q->buf_size,
+					SKB_WITH_OVERHEAD(q->buf_size),
+					GFP_KERNEL);
+		else
+			err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
+					      q->buf_size,
+					      SKB_WITH_OVERHEAD(q->buf_size),
+					      GFP_KERNEL);
 		if (err < 0)
 			return err;
 	}
@@ -731,7 +744,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
 {
 	struct usb_interface *intf = to_usb_interface(dev->dev);
 	struct usb_device *udev = interface_to_usbdev(intf);
-	u8 ep = q2ep(q->hw_idx);
+	u8 *data = NULL, ep = q2ep(q->hw_idx);
 	struct mt76u_buf *buf;
 	u16 idx = q->tail;
 	unsigned int pipe;
@@ -748,12 +761,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
 	buf = &q->entry[idx].ubuf;
 	buf->done = false;
 
-	err = mt76u_tx_build_sg(skb, buf->urb);
-	if (err < 0)
-		return err;
+	if (dev->usb.sg_en) {
+		err = mt76u_tx_build_sg(skb, buf->urb);
+		if (err < 0)
+			return err;
+	} else {
+		data = skb->data;
+	}
 
 	pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]);
-	usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len,
+	usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len,
 			  mt76u_complete_tx, buf);
 
 	q->tail = (q->tail + 1) % q->ndesc;
@@ -789,10 +806,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
 {
 	struct mt76u_buf *buf;
 	struct mt76_queue *q;
-	size_t size;
 	int i, j;
 
-	size = MT_SG_MAX_SIZE * sizeof(struct scatterlist);
 	for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 		q = &dev->q_tx[i];
 		spin_lock_init(&q->lock);
@@ -814,9 +829,15 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
 			if (!buf->urb)
 				return -ENOMEM;
 
-			buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL);
-			if (!buf->urb->sg)
-				return -ENOMEM;
+			if (dev->usb.sg_en) {
+				size_t size = MT_SG_MAX_SIZE *
+					      sizeof(struct scatterlist);
+
+				buf->urb->sg = devm_kzalloc(dev->dev, size,
+							    GFP_KERNEL);
+				if (!buf->urb->sg)
+					return -ENOMEM;
+			}
 		}
 	}
 	return 0;
-- 
2.20.1


^ permalink raw reply related

* [PATCH RESEND 4/4] mt76: usb: introduce disable_usb_sg parameter
From: lorenzo @ 2019-02-12 13:42 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <cover.1549977282.git.lorenzo@kernel.org>

From: Lorenzo Bianconi <lorenzo@kernel.org>

Add disable_usb_sg module parameter to disable scatter-gather on demand

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
 drivers/net/wireless/mediatek/mt76/usb.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 7e7da6b49a88..78191968b4fa 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -22,6 +22,10 @@
 #define MT_VEND_REQ_MAX_RETRY	10
 #define MT_VEND_REQ_TOUT_MS	300
 
+static bool disable_usb_sg;
+module_param_named(disable_usb_sg, disable_usb_sg, bool, 0644);
+MODULE_PARM_DESC(disable_usb_sg, "Disable usb scatter-gather support");
+
 /* should be called with usb_ctrl_mtx locked */
 static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
 				  u8 req_type, u16 val, u16 offset,
@@ -246,7 +250,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
 	struct usb_interface *intf = to_usb_interface(dev->dev);
 	struct usb_device *udev = interface_to_usbdev(intf);
 
-	return (udev->bus->sg_tablesize > 0 &&
+	return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
 		(udev->bus->no_sg_constraint ||
 		 udev->speed == USB_SPEED_WIRELESS));
 }
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Stanislaw Gruszka @ 2019-02-12 13:45 UTC (permalink / raw)
  To: LorenzoBianconilorenzo; +Cc: nbd, linux-wireless
In-Reply-To: <cover.1549977282.git.lorenzo@kernel.org>

On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> From: Lorenzo Bianconi <lorenzo@kernel.org>
> 
> Use linear fragment and not a single usb scatter-gather buffer in mt76u
> {tx,rx} datapath if the usb controller has sg data length constraints.
> Moreover add disable_usb_sg module parameter in order to explicitly
> disable scatter-gather. SG I/O is not supported by all host drivers and
> some users have reported sg issues on AMD IOMMU.

Again. This is not right approach. SG issues should be fixed
not workarounded.

> This series has been tested on AMD IOMMU cpus/motherboards and on rpi3+

> - rebased on top of 'fix multiple issues in mt76u error path'
>   https://patchwork.kernel.org/cover/10804919/
> 
> Lorenzo Bianconi (4):
>   mt76: usb: move mt76u_check_sg in usb.c
>   mt76: usb: do not use sg buffers for mcu messages
>   mt76: usb: use a linear buffer for tx/rx datapath if sg is not
>     supported
>   mt76: usb: introduce disable_usb_sg parameter
> 
>  drivers/net/wireless/mediatek/mt76/mt76.h     |  14 +-
>  .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   2 +-
>  .../wireless/mediatek/mt76/mt76x02_usb_mcu.c  |   3 +-
>  .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
>  drivers/net/wireless/mediatek/mt76/usb.c      | 133 +++++++++++++-----
>  drivers/net/wireless/mediatek/mt76/usb_mcu.c  |   5 +-
>  6 files changed, 105 insertions(+), 54 deletions(-)

I really think my approach is simpler. Diffstat from my proposed patch is:

  drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
  drivers/net/wireless/mediatek/mt76/usb.c  | 55 ++++++++++++++---------
  2 files changed, 36 insertions(+), 20 deletions(-)

Also this fix bug(s), presumably regression for mt76x0, should be
backported.

Stanislaw


^ permalink raw reply

* [PATCH] ath10k: Enable support for beacon interval per VAP
From: Dundi Raviteja @ 2019-02-12 13:48 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Dundi Raviteja

Enable support to configure different beacon interval per VAP.

To support this feature, map different beacon interval service bit
to wmi tlv service.

Tested HW: WCN3990
Tested FW: WLAN.HL.2.0-01188-QCAHLSWMTPLZ-1

Signed-off-by: Dundi Raviteja <dundi@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/mac.c     | 33 +++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/wmi-tlv.h |  3 +++
 2 files changed, 36 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e49b367..09c4705 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8232,6 +8232,30 @@ void ath10k_mac_destroy(struct ath10k *ar)
 	},
 };
 
+static struct
+ieee80211_iface_combination ath10k_tlv_qcs_bcn_int_if_comb[] = {
+	{
+		.limits = ath10k_tlv_if_limit,
+		.num_different_channels = 1,
+		.max_interfaces = 4,
+		.beacon_int_infra_match = true,
+		.beacon_int_min_gcd = 1,
+		.n_limits = ARRAY_SIZE(ath10k_tlv_if_limit),
+	},
+	{
+		.limits = ath10k_tlv_qcs_if_limit,
+		.num_different_channels = 2,
+		.max_interfaces = 4,
+		.n_limits = ARRAY_SIZE(ath10k_tlv_qcs_if_limit),
+	},
+	{
+		.limits = ath10k_tlv_if_limit_ibss,
+		.num_different_channels = 1,
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(ath10k_tlv_if_limit_ibss),
+	},
+};
+
 static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = {
 	{
 		.max = 1,
@@ -8642,6 +8666,15 @@ int ath10k_mac_register(struct ath10k *ar)
 				ath10k_tlv_qcs_if_comb;
 			ar->hw->wiphy->n_iface_combinations =
 				ARRAY_SIZE(ath10k_tlv_qcs_if_comb);
+
+			if (test_bit
+			    (WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+			    ar->wmi.svc_map)) {
+				ar->hw->wiphy->iface_combinations =
+						ath10k_tlv_qcs_bcn_int_if_comb;
+				ar->hw->wiphy->n_iface_combinations =
+				     ARRAY_SIZE(ath10k_tlv_qcs_bcn_int_if_comb);
+			}
 		} else {
 			ar->hw->wiphy->iface_combinations = ath10k_tlv_if_comb;
 			ar->hw->wiphy->n_iface_combinations =
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index e07e990..9f78502 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1567,6 +1567,9 @@ enum wmi_tlv_service {
 	SVCMAP(WMI_TLV_SERVICE_THERM_THROT,
 	       WMI_SERVICE_THERM_THROT,
 	       WMI_TLV_MAX_SERVICE);
+	SVCMAP(WMI_TLV_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+	       WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT,
+	       WMI_TLV_MAX_SERVICE);
 }
 
 #undef SVCMAP
-- 
1.9.1


^ permalink raw reply related

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Stanislaw Gruszka @ 2019-02-12 13:51 UTC (permalink / raw)
  To: lorenzo.bianconi; +Cc: nbd, linux-wireless
In-Reply-To: <20190212134550.GA12256@redhat.com>

(repost with corrected Lorenzo email)

On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > 
> > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > {tx,rx} datapath if the usb controller has sg data length constraints.
> > Moreover add disable_usb_sg module parameter in order to explicitly
> > disable scatter-gather. SG I/O is not supported by all host drivers and
> > some users have reported sg issues on AMD IOMMU.
> 
> Again. This is not right approach. SG issues should be fixed
> not workarounded.
> 
> > This series has been tested on AMD IOMMU cpus/motherboards and on rpi3+
> 
> > - rebased on top of 'fix multiple issues in mt76u error path'
> >   https://patchwork.kernel.org/cover/10804919/
> > 
> > Lorenzo Bianconi (4):
> >   mt76: usb: move mt76u_check_sg in usb.c
> >   mt76: usb: do not use sg buffers for mcu messages
> >   mt76: usb: use a linear buffer for tx/rx datapath if sg is not
> >     supported
> >   mt76: usb: introduce disable_usb_sg parameter
> > 
> >  drivers/net/wireless/mediatek/mt76/mt76.h     |  14 +-
> >  .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   2 +-
> >  .../wireless/mediatek/mt76/mt76x02_usb_mcu.c  |   3 +-
> >  .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
> >  drivers/net/wireless/mediatek/mt76/usb.c      | 133 +++++++++++++-----
> >  drivers/net/wireless/mediatek/mt76/usb_mcu.c  |   5 +-
> >  6 files changed, 105 insertions(+), 54 deletions(-)
> 
> I really think my approach is simpler. Diffstat from my proposed patch is:
> 
>   drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
>   drivers/net/wireless/mediatek/mt76/usb.c  | 55 ++++++++++++++---------
>   2 files changed, 36 insertions(+), 20 deletions(-)
> 
> Also this fix bug(s), presumably regression for mt76x0, should be
> backported.
> 
> Stanislaw
> 

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Lorenzo Bianconi @ 2019-02-12 14:09 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212135100.GA15292@redhat.com>

>
> (repost with corrected Lorenzo email)
>
> On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> > On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > >
> > > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > > {tx,rx} datapath if the usb controller has sg data length constraints.
> > > Moreover add disable_usb_sg module parameter in order to explicitly
> > > disable scatter-gather. SG I/O is not supported by all host drivers and
> > > some users have reported sg issues on AMD IOMMU.
> >
> > Again. This is not right approach. SG issues should be fixed
> > not workarounded.

Hi Stanislaw,

here we do not use SG, so num_sg is 0 and we use transfer_buffer. I do
not see how I am working around the issue.
Moreover with this approach we avoid some unnecessary operation in the hotpath

Regards,
Lorenzo

> >
> > > This series has been tested on AMD IOMMU cpus/motherboards and on rpi3+
> >
> > > - rebased on top of 'fix multiple issues in mt76u error path'
> > >   https://patchwork.kernel.org/cover/10804919/
> > >
> > > Lorenzo Bianconi (4):
> > >   mt76: usb: move mt76u_check_sg in usb.c
> > >   mt76: usb: do not use sg buffers for mcu messages
> > >   mt76: usb: use a linear buffer for tx/rx datapath if sg is not
> > >     supported
> > >   mt76: usb: introduce disable_usb_sg parameter
> > >
> > >  drivers/net/wireless/mediatek/mt76/mt76.h     |  14 +-
> > >  .../net/wireless/mediatek/mt76/mt76x0/usb.c   |   2 +-
> > >  .../wireless/mediatek/mt76/mt76x02_usb_mcu.c  |   3 +-
> > >  .../wireless/mediatek/mt76/mt76x2/usb_init.c  |   2 +-
> > >  drivers/net/wireless/mediatek/mt76/usb.c      | 133 +++++++++++++-----
> > >  drivers/net/wireless/mediatek/mt76/usb_mcu.c  |   5 +-
> > >  6 files changed, 105 insertions(+), 54 deletions(-)
> >
> > I really think my approach is simpler. Diffstat from my proposed patch is:
> >
> >   drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
> >   drivers/net/wireless/mediatek/mt76/usb.c  | 55 ++++++++++++++---------
> >   2 files changed, 36 insertions(+), 20 deletions(-)
> >
> > Also this fix bug(s), presumably regression for mt76x0, should be
> > backported.
> >
> > Stanislaw
> >

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Stanislaw Gruszka @ 2019-02-12 14:17 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <CAJ0CqmVhH61P1V1fmhicPXwA7vHjv+Hh7h2DYbci1uDRJCyENA@mail.gmail.com>

On Tue, Feb 12, 2019 at 03:09:53PM +0100, Lorenzo Bianconi wrote:
> >
> > (repost with corrected Lorenzo email)
> >
> > On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> > > On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > > > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > > >
> > > > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > > > {tx,rx} datapath if the usb controller has sg data length constraints.
> > > > Moreover add disable_usb_sg module parameter in order to explicitly
> > > > disable scatter-gather. SG I/O is not supported by all host drivers and
> > > > some users have reported sg issues on AMD IOMMU.
> > >
> > > Again. This is not right approach. SG issues should be fixed
> > > not workarounded.
> 
> Hi Stanislaw,
> 
> here we do not use SG, so num_sg is 0 and we use transfer_buffer. I do
> not see how I am working around the issue.

By avoiding SG buffer allocation and configuration which most likely
need to be fixed.

> Moreover with this approach we avoid some unnecessary operation in the hotpath

What unnecessary operation ?

Stanislaw

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Lorenzo Bianconi @ 2019-02-12 14:25 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212141725.GD12906@redhat.com>

> On Tue, Feb 12, 2019 at 03:09:53PM +0100, Lorenzo Bianconi wrote:
> > >
> > > (repost with corrected Lorenzo email)
> > >
> > > On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> > > > On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > > > > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > >
> > > > > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > > > > {tx,rx} datapath if the usb controller has sg data length constraints.
> > > > > Moreover add disable_usb_sg module parameter in order to explicitly
> > > > > disable scatter-gather. SG I/O is not supported by all host drivers and
> > > > > some users have reported sg issues on AMD IOMMU.
> > > >
> > > > Again. This is not right approach. SG issues should be fixed
> > > > not workarounded.
> > 
> > Hi Stanislaw,
> > 
> > here we do not use SG, so num_sg is 0 and we use transfer_buffer. I do
> > not see how I am working around the issue.
> 
> By avoiding SG buffer allocation and configuration which most likely
> need to be fixed.

In my series I:
1- set num_sg to 0
2- use transfer_buffer

please correct me if I am wrong but in your solution you did the same since AFAIK
PageHighMem is always 0 so you end up setting num_sg to 0 and using
transfer_buffer as well. Is my understanding correct?

> 
> > Moreover with this approach we avoid some unnecessary operation in the hotpath
> 
> What unnecessary operation ?

the ones in mt76u_fill_bulk_urb()

Regards,
Lorenzo

> 
> Stanislaw

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Stanislaw Gruszka @ 2019-02-12 14:54 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212142528.GB24197@localhost.localdomain>

On Tue, Feb 12, 2019 at 03:25:30PM +0100, Lorenzo Bianconi wrote:
> > On Tue, Feb 12, 2019 at 03:09:53PM +0100, Lorenzo Bianconi wrote:
> > > >
> > > > (repost with corrected Lorenzo email)
> > > >
> > > > On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> > > > > On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > > > > > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > >
> > > > > > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > > > > > {tx,rx} datapath if the usb controller has sg data length constraints.
> > > > > > Moreover add disable_usb_sg module parameter in order to explicitly
> > > > > > disable scatter-gather. SG I/O is not supported by all host drivers and
> > > > > > some users have reported sg issues on AMD IOMMU.
> > > > >
> > > > > Again. This is not right approach. SG issues should be fixed
> > > > > not workarounded.
> > > 
> > > Hi Stanislaw,
> > > 
> > > here we do not use SG, so num_sg is 0 and we use transfer_buffer. I do
> > > not see how I am working around the issue.
> > 
> > By avoiding SG buffer allocation and configuration which most likely
> > need to be fixed.
> 
> In my series I:
> 1- set num_sg to 0
> 2- use transfer_buffer
>
> please correct me if I am wrong but in your solution you did the same since AFAIK
> PageHighMem is always 0 so you end up setting num_sg to 0 and using
> transfer_buffer as well. Is my understanding correct?

Yes. But it still using all existing SG allocation and setup code and
buffer is tracked in urb->sg[0].

> > > Moreover with this approach we avoid some unnecessary operation in the hotpath
> > 
> > What unnecessary operation ?
> 
> the ones in mt76u_fill_bulk_urb()

Your patches also add extra operations on hotpath due to urb->num_sgs and
dev->usb.sg_en checks.

Stanislaw

^ permalink raw reply

* Re: [PATCH v2 2/3] rt2x00: check number of EPROTO errors
From: Stanislaw Gruszka @ 2019-02-12 15:02 UTC (permalink / raw)
  To: Jeroen Roovers
  Cc: Tom Psyborg, linux-wireless, Randy Oostdyk, Daniel Golle,
	Felix Fietkau, Mathias Kresin
In-Reply-To: <CANCHnQrb57bUCj_kftD+5_gRZFeruFxaXWR8B_feEcpyF-6rVw@mail.gmail.com>

On Tue, Jan 22, 2019 at 06:32:05PM +0100, Jeroen Roovers wrote:
> > then triggered a kernel panic. Sadly I couldn't capture it in time but
> > I did spot that more phyN (up to phy4) devices had been added.
> 
> Yes, even when some rt2x00usb_vendor_request starts to fail but keeps
> on trying, the WLAN modules remain unrecoverable except by removing
> power, so the 10 retries are usually not reached and the device is
> never removed. Could it be that some operations do succeed, perhaps
> because the MCU was reset and is now capable of responding to some
> "vendor requests" but not others?
> 
> Checking for num_proto_errs > 1 would then make as much sense as
> num_proto_errs > 10 when running an AP. Maybe it's different for an
> STA?

Does it make sense to do num_proto_err > 3 check. Would that
be helpful on your problem with rt2800usb device? I don't want
make num_proto_err > 1 since this will remove device just after
2 errors.

Also have you tested tx_power patch with lowering txpower ?
Did it improve things ?

Stanislaw

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Lorenzo Bianconi @ 2019-02-12 15:08 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212145424.GE12906@redhat.com>

> On Tue, Feb 12, 2019 at 03:25:30PM +0100, Lorenzo Bianconi wrote:
> > > On Tue, Feb 12, 2019 at 03:09:53PM +0100, Lorenzo Bianconi wrote:
> > > > >
> > > > > (repost with corrected Lorenzo email)
> > > > >
> > > > > On Tue, Feb 12, 2019 at 02:45:50PM +0100, Stanislaw Gruszka wrote:
> > > > > > On Tue, Feb 12, 2019 at 02:24:47PM +0100, LorenzoBianconilorenzo@kernel.org wrote:
> > > > > > > From: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > > >
> > > > > > > Use linear fragment and not a single usb scatter-gather buffer in mt76u
> > > > > > > {tx,rx} datapath if the usb controller has sg data length constraints.
> > > > > > > Moreover add disable_usb_sg module parameter in order to explicitly
> > > > > > > disable scatter-gather. SG I/O is not supported by all host drivers and
> > > > > > > some users have reported sg issues on AMD IOMMU.
> > > > > >
> > > > > > Again. This is not right approach. SG issues should be fixed
> > > > > > not workarounded.
> > > > 
> > > > Hi Stanislaw,
> > > > 
> > > > here we do not use SG, so num_sg is 0 and we use transfer_buffer. I do
> > > > not see how I am working around the issue.
> > > 
> > > By avoiding SG buffer allocation and configuration which most likely
> > > need to be fixed.
> > 
> > In my series I:
> > 1- set num_sg to 0
> > 2- use transfer_buffer
> >
> > please correct me if I am wrong but in your solution you did the same since AFAIK
> > PageHighMem is always 0 so you end up setting num_sg to 0 and using
> > transfer_buffer as well. Is my understanding correct?
> 
> Yes. But it still using all existing SG allocation and setup code and
> buffer is tracked in urb->sg[0].

both of them are from page_frag_alloc()

> 
> > > > Moreover with this approach we avoid some unnecessary operation in the hotpath
> > > 
> > > What unnecessary operation ?
> > 
> > the ones in mt76u_fill_bulk_urb()
> 
> Your patches also add extra operations on hotpath due to urb->num_sgs and
> dev->usb.sg_en checks.

here I guess you should use mt76u_check_sg() instead of
udev->bus->sg_tablesize > 0 so I think you need to precompute it since it is in
the hotpath

Moreover the RFC series has been tested by multiple users and on multiple
devices

Regards,
Lorenzo

> 
> Stanislaw

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Stanislaw Gruszka @ 2019-02-12 15:26 UTC (permalink / raw)
  To: Lorenzo Bianconi; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212150836.GA10823@localhost.localdomain>

On Tue, Feb 12, 2019 at 04:08:37PM +0100, Lorenzo Bianconi wrote:
> > > > What unnecessary operation ?
> > > 
> > > the ones in mt76u_fill_bulk_urb()
> > 
> > Your patches also add extra operations on hotpath due to urb->num_sgs and
> > dev->usb.sg_en checks.
> 
> here I guess you should use mt76u_check_sg() instead of
> udev->bus->sg_tablesize > 0 so I think you need to precompute it since it is in
> the hotpath

It's not necessary. If udev->bus->sg_tablesize > 0 is true and rest
of mt76u_check_sg() is not, we will submit urb with urb->num_sgs = 1 to
usb host driver, what is fine. 

> Moreover the RFC series has been tested by multiple users and on multiple
> devices

I know. Perhaps you could test my patch on rpi ?

Stanislaw 



^ permalink raw reply

* Re: [BUG] mt76x0u: Probing issues on Raspberry Pi 3 B+
From: Alan Stern @ 2019-02-12 15:27 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Stanislaw Gruszka, Stefan Wahren, Felix Fietkau, Doug Anderson,
	Minas Harutyunyan, USB list, linux-wireless
In-Reply-To: <CAJ0CqmVFVBXi5E07-ZsYojC7mP4ogpwbcDkDTeebHwX+ayz2DQ@mail.gmail.com>

On Tue, 12 Feb 2019, Lorenzo Bianconi wrote:

> Hi Alan,
> 
> I actually used usb_sg_init()/usb_sg_wait() as reference to implement
> mt76u {tx/rx} datapath, but I will double-check.
> I guess we should even consider if there are other usb host drivers
> that do not implement SG I/O and it is worth to support.
> I am wondering if the right approach is to add SG to the controller
> one by one or have legacy I/O in mt76 (not sure what is the 'best'
> approach)
> What do you think?

If mt76u can use usb_sg_init/usb_sg_wait, that would be the simplest.  
It would allow you to remove a lot of code from the driver.  And then
adding SG support to the controller drivers one by one would be fine.

However, if that isn't feasible then you have to keep legacy I/O in 
mt76u as long as any controller drivers don't support SG.

Alan Stern


^ permalink raw reply

* [PATCH] mt76: Use the correct hweight8() function
From: Ben Hutchings @ 2019-02-12 15:36 UTC (permalink / raw)
  To: Felix Fietkau, Lorenzo Bianconi; +Cc: linux-wireless

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

mt76_init_stream_cap() and mt76_get_txpower() call __sw_hweight8()
directly, but that's only defined if CONFIG_GENERIC_HWEIGHT is
enabled.  The function that works on all architectures is hweight8().

Fixes: 551e1ef4d291 ("mt76: add mt76_init_stream_cap routine")
Fixes: 9313faacbb4e ("mt76: move mt76x02_get_txpower to mt76 core")
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 drivers/net/wireless/mediatek/mt76/mac80211.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 484d3ac3a206..7c3a24cc9c77 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -124,7 +124,7 @@ static void mt76_init_stream_cap(struct mt76_dev *dev,
 				 bool vht)
 {
 	struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
-	int i, nstream = __sw_hweight8(dev->antenna_mask);
+	int i, nstream = hweight8(dev->antenna_mask);
 	struct ieee80211_sta_vht_cap *vht_cap;
 	u16 mcs_map = 0;
 
@@ -714,7 +714,7 @@ int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		     int *dbm)
 {
 	struct mt76_dev *dev = hw->priv;
-	int n_chains = __sw_hweight8(dev->antenna_mask);
+	int n_chains = hweight8(dev->antenna_mask);
 
 	*dbm = dev->txpower_cur / 2;
 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply related

* Re: RTL8723bu: poor signal and connection troubles
From: Chris Chiu @ 2019-02-12 15:38 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Jes Sorensen, Barry Day, kvalo, linux-wireless, mylene.josserand,
	Linux Upstreaming Team
In-Reply-To: <CAB4CAwd2WtWwf9p=kZZQ-SzE6DhsLu1OpGaVyS1Mq8wx8eT6ww@mail.gmail.com>

On Tue, Jan 29, 2019 at 5:56 PM Chris Chiu <chiu@endlessm.com> wrote:
>
> On Mon, Jan 22, 2018 at 6:56 AM Carlo Caione <carlo@endlessm.com> wrote:
> >
> > On Sun, Jan 21, 2018 at 9:46 PM, Jes Sorensen <jes.sorensen@gmail.com> wrote:
> > > On 01/11/2018 05:30 AM, Barry Day wrote:
> >
> > > One issue with rtl8723bu is that it needs to coexist with the bluetooth
> > > driver. When I wrote the rtl8723bu support that was no BT support for
> > > the chip in the kernel and it worked fine, at least for me. However if
> > > you load the BT driver for the dongle which someone pushed into the
> > > kernel since then, it is likely to hijack the antennas causing the weak
> > > signal you describe.
> >
> > Yeah, that's why when testing the dongle I carefully disabled BT and
> > made sure no BT driver was probed at all. Still I can see the issue.
> > I honestly doubt that the problem is caused by BT coexistence. Any
> > other idea or suggestion to debug this problem?
> >
> > Thanks,
> >
> > --
> > Carlo Caione  |  +44.7384.69.16.04  |  Endless
>
> This problem has been reported for 1 year, but it still persists now.
>
> I found that the problem disappeared after I resume from suspend. Before
> suspend, the rssi observed from AP side for this dongle is quite poor. But
> it comes back to normal after resume. The signal strength differs almost
> 30dBm. So I compared/checked the RF/BB related register values
> (in .init_phy_bb/.init_phy_rf/.set_tx_power) but they are identical with the
> same routines in the driver from https://github.com/lwfinger/rtl8723bu
>
> The registers also remain the same across suspend/resume. Don't really
> know why a simple suspend/resume could cause such difference. Can
> anyone suggest which part I should look into to get more information?
>
> Chris

I found one thing interesting. It does seem to be related to BT coexist just
as Jes mentioned. Follow the steps below and the signal can always come
back to normal. The '1-7:1.0' is one of the IDs for the rtl8723bu usb interface.

1. unbind btusb first, cd /sys/bus/usb/drivers/btusb; echo 1-7:1.0 > unbind
2. unload rtl8xxxu driver then reload it. The signal stays at poor level
3. bind the btusb. cd /sys/bus/usb/drivers/btusb; echo 1-7:1.0 > bind

Seems that the BT firmware loaded is helpful for the only antenna config
which is shared by WiFi/BT. If I load the BT firmware after rtl8xxxu driver,
everything's fine.

Can anyone suggest the next step? I've compared all registers and h2c cmds
between vendor driver and rtl8xxxu driver. Basically, they're almost the same
even the bt coexist related settings. So it's difficult to imagine why the same
power on sequence setting and RF enable setting cause that huge signal
difference.

Chris

^ permalink raw reply

* Re: [PATCH 0/4] do not use sg if not properly supported by usb controller
From: Lorenzo Bianconi @ 2019-02-12 15:50 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: Felix Fietkau, linux-wireless, lorenzo
In-Reply-To: <20190212152559.GB23126@redhat.com>

> On Tue, Feb 12, 2019 at 04:08:37PM +0100, Lorenzo Bianconi wrote:
> > > > > What unnecessary operation ?
> > > > 
> > > > the ones in mt76u_fill_bulk_urb()
> > > 
> > > Your patches also add extra operations on hotpath due to urb->num_sgs and
> > > dev->usb.sg_en checks.
> > 
> > here I guess you should use mt76u_check_sg() instead of
> > udev->bus->sg_tablesize > 0 so I think you need to precompute it since it is in
> > the hotpath
> 
> It's not necessary. If udev->bus->sg_tablesize > 0 is true and rest
> of mt76u_check_sg() is not, we will submit urb with urb->num_sgs = 1 to
> usb host driver, what is fine. 
> 
> > Moreover the RFC series has been tested by multiple users and on multiple
> > devices
> 
> I know. Perhaps you could test my patch on rpi ?

sure, I will do it later

Regards,
Lorenzo

> 
> Stanislaw 
> 
> 

^ permalink raw reply

* Re: pull-request: mac80211 2019-02-12
From: David Miller @ 2019-02-12 16:43 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20190212115121.27086-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Tue, 12 Feb 2019 12:51:20 +0100

> We have few more fixes, mostly one-liners; two are bigger:
>  * the speculation one, only because the function had multiple
>    return points and that had to change, and
>  * the peer measurement locking one, because I had to refactor
>    a function to be able to call it with or without locking
>    (depending on context).
> 
> Please pull and let me know if there's any problem.

Pulled, thanks Johannes.

^ 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