Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH v4] rtw88: pci: Move a mass of jobs in hw IRQ to soft IRQ
From: Kalle Valo @ 2019-09-02 12:18 UTC (permalink / raw)
  To: Tony Chuang
  Cc: Jian-Hong Pan, David S . Miller, linux-wireless@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux@endlessm.com
In-Reply-To: <F7CD281DE3E379468C6D07993EA72F84D18AE2DA@RTITMBSVM04.realtek.com.tw>

Tony Chuang <yhchuang@realtek.com> writes:

>> From: Jian-Hong Pan 
>> Subject: [PATCH v4] rtw88: pci: Move a mass of jobs in hw IRQ to soft IRQ
>> 
>> There is a mass of jobs between spin lock and unlock in the hardware
>> IRQ which will occupy much time originally. To make system work more
>> efficiently, this patch moves the jobs to the soft IRQ (bottom half) to
>> reduce the time in hardware IRQ.
>> 
>> Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com>
>
> Now it works fine with MSI interrupt enabled.
>
> But this patch is conflicting with MSI interrupt patch.
> Is there a better way we can make Kalle apply them more smoothly?
> I can rebase them and submit both if you're OK.

Yeah, submitting all the MSI patches in the same patchset is the easiest
approach. That way they apply cleanly to wireless-drivers-next.

-- 
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

^ permalink raw reply

* Re: [PATCH v3] rtw88: pci: enable MSI interrupt
From: Daniel Drake @ 2019-09-02 10:34 UTC (permalink / raw)
  To: Tony Chuang
  Cc: Kalle Valo, linux-wireless, Ján Veselý,
	Linux Upstreaming Team, Brian Norris, gojun077
In-Reply-To: <1567407757-26951-1-git-send-email-yhchuang@realtek.com>

On Mon, Sep 2, 2019 at 3:02 PM <yhchuang@realtek.com> wrote:
> From: Yu-Yen Ting <steventing@realtek.com>
>
> MSI interrupt should be enabled on certain platform.
>
> Add a module parameter disable_msi to disable MSI interrupt,
> driver will then use legacy interrupt instead.
>
> One could rebind the PCI device, probe() will pick up the
> new value of the module parameter. Such as:
>
>     echo '0000:01:00.0' > /sys/bus/pci/drivers/rtw_pci/unbind
>     echo '0000:01:00.0' > /sys/bus/pci/drivers/rtw_pci/bind
>
> Tested-by: Ján Veselý <jano.vesely@gmail.com>
> Reviewed-by: Brian Norris <briannorris@chromium.org>
Reviewed-by: Daniel Drake <drake@endlessm.com>
> Signed-off-by: Yu-Yen Ting <steventing@realtek.com>
> Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>

^ permalink raw reply

* [PATCH v4 8/8] ath10k: enable napi on RX path for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

For tcp RX, the quantity of tcp acks to remote is 1/2 of the quantity
of tcp data from remote, then it will have many small length packets
on TX path of sdio bus, then it reduce the RX packets's bandwidth of
tcp.

This patch enable napi on RX path, then the RX packet of tcp will not
feed to tcp stack immeditely from mac80211 since GRO is enabled by
default, it will feed to tcp stack after napi complete, if rx bundle
is enabled, then it will feed to tcp stack one time for each bundle
of RX. For example, RX bundle size is 32, then tcp stack will receive
one large length packet, its length is neary 1500*32, then tcp stack
will send a tcp ack for this large packet, this will reduce the tcp
acks ratio from 1/2 to 1/32. This results in significant performance
improvement for tcp RX.

Tcp rx throughout is 240Mbps without this patch, and it arrive 390Mbps
with this patch. The cpu usage has no obvious difference with and
without NAPI.

call stack for each RX packet on GRO path:
(skb length is about 1500 bytes)
  skb_gro_receive ([kernel.kallsyms])
  tcp4_gro_receive ([kernel.kallsyms])
  inet_gro_receive ([kernel.kallsyms])
  dev_gro_receive ([kernel.kallsyms])
  napi_gro_receive ([kernel.kallsyms])
  ieee80211_deliver_skb ([mac80211])
  ieee80211_rx_handlers ([mac80211])
  ieee80211_prepare_and_rx_handle ([mac80211])
  ieee80211_rx_napi ([mac80211])
  ath10k_htt_rx_proc_rx_ind_hl ([ath10k_core])
  ath10k_htt_rx_pktlog_completion_handler ([ath10k_core])
  ath10k_sdio_napi_poll ([ath10k_sdio])
  net_rx_action ([kernel.kallsyms])
  softirqentry_text_start ([kernel.kallsyms])
  do_softirq ([kernel.kallsyms])

call stack for napi complete and send tcp ack from tcp stack:
(skb length is about 1500*32 bytes)
 _tcp_ack_snd_check ([kernel.kallsyms])
 tcp_v4_do_rcv ([kernel.kallsyms])
 tcp_v4_rcv ([kernel.kallsyms])
 local_deliver_finish ([kernel.kallsyms])
 ip_local_deliver ([kernel.kallsyms])
 ip_rcv_finish ([kernel.kallsyms])
 ip_rcv ([kernel.kallsyms])
 netif_receive_skb_core ([kernel.kallsyms])
 netif_receive_skb_one_core([kernel.kallsyms])
 netif_receive_skb ([kernel.kallsyms])
 netif_receive_skb_internal ([kernel.kallsyms])
 napi_gro_complete ([kernel.kallsyms])
 napi_gro_flush ([kernel.kallsyms])
 napi_complete_done ([kernel.kallsyms])
 ath10k_sdio_napi_poll ([ath10k_sdio])
 net_rx_action ([kernel.kallsyms])
 __softirqentry_text_start ([kernel.kallsyms])
 do_softirq ([kernel.kallsyms])

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: no change
v3: change some code style
v4: change some code style
 drivers/net/wireless/ath/ath10k/htt.c    |  2 ++
 drivers/net/wireless/ath/ath10k/htt.h    |  3 +++
 drivers/net/wireless/ath/ath10k/htt_rx.c | 45 ++++++++++++++++++++++++++------
 drivers/net/wireless/ath/ath10k/sdio.c   | 33 +++++++++++++++++++++++
 4 files changed, 75 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 127b4e4..f69346f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -157,6 +157,8 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
 
 	htt->eid = conn_resp.eid;
 
+	skb_queue_head_init(&htt->rx_indication_head);
+
 	if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
 		ep = &ar->htc.endpoint[htt->eid];
 		ath10k_htc_setup_tx_req(ep);
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 4851a2e..462a25b 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1879,6 +1879,8 @@ struct ath10k_htt {
 	struct ath10k *ar;
 	enum ath10k_htc_ep_id eid;
 
+	struct sk_buff_head rx_indication_head;
+
 	u8 target_version_major;
 	u8 target_version_minor;
 	struct completion target_version_received;
@@ -2298,6 +2300,7 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
 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);
+int ath10k_htt_rx_hl_indication(struct ath10k *ar, int budget);
 void ath10k_htt_set_tx_ops(struct ath10k_htt *htt);
 void ath10k_htt_set_rx_ops(struct ath10k_htt *htt);
 #endif
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 09825b1..07b6351 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2263,7 +2263,7 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
 	if (mpdu_ranges->mpdu_range_status == HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR)
 		rx_status->flag |= RX_FLAG_MMIC_ERROR;
 
-	ieee80211_rx_ni(ar->hw, skb);
+	ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
 
 	/* We have delivered the skb to the upper layers (mac80211) so we
 	 * must not free it.
@@ -3664,14 +3664,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		break;
 	}
 	case HTT_T2H_MSG_TYPE_RX_IND:
-		if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
-			return ath10k_htt_rx_proc_rx_ind_hl(htt,
-							    &resp->rx_ind_hl,
-							    skb,
-							    HTT_RX_PN_CHECK,
-							    HTT_RX_NON_TKIP_MIC);
-		else
+		if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) {
 			ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);
+		} else {
+			skb_queue_tail(&htt->rx_indication_head, skb);
+			return false;
+		}
 		break;
 	case HTT_T2H_MSG_TYPE_PEER_MAP: {
 		struct htt_peer_map_event ev = {
@@ -3894,6 +3892,37 @@ static int ath10k_htt_rx_deliver_msdu(struct ath10k *ar, int quota, int budget)
 	return quota;
 }
 
+int ath10k_htt_rx_hl_indication(struct ath10k *ar, int budget)
+{
+	struct htt_resp *resp;
+	struct ath10k_htt *htt = &ar->htt;
+	struct sk_buff *skb;
+	bool release;
+	int quota;
+
+	for (quota = 0; quota < budget; quota++) {
+		skb = skb_dequeue(&htt->rx_indication_head);
+		if (!skb)
+			break;
+
+		resp = (struct htt_resp *)skb->data;
+
+		release = ath10k_htt_rx_proc_rx_ind_hl(htt,
+						       &resp->rx_ind_hl,
+						       skb,
+						       HTT_RX_PN_CHECK,
+						       HTT_RX_NON_TKIP_MIC);
+
+		if (release)
+			dev_kfree_skb_any(skb);
+
+		ath10k_dbg(ar, ATH10K_DBG_HTT, "rx indication poll pending count:%d\n",
+			   skb_queue_len(&htt->rx_indication_head));
+	}
+	return quota;
+}
+EXPORT_SYMBOL(ath10k_htt_rx_hl_indication);
+
 int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
 {
 	struct ath10k_htt *htt = &ar->htt;
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index e01ab63..7432d1c 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1402,6 +1402,9 @@ static void ath10k_rx_indication_async_work(struct work_struct *work)
 		spin_lock_bh(&ar_sdio->wr_async_lock_rx);
 	}
 
+	if (test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
+		napi_schedule(&ar->napi);
+
 	spin_unlock_bh(&ar_sdio->wr_async_lock_rx);
 }
 
@@ -1815,6 +1818,8 @@ static int ath10k_sdio_hif_start(struct ath10k *ar)
 	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
 	int ret;
 
+	napi_enable(&ar->napi);
+
 	/* Sleep 20 ms before HIF interrupts are disabled.
 	 * This will give target plenty of time to process the BMI done
 	 * request before interrupts are disabled.
@@ -1953,6 +1958,9 @@ static void ath10k_sdio_hif_stop(struct ath10k *ar)
 	}
 
 	spin_unlock_bh(&ar_sdio->wr_async_lock);
+
+	napi_synchronize(&ar->napi);
+	napi_disable(&ar->napi);
 }
 
 #ifdef CONFIG_PM
@@ -2129,6 +2137,26 @@ static SIMPLE_DEV_PM_OPS(ath10k_sdio_pm_ops, ath10k_sdio_pm_suspend,
 
 #endif /* CONFIG_PM_SLEEP */
 
+static int ath10k_sdio_napi_poll(struct napi_struct *ctx, int budget)
+{
+	struct ath10k *ar = container_of(ctx, struct ath10k, napi);
+	int done;
+
+	done = ath10k_htt_rx_hl_indication(ar, budget);
+	ath10k_dbg(ar, ATH10K_DBG_SDIO, "napi poll: done: %d, budget:%d\n", done, budget);
+
+	if (done < budget)
+		napi_complete_done(ctx, done);
+
+	return done;
+}
+
+void ath10k_sdio_init_napi(struct ath10k *ar)
+{
+	netif_napi_add(&ar->napi_dev, &ar->napi, ath10k_sdio_napi_poll,
+		       ATH10K_NAPI_BUDGET);
+}
+
 static int ath10k_sdio_probe(struct sdio_func *func,
 			     const struct sdio_device_id *id)
 {
@@ -2154,6 +2182,8 @@ static int ath10k_sdio_probe(struct sdio_func *func,
 		return -ENOMEM;
 	}
 
+	ath10k_sdio_init_napi(ar);
+
 	ath10k_dbg(ar, ATH10K_DBG_BOOT,
 		   "sdio new func %d vendor 0x%x device 0x%x block 0x%x/0x%x\n",
 		   func->num, func->vendor, func->device,
@@ -2274,6 +2304,9 @@ static void ath10k_sdio_remove(struct sdio_func *func)
 		   func->num, func->vendor, func->device);
 
 	ath10k_core_unregister(ar);
+
+	netif_napi_del(&ar->napi);
+
 	ath10k_core_destroy(ar);
 
 	flush_workqueue(ar_sdio->workqueue);
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 7/8] ath10k: enable alt data of TX path for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

The default credit size is 1792 bytes, but the IP mtu is 1500 bytes,
then it has about 290 bytes's waste for each data packet on sdio
transfer path for TX bundle, it will reduce the transmission utilization
ratio for data packet.

This patch enable the small credit size in firmware, firmware will use
the new credit size 1556 bytes, it will increase the transmission
utilization ratio for data packet on TX patch. It results in significant
performance improvement on TX path.

This patch only effect sdio chip, it will not effect PCI, SNOC etc.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00017-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: no change
v3: change some code style
v4: add macro ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK
 drivers/net/wireless/ath/ath10k/core.c | 19 +++++++++++++++++--
 drivers/net/wireless/ath/ath10k/htc.c  | 12 ++++++++++--
 drivers/net/wireless/ath/ath10k/htc.h  | 13 +++++++++++--
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 9841533..9fd07c7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -31,6 +31,7 @@
 static unsigned int ath10k_cryptmode_param;
 static bool uart_print;
 static bool disable_tx_comp = true;
+static bool alt_data = true;
 static bool skip_otp;
 static bool rawmode;
 static bool fw_diag_log;
@@ -45,6 +46,15 @@
 
 /* If upper layer need the TX complete status, it can enable tx complete */
 module_param(disable_tx_comp, bool, 0644);
+
+/* alt_data is only used for sdio chip, for previous version of firmware, its
+ * alt data size is 1544 which is not enough for native wifi, so it need to
+ * alt_data for the firmware.
+ * If the firmware has changed alt data size to 1556, then it can enable
+ * alt_data for the firmware.
+ * alt_data will not effect PCI, SNOC etc.
+ */
+module_param(alt_data, bool, 0644);
 module_param(skip_otp, bool, 0644);
 module_param(rawmode, bool, 0644);
 module_param(fw_diag_log, bool, 0644);
@@ -698,9 +708,14 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
 		param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
 
 	/* Alternate credit size of 1544 as used by SDIO firmware is
-	 * not big enough for mac80211 / native wifi frames. disable it
+	 * not big enough for mac80211 / native wifi frames. disable it.
+	 * If alternate credit size of 1556 as used by SDIO firmware is
+	 * big enough for mac80211 / native wifi frames. enable it
 	 */
-	param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
+	if (alt_data && mode == ATH10K_FIRMWARE_MODE_NORMAL)
+		param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
+	else
+		param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE;
 
 	if (mode == ATH10K_FIRMWARE_MODE_UTF)
 		param &= ~HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 5269168..ace0fec 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -940,12 +940,16 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 	 */
 	if (htc->control_resp_len >=
 	    sizeof(msg->hdr) + sizeof(msg->ready_ext)) {
+		htc->alt_data_credit_size =
+			__le16_to_cpu(msg->ready_ext.reserved) &
+			ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK;
 		htc->max_msgs_per_htc_bundle =
 			min_t(u8, msg->ready_ext.max_msgs_per_htc_bundle,
 			      HTC_HOST_MAX_MSG_PER_RX_BUNDLE);
 		ath10k_dbg(ar, ATH10K_DBG_HTC,
-			   "Extended ready message. RX bundle size: %d\n",
-			   htc->max_msgs_per_htc_bundle);
+			   "Extended ready message. RX bundle size: %d, alt size:%d\n",
+			   htc->max_msgs_per_htc_bundle,
+			   htc->alt_data_credit_size);
 	}
 
 	INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work);
@@ -1097,6 +1101,10 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
 	ep->tx_credits = tx_alloc;
 	ep->tx_credit_size = htc->target_credit_size;
 
+	if (conn_req->service_id == ATH10K_HTC_SVC_ID_HTT_DATA_MSG &&
+	    htc->alt_data_credit_size != 0)
+		ep->tx_credit_size = htc->alt_data_credit_size;
+
 	/* copy all the callbacks */
 	ep->ep_ops = conn_req->ep_ops;
 
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index ec4957a..5c21ec7 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -109,6 +109,8 @@ enum ath10k_htc_conn_flags {
 #define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB  8
 };
 
+#define ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK 0xFFF
+
 enum ath10k_htc_conn_svc_status {
 	ATH10K_HTC_CONN_SVC_STATUS_SUCCESS      = 0,
 	ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND    = 1,
@@ -141,8 +143,14 @@ struct ath10k_htc_ready_extended {
 	struct ath10k_htc_ready base;
 	u8 htc_version; /* @enum ath10k_htc_version */
 	u8 max_msgs_per_htc_bundle;
-	u8 pad0;
-	u8 pad1;
+	union {
+		__le16 reserved;
+		struct {
+			u8 pad0;
+			u8 pad1;
+		} __packed;
+	} __packed;
+
 } __packed;
 
 struct ath10k_htc_conn_svc {
@@ -379,6 +387,7 @@ struct ath10k_htc {
 	int total_transmit_credits;
 	int target_credit_size;
 	u8 max_msgs_per_htc_bundle;
+	int alt_data_credit_size;
 };
 
 int ath10k_htc_init(struct ath10k *ar);
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 6/8] ath10k: add htt TX bundle for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

The transmission utilization ratio for sdio bus for small packet is
slow, because the space and time cost for sdio bus is same for large
length packet and small length packet. So the speed of data for large
length packet is higher than small length.

Test result of different length of data:

data packet(byte)   cost time(us)   calculated rate(Mbps)
      256               28                73
      512               33               124
     1024               35               234
     1792               45               318
    14336              168               682
    28672              333               688
    57344              660               695

This patch change the TX packet from single packet to a large length
bundle packet, max size is 32, it results in significant performance
improvement on TX path.

This patch only effect sdio chip, it will not effect PCI, SNOC etc.
It only enable bundle for sdio chip.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: no change
v3: change some code style
v4: no change
 drivers/net/wireless/ath/ath10k/core.c   |  14 +-
 drivers/net/wireless/ath/ath10k/core.h   |   4 +-
 drivers/net/wireless/ath/ath10k/htc.c    | 355 ++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/htc.h    |  21 +-
 drivers/net/wireless/ath/ath10k/htt.c    |   8 +
 drivers/net/wireless/ath/ath10k/htt.h    |   4 +
 drivers/net/wireless/ath/ath10k/htt_rx.c |   1 +
 drivers/net/wireless/ath/ath10k/htt_tx.c |   7 +-
 8 files changed, 377 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index d56dcbd..9841533 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -3195,6 +3195,11 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 	if (!ar->workqueue_aux)
 		goto err_free_wq;
 
+	ar->workqueue_tx_complete =
+		create_singlethread_workqueue("ath10k_tx_complete_wq");
+	if (!ar->workqueue_tx_complete)
+		goto err_free_aux_wq;
+
 	mutex_init(&ar->conf_mutex);
 	mutex_init(&ar->dump_mutex);
 	spin_lock_init(&ar->data_lock);
@@ -3220,7 +3225,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
 	ret = ath10k_coredump_create(ar);
 	if (ret)
-		goto err_free_aux_wq;
+		goto err_free_tx_complete;
 
 	ret = ath10k_debug_create(ar);
 	if (ret)
@@ -3230,12 +3235,12 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
 err_free_coredump:
 	ath10k_coredump_destroy(ar);
-
+err_free_tx_complete:
+	destroy_workqueue(ar->workqueue_tx_complete);
 err_free_aux_wq:
 	destroy_workqueue(ar->workqueue_aux);
 err_free_wq:
 	destroy_workqueue(ar->workqueue);
-
 err_free_mac:
 	ath10k_mac_destroy(ar);
 
@@ -3251,6 +3256,9 @@ void ath10k_core_destroy(struct ath10k *ar)
 	flush_workqueue(ar->workqueue_aux);
 	destroy_workqueue(ar->workqueue_aux);
 
+	flush_workqueue(ar->workqueue_tx_complete);
+	destroy_workqueue(ar->workqueue_tx_complete);
+
 	ath10k_debug_destroy(ar);
 	ath10k_coredump_destroy(ar);
 	ath10k_htt_tx_destroy(&ar->htt);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 4d7db07..be9eb37 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -1079,7 +1079,7 @@ struct ath10k {
 	struct workqueue_struct *workqueue;
 	/* Auxiliary workqueue */
 	struct workqueue_struct *workqueue_aux;
-
+	struct workqueue_struct *workqueue_tx_complete;
 	/* prevents concurrent FW reconfiguration */
 	struct mutex conf_mutex;
 
@@ -1120,6 +1120,8 @@ struct ath10k {
 
 	struct work_struct register_work;
 	struct work_struct restart_work;
+	struct work_struct bundle_tx_work;
+	struct work_struct tx_complete_work;
 
 	/* cycle count is reported twice for each visited channel during scan.
 	 * access protected by data_lock
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 4c6cdc2..5269168 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -51,10 +51,12 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
 				     struct sk_buff *skb)
 {
 	struct ath10k *ar = ep->htc->ar;
+	struct ath10k_htc_hdr *hdr;
 
 	ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %pK\n", __func__,
 		   ep->eid, skb);
 
+	hdr = (struct ath10k_htc_hdr *)skb->data;
 	ath10k_htc_restore_tx_skb(ep->htc, skb);
 
 	if (!ep->ep_ops.ep_tx_complete) {
@@ -63,6 +65,11 @@ void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
 		return;
 	}
 
+	if (hdr->flags & ATH10K_HTC_FLAG_SEND_BUNDLE) {
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
 	ep->ep_ops.ep_tx_complete(ep->htc->ar, skb);
 }
 EXPORT_SYMBOL(ath10k_htc_notify_tx_completion);
@@ -78,7 +85,7 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
 	hdr->eid = ep->eid;
 	hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr));
 	hdr->flags = 0;
-	if (ep->tx_credit_flow_enabled)
+	if (ep->tx_credit_flow_enabled && !ep->bundle_tx)
 		hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE;
 
 	spin_lock_bh(&ep->htc->tx_lock);
@@ -86,6 +93,64 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep,
 	spin_unlock_bh(&ep->htc->tx_lock);
 }
 
+static int ath10k_htc_consume_credit(struct ath10k_htc_ep *ep,
+				     unsigned int len,
+				     bool consume)
+{
+	int credits;
+	struct ath10k_htc *htc = ep->htc;
+	struct ath10k *ar = htc->ar;
+	enum ath10k_htc_ep_id eid = ep->eid;
+	int ret = 0;
+
+	if (!ep->tx_credit_flow_enabled)
+		return 0;
+
+	credits = DIV_ROUND_UP(len, ep->tx_credit_size);
+	spin_lock_bh(&htc->tx_lock);
+
+	if (ep->tx_credits < credits) {
+		ath10k_dbg(ar, ATH10K_DBG_HTC,
+			   "htc insufficient credits ep %d required %d available %d consume %d\n",
+			   eid, credits, ep->tx_credits, consume);
+		ret = -EAGAIN;
+		goto unlock;
+	}
+
+	if (consume) {
+		ep->tx_credits -= credits;
+		ath10k_dbg(ar, ATH10K_DBG_HTC,
+			   "htc ep %d consumed %d credits (total %d)\n",
+			   eid, credits, ep->tx_credits);
+	}
+
+unlock:
+	spin_unlock_bh(&htc->tx_lock);
+	return ret;
+}
+
+static void ath10k_htc_release_credit(struct ath10k_htc_ep *ep, unsigned int len)
+{
+	int credits;
+	struct ath10k_htc *htc = ep->htc;
+	struct ath10k *ar = htc->ar;
+	enum ath10k_htc_ep_id eid = ep->eid;
+
+	if (!ep->tx_credit_flow_enabled)
+		return;
+
+	credits = DIV_ROUND_UP(len, ep->tx_credit_size);
+	spin_lock_bh(&htc->tx_lock);
+	ep->tx_credits += credits;
+	ath10k_dbg(ar, ATH10K_DBG_HTC,
+		   "htc ep %d reverted %d credits back (total %d)\n",
+		   eid, credits, ep->tx_credits);
+	spin_unlock_bh(&htc->tx_lock);
+
+	if (ep->ep_ops.ep_tx_credits)
+		ep->ep_ops.ep_tx_credits(htc->ar);
+}
+
 int ath10k_htc_send(struct ath10k_htc *htc,
 		    enum ath10k_htc_ep_id eid,
 		    struct sk_buff *skb)
@@ -95,8 +160,8 @@ int ath10k_htc_send(struct ath10k_htc *htc,
 	struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
 	struct ath10k_hif_sg_item sg_item;
 	struct device *dev = htc->ar->dev;
-	int credits = 0;
 	int ret;
+	unsigned int skb_len;
 
 	if (htc->ar->state == ATH10K_STATE_WEDGED)
 		return -ECOMM;
@@ -108,23 +173,10 @@ int ath10k_htc_send(struct ath10k_htc *htc,
 
 	skb_push(skb, sizeof(struct ath10k_htc_hdr));
 
-	if (ep->tx_credit_flow_enabled) {
-		credits = DIV_ROUND_UP(skb->len, htc->target_credit_size);
-		spin_lock_bh(&htc->tx_lock);
-		if (ep->tx_credits < credits) {
-			ath10k_dbg(ar, ATH10K_DBG_HTC,
-				   "htc insufficient credits ep %d required %d available %d\n",
-				   eid, credits, ep->tx_credits);
-			spin_unlock_bh(&htc->tx_lock);
-			ret = -EAGAIN;
-			goto err_pull;
-		}
-		ep->tx_credits -= credits;
-		ath10k_dbg(ar, ATH10K_DBG_HTC,
-			   "htc ep %d consumed %d credits (total %d)\n",
-			   eid, credits, ep->tx_credits);
-		spin_unlock_bh(&htc->tx_lock);
-	}
+	skb_len = skb->len;
+	ret = ath10k_htc_consume_credit(ep, skb_len, true);
+	if (ret)
+		goto err_pull;
 
 	ath10k_htc_prepare_tx_skb(ep, skb);
 
@@ -155,17 +207,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
 	if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
 		dma_unmap_single(dev, skb_cb->paddr, skb->len, DMA_TO_DEVICE);
 err_credits:
-	if (ep->tx_credit_flow_enabled) {
-		spin_lock_bh(&htc->tx_lock);
-		ep->tx_credits += credits;
-		ath10k_dbg(ar, ATH10K_DBG_HTC,
-			   "htc ep %d reverted %d credits back (total %d)\n",
-			   eid, credits, ep->tx_credits);
-		spin_unlock_bh(&htc->tx_lock);
-
-		if (ep->ep_ops.ep_tx_credits)
-			ep->ep_ops.ep_tx_credits(htc->ar);
-	}
+	ath10k_htc_release_credit(ep, skb_len);
 err_pull:
 	skb_pull(skb, sizeof(struct ath10k_htc_hdr));
 	return ret;
@@ -581,6 +623,255 @@ static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
 	return allocation;
 }
 
+static int ath10k_htc_send_bundle(struct ath10k_htc_ep *ep,
+				  struct sk_buff *bundle_skb,
+				  struct sk_buff_head *tx_save_head)
+{
+	struct ath10k_hif_sg_item sg_item;
+	struct ath10k_htc *htc = ep->htc;
+	struct ath10k *ar = htc->ar;
+	struct sk_buff *skb;
+	int ret;
+	int cn = 0;
+	unsigned int skb_len;
+
+	ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle skb: len:%d\n", bundle_skb->len);
+	skb_len = bundle_skb->len;
+	ret = ath10k_htc_consume_credit(ep, skb_len, true);
+
+	if (!ret) {
+		sg_item.transfer_id = ep->eid;
+		sg_item.transfer_context = bundle_skb;
+		sg_item.vaddr = bundle_skb->data;
+		sg_item.len = bundle_skb->len;
+
+		ret = ath10k_hif_tx_sg(htc->ar, ep->ul_pipe_id, &sg_item, 1);
+		if (ret)
+			ath10k_htc_release_credit(ep, skb_len);
+	}
+
+	if (ret)
+		dev_kfree_skb_any(bundle_skb);
+
+	for (cn = 0; (skb = skb_dequeue_tail(tx_save_head)); cn++) {
+		if (ret) {
+			skb_pull(skb, sizeof(struct ath10k_htc_hdr));
+			skb_queue_head(&ep->tx_req_head, skb);
+		} else {
+			skb_queue_tail(&ep->tx_complete_head, skb);
+		}
+	}
+
+	if (!ret)
+		queue_work(ar->workqueue_tx_complete, &ar->tx_complete_work);
+
+	ath10k_dbg(ar, ATH10K_DBG_HTC,
+		   "bundle tx status:%d, eid:%d, req count:%d, count:%d, len:%d\n",
+		   ret, ep->eid, skb_queue_len(&ep->tx_req_head), cn, bundle_skb->len);
+	return ret;
+}
+
+static void ath10k_htc_send_one_skb(struct ath10k_htc_ep *ep, struct sk_buff *skb)
+{
+	struct ath10k_htc *htc = ep->htc;
+	struct ath10k *ar = htc->ar;
+	int ret;
+
+	ret = ath10k_htc_send(htc, ep->eid, skb);
+
+	if (ret)
+		skb_queue_head(&ep->tx_req_head, skb);
+
+	ath10k_dbg(ar, ATH10K_DBG_HTC, "tx one status:%d, eid:%d, len:%d, pending count:%d\n",
+		   ret, ep->eid, skb->len, skb_queue_len(&ep->tx_req_head));
+}
+
+static int ath10k_htc_send_bundle_skbs(struct ath10k_htc_ep *ep)
+{
+	int ret = 0;
+	struct ath10k_htc *htc = ep->htc;
+	struct sk_buff *bundle_skb, *skb;
+	struct sk_buff_head tx_save_head;
+	struct ath10k_htc_hdr *hdr;
+	u8 *bundle_buf;
+	int credit_pad, credit_remainder, trans_len, bundles_left = 0;
+
+	if (htc->ar->state == ATH10K_STATE_WEDGED)
+		return -ECOMM;
+
+	if (ep->tx_credit_flow_enabled &&
+	    ep->tx_credits < HTC_HOST_MIN_CREDIT_PER_TX_BUNDLE)
+		return 0;
+
+	bundles_left = HTC_HOST_MAX_MSG_PER_TX_BUNDLE * ep->tx_credit_size;
+	bundle_skb = dev_alloc_skb(bundles_left);
+
+	if (!bundle_skb)
+		return -ENOMEM;
+
+	bundle_buf = bundle_skb->data;
+	skb_queue_head_init(&tx_save_head);
+
+	while (true) {
+		skb = skb_dequeue(&ep->tx_req_head);
+		if (!skb)
+			break;
+
+		credit_pad = 0;
+		trans_len = skb->len + sizeof(*hdr);
+		credit_remainder = trans_len % ep->tx_credit_size;
+
+		if (credit_remainder != 0) {
+			credit_pad = ep->tx_credit_size - credit_remainder;
+			trans_len += credit_pad;
+		}
+
+		ret = ath10k_htc_consume_credit(ep,
+						bundle_buf + trans_len - bundle_skb->data,
+						false);
+		if (ret) {
+			skb_queue_head(&ep->tx_req_head, skb);
+			break;
+		}
+
+		if (bundles_left < trans_len) {
+			bundle_skb->len = bundle_buf - bundle_skb->data;
+			ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
+
+			if (ret) {
+				skb_queue_head(&ep->tx_req_head, skb);
+				return ret;
+			}
+
+			if (skb_queue_len(&ep->tx_req_head) == 0) {
+				ath10k_htc_send_one_skb(ep, skb);
+				return ret;
+			}
+
+			if (ep->tx_credit_flow_enabled &&
+			    ep->tx_credits < HTC_HOST_MIN_CREDIT_PER_TX_BUNDLE) {
+				skb_queue_head(&ep->tx_req_head, skb);
+				return 0;
+			}
+
+			bundles_left =
+				HTC_HOST_MAX_MSG_PER_TX_BUNDLE * ep->tx_credit_size;
+			bundle_skb = dev_alloc_skb(bundles_left);
+
+			if (!bundle_skb) {
+				skb_queue_head(&ep->tx_req_head, skb);
+				return -ENOMEM;
+			}
+			bundle_buf = bundle_skb->data;
+			skb_queue_head_init(&tx_save_head);
+		}
+
+		skb_push(skb, sizeof(struct ath10k_htc_hdr));
+		ath10k_htc_prepare_tx_skb(ep, skb);
+
+		memcpy(bundle_buf, skb->data, skb->len);
+		hdr = (struct ath10k_htc_hdr *)bundle_buf;
+		hdr->flags |= ATH10K_HTC_FLAG_SEND_BUNDLE;
+		hdr->pad_len = __cpu_to_le16(credit_pad);
+		bundle_buf += trans_len;
+		bundles_left -= trans_len;
+		skb_queue_tail(&tx_save_head, skb);
+	}
+
+	if (bundle_buf != bundle_skb->data) {
+		bundle_skb->len = bundle_buf - bundle_skb->data;
+		ret = ath10k_htc_send_bundle(ep, bundle_skb, &tx_save_head);
+	} else {
+		dev_kfree_skb_any(bundle_skb);
+	}
+
+	return ret;
+}
+
+static void ath10k_htc_bundle_tx_work(struct work_struct *work)
+{
+	struct ath10k *ar = container_of(work, struct ath10k, bundle_tx_work);
+	int i;
+	struct ath10k_htc_ep *ep;
+	enum ath10k_htc_ep_id eid;
+	struct sk_buff *skb;
+
+	for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
+		ep = &ar->htc.endpoint[i];
+		eid = ep->eid;
+
+		if (!ep->bundle_tx)
+			continue;
+
+		ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx work, eid:%d, count:%d\n",
+			   ep->eid, skb_queue_len(&ep->tx_req_head));
+
+		if (skb_queue_len(&ep->tx_req_head) >=
+		    HTC_HOST_MIN_MSG_PER_TX_BUNDLE) {
+			ath10k_htc_send_bundle_skbs(ep);
+		} else {
+			skb = skb_dequeue(&ep->tx_req_head);
+
+			if (!skb)
+				continue;
+			ath10k_htc_send_one_skb(ep, skb);
+		}
+	}
+}
+
+static void ath10k_htc_tx_complete_work(struct work_struct *work)
+{
+	struct ath10k *ar = container_of(work, struct ath10k, tx_complete_work);
+	int i;
+	struct ath10k_htc_ep *ep;
+	enum ath10k_htc_ep_id eid;
+	struct sk_buff *skb;
+
+	for (i = 0; i < ARRAY_SIZE(ar->htc.endpoint); i++) {
+		ep = &ar->htc.endpoint[i];
+		eid = ep->eid;
+		if (ep->bundle_tx && eid == ar->htt.eid) {
+			ath10k_dbg(ar, ATH10K_DBG_HTC, "bundle tx complete, eid:%d, pending complete count:%d\n",
+				   ep->eid, skb_queue_len(&ep->tx_complete_head));
+
+			while (true) {
+				skb = skb_dequeue(&ep->tx_complete_head);
+				if (!skb)
+					break;
+				ath10k_htc_notify_tx_completion(ep, skb);
+			}
+		}
+	}
+}
+
+int ath10k_htc_send_hl(struct ath10k_htc *htc,
+		       enum ath10k_htc_ep_id eid,
+		       struct sk_buff *skb)
+{
+	struct ath10k_htc_ep *ep = &htc->endpoint[eid];
+	struct ath10k *ar = htc->ar;
+
+	ath10k_dbg(ar, ATH10K_DBG_HTC, "htc send hl: eid:%d, bundle:%d, tx count:%d, len:%d\n",
+		   eid, ep->bundle_tx, skb_queue_len(&ep->tx_req_head), skb->len);
+
+	if (ep->bundle_tx) {
+		skb_queue_tail(&ep->tx_req_head, skb);
+		queue_work(ar->workqueue, &ar->bundle_tx_work);
+		return 0;
+	} else {
+		return ath10k_htc_send(htc, eid, skb);
+	}
+}
+
+void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep)
+{
+	if (ep->htc->max_msgs_per_htc_bundle >= HTC_HOST_MIN_MSG_PER_TX_BUNDLE) {
+		ep->bundle_tx = true;
+		skb_queue_head_init(&ep->tx_req_head);
+		skb_queue_head_init(&ep->tx_complete_head);
+	}
+}
+
 int ath10k_htc_wait_target(struct ath10k_htc *htc)
 {
 	struct ath10k *ar = htc->ar;
@@ -657,6 +948,9 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 			   htc->max_msgs_per_htc_bundle);
 	}
 
+	INIT_WORK(&ar->bundle_tx_work, ath10k_htc_bundle_tx_work);
+	INIT_WORK(&ar->tx_complete_work, ath10k_htc_tx_complete_work);
+
 	return 0;
 }
 
@@ -801,6 +1095,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
 	ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
 	ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
 	ep->tx_credits = tx_alloc;
+	ep->tx_credit_size = htc->target_credit_size;
 
 	/* copy all the callbacks */
 	ep->ep_ops = conn_req->ep_ops;
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index d61eb6c0..ec4957a 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -40,6 +40,9 @@
  */
 
 #define HTC_HOST_MAX_MSG_PER_RX_BUNDLE        32
+#define HTC_HOST_MAX_MSG_PER_TX_BUNDLE        32
+#define HTC_HOST_MIN_MSG_PER_TX_BUNDLE        2
+#define HTC_HOST_MIN_CREDIT_PER_TX_BUNDLE     2
 
 enum ath10k_htc_tx_flags {
 	ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
@@ -70,8 +73,14 @@ struct ath10k_htc_hdr {
 		u8 seq_no; /* for tx */
 		u8 control_byte1;
 	} __packed;
-	u8 pad0;
-	u8 pad1;
+	union {
+		__le16 pad_len;
+		struct {
+			u8 pad0;
+			u8 pad1;
+		} __packed;
+	} __packed;
+
 } __packed __aligned(4);
 
 enum ath10k_ath10k_htc_msg_id {
@@ -340,7 +349,12 @@ struct ath10k_htc_ep {
 
 	u8 seq_no; /* for debugging */
 	int tx_credits;
+	int tx_credit_size;
 	bool tx_credit_flow_enabled;
+	bool bundle_tx;
+	struct sk_buff_head tx_req_head;
+	struct sk_buff_head tx_complete_head;
+
 };
 
 struct ath10k_htc_svc_tx_credits {
@@ -369,6 +383,7 @@ struct ath10k_htc {
 
 int ath10k_htc_init(struct ath10k *ar);
 int ath10k_htc_wait_target(struct ath10k_htc *htc);
+void ath10k_htc_setup_tx_req(struct ath10k_htc_ep *ep);
 int ath10k_htc_start(struct ath10k_htc *htc);
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
 			       struct ath10k_htc_svc_conn_req  *conn_req,
@@ -378,6 +393,8 @@ void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
 				      bool enable);
 int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 		    struct sk_buff *packet);
+int ath10k_htc_send_hl(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
+		       struct sk_buff *packet);
 struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
 void ath10k_htc_tx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_htc_rx_completion_handler(struct ath10k *ar, struct sk_buff *skb);
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 4354bf2..127b4e4 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -135,6 +135,8 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
 {
 	struct ath10k_htc_svc_conn_req conn_req;
 	struct ath10k_htc_svc_conn_resp conn_resp;
+	struct ath10k *ar = htt->ar;
+	struct ath10k_htc_ep *ep;
 	int status;
 
 	memset(&conn_req, 0, sizeof(conn_req));
@@ -142,6 +144,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
 
 	conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete;
 	conn_req.ep_ops.ep_rx_complete = ath10k_htt_htc_t2h_msg_handler;
+	conn_req.ep_ops.ep_tx_credits = ath10k_htt_op_ep_tx_credits;
 
 	/* connect to control service */
 	conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
@@ -154,6 +157,11 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
 
 	htt->eid = conn_resp.eid;
 
+	if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
+		ep = &ar->htc.endpoint[htt->eid];
+		ath10k_htc_setup_tx_req(ep);
+	}
+
 	htt->disable_tx_comp = ath10k_hif_get_htt_tx_complete(htt->ar);
 	if (htt->disable_tx_comp)
 		ath10k_htc_change_tx_credit_flow(&htt->ar->htc, htt->eid, true);
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 889bf9f..4851a2e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -2030,6 +2030,9 @@ struct ath10k_htt {
 	const struct ath10k_htt_tx_ops *tx_ops;
 	const struct ath10k_htt_rx_ops *rx_ops;
 	bool disable_tx_comp;
+	bool bundle_tx;
+	struct sk_buff_head tx_req_head;
+	struct sk_buff_head tx_complete_head;
 };
 
 struct ath10k_htt_tx_ops {
@@ -2276,6 +2279,7 @@ int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
 			     __le16 fetch_seq_num,
 			     struct htt_tx_fetch_record *records,
 			     size_t num_records);
+void ath10k_htt_op_ep_tx_credits(struct ath10k *ar);
 
 void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
 			      struct ieee80211_txq *txq);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 5bf3179..09825b1 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -3821,6 +3821,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 			ath10k_dbg(ar, ATH10K_DBG_HTT,
 				   "credit total:%d\n",
 				   ep->tx_credits);
+			ep->ep_ops.ep_tx_credits(htc->ar);
 		}
 		break;
 	}
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7eb753a8..e619b33 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -541,6 +541,11 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
 	ath10k_htt_tx_destroy(htt);
 }
 
+void ath10k_htt_op_ep_tx_credits(struct ath10k *ar)
+{
+	queue_work(ar->workqueue, &ar->bundle_tx_work);
+}
+
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct ath10k_htt *htt = &ar->htt;
@@ -1357,7 +1362,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
 	 */
 	tx_desc->peerid = __cpu_to_le32(HTT_INVALID_PEERID);
 
-	res = ath10k_htc_send(&htt->ar->htc, htt->eid, msdu);
+	res = ath10k_htc_send_hl(&htt->ar->htc, htt->eid, msdu);
 
 out:
 	return res;
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 5/8] ath10k: disable TX complete indication of htt for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

Tx complete message from firmware cost bus bandwidth of sdio, and bus
bandwidth is the bollteneck of throughput, it will effect the bandwidth
occupancy of data packet of TX and RX.

This patch disable TX complete indication from firmware for htt data
packet, it results in significant performance improvement on TX path.

The downside of this patch is ath10k will not know the TX status of
the data packet for poor signal situation. Although upper network stack
or application layer have retry mechanism, the retry will be later than
ath10k get the TX fail status if not disable TX complete.

This patch only effect sdio chip, it will not effect PCI, SNOC etc.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: change some code style
v3: change some code style
v4: no change
 drivers/net/wireless/ath/ath10k/core.c   |  9 ++++++++-
 drivers/net/wireless/ath/ath10k/hif.h    |  9 +++++++++
 drivers/net/wireless/ath/ath10k/htc.c    | 10 ++++++++++
 drivers/net/wireless/ath/ath10k/htc.h    |  3 +++
 drivers/net/wireless/ath/ath10k/htt.c    |  5 +++++
 drivers/net/wireless/ath/ath10k/htt.h    | 13 +++++++++++-
 drivers/net/wireless/ath/ath10k/htt_rx.c | 34 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/htt_tx.c | 31 +++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath10k/hw.h     |  2 +-
 drivers/net/wireless/ath/ath10k/sdio.c   | 23 +++++++++++++++++++++
 10 files changed, 135 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index dc45d16..d56dcbd 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -30,6 +30,7 @@
 
 static unsigned int ath10k_cryptmode_param;
 static bool uart_print;
+static bool disable_tx_comp = true;
 static bool skip_otp;
 static bool rawmode;
 static bool fw_diag_log;
@@ -41,6 +42,9 @@
 module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
 module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
 module_param(uart_print, bool, 0644);
+
+/* If upper layer need the TX complete status, it can enable tx complete */
+module_param(disable_tx_comp, bool, 0644);
 module_param(skip_otp, bool, 0644);
 module_param(rawmode, bool, 0644);
 module_param(fw_diag_log, bool, 0644);
@@ -688,7 +692,10 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
 	/* Data transfer is not initiated, when reduced Tx completion
 	 * is used for SDIO. disable it until fixed
 	 */
-	param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
+	if (disable_tx_comp)
+		param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
+	else
+		param &= ~HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET;
 
 	/* Alternate credit size of 1544 as used by SDIO firmware is
 	 * not big enough for mac80211 / native wifi frames. disable it
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 496ee34..0dd8973 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -56,6 +56,8 @@ struct ath10k_hif_ops {
 
 	int (*swap_mailbox)(struct ath10k *ar);
 
+	int (*get_htt_tx_complete)(struct ath10k *ar);
+
 	int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
 				   u8 *ul_pipe, u8 *dl_pipe);
 
@@ -144,6 +146,13 @@ static inline int ath10k_hif_swap_mailbox(struct ath10k *ar)
 	return 0;
 }
 
+static inline int ath10k_hif_get_htt_tx_complete(struct ath10k *ar)
+{
+	if (ar->hif.ops->get_htt_tx_complete)
+		return ar->hif.ops->get_htt_tx_complete(ar);
+	return 0;
+}
+
 static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar,
 						 u16 service_id,
 						 u8 *ul_pipe, u8 *dl_pipe)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 1d4d1a1..4c6cdc2 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -660,6 +660,16 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
 	return 0;
 }
 
+void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
+				      enum ath10k_htc_ep_id eid,
+				      bool enable)
+{
+	struct ath10k *ar = htc->ar;
+	struct ath10k_htc_ep *ep = &ar->htc.endpoint[eid];
+
+	ep->tx_credit_flow_enabled = enable;
+}
+
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
 			       struct ath10k_htc_svc_conn_req *conn_req,
 			       struct ath10k_htc_svc_conn_resp *conn_resp)
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 7055156..d61eb6c0 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -373,6 +373,9 @@ struct ath10k_htc {
 int ath10k_htc_connect_service(struct ath10k_htc *htc,
 			       struct ath10k_htc_svc_conn_req  *conn_req,
 			       struct ath10k_htc_svc_conn_resp *conn_resp);
+void ath10k_htc_change_tx_credit_flow(struct ath10k_htc *htc,
+				      enum ath10k_htc_ep_id eid,
+				      bool enable);
 int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
 		    struct sk_buff *packet);
 struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 7b75200..4354bf2 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -10,6 +10,7 @@
 #include "htt.h"
 #include "core.h"
 #include "debug.h"
+#include "hif.h"
 
 static const enum htt_t2h_msg_type htt_main_t2h_msg_types[] = {
 	[HTT_MAIN_T2H_MSG_TYPE_VERSION_CONF] = HTT_T2H_MSG_TYPE_VERSION_CONF,
@@ -153,6 +154,10 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
 
 	htt->eid = conn_resp.eid;
 
+	htt->disable_tx_comp = ath10k_hif_get_htt_tx_complete(htt->ar);
+	if (htt->disable_tx_comp)
+		ath10k_htc_change_tx_credit_flow(&htt->ar->htc, htt->eid, true);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 30c0800..889bf9f 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -150,9 +150,19 @@ enum htt_data_tx_desc_flags1 {
 	HTT_DATA_TX_DESC_FLAGS1_MORE_IN_BATCH    = 1 << 12,
 	HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD = 1 << 13,
 	HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD = 1 << 14,
-	HTT_DATA_TX_DESC_FLAGS1_RSVD1            = 1 << 15
+	HTT_DATA_TX_DESC_FLAGS1_TX_COMPLETE      = 1 << 15
 };
 
+#define HTT_TX_CREDIT_DELTA_ABS_M      0xffff0000
+#define HTT_TX_CREDIT_DELTA_ABS_S      16
+#define HTT_TX_CREDIT_DELTA_ABS_GET(word) \
+	    (((word) & HTT_TX_CREDIT_DELTA_ABS_M) >> HTT_TX_CREDIT_DELTA_ABS_S)
+
+#define HTT_TX_CREDIT_SIGN_BIT_M       0x00000100
+#define HTT_TX_CREDIT_SIGN_BIT_S       8
+#define HTT_TX_CREDIT_SIGN_BIT_GET(word) \
+	    (((word) & HTT_TX_CREDIT_SIGN_BIT_M) >> HTT_TX_CREDIT_SIGN_BIT_S)
+
 enum htt_data_tx_ext_tid {
 	HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST = 16,
 	HTT_DATA_TX_EXT_TID_MGMT                = 17,
@@ -2019,6 +2029,7 @@ struct ath10k_htt {
 	bool tx_mem_allocated;
 	const struct ath10k_htt_tx_ops *tx_ops;
 	const struct ath10k_htt_rx_ops *rx_ops;
+	bool disable_tx_comp;
 };
 
 struct ath10k_htt_tx_ops {
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 83a7fb6..5bf3179 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -3691,6 +3691,9 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 	}
 	case HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION: {
 		struct htt_tx_done tx_done = {};
+		struct ath10k_htt *htt = &ar->htt;
+		struct ath10k_htc *htc = &ar->htc;
+		struct ath10k_htc_ep *ep = &ar->htc.endpoint[htt->eid];
 		int status = __le32_to_cpu(resp->mgmt_tx_completion.status);
 		int info = __le32_to_cpu(resp->mgmt_tx_completion.info);
 
@@ -3716,6 +3719,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 			break;
 		}
 
+		if (htt->disable_tx_comp) {
+			spin_lock_bh(&htc->tx_lock);
+			ep->tx_credits++;
+			spin_unlock_bh(&htc->tx_lock);
+		}
+
 		status = ath10k_txrx_tx_unref(htt, &tx_done);
 		if (!status) {
 			spin_lock_bh(&htt->tx_lock);
@@ -3790,8 +3799,31 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 		skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
 		return false;
 	}
-	case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
+	case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: {
+		struct ath10k_htt *htt = &ar->htt;
+		struct ath10k_htc *htc = &ar->htc;
+		struct ath10k_htc_ep *ep = &ar->htc.endpoint[htt->eid];
+		u32 msg_word = __le32_to_cpu(*(__le32 *)resp);
+		int htt_credit_delta;
+
+		htt_credit_delta = HTT_TX_CREDIT_DELTA_ABS_GET(msg_word);
+		if (HTT_TX_CREDIT_SIGN_BIT_GET(msg_word))
+			htt_credit_delta = -htt_credit_delta;
+
+		ath10k_dbg(ar, ATH10K_DBG_HTT,
+			   "credit update: delta:%d\n",
+			   htt_credit_delta);
+
+		if (htt->disable_tx_comp) {
+			spin_lock_bh(&htc->tx_lock);
+			ep->tx_credits += htt_credit_delta;
+			spin_unlock_bh(&htc->tx_lock);
+			ath10k_dbg(ar, ATH10K_DBG_HTT,
+				   "credit total:%d\n",
+				   ep->tx_credits);
+		}
 		break;
+	}
 	case HTT_T2H_MSG_TYPE_CHAN_CHANGE: {
 		u32 phymode = __le32_to_cpu(resp->chan_change.phymode);
 		u32 freq = __le32_to_cpu(resp->chan_change.freq);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 2ef717f1..7eb753a8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -543,7 +543,35 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
 
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
 {
+	struct ath10k_htt *htt = &ar->htt;
+	struct htt_tx_done tx_done = {0};
+	struct htt_cmd_hdr *htt_hdr;
+	struct htt_data_tx_desc *desc_hdr;
+	u16 flags1;
+
 	dev_kfree_skb_any(skb);
+
+	if (!htt->disable_tx_comp)
+		return;
+
+	htt_hdr = (struct htt_cmd_hdr *)skb->data;
+	if (htt_hdr->msg_type != HTT_H2T_MSG_TYPE_TX_FRM)
+		return;
+
+	desc_hdr = (struct htt_data_tx_desc *)
+		(skb->data + sizeof(*htt_hdr));
+	flags1 = __le16_to_cpu(desc_hdr->flags1);
+
+	ath10k_dbg(ar, ATH10K_DBG_HTT,
+		   "htt tx complete msdu id:%u ,flags1:%x\n",
+		   __le16_to_cpu(desc_hdr->id), flags1);
+
+	if (flags1 & HTT_DATA_TX_DESC_FLAGS1_TX_COMPLETE)
+		return;
+
+	tx_done.status = HTT_TX_COMPL_STATE_ACK;
+	tx_done.msdu_id = __le16_to_cpu(desc_hdr->id);
+	ath10k_txrx_tx_unref(&ar->htt, &tx_done);
 }
 
 void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb)
@@ -1261,6 +1289,9 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
 		flags0 |= SM(ATH10K_HW_TXRX_MGMT,
 			     HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
 		flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
+
+		if (htt->disable_tx_comp)
+			flags1 |= HTT_DATA_TX_DESC_FLAGS1_TX_COMPLETE;
 		break;
 	}
 
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 2ae57c1..6349665 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -759,7 +759,7 @@ struct ath10k_hw_ops {
 #define TARGET_TLV_NUM_TDLS_VDEVS		1
 #define TARGET_TLV_NUM_TIDS			((TARGET_TLV_NUM_PEERS) * 2)
 #define TARGET_TLV_NUM_MSDU_DESC		(1024 + 32)
-#define TARGET_TLV_NUM_MSDU_DESC_HL		64
+#define TARGET_TLV_NUM_MSDU_DESC_HL		1024
 #define TARGET_TLV_NUM_WOW_PATTERNS		22
 #define TARGET_TLV_MGMT_NUM_MSDU_DESC		(50)
 
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 3b808a3..e01ab63 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -1786,6 +1786,28 @@ static int ath10k_sdio_hif_swap_mailbox(struct ath10k *ar)
 	return 0;
 }
 
+static int ath10k_sdio_get_htt_tx_complete(struct ath10k *ar)
+{
+	u32 addr, val;
+	int ret;
+
+	addr = host_interest_item_address(HI_ITEM(hi_acs_flags));
+
+	ret = ath10k_sdio_hif_diag_read32(ar, addr, &val);
+	if (ret) {
+		ath10k_warn(ar,
+			    "unable to read hi_acs_flags for htt tx comple : %d\n", ret);
+		return ret;
+	}
+
+	ret = (val & HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK);
+
+	ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio reduce tx complete fw%sack\n",
+		   ret ? " " : " not ");
+
+	return ret;
+}
+
 /* HIF start/stop */
 
 static int ath10k_sdio_hif_start(struct ath10k *ar)
@@ -2069,6 +2091,7 @@ static void ath10k_sdio_hif_send_complete_check(struct ath10k *ar,
 	.start			= ath10k_sdio_hif_start,
 	.stop			= ath10k_sdio_hif_stop,
 	.swap_mailbox		= ath10k_sdio_hif_swap_mailbox,
+	.get_htt_tx_complete	= ath10k_sdio_get_htt_tx_complete,
 	.map_service_to_pipe	= ath10k_sdio_hif_map_service_to_pipe,
 	.get_default_pipe	= ath10k_sdio_hif_get_default_pipe,
 	.send_complete_check	= ath10k_sdio_hif_send_complete_check,
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 4/8] ath10k: add workqueue for RX path of sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

The thread of read rx message by sdio bus from firmware is
synchronous, it will cost much time for process the left part
of rx message which includes indicate the rx packet to uppper
net stack. It will reduce the time of read from sdio.

This patch move the indication to a workqueue, it results in
significant performance improvement on RX path.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: no change
v3: change some code style
v4: no change
 drivers/net/wireless/ath/ath10k/sdio.c | 116 ++++++++++++++++++++++++++++++++-
 drivers/net/wireless/ath/ath10k/sdio.h |  20 ++++++
 2 files changed, 133 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 714b0b1..3b808a3 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -412,6 +412,66 @@ static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar,
 	return 0;
 }
 
+static struct ath10k_sdio_rx_request *ath10k_sdio_alloc_rx_req(struct ath10k *ar)
+{
+	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+	struct ath10k_sdio_rx_request *rx_req;
+
+	spin_lock_bh(&ar_sdio->rx_lock);
+
+	if (list_empty(&ar_sdio->rx_req_freeq)) {
+		rx_req = NULL;
+		ath10k_dbg(ar, ATH10K_DBG_SDIO, "rx_req alloc fail\n");
+		goto out;
+	}
+
+	rx_req = list_first_entry(&ar_sdio->rx_req_freeq,
+				  struct ath10k_sdio_rx_request, list);
+	list_del(&rx_req->list);
+
+out:
+	spin_unlock_bh(&ar_sdio->rx_lock);
+	return rx_req;
+}
+
+static void ath10k_sdio_free_rx_req(struct ath10k *ar,
+				    struct ath10k_sdio_rx_request *rx_req)
+{
+	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+
+	memset(rx_req, 0, sizeof(*rx_req));
+
+	spin_lock_bh(&ar_sdio->rx_lock);
+	list_add_tail(&rx_req->list, &ar_sdio->rx_req_freeq);
+	spin_unlock_bh(&ar_sdio->rx_lock);
+}
+
+static int ath10k_sdio_prep_async_rx_req(struct ath10k *ar,
+					 struct sk_buff *skb,
+					 struct ath10k_htc_ep *ep)
+{
+	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+	struct ath10k_sdio_rx_request *rx_req;
+
+	/* Allocate a rx request for the message and queue it on the
+	 * SDIO rx workqueue.
+	 */
+	rx_req = ath10k_sdio_alloc_rx_req(ar);
+	if (!rx_req) {
+		ath10k_warn(ar, "unable to allocate rx request for async request\n");
+		return -ENOMEM;
+	}
+
+	rx_req->skb = skb;
+	rx_req->ep = ep;
+
+	spin_lock_bh(&ar_sdio->wr_async_lock_rx);
+	list_add_tail(&rx_req->list, &ar_sdio->wr_asyncq_rx);
+	spin_unlock_bh(&ar_sdio->wr_async_lock_rx);
+
+	return 0;
+}
+
 static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
 					       u32 lookaheads[],
 					       int *n_lookahead)
@@ -465,10 +525,16 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
 		if (ret)
 			goto out;
 
-		if (!pkt->trailer_only)
-			ep->ep_ops.ep_rx_complete(ar_sdio->ar, pkt->skb);
-		else
+		if (!pkt->trailer_only) {
+			ret = ath10k_sdio_prep_async_rx_req(ar, pkt->skb, ep);
+			if (ret)
+				kfree_skb(pkt->skb);
+			else
+				queue_work(ar->workqueue_aux,
+					   &ar_sdio->wr_async_work_rx);
+		} else {
 			kfree_skb(pkt->skb);
+		}
 
 		/* The RX complete handler now owns the skb...*/
 		pkt->skb = NULL;
@@ -1319,6 +1385,26 @@ static void __ath10k_sdio_write_async(struct ath10k *ar,
 	ath10k_sdio_free_bus_req(ar, req);
 }
 
+static void ath10k_rx_indication_async_work(struct work_struct *work)
+{
+	struct ath10k_sdio *ar_sdio = container_of(work, struct ath10k_sdio,
+						   wr_async_work_rx);
+	struct ath10k *ar = ar_sdio->ar;
+	struct ath10k_sdio_rx_request *req, *tmp_req;
+
+	spin_lock_bh(&ar_sdio->wr_async_lock_rx);
+
+	list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq_rx, list) {
+		list_del(&req->list);
+		spin_unlock_bh(&ar_sdio->wr_async_lock_rx);
+		req->ep->ep_ops.ep_rx_complete(ar, req->skb);
+		ath10k_sdio_free_rx_req(ar, req);
+		spin_lock_bh(&ar_sdio->wr_async_lock_rx);
+	}
+
+	spin_unlock_bh(&ar_sdio->wr_async_lock_rx);
+}
+
 static void ath10k_sdio_write_async_work(struct work_struct *work)
 {
 	struct ath10k_sdio *ar_sdio = container_of(work, struct ath10k_sdio,
@@ -1807,10 +1893,24 @@ static void ath10k_sdio_irq_disable(struct ath10k *ar)
 static void ath10k_sdio_hif_stop(struct ath10k *ar)
 {
 	struct ath10k_sdio_bus_request *req, *tmp_req;
+	struct ath10k_sdio_rx_request *rx_req, *tmp_rx_req;
 	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
 
 	ath10k_sdio_irq_disable(ar);
 
+	cancel_work_sync(&ar_sdio->wr_async_work_rx);
+
+	spin_lock_bh(&ar_sdio->wr_async_lock_rx);
+
+	/* Free all RX requests that have not been handled */
+	list_for_each_entry_safe(rx_req, tmp_rx_req, &ar_sdio->wr_asyncq_rx, list) {
+		list_del(&rx_req->list);
+		rx_req->ep->ep_ops.ep_rx_complete(ar, rx_req->skb);
+		ath10k_sdio_free_rx_req(ar, rx_req);
+	}
+
+	spin_unlock_bh(&ar_sdio->wr_async_lock_rx);
+
 	cancel_work_sync(&ar_sdio->wr_async_work);
 
 	spin_lock_bh(&ar_sdio->wr_async_lock);
@@ -2089,6 +2189,16 @@ static int ath10k_sdio_probe(struct sdio_func *func,
 	for (i = 0; i < ATH10K_SDIO_BUS_REQUEST_MAX_NUM; i++)
 		ath10k_sdio_free_bus_req(ar, &ar_sdio->bus_req[i]);
 
+	spin_lock_init(&ar_sdio->rx_lock);
+	spin_lock_init(&ar_sdio->wr_async_lock_rx);
+	INIT_LIST_HEAD(&ar_sdio->rx_req_freeq);
+	INIT_LIST_HEAD(&ar_sdio->wr_asyncq_rx);
+
+	INIT_WORK(&ar_sdio->wr_async_work_rx, ath10k_rx_indication_async_work);
+
+	for (i = 0; i < ARRAY_SIZE(ar_sdio->rx_req); i++)
+		ath10k_sdio_free_rx_req(ar, &ar_sdio->rx_req[i]);
+
 	dev_id_base = FIELD_GET(QCA_MANUFACTURER_ID_BASE, id->device);
 	switch (dev_id_base) {
 	case QCA_MANUFACTURER_ID_AR6005_BASE:
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
index 3ca76c7..9bb438e 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -38,6 +38,7 @@
 
 #define ATH10K_HIF_MBOX_NUM_MAX                 4
 #define ATH10K_SDIO_BUS_REQUEST_MAX_NUM         64
+#define ATH10K_SDIO_RX_REQUEST_MAX_NUM          1024
 
 #define ATH10K_SDIO_HIF_COMMUNICATION_TIMEOUT_HZ (100 * HZ)
 
@@ -98,6 +99,12 @@
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
 
+struct ath10k_sdio_rx_request {
+	struct list_head list;
+	struct sk_buff *skb;
+	struct ath10k_htc_ep *ep;
+};
+
 struct ath10k_sdio_bus_request {
 	struct list_head list;
 
@@ -187,9 +194,17 @@ struct ath10k_sdio {
 	struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
 	/* free list of bus requests */
 	struct list_head bus_req_freeq;
+
 	/* protects access to bus_req_freeq */
 	spinlock_t lock;
 
+	/* available rx requests */
+	struct ath10k_sdio_rx_request rx_req[ATH10K_SDIO_RX_REQUEST_MAX_NUM];
+	/* free list of rx requests */
+	struct list_head rx_req_freeq;
+	/* protects access to rx_req_freeq */
+	spinlock_t rx_lock;
+
 	struct ath10k_sdio_rx_data rx_pkts[ATH10K_SDIO_MAX_RX_MSGS];
 	size_t n_rx_pkts;
 
@@ -209,6 +224,11 @@ struct ath10k_sdio {
 	struct list_head wr_asyncq;
 	/* protects access to wr_asyncq */
 	spinlock_t wr_async_lock;
+
+	struct work_struct wr_async_work_rx;
+	struct list_head wr_asyncq_rx;
+	/* protects access to wr_asyncq_rx */
+	spinlock_t wr_async_lock_rx;
 };
 
 static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 3/8] ath10k: change max RX bundle size from 8 to 32 for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

The max bundle size support by firmware is 32, change it from 8 to 32
will help performance. This results in significant performance
improvement on RX path.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: change macro HTC_GET_BUNDLE_COUNT
v3: change some code style
v4: add macro ATH10K_HTC_FLAG_BUNDLE_MASK
 drivers/net/wireless/ath/ath10k/htc.h  | 12 +++++++++---
 drivers/net/wireless/ath/ath10k/sdio.c |  6 +++---
 drivers/net/wireless/ath/ath10k/sdio.h |  4 ++--
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index f55d3ca..7055156 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -39,7 +39,7 @@
  * 4-byte aligned.
  */
 
-#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE        8
+#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE        32
 
 enum ath10k_htc_tx_flags {
 	ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
@@ -48,10 +48,16 @@ enum ath10k_htc_tx_flags {
 
 enum ath10k_htc_rx_flags {
 	ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK = 0x01,
-	ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
-	ATH10K_HTC_FLAG_BUNDLE_MASK     = 0xF0
+	ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02
 };
 
+#define ATH10K_HTC_FLAG_BUNDLE_MASK 0xF0
+#define ATH10K_HTC_BUNDLE_EXTRA_MASK GENMASK(3, 2)
+
+#define ATH10K_HTC_GET_BUNDLE_COUNT(flags) \
+	    (FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, (flags)) +  \
+	    (FIELD_GET(ATH10K_HTC_BUNDLE_EXTRA_MASK, (flags)) << 4))
+
 struct ath10k_htc_hdr {
 	u8 eid; /* @enum ath10k_htc_ep_id */
 	u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */
diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index d7ffcd5..714b0b1 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -24,8 +24,8 @@
 #include "trace.h"
 #include "sdio.h"
 
-#define ATH10K_SDIO_DMA_BUF_SIZE	(32 * 1024)
-#define ATH10K_SDIO_VSG_BUF_SIZE	(32 * 1024)
+#define ATH10K_SDIO_DMA_BUF_SIZE	(64 * 1024)
+#define ATH10K_SDIO_VSG_BUF_SIZE	(64 * 1024)
 
 /* inlined helper functions */
 
@@ -495,7 +495,7 @@ static int ath10k_sdio_mbox_alloc_bundle(struct ath10k *ar,
 {
 	int ret, i;
 
-	*bndl_cnt = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, htc_hdr->flags);
+	*bndl_cnt = ATH10K_HTC_GET_BUNDLE_COUNT(htc_hdr->flags);
 
 	if (*bndl_cnt > HTC_HOST_MAX_MSG_PER_RX_BUNDLE) {
 		ath10k_warn(ar,
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
index 4896eca..3ca76c7 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -89,10 +89,10 @@
  * to the maximum value (HTC_HOST_MAX_MSG_PER_RX_BUNDLE).
  *
  * in this case the driver must allocate
- * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE) skb's.
+ * (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2) skb's.
  */
 #define ATH10K_SDIO_MAX_RX_MSGS \
-	(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE)
+	(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2)
 
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL   0x00000868u
 #define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 2/8] ath10k: enable RX bundle receive for sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

From: Alagu Sankar <alagusankar@silex-india.com>

The existing implementation of initiating multiple sdio transfers for
receive bundling is slowing down the receive speed. Combining the
transfers using a bundle method would be ideal.

The transmission utilization ratio for sdio bus for small packet is
slow, because the space and time cost for sdio bus is same for large
length packet and small length packet. So the speed of data for large
length packet is higher than small length.

Test result of different length of data:
data packet(byte)   cost time(us)   calculated rate(Mbps)
      256               28                73
      512               33               124
     1024               35               234
     1792               45               318
    14336              168               682
    28672              333               688
    57344              660               695

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Signed-off-by: Alagu Sankar <alagusankar@silex-india.com>
Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: fix incorrect skb tail of rx bundle in ath10k_sdio_mbox_rx_process_packet
v3: change some code style
split fix incorrect skb tail of rx bundle to patch "adjust skb length in ath10k_sdio_mbox_rx_packet"
v4: add err handle in ath10k_sdio_mbox_rx_fetch_bundle
 drivers/net/wireless/ath/ath10k/sdio.c | 108 ++++++++++++++++++++++-----------
 drivers/net/wireless/ath/ath10k/sdio.h |   7 ++-
 2 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 1127e44..d7ffcd5 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -24,6 +24,9 @@
 #include "trace.h"
 #include "sdio.h"
 
+#define ATH10K_SDIO_DMA_BUF_SIZE	(32 * 1024)
+#define ATH10K_SDIO_VSG_BUF_SIZE	(32 * 1024)
+
 /* inlined helper functions */
 
 static inline int ath10k_sdio_calc_txrx_padded_len(struct ath10k_sdio *ar_sdio,
@@ -484,11 +487,11 @@ static int ath10k_sdio_mbox_rx_process_packets(struct ath10k *ar,
 	return ret;
 }
 
-static int ath10k_sdio_mbox_alloc_pkt_bundle(struct ath10k *ar,
-					     struct ath10k_sdio_rx_data *rx_pkts,
-					     struct ath10k_htc_hdr *htc_hdr,
-					     size_t full_len, size_t act_len,
-					     size_t *bndl_cnt)
+static int ath10k_sdio_mbox_alloc_bundle(struct ath10k *ar,
+					 struct ath10k_sdio_rx_data *rx_pkts,
+					 struct ath10k_htc_hdr *htc_hdr,
+					 size_t full_len, size_t act_len,
+					 size_t *bndl_cnt)
 {
 	int ret, i;
 
@@ -529,6 +532,7 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 	size_t full_len, act_len;
 	bool last_in_bundle;
 	int ret, i;
+	int pkt_cnt = 0;
 
 	if (n_lookaheads > ATH10K_SDIO_MAX_RX_MSGS) {
 		ath10k_warn(ar,
@@ -572,20 +576,22 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 			 */
 			size_t bndl_cnt;
 
-			ret = ath10k_sdio_mbox_alloc_pkt_bundle(ar,
-								&ar_sdio->rx_pkts[i],
-								htc_hdr,
-								full_len,
-								act_len,
-								&bndl_cnt);
+			struct ath10k_sdio_rx_data *rx_pkts =
+				&ar_sdio->rx_pkts[pkt_cnt];
+
+			ret = ath10k_sdio_mbox_alloc_bundle(ar,
+							    rx_pkts,
+							    htc_hdr,
+							    full_len,
+							    act_len,
+							    &bndl_cnt);
 
 			if (ret) {
 				ath10k_warn(ar, "alloc_bundle error %d\n", ret);
 				goto err;
 			}
 
-			n_lookaheads += bndl_cnt;
-			i += bndl_cnt;
+			pkt_cnt += bndl_cnt;
 			/*Next buffer will be the last in the bundle */
 			last_in_bundle = true;
 		}
@@ -597,7 +603,7 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 		if (htc_hdr->flags & ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK)
 			full_len += ATH10K_HIF_MBOX_BLOCK_SIZE;
 
-		ret = ath10k_sdio_mbox_alloc_rx_pkt(&ar_sdio->rx_pkts[i],
+		ret = ath10k_sdio_mbox_alloc_rx_pkt(&ar_sdio->rx_pkts[pkt_cnt],
 						    act_len,
 						    full_len,
 						    last_in_bundle,
@@ -606,9 +612,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 			ath10k_warn(ar, "alloc_rx_pkt error %d\n", ret);
 			goto err;
 		}
+		pkt_cnt++;
 	}
 
-	ar_sdio->n_rx_pkts = i;
+	ar_sdio->n_rx_pkts = pkt_cnt;
 
 	return 0;
 
@@ -622,10 +629,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
 	return ret;
 }
 
-static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
-				      struct ath10k_sdio_rx_data *pkt)
+static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
 {
 	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+	struct ath10k_sdio_rx_data *pkt = &ar_sdio->rx_pkts[0];
 	struct sk_buff *skb = pkt->skb;
 	struct ath10k_htc_hdr *htc_hdr;
 	int ret;
@@ -633,46 +640,64 @@ static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
 	ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
 				 skb->data, pkt->alloc_len);
 
-	if (!ret) {
-		/* Update actual length. The original length may be incorrect,
-		 * as the FW will bundle multiple packets as long as their sizes
-		 * fit within the same aligned length (pkt->alloc_len).
-		 */
-		htc_hdr = (struct ath10k_htc_hdr *)skb->data;
-		pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
-		if (pkt->act_len <= pkt->alloc_len) {
-			skb_put(skb, pkt->act_len);
-		} else {
-			ath10k_warn(ar, "rx packet too large (%zu > %zu)\n",
-				    pkt->act_len, pkt->alloc_len);
-			ret = -EMSGSIZE;
-		}
+	if (ret) {
+		ar_sdio->n_rx_pkts = 0;
+		ath10k_sdio_mbox_free_rx_pkt(pkt);
+		return ret;
 	}
 
+	htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+	pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
 	pkt->status = ret;
+	skb_put(skb, pkt->act_len);
 
 	return ret;
 }
 
-static int ath10k_sdio_mbox_rx_fetch(struct ath10k *ar)
+static int ath10k_sdio_mbox_rx_fetch_bundle(struct ath10k *ar)
 {
 	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
+	struct ath10k_sdio_rx_data *pkt;
+	struct ath10k_htc_hdr *htc_hdr;
 	int ret, i;
+	u32 pkt_offset, virt_pkt_len;
 
+	virt_pkt_len = 0;
 	for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
-		ret = ath10k_sdio_mbox_rx_packet(ar,
-						 &ar_sdio->rx_pkts[i]);
+		virt_pkt_len += ar_sdio->rx_pkts[i].alloc_len;
+	}
+
+	if (virt_pkt_len < ATH10K_SDIO_DMA_BUF_SIZE) {
+		ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
+					 ar_sdio->vsg_buffer, virt_pkt_len);
 		if (ret)
 			goto err;
+	} else {
+		ath10k_err(ar, "size exceeding limit %d\n", virt_pkt_len);
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	pkt_offset = 0;
+	for (i = 0; i < ar_sdio->n_rx_pkts; i++) {
+		pkt = &ar_sdio->rx_pkts[i];
+		htc_hdr = (struct ath10k_htc_hdr *)(ar_sdio->vsg_buffer + pkt_offset);
+		pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
+
+		skb_put_data(pkt->skb, htc_hdr, pkt->act_len);
+		pkt->status = 0;
+		pkt_offset += pkt->alloc_len;
 	}
 
 	return 0;
 
 err:
 	/* Free all packets that was not successfully fetched. */
-	for (; i < ar_sdio->n_rx_pkts; i++)
+	for (i = 0; i < ar_sdio->n_rx_pkts; i++)
 		ath10k_sdio_mbox_free_rx_pkt(&ar_sdio->rx_pkts[i]);
 
+	ar_sdio->n_rx_pkts = 0;
+
 	return ret;
 }
 
@@ -715,7 +740,10 @@ static int ath10k_sdio_mbox_rxmsg_pending_handler(struct ath10k *ar,
 			 */
 			*done = false;
 
-		ret = ath10k_sdio_mbox_rx_fetch(ar);
+		if (ar_sdio->n_rx_pkts > 1)
+			ret = ath10k_sdio_mbox_rx_fetch_bundle(ar);
+		else
+			ret = ath10k_sdio_mbox_rx_fetch(ar);
 
 		/* Process fetched packets. This will potentially update
 		 * n_lookaheads depending on if the packets contain lookahead
@@ -1123,7 +1151,7 @@ static int ath10k_sdio_bmi_get_rx_lookahead(struct ath10k *ar)
 					 MBOX_HOST_INT_STATUS_ADDRESS,
 					 &rx_word);
 		if (ret) {
-			ath10k_warn(ar, "unable to read RX_LOOKAHEAD_VALID: %d\n", ret);
+			ath10k_warn(ar, "unable to read rx_lookahd: %d\n", ret);
 			return ret;
 		}
 
@@ -2018,6 +2046,12 @@ static int ath10k_sdio_probe(struct sdio_func *func,
 		goto err_core_destroy;
 	}
 
+	ar_sdio->vsg_buffer = devm_kmalloc(ar->dev, ATH10K_SDIO_VSG_BUF_SIZE, GFP_KERNEL);
+	if (!ar_sdio->vsg_buffer) {
+		ret = -ENOMEM;
+		goto err_core_destroy;
+	}
+
 	ar_sdio->irq_data.irq_en_reg =
 		devm_kzalloc(ar->dev, sizeof(struct ath10k_sdio_irq_enable_regs),
 			     GFP_KERNEL);
diff --git a/drivers/net/wireless/ath/ath10k/sdio.h b/drivers/net/wireless/ath/ath10k/sdio.h
index b8c7ac0..4896eca 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.h
+++ b/drivers/net/wireless/ath/ath10k/sdio.h
@@ -138,8 +138,8 @@ struct ath10k_sdio_irq_proc_regs {
 	u8 rx_lookahead_valid;
 	u8 host_int_status2;
 	u8 gmbox_rx_avail;
-	__le32 rx_lookahead[2];
-	__le32 rx_gmbox_lookahead_alias[2];
+	__le32 rx_lookahead[2 * ATH10K_HIF_MBOX_NUM_MAX];
+	__le32 int_status_enable;
 };
 
 struct ath10k_sdio_irq_enable_regs {
@@ -196,6 +196,9 @@ struct ath10k_sdio {
 	struct ath10k *ar;
 	struct ath10k_sdio_irq_data irq_data;
 
+	/* temporary buffer for sdio read */
+	u8 *vsg_buffer;
+
 	/* temporary buffer for BMI requests */
 	u8 *bmi_buf;
 
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 1/8] ath10k: adjust skb length in ath10k_sdio_mbox_rx_packet
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless
In-Reply-To: <1567416146-14403-1-git-send-email-wgong@codeaurora.org>

From: Nicolas Boichat <drinkcat@chromium.org>

When the FW bundles multiple packets, pkt->act_len may be incorrect
as it refers to the first packet only (however, the FW will only
bundle packets that fit into the same pkt->alloc_len).

Before this patch, the skb length would be set (incorrectly) to
pkt->act_len in ath10k_sdio_mbox_rx_packet, and then later manually
adjusted in ath10k_sdio_mbox_rx_process_packet.

The first problem is that ath10k_sdio_mbox_rx_process_packet does not
use proper skb_put commands to adjust the length (it directly changes
skb->len), so we end up with a mismatch between skb->head + skb->tail
and skb->data + skb->len. This is quite serious, and causes corruptions
in the TCP stack, as the stack tries to coalesce packets, and relies
on skb->tail being correct (that is, skb_tail_pointer must point to
the first byte_after_ the data).

Instead of re-adjusting the size in ath10k_sdio_mbox_rx_process_packet,
this moves the code to ath10k_sdio_mbox_rx_packet, and also add a
bounds check, as skb_put would crash the kernel if not enough space is
available.

Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00007-QCARMSWP-1.

Fixes: 8530b4e7b22bc3b ("ath10k: sdio: set skb len for all rx packets")
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Wen Gong <wgong@codeaurora.org>
---
v2: no this patch
v3: new added
v4: change commit log

 drivers/net/wireless/ath/ath10k/sdio.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c
index 8ed4fbd..1127e44 100644
--- a/drivers/net/wireless/ath/ath10k/sdio.c
+++ b/drivers/net/wireless/ath/ath10k/sdio.c
@@ -381,16 +381,11 @@ static int ath10k_sdio_mbox_rx_process_packet(struct ath10k *ar,
 	struct ath10k_htc_hdr *htc_hdr = (struct ath10k_htc_hdr *)skb->data;
 	bool trailer_present = htc_hdr->flags & ATH10K_HTC_FLAG_TRAILER_PRESENT;
 	enum ath10k_htc_ep_id eid;
-	u16 payload_len;
 	u8 *trailer;
 	int ret;
 
-	payload_len = le16_to_cpu(htc_hdr->len);
-	skb->len = payload_len + sizeof(struct ath10k_htc_hdr);
-
 	if (trailer_present) {
-		trailer = skb->data + sizeof(*htc_hdr) +
-			  payload_len - htc_hdr->trailer_len;
+		trailer = skb->data + skb->len - htc_hdr->trailer_len;
 
 		eid = pipe_id_to_eid(htc_hdr->eid);
 
@@ -632,13 +627,29 @@ static int ath10k_sdio_mbox_rx_packet(struct ath10k *ar,
 {
 	struct ath10k_sdio *ar_sdio = ath10k_sdio_priv(ar);
 	struct sk_buff *skb = pkt->skb;
+	struct ath10k_htc_hdr *htc_hdr;
 	int ret;
 
 	ret = ath10k_sdio_readsb(ar, ar_sdio->mbox_info.htc_addr,
 				 skb->data, pkt->alloc_len);
+
+	if (!ret) {
+		/* Update actual length. The original length may be incorrect,
+		 * as the FW will bundle multiple packets as long as their sizes
+		 * fit within the same aligned length (pkt->alloc_len).
+		 */
+		htc_hdr = (struct ath10k_htc_hdr *)skb->data;
+		pkt->act_len = le16_to_cpu(htc_hdr->len) + sizeof(*htc_hdr);
+		if (pkt->act_len <= pkt->alloc_len) {
+			skb_put(skb, pkt->act_len);
+		} else {
+			ath10k_warn(ar, "rx packet too large (%zu > %zu)\n",
+				    pkt->act_len, pkt->alloc_len);
+			ret = -EMSGSIZE;
+		}
+	}
+
 	pkt->status = ret;
-	if (!ret)
-		skb_put(skb, pkt->act_len);
 
 	return ret;
 }
-- 
1.9.1


^ permalink raw reply related

* [PATCH v4 0/8] ath10k: improve throughout of tcp/udp TX/RX of sdio
From: Wen Gong @ 2019-09-02  9:22 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless

The bottleneck of throughout on sdio chip is the bus bandwidth, to the
patches are all to increase the use ratio of sdio bus.

                      udp-rx    udp-tx    tcp-rx    tcp-tx
without patches(Mbps)  320        180       170       151
with patches(Mbps)     450        410       400       320

These patches only affect sdio bus chip, explanation is mentioned in each
patch's commit log.

Alagu Sankar (1):
  ath10k: enable RX bundle receive for sdio
v2: fix incorrect skb tail of rx bundle in ath10k_sdio_mbox_rx_process_packet
v3: change some code style
split fix incorrect skb tail of rx bundle to patch "adjust skb length in ath10k_sdio_mbox_rx_packet"
v4: add err handle in ath10k_sdio_mbox_rx_fetch_bundle

Nicolas Boichat (1):
  ath10k: adjust skb length in ath10k_sdio_mbox_rx_packet
v2: no this patch
v3: new added
v4: change commit log

Wen Gong (6):
  ath10k: change max RX bundle size from 8 to 32 for sdio
v2: change macro HTC_GET_BUNDLE_COUNT
v3: change some code style
v4: add macro ATH10K_HTC_FLAG_BUNDLE_MASK

  ath10k: add workqueue for RX path of sdio
v2: no change
v3: change some code style
v4: no change

  ath10k: disable TX complete indication of htt for sdio
v2: change some code style
v3: change some code style
v4: no change

  ath10k: add htt TX bundle for sdio
v2: no change
v3: change some code style
v4: no change

  ath10k: enable alt data of TX path for sdio
v2: no change
v3: change some code style
v4: add macro ATH10K_HTC_MSG_READY_EXT_ALT_DATA_MASK

  ath10k: enable napi on RX path for sdio
v2: no change
v3: change some code style
v4: change some code style

 drivers/net/wireless/ath/ath10k/core.c   |  42 +++-
 drivers/net/wireless/ath/ath10k/core.h   |   4 +-
 drivers/net/wireless/ath/ath10k/hif.h    |   9 +
 drivers/net/wireless/ath/ath10k/htc.c    | 377 ++++++++++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/htc.h    |  49 +++-
 drivers/net/wireless/ath/ath10k/htt.c    |  15 ++
 drivers/net/wireless/ath/ath10k/htt.h    |  20 +-
 drivers/net/wireless/ath/ath10k/htt_rx.c |  80 ++++++-
 drivers/net/wireless/ath/ath10k/htt_tx.c |  38 +++-
 drivers/net/wireless/ath/ath10k/hw.h     |   2 +-
 drivers/net/wireless/ath/ath10k/sdio.c   | 281 ++++++++++++++++++++---
 drivers/net/wireless/ath/ath10k/sdio.h   |  31 ++-
 12 files changed, 851 insertions(+), 97 deletions(-)

-- 
1.9.1


^ permalink raw reply

* RE: [PATCH 0/8] rtw88: enhance and stabilize T-Put performance
From: Tony Chuang @ 2019-09-02  9:06 UTC (permalink / raw)
  To: Tony Chuang, kvalo@codeaurora.org
  Cc: linux-wireless@vger.kernel.org, briannorris@chromium.org,
	sgruszka@redhat.com
In-Reply-To: <1565174405-2689-1-git-send-email-yhchuang@realtek.com>

> From: Yan-Hsuan Chuang <yhchuang@realtek.com>
> 
> This patch set could enhance and stabilize the throughput
> performance for rtw88, especially for RTL8822CE.
> 
> The RFKs, such as IQK and DPK, can make sure the radio
> components works more reliable. They reduce the distortion
> and nonlinearity that the components inherently have.
> 
> The parameter update is a result that is fine-tuned to
> optimize the hardware utilization.
> 
> And CCK PD can help to adjust CCK signal threshold to
> reduce FAs, and get a better TRX performance in 2.4G.
> 
> Interrupt migration helps some slower platforms not to
> over utilize the host CPU, reduce its loading.
> 
> 
> Chin-Yen Lee (1):
>   rtw88: 8822c: update pwr_seq to v13
> 
> Tsang-Shian Lin (1):
>   rtw88: 8822c: Enable interrupt migration
> 
> Tzu-En Huang (2):
>   rtw88: 8822c: add SW DPK support
>   rtw88: add dynamic cck pd mechanism
> 
> Yan-Hsuan Chuang (4):
>   rtw88: 8822c: update PHY parameter to v38
>   rtw88: 8822c: add FW IQK support
>   rtw88: move IQK/DPK into phy_calibration
>   rtw88: allows to receive AMSDU in AMPDU
> 
>  drivers/net/wireless/realtek/rtw88/coex.c          |    2 +-
>  drivers/net/wireless/realtek/rtw88/coex.h          |    1 +
>  drivers/net/wireless/realtek/rtw88/mac80211.c      |    2 +-
>  drivers/net/wireless/realtek/rtw88/main.c          |    1 +
>  drivers/net/wireless/realtek/rtw88/main.h          |   56 +-
>  drivers/net/wireless/realtek/rtw88/phy.c           |  143 +
>  drivers/net/wireless/realtek/rtw88/phy.h           |    2 +
>  drivers/net/wireless/realtek/rtw88/reg.h           |   17 +
>  drivers/net/wireless/realtek/rtw88/rtw8822b.c      |    7 +-
>  drivers/net/wireless/realtek/rtw88/rtw8822c.c      | 1178 +++-
>  drivers/net/wireless/realtek/rtw88/rtw8822c.h      |   86 +
>  .../net/wireless/realtek/rtw88/rtw8822c_table.c    | 6930
> ++++++++++++++------
>  .../net/wireless/realtek/rtw88/rtw8822c_table.h    |    3 +
>  13 files changed, 6323 insertions(+), 2105 deletions(-)
> 
> --
> 2.7.4
> 
> 

This a gentle ping for the series.
Any suggestion is welcome :)

Yan-Hsuan

^ permalink raw reply

* Re: [PATCH] iwlwifi: mvm: Move static keyword to the front of declarations
From: Luca Coelho @ 2019-09-02  7:52 UTC (permalink / raw)
  To: Krzysztof Wilczynski, Kalle Valo
  Cc: Johannes Berg, Emmanuel Grumbach, Intel Linux Wireless,
	David S. Miller, Sara Sharon, Shaul Triebitz, Liad Kaufman,
	linux-wireless, netdev, linux-kernel
In-Reply-To: <20190831220108.10602-1-kw@linux.com>

On Sun, 2019-09-01 at 00:01 +0200, Krzysztof Wilczynski wrote:
> Move the static keyword to the front of declarations of
> he_if_types_ext_capa_sta and he_iftypes_ext_capa, and
> resolve the following compiler warnings that can be seen
> when building with warnings enabled (W=1):
> 
> drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:427:1: warning:
>   ‘static’ is not at beginning of declaration [-Wold-style-declaration]
> 
> drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c:434:1: warning:
>   ‘static’ is not at beginning of declaration [-Wold-style-declaration]
> 
> Signed-off-by: Krzysztof Wilczynski <kw@linux.com>
> ---
> Related: https://lore.kernel.org/r/20190827233017.GK9987@google.com
> 
>  drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
> index d6499763f0dd..937a843fed56 100644
> --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
> +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
> @@ -424,14 +424,14 @@ int iwl_mvm_init_fw_regd(struct iwl_mvm *mvm)
>  	return ret;
>  }
>  
> -const static u8 he_if_types_ext_capa_sta[] = {
> +static const u8 he_if_types_ext_capa_sta[] = {
>  	 [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
>  	 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
>  	 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
>  	 [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
>  };
>  
> -const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
> +static const struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
>  	{
>  		.iftype = NL80211_IFTYPE_STATION,
>  		.extended_capabilities = he_if_types_ext_capa_sta,

Thanks for your patch! Though we already have this change in our
internal tree (submitted by YueHaibing) and it will reach the mainline
soon.

--
Cheers,
Luca.


^ permalink raw reply

* [PATCH v3] rtw88: pci: enable MSI interrupt
From: yhchuang @ 2019-09-02  7:02 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, jano.vesely, drake, linux, briannorris, gojun077

From: Yu-Yen Ting <steventing@realtek.com>

MSI interrupt should be enabled on certain platform.

Add a module parameter disable_msi to disable MSI interrupt,
driver will then use legacy interrupt instead.

One could rebind the PCI device, probe() will pick up the
new value of the module parameter. Such as:

    echo '0000:01:00.0' > /sys/bus/pci/drivers/rtw_pci/unbind
    echo '0000:01:00.0' > /sys/bus/pci/drivers/rtw_pci/bind

Tested-by: Ján Veselý <jano.vesely@gmail.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Yu-Yen Ting <steventing@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
---

v1 -> v2
    * Module parameter file mode change from 0444 to 0644
      This allows to change interrupt mode at run-time,
      as user rebind the PCI device
    * Print out returned value for pci_enable_msi(), as the
      value is not going to be returned to upper stacks
    * Print out request_irq() return value if it failed

v2 -> v3
    * pci_enable_msi() is deprecated, use pci_alloc_irq_vectors()
    * Add a comment to describe why it is required to disable HIMR


 drivers/net/wireless/realtek/rtw88/pci.c | 50 ++++++++++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index 00ef229..f13a325 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -11,6 +11,10 @@
 #include "fw.h"
 #include "debug.h"
 
+static bool rtw_disable_msi;
+module_param_named(disable_msi, rtw_disable_msi, bool, 0644);
+MODULE_PARM_DESC(disable_msi, "Set Y to disable MSI interrupt support");
+
 static u32 rtw_pci_tx_queue_idx_addr[] = {
 	[RTW_TX_QUEUE_BK]	= RTK_PCI_TXBD_IDX_BKQ,
 	[RTW_TX_QUEUE_BE]	= RTK_PCI_TXBD_IDX_BEQ,
@@ -872,6 +876,12 @@ static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev)
 	if (!rtwpci->irq_enabled)
 		goto out;
 
+	/* Disable HIMR here to avoid new HISR flag being raised before
+	 * the HISRs have been Write-1-cleared. If not all of the HISRs
+	 * are cleared, interrupt will not be generated when a new HISR
+	 * flag is set.
+	 */
+	rtw_pci_disable_interrupt(rtwdev, rtwpci);
 	rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status);
 
 	if (irq_status[0] & IMR_MGNTDOK)
@@ -891,6 +901,8 @@ static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev)
 	if (irq_status[0] & IMR_ROK)
 		rtw_pci_rx_isr(rtwdev, rtwpci, RTW_RX_QUEUE_MPDU);
 
+	rtw_pci_enable_interrupt(rtwdev, rtwpci);
+
 out:
 	spin_unlock(&rtwpci->irq_lock);
 
@@ -1098,6 +1110,39 @@ static struct rtw_hci_ops rtw_pci_ops = {
 	.write_data_h2c = rtw_pci_write_data_h2c,
 };
 
+static int rtw_pci_request_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+	unsigned int flags = PCI_IRQ_LEGACY;
+	int ret;
+
+	if (!rtw_disable_msi)
+		flags |= PCI_IRQ_MSI;
+
+	ret = pci_alloc_irq_vectors(pdev, 1, 1, flags);
+	if (ret < 0) {
+		rtw_err(rtwdev, "failed to alloc PCI irq vectors\n");
+		return ret;
+	}
+
+	ret = request_irq(pdev->irq, &rtw_pci_interrupt_handler, IRQF_SHARED,
+			  KBUILD_MODNAME, rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to request irq %d\n", ret);
+		pci_free_irq_vectors(pdev);
+	}
+
+	return ret;
+}
+
+static void rtw_pci_free_irq(struct rtw_dev *rtwdev, struct pci_dev *pdev)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+	free_irq(pdev->irq, rtwdev);
+	pci_free_irq_vectors(pdev);
+}
+
 static int rtw_pci_probe(struct pci_dev *pdev,
 			 const struct pci_device_id *id)
 {
@@ -1152,8 +1197,7 @@ static int rtw_pci_probe(struct pci_dev *pdev,
 		goto err_destroy_pci;
 	}
 
-	ret = request_irq(pdev->irq, &rtw_pci_interrupt_handler,
-			  IRQF_SHARED, KBUILD_MODNAME, rtwdev);
+	ret = rtw_pci_request_irq(rtwdev, pdev);
 	if (ret) {
 		ieee80211_unregister_hw(hw);
 		goto err_destroy_pci;
@@ -1192,7 +1236,7 @@ static void rtw_pci_remove(struct pci_dev *pdev)
 	rtw_pci_disable_interrupt(rtwdev, rtwpci);
 	rtw_pci_destroy(rtwdev, pdev);
 	rtw_pci_declaim(rtwdev, pdev);
-	free_irq(rtwpci->pdev->irq, rtwdev);
+	rtw_pci_free_irq(rtwdev, pdev);
 	rtw_core_deinit(rtwdev);
 	ieee80211_free_hw(hw);
 }
-- 
2.7.4


^ permalink raw reply related

* Re: [PATCH v2] rtw88: pci: enable MSI interrupt
From: Daniel Drake @ 2019-09-02  3:13 UTC (permalink / raw)
  To: Tony Chuang
  Cc: Ján Veselý, briannorris@chromium.org,
	gojun077@gmail.com, kvalo@codeaurora.org, linux-wireless,
	linux@endlessm.com
In-Reply-To: <F7CD281DE3E379468C6D07993EA72F84D18C1ABF@RTITMBSVM04.realtek.com.tw>

On Mon, Sep 2, 2019 at 11:02 AM Tony Chuang <yhchuang@realtek.com> wrote:
> Indeed it is a little strange but it works like that, if I don't disable HIMR,
> interrupt could be lost and never gets into interrupt handler again.
> If so, the interrupt will be stopped, and TX/RX path will be freezed.

OK, thanks for checking & explaining.

It's a bit hard to put in words as we have seen, but it would be good
if you could try to summarise this unusual design in the commit
message or in a code comment.

Thanks!
Daniel

^ permalink raw reply

* RE: [PATCH v2] rtw88: pci: enable MSI interrupt
From: Tony Chuang @ 2019-09-02  3:02 UTC (permalink / raw)
  To: Daniel Drake
  Cc: Ján Veselý, briannorris@chromium.org,
	gojun077@gmail.com, kvalo@codeaurora.org, linux-wireless,
	linux@endlessm.com
In-Reply-To: <CAD8Lp46=Adn3GWAkHspdqBHVjz6sekET9nzNOCnW7sCFGtoeDQ@mail.gmail.com>

Hi,

A few scattered comments below.

> From: Daniel Drake [mailto:drake@endlessm.com]
> 
> On Tue, Aug 27, 2019 at 8:11 PM Tony Chuang <yhchuang@realtek.com>
> wrote:
> > Because there's a race condition between SW/HW when clearing the ISR.
> > If interrupt comes after reading ISR and before write-1-clear, the interrupt
> > controller would have interrupt status raised, and never issue interrupt
> > signal to host when other new interrupts status are raised.
> >
> > To avoid this, driver requires to protect the ISR write-1-clear process by
> > disabling the IMR.
> 
> Just to be clear with an example of two interrupts in quick
> succession, first ROK then MGNTDOK. I would expect the hardware to
> behave as follows:
> 
> 1. Interrupts are enabled in HIMR reg. MSI is in use.
> --- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
> then raises a MSI interrupt.
> --- Interrupt controller receives this and begins handling it:
> 2. rtw88 interrupt handler begins execution
> 3. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
> --- Hardware needs to flag MGNTDOK condition, so it sets the MGNTDOK
> bit in HISR and raises another interrupt.
> --- Interrupt controller queues this interrupt since it's in the
> middle of handling the original ROK interrupt.
> 4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
> written back to clear them. In this case just the ROK bit is written
> back to unset the interrupt. MGNTDOK interrupt is left pending (not
> yet noticed by the driver)
> 5. Interrupt handler continues & finishes handling the RX event.
> 6. With the first interrupt done, interrupt controller handles the
> queued interrupt and causes rtw88 interrupt handler to execute again
> 7. rtw88 interrupt handler handles and MGNTDOK interrupt.
> 
> 
> But are you saying it does not do this, and the behaviour (without
> your change) is instead:
> 
> 1. Interrupts are enabled in HIMR reg. MSI is in use.
> --- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
> then raises a MSI interrupt.
> --- Interrupt controller receives this and begins handling it:
> 2. rtw88 interrupt handler begins execution
> 3. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
> --- Hardware needs to flag MGNTDOK condition, so it sets the MGNTDOK
> bit in HISR. However it does NOT raise an interrupt since other bits
> in HISR were still set at this time.
> 4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
> written back. In this case just the ROK bit is written back to unset
> the interrupt. MGNTDOK interrupt is left pending (not yet noticed by
> the driver)
> 5. Interrupt handler continues & finishes handling the RX event.
> 6. MGNTDOK interrupt is left pending, and no more interrupts will be
> generated by the hardware because even if it sets more HISR bits, the
> MGNTDOK bit was already set so it doesn't raise more interrupts.
> 
> i.e. you're effectively saying that the hardware will *only* generate
> an interrupt when *all* HISR bits were zero immediately before the new
> interrupt HISR bit is set?

Yes, that's what I am saying about. I know it looks strange, but I think
this is Realtek's design. And as far as I know this has been used for 9-10
years.

> 
> 
> And then with your change applied it would look like this:
> 
> 1. Interrupts are enabled in HIMR reg. MSI is in use.
> --- Hardware needs to flag RX condition. It sets IMR_ROK flag in HISR,
> then raises a MSI interrupt.
> --- Interrupt controller receives this and begins handling it:
> 2. rtw88 interrupt handler begins execution
> 3. Interrupts are disabled in HIMR reg.
> 4. rtw_pci_irq_recognized()  reads HISR values. ROK is the only bit set.
> --- Hardware needs to flag MGNTDOK condition, however because
> interrupts are disabled in HIMR, it simply queues this condition
> internally, without affecting HISR values, without generating another
> interrupt.

This might be a little different here, I think the MGNTDOK flag is still set.
But new interrupt will not be generated, until HIMR is re-enabled, and I
think re-enabling the HIMR could trigger the hardware to check if any
HISR bit is set, and then generate interrupt.

> 4. Back in rtw_pci_irq_recognized(), the HISR values from earlier are
> written back. In this case just the ROK bit is written back to unset
> the interrupt. HISR is now value 0.
> 5. Interrupt handler handles the RX event.
> 6. Interrupt handler re-enables interrupts in HIMR just before finishing.
> --- In response, hardware checks its internal queue and realises that
> a MGNTDOK condition is pending. It sets the MGNTDOK bit in HISR and
> raises a new interrupt.
> 
> Is that right? It seems like strange behaviour on the hardware side.
> 

Indeed it is a little strange but it works like that, if I don't disable HIMR,
interrupt could be lost and never gets into interrupt handler again.
If so, the interrupt will be stopped, and TX/RX path will be freezed.

> 
> Thanks,
> Daniel
> 

Thanks,
Yan-Hsuan

^ permalink raw reply

* Re: [PATCH 2/2] Fix a NULL-ptr-deref bug in ath10k_usb_alloc_urb_from_pipe
From: Hui Peng @ 2019-09-01 19:45 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: kvalo, davem, Mathias Payer, ath10k, linux-wireless, netdev,
	linux-kernel
In-Reply-To: <20190831213139.GA32507@roeck-us.net>

On 8/31/19 5:31 PM, Guenter Roeck wrote:
> Hi,
>
> On Sat, Aug 03, 2019 at 08:31:01PM -0400, Hui Peng wrote:
>> The `ar_usb` field of `ath10k_usb_pipe_usb_pipe` objects
>> are initialized to point to the containing `ath10k_usb` object
>> according to endpoint descriptors read from the device side, as shown
>> below in `ath10k_usb_setup_pipe_resources`:
>>
>> for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
>>         endpoint = &iface_desc->endpoint[i].desc;
>>
>>         // get the address from endpoint descriptor
>>         pipe_num = ath10k_usb_get_logical_pipe_num(ar_usb,
>>                                                 endpoint->bEndpointAddress,
>>                                                 &urbcount);
>>         ......
>>         // select the pipe object
>>         pipe = &ar_usb->pipes[pipe_num];
>>
>>         // initialize the ar_usb field
>>         pipe->ar_usb = ar_usb;
>> }
>>
>> The driver assumes that the addresses reported in endpoint
>> descriptors from device side  to be complete. If a device is
>> malicious and does not report complete addresses, it may trigger
>> NULL-ptr-deref `ath10k_usb_alloc_urb_from_pipe` and
>> `ath10k_usb_free_urb_to_pipe`.
>>
>> This patch fixes the bug by preventing potential NULL-ptr-deref.
>>
>> Signed-off-by: Hui Peng <benquike@gmail.com>
>> Reported-by: Hui Peng <benquike@gmail.com>
>> Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
> This patch fixes CVE-2019-15099, which has CVSS scores of 7.5 (CVSS 3.0)
> and 7.8 (CVSS 2.0). Yet, I don't find it in the upstream kernel or in Linux
> next.
>
> Is the patch going to be applied to the upstream kernel anytime soon ? If
> not, is there reason to believe that its severity may not be as high as the
> CVSS score indicates ?
The score was assigned by MITRE.
Same as previous ones, it is under review, once passed, it will be applied.
> Thanks,
> Guenter
>
>> ---
>>  drivers/net/wireless/ath/ath10k/usb.c | 8 ++++++++
>>  1 file changed, 8 insertions(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c
>> index e1420f67f776..14d86627b47f 100644
>> --- a/drivers/net/wireless/ath/ath10k/usb.c
>> +++ b/drivers/net/wireless/ath/ath10k/usb.c
>> @@ -38,6 +38,10 @@ ath10k_usb_alloc_urb_from_pipe(struct ath10k_usb_pipe *pipe)
>>  	struct ath10k_urb_context *urb_context = NULL;
>>  	unsigned long flags;
>>  
>> +	/* bail if this pipe is not initialized */
>> +	if (!pipe->ar_usb)
>> +		return NULL;
>> +
>>  	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
>>  	if (!list_empty(&pipe->urb_list_head)) {
>>  		urb_context = list_first_entry(&pipe->urb_list_head,
>> @@ -55,6 +59,10 @@ static void ath10k_usb_free_urb_to_pipe(struct ath10k_usb_pipe *pipe,
>>  {
>>  	unsigned long flags;
>>  
>> +	/* bail if this pipe is not initialized */
>> +	if (!pipe->ar_usb)
>> +		return NULL;
>> +
>>  	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
>>  
>>  	pipe->urb_cnt++;
>> -- 
>> 2.22.0
>>

^ permalink raw reply

* [PATCH 4/4] rtlwifi: rtl8192cu: Convert inline routines to little-endian words
From: Larry Finger @ 2019-09-01 15:47 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190901154706.24193-1-Larry.Finger@lwfinger.net>

In this step, the read/write routines for the descriptors are converted
to use __le32 quantities, thus a lot of casts can be removed. Callback
routines still use the 8-bit arrays, but these are changed within the
specified routine.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.c   |   2 +-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c   |  26 ++-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h   | 220 ++++++++++-----------
 3 files changed, 127 insertions(+), 121 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index a2f878de0a70..c8daad1e749f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -638,7 +638,7 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
 	u32 rssi, total_rssi = 0;
 	bool in_powersavemode = false;
 	bool is_cck_rate;
-	u8 *pdesc = (u8 *)p_desc;
+	__le32 *pdesc = (__le32 *)p_desc;
 
 	is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc->rxmcs);
 	pstats->packet_matchbssid = packet_match_bssid;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index a9f16868791f..fc526477740f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -282,10 +282,11 @@ static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw,
 bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
 			   struct rtl_stats *stats,
 			   struct ieee80211_rx_status *rx_status,
-			   u8 *pdesc, struct sk_buff *skb)
+			   u8 *pdesc8, struct sk_buff *skb)
 {
 	struct rx_fwinfo_92c *p_drvinfo;
-	struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc;
+	struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc8;
+	__le32 *pdesc = (__le32 *)pdesc8;
 	u32 phystatus = get_rx_desc_phy_status(pdesc);
 
 	stats->length = (u16)get_rx_desc_pkt_len(pdesc);
@@ -339,7 +340,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
 		 (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb);
 	u32 skb_len, pkt_len, drvinfo_len;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 *rxdesc;
+	__le32 *rxdesc;
 	struct rtl_stats stats = {
 		.signal = 0,
 		.rate = 0,
@@ -350,7 +351,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
 	struct ieee80211_hdr *hdr;
 
 	memset(rx_status, 0, sizeof(*rx_status));
-	rxdesc	= skb->data;
+	rxdesc	= (__le32 *)skb->data;
 	skb_len	= skb->len;
 	drvinfo_len = (get_rx_desc_drvinfo_size(rxdesc) * RTL_RX_DRV_INFO_UNIT);
 	pkt_len		= get_rx_desc_pkt_len(rxdesc);
@@ -440,7 +441,7 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw,
 
 /*======================================== trx ===============================*/
 
-static void _rtl_fill_usb_tx_desc(u8 *txdesc)
+static void _rtl_fill_usb_tx_desc(__le32 *txdesc)
 {
 	set_tx_desc_own(txdesc, 1);
 	set_tx_desc_last_seg(txdesc, 1);
@@ -450,7 +451,7 @@ static void _rtl_fill_usb_tx_desc(u8 *txdesc)
 /**
  *	For HW recovery information
  */
-static void _rtl_tx_desc_checksum(u8 *txdesc)
+static void _rtl_tx_desc_checksum(__le32 *txdesc)
 {
 	__le16 *ptr = (__le16 *)txdesc;
 	u16	checksum = 0;
@@ -483,11 +484,13 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
 	u16 pktlen = skb->len;
 	enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc,
 						skb_get_queue_mapping(skb));
-	u8 *txdesc;
+	u8 *txdesc8;
+	__le32 *txdesc;
 
 	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
 	rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc);
-	txdesc = skb_push(skb, RTL_TX_HEADER_SIZE);
+	txdesc8 = skb_push(skb, RTL_TX_HEADER_SIZE);
+	txdesc = (__le32 *)txdesc8;
 	memset(txdesc, 0, RTL_TX_HEADER_SIZE);
 	set_tx_desc_pkt_size(txdesc, pktlen);
 	set_tx_desc_linip(txdesc, 0);
@@ -597,9 +600,11 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
 	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n");
 }
 
-void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc8,
 			      u32 buffer_len, bool is_pspoll)
 {
+	__le32 *pdesc = (__le32 *)pdesc8;
+
 	/* Clear all status */
 	memset(pdesc, 0, RTL_TX_HEADER_SIZE);
 	set_tx_desc_first_seg(pdesc, 1); /* bFirstSeg; */
@@ -622,13 +627,14 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
 }
 
 void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
-			     u8 *pdesc, bool firstseg,
+			     u8 *pdesc8, bool firstseg,
 			     bool lastseg, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u8 fw_queue = QSLT_BEACON;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	__le16 fc = hdr->frame_control;
+	__le32 *pdesc = (__le32 *)pdesc8;
 
 	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
 	if (firstseg)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index 3d8a913d799d..171fe39dfb0c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -73,80 +73,80 @@ struct rx_drv_info_92c {
 /* macros to read various fields in RX descriptor */
 
 /* DWORD 0 */
-static inline u32 get_rx_desc_pkt_len(u8 *__rxdesc)
+static inline u32 get_rx_desc_pkt_len(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(13, 0));
+	return le32_get_bits(*__rxdesc, GENMASK(13, 0));
 }
 
-static inline u32 get_rx_desc_crc32(u8 *__rxdesc)
+static inline u32 get_rx_desc_crc32(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, BIT(14));
+	return le32_get_bits(*__rxdesc, BIT(14));
 }
 
-static inline u32 get_rx_desc_icv(u8 *__rxdesc)
+static inline u32 get_rx_desc_icv(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, BIT(15));
+	return le32_get_bits(*__rxdesc, BIT(15));
 }
 
-static inline u32 get_rx_desc_drvinfo_size(u8 *__rxdesc)
+static inline u32 get_rx_desc_drvinfo_size(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(19, 16));
+	return le32_get_bits(*__rxdesc, GENMASK(19, 16));
 }
 
-static inline u32 get_rx_desc_shift(u8 *__rxdesc)
+static inline u32 get_rx_desc_shift(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(25, 24));
+	return le32_get_bits(*__rxdesc, GENMASK(25, 24));
 }
 
-static inline u32 get_rx_desc_phy_status(u8 *__rxdesc)
+static inline u32 get_rx_desc_phy_status(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, BIT(26));
+	return le32_get_bits(*__rxdesc, BIT(26));
 }
 
-static inline u32 get_rx_desc_swdec(u8 *__rxdesc)
+static inline u32 get_rx_desc_swdec(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)__rxdesc, BIT(27));
+	return le32_get_bits(*__rxdesc, BIT(27));
 }
 
 
 /* DWORD 1 */
-static inline u32 get_rx_desc_paggr(u8 *__rxdesc)
+static inline u32 get_rx_desc_paggr(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(14));
+	return le32_get_bits(*(__rxdesc + 1), BIT(14));
 }
 
-static inline u32 get_rx_desc_faggr(u8 *__rxdesc)
+static inline u32 get_rx_desc_faggr(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(15));
+	return le32_get_bits(*(__rxdesc + 1), BIT(15));
 }
 
 
 /* DWORD 3 */
-static inline u32 get_rx_desc_rx_mcs(u8 *__rxdesc)
+static inline u32 get_rx_desc_rx_mcs(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 12), GENMASK(5, 0));
+	return le32_get_bits(*(__rxdesc + 3), GENMASK(5, 0));
 }
 
-static inline u32 get_rx_desc_rx_ht(u8 *__rxdesc)
+static inline u32 get_rx_desc_rx_ht(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(6));
+	return le32_get_bits(*(__rxdesc + 3), BIT(6));
 }
 
-static inline u32 get_rx_desc_splcp(u8 *__rxdesc)
+static inline u32 get_rx_desc_splcp(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(8));
+	return le32_get_bits(*(__rxdesc + 3), BIT(8));
 }
 
-static inline u32 get_rx_desc_bw(u8 *__rxdesc)
+static inline u32 get_rx_desc_bw(__le32 *__rxdesc)
 {
-	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(9));
+	return le32_get_bits(*(__rxdesc + 3), BIT(9));
 }
 
 
 /* DWORD 5 */
-static inline u32 get_rx_desc_tsfl(u8 *__rxdesc)
+static inline u32 get_rx_desc_tsfl(__le32 *__rxdesc)
 {
-	return le32_to_cpu(*((__le32 *)(__rxdesc + 20)));
+	return le32_to_cpu(*((__rxdesc + 5)));
 }
 
 
@@ -155,223 +155,223 @@ static inline u32 get_rx_desc_tsfl(u8 *__rxdesc)
 /* macros to set various fields in TX descriptor */
 
 /* Dword 0 */
-static inline void set_tx_desc_pkt_size(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_pkt_size(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(15, 0));
+	le32p_replace_bits(__txdesc, __value, GENMASK(15, 0));
 }
 
-static inline void set_tx_desc_offset(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_offset(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(23, 16));
+	le32p_replace_bits(__txdesc, __value, GENMASK(23, 16));
 }
 
-static inline void set_tx_desc_bmc(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_bmc(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(24));
+	le32p_replace_bits(__txdesc, __value, BIT(24));
 }
 
-static inline void set_tx_desc_htc(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_htc(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(25));
+	le32p_replace_bits(__txdesc, __value, BIT(25));
 }
 
-static inline void set_tx_desc_last_seg(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_last_seg(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(26));
+	le32p_replace_bits(__txdesc, __value, BIT(26));
 }
 
-static inline void set_tx_desc_first_seg(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_first_seg(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(27));
+	le32p_replace_bits(__txdesc, __value, BIT(27));
 }
 
-static inline void set_tx_desc_linip(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_linip(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(28));
+	le32p_replace_bits(__txdesc, __value, BIT(28));
 }
 
-static inline void set_tx_desc_own(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_own(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(31));
+	le32p_replace_bits(__txdesc, __value, BIT(31));
 }
 
 
 /* Dword 1 */
-static inline void set_tx_desc_macid(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_macid(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(4, 0));
+	le32p_replace_bits((__txdesc + 1), __value, GENMASK(4, 0));
 }
 
-static inline void set_tx_desc_agg_enable(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_agg_enable(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(5));
+	le32p_replace_bits((__txdesc + 1), __value, BIT(5));
 }
 
-static inline void set_tx_desc_agg_break(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_agg_break(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(6));
+	le32p_replace_bits((__txdesc + 1), __value, BIT(6));
 }
 
-static inline void set_tx_desc_rdg_enable(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rdg_enable(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(7));
+	le32p_replace_bits((__txdesc + 1), __value, BIT(7));
 }
 
-static inline void set_tx_desc_queue_sel(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_queue_sel(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(12, 8));
+	le32p_replace_bits((__txdesc + 1), __value, GENMASK(12, 8));
 }
 
-static inline void set_tx_desc_rate_id(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rate_id(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(19, 16));
+	le32p_replace_bits((__txdesc + 1), __value, GENMASK(19, 16));
 }
 
-static inline void set_tx_desc_nav_use_hdr(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_nav_use_hdr(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(20));
+	le32p_replace_bits((__txdesc + 1), __value, BIT(20));
 }
 
-static inline void set_tx_desc_sec_type(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_sec_type(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(23, 22));
+	le32p_replace_bits((__txdesc + 1), __value, GENMASK(23, 22));
 }
 
-static inline void set_tx_desc_pkt_offset(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_pkt_offset(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(30, 26));
+	le32p_replace_bits((__txdesc + 1), __value, GENMASK(30, 26));
 }
 
 
 /* Dword 2 */
-static inline void set_tx_desc_more_frag(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_more_frag(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, BIT(17));
+	le32p_replace_bits((__txdesc + 2), __value, BIT(17));
 }
 
-static inline void set_tx_desc_ampdu_density(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_ampdu_density(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, GENMASK(22, 20));
+	le32p_replace_bits((__txdesc + 2), __value, GENMASK(22, 20));
 }
 
 
 /* Dword 3 */
-static inline void set_tx_desc_seq(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_seq(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(27, 16));
+	le32p_replace_bits((__txdesc + 3), __value, GENMASK(27, 16));
 }
 
-static inline void set_tx_desc_pkt_id(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_pkt_id(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(31, 28));
+	le32p_replace_bits((__txdesc + 3), __value, GENMASK(31, 28));
 }
 
 
 /* Dword 4 */
-static inline void set_tx_desc_rts_rate(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_rate(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(4, 0));
+	le32p_replace_bits((__txdesc + 4), __value, GENMASK(4, 0));
 }
 
-static inline void set_tx_desc_qos(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_qos(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(6));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(6));
 }
 
-static inline void set_tx_desc_hwseq_en(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_hwseq_en(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(7));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(7));
 }
 
-static inline void set_tx_desc_use_rate(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_use_rate(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(8));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(8));
 }
 
-static inline void set_tx_desc_disable_fb(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_disable_fb(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(10));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(10));
 }
 
-static inline void set_tx_desc_cts2self(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_cts2self(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(11));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(11));
 }
 
-static inline void set_tx_desc_rts_enable(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_enable(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(12));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(12));
 }
 
-static inline void set_tx_desc_hw_rts_enable(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_hw_rts_enable(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(13));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(13));
 }
 
-static inline void set_tx_desc_data_sc(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_data_sc(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(21, 20));
+	le32p_replace_bits((__txdesc + 4), __value, GENMASK(21, 20));
 }
 
-static inline void set_tx_desc_data_bw(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_data_bw(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(25));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(25));
 }
 
-static inline void set_tx_desc_rts_short(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_short(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(26));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(26));
 }
 
-static inline void set_tx_desc_rts_bw(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_bw(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(27));
+	le32p_replace_bits((__txdesc + 4), __value, BIT(27));
 }
 
-static inline void set_tx_desc_rts_sc(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_sc(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(29, 28));
+	le32p_replace_bits((__txdesc + 4), __value, GENMASK(29, 28));
 }
 
-static inline void set_tx_desc_rts_stbc(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_stbc(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(31, 30));
+	le32p_replace_bits((__txdesc + 4), __value, GENMASK(31, 30));
 }
 
 
 /* Dword 5 */
-static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val)
+static inline void set_tx_desc_tx_rate(__le32 *__pdesc, u32 __val)
 {
-	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0));
+	le32p_replace_bits((__pdesc + 5), __val, GENMASK(5, 0));
 }
 
-static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val)
+static inline void set_tx_desc_data_shortgi(__le32 *__pdesc, u32 __val)
 {
-	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6));
+	le32p_replace_bits((__pdesc + 5), __val, BIT(6));
 }
 
-static inline void set_tx_desc_data_rate_fb_limit(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_data_rate_fb_limit(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(12, 8));
+	le32p_replace_bits((__txdesc + 5), __value, GENMASK(12, 8));
 }
 
-static inline void set_tx_desc_rts_rate_fb_limit(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_rts_rate_fb_limit(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(16, 13));
+	le32p_replace_bits((__txdesc + 5), __value, GENMASK(16, 13));
 }
 
 
 /* Dword 6 */
-static inline void set_tx_desc_max_agg_num(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_max_agg_num(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 24), __value, GENMASK(15, 11));
+	le32p_replace_bits((__txdesc + 6), __value, GENMASK(15, 11));
 }
 
 
 /* Dword 7 */
-static inline void set_tx_desc_tx_desc_checksum(u8 *__txdesc, u32 __value)
+static inline void set_tx_desc_tx_desc_checksum(__le32 *__txdesc, u32 __value)
 {
-	le32p_replace_bits((__le32 *)(__txdesc + 28), __value, GENMASK(15, 0));
+	le32p_replace_bits((__txdesc + 7), __value, GENMASK(15, 0));
 }
 
 
-- 
2.16.4


^ permalink raw reply related

* [PATCH 3/4] rtlwifi: rtl8192cu: Convert macros that set descriptor
From: Larry Finger @ 2019-09-01 15:47 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190901154706.24193-1-Larry.Finger@lwfinger.net>

As a first step in the conversion, the macros that set the RX and TX
descriptors are converted to static inline routines, and the names are
changed from upper to lower case. To minimize the changes in a given
step, the input descriptor information is left as as a byte array
(u8 *), even though it should be a little-endian word array (__le32 *).
That will be changed in the next patch.

Several places where checkpatch.pl complains about a space after a cast
and other warnings are fixed.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.c   |   6 +-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c   | 246 ++++++-------
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h   | 385 +++++++++++++++------
 3 files changed, 402 insertions(+), 235 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
index b3ce8000d52d..a2f878de0a70 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/mac.c
@@ -736,9 +736,9 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->rxpower = rx_pwr_all;
 		pstats->recvsignalpower = rx_pwr_all;
-		if (GET_RX_DESC_RX_MCS(pdesc) &&
-		    GET_RX_DESC_RX_MCS(pdesc) >= DESC_RATEMCS8 &&
-		    GET_RX_DESC_RX_MCS(pdesc) <= DESC_RATEMCS15)
+		if (get_rx_desc_rx_mcs(pdesc) &&
+		    get_rx_desc_rx_mcs(pdesc) >= DESC_RATEMCS8 &&
+		    get_rx_desc_rx_mcs(pdesc) <= DESC_RATEMCS15)
 			max_spatial_stream = 2;
 		else
 			max_spatial_stream = 1;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
index 9b5c7ec6b6f7..a9f16868791f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c
@@ -286,40 +286,40 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
 {
 	struct rx_fwinfo_92c *p_drvinfo;
 	struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc;
-	u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc);
+	u32 phystatus = get_rx_desc_phy_status(pdesc);
 
-	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
-	stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) *
+	stats->length = (u16)get_rx_desc_pkt_len(pdesc);
+	stats->rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(pdesc) *
 				 RX_DRV_INFO_SIZE_UNIT;
-	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
-	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
-	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03);
+	stats->icv = (u16)get_rx_desc_icv(pdesc);
+	stats->crc = (u16)get_rx_desc_crc32(pdesc);
 	stats->hwerror = (stats->crc | stats->icv);
-	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
-	stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc);
-	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
-	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
-	stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1)
-				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
-	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
-	stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
-	stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc);
+	stats->decrypted = !get_rx_desc_swdec(pdesc);
+	stats->rate = (u8)get_rx_desc_rx_mcs(pdesc);
+	stats->shortpreamble = (u16)get_rx_desc_splcp(pdesc);
+	stats->isampdu = (bool)(get_rx_desc_paggr(pdesc) == 1);
+	stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(pdesc) == 1) &&
+				      (get_rx_desc_faggr(pdesc) == 1));
+	stats->timestamp_low = get_rx_desc_tsfl(pdesc);
+	stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(pdesc);
+	stats->is_ht = (bool)get_rx_desc_rx_ht(pdesc);
 	rx_status->freq = hw->conf.chandef.chan->center_freq;
 	rx_status->band = hw->conf.chandef.chan->band;
-	if (GET_RX_DESC_CRC32(pdesc))
+	if (get_rx_desc_crc32(pdesc))
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-	if (!GET_RX_DESC_SWDEC(pdesc))
+	if (!get_rx_desc_swdec(pdesc))
 		rx_status->flag |= RX_FLAG_DECRYPTED;
-	if (GET_RX_DESC_BW(pdesc))
+	if (get_rx_desc_bw(pdesc))
 		rx_status->bw = RATE_INFO_BW_40;
-	if (GET_RX_DESC_RX_HT(pdesc))
+	if (get_rx_desc_rx_ht(pdesc))
 		rx_status->encoding = RX_ENC_HT;
 	rx_status->flag |= RX_FLAG_MACTIME_START;
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht,
 						   false, stats->rate);
-	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+	rx_status->mactime = get_rx_desc_tsfl(pdesc);
 	if (phystatus) {
 		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
 						     stats->rx_bufshift);
@@ -352,42 +352,42 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
 	memset(rx_status, 0, sizeof(*rx_status));
 	rxdesc	= skb->data;
 	skb_len	= skb->len;
-	drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT);
-	pkt_len		= GET_RX_DESC_PKT_LEN(rxdesc);
+	drvinfo_len = (get_rx_desc_drvinfo_size(rxdesc) * RTL_RX_DRV_INFO_UNIT);
+	pkt_len		= get_rx_desc_pkt_len(rxdesc);
 	/* TODO: Error recovery. drop this skb or something. */
 	WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len));
-	stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc);
-	stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) *
+	stats.length = (u16)get_rx_desc_pkt_len(rxdesc);
+	stats.rx_drvinfo_size = (u8)get_rx_desc_drvinfo_size(rxdesc) *
 				RX_DRV_INFO_SIZE_UNIT;
-	stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03);
-	stats.icv = (u16) GET_RX_DESC_ICV(rxdesc);
-	stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc);
+	stats.rx_bufshift = (u8)(get_rx_desc_shift(rxdesc) & 0x03);
+	stats.icv = (u16)get_rx_desc_icv(rxdesc);
+	stats.crc = (u16)get_rx_desc_crc32(rxdesc);
 	stats.hwerror = (stats.crc | stats.icv);
-	stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc);
-	stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc);
-	stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc);
-	stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1)
-				   && (GET_RX_DESC_FAGGR(rxdesc) == 1));
-	stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc);
-	stats.rx_is40mhzpacket = (bool)GET_RX_DESC_BW(rxdesc);
-	stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc);
+	stats.decrypted = !get_rx_desc_swdec(rxdesc);
+	stats.rate = (u8)get_rx_desc_rx_mcs(rxdesc);
+	stats.shortpreamble = (u16)get_rx_desc_splcp(rxdesc);
+	stats.isampdu = (bool)((get_rx_desc_paggr(rxdesc) == 1) &&
+			       (get_rx_desc_faggr(rxdesc) == 1));
+	stats.timestamp_low = get_rx_desc_tsfl(rxdesc);
+	stats.rx_is40mhzpacket = (bool)get_rx_desc_bw(rxdesc);
+	stats.is_ht = (bool)get_rx_desc_rx_ht(rxdesc);
 	/* TODO: is center_freq changed when doing scan? */
 	/* TODO: Shall we add protection or just skip those two step? */
 	rx_status->freq = hw->conf.chandef.chan->center_freq;
 	rx_status->band = hw->conf.chandef.chan->band;
-	if (GET_RX_DESC_CRC32(rxdesc))
+	if (get_rx_desc_crc32(rxdesc))
 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-	if (!GET_RX_DESC_SWDEC(rxdesc))
+	if (!get_rx_desc_swdec(rxdesc))
 		rx_status->flag |= RX_FLAG_DECRYPTED;
-	if (GET_RX_DESC_BW(rxdesc))
+	if (get_rx_desc_bw(rxdesc))
 		rx_status->bw = RATE_INFO_BW_40;
-	if (GET_RX_DESC_RX_HT(rxdesc))
+	if (get_rx_desc_rx_ht(rxdesc))
 		rx_status->encoding = RX_ENC_HT;
 	/* Data rate */
 	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats.is_ht,
 						   false, stats.rate);
 	/*  There is a phy status after this rx descriptor. */
-	if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
+	if (get_rx_desc_phy_status(rxdesc)) {
 		p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
 		rtl92c_translate_rx_signal_stuff(hw, skb, &stats,
 				 (struct rx_desc_92c *)rxdesc, p_drvinfo);
@@ -442,9 +442,9 @@ struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw,
 
 static void _rtl_fill_usb_tx_desc(u8 *txdesc)
 {
-	SET_TX_DESC_OWN(txdesc, 1);
-	SET_TX_DESC_LAST_SEG(txdesc, 1);
-	SET_TX_DESC_FIRST_SEG(txdesc, 1);
+	set_tx_desc_own(txdesc, 1);
+	set_tx_desc_last_seg(txdesc, 1);
+	set_tx_desc_first_seg(txdesc, 1);
 }
 
 /**
@@ -457,10 +457,10 @@ static void _rtl_tx_desc_checksum(u8 *txdesc)
 	u32 index;
 
 	/* Clear first */
-	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
+	set_tx_desc_tx_desc_checksum(txdesc, 0);
 	for (index = 0; index < 16; index++)
 		checksum = checksum ^ le16_to_cpu(*(ptr + index));
-	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
+	set_tx_desc_tx_desc_checksum(txdesc, checksum);
 }
 
 void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
@@ -489,55 +489,57 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
 	rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc);
 	txdesc = skb_push(skb, RTL_TX_HEADER_SIZE);
 	memset(txdesc, 0, RTL_TX_HEADER_SIZE);
-	SET_TX_DESC_PKT_SIZE(txdesc, pktlen);
-	SET_TX_DESC_LINIP(txdesc, 0);
-	SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET);
-	SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE);
-	SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate);
+	set_tx_desc_pkt_size(txdesc, pktlen);
+	set_tx_desc_linip(txdesc, 0);
+	set_tx_desc_pkt_offset(txdesc, RTL_DUMMY_OFFSET);
+	set_tx_desc_offset(txdesc, RTL_TX_HEADER_SIZE);
+	set_tx_desc_tx_rate(txdesc, tcb_desc->hw_rate);
 	if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble)
-		SET_TX_DESC_DATA_SHORTGI(txdesc, 1);
+		set_tx_desc_data_shortgi(txdesc, 1);
 	if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
 		    info->flags & IEEE80211_TX_CTL_AMPDU) {
-		SET_TX_DESC_AGG_ENABLE(txdesc, 1);
-		SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14);
+		set_tx_desc_agg_enable(txdesc, 1);
+		set_tx_desc_max_agg_num(txdesc, 0x14);
 	} else {
-		SET_TX_DESC_AGG_BREAK(txdesc, 1);
+		set_tx_desc_agg_break(txdesc, 1);
 	}
-	SET_TX_DESC_SEQ(txdesc, seq_number);
-	SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable &&
-			       !tcb_desc->cts_enable) ? 1 : 0));
-	SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable ||
-				  tcb_desc->cts_enable) ? 1 : 0));
-	SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0));
-	SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0));
-	SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate);
-	SET_TX_DESC_RTS_BW(txdesc, 0);
-	SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc);
-	SET_TX_DESC_RTS_SHORT(txdesc,
+	set_tx_desc_seq(txdesc, seq_number);
+	set_tx_desc_rts_enable(txdesc,
+			       ((tcb_desc->rts_enable &&
+				!tcb_desc->cts_enable) ? 1 : 0));
+	set_tx_desc_hw_rts_enable(txdesc,
+				  ((tcb_desc->rts_enable ||
+				   tcb_desc->cts_enable) ? 1 : 0));
+	set_tx_desc_cts2self(txdesc, ((tcb_desc->cts_enable) ? 1 : 0));
+	set_tx_desc_rts_stbc(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0));
+	set_tx_desc_rts_rate(txdesc, tcb_desc->rts_rate);
+	set_tx_desc_rts_bw(txdesc, 0);
+	set_tx_desc_rts_sc(txdesc, tcb_desc->rts_sc);
+	set_tx_desc_rts_short(txdesc,
 			      ((tcb_desc->rts_rate <= DESC_RATE54M) ?
 			       (tcb_desc->rts_use_shortpreamble ? 1 : 0)
 			       : (tcb_desc->rts_use_shortgi ? 1 : 0)));
 	if (mac->bw_40) {
 		if (rate_flag & IEEE80211_TX_RC_DUP_DATA) {
-			SET_TX_DESC_DATA_BW(txdesc, 1);
-			SET_TX_DESC_DATA_SC(txdesc, 3);
+			set_tx_desc_data_bw(txdesc, 1);
+			set_tx_desc_data_sc(txdesc, 3);
 		} else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){
-			SET_TX_DESC_DATA_BW(txdesc, 1);
-			SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc);
+			set_tx_desc_data_bw(txdesc, 1);
+			set_tx_desc_data_sc(txdesc, mac->cur_40_prime_sc);
 		} else {
-			SET_TX_DESC_DATA_BW(txdesc, 0);
-			SET_TX_DESC_DATA_SC(txdesc, 0);
+			set_tx_desc_data_bw(txdesc, 0);
+			set_tx_desc_data_sc(txdesc, 0);
 		}
 	} else {
-		SET_TX_DESC_DATA_BW(txdesc, 0);
-		SET_TX_DESC_DATA_SC(txdesc, 0);
+		set_tx_desc_data_bw(txdesc, 0);
+		set_tx_desc_data_sc(txdesc, 0);
 	}
 	rcu_read_lock();
 	sta = ieee80211_find_sta(mac->vif, mac->bssid);
 	if (sta) {
 		u8 ampdu_density = sta->ht_cap.ampdu_density;
 
-		SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
+		set_tx_desc_ampdu_density(txdesc, ampdu_density);
 	}
 	rcu_read_unlock();
 	if (info->control.hw_key) {
@@ -547,49 +549,49 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
 		case WLAN_CIPHER_SUITE_WEP40:
 		case WLAN_CIPHER_SUITE_WEP104:
 		case WLAN_CIPHER_SUITE_TKIP:
-			SET_TX_DESC_SEC_TYPE(txdesc, 0x1);
+			set_tx_desc_sec_type(txdesc, 0x1);
 			break;
 		case WLAN_CIPHER_SUITE_CCMP:
-			SET_TX_DESC_SEC_TYPE(txdesc, 0x3);
+			set_tx_desc_sec_type(txdesc, 0x3);
 			break;
 		default:
-			SET_TX_DESC_SEC_TYPE(txdesc, 0x0);
+			set_tx_desc_sec_type(txdesc, 0x0);
 			break;
 		}
 	}
-	SET_TX_DESC_PKT_ID(txdesc, 0);
-	SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel);
-	SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F);
-	SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF);
-	SET_TX_DESC_DISABLE_FB(txdesc, 0);
-	SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0);
+	set_tx_desc_pkt_id(txdesc, 0);
+	set_tx_desc_queue_sel(txdesc, fw_qsel);
+	set_tx_desc_data_rate_fb_limit(txdesc, 0x1F);
+	set_tx_desc_rts_rate_fb_limit(txdesc, 0xF);
+	set_tx_desc_disable_fb(txdesc, 0);
+	set_tx_desc_use_rate(txdesc, tcb_desc->use_driver_rate ? 1 : 0);
 	if (ieee80211_is_data_qos(fc)) {
 		if (mac->rdg_en) {
 			RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
 				 "Enable RDG function\n");
-			SET_TX_DESC_RDG_ENABLE(txdesc, 1);
-			SET_TX_DESC_HTC(txdesc, 1);
+			set_tx_desc_rdg_enable(txdesc, 1);
+			set_tx_desc_htc(txdesc, 1);
 		}
 	}
 	if (rtlpriv->dm.useramask) {
-		SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index);
-		SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id);
+		set_tx_desc_rate_id(txdesc, tcb_desc->ratr_index);
+		set_tx_desc_macid(txdesc, tcb_desc->mac_id);
 	} else {
-		SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index);
-		SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index);
+		set_tx_desc_rate_id(txdesc, 0xC + tcb_desc->ratr_index);
+		set_tx_desc_macid(txdesc, tcb_desc->ratr_index);
 	}
 	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
 	      ppsc->fwctrl_lps) {
-		SET_TX_DESC_HWSEQ_EN(txdesc, 1);
-		SET_TX_DESC_PKT_ID(txdesc, 8);
+		set_tx_desc_hwseq_en(txdesc, 1);
+		set_tx_desc_pkt_id(txdesc, 8);
 		if (!defaultadapter)
-			SET_TX_DESC_QOS(txdesc, 1);
+			set_tx_desc_qos(txdesc, 1);
 	}
 	if (ieee80211_has_morefrags(fc))
-		SET_TX_DESC_MORE_FRAG(txdesc, 1);
+		set_tx_desc_more_frag(txdesc, 1);
 	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
 	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
-		SET_TX_DESC_BMC(txdesc, 1);
+		set_tx_desc_bmc(txdesc, 1);
 	_rtl_fill_usb_tx_desc(txdesc);
 	_rtl_tx_desc_checksum(txdesc);
 	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n");
@@ -600,22 +602,22 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
 {
 	/* Clear all status */
 	memset(pdesc, 0, RTL_TX_HEADER_SIZE);
-	SET_TX_DESC_FIRST_SEG(pdesc, 1); /* bFirstSeg; */
-	SET_TX_DESC_LAST_SEG(pdesc, 1); /* bLastSeg; */
-	SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
-	SET_TX_DESC_PKT_SIZE(pdesc, buffer_len); /* Buffer size + command hdr */
-	SET_TX_DESC_QUEUE_SEL(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
+	set_tx_desc_first_seg(pdesc, 1); /* bFirstSeg; */
+	set_tx_desc_last_seg(pdesc, 1); /* bLastSeg; */
+	set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
+	set_tx_desc_pkt_size(pdesc, buffer_len); /* Buffer size + command hdr */
+	set_tx_desc_queue_sel(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
 	/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error
 	 * vlaue by Hw. */
 	if (is_pspoll) {
-		SET_TX_DESC_NAV_USE_HDR(pdesc, 1);
+		set_tx_desc_nav_use_hdr(pdesc, 1);
 	} else {
-		SET_TX_DESC_HWSEQ_EN(pdesc, 1); /* Hw set sequence number */
-		SET_TX_DESC_PKT_ID(pdesc, BIT(3)); /* set bit3 to 1. */
+		set_tx_desc_hwseq_en(pdesc, 1); /* Hw set sequence number */
+		set_tx_desc_pkt_id(pdesc, BIT(3)); /* set bit3 to 1. */
 	}
-	SET_TX_DESC_USE_RATE(pdesc, 1); /* use data rate which is set by Sw */
-	SET_TX_DESC_OWN(pdesc, 1);
-	SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M);
+	set_tx_desc_use_rate(pdesc, 1); /* use data rate which is set by Sw */
+	set_tx_desc_own(pdesc, 1);
+	set_tx_desc_tx_rate(pdesc, DESC_RATE1M);
 	_rtl_tx_desc_checksum(pdesc);
 }
 
@@ -630,24 +632,24 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
 
 	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
 	if (firstseg)
-		SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
-	SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M);
-	SET_TX_DESC_SEQ(pdesc, 0);
-	SET_TX_DESC_LINIP(pdesc, 0);
-	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
-	SET_TX_DESC_FIRST_SEG(pdesc, 1);
-	SET_TX_DESC_LAST_SEG(pdesc, 1);
-	SET_TX_DESC_RATE_ID(pdesc, 7);
-	SET_TX_DESC_MACID(pdesc, 0);
-	SET_TX_DESC_OWN(pdesc, 1);
-	SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb->len);
-	SET_TX_DESC_FIRST_SEG(pdesc, 1);
-	SET_TX_DESC_LAST_SEG(pdesc, 1);
-	SET_TX_DESC_OFFSET(pdesc, 0x20);
-	SET_TX_DESC_USE_RATE(pdesc, 1);
+		set_tx_desc_offset(pdesc, RTL_TX_HEADER_SIZE);
+	set_tx_desc_tx_rate(pdesc, DESC_RATE1M);
+	set_tx_desc_seq(pdesc, 0);
+	set_tx_desc_linip(pdesc, 0);
+	set_tx_desc_queue_sel(pdesc, fw_queue);
+	set_tx_desc_first_seg(pdesc, 1);
+	set_tx_desc_last_seg(pdesc, 1);
+	set_tx_desc_rate_id(pdesc, 7);
+	set_tx_desc_macid(pdesc, 0);
+	set_tx_desc_own(pdesc, 1);
+	set_tx_desc_pkt_size(pdesc, (u16)skb->len);
+	set_tx_desc_first_seg(pdesc, 1);
+	set_tx_desc_last_seg(pdesc, 1);
+	set_tx_desc_offset(pdesc, 0x20);
+	set_tx_desc_use_rate(pdesc, 1);
 	if (!ieee80211_is_data_qos(fc)) {
-		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
-		SET_TX_DESC_PKT_ID(pdesc, 8);
+		set_tx_desc_hwseq_en(pdesc, 1);
+		set_tx_desc_pkt_id(pdesc, 8);
 	}
 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content",
 		      pdesc, RTL_TX_DESC_SIZE);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index 916fa0e98123..3d8a913d799d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -73,142 +73,307 @@ struct rx_drv_info_92c {
 /* macros to read various fields in RX descriptor */
 
 /* DWORD 0 */
-#define GET_RX_DESC_PKT_LEN(__rxdesc)		\
-	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(13, 0))
-#define GET_RX_DESC_CRC32(__rxdesc)		\
-	le32_get_bits(*(__le32 *)__rxdesc, BIT(14))
-#define GET_RX_DESC_ICV(__rxdesc)		\
-	le32_get_bits(*(__le32 *)__rxdesc, BIT(15))
-#define GET_RX_DESC_DRVINFO_SIZE(__rxdesc)	\
-	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(19, 16))
-#define GET_RX_DESC_SHIFT(__rxdesc)		\
-	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(25, 24))
-#define GET_RX_DESC_PHY_STATUS(__rxdesc)	\
-	le32_get_bits(*(__le32 *)__rxdesc, BIT(26))
-#define GET_RX_DESC_SWDEC(__rxdesc)		\
-	le32_get_bits(*(__le32 *)__rxdesc, BIT(27))
+static inline u32 get_rx_desc_pkt_len(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(13, 0));
+}
+
+static inline u32 get_rx_desc_crc32(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, BIT(14));
+}
+
+static inline u32 get_rx_desc_icv(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, BIT(15));
+}
+
+static inline u32 get_rx_desc_drvinfo_size(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(19, 16));
+}
+
+static inline u32 get_rx_desc_shift(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, GENMASK(25, 24));
+}
+
+static inline u32 get_rx_desc_phy_status(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, BIT(26));
+}
+
+static inline u32 get_rx_desc_swdec(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)__rxdesc, BIT(27));
+}
+
 
 /* DWORD 1 */
-#define GET_RX_DESC_PAGGR(__rxdesc)		\
-	le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(14))
-#define GET_RX_DESC_FAGGR(__rxdesc)		\
-	le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(15))
+static inline u32 get_rx_desc_paggr(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(14));
+}
+
+static inline u32 get_rx_desc_faggr(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(15));
+}
+
 
 /* DWORD 3 */
-#define GET_RX_DESC_RX_MCS(__rxdesc)		\
-	le32_get_bits(*(__le32 *)(__rxdesc + 12), GENMASK(5, 0))
-#define GET_RX_DESC_RX_HT(__rxdesc)            \
-	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(6))
-#define GET_RX_DESC_SPLCP(__rxdesc)            \
-	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(8))
-#define GET_RX_DESC_BW(__rxdesc)               \
-	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(9))
+static inline u32 get_rx_desc_rx_mcs(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 12), GENMASK(5, 0));
+}
+
+static inline u32 get_rx_desc_rx_ht(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(6));
+}
+
+static inline u32 get_rx_desc_splcp(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(8));
+}
+
+static inline u32 get_rx_desc_bw(u8 *__rxdesc)
+{
+	return le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(9));
+}
+
 
 /* DWORD 5 */
-#define GET_RX_DESC_TSFL(__rxdesc)		\
-	le32_to_cpu(*((__le32 *)(__rxdesc + 20)))
+static inline u32 get_rx_desc_tsfl(u8 *__rxdesc)
+{
+	return le32_to_cpu(*((__le32 *)(__rxdesc + 20)));
+}
+
 
 /*======================= tx desc ============================================*/
 
 /* macros to set various fields in TX descriptor */
 
 /* Dword 0 */
-#define SET_TX_DESC_PKT_SIZE(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(15, 0))
-#define SET_TX_DESC_OFFSET(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(23, 16))
-#define SET_TX_DESC_BMC(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(24))
-#define SET_TX_DESC_HTC(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(25))
-#define SET_TX_DESC_LAST_SEG(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(26))
-#define SET_TX_DESC_FIRST_SEG(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(27))
-#define SET_TX_DESC_LINIP(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(28))
-#define SET_TX_DESC_OWN(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(31))
+static inline void set_tx_desc_pkt_size(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(15, 0));
+}
+
+static inline void set_tx_desc_offset(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(23, 16));
+}
+
+static inline void set_tx_desc_bmc(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(24));
+}
+
+static inline void set_tx_desc_htc(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(25));
+}
+
+static inline void set_tx_desc_last_seg(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(26));
+}
+
+static inline void set_tx_desc_first_seg(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(27));
+}
+
+static inline void set_tx_desc_linip(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(28));
+}
+
+static inline void set_tx_desc_own(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(31));
+}
+
 
 /* Dword 1 */
-#define SET_TX_DESC_MACID(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(4, 0))
-#define SET_TX_DESC_AGG_ENABLE(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(5))
-#define SET_TX_DESC_AGG_BREAK(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(6))
-#define SET_TX_DESC_RDG_ENABLE(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(7))
-#define SET_TX_DESC_QUEUE_SEL(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(12, 8))
-#define SET_TX_DESC_RATE_ID(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(19, 16))
-#define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(20))
-#define SET_TX_DESC_SEC_TYPE(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(23, 22))
-#define SET_TX_DESC_PKT_OFFSET(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(30, 26))
+static inline void set_tx_desc_macid(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(4, 0));
+}
+
+static inline void set_tx_desc_agg_enable(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(5));
+}
+
+static inline void set_tx_desc_agg_break(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(6));
+}
+
+static inline void set_tx_desc_rdg_enable(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(7));
+}
+
+static inline void set_tx_desc_queue_sel(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(12, 8));
+}
+
+static inline void set_tx_desc_rate_id(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(19, 16));
+}
+
+static inline void set_tx_desc_nav_use_hdr(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(20));
+}
+
+static inline void set_tx_desc_sec_type(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(23, 22));
+}
+
+static inline void set_tx_desc_pkt_offset(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(30, 26));
+}
+
 
 /* Dword 2 */
-#define SET_TX_DESC_MORE_FRAG(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, BIT(17))
-#define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, GENMASK(22, 20))
+static inline void set_tx_desc_more_frag(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, BIT(17));
+}
+
+static inline void set_tx_desc_ampdu_density(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, GENMASK(22, 20));
+}
+
 
 /* Dword 3 */
-#define SET_TX_DESC_SEQ(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(27, 16))
-#define SET_TX_DESC_PKT_ID(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(31, 28))
+static inline void set_tx_desc_seq(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(27, 16));
+}
+
+static inline void set_tx_desc_pkt_id(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(31, 28));
+}
+
 
 /* Dword 4 */
-#define SET_TX_DESC_RTS_RATE(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(4, 0))
-#define SET_TX_DESC_QOS(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(6))
-#define SET_TX_DESC_HWSEQ_EN(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(7))
-#define SET_TX_DESC_USE_RATE(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(8))
-#define SET_TX_DESC_DISABLE_FB(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(10))
-#define SET_TX_DESC_CTS2SELF(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(11))
-#define SET_TX_DESC_RTS_ENABLE(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(12))
-#define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(13))
-#define SET_TX_DESC_DATA_SC(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(21, 20))
-#define SET_TX_DESC_DATA_BW(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(25))
-#define SET_TX_DESC_RTS_SHORT(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(26))
-#define SET_TX_DESC_RTS_BW(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(27))
-#define SET_TX_DESC_RTS_SC(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(29, 28))
-#define SET_TX_DESC_RTS_STBC(__txdesc, __value)		\
-	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(31, 30))
+static inline void set_tx_desc_rts_rate(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(4, 0));
+}
+
+static inline void set_tx_desc_qos(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(6));
+}
+
+static inline void set_tx_desc_hwseq_en(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(7));
+}
+
+static inline void set_tx_desc_use_rate(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(8));
+}
+
+static inline void set_tx_desc_disable_fb(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(10));
+}
+
+static inline void set_tx_desc_cts2self(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(11));
+}
+
+static inline void set_tx_desc_rts_enable(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(12));
+}
+
+static inline void set_tx_desc_hw_rts_enable(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(13));
+}
+
+static inline void set_tx_desc_data_sc(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(21, 20));
+}
+
+static inline void set_tx_desc_data_bw(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(25));
+}
+
+static inline void set_tx_desc_rts_short(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(26));
+}
+
+static inline void set_tx_desc_rts_bw(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(27));
+}
+
+static inline void set_tx_desc_rts_sc(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(29, 28));
+}
+
+static inline void set_tx_desc_rts_stbc(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(31, 30));
+}
+
 
 /* Dword 5 */
-#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
-	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0))
-#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
-	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6))
-#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \
-	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(12, 8))
-#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \
-	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(16, 13))
+static inline void set_tx_desc_tx_rate(u8 *__pdesc, u32 __val)
+{
+	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0));
+}
+
+static inline void set_tx_desc_data_shortgi(u8 *__pdesc, u32 __val)
+{
+	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6));
+}
+
+static inline void set_tx_desc_data_rate_fb_limit(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(12, 8));
+}
+
+static inline void set_tx_desc_rts_rate_fb_limit(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(16, 13));
+}
+
 
 /* Dword 6 */
-#define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value)	\
-	le32p_replace_bits((__le32 *)(__txdesc + 24), __value, GENMASK(15, 11))
+static inline void set_tx_desc_max_agg_num(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 24), __value, GENMASK(15, 11));
+}
+
 
 /* Dword 7 */
-#define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \
-	le32p_replace_bits((__le32 *)(__txdesc + 28), __value, GENMASK(15, 0))
+static inline void set_tx_desc_tx_desc_checksum(u8 *__txdesc, u32 __value)
+{
+	le32p_replace_bits((__le32 *)(__txdesc + 28), __value, GENMASK(15, 0));
+}
+
 
 int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
 u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
-- 
2.16.4


^ permalink raw reply related

* [PATCH 2/4] rtlwifi: rtl8192cu: Replace local bit manipulation macros
From: Larry Finger @ 2019-09-01 15:47 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190901154706.24193-1-Larry.Finger@lwfinger.net>

This driver uses a set of local macros to manipulate the TX and RX
descriptors, which are all little-endian quantities. These macros
are replaced by the bitfield macros le32p_replace_bits() and
le32_get_bits(). In several places, the macros operated on an entire
32-bit word. In these cases, a direct read or replacement is used.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h   | 110 ++++++++++-----------
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index 15627a7d42f5..916fa0e98123 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -74,39 +74,39 @@ struct rx_drv_info_92c {
 
 /* DWORD 0 */
 #define GET_RX_DESC_PKT_LEN(__rxdesc)		\
-	LE_BITS_TO_4BYTE((__rxdesc), 0, 14)
+	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(13, 0))
 #define GET_RX_DESC_CRC32(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 14, 1)
+	le32_get_bits(*(__le32 *)__rxdesc, BIT(14))
 #define GET_RX_DESC_ICV(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 15, 1)
+	le32_get_bits(*(__le32 *)__rxdesc, BIT(15))
 #define GET_RX_DESC_DRVINFO_SIZE(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc, 16, 4)
+	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(19, 16))
 #define GET_RX_DESC_SHIFT(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 24, 2)
+	le32_get_bits(*(__le32 *)__rxdesc, GENMASK(25, 24))
 #define GET_RX_DESC_PHY_STATUS(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc, 26, 1)
+	le32_get_bits(*(__le32 *)__rxdesc, BIT(26))
 #define GET_RX_DESC_SWDEC(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 27, 1)
+	le32_get_bits(*(__le32 *)__rxdesc, BIT(27))
 
 /* DWORD 1 */
 #define GET_RX_DESC_PAGGR(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 14, 1)
+	le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(14))
 #define GET_RX_DESC_FAGGR(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 15, 1)
+	le32_get_bits(*(__le32 *)(__rxdesc + 4), BIT(15))
 
 /* DWORD 3 */
 #define GET_RX_DESC_RX_MCS(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 0, 6)
+	le32_get_bits(*(__le32 *)(__rxdesc + 12), GENMASK(5, 0))
 #define GET_RX_DESC_RX_HT(__rxdesc)            \
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 6, 1)
+	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(6))
 #define GET_RX_DESC_SPLCP(__rxdesc)            \
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 8, 1)
+	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(8))
 #define GET_RX_DESC_BW(__rxdesc)               \
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 9, 1)
+	le32_get_bits(*(__le32 *)(__rxdesc + 12), BIT(9))
 
 /* DWORD 5 */
 #define GET_RX_DESC_TSFL(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 20, 0, 32)
+	le32_to_cpu(*((__le32 *)(__rxdesc + 20)))
 
 /*======================= tx desc ============================================*/
 
@@ -114,101 +114,101 @@ struct rx_drv_info_92c {
 
 /* Dword 0 */
 #define SET_TX_DESC_PKT_SIZE(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 0, 16, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(15, 0))
 #define SET_TX_DESC_OFFSET(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 16, 8, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, GENMASK(23, 16))
 #define SET_TX_DESC_BMC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 24, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(24))
 #define SET_TX_DESC_HTC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 25, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(25))
 #define SET_TX_DESC_LAST_SEG(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 26, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(26))
 #define SET_TX_DESC_FIRST_SEG(__txdesc, __value)	\
-	 SET_BITS_TO_LE_4BYTE(__txdesc, 27, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(27))
 #define SET_TX_DESC_LINIP(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 28, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(28))
 #define SET_TX_DESC_OWN(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value)
+	le32p_replace_bits((__le32 *)__txdesc, __value, BIT(31))
 
 /* Dword 1 */
 #define SET_TX_DESC_MACID(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 0, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(4, 0))
 #define SET_TX_DESC_AGG_ENABLE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 5, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(5))
 #define SET_TX_DESC_AGG_BREAK(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 6, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(6))
 #define SET_TX_DESC_RDG_ENABLE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 7, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(7))
 #define SET_TX_DESC_QUEUE_SEL(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 8, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(12, 8))
 #define SET_TX_DESC_RATE_ID(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 16, 4, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(19, 16))
 #define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 20, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, BIT(20))
 #define SET_TX_DESC_SEC_TYPE(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 22, 2, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(23, 22))
 #define SET_TX_DESC_PKT_OFFSET(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 26, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 4), __value, GENMASK(30, 26))
 
 /* Dword 2 */
 #define SET_TX_DESC_MORE_FRAG(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 17, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, BIT(17))
 #define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 20, 3, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 8), __value, GENMASK(22, 20))
 
 /* Dword 3 */
 #define SET_TX_DESC_SEQ(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 12, 16, 12, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(27, 16))
 #define SET_TX_DESC_PKT_ID(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 12, 28, 4, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 12), __value, GENMASK(31, 28))
 
 /* Dword 4 */
 #define SET_TX_DESC_RTS_RATE(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 0, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(4, 0))
 #define SET_TX_DESC_QOS(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 6, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(6))
 #define SET_TX_DESC_HWSEQ_EN(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 7, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(7))
 #define SET_TX_DESC_USE_RATE(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 8, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(8))
 #define SET_TX_DESC_DISABLE_FB(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 10, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(10))
 #define SET_TX_DESC_CTS2SELF(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 11, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(11))
 #define SET_TX_DESC_RTS_ENABLE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 12, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(12))
 #define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 13, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(13))
 #define SET_TX_DESC_DATA_SC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 20, 2, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(21, 20))
 #define SET_TX_DESC_DATA_BW(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 25, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(25))
 #define SET_TX_DESC_RTS_SHORT(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 26, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(26))
 #define SET_TX_DESC_RTS_BW(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 27, 1, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, BIT(27))
 #define SET_TX_DESC_RTS_SC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 28, 2, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(29, 28))
 #define SET_TX_DESC_RTS_STBC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 30, 2, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 16), __value, GENMASK(31, 30))
 
 /* Dword 5 */
 #define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc + 20, 0, 6, __val)
+	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, GENMASK(5, 0))
 #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc + 20, 6, 1, __val)
+	le32p_replace_bits((__le32 *)(__pdesc + 20), __val, BIT(6))
 #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \
-	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 8, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(12, 8))
 #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \
-	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 13, 4, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 20), __value, GENMASK(16, 13))
 
 /* Dword 6 */
 #define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 11, 5, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 24), __value, GENMASK(15, 11))
 
 /* Dword 7 */
 #define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \
-	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 0, 16, __value)
+	le32p_replace_bits((__le32 *)(__txdesc + 28), __value, GENMASK(15, 0))
 
 int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
 u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
-- 
2.16.4


^ permalink raw reply related

* [PATCH 1/4] rtlwifi: rtl8192cu: Remove unused GET_XXX and SET_XXX
From: Larry Finger @ 2019-09-01 15:47 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger
In-Reply-To: <20190901154706.24193-1-Larry.Finger@lwfinger.net>

As the first step in converting from macros that get/set information
in the RX and TX descriptors, unused macros are being removed.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
---
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h   | 150 +--------------------
 1 file changed, 3 insertions(+), 147 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
index ae2e8aa212de..15627a7d42f5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.h
@@ -81,92 +81,28 @@ struct rx_drv_info_92c {
 	LE_BITS_TO_4BYTE(__rxdesc, 15, 1)
 #define GET_RX_DESC_DRVINFO_SIZE(__rxdesc)	\
 	LE_BITS_TO_4BYTE(__rxdesc, 16, 4)
-#define GET_RX_DESC_SECURITY(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 20, 3)
-#define GET_RX_DESC_QOS(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 23, 1)
 #define GET_RX_DESC_SHIFT(__rxdesc)		\
 	LE_BITS_TO_4BYTE(__rxdesc, 24, 2)
 #define GET_RX_DESC_PHY_STATUS(__rxdesc)	\
 	LE_BITS_TO_4BYTE(__rxdesc, 26, 1)
 #define GET_RX_DESC_SWDEC(__rxdesc)		\
 	LE_BITS_TO_4BYTE(__rxdesc, 27, 1)
-#define GET_RX_DESC_LAST_SEG(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 28, 1)
-#define GET_RX_DESC_FIRST_SEG(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 29, 1)
-#define GET_RX_DESC_EOR(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 30, 1)
-#define GET_RX_DESC_OWN(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc, 31, 1)
 
 /* DWORD 1 */
-#define GET_RX_DESC_MACID(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 0, 5)
-#define GET_RX_DESC_TID(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 5, 4)
 #define GET_RX_DESC_PAGGR(__rxdesc)		\
 	LE_BITS_TO_4BYTE(__rxdesc + 4, 14, 1)
 #define GET_RX_DESC_FAGGR(__rxdesc)		\
 	LE_BITS_TO_4BYTE(__rxdesc + 4, 15, 1)
-#define GET_RX_DESC_A1_FIT(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 16, 4)
-#define GET_RX_DESC_A2_FIT(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 20, 4)
-#define GET_RX_DESC_PAM(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 24, 1)
-#define GET_RX_DESC_PWR(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 25, 1)
-#define GET_RX_DESC_MORE_DATA(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 26, 1)
-#define GET_RX_DESC_MORE_FRAG(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 27, 1)
-#define GET_RX_DESC_TYPE(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 28, 2)
-#define GET_RX_DESC_MC(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 30, 1)
-#define GET_RX_DESC_BC(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 4, 31, 1)
-
-/* DWORD 2 */
-#define GET_RX_DESC_SEQ(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 8, 0, 12)
-#define GET_RX_DESC_FRAG(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 8, 12, 4)
-#define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc + 8, 16, 8)
-#define GET_RX_DESC_NEXT_IND(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 8, 30, 1)
 
 /* DWORD 3 */
 #define GET_RX_DESC_RX_MCS(__rxdesc)		\
 	LE_BITS_TO_4BYTE(__rxdesc + 12, 0, 6)
-#define GET_RX_DESC_RX_HT(__rxdesc)		\
+#define GET_RX_DESC_RX_HT(__rxdesc)            \
 	LE_BITS_TO_4BYTE(__rxdesc + 12, 6, 1)
-#define GET_RX_DESC_AMSDU(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 7, 1)
-#define GET_RX_DESC_SPLCP(__rxdesc)		\
+#define GET_RX_DESC_SPLCP(__rxdesc)            \
 	LE_BITS_TO_4BYTE(__rxdesc + 12, 8, 1)
-#define GET_RX_DESC_BW(__rxdesc)		\
+#define GET_RX_DESC_BW(__rxdesc)               \
 	LE_BITS_TO_4BYTE(__rxdesc + 12, 9, 1)
-#define GET_RX_DESC_HTC(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 10, 1)
-#define GET_RX_DESC_TCP_CHK_RPT(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 11, 1)
-#define GET_RX_DESC_IP_CHK_RPT(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 12, 1)
-#define GET_RX_DESC_TCP_CHK_VALID(__rxdesc)	\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 13, 1)
-#define GET_RX_DESC_HWPC_ERR(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 14, 1)
-#define GET_RX_DESC_HWPC_IND(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 15, 1)
-#define GET_RX_DESC_IV0(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 12, 16, 16)
-
-/* DWORD 4 */
-#define GET_RX_DESC_IV1(__rxdesc)		\
-	LE_BITS_TO_4BYTE(__rxdesc + 16, 0, 32)
 
 /* DWORD 5 */
 #define GET_RX_DESC_TSFL(__rxdesc)		\
@@ -191,10 +127,6 @@ struct rx_drv_info_92c {
 	 SET_BITS_TO_LE_4BYTE(__txdesc, 27, 1, __value)
 #define SET_TX_DESC_LINIP(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc, 28, 1, __value)
-#define SET_TX_DESC_NO_ACM(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 29, 1, __value)
-#define SET_TX_DESC_GF(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc, 30, 1, __value)
 #define SET_TX_DESC_OWN(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc, 31, 1, __value)
 
@@ -209,56 +141,22 @@ struct rx_drv_info_92c {
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 7, 1, __value)
 #define SET_TX_DESC_QUEUE_SEL(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 8, 5, __value)
-#define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 13, 1, __value)
-#define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 14, 1, __value)
-#define SET_TX_DESC_PIFS(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 15, 1, __value)
 #define SET_TX_DESC_RATE_ID(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 16, 4, __value)
-#define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 16, 4, __value)
 #define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 20, 1, __value)
-#define SET_TX_DESC_EN_DESC_ID(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 21, 1, __value)
 #define SET_TX_DESC_SEC_TYPE(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 22, 2, __value)
 #define SET_TX_DESC_PKT_OFFSET(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 4, 26, 5, __value)
 
 /* Dword 2 */
-#define SET_TX_DESC_RTS_RC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 0, 6, __value)
-#define SET_TX_DESC_DATA_RC(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 6, 6, __value)
-#define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 14, 2, __value)
 #define SET_TX_DESC_MORE_FRAG(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 17, 1, __value)
-#define SET_TX_DESC_RAW(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 18, 1, __value)
-#define SET_TX_DESC_CCX(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 19, 1, __value)
 #define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 20, 3, __value)
-#define SET_TX_DESC_ANTSEL_A(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 24, 1, __value)
-#define SET_TX_DESC_ANTSEL_B(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 25, 1, __value)
-#define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 26, 2, __value)
-#define SET_TX_DESC_TX_ANTL(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 28, 2, __value)
-#define SET_TX_DESC_TX_ANT_HT(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 8, 30, 2, __value)
 
 /* Dword 3 */
-#define SET_TX_DESC_NEXT_HEAP_PAGE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 12, 0, 8, __value)
-#define SET_TX_DESC_TAIL_PAGE(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 12, 8, 8, __value)
 #define SET_TX_DESC_SEQ(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 12, 16, 12, __value)
 #define SET_TX_DESC_PKT_ID(__txdesc, __value)		\
@@ -267,16 +165,12 @@ struct rx_drv_info_92c {
 /* Dword 4 */
 #define SET_TX_DESC_RTS_RATE(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 0, 5, __value)
-#define SET_TX_DESC_AP_DCFE(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 5, 1, __value)
 #define SET_TX_DESC_QOS(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 6, 1, __value)
 #define SET_TX_DESC_HWSEQ_EN(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 7, 1, __value)
 #define SET_TX_DESC_USE_RATE(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 8, 1, __value)
-#define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 9, 1, __value)
 #define SET_TX_DESC_DISABLE_FB(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 10, 1, __value)
 #define SET_TX_DESC_CTS2SELF(__txdesc, __value)		\
@@ -285,16 +179,8 @@ struct rx_drv_info_92c {
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 12, 1, __value)
 #define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 13, 1, __value)
-#define SET_TX_DESC_WAIT_DCTS(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 18, 1, __value)
-#define SET_TX_DESC_CTS2AP_EN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 19, 1, __value)
 #define SET_TX_DESC_DATA_SC(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 20, 2, __value)
-#define SET_TX_DESC_DATA_STBC(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 22, 2, __value)
-#define SET_TX_DESC_DATA_SHORT(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 24, 1, __value)
 #define SET_TX_DESC_DATA_BW(__txdesc, __value)		\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 16, 25, 1, __value)
 #define SET_TX_DESC_RTS_SHORT(__txdesc, __value)	\
@@ -311,48 +197,18 @@ struct rx_drv_info_92c {
 	SET_BITS_TO_LE_4BYTE(__pdesc + 20, 0, 6, __val)
 #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
 	SET_BITS_TO_LE_4BYTE(__pdesc + 20, 6, 1, __val)
-#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc + 20, 7, 1, __val)
 #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \
 	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 8, 5, __value)
 #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \
 	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 13, 4, __value)
-#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \
-	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 17, 1, __value)
-#define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 18, 6, __value)
-#define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 20, 24, 8, __value)
 
 /* Dword 6 */
-#define SET_TX_DESC_TXAGC_A(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 0, 5, __value)
-#define SET_TX_DESC_TXAGC_B(__txdesc, __value)		\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 5, 5, __value)
-#define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 10, 1, __value)
 #define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value)	\
 	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 11, 5, __value)
-#define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 16, 4, __value)
-#define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 20, 4, __value)
-#define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 24, 4, __value)
-#define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 24, 28, 4, __value)
 
 /* Dword 7 */
 #define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \
 	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 0, 16, __value)
-#define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 16, 4, __value)
-#define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 20, 4, __value)
-#define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 24, 4, __value)
-#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value)	\
-	SET_BITS_TO_LE_4BYTE(__txdesc + 28, 28, 4, __value)
 
 int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
 u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
-- 
2.16.4


^ permalink raw reply related

* [PATCH 0/4] rtlwifi: rtl8192cu:  Replace local TX and RX bit manipulation macro
From: Larry Finger @ 2019-09-01 15:47 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless, pkshih, Larry Finger

These patches are part of a series intended to replace the bit-manipulation
macros used to set and read the various descriptors with a set of inline
routines.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>

Larry Finger (4):
  rtlwifi: rtl8192cu: Remove unused GET_XXX and SET_XXX
  rtlwifi: rtl8192cu: Replace local bit manipulation macros
  rtlwifi: rtl8192cu: Convert macros that set descriptor
  rtlwifi: rtl8192cu: Convert inline routines to little-endian words

 .../net/wireless/realtek/rtlwifi/rtl8192cu/mac.c   |   8 +-
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.c   | 272 ++++++-----
 .../net/wireless/realtek/rtlwifi/rtl8192cu/trx.h   | 529 +++++++++++----------
 3 files changed, 419 insertions(+), 390 deletions(-)

-- 
2.16.4


^ permalink raw reply

* Re: [PATCH] Fix a double free bug in rsi_91x_deinit
From: Guenter Roeck @ 2019-09-01 14:08 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Hui Peng, security, Mathias Payer, David S. Miller,
	linux-wireless, netdev, linux-kernel
In-Reply-To: <87k1asqw87.fsf@kamboji.qca.qualcomm.com>

On 9/1/19 1:03 AM, Kalle Valo wrote:
> Guenter Roeck <linux@roeck-us.net> writes:
> 
>> On Mon, Aug 19, 2019 at 06:02:29PM -0400, Hui Peng wrote:
>>> `dev` (struct rsi_91x_usbdev *) field of adapter
>>> (struct rsi_91x_usbdev *) is allocated  and initialized in
>>> `rsi_init_usb_interface`. If any error is detected in information
>>> read from the device side,  `rsi_init_usb_interface` will be
>>> freed. However, in the higher level error handling code in
>>> `rsi_probe`, if error is detected, `rsi_91x_deinit` is called
>>> again, in which `dev` will be freed again, resulting double free.
>>>
>>> This patch fixes the double free by removing the free operation on
>>> `dev` in `rsi_init_usb_interface`, because `rsi_91x_deinit` is also
>>> used in `rsi_disconnect`, in that code path, the `dev` field is not
>>>   (and thus needs to be) freed.
>>>
>>> This bug was found in v4.19, but is also present in the latest version
>>> of kernel.
>>>
>>> Reported-by: Hui Peng <benquike@gmail.com>
>>> Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
>>> Signed-off-by: Hui Peng <benquike@gmail.com>
>>
>> FWIW:
>>
>> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
>>
>> This patch is listed as fix for CVE-2019-15504, which has a CVSS 2.0 score
>> of 10.0 (high) and CVSS 3.0 score of 9.8 (critical).
> 
> A double free in error path is considered as a critical CVE issue? I'm
> very curious, why is that?
> 

You'd have to ask the people assigning CVSS scores. However, if the memory
was reallocated, that reallocated memory (which is still in use) is freed.
Then all kinds of bad things can happen.

Guenter

>> Are there any plans to apply this patch to the upstream kernel anytime
>> soon ?
> 
> I was on vacation last week and hence I have not been able to apply any
> wireless patches. I should be able to catch up next week.
> 


^ permalink raw reply

* [PATCH V2 2/2] brcmfmac: add "reset" debugfs entry for testing reset
From: Rafał Miłecki @ 2019-09-01 11:34 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Winnie Chang, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Rafał Miłecki
In-Reply-To: <20190901113436.23665-1-zajec5@gmail.com>

From: Rafał Miłecki <rafal@milecki.pl>

This is a trivial debugfs entry for triggering reset just like in case
of firmware crash. It works by writing 1 to it:
echo 1 > reset

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
 .../broadcom/brcm80211/brcmfmac/core.c        | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index 705b8cc53c3e..21e07d1ceeae 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1086,6 +1086,29 @@ static void brcmf_core_bus_reset(struct work_struct *work)
 	brcmf_bus_reset(drvr->bus_if);
 }
 
+static ssize_t bus_reset_write(struct file *file, const char __user *user_buf,
+			       size_t count, loff_t *ppos)
+{
+	struct brcmf_pub *drvr = file->private_data;
+	u8 value;
+
+	if (kstrtou8_from_user(user_buf, count, 0, &value))
+		return -EINVAL;
+
+	if (value != 1)
+		return -EINVAL;
+
+	schedule_work(&drvr->bus_reset);
+
+	return count;
+}
+
+static const struct file_operations bus_reset_fops = {
+	.open	= simple_open,
+	.llseek	= no_llseek,
+	.write	= bus_reset_write,
+};
+
 static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
 {
 	int ret = -1;
@@ -1161,6 +1184,8 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
 
 	/* populate debugfs */
 	brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
+	debugfs_create_file("reset", 0600, brcmf_debugfs_get_devdir(drvr), drvr,
+			    &bus_reset_fops);
 	brcmf_feat_debugfs_create(drvr);
 	brcmf_proto_debugfs_create(drvr);
 	brcmf_bus_debugfs_create(bus_if);
-- 
2.21.0


^ permalink raw reply related

* [PATCH V2 1/2] brcmfmac: add stub version of brcmf_debugfs_get_devdir()
From: Rafał Miłecki @ 2019-09-01 11:34 UTC (permalink / raw)
  To: Kalle Valo
  Cc: Arend van Spriel, Franky Lin, Hante Meuleman, Chi-Hsien Lin,
	Wright Feng, Winnie Chang, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, Rafał Miłecki

From: Rafał Miłecki <rafal@milecki.pl>

In case of compiling driver without DEBUG expose a stub function to make
writing debug code much simpler (no extra conditions). This will allow
e.g. using debugfs_create_file() without any magic if or #ifdef.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index ea6e8e839cae..9b221b509ade 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -121,6 +121,10 @@ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
 int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
 			       size_t len);
 #else
+static inline struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
+{
+	return ERR_PTR(-ENOENT);
+}
 static inline
 int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
 			    int (*read_fn)(struct seq_file *seq, void *data))
-- 
2.21.0


^ permalink raw reply related


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