From 3b50a7a585b7f7da56208dead7d803e54e1e2569 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 16 Mar 2023 12:35:49 +0800
Subject: [PATCH 03/70] sync backport patches/ath5k

---
 drivers/net/wireless/ath/ath5k/ath5k.h        |  1 +
 drivers/net/wireless/ath/ath5k/base.c         |  8 +-
 drivers/net/wireless/ath/ath5k/debug.c        | 93 +++++++++++++++++++
 drivers/net/wireless/ath/ath5k/dma.c          |  8 ++
 drivers/net/wireless/ath/ath5k/initvals.c     |  6 ++
 drivers/net/wireless/ath/ath5k/mac80211-ops.c |  9 +-
 drivers/net/wireless/ath/ath5k/pci.c          |  2 +
 drivers/net/wireless/ath/ath5k/reset.c        |  2 +
 include/linux/ath5k_platform.h                | 30 ++++++
 9 files changed, 150 insertions(+), 9 deletions(-)
 create mode 100644 include/linux/ath5k_platform.h

diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 308a429..0e6d184 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1372,6 +1372,7 @@ struct ath5k_hw {
 	u8			ah_coverage_class;
 	bool			ah_ack_bitrate_high;
 	u8			ah_bwmode;
+	u8			ah_bwmode_debug;
 	bool			ah_short_slot;
 
 	/* Antenna Control */
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 469ebc4..97bb797 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -465,6 +465,9 @@ ath5k_chan_set(struct ath5k_hw *ah, struct cfg80211_chan_def *chandef)
 		return -EINVAL;
 	}
 
+	if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
+		ah->ah_bwmode = ah->ah_bwmode_debug;
+
 	/*
 	 * To switch channels clear any pending DMA operations;
 	 * wait long enough for the RX fifo to drain, reset the
@@ -2009,7 +2012,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
 	}
 
 	if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
-			ah->num_mesh_vifs > 1) ||
+			ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
 			ah->opmode == NL80211_IFTYPE_MESH_POINT) {
 		u64 tsf = ath5k_hw_get_tsf64(ah);
 		u32 tsftu = TSF_TO_TU(tsf);
@@ -2095,7 +2098,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
 
 	intval = ah->bintval & AR5K_BEACON_PERIOD;
 	if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
-		+ ah->num_mesh_vifs > 1) {
+		+ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
 		intval /= ATH_BCBUF;	/* staggered multi-bss beacons */
 		if (intval < 15)
 			ATH5K_WARN(ah, "intval %u is too low, min 15\n",
@@ -2561,6 +2564,7 @@ static const struct ieee80211_iface_limit if_limits[] = {
 				 BIT(NL80211_IFTYPE_MESH_POINT) |
 #endif
 				 BIT(NL80211_IFTYPE_AP) },
+	{ .max = 1,	.types = BIT(NL80211_IFTYPE_ADHOC) },
 };
 
 static const struct ieee80211_iface_combination if_comb = {
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 4b41160..257101e 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -803,6 +803,97 @@ static const struct file_operations fops_ani = {
 	.llseek = default_llseek,
 };
 
+/* debugfs: bwmode */
+
+static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
+				   size_t count, loff_t *ppos)
+{
+	struct ath5k_hw *ah = file->private_data;
+	char buf[15];
+	unsigned int len = 0;
+
+	int cur_ah_bwmode = ah->ah_bwmode_debug;
+
+#define print_selected(MODE, LABEL) \
+	if (cur_ah_bwmode == MODE) \
+		len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
+	else \
+		len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
+	len += snprintf(buf+len, sizeof(buf)-len, " ");
+
+	print_selected(AR5K_BWMODE_5MHZ, "5");
+	print_selected(AR5K_BWMODE_10MHZ, "10");
+	print_selected(AR5K_BWMODE_DEFAULT, "20");
+	print_selected(AR5K_BWMODE_40MHZ, "40");
+#undef print_selected
+
+	len += snprintf(buf+len, sizeof(buf)-len, "\n");
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_bwmode(struct file *file,
+				 const char __user *userbuf,
+				 size_t count, loff_t *ppos)
+{
+	struct ath5k_hw *ah = file->private_data;
+	char buf[3];
+	int bw = 20;
+	int tobwmode = AR5K_BWMODE_DEFAULT;
+
+	if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
+		return -EFAULT;
+
+	/* TODO: Add check for active interface */
+
+	if(strncmp(buf, "5", 1) == 0 ) {
+		tobwmode = AR5K_BWMODE_5MHZ;
+		bw = 5;
+	} else if ( strncmp(buf, "10", 2) == 0 ) {
+		tobwmode = AR5K_BWMODE_10MHZ;
+		bw = 10;
+	} else if ( strncmp(buf, "20", 2) == 0 ) {
+		tobwmode = AR5K_BWMODE_DEFAULT;
+		bw = 20;
+	} else if ( strncmp(buf, "40", 2) == 0 ) {
+		tobwmode = AR5K_BWMODE_40MHZ;
+		bw = 40;
+	} else
+		return -EINVAL;
+
+	ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
+		bw, tobwmode);
+
+	switch (ah->ah_radio) {
+	/* TODO: only define radios that actually support 5/10mhz channels */
+	case AR5K_RF5413:
+	case AR5K_RF5110:
+	case AR5K_RF5111:
+	case AR5K_RF5112:
+	case AR5K_RF2413:
+	case AR5K_RF2316:
+	case AR5K_RF2317:
+	case AR5K_RF2425:
+		if(ah->ah_bwmode_debug != tobwmode) {
+			mutex_lock(&ah->lock);
+			ah->ah_bwmode = tobwmode;
+			ah->ah_bwmode_debug = tobwmode;
+			mutex_unlock(&ah->lock);
+		}
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	return count;
+}
+
+static const struct file_operations fops_bwmode = {
+	.read = read_file_bwmode,
+	.write = write_file_bwmode,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
 
 /* debugfs: queues etc */
 
@@ -997,6 +1088,8 @@ ath5k_debug_init_device(struct ath5k_hw *ah)
 	debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
 	debugfs_create_bool("32khz_clock", 0600, phydir,
 			    &ah->ah_use_32khz_clock);
+	debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
+			    &fops_bwmode);
 }
 
 /* functions used in other places */
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index d9e376e..db06ff8 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -854,10 +854,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
 	 * guess we can tweak it and see how it goes ;-)
 	 */
 	if (ah->ah_version != AR5K_AR5210) {
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
 		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
 			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
 		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
 			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
+#else
+		/* WAR for AR71xx PCI bug */
+		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+			AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+		AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+			AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
+#endif
 	}
 
 	/* Pre-enable interrupts on 5211/5212*/
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index ee1c2fa..122fe1c 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini[] = {
 	{ AR5K_IMR,		0 },
 	{ AR5K_IER,		AR5K_IER_DISABLE },
 	{ AR5K_BSR,		0, AR5K_INI_READ },
+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
 	{ AR5K_TXCFG,		AR5K_DMASIZE_128B },
 	{ AR5K_RXCFG,		AR5K_DMASIZE_128B },
+#else
+	/* WAR for AR71xx PCI bug */
+	{ AR5K_TXCFG,		AR5K_DMASIZE_128B },
+	{ AR5K_RXCFG,		AR5K_DMASIZE_4B },
+#endif
 	{ AR5K_CFG,		AR5K_INIT_CFG },
 	{ AR5K_TOPS,		8 },
 	{ AR5K_RXNOFRM,		8 },
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 11ed30d..7de7e71 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 		goto end;
 	}
 
-	/* Don't allow other interfaces if one ad-hoc is configured.
-	 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
-	 * We would need to operate the HW in ad-hoc mode to allow TSF updates
-	 * for the IBSS, but this breaks with additional AP or STA interfaces
-	 * at the moment. */
-	if (ah->num_adhoc_vifs ||
-	    (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+	/* Don't allow more than one ad-hoc interface */
+	if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
 		ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
 		ret = -ELNRNG;
 		goto end;
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index 6c724fa..6c993af 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -47,6 +47,8 @@ static const struct pci_device_id ath5k_pci_id_table[] = {
 	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
 	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
 	{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+	{ PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
+	{ PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
 	{ PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
 	{ 0 }
 };
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 9fdb528..eabf225 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	tsf_lo = 0;
 	mode = 0;
 
+#if 0
 	/*
 	 * Sanity check for fast flag
 	 * Fast channel change only available
@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
 	 */
 	if (fast && (ah->ah_radio != AR5K_RF2413) &&
 	(ah->ah_radio != AR5K_RF5413))
+#endif
 		fast = false;
 
 	/* Disable sleep clock operation
diff --git a/include/linux/ath5k_platform.h b/include/linux/ath5k_platform.h
new file mode 100644
index 0000000..ec85224
--- /dev/null
+++ b/include/linux/ath5k_platform.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LINUX_ATH5K_PLATFORM_H
+#define _LINUX_ATH5K_PLATFORM_H
+
+#define ATH5K_PLAT_EEP_MAX_WORDS	2048
+
+struct ath5k_platform_data {
+	u16 *eeprom_data;
+	u8 *macaddr;
+};
+
+#endif /* _LINUX_ATH5K_PLATFORM_H */
-- 
2.39.2

