From 6aaacd861517f89797f2f4a54624a599847262f3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 13 Jan 2013 19:54:58 +0100 Subject: [PATCH] ath9k_hw: fix RF bank initialization ar900*_init_mode_regs needs to be called before RF banks are allocated, otherwise the storage size of RF banks isn't known. This patch fixes a memory overrun that can show up as a crash on unloading the module. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9002_hw.c | 12 ++++++++---- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 2 +- drivers/net/wireless/ath/ath9k/hw.c | 7 ------- drivers/net/wireless/ath/ath9k/hw.h | 2 -- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 54da026..f053d97 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -23,13 +23,13 @@ /* General hardware code for the A5008/AR9001/AR9002 hadware families */ -static void ar9002_hw_init_mode_regs(struct ath_hw *ah) +static int ar9002_hw_init_mode_regs(struct ath_hw *ah) { if (AR_SREV_9271(ah)) { INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271); INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271); INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg); - return; + return 0; } if (ah->config.pcie_clock_req) @@ -104,7 +104,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) data = devm_kzalloc(ah->dev, size, GFP_KERNEL); if (!data) - return; + return -ENOMEM; memcpy(data, addac->ia_array, size); addac->ia_array = data; @@ -120,6 +120,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah) INIT_INI_ARRAY(&ah->iniCckfirJapan2484, ar9287Common_japan_2484_cck_fir_coeff_9287_1_1); } + return 0; } static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) @@ -415,7 +416,10 @@ int ar9002_hw_attach_ops(struct ath_hw *ah) struct ath_hw_ops *ops = ath9k_hw_ops(ah); int ret; - priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; + ret = ar9002_hw_init_mode_regs(ah); + if (ret) + return ret; + priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; ops->config_pci_powersave = ar9002_hw_configpcipowersave; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index de8a56c..6fcd6e9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -704,7 +704,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_ops *ops = ath9k_hw_ops(ah); - priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; + ar9003_hw_init_mode_regs(ah); priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; ops->config_pci_powersave = ar9003_hw_configpcipowersave; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index caf0626..a7448d1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -54,11 +54,6 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah) ath9k_hw_private_ops(ah)->init_cal_settings(ah); } -static void ath9k_hw_init_mode_regs(struct ath_hw *ah) -{ - ath9k_hw_private_ops(ah)->init_mode_regs(ah); -} - static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, struct ath9k_channel *chan) { @@ -670,8 +665,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_MRC_CCK; - ath9k_hw_init_mode_regs(ah); - if (!ah->is_pciexpress) ath9k_hw_disablepcie(ah); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index d32ebf7..195613f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -600,7 +600,6 @@ struct ath_hw_radar_conf { * @init_cal_settings: setup types of calibrations supported * @init_cal: starts actual calibration * - * @init_mode_regs: Initializes mode registers * @init_mode_gain_regs: Initialize TX/RX gain registers * * @rf_set_freq: change frequency @@ -619,7 +618,6 @@ struct ath_hw_private_ops { void (*init_cal_settings)(struct ath_hw *ah); bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); - void (*init_mode_regs)(struct ath_hw *ah); void (*init_mode_gain_regs)(struct ath_hw *ah); void (*setup_calibration)(struct ath_hw *ah, struct ath9k_cal_list *currCal); -- 2.7.4