All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] ath11k: Add support for sram dump
@ 2021-09-13 18:08 ` Jouni Malinen
  0 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:08 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang

From: Baochen Qiang <bqiang@codeaurora.org>

On-board sram contains valuable infomation for debug, this patch adds
a new interface named "sram" in debugfs with which we can dump sram
content using following cmd:

        cat /sys/kernel/ath11k/<pdev name>/sram > sram.dump

Baochen Qiang (3):
  ath11k: Split PCI write/read functions
  ath11k: Move pdev debugfs creation ahead
  ath11k: Implement sram dump interface

 drivers/net/wireless/ath/ath11k/core.c    | 31 +++++---
 drivers/net/wireless/ath/ath11k/debugfs.c | 85 +++++++++++++++++++--
 drivers/net/wireless/ath/ath11k/debugfs.h | 14 ++++
 drivers/net/wireless/ath/ath11k/hif.h     | 10 +++
 drivers/net/wireless/ath/ath11k/hw.c      | 10 +++
 drivers/net/wireless/ath/ath11k/hw.h      |  8 ++
 drivers/net/wireless/ath/ath11k/pci.c     | 91 ++++++++++++++++++-----
 7 files changed, 214 insertions(+), 35 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 0/3] ath11k: Add support for sram dump
@ 2021-09-13 18:08 ` Jouni Malinen
  0 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:08 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang

From: Baochen Qiang <bqiang@codeaurora.org>

On-board sram contains valuable infomation for debug, this patch adds
a new interface named "sram" in debugfs with which we can dump sram
content using following cmd:

        cat /sys/kernel/ath11k/<pdev name>/sram > sram.dump

Baochen Qiang (3):
  ath11k: Split PCI write/read functions
  ath11k: Move pdev debugfs creation ahead
  ath11k: Implement sram dump interface

 drivers/net/wireless/ath/ath11k/core.c    | 31 +++++---
 drivers/net/wireless/ath/ath11k/debugfs.c | 85 +++++++++++++++++++--
 drivers/net/wireless/ath/ath11k/debugfs.h | 14 ++++
 drivers/net/wireless/ath/ath11k/hif.h     | 10 +++
 drivers/net/wireless/ath/ath11k/hw.c      | 10 +++
 drivers/net/wireless/ath/ath11k/hw.h      |  8 ++
 drivers/net/wireless/ath/ath11k/pci.c     | 91 ++++++++++++++++++-----
 7 files changed, 214 insertions(+), 35 deletions(-)

-- 
2.25.1


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] ath11k: Split PCI write/read functions
  2021-09-13 18:08 ` Jouni Malinen
@ 2021-09-13 18:09   ` Jouni Malinen
  -1 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

ath11k_pci_write32/read32 tries to wake up MHI before doing actual
write/read work, which means each time a u32 is written/read, MHI
wake up is performed. This is not necessary in case where we do a
large amount of write/read, cause only one time of wake up is needed.
So split each one into two parts, the first part does MHI get/put
and the second one does actual write/read work.

Also avoid the put operation if the previous get operation fails.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/pci.c | 61 ++++++++++++++++++---------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 1094b53465bc..5c3ec3e7be89 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -174,18 +174,11 @@ static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
 	return window_start;
 }
 
-void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
+void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
 	u32 window_start;
 
-	/* for offset beyond BAR + 4K - 32, may
-	 * need to wakeup MHI to access.
-	 */
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
-
 	if (offset < WINDOW_START) {
 		iowrite32(value, ab->mem  + offset);
 	} else {
@@ -205,23 +198,33 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
 				  (offset & WINDOW_RANGE_MASK));
 		}
 	}
-
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 }
 
-u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
+void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
-	u32 val, window_start;
+	bool wakeup_required;
+	int ret;
 
 	/* for offset beyond BAR + 4K - 32, may
 	 * need to wakeup MHI to access.
 	 */
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  offset >= ACCESS_ALWAYS_OFF;
+
+	if (wakeup_required)
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+
+	ath11k_pci_do_write32(ab, offset, value);
+
+	if (wakeup_required && !ret)
+		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
+}
+
+u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 val, window_start;
 
 	if (offset < WINDOW_START) {
 		val = ioread32(ab->mem + offset);
@@ -243,8 +246,28 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
 		}
 	}
 
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
+	return val;
+}
+
+u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 val;
+	bool wakeup_required;
+	int ret;
+
+	/* for offset beyond BAR + 4K - 32, may
+	 * need to wakeup MHI to access.
+	 */
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  offset >= ACCESS_ALWAYS_OFF;
+
+	if (wakeup_required)
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+
+	val = ath11k_pci_do_read32(ab, offset);
+
+	if (wakeup_required && !ret)
 		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 
 	return val;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 1/3] ath11k: Split PCI write/read functions
@ 2021-09-13 18:09   ` Jouni Malinen
  0 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

ath11k_pci_write32/read32 tries to wake up MHI before doing actual
write/read work, which means each time a u32 is written/read, MHI
wake up is performed. This is not necessary in case where we do a
large amount of write/read, cause only one time of wake up is needed.
So split each one into two parts, the first part does MHI get/put
and the second one does actual write/read work.

Also avoid the put operation if the previous get operation fails.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/pci.c | 61 ++++++++++++++++++---------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 1094b53465bc..5c3ec3e7be89 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -174,18 +174,11 @@ static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
 	return window_start;
 }
 
-void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
+void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
 	u32 window_start;
 
-	/* for offset beyond BAR + 4K - 32, may
-	 * need to wakeup MHI to access.
-	 */
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
-
 	if (offset < WINDOW_START) {
 		iowrite32(value, ab->mem  + offset);
 	} else {
@@ -205,23 +198,33 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
 				  (offset & WINDOW_RANGE_MASK));
 		}
 	}
-
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 }
 
-u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
+void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
 	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
-	u32 val, window_start;
+	bool wakeup_required;
+	int ret;
 
 	/* for offset beyond BAR + 4K - 32, may
 	 * need to wakeup MHI to access.
 	 */
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
-		mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  offset >= ACCESS_ALWAYS_OFF;
+
+	if (wakeup_required)
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+
+	ath11k_pci_do_write32(ab, offset, value);
+
+	if (wakeup_required && !ret)
+		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
+}
+
+u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 val, window_start;
 
 	if (offset < WINDOW_START) {
 		val = ioread32(ab->mem + offset);
@@ -243,8 +246,28 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
 		}
 	}
 
-	if (test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
-	    offset >= ACCESS_ALWAYS_OFF)
+	return val;
+}
+
+u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 val;
+	bool wakeup_required;
+	int ret;
+
+	/* for offset beyond BAR + 4K - 32, may
+	 * need to wakeup MHI to access.
+	 */
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  offset >= ACCESS_ALWAYS_OFF;
+
+	if (wakeup_required)
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+
+	val = ath11k_pci_do_read32(ab, offset);
+
+	if (wakeup_required && !ret)
 		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 
 	return val;
-- 
2.25.1


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
  2021-09-13 18:08 ` Jouni Malinen
@ 2021-09-13 18:09   ` Jouni Malinen
  -1 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

The sram dump debugfs interface has to be put under pdev directory
located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev directory
is created after firmware is ready, this is too late for sram dump.
Suppose that if errors happen and ath11k fails to reach firmware
ready, we have no way to dump sram content to debug cause the
interface has not been created yet. So move it ahead.

Also move pdev debugfs destroy to ath11k_core_soc_destroy as a mirror.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.c    | 23 +++++++++++++----------
 drivers/net/wireless/ath/ath11k/debugfs.c | 21 +++++++++++++++------
 drivers/net/wireless/ath/ath11k/debugfs.h |  9 +++++++++
 3 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 9f2c9795767e..59fa0ff06dff 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -701,14 +701,22 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 		goto err_qmi_deinit;
 	}
 
+	ret = ath11k_debugfs_pdev_create(ab);
+	if (ret) {
+		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
+		goto err_debugfs_reg;
+	}
+
 	ret = ath11k_hif_power_up(ab);
 	if (ret) {
 		ath11k_err(ab, "failed to power up :%d\n", ret);
-		goto err_debugfs_reg;
+		goto err_pdev_debug;
 	}
 
 	return 0;
 
+err_pdev_debug:
+	ath11k_debugfs_pdev_destroy(ab);
 err_debugfs_reg:
 	ath11k_debugfs_soc_destroy(ab);
 err_qmi_deinit:
@@ -718,6 +726,7 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 
 static void ath11k_core_soc_destroy(struct ath11k_base *ab)
 {
+	ath11k_debugfs_pdev_destroy(ab);
 	ath11k_debugfs_soc_destroy(ab);
 	ath11k_dp_free(ab);
 	ath11k_reg_free(ab);
@@ -728,16 +737,13 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
 {
 	int ret;
 
-	ret = ath11k_debugfs_pdev_create(ab);
-	if (ret) {
-		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
-		return ret;
-	}
+	ath11k_debugfs_crash_trigger_create(ab);
+	ath11k_debugfs_dp_stats_create(ab);
 
 	ret = ath11k_mac_register(ab);
 	if (ret) {
 		ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
-		goto err_pdev_debug;
+		return ret;
 	}
 
 	ret = ath11k_dp_pdev_alloc(ab);
@@ -767,8 +773,6 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
 	ath11k_dp_pdev_free(ab);
 err_mac_unregister:
 	ath11k_mac_unregister(ab);
-err_pdev_debug:
-	ath11k_debugfs_pdev_destroy(ab);
 
 	return ret;
 }
@@ -780,7 +784,6 @@ static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
 	ath11k_mac_unregister(ab);
 	ath11k_hif_irq_disable(ab);
 	ath11k_dp_pdev_free(ab);
-	ath11k_debugfs_pdev_destroy(ab);
 }
 
 static int ath11k_core_start(struct ath11k_base *ab,
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 17f0bbbac7ae..cdc492421807 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -831,20 +831,29 @@ static const struct file_operations fops_soc_dp_stats = {
 	.llseek = default_llseek,
 };
 
-int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
+void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
 {
 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
-		return 0;
-
-	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
-	if (IS_ERR(ab->debugfs_soc))
-		return PTR_ERR(ab->debugfs_soc);
+		return;
 
 	debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
 			    &fops_simulate_fw_crash);
+}
+
+void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
+{
+	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
+		return;
 
 	debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
 			    &fops_soc_dp_stats);
+}
+
+int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
+{
+	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
+	if (IS_ERR(ab->debugfs_soc))
+		return PTR_ERR(ab->debugfs_soc);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
index e5346af71f24..47b96848cf0a 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
@@ -145,6 +145,8 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 	return ar->debug.rx_filter;
 }
 
+void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab);
+void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab);
 #else
 static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
 {
@@ -212,6 +214,13 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 	return 0;
 }
 
+static inline void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
+{
+}
+
+static inline void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
+{
+}
 #endif /* CONFIG_MAC80211_DEBUGFS*/
 
 #endif /* _ATH11K_DEBUGFS_H_ */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
@ 2021-09-13 18:09   ` Jouni Malinen
  0 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

The sram dump debugfs interface has to be put under pdev directory
located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev directory
is created after firmware is ready, this is too late for sram dump.
Suppose that if errors happen and ath11k fails to reach firmware
ready, we have no way to dump sram content to debug cause the
interface has not been created yet. So move it ahead.

Also move pdev debugfs destroy to ath11k_core_soc_destroy as a mirror.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.c    | 23 +++++++++++++----------
 drivers/net/wireless/ath/ath11k/debugfs.c | 21 +++++++++++++++------
 drivers/net/wireless/ath/ath11k/debugfs.h |  9 +++++++++
 3 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 9f2c9795767e..59fa0ff06dff 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -701,14 +701,22 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 		goto err_qmi_deinit;
 	}
 
+	ret = ath11k_debugfs_pdev_create(ab);
+	if (ret) {
+		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
+		goto err_debugfs_reg;
+	}
+
 	ret = ath11k_hif_power_up(ab);
 	if (ret) {
 		ath11k_err(ab, "failed to power up :%d\n", ret);
-		goto err_debugfs_reg;
+		goto err_pdev_debug;
 	}
 
 	return 0;
 
+err_pdev_debug:
+	ath11k_debugfs_pdev_destroy(ab);
 err_debugfs_reg:
 	ath11k_debugfs_soc_destroy(ab);
 err_qmi_deinit:
@@ -718,6 +726,7 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 
 static void ath11k_core_soc_destroy(struct ath11k_base *ab)
 {
+	ath11k_debugfs_pdev_destroy(ab);
 	ath11k_debugfs_soc_destroy(ab);
 	ath11k_dp_free(ab);
 	ath11k_reg_free(ab);
@@ -728,16 +737,13 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
 {
 	int ret;
 
-	ret = ath11k_debugfs_pdev_create(ab);
-	if (ret) {
-		ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
-		return ret;
-	}
+	ath11k_debugfs_crash_trigger_create(ab);
+	ath11k_debugfs_dp_stats_create(ab);
 
 	ret = ath11k_mac_register(ab);
 	if (ret) {
 		ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
-		goto err_pdev_debug;
+		return ret;
 	}
 
 	ret = ath11k_dp_pdev_alloc(ab);
@@ -767,8 +773,6 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
 	ath11k_dp_pdev_free(ab);
 err_mac_unregister:
 	ath11k_mac_unregister(ab);
-err_pdev_debug:
-	ath11k_debugfs_pdev_destroy(ab);
 
 	return ret;
 }
@@ -780,7 +784,6 @@ static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
 	ath11k_mac_unregister(ab);
 	ath11k_hif_irq_disable(ab);
 	ath11k_dp_pdev_free(ab);
-	ath11k_debugfs_pdev_destroy(ab);
 }
 
 static int ath11k_core_start(struct ath11k_base *ab,
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 17f0bbbac7ae..cdc492421807 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -831,20 +831,29 @@ static const struct file_operations fops_soc_dp_stats = {
 	.llseek = default_llseek,
 };
 
-int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
+void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
 {
 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
-		return 0;
-
-	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
-	if (IS_ERR(ab->debugfs_soc))
-		return PTR_ERR(ab->debugfs_soc);
+		return;
 
 	debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
 			    &fops_simulate_fw_crash);
+}
+
+void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
+{
+	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
+		return;
 
 	debugfs_create_file("soc_dp_stats", 0600, ab->debugfs_soc, ab,
 			    &fops_soc_dp_stats);
+}
+
+int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
+{
+	ab->debugfs_soc = debugfs_create_dir(ab->hw_params.name, ab->debugfs_ath11k);
+	if (IS_ERR(ab->debugfs_soc))
+		return PTR_ERR(ab->debugfs_soc);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
index e5346af71f24..47b96848cf0a 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
@@ -145,6 +145,8 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 	return ar->debug.rx_filter;
 }
 
+void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab);
+void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab);
 #else
 static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
 {
@@ -212,6 +214,13 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 	return 0;
 }
 
+static inline void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
+{
+}
+
+static inline void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
+{
+}
 #endif /* CONFIG_MAC80211_DEBUGFS*/
 
 #endif /* _ATH11K_DEBUGFS_H_ */
-- 
2.25.1


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] ath11k: Implement sram dump interface
  2021-09-13 18:08 ` Jouni Malinen
@ 2021-09-13 18:09   ` Jouni Malinen
  -1 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

Currently this feature is enabled for QCA6390/WCN6855.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.c    |  8 +++
 drivers/net/wireless/ath/ath11k/debugfs.c | 64 +++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/debugfs.h |  5 ++
 drivers/net/wireless/ath/ath11k/hif.h     | 10 ++++
 drivers/net/wireless/ath/ath11k/hw.c      | 10 ++++
 drivers/net/wireless/ath/ath11k/hw.h      |  8 +++
 drivers/net/wireless/ath/ath11k/pci.c     | 30 +++++++++++
 7 files changed, 135 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 59fa0ff06dff..8f09ae827170 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -81,6 +81,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -129,6 +130,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.name = "qca6390 hw2.0",
@@ -176,6 +178,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = true,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = &sram_dump_qca6390,
 	},
 	{
 		.name = "qcn9074 hw1.0",
@@ -223,6 +226,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.fw_mem_mode = 2,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.name = "wcn6855 hw2.0",
@@ -269,6 +273,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.fw_mem_mode = 0,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
 		.fix_l1ss = false,
+		.sram_dump = &sram_dump_wcn6855,
 	},
 };
 
@@ -707,6 +712,9 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 		goto err_debugfs_reg;
 	}
 
+	if (ab->hw_params.sram_dump)
+		ath11k_debugfs_sram_dump_create(ab);
+
 	ret = ath11k_hif_power_up(ab);
 	if (ret) {
 		ath11k_err(ab, "failed to power up :%d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index cdc492421807..871445f4e96a 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -12,6 +12,7 @@
 #include "dp_tx.h"
 #include "debugfs_htt_stats.h"
 #include "peer.h"
+#include "hif.h"
 
 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
 	"REO2SW1_RING",
@@ -1122,3 +1123,66 @@ int ath11k_debugfs_register(struct ath11k *ar)
 void ath11k_debugfs_unregister(struct ath11k *ar)
 {
 }
+
+static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
+{
+	struct ath11k_base *ab = inode->i_private;
+	u8 *buf;
+	u32 start, end;
+	int ret;
+
+	start = ab->hw_params.sram_dump->start;
+	end = ab->hw_params.sram_dump->end;
+
+	buf = vmalloc(end - start + 1);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = ath11k_hif_dump_sram(ab, buf, start, end);
+	if (ret) {
+		ath11k_err(ab, "failed to dump sram: %d\n", ret);
+		vfree(buf);
+		return ret;
+	}
+
+	file->private_data = buf;
+	return 0;
+}
+
+static ssize_t ath11k_read_sram_dump(struct file *file,
+				     char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	struct ath11k_base *ab = file->f_inode->i_private;
+	const char *buf = file->private_data;
+	int len;
+	u32 start, end;
+
+	start = ab->hw_params.sram_dump->start;
+	end = ab->hw_params.sram_dump->end;
+	len = end - start + 1;
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
+{
+	vfree(file->private_data);
+	file->private_data = NULL;
+
+	return 0;
+}
+
+static const struct file_operations fops_sram_dump = {
+	.open = ath11k_open_sram_dump,
+	.read = ath11k_read_sram_dump,
+	.release = ath11k_release_sram_dump,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab)
+{
+	debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
+			    &fops_sram_dump);
+}
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
index 47b96848cf0a..7b9c5e465208 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
@@ -147,6 +147,7 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 
 void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab);
 void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab);
+void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab);
 #else
 static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
 {
@@ -221,6 +222,10 @@ static inline void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
 static inline void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
 {
 }
+
+static inline void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab)
+{
+}
 #endif /* CONFIG_MAC80211_DEBUGFS*/
 
 #endif /* _ATH11K_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h
index e9366f786fbb..8fcf7500e5c6 100644
--- a/drivers/net/wireless/ath/ath11k/hif.h
+++ b/drivers/net/wireless/ath/ath11k/hif.h
@@ -29,6 +29,7 @@ struct ath11k_hif_ops {
 	void (*ce_irq_enable)(struct ath11k_base *ab);
 	void (*ce_irq_disable)(struct ath11k_base *ab);
 	void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx);
+	int (*dump_sram)(struct ath11k_base *ab, u8 *buf, u32 start, u32 end);
 };
 
 static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab)
@@ -134,4 +135,13 @@ static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
 	else
 		*msi_data_idx = ce_id;
 }
+
+static inline int ath11k_hif_dump_sram(struct ath11k_base *ab, u8 *buf,
+				       u32 start, u32 end)
+{
+	if (!ab->hif.ops->dump_sram)
+		return -EOPNOTSUPP;
+
+	return ab->hif.ops->dump_sram(ab, buf, start, end);
+}
 #endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index e54b02fd2cc3..57fab9d085d0 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2124,3 +2124,13 @@ const struct ath11k_hw_regs wcn6855_regs = {
 	.pcie_qserdes_sysclk_en_sel = 0x01e0c0ac,
 	.pcie_pcs_osc_dtct_config_base = 0x01e0c628,
 };
+
+const struct ath11k_hw_sram_dump sram_dump_qca6390 = {
+	.start = 0x01400000,
+	.end = 0x0171ffff,
+};
+
+const struct ath11k_hw_sram_dump sram_dump_wcn6855 = {
+	.start = 0x01400000,
+	.end = 0x0177ffff,
+};
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index a1be4f79acb4..484c0bcec86d 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -120,6 +120,11 @@ struct ath11k_hw_ring_mask {
 	u8 host2rxdma[ATH11K_EXT_IRQ_GRP_NUM_MAX];
 };
 
+struct ath11k_hw_sram_dump {
+	u32 start;
+	u32 end;
+};
+
 struct ath11k_hw_params {
 	const char *name;
 	u16 hw_rev;
@@ -173,6 +178,7 @@ struct ath11k_hw_params {
 	bool supports_suspend;
 	u32 hal_desc_sz;
 	bool fix_l1ss;
+	const struct ath11k_hw_sram_dump *sram_dump;
 };
 
 struct ath11k_hw_ops {
@@ -336,4 +342,6 @@ extern const struct ath11k_hw_regs qca6390_regs;
 extern const struct ath11k_hw_regs qcn9074_regs;
 extern const struct ath11k_hw_regs wcn6855_regs;
 
+extern const struct ath11k_hw_sram_dump sram_dump_qca6390;
+extern const struct ath11k_hw_sram_dump sram_dump_wcn6855;
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 5c3ec3e7be89..c6540d562c42 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -273,6 +273,35 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
 	return val;
 }
 
+static int ath11k_pci_dump_sram(struct ath11k_base *ab, u8 *buf,
+				u32 start, u32 end)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 i;
+	int ret;
+	bool wakeup_required;
+	u32 *data = (u32 *)buf;
+
+	/* for offset beyond BAR + 4K - 32, may
+	 * need to wakeup MHI to access.
+	 */
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  end >= ACCESS_ALWAYS_OFF;
+	if (wakeup_required) {
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+		if (ret)
+			ath11k_warn(ab, "%s: failed to wakeup MHI: %d\n", __func__, ret);
+	}
+
+	for (i = start; i < end + 1; i += 4)
+		*data++ = ath11k_pci_do_read32(ab, i);
+
+	if (wakeup_required && !ret)
+		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
+
+	return 0;
+}
+
 static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
 {
 	u32 val, delay;
@@ -1213,6 +1242,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
 	.ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
 	.ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
 	.get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
+	.dump_sram = ath11k_pci_dump_sram,
 };
 
 static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] ath11k: Implement sram dump interface
@ 2021-09-13 18:09   ` Jouni Malinen
  0 siblings, 0 replies; 14+ messages in thread
From: Jouni Malinen @ 2021-09-13 18:09 UTC (permalink / raw)
  To: Kalle Valo; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

From: Baochen Qiang <bqiang@codeaurora.org>

Currently this feature is enabled for QCA6390/WCN6855.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1

Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.c    |  8 +++
 drivers/net/wireless/ath/ath11k/debugfs.c | 64 +++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/debugfs.h |  5 ++
 drivers/net/wireless/ath/ath11k/hif.h     | 10 ++++
 drivers/net/wireless/ath/ath11k/hw.c      | 10 ++++
 drivers/net/wireless/ath/ath11k/hw.h      |  8 +++
 drivers/net/wireless/ath/ath11k/pci.c     | 30 +++++++++++
 7 files changed, 135 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 59fa0ff06dff..8f09ae827170 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -81,6 +81,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -129,6 +130,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.name = "qca6390 hw2.0",
@@ -176,6 +178,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.supports_suspend = true,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
 		.fix_l1ss = true,
+		.sram_dump = &sram_dump_qca6390,
 	},
 	{
 		.name = "qcn9074 hw1.0",
@@ -223,6 +226,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.fw_mem_mode = 2,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
 		.fix_l1ss = true,
+		.sram_dump = NULL,
 	},
 	{
 		.name = "wcn6855 hw2.0",
@@ -269,6 +273,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 		.fw_mem_mode = 0,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
 		.fix_l1ss = false,
+		.sram_dump = &sram_dump_wcn6855,
 	},
 };
 
@@ -707,6 +712,9 @@ static int ath11k_core_soc_create(struct ath11k_base *ab)
 		goto err_debugfs_reg;
 	}
 
+	if (ab->hw_params.sram_dump)
+		ath11k_debugfs_sram_dump_create(ab);
+
 	ret = ath11k_hif_power_up(ab);
 	if (ret) {
 		ath11k_err(ab, "failed to power up :%d\n", ret);
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index cdc492421807..871445f4e96a 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -12,6 +12,7 @@
 #include "dp_tx.h"
 #include "debugfs_htt_stats.h"
 #include "peer.h"
+#include "hif.h"
 
 static const char *htt_bp_umac_ring[HTT_SW_UMAC_RING_IDX_MAX] = {
 	"REO2SW1_RING",
@@ -1122,3 +1123,66 @@ int ath11k_debugfs_register(struct ath11k *ar)
 void ath11k_debugfs_unregister(struct ath11k *ar)
 {
 }
+
+static int ath11k_open_sram_dump(struct inode *inode, struct file *file)
+{
+	struct ath11k_base *ab = inode->i_private;
+	u8 *buf;
+	u32 start, end;
+	int ret;
+
+	start = ab->hw_params.sram_dump->start;
+	end = ab->hw_params.sram_dump->end;
+
+	buf = vmalloc(end - start + 1);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = ath11k_hif_dump_sram(ab, buf, start, end);
+	if (ret) {
+		ath11k_err(ab, "failed to dump sram: %d\n", ret);
+		vfree(buf);
+		return ret;
+	}
+
+	file->private_data = buf;
+	return 0;
+}
+
+static ssize_t ath11k_read_sram_dump(struct file *file,
+				     char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	struct ath11k_base *ab = file->f_inode->i_private;
+	const char *buf = file->private_data;
+	int len;
+	u32 start, end;
+
+	start = ab->hw_params.sram_dump->start;
+	end = ab->hw_params.sram_dump->end;
+	len = end - start + 1;
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static int ath11k_release_sram_dump(struct inode *inode, struct file *file)
+{
+	vfree(file->private_data);
+	file->private_data = NULL;
+
+	return 0;
+}
+
+static const struct file_operations fops_sram_dump = {
+	.open = ath11k_open_sram_dump,
+	.read = ath11k_read_sram_dump,
+	.release = ath11k_release_sram_dump,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab)
+{
+	debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
+			    &fops_sram_dump);
+}
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.h b/drivers/net/wireless/ath/ath11k/debugfs.h
index 47b96848cf0a..7b9c5e465208 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.h
+++ b/drivers/net/wireless/ath/ath11k/debugfs.h
@@ -147,6 +147,7 @@ static inline int ath11k_debugfs_rx_filter(struct ath11k *ar)
 
 void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab);
 void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab);
+void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab);
 #else
 static inline int ath11k_debugfs_soc_create(struct ath11k_base *ab)
 {
@@ -221,6 +222,10 @@ static inline void ath11k_debugfs_crash_trigger_create(struct ath11k_base *ab)
 static inline void ath11k_debugfs_dp_stats_create(struct ath11k_base *ab)
 {
 }
+
+static inline void ath11k_debugfs_sram_dump_create(struct ath11k_base *ab)
+{
+}
 #endif /* CONFIG_MAC80211_DEBUGFS*/
 
 #endif /* _ATH11K_DEBUGFS_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/hif.h b/drivers/net/wireless/ath/ath11k/hif.h
index e9366f786fbb..8fcf7500e5c6 100644
--- a/drivers/net/wireless/ath/ath11k/hif.h
+++ b/drivers/net/wireless/ath/ath11k/hif.h
@@ -29,6 +29,7 @@ struct ath11k_hif_ops {
 	void (*ce_irq_enable)(struct ath11k_base *ab);
 	void (*ce_irq_disable)(struct ath11k_base *ab);
 	void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx);
+	int (*dump_sram)(struct ath11k_base *ab, u8 *buf, u32 start, u32 end);
 };
 
 static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab)
@@ -134,4 +135,13 @@ static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
 	else
 		*msi_data_idx = ce_id;
 }
+
+static inline int ath11k_hif_dump_sram(struct ath11k_base *ab, u8 *buf,
+				       u32 start, u32 end)
+{
+	if (!ab->hif.ops->dump_sram)
+		return -EOPNOTSUPP;
+
+	return ab->hif.ops->dump_sram(ab, buf, start, end);
+}
 #endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c
index e54b02fd2cc3..57fab9d085d0 100644
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -2124,3 +2124,13 @@ const struct ath11k_hw_regs wcn6855_regs = {
 	.pcie_qserdes_sysclk_en_sel = 0x01e0c0ac,
 	.pcie_pcs_osc_dtct_config_base = 0x01e0c628,
 };
+
+const struct ath11k_hw_sram_dump sram_dump_qca6390 = {
+	.start = 0x01400000,
+	.end = 0x0171ffff,
+};
+
+const struct ath11k_hw_sram_dump sram_dump_wcn6855 = {
+	.start = 0x01400000,
+	.end = 0x0177ffff,
+};
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index a1be4f79acb4..484c0bcec86d 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -120,6 +120,11 @@ struct ath11k_hw_ring_mask {
 	u8 host2rxdma[ATH11K_EXT_IRQ_GRP_NUM_MAX];
 };
 
+struct ath11k_hw_sram_dump {
+	u32 start;
+	u32 end;
+};
+
 struct ath11k_hw_params {
 	const char *name;
 	u16 hw_rev;
@@ -173,6 +178,7 @@ struct ath11k_hw_params {
 	bool supports_suspend;
 	u32 hal_desc_sz;
 	bool fix_l1ss;
+	const struct ath11k_hw_sram_dump *sram_dump;
 };
 
 struct ath11k_hw_ops {
@@ -336,4 +342,6 @@ extern const struct ath11k_hw_regs qca6390_regs;
 extern const struct ath11k_hw_regs qcn9074_regs;
 extern const struct ath11k_hw_regs wcn6855_regs;
 
+extern const struct ath11k_hw_sram_dump sram_dump_qca6390;
+extern const struct ath11k_hw_sram_dump sram_dump_wcn6855;
 #endif
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 5c3ec3e7be89..c6540d562c42 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -273,6 +273,35 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
 	return val;
 }
 
+static int ath11k_pci_dump_sram(struct ath11k_base *ab, u8 *buf,
+				u32 start, u32 end)
+{
+	struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+	u32 i;
+	int ret;
+	bool wakeup_required;
+	u32 *data = (u32 *)buf;
+
+	/* for offset beyond BAR + 4K - 32, may
+	 * need to wakeup MHI to access.
+	 */
+	wakeup_required = test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) &&
+			  end >= ACCESS_ALWAYS_OFF;
+	if (wakeup_required) {
+		ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev);
+		if (ret)
+			ath11k_warn(ab, "%s: failed to wakeup MHI: %d\n", __func__, ret);
+	}
+
+	for (i = start; i < end + 1; i += 4)
+		*data++ = ath11k_pci_do_read32(ab, i);
+
+	if (wakeup_required && !ret)
+		mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
+
+	return 0;
+}
+
 static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
 {
 	u32 val, delay;
@@ -1213,6 +1242,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
 	.ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
 	.ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
 	.get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
+	.dump_sram = ath11k_pci_dump_sram,
 };
 
 static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
-- 
2.25.1


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] ath11k: Split PCI write/read functions
  2021-09-13 18:09   ` Jouni Malinen
  (?)
  (?)
@ 2021-09-14  8:36   ` Kalle Valo
  -1 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2021-09-14  8:36 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

Jouni Malinen <jouni@codeaurora.org> wrote:

> ath11k_pci_write32/read32 tries to wake up MHI before doing actual
> write/read work, which means each time a u32 is written/read, MHI
> wake up is performed. This is not necessary in case where we do a
> large amount of write/read, cause only one time of wake up is needed.
> So split each one into two parts, the first part does MHI get/put
> and the second one does actual write/read work.
> 
> Also avoid the put operation if the previous get operation fails.
> 
> Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
> 
> Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
> Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

This causes new warnings:

drivers/net/wireless/ath/ath11k/pci.c:177:6: error: no previous prototype for 'ath11k_pci_do_write32' [-Werror=missing-prototypes]
drivers/net/wireless/ath/ath11k/pci.c:224:5: error: no previous prototype for 'ath11k_pci_do_read32' [-Werror=missing-prototypes]

I fixed them in the pending branch like this:

--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -174,7 +174,7 @@ static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
        return window_start;
 }
 
-void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
+static void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 window_start;
@@ -221,7 +221,7 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
                mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 }
 
-u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
+static u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 val, window_start;


-- 
https://patchwork.kernel.org/project/linux-wireless/patch/20210913180902.193874-2-jouni@codeaurora.org/

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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] ath11k: Split PCI write/read functions
  2021-09-13 18:09   ` Jouni Malinen
  (?)
@ 2021-09-14  8:36   ` Kalle Valo
  -1 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2021-09-14  8:36 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: ath11k, linux-wireless, Baochen Qiang, Jouni Malinen

Jouni Malinen <jouni@codeaurora.org> wrote:

> ath11k_pci_write32/read32 tries to wake up MHI before doing actual
> write/read work, which means each time a u32 is written/read, MHI
> wake up is performed. This is not necessary in case where we do a
> large amount of write/read, cause only one time of wake up is needed.
> So split each one into two parts, the first part does MHI get/put
> and the second one does actual write/read work.
> 
> Also avoid the put operation if the previous get operation fails.
> 
> Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
> Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1
> 
> Signed-off-by: Baochen Qiang <bqiang@codeaurora.org>
> Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

This causes new warnings:

drivers/net/wireless/ath/ath11k/pci.c:177:6: error: no previous prototype for 'ath11k_pci_do_write32' [-Werror=missing-prototypes]
drivers/net/wireless/ath/ath11k/pci.c:224:5: error: no previous prototype for 'ath11k_pci_do_read32' [-Werror=missing-prototypes]

I fixed them in the pending branch like this:

--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -174,7 +174,7 @@ static inline u32 ath11k_pci_get_window_start(struct ath11k_base *ab,
        return window_start;
 }
 
-void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
+static void ath11k_pci_do_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 window_start;
@@ -221,7 +221,7 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
                mhi_device_put(ab_pci->mhi_ctrl->mhi_dev);
 }
 
-u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
+static u32 ath11k_pci_do_read32(struct ath11k_base *ab, u32 offset)
 {
        struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
        u32 val, window_start;


-- 
https://patchwork.kernel.org/project/linux-wireless/patch/20210913180902.193874-2-jouni@codeaurora.org/

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


-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
  2021-09-13 18:09   ` Jouni Malinen
@ 2021-12-07 17:47     ` Kalle Valo
  -1 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2021-12-07 17:47 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: ath11k, linux-wireless, Baochen Qiang

Jouni Malinen <jouni@codeaurora.org> writes:

> From: Baochen Qiang <bqiang@codeaurora.org>
>
> The sram dump debugfs interface has to be put under pdev directory
> located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev directory
> is created after firmware is ready, this is too late for sram dump.
> Suppose that if errors happen and ath11k fails to reach firmware
> ready, we have no way to dump sram content to debug cause the
> interface has not been created yet. So move it ahead.

I'm not sure about this. What will happen with other debugfs files now
that they are created before the firmware is ready, doesn't that create
race conditions?

Also we need to do some refactoring in debugfs, for example see Anil's
patch:

https://patchwork.kernel.org/project/linux-wireless/patch/1614160542-27882-1-git-send-email-akolli@codeaurora.org/

So I recommend dropping patch 2 for now and get the basic sram dump
functionality ready first. After that we can discuss how to handle
firmware crashes during driver initialisation, maybe coredump would be a
better approach?

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
@ 2021-12-07 17:47     ` Kalle Valo
  0 siblings, 0 replies; 14+ messages in thread
From: Kalle Valo @ 2021-12-07 17:47 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: ath11k, linux-wireless, Baochen Qiang

Jouni Malinen <jouni@codeaurora.org> writes:

> From: Baochen Qiang <bqiang@codeaurora.org>
>
> The sram dump debugfs interface has to be put under pdev directory
> located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev directory
> is created after firmware is ready, this is too late for sram dump.
> Suppose that if errors happen and ath11k fails to reach firmware
> ready, we have no way to dump sram content to debug cause the
> interface has not been created yet. So move it ahead.

I'm not sure about this. What will happen with other debugfs files now
that they are created before the firmware is ready, doesn't that create
race conditions?

Also we need to do some refactoring in debugfs, for example see Anil's
patch:

https://patchwork.kernel.org/project/linux-wireless/patch/1614160542-27882-1-git-send-email-akolli@codeaurora.org/

So I recommend dropping patch 2 for now and get the basic sram dump
functionality ready first. After that we can discuss how to handle
firmware crashes during driver initialisation, maybe coredump would be a
better approach?

-- 
https://patchwork.kernel.org/project/linux-wireless/list/

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

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
  2021-12-07 17:47     ` Kalle Valo
@ 2021-12-08  1:34       ` Baochen Qiang
  -1 siblings, 0 replies; 14+ messages in thread
From: Baochen Qiang @ 2021-12-08  1:34 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Jouni Malinen, ath11k, linux-wireless

On 2021-12-08 01:47, Kalle Valo wrote:
> Jouni Malinen <jouni@codeaurora.org> writes:
> 
>> From: Baochen Qiang <bqiang@codeaurora.org>
>> 
>> The sram dump debugfs interface has to be put under pdev directory
>> located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev 
>> directory
>> is created after firmware is ready, this is too late for sram dump.
>> Suppose that if errors happen and ath11k fails to reach firmware
>> ready, we have no way to dump sram content to debug cause the
>> interface has not been created yet. So move it ahead.
> 
> I'm not sure about this. What will happen with other debugfs files now
> that they are created before the firmware is ready, doesn't that create
> race conditions?
> 
> Also we need to do some refactoring in debugfs, for example see Anil's
> patch:
> 
> https://patchwork.kernel.org/project/linux-wireless/patch/1614160542-27882-1-git-send-email-akolli@codeaurora.org/
> 
> So I recommend dropping patch 2 for now and get the basic sram dump
> functionality ready first. After that we can discuss how to handle
> firmware crashes during driver initialisation, maybe coredump would be 
> a
> better approach?

Sure, Kalle, let's get basic functionality ready first.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] ath11k: Move pdev debugfs creation ahead
@ 2021-12-08  1:34       ` Baochen Qiang
  0 siblings, 0 replies; 14+ messages in thread
From: Baochen Qiang @ 2021-12-08  1:34 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Jouni Malinen, ath11k, linux-wireless

On 2021-12-08 01:47, Kalle Valo wrote:
> Jouni Malinen <jouni@codeaurora.org> writes:
> 
>> From: Baochen Qiang <bqiang@codeaurora.org>
>> 
>> The sram dump debugfs interface has to be put under pdev directory
>> located under /sys/kernel/debug/ath11k/<pdev name>. Currently pdev 
>> directory
>> is created after firmware is ready, this is too late for sram dump.
>> Suppose that if errors happen and ath11k fails to reach firmware
>> ready, we have no way to dump sram content to debug cause the
>> interface has not been created yet. So move it ahead.
> 
> I'm not sure about this. What will happen with other debugfs files now
> that they are created before the firmware is ready, doesn't that create
> race conditions?
> 
> Also we need to do some refactoring in debugfs, for example see Anil's
> patch:
> 
> https://patchwork.kernel.org/project/linux-wireless/patch/1614160542-27882-1-git-send-email-akolli@codeaurora.org/
> 
> So I recommend dropping patch 2 for now and get the basic sram dump
> functionality ready first. After that we can discuss how to handle
> firmware crashes during driver initialisation, maybe coredump would be 
> a
> better approach?

Sure, Kalle, let's get basic functionality ready first.

-- 
ath11k mailing list
ath11k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath11k

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2021-12-08  1:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-13 18:08 [PATCH 0/3] ath11k: Add support for sram dump Jouni Malinen
2021-09-13 18:08 ` Jouni Malinen
2021-09-13 18:09 ` [PATCH 1/3] ath11k: Split PCI write/read functions Jouni Malinen
2021-09-13 18:09   ` Jouni Malinen
2021-09-14  8:36   ` Kalle Valo
2021-09-14  8:36   ` Kalle Valo
2021-09-13 18:09 ` [PATCH 2/3] ath11k: Move pdev debugfs creation ahead Jouni Malinen
2021-09-13 18:09   ` Jouni Malinen
2021-12-07 17:47   ` Kalle Valo
2021-12-07 17:47     ` Kalle Valo
2021-12-08  1:34     ` Baochen Qiang
2021-12-08  1:34       ` Baochen Qiang
2021-09-13 18:09 ` [PATCH 3/3] ath11k: Implement sram dump interface Jouni Malinen
2021-09-13 18:09   ` Jouni Malinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.