John W. Linville 88b9de1
From 9bbb8168ed3d8b946f9c1901a63a675012de88f2 Mon Sep 17 00:00:00 2001
John W. Linville 88b9de1
From: Felix Fietkau <nbd@openwrt.org>
John W. Linville 88b9de1
Date: Wed, 15 Feb 2012 19:31:20 +0100
John W. Linville 88b9de1
Subject: [PATCH] ath9k_hw: prevent writes to const data on AR9160
John W. Linville 88b9de1
MIME-Version: 1.0
John W. Linville 88b9de1
Content-Type: text/plain; charset=UTF-8
John W. Linville 88b9de1
Content-Transfer-Encoding: 8bit
John W. Linville 88b9de1
John W. Linville 88b9de1
Duplicate the data for iniAddac early on, to avoid having to do redundant
John W. Linville 88b9de1
memcpy calls later. While we're at it, make AR5416 < v2.2 use the same
John W. Linville 88b9de1
codepath. Fixes a reported crash on x86.
John W. Linville 88b9de1
John W. Linville 88b9de1
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
John W. Linville 88b9de1
Reported-by: Magnus Määttä <magnus.maatta@logica.com>
John W. Linville 88b9de1
Cc: stable@vger.kernel.org
John W. Linville 88b9de1
Signed-off-by: John W. Linville <linville@tuxdriver.com>
John W. Linville 88b9de1
---
John W. Linville 88b9de1
 drivers/net/wireless/ath/ath9k/ar5008_phy.c |   25 +------------------------
John W. Linville 88b9de1
 drivers/net/wireless/ath/ath9k/ar9002_hw.c  |   19 +++++++++++++++++++
John W. Linville 88b9de1
 drivers/net/wireless/ath/ath9k/hw.h         |    1 -
John W. Linville 88b9de1
 3 files changed, 20 insertions(+), 25 deletions(-)
John W. Linville 88b9de1
John W. Linville 88b9de1
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
John W. Linville 88b9de1
index f901a17..86a891f 100644
John W. Linville 88b9de1
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
John W. Linville 88b9de1
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
John W. Linville 88b9de1
@@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
John W. Linville 88b9de1
 	ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
John W. Linville 88b9de1
 	ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
John W. Linville 88b9de1
 	ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
John W. Linville 88b9de1
-	ATH_ALLOC_BANK(ah->addac5416_21,
John W. Linville 88b9de1
-		       ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
John W. Linville 88b9de1
 	ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
John W. Linville 88b9de1
 
John W. Linville 88b9de1
 	return 0;
John W. Linville 88b9de1
@@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
John W. Linville 88b9de1
 	ATH_FREE_BANK(ah->analogBank6Data);
John W. Linville 88b9de1
 	ATH_FREE_BANK(ah->analogBank6TPCData);
John W. Linville 88b9de1
 	ATH_FREE_BANK(ah->analogBank7Data);
John W. Linville 88b9de1
-	ATH_FREE_BANK(ah->addac5416_21);
John W. Linville 88b9de1
 	ATH_FREE_BANK(ah->bank6Temp);
John W. Linville 88b9de1
 
John W. Linville 88b9de1
 #undef ATH_FREE_BANK
John W. Linville 88b9de1
@@ -805,27 +802,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
John W. Linville 88b9de1
 	if (ah->eep_ops->set_addac)
John W. Linville 88b9de1
 		ah->eep_ops->set_addac(ah, chan);
John W. Linville 88b9de1
 
John W. Linville 88b9de1
-	if (AR_SREV_5416_22_OR_LATER(ah)) {
John W. Linville 88b9de1
-		REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
John W. Linville 88b9de1
-	} else {
John W. Linville 88b9de1
-		struct ar5416IniArray temp;
John W. Linville 88b9de1
-		u32 addacSize =
John W. Linville 88b9de1
-			sizeof(u32) * ah->iniAddac.ia_rows *
John W. Linville 88b9de1
-			ah->iniAddac.ia_columns;
John W. Linville 88b9de1
-
John W. Linville 88b9de1
-		/* For AR5416 2.0/2.1 */
John W. Linville 88b9de1
-		memcpy(ah->addac5416_21,
John W. Linville 88b9de1
-		       ah->iniAddac.ia_array, addacSize);
John W. Linville 88b9de1
-
John W. Linville 88b9de1
-		/* override CLKDRV value at [row, column] = [31, 1] */
John W. Linville 88b9de1
-		(ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
John W. Linville 88b9de1
-
John W. Linville 88b9de1
-		temp.ia_array = ah->addac5416_21;
John W. Linville 88b9de1
-		temp.ia_columns = ah->iniAddac.ia_columns;
John W. Linville 88b9de1
-		temp.ia_rows = ah->iniAddac.ia_rows;
John W. Linville 88b9de1
-		REG_WRITE_ARRAY(&temp, 1, regWrites);
John W. Linville 88b9de1
-	}
John W. Linville 88b9de1
-
John W. Linville 88b9de1
+	REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
John W. Linville 88b9de1
 	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
John W. Linville 88b9de1
 
John W. Linville 88b9de1
 	ENABLE_REGWRITE_BUFFER(ah);
John W. Linville 88b9de1
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
John W. Linville 88b9de1
index 11f192a..d190411 100644
John W. Linville 88b9de1
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
John W. Linville 88b9de1
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
John W. Linville 88b9de1
@@ -180,6 +180,25 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
John W. Linville 88b9de1
 		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
John W. Linville 88b9de1
 			       ARRAY_SIZE(ar5416Addac), 2);
John W. Linville 88b9de1
 	}
John W. Linville 88b9de1
+
John W. Linville 88b9de1
+	/* iniAddac needs to be modified for these chips */
John W. Linville 88b9de1
+	if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
John W. Linville 88b9de1
+		struct ar5416IniArray *addac = &ah->iniAddac;
John W. Linville 88b9de1
+		u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
John W. Linville 88b9de1
+		u32 *data;
John W. Linville 88b9de1
+
John W. Linville 88b9de1
+		data = kmalloc(size, GFP_KERNEL);
John W. Linville 88b9de1
+		if (!data)
John W. Linville 88b9de1
+			return;
John W. Linville 88b9de1
+
John W. Linville 88b9de1
+		memcpy(data, addac->ia_array, size);
John W. Linville 88b9de1
+		addac->ia_array = data;
John W. Linville 88b9de1
+
John W. Linville 88b9de1
+		if (!AR_SREV_5416_22_OR_LATER(ah)) {
John W. Linville 88b9de1
+			/* override CLKDRV value */
John W. Linville 88b9de1
+			INI_RA(addac, 31,1) = 0;
John W. Linville 88b9de1
+		}
John W. Linville 88b9de1
+	}
John W. Linville 88b9de1
 }
John W. Linville 88b9de1
 
John W. Linville 88b9de1
 /* Support for Japan ch.14 (2484) spread */
John W. Linville 88b9de1
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
John W. Linville 88b9de1
index 6a29004..c8261d4 100644
John W. Linville 88b9de1
--- a/drivers/net/wireless/ath/ath9k/hw.h
John W. Linville 88b9de1
+++ b/drivers/net/wireless/ath/ath9k/hw.h
John W. Linville 88b9de1
@@ -940,7 +940,6 @@ struct ath_hw {
John W. Linville 88b9de1
 	u32 *analogBank6Data;
John W. Linville 88b9de1
 	u32 *analogBank6TPCData;
John W. Linville 88b9de1
 	u32 *analogBank7Data;
John W. Linville 88b9de1
-	u32 *addac5416_21;
John W. Linville 88b9de1
 	u32 *bank6Temp;
John W. Linville 88b9de1
 
John W. Linville 88b9de1
 	u8 txpower_limit;
John W. Linville 88b9de1
-- 
John W. Linville 88b9de1
1.7.4.4
John W. Linville 88b9de1