2012-04-27 02:22:30

by Woody Hung

[permalink] [raw]
Subject: [PATCH] rt2x00 : RT3290 chip support

This support RT3290 chip

Signed-off-by: Woody Hung <[email protected]>
---
drivers/net/wireless/rt2x00/Kconfig | 8 +
drivers/net/wireless/rt2x00/rt2800.h | 120 +++++++++-
drivers/net/wireless/rt2x00/rt2800lib.c | 395 ++++++++++++++++++++++++++++--
drivers/net/wireless/rt2x00/rt2800lib.h | 3 +-
drivers/net/wireless/rt2x00/rt2800pci.c | 12 +
drivers/net/wireless/rt2x00/rt2800pci.h | 3 +
drivers/net/wireless/rt2x00/rt2x00.h | 3 +-
drivers/net/wireless/rt2x00/rt2x00pci.c | 6 +
8 files changed, 520 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 299c387..c7548da 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
rt2800pci driver.
Supported chips: RT5390

+config RT2800PCI_RT3290
+ bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ default y
+ ---help---
+ This adds support for rt3290 wireless chipset family to the
+ rt2800pci driver.
+ Supported chips: RT3290
endif

config RT2500USB
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index d91f4f6..39b1685 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -70,7 +70,7 @@
#define RF5370 0x5370
#define RF5372 0x5372
#define RF5390 0x5390
-
+#define RF3290 0x3290
/*
* Chipset revisions.
*/
@@ -112,6 +112,12 @@
* Registers.
*/

+
+/*
+ * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
+ */
+#define MAC_CSR0_3290 0x0000
+
/*
* E2PROM_CSR: PCI EEPROM control register.
* RELOAD: Write 1 to reload eeprom content.
@@ -305,6 +311,118 @@
#define GPIO_CTRL_CFG_GPIOD_BIT7 FIELD32(0x00008000)

/*
+ * WLAN_CTRL_CFG
+ */
+#define WLAN_FUN_CTRL 0x80
+#define WLAN_EN FIELD32(0x00000001)
+#define WLAN_CLK_EN FIELD32(0x00000002)
+#define WLAN_RSV1 FIELD32(0x00000004)
+#define WLAN_RESET FIELD32(0x00000008)
+#define PCIE_APP0_CLK_REQ FIELD32(0x00000010)
+#define FRC_WL_ANT_SET FIELD32(0x00000020)
+#define INV_TR_SW0 FIELD32(0x00000040)
+#define WLAN_GPIO_IN_BIT0 FIELD32(0x00000100)
+#define WLAN_GPIO_IN_BIT1 FIELD32(0x00000200)
+#define WLAN_GPIO_IN_BIT2 FIELD32(0x00000400)
+#define WLAN_GPIO_IN_BIT3 FIELD32(0x00000800)
+#define WLAN_GPIO_IN_BIT4 FIELD32(0x00001000)
+#define WLAN_GPIO_IN_BIT5 FIELD32(0x00002000)
+#define WLAN_GPIO_IN_BIT6 FIELD32(0x00004000)
+#define WLAN_GPIO_IN_BIT7 FIELD32(0x00008000)
+#define WLAN_GPIO_IN_BIT_ALL FIELD32(0x0000ff00)
+#define WLAN_GPIO_OUT_BIT0 FIELD32(0x00010000)
+#define WLAN_GPIO_OUT_BIT1 FIELD32(0x00020000)
+#define WLAN_GPIO_OUT_BIT2 FIELD32(0x00040000)
+#define WLAN_GPIO_OUT_BIT3 FIELD32(0x00050000)
+#define WLAN_GPIO_OUT_BIT4 FIELD32(0x00100000)
+#define WLAN_GPIO_OUT_BIT5 FIELD32(0x00200000)
+#define WLAN_GPIO_OUT_BIT6 FIELD32(0x00400000)
+#define WLAN_GPIO_OUT_BIT7 FIELD32(0x00800000)
+#define WLAN_GPIO_OUT_BIT_ALL FIELD32(0x00ff0000)
+#define WLAN_GPIO_OUT_OE_BIT0 FIELD32(0x01000000)
+#define WLAN_GPIO_OUT_OE_BIT1 FIELD32(0x02000000)
+#define WLAN_GPIO_OUT_OE_BIT2 FIELD32(0x04000000)
+#define WLAN_GPIO_OUT_OE_BIT3 FIELD32(0x08000000)
+#define WLAN_GPIO_OUT_OE_BIT4 FIELD32(0x10000000)
+#define WLAN_GPIO_OUT_OE_BIT5 FIELD32(0x20000000)
+#define WLAN_GPIO_OUT_OE_BIT6 FIELD32(0x40000000)
+#define WLAN_GPIO_OUT_OE_BIT7 FIELD32(0x80000000)
+#define WLAN_GPIO_OUT_OE_BIT_ALL FIELD32(0xff000000)
+
+/*
+ * CMB_CTRL_CFG
+ */
+#define CMB_CTRL 0x20
+#define AUX_OPT_BIT0 FIELD32(0x00000001)
+#define AUX_OPT_BIT1 FIELD32(0x00000002)
+#define AUX_OPT_BIT2 FIELD32(0x00000004)
+#define AUX_OPT_BIT3 FIELD32(0x00000008)
+#define AUX_OPT_BIT4 FIELD32(0x00000010)
+#define AUX_OPT_BIT5 FIELD32(0x00000020)
+#define AUX_OPT_BIT6 FIELD32(0x00000040)
+#define AUX_OPT_BIT7 FIELD32(0x00000080)
+#define AUX_OPT_BIT8 FIELD32(0x00000100)
+#define AUX_OPT_BIT9 FIELD32(0x00000200)
+#define AUX_OPT_BIT10 FIELD32(0x00000400)
+#define AUX_OPT_BIT11 FIELD32(0x00000800)
+#define AUX_OPT_BIT12 FIELD32(0x00001000)
+#define AUX_OPT_BIT13 FIELD32(0x00002000)
+#define AUX_OPT_BIT14 FIELD32(0x00004000)
+#define AUX_OPT_BIT15 FIELD32(0x00008000)
+#define LDO25_LEVEL FIELD32(0x00030000)
+#define LDO25_LARGEA FIELD32(0x00040000)
+#define LDO25_FRC_ON FIELD32(0x00080000)
+#define CMB_RSV FIELD32(0x00300000)
+#define XTAL_RDY FIELD32(0x00400000)
+#define PLL_LD FIELD32(0x00800000)
+#define LDO_CORE_LEVEL FIELD32(0x0F000000)
+#define LDO_BGSEL FIELD32(0x30000000)
+#define LDO3_EN FIELD32(0x40000000)
+#define LDO0_EN FIELD32(0x80000000)
+
+/*
+ * OSC_CTRL_CFG
+ */
+#define OSC_CTRL 0x38
+#define OSC_REF_CYCLE FIELD32(0x00001fff)
+#define OSC_RSV FIELD32(0x0000e000)
+#define OSC_CAL_CNT FIELD32(0x0fff0000)
+#define OSC_CAL_ACK FIELD32(0x10000000)
+#define OSC_CLK_32K_VLD FIELD32(0x20000000)
+#define OSC_CAL_REQ FIELD32(0x40000000)
+#define OSC_ROSC_EN FIELD32(0x80000000)
+
+/*
+ * PLL_CTRL_CFG
+ */
+#define PLL_CTRL 0x50
+#define PLL_RESERVED_INPUT1 FIELD32(0x000000ff)
+#define PLL_RESERVED_INPUT2 FIELD32(0x0000ff00)
+#define PLL_CONTROL FIELD32(0x00070000)
+#define PLL_LPF_R1 FIELD32(0x00080000)
+#define PLL_LPF_C1_CTRL FIELD32(0x00300000)
+#define PLL_LPF_C2_CTRL FIELD32(0x00c00000)
+#define PLL_CP_CURRENT_CTRL FIELD32(0x03000000)
+#define PLL_PFD_DELAY_CTRL FIELD32(0x0c000000)
+#define PLL_LOCK_CTRL FIELD32(0x70000000)
+#define PLL_VBGBK_EN FIELD32(0x80000000)
+
+/*
+ * COEX_CFG_0
+ */
+#define COEX_CFG0 0x40
+
+/*
+ * COEX_CFG_1
+ */
+#define COEX_CFG1 0x44
+
+/*
+ * COEX_CFG_2
+ */
+#define COEX_CFG2 0x48
+
+/*
* MCU_CMD_CFG
*/
#define MCU_CMD_CFG 0x022c
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 1cd16b4..7753791 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
multiple = true;
} else {
fw_len = 8192;
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ fw_len = 4096;
+
multiple = true;
}

@@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
if (rt2x00_is_pci(rt2x00dev)) {
if (rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
@@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
{
u32 reg;

+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
+ } else
rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
}
@@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,

#define RT5390_POWER_BOUND 0x27
#define RT5390_FREQ_OFFSET_BOUND 0x5f
-
+#define RT3290_POWER_BOUND 0x27
+#define RT3290_FREQ_OFFSET_BOUND 0x5f
static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
}

+
+static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+
+ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+ rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+ rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+ if (info->default_power1 > RT5390_POWER_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+ if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
+ rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
+ RT3290_FREQ_OFFSET_BOUND);
+ else
+ rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+ if (rf->channel <= 14) {
+ rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
+ rfcsr &= ~0xF8;
+ rfcsr |= (0x1f << 3);
+ rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
+ rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+ rfcsr &= ~0xF8;
+ rfcsr |= (0x1f << 3);
+ rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
+ if (rf->channel == 6)
+ rt2800_bbp_write(rt2x00dev, 68, 0x0c);
+ else
+ rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
+ if (rf->channel >= 1 && rf->channel <= 6)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0f);
+ else if (rf->channel >= 7 && rf->channel <= 11)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0e);
+ else if (rf->channel >= 12 && rf->channel <= 14)
+ rt2800_bbp_write(rt2x00dev, 59, 0x0d);
+ }
+
+ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+}
static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf,
struct rf_channel *rf,
@@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
case RF5390:
rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
break;
+ case RF3290:
+ rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
+ break;
default:
rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
}
@@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
case RF5370:
case RF5372:
case RF5390:
+ case RF3290:
rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
@@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3090) ||
rt2x00_rt(rt2x00dev, RT3390) ||
rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
return 0x1c + (2 * rt2x00dev->lna_gain);
else
return 0x2e + rt2x00dev->lna_gain;
@@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);

+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800pci_3290_enable_wlan(rt2x00dev);
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
+ if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
+ rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
+ }
+
+ rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
+ if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
+ rt2x00_set_field32(&reg, LDO0_EN, 1);
+ rt2x00_set_field32(&reg, LDO_BGSEL, 1);
+ rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
+ }
+
+ rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
+ rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+ rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+ rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
+ rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
+ rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
+ rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
+ rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
+ reg &= ~(0xFF000000);
+ reg |= 0x5E000000;
+ rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
+ rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
+ rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
+ rt2x00_set_field32(&reg, PLL_CONTROL, 1);
+ rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
+ }
+
if (rt2x00_rt(rt2x00dev, RT3071) ||
rt2x00_rt(rt2x00dev, RT3090) ||
- rt2x00_rt(rt2x00dev, RT3390)) {
+ rt2x00_rt(rt2x00dev, RT3390) ||
+ rt2x00_rt(rt2x00dev, RT3290)) {
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0,
+ 0x00000404);
+ else
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
return -EACCES;

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_bbp_read(rt2x00dev, 4, &value);
rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
rt2800_bbp_write(rt2x00dev, 4, value);
@@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2800_is_305x_soc(rt2x00dev) ||
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 31, 0x08);

rt2800_bbp_write(rt2x00dev, 65, 0x2c);
rt2800_bbp_write(rt2x00dev, 66, 0x38);

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 68, 0x0b);

if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
rt2800_bbp_write(rt2x00dev, 69, 0x16);
rt2800_bbp_write(rt2x00dev, 73, 0x12);
} else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
rt2800_bbp_write(rt2x00dev, 73, 0x13);
rt2800_bbp_write(rt2x00dev, 75, 0x46);
rt2800_bbp_write(rt2x00dev, 76, 0x28);
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_bbp_write(rt2x00dev, 77, 0x58);
+ else
rt2800_bbp_write(rt2x00dev, 77, 0x59);
} else {
rt2800_bbp_write(rt2x00dev, 69, 0x12);
@@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 81, 0x37);
}

+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_bbp_write(rt2x00dev, 74, 0x0b);
+ rt2800_bbp_write(rt2x00dev, 79, 0x18);
+ rt2800_bbp_write(rt2x00dev, 80, 0x09);
+ rt2800_bbp_write(rt2x00dev, 81, 0x33);
+ }
+
rt2800_bbp_write(rt2x00dev, 82, 0x62);
if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 83, 0x7a);
else
rt2800_bbp_write(rt2x00dev, 83, 0x6a);
@@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
rt2800_bbp_write(rt2x00dev, 84, 0x19);
else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 84, 0x9a);
else
rt2800_bbp_write(rt2x00dev, 84, 0x99);

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 86, 0x38);
else
rt2800_bbp_write(rt2x00dev, 86, 0x00);
@@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 91, 0x04);

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 92, 0x02);
else
rt2800_bbp_write(rt2x00dev, 92, 0x00);
@@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3572) ||
rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290) ||
rt2800_is_305x_soc(rt2x00dev))
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
else
rt2800_bbp_write(rt2x00dev, 103, 0x00);

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 104, 0x92);

if (rt2800_is_305x_soc(rt2x00dev))
@@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
else if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 105, 0x3c);
+ else if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800_bbp_write(rt2x00dev, 105, 0x1c);
else
rt2800_bbp_write(rt2x00dev, 105, 0x05);

- if (rt2x00_rt(rt2x00dev, RT5390))
+ if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 106, 0x03);
else if (rt2x00_rt(rt2x00dev, RT5392))
rt2800_bbp_write(rt2x00dev, 106, 0x12);
@@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 106, 0x35);

if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392))
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290))
rt2800_bbp_write(rt2x00dev, 128, 0x12);

if (rt2x00_rt(rt2x00dev, RT5392)) {
@@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2800_bbp_write(rt2x00dev, 138, value);
}

+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_bbp_write(rt2x00dev, 67, 0x24);
+ rt2800_bbp_write(rt2x00dev, 143, 0x04);
+ rt2800_bbp_write(rt2x00dev, 142, 0x99);
+ rt2800_bbp_write(rt2x00dev, 150, 0x30);
+ rt2800_bbp_write(rt2x00dev, 151, 0x2e);
+ rt2800_bbp_write(rt2x00dev, 152, 0x20);
+ rt2800_bbp_write(rt2x00dev, 153, 0x34);
+ rt2800_bbp_write(rt2x00dev, 154, 0x40);
+ rt2800_bbp_write(rt2x00dev, 155, 0x3b);
+ rt2800_bbp_write(rt2x00dev, 253, 0x04);
+
+ rt2800_bbp_read(rt2x00dev, 47, &value);
+ rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
+ rt2800_bbp_write(rt2x00dev, 47, value);
+
+ rt2800_bbp_read(rt2x00dev, 3, &value);
+ value &= (~0xc0);
+ value |= 0xc0;
+ rt2800_bbp_write(rt2x00dev, 3, value);
+ }
if (rt2x00_rt(rt2x00dev, RT5390) ||
rt2x00_rt(rt2x00dev, RT5392)) {
int ant, div_mode;
@@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
!rt2x00_rt(rt2x00dev, RT3572) &&
!rt2x00_rt(rt2x00dev, RT5390) &&
!rt2x00_rt(rt2x00dev, RT5392) &&
+ !rt2x00_rt(rt2x00dev, RT3290) &&
!rt2800_is_305x_soc(rt2x00dev))
return 0;

@@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
* Init RF calibration.
*/
if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392)) {
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT3290)) {
rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
@@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
+ } else if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+ rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
+ rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+ rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+ rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+ rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+ rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
+ rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
+ rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+ rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+ rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+ rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
+ rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+ rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+ rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
+ rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+ rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+ rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
+ rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+ rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
}

if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
}

+ if (rt2x00_rt(rt2x00dev, RT3290)) {
+ rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
+ rfcsr = ((rfcsr & ~0xc0) | 0xc0);
+ rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
+ }
+
return 0;
}

@@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
+ u16 efuse_ctrl_reg;
+ efuse_ctrl_reg = EFUSE_CTRL;

- rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+ if (rt2x00dev->chip.mac_version == 0x3290)
+ efuse_ctrl_reg = 0x24;

+ rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
}
EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
@@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
{
u32 reg;

+ u16 efuse_ctrl_reg;
+ u16 efuse_data0_reg;
+ u16 efuse_data1_reg;
+ u16 efuse_data2_reg;
+ u16 efuse_data3_reg;
+
+ efuse_ctrl_reg = EFUSE_CTRL;
+ efuse_data0_reg = EFUSE_DATA0;
+ efuse_data1_reg = EFUSE_DATA1;
+ efuse_data2_reg = EFUSE_DATA2;
+ efuse_data3_reg = EFUSE_DATA3;
+
+ if (rt2x00dev->chip.mac_version == 0x3290) {
+ efuse_ctrl_reg = 0x24;
+ efuse_data3_reg = 0x28;
+ efuse_data2_reg = efuse_data3_reg + 4;
+ efuse_data1_reg = efuse_data2_reg + 4;
+ efuse_data0_reg = efuse_data1_reg + 4;
+ }
mutex_lock(&rt2x00dev->csr_mutex);

- rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
- rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
+ rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);

/* Wait until the EEPROM has been loaded */
- rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
-
+ rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
/* Apparently the data is read from end to start */
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
/* The returned value is in CPU order, but eeprom is le */
*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
- rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
+ rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);

mutex_unlock(&rt2x00dev->csr_mutex);
@@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
* RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
* RT53xx: defined in "EEPROM_CHIP_ID" field
*/
+ if (rt2x00dev->chip.mac_version == 0x3290)
+ rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
+ else
rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
- rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
+ rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
+ rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
else
value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
@@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RT3572:
case RT5390:
case RT5392:
+ case RT3290:
break;
default:
ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
@@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
case RF5370:
case RF5372:
case RF5390:
+ case RF3290:
break;
default:
ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
@@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00_rf(rt2x00dev, RF3320) ||
rt2x00_rf(rt2x00dev, RF5370) ||
rt2x00_rf(rt2x00dev, RF5372) ||
- rt2x00_rf(rt2x00dev, RF5390)) {
+ rt2x00_rf(rt2x00dev, RF5390) ||
+ rt2x00_rf(rt2x00dev, RF3290)) {
spec->num_channels = 14;
spec->channels = rf_vals_3x;
} else if (rt2x00_rf(rt2x00dev, RF3052)) {
@@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
case RF5370:
case RF5372:
case RF5390:
+ case RF3290:
__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
break;
}
@@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
}
EXPORT_SYMBOL_GPL(rt2800_get_survey);

+int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
+{
+ u32 wlanfunctrl;
+ u32 glocfg;
+ u32 cmbctrl;
+ u8 index;
+ int i;
+
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
+ rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
+ rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
+ if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
+ return 0;
+
+ rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
+ rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
+ udelay(REGISTER_BUSY_DELAY);
+
+ index = 0;
+ cmbctrl = 0;
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
+ if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
+ (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
+ break;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ if (index >= REGISTER_BUSY_COUNT) {
+ rt2800_register_write(rt2x00dev, 0x58, 0x018);
+ udelay(REGISTER_BUSY_DELAY);
+ rt2800_register_write(rt2x00dev, 0x58, 0x418);
+ udelay(REGISTER_BUSY_DELAY);
+ rt2800_register_write(rt2x00dev, 0x58, 0x618);
+ udelay(REGISTER_BUSY_DELAY);
+ } else {
+ rt2800_register_read(rt2x00dev,
+ WPDMA_GLO_CFG, &glocfg);
+ }
+ rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
+ rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
+
+ rt2800_register_write(rt2x00dev,
+ WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
+ udelay(REGISTER_BUSY_DELAY);
+ rt2800_register_write(rt2x00dev,
+ WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
+ udelay(2);
+ rt2800_register_write(rt2x00dev,
+ INT_SOURCE_CSR, 0x7fffffff);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
+
+int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
+{
+ u32 wlanfunctrl;
+ u32 glocfg;
+ u32 reg;
+ int i;
+
+ /* Change Interrupt bitmask. */
+ rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
+ rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
+
+ /* wait RX DMA idle */
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
+ if ((rt2x00_get_field32(glocfg,
+ WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
+ (glocfg == 0xFFFFFFFF))
+ break;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ if (i >= REGISTER_BUSY_COUNT) {
+ rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+ return 0;
+ }
+
+ rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
+ rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
+ rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
+ rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
+ rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
+ udelay(REGISTER_BUSY_DELAY);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 library");
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 18a0b67..22d7cbb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
-
+int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
+int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
#endif /* RT2800LIB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 931331d..9251f2d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
*/
static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ return FIRMWARE_RT3290;
+
return FIRMWARE_RT2860;
}

@@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
}
+
+ if (rt2x00_rt(rt2x00dev, RT3290))
+ rt2800pci_3290_disable_wlan(rt2x00dev);
}

static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
*/
rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;

+ if (rt2x00_rf(rt2x00dev, RF3290))
+ rt2800pci_3290_enable_wlan(rt2x00dev);
return 0;
}

@@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
{ PCI_DEVICE(0x1814, 0x539a) },
{ PCI_DEVICE(0x1814, 0x539f) },
#endif
+#ifdef CONFIG_RT2800PCI_RT3290
+ { PCI_DEVICE(0x1814, 0x3290) },
+#endif
{ 0, }
};
#endif /* CONFIG_PCI */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index 70e050d..dd043c7 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -49,6 +49,9 @@
#define FIRMWARE_RT2860 "rt2860.bin"
#define FIRMWARE_IMAGE_BASE 0x2000

+
+#define FIRMWARE_RT3290 "rt3290.bin"
+
/*
* DMA descriptor defines.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index ca36ccc..ee770e7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -193,10 +193,11 @@ struct rt2x00_chip {
#define RT3883 0x3883 /* WSOC */
#define RT5390 0x5390 /* 2.4GHz */
#define RT5392 0x5392 /* 2.4GHz */
+#define RT3290 0x3290

u16 rf;
u16 rev;
-
+ u16 mac_version;
enum rt2x00_chip_intf intf;
};

diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 0a4653a..9bbd9a3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
struct ieee80211_hw *hw;
struct rt2x00_dev *rt2x00dev;
int retval;
+ u16 device_id;

retval = pci_enable_device(pci_dev);
if (retval) {
@@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
if (retval)
goto exit_free_device;

+
+ pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
+ if (device_id == 0x3290)
+ rt2x00dev->chip.mac_version = 0x3290;
+
retval = rt2x00lib_probe_dev(rt2x00dev);
if (retval)
goto exit_free_reg;
--
1.7.5.4



2012-04-27 07:40:29

by Helmut Schaa

[permalink] [raw]
Subject: Re: [PATCH] rt2x00 : RT3290 chip support

Hi Woody,

A bit more verbose patch description would be highly appreciated. Also
see some inline
comments about the patch itself. However, I only had a quick look, so
expect a few more
comments from others too ...

Also, please always check your patch by running scripts/checkpatch.pl from your
kernel tree onto it.

Helmut

On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <[email protected]> wrote:
> This support RT3290 chip
>
> Signed-off-by: Woody Hung <[email protected]>
> ---
> ?drivers/net/wireless/rt2x00/Kconfig ? ? | ? ?8 +
> ?drivers/net/wireless/rt2x00/rt2800.h ? ?| ?120 +++++++++-
> ?drivers/net/wireless/rt2x00/rt2800lib.c | ?395 ++++++++++++++++++++++++++++--
> ?drivers/net/wireless/rt2x00/rt2800lib.h | ? ?3 +-
> ?drivers/net/wireless/rt2x00/rt2800pci.c | ? 12 +
> ?drivers/net/wireless/rt2x00/rt2800pci.h | ? ?3 +
> ?drivers/net/wireless/rt2x00/rt2x00.h ? ?| ? ?3 +-
> ?drivers/net/wireless/rt2x00/rt2x00pci.c | ? ?6 +
> ?8 files changed, 520 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> index 299c387..c7548da 100644
> --- a/drivers/net/wireless/rt2x00/Kconfig
> +++ b/drivers/net/wireless/rt2x00/Kconfig
> @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
> ? ? ? ? ?rt2800pci driver.
> ? ? ? ? ?Supported chips: RT5390
>
> +config RT2800PCI_RT3290
> + ? ? ? bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> + ? ? ? depends on EXPERIMENTAL
> + ? ? ? default y
> + ? ? ? ---help---
> + ? ? ? ? This adds support for rt3290 wireless chipset family to the
> + ? ? ? ? rt2800pci driver.
> + ? ? ? ? Supported chips: RT3290
> ?endif
>
> ?config RT2500USB
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index d91f4f6..39b1685 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -70,7 +70,7 @@
> ?#define RF5370 ? ? ? ? ? ? ? ? ? ? ? ? 0x5370
> ?#define RF5372 ? ? ? ? ? ? ? ? ? ? ? ? 0x5372
> ?#define RF5390 ? ? ? ? ? ? ? ? ? ? ? ? 0x5390
> -
> +#define RF3290 ? ? ? ? ? ? ? ? ? ? ? ? 0x3290

There's no need to remove the emty line here.

> ?/*
> ?* Chipset revisions.
> ?*/
> @@ -112,6 +112,12 @@
> ?* Registers.
> ?*/
>
> +
> +/*
> + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> + */
> +#define MAC_CSR0_3290 ? ? ? ? ? ? ? ? ? ? ? ? ?0x0000
> +

This should be moved to the other MAC register definitions.
Is this register only valid on 3290 chipsets?

> ?/*
> ?* E2PROM_CSR: PCI EEPROM control register.
> ?* RELOAD: Write 1 to reload eeprom content.
> @@ -305,6 +311,118 @@
> ?#define GPIO_CTRL_CFG_GPIOD_BIT7 ? ? ? FIELD32(0x00008000)
>
> ?/*
> + * WLAN_CTRL_CFG
> + */
> +#define WLAN_FUN_CTRL ? ? ? ? ? ? ? ? ?0x80
> +#define WLAN_EN ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000001)
> +#define WLAN_CLK_EN ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000002)
> +#define WLAN_RSV1 ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000004)
> +#define WLAN_RESET ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000008)
> +#define PCIE_APP0_CLK_REQ ? ? ? ? ? ? ?FIELD32(0x00000010)
> +#define FRC_WL_ANT_SET ? ? ? ? ? ? ? ? FIELD32(0x00000020)
> +#define INV_TR_SW0 ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000040)
> +#define WLAN_GPIO_IN_BIT0 ? ? ? ? ? ? ?FIELD32(0x00000100)
> +#define WLAN_GPIO_IN_BIT1 ? ? ? ? ? ? ?FIELD32(0x00000200)
> +#define WLAN_GPIO_IN_BIT2 ? ? ? ? ? ? ?FIELD32(0x00000400)
> +#define WLAN_GPIO_IN_BIT3 ? ? ? ? ? ? ?FIELD32(0x00000800)
> +#define WLAN_GPIO_IN_BIT4 ? ? ? ? ? ? ?FIELD32(0x00001000)
> +#define WLAN_GPIO_IN_BIT5 ? ? ? ? ? ? ?FIELD32(0x00002000)
> +#define WLAN_GPIO_IN_BIT6 ? ? ? ? ? ? ?FIELD32(0x00004000)
> +#define WLAN_GPIO_IN_BIT7 ? ? ? ? ? ? ?FIELD32(0x00008000)
> +#define WLAN_GPIO_IN_BIT_ALL ? ? ? ? ? FIELD32(0x0000ff00)
> +#define WLAN_GPIO_OUT_BIT0 ? ? ? ? ? ? FIELD32(0x00010000)
> +#define WLAN_GPIO_OUT_BIT1 ? ? ? ? ? ? FIELD32(0x00020000)
> +#define WLAN_GPIO_OUT_BIT2 ? ? ? ? ? ? FIELD32(0x00040000)
> +#define WLAN_GPIO_OUT_BIT3 ? ? ? ? ? ? FIELD32(0x00050000)
> +#define WLAN_GPIO_OUT_BIT4 ? ? ? ? ? ? FIELD32(0x00100000)
> +#define WLAN_GPIO_OUT_BIT5 ? ? ? ? ? ? FIELD32(0x00200000)
> +#define WLAN_GPIO_OUT_BIT6 ? ? ? ? ? ? FIELD32(0x00400000)
> +#define WLAN_GPIO_OUT_BIT7 ? ? ? ? ? ? FIELD32(0x00800000)
> +#define WLAN_GPIO_OUT_BIT_ALL ? ? ? ? ?FIELD32(0x00ff0000)
> +#define WLAN_GPIO_OUT_OE_BIT0 ? ? ? ? ?FIELD32(0x01000000)
> +#define WLAN_GPIO_OUT_OE_BIT1 ? ? ? ? ?FIELD32(0x02000000)
> +#define WLAN_GPIO_OUT_OE_BIT2 ? ? ? ? ?FIELD32(0x04000000)
> +#define WLAN_GPIO_OUT_OE_BIT3 ? ? ? ? ?FIELD32(0x08000000)
> +#define WLAN_GPIO_OUT_OE_BIT4 ? ? ? ? ?FIELD32(0x10000000)
> +#define WLAN_GPIO_OUT_OE_BIT5 ? ? ? ? ?FIELD32(0x20000000)
> +#define WLAN_GPIO_OUT_OE_BIT6 ? ? ? ? ?FIELD32(0x40000000)
> +#define WLAN_GPIO_OUT_OE_BIT7 ? ? ? ? ?FIELD32(0x80000000)
> +#define WLAN_GPIO_OUT_OE_BIT_ALL ? ? ? FIELD32(0xff000000)
> +
> +/*
> + * CMB_CTRL_CFG
> + */
> +#define CMB_CTRL ? ? ? ? ? ? ? 0x20
> +#define AUX_OPT_BIT0 ? ? ? ? ? FIELD32(0x00000001)
> +#define AUX_OPT_BIT1 ? ? ? ? ? FIELD32(0x00000002)
> +#define AUX_OPT_BIT2 ? ? ? ? ? FIELD32(0x00000004)
> +#define AUX_OPT_BIT3 ? ? ? ? ? FIELD32(0x00000008)
> +#define AUX_OPT_BIT4 ? ? ? ? ? FIELD32(0x00000010)
> +#define AUX_OPT_BIT5 ? ? ? ? ? FIELD32(0x00000020)
> +#define AUX_OPT_BIT6 ? ? ? ? ? FIELD32(0x00000040)
> +#define AUX_OPT_BIT7 ? ? ? ? ? FIELD32(0x00000080)
> +#define AUX_OPT_BIT8 ? ? ? ? ? FIELD32(0x00000100)
> +#define AUX_OPT_BIT9 ? ? ? ? ? FIELD32(0x00000200)
> +#define AUX_OPT_BIT10 ? ? ? ? ?FIELD32(0x00000400)
> +#define AUX_OPT_BIT11 ? ? ? ? ?FIELD32(0x00000800)
> +#define AUX_OPT_BIT12 ? ? ? ? ?FIELD32(0x00001000)
> +#define AUX_OPT_BIT13 ? ? ? ? ?FIELD32(0x00002000)
> +#define AUX_OPT_BIT14 ? ? ? ? ?FIELD32(0x00004000)
> +#define AUX_OPT_BIT15 ? ? ? ? ?FIELD32(0x00008000)
> +#define LDO25_LEVEL ? ? ? ? ? ?FIELD32(0x00030000)
> +#define LDO25_LARGEA ? ? ? ? ? FIELD32(0x00040000)
> +#define LDO25_FRC_ON ? ? ? ? ? FIELD32(0x00080000)
> +#define CMB_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00300000)
> +#define XTAL_RDY ? ? ? ? ? ? ? FIELD32(0x00400000)
> +#define PLL_LD ? ? ? ? ? ? ? ? FIELD32(0x00800000)
> +#define LDO_CORE_LEVEL ? ? ? ? FIELD32(0x0F000000)
> +#define LDO_BGSEL ? ? ? ? ? ? ?FIELD32(0x30000000)
> +#define LDO3_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x40000000)
> +#define LDO0_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x80000000)
> +
> +/*
> + * OSC_CTRL_CFG
> + */
> +#define OSC_CTRL ? ? ? ? ? ? ? 0x38
> +#define OSC_REF_CYCLE ? ? ? ? ?FIELD32(0x00001fff)
> +#define OSC_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x0000e000)
> +#define OSC_CAL_CNT ? ? ? ? ? ?FIELD32(0x0fff0000)
> +#define OSC_CAL_ACK ? ? ? ? ? ?FIELD32(0x10000000)
> +#define OSC_CLK_32K_VLD ? ? ? ? ? ? ? ?FIELD32(0x20000000)
> +#define OSC_CAL_REQ ? ? ? ? ? ?FIELD32(0x40000000)
> +#define OSC_ROSC_EN ? ? ? ? ? ?FIELD32(0x80000000)
> +
> +/*
> + * PLL_CTRL_CFG
> + */
> +#define PLL_CTRL ? ? ? ? ? ? ? 0x50
> +#define PLL_RESERVED_INPUT1 ? ?FIELD32(0x000000ff)
> +#define PLL_RESERVED_INPUT2 ? ?FIELD32(0x0000ff00)
> +#define PLL_CONTROL ? ? ? ? ? ?FIELD32(0x00070000)
> +#define PLL_LPF_R1 ? ? ? ? ? ? FIELD32(0x00080000)
> +#define PLL_LPF_C1_CTRL ? ? ? ?FIELD32(0x00300000)
> +#define PLL_LPF_C2_CTRL ? ? ? ?FIELD32(0x00c00000)
> +#define PLL_CP_CURRENT_CTRL ? ?FIELD32(0x03000000)
> +#define PLL_PFD_DELAY_CTRL ? ? FIELD32(0x0c000000)
> +#define PLL_LOCK_CTRL ? ? ? ? ?FIELD32(0x70000000)
> +#define PLL_VBGBK_EN ? ? ? ? ? FIELD32(0x80000000)
> +
> +/*
> + * COEX_CFG_0
> + */
> +#define COEX_CFG0 ? ? ? ? ? ? ? ? ? ? ?0x40
> +
> +/*
> + * COEX_CFG_1
> + */
> +#define COEX_CFG1 ? ? ? ? ? ? ? ? ? ? ?0x44
> +
> +/*
> + * COEX_CFG_2
> + */
> +#define COEX_CFG2 ? ? ? ? ? ? ? ? ? ? ?0x48
> +
> +/*
> ?* MCU_CMD_CFG
> ?*/
> ?#define MCU_CMD_CFG ? ? ? ? ? ? ? ? ? ?0x022c
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 1cd16b4..7753791 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ?multiple = true;
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?fw_len = 8192;
> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? fw_len = 4096;
> +
> ? ? ? ? ? ? ? ?multiple = true;
> ? ? ? ?}
>
> @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?if (rt2x00_is_pci(rt2x00dev)) {
> ? ? ? ? ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
> @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
> ?{
> ? ? ? ?u32 reg;
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> + ? ? ? ? ? ? ? return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> + ? ? ? } else
> ? ? ? ?rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);

This looks awkward, either you have to use correct indention here
or drop the else completely.

> ? ? ? ?return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
> ?}
> @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
>
> ?#define RT5390_POWER_BOUND ? ? 0x27
> ?#define RT5390_FREQ_OFFSET_BOUND ? ? ? 0x5f
> -

This empty line can stay.

> +#define RT3290_POWER_BOUND ? ? 0x27
> +#define RT3290_FREQ_OFFSET_BOUND ? ? ? 0x5f

Might be worth to add another empty line here.

> ?static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ieee80211_conf *conf,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct rf_channel *rf,
> @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> ?}
>
> +
> +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct channel_info *info)
> +{
> + ? ? ? u8 rfcsr;
> +
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> + ? ? ? if (info->default_power1 > RT5390_POWER_BOUND)
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> + ? ? ? else
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> + ? ? ? if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RT3290_FREQ_OFFSET_BOUND);
> + ? ? ? else
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> +
> + ? ? ? if (rf->channel <= 14) {
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
> +
> + ? ? ? ? ? ? ? if (rf->channel == 6)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> +
> + ? ? ? ? ? ? ? if (rf->channel >= 1 && rf->channel <= 6)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> + ? ? ? ? ? ? ? else if (rf->channel >= 7 && rf->channel <= 11)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> + ? ? ? ? ? ? ? else if (rf->channel >= 12 && rf->channel <= 14)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> + ? ? ? }
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> +}

This function could really use a few comments.

> ?static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,
> @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?case RF5390:
> ? ? ? ? ? ? ? ?rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
> ? ? ? ? ? ? ? ?break;
> + ? ? ? case RF3290:
> + ? ? ? ? ? ? ? rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> + ? ? ? ? ? ? ? break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
> ? ? ? ?}
> @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3390) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ? ? ? ? ?return 0x1c + (2 * rt2x00dev->lna_gain);
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?return 0x2e + rt2x00dev->lna_gain;
> @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
> ? ? ? ?rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);

Calling a rt2800pci function from within rt2800lib doesn't look correct. Maybe
use a new callback function for that?

> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> + ? ? ? ? ? ? ? if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> + ? ? ? ? ? ? ? if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO0_EN, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> + ? ? ? ? ? ? ? reg &= ~(0xFF000000);
> + ? ? ? ? ? ? ? reg |= 0x5E000000;
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> + ? ? ? }
> +
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3071) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390)) {
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {

Indention looks strange here.

> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x00000404);
> + ? ? ? ? ? ? ? else
> ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);

Indention again.

> ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
> ? ? ? ? ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?return -EACCES;
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ? ?||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_read(rt2x00dev, 4, &value);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 4, value);
> @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 31, 0x08);
>
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 65, 0x2c);
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 66, 0x38);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 68, 0x0b);
>
> ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x16);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x12);
> ? ? ? ?} else if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x13);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 75, 0x46);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 76, 0x28);
> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 77, 0x58);
> + ? ? ? ? ? ? ? else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 77, 0x59);

Indention.

> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);
> @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 81, 0x37);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 79, 0x18);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 80, 0x09);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 81, 0x33);
> + ? ? ? }
> +
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 82, 0x62);
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x7a);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x19);
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x9a);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x99);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x38);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x00);
> @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 91, 0x04);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x02);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x00);
> @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290) ||
> ? ? ? ? ? ?rt2800_is_305x_soc(rt2x00dev))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0xc0);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0x00);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 104, 0x92);
>
> ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev))
> @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> + ? ? ? else if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 105, 0x1c);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x05);
>
> - ? ? ? if (rt2x00_rt(rt2x00dev, RT5390))
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT5390) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x03);
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5392))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x12);
> @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x35);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 128, 0x12);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5392)) {
> @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 138, value);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 67, 0x24);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 143, 0x04);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 142, 0x99);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 150, 0x30);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 152, 0x20);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 153, 0x34);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 154, 0x40);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 253, 0x04);
> +
> + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 47, &value);
> + ? ? ? ? ? ? ? rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 47, value);
> +
> + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 3, &value);
> + ? ? ? ? ? ? ? value &= (~0xc0);
> + ? ? ? ? ? ? ? value |= 0xc0;
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 3, value);
> + ? ? ? }
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> ? ? ? ? ? ? ? ?int ant, div_mode;
> @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT3572) &&
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5390) &&
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5392) &&
> + ? ? ? ? ? !rt2x00_rt(rt2x00dev, RT3290) &&
> ? ? ? ? ? ?!rt2800_is_305x_soc(rt2x00dev))
> ? ? ? ? ? ? ? ?return 0;
>
> @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? * Init RF calibration.
> ? ? ? ? */
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> + ? ? ? } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
> ? ? ? ?}
>
> ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> + ? ? ? }
> +
> ? ? ? ?return 0;
> ?}
>
> @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
> ?int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
> ?{
> ? ? ? ?u32 reg;
> + ? ? ? u16 efuse_ctrl_reg;
> + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
>
> - ? ? ? rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;

This shouldn't be hardcoded. Please add a define to rt2800.h.

>
> + ? ? ? rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
> ? ? ? ?return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
> ?}
> ?EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
> @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
> ?{
> ? ? ? ?u32 reg;
>
> + ? ? ? u16 efuse_ctrl_reg;
> + ? ? ? u16 efuse_data0_reg;
> + ? ? ? u16 efuse_data1_reg;
> + ? ? ? u16 efuse_data2_reg;
> + ? ? ? u16 efuse_data3_reg;
> +
> + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
> + ? ? ? efuse_data0_reg = EFUSE_DATA0;
> + ? ? ? efuse_data1_reg = EFUSE_DATA1;
> + ? ? ? efuse_data2_reg = EFUSE_DATA2;
> + ? ? ? efuse_data3_reg = EFUSE_DATA3;
> +
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290) {
> + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;
> + ? ? ? ? ? ? ? efuse_data3_reg = 0x28;
> + ? ? ? ? ? ? ? efuse_data2_reg = efuse_data3_reg + 4;
> + ? ? ? ? ? ? ? efuse_data1_reg = efuse_data2_reg + 4;
> + ? ? ? ? ? ? ? efuse_data0_reg = efuse_data1_reg + 4;
> + ? ? ? }

Same here, the register offsets would make sense as defines.

> ? ? ? ?mutex_lock(&rt2x00dev->csr_mutex);
>
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> - ? ? ? rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> + ? ? ? rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
>
> ? ? ? ?/* Wait until the EEPROM has been loaded */
> - ? ? ? rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> -
> + ? ? ? rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
> ? ? ? ?/* Apparently the data is read from end to start */
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
> ? ? ? ?/* The returned value is in CPU order, but eeprom is le */
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
>
> ? ? ? ?mutex_unlock(&rt2x00dev->csr_mutex);
> @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
> ? ? ? ? * RT53xx: defined in "EEPROM_CHIP_ID" field
> ? ? ? ? */
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> + ? ? ? else
> ? ? ? ?rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);

Indention.

> ? ? ? ?if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> - ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
> ? ? ? ? ? ? ? ?rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RT3572:
> ? ? ? ?case RT5390:
> ? ? ? ?case RT5392:
> + ? ? ? case RT3290:
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF3320) ||
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5370) ||
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5372) ||
> - ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390)) {
> + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390) ||
> + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF3290)) {
> ? ? ? ? ? ? ? ?spec->num_channels = 14;
> ? ? ? ? ? ? ? ?spec->channels = rf_vals_3x;
> ? ? ? ?} else if (rt2x00_rf(rt2x00dev, RF3052)) {
> @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> ?}
> ?EXPORT_SYMBOL_GPL(rt2800_get_survey);
>
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)

rt2800pci functions should live in rt2800pci.c, not in rt2800lib.c.

> +{
> + ? ? ? u32 wlanfunctrl;
> + ? ? ? u32 glocfg;
> + ? ? ? u32 cmbctrl;
> + ? ? ? u8 index;
> + ? ? ? int i;
> +
> + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> + ? ? ? if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> + ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> +
> + ? ? ? index = 0;
> + ? ? ? cmbctrl = 0;
> + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> + ? ? ? ? ? ? ? if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> + ? ? ? ? ? ? ? ? ? ? ? (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? }
> +
> + ? ? ? if (index >= REGISTER_BUSY_COUNT) {
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x018);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x418);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x618);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? } else {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev,
> + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG, &glocfg);
> + ? ? ? }
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> +
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> + ? ? ? udelay(2);
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? INT_SOURCE_CSR, 0x7fffffff);
> + ? ? ? return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> +
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> + ? ? ? u32 wlanfunctrl;
> + ? ? ? u32 glocfg;
> + ? ? ? u32 reg;
> + ? ? ? int i;
> +
> + ? ? ? /* Change Interrupt bitmask. */
> + ? ? ? rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> + ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> + ? ? ? rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> + ? ? ? rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> +
> + ? ? ? /* wait RX DMA idle */
> + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> + ? ? ? ? ? ? ? if ((rt2x00_get_field32(glocfg,
> + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> + ? ? ? ? ? ? ? ? ? ? ? (glocfg == 0xFFFFFFFF))
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? }
> +
> + ? ? ? if (i >= REGISTER_BUSY_COUNT) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
> ?MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
> ?MODULE_VERSION(DRV_VERSION);
> ?MODULE_DESCRIPTION("Ralink RT2800 library");
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> index 18a0b67..22d7cbb 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> ?int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> ? ? ? ? ? ? ? ? ? ? ?struct survey_info *survey);
> ?void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> -
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
> ?#endif /* RT2800LIB_H */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 931331d..9251f2d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
> ?*/
> ?static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
> ?{
> +
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? return FIRMWARE_RT3290;
> +
> ? ? ? ?return FIRMWARE_RT2860;
> ?}
>
> @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
> ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
> ? ? ? ?}
> +
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? rt2800pci_3290_disable_wlan(rt2x00dev);
> ?}
>
> ?static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? */
> ? ? ? ?rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
>
> + ? ? ? if (rt2x00_rf(rt2x00dev, RF3290))
> + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);
> ? ? ? ?return 0;
> ?}
>
> @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
> ? ? ? ?{ PCI_DEVICE(0x1814, 0x539a) },
> ? ? ? ?{ PCI_DEVICE(0x1814, 0x539f) },
> ?#endif
> +#ifdef CONFIG_RT2800PCI_RT3290
> + ? ? ? { PCI_DEVICE(0x1814, 0x3290) },
> +#endif
> ? ? ? ?{ 0, }
> ?};
> ?#endif /* CONFIG_PCI */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> index 70e050d..dd043c7 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> @@ -49,6 +49,9 @@
> ?#define FIRMWARE_RT2860 ? ? ? ? ? ? ? ? ? ? ? ?"rt2860.bin"
> ?#define FIRMWARE_IMAGE_BASE ? ? ? ? ? ?0x2000
>
> +
> +#define FIRMWARE_RT3290 ? ? ? ? ? ? ? ? ? ? ? ?"rt3290.bin"
> +
> ?/*
> ?* DMA descriptor defines.
> ?*/
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index ca36ccc..ee770e7 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -193,10 +193,11 @@ struct rt2x00_chip {
> ?#define RT3883 ? ? ? ? 0x3883 ?/* WSOC */
> ?#define RT5390 ? ? ? ? 0x5390 ?/* 2.4GHz */
> ?#define RT5392 ? ? ? ? 0x5392 ?/* 2.4GHz */
> +#define RT3290 ? ? ? ? 0x3290
>
> ? ? ? ?u16 rf;
> ? ? ? ?u16 rev;
> -
> + ? ? ? u16 mac_version;
> ? ? ? ?enum rt2x00_chip_intf intf;
> ?};
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index 0a4653a..9bbd9a3 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> ? ? ? ?struct ieee80211_hw *hw;
> ? ? ? ?struct rt2x00_dev *rt2x00dev;
> ? ? ? ?int retval;
> + ? ? ? u16 device_id;
>
> ? ? ? ?retval = pci_enable_device(pci_dev);
> ? ? ? ?if (retval) {
> @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> ? ? ? ?if (retval)
> ? ? ? ? ? ? ? ?goto exit_free_device;
>
> +
> + ? ? ? pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> + ? ? ? if (device_id == 0x3290)
> + ? ? ? ? ? ? ? rt2x00dev->chip.mac_version = 0x3290;
> +
> ? ? ? ?retval = rt2x00lib_probe_dev(rt2x00dev);
> ? ? ? ?if (retval)
> ? ? ? ? ? ? ? ?goto exit_free_reg;
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html

2012-05-11 12:05:09

by Gertjan van Wingerde

[permalink] [raw]
Subject: Re: [PATCH] rt2x00 : RT3290 chip support

Hi Woody,

On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <[email protected]> wrote:
> This support RT3290 chip
>
> Signed-off-by: Woody Hung <[email protected]>

I'm sorry for the late review. I couldn't find time sooner to look at this.

See further down for a number of comments to your patch.

> ---
> ?drivers/net/wireless/rt2x00/Kconfig ? ? | ? ?8 +
> ?drivers/net/wireless/rt2x00/rt2800.h ? ?| ?120 +++++++++-
> ?drivers/net/wireless/rt2x00/rt2800lib.c | ?395 ++++++++++++++++++++++++++++--
> ?drivers/net/wireless/rt2x00/rt2800lib.h | ? ?3 +-
> ?drivers/net/wireless/rt2x00/rt2800pci.c | ? 12 +
> ?drivers/net/wireless/rt2x00/rt2800pci.h | ? ?3 +
> ?drivers/net/wireless/rt2x00/rt2x00.h ? ?| ? ?3 +-
> ?drivers/net/wireless/rt2x00/rt2x00pci.c | ? ?6 +
> ?8 files changed, 520 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> index 299c387..c7548da 100644
> --- a/drivers/net/wireless/rt2x00/Kconfig
> +++ b/drivers/net/wireless/rt2x00/Kconfig
> @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
> ? ? ? ? ?rt2800pci driver.
> ? ? ? ? ?Supported chips: RT5390
>
> +config RT2800PCI_RT3290
> + ? ? ? bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> + ? ? ? depends on EXPERIMENTAL
> + ? ? ? default y
> + ? ? ? ---help---
> + ? ? ? ? This adds support for rt3290 wireless chipset family to the
> + ? ? ? ? rt2800pci driver.
> + ? ? ? ? Supported chips: RT3290
> ?endif
>
> ?config RT2500USB
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index d91f4f6..39b1685 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -70,7 +70,7 @@
> ?#define RF5370 ? ? ? ? ? ? ? ? ? ? ? ? 0x5370
> ?#define RF5372 ? ? ? ? ? ? ? ? ? ? ? ? 0x5372
> ?#define RF5390 ? ? ? ? ? ? ? ? ? ? ? ? 0x5390
> -
> +#define RF3290 ? ? ? ? ? ? ? ? ? ? ? ? 0x3290
> ?/*
> ?* Chipset revisions.
> ?*/

Please add the define in the right numerical order. It just looks
nicer when things are in numerical order.

> @@ -112,6 +112,12 @@
> ?* Registers.
> ?*/
>
> +
> +/*
> + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> + */
> +#define MAC_CSR0_3290 ? ? ? ? ? ? ? ? ? ? ? ? ?0x0000
> +
> ?/*
> ?* E2PROM_CSR: PCI EEPROM control register.
> ?* RELOAD: Write 1 to reload eeprom content.
> @@ -305,6 +311,118 @@
> ?#define GPIO_CTRL_CFG_GPIOD_BIT7 ? ? ? FIELD32(0x00008000)
>
> ?/*
> + * WLAN_CTRL_CFG
> + */
> +#define WLAN_FUN_CTRL ? ? ? ? ? ? ? ? ?0x80
> +#define WLAN_EN ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000001)
> +#define WLAN_CLK_EN ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000002)
> +#define WLAN_RSV1 ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000004)
> +#define WLAN_RESET ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000008)
> +#define PCIE_APP0_CLK_REQ ? ? ? ? ? ? ?FIELD32(0x00000010)
> +#define FRC_WL_ANT_SET ? ? ? ? ? ? ? ? FIELD32(0x00000020)
> +#define INV_TR_SW0 ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000040)
> +#define WLAN_GPIO_IN_BIT0 ? ? ? ? ? ? ?FIELD32(0x00000100)
> +#define WLAN_GPIO_IN_BIT1 ? ? ? ? ? ? ?FIELD32(0x00000200)
> +#define WLAN_GPIO_IN_BIT2 ? ? ? ? ? ? ?FIELD32(0x00000400)
> +#define WLAN_GPIO_IN_BIT3 ? ? ? ? ? ? ?FIELD32(0x00000800)
> +#define WLAN_GPIO_IN_BIT4 ? ? ? ? ? ? ?FIELD32(0x00001000)
> +#define WLAN_GPIO_IN_BIT5 ? ? ? ? ? ? ?FIELD32(0x00002000)
> +#define WLAN_GPIO_IN_BIT6 ? ? ? ? ? ? ?FIELD32(0x00004000)
> +#define WLAN_GPIO_IN_BIT7 ? ? ? ? ? ? ?FIELD32(0x00008000)
> +#define WLAN_GPIO_IN_BIT_ALL ? ? ? ? ? FIELD32(0x0000ff00)
> +#define WLAN_GPIO_OUT_BIT0 ? ? ? ? ? ? FIELD32(0x00010000)
> +#define WLAN_GPIO_OUT_BIT1 ? ? ? ? ? ? FIELD32(0x00020000)
> +#define WLAN_GPIO_OUT_BIT2 ? ? ? ? ? ? FIELD32(0x00040000)
> +#define WLAN_GPIO_OUT_BIT3 ? ? ? ? ? ? FIELD32(0x00050000)
> +#define WLAN_GPIO_OUT_BIT4 ? ? ? ? ? ? FIELD32(0x00100000)
> +#define WLAN_GPIO_OUT_BIT5 ? ? ? ? ? ? FIELD32(0x00200000)
> +#define WLAN_GPIO_OUT_BIT6 ? ? ? ? ? ? FIELD32(0x00400000)
> +#define WLAN_GPIO_OUT_BIT7 ? ? ? ? ? ? FIELD32(0x00800000)
> +#define WLAN_GPIO_OUT_BIT_ALL ? ? ? ? ?FIELD32(0x00ff0000)
> +#define WLAN_GPIO_OUT_OE_BIT0 ? ? ? ? ?FIELD32(0x01000000)
> +#define WLAN_GPIO_OUT_OE_BIT1 ? ? ? ? ?FIELD32(0x02000000)
> +#define WLAN_GPIO_OUT_OE_BIT2 ? ? ? ? ?FIELD32(0x04000000)
> +#define WLAN_GPIO_OUT_OE_BIT3 ? ? ? ? ?FIELD32(0x08000000)
> +#define WLAN_GPIO_OUT_OE_BIT4 ? ? ? ? ?FIELD32(0x10000000)
> +#define WLAN_GPIO_OUT_OE_BIT5 ? ? ? ? ?FIELD32(0x20000000)
> +#define WLAN_GPIO_OUT_OE_BIT6 ? ? ? ? ?FIELD32(0x40000000)
> +#define WLAN_GPIO_OUT_OE_BIT7 ? ? ? ? ?FIELD32(0x80000000)
> +#define WLAN_GPIO_OUT_OE_BIT_ALL ? ? ? FIELD32(0xff000000)
> +
> +/*
> + * CMB_CTRL_CFG
> + */
> +#define CMB_CTRL ? ? ? ? ? ? ? 0x20
> +#define AUX_OPT_BIT0 ? ? ? ? ? FIELD32(0x00000001)
> +#define AUX_OPT_BIT1 ? ? ? ? ? FIELD32(0x00000002)
> +#define AUX_OPT_BIT2 ? ? ? ? ? FIELD32(0x00000004)
> +#define AUX_OPT_BIT3 ? ? ? ? ? FIELD32(0x00000008)
> +#define AUX_OPT_BIT4 ? ? ? ? ? FIELD32(0x00000010)
> +#define AUX_OPT_BIT5 ? ? ? ? ? FIELD32(0x00000020)
> +#define AUX_OPT_BIT6 ? ? ? ? ? FIELD32(0x00000040)
> +#define AUX_OPT_BIT7 ? ? ? ? ? FIELD32(0x00000080)
> +#define AUX_OPT_BIT8 ? ? ? ? ? FIELD32(0x00000100)
> +#define AUX_OPT_BIT9 ? ? ? ? ? FIELD32(0x00000200)
> +#define AUX_OPT_BIT10 ? ? ? ? ?FIELD32(0x00000400)
> +#define AUX_OPT_BIT11 ? ? ? ? ?FIELD32(0x00000800)
> +#define AUX_OPT_BIT12 ? ? ? ? ?FIELD32(0x00001000)
> +#define AUX_OPT_BIT13 ? ? ? ? ?FIELD32(0x00002000)
> +#define AUX_OPT_BIT14 ? ? ? ? ?FIELD32(0x00004000)
> +#define AUX_OPT_BIT15 ? ? ? ? ?FIELD32(0x00008000)
> +#define LDO25_LEVEL ? ? ? ? ? ?FIELD32(0x00030000)
> +#define LDO25_LARGEA ? ? ? ? ? FIELD32(0x00040000)
> +#define LDO25_FRC_ON ? ? ? ? ? FIELD32(0x00080000)
> +#define CMB_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00300000)
> +#define XTAL_RDY ? ? ? ? ? ? ? FIELD32(0x00400000)
> +#define PLL_LD ? ? ? ? ? ? ? ? FIELD32(0x00800000)
> +#define LDO_CORE_LEVEL ? ? ? ? FIELD32(0x0F000000)
> +#define LDO_BGSEL ? ? ? ? ? ? ?FIELD32(0x30000000)
> +#define LDO3_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x40000000)
> +#define LDO0_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x80000000)
> +
> +/*
> + * OSC_CTRL_CFG
> + */
> +#define OSC_CTRL ? ? ? ? ? ? ? 0x38
> +#define OSC_REF_CYCLE ? ? ? ? ?FIELD32(0x00001fff)
> +#define OSC_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x0000e000)
> +#define OSC_CAL_CNT ? ? ? ? ? ?FIELD32(0x0fff0000)
> +#define OSC_CAL_ACK ? ? ? ? ? ?FIELD32(0x10000000)
> +#define OSC_CLK_32K_VLD ? ? ? ? ? ? ? ?FIELD32(0x20000000)
> +#define OSC_CAL_REQ ? ? ? ? ? ?FIELD32(0x40000000)
> +#define OSC_ROSC_EN ? ? ? ? ? ?FIELD32(0x80000000)
> +
> +/*
> + * PLL_CTRL_CFG
> + */
> +#define PLL_CTRL ? ? ? ? ? ? ? 0x50
> +#define PLL_RESERVED_INPUT1 ? ?FIELD32(0x000000ff)
> +#define PLL_RESERVED_INPUT2 ? ?FIELD32(0x0000ff00)
> +#define PLL_CONTROL ? ? ? ? ? ?FIELD32(0x00070000)
> +#define PLL_LPF_R1 ? ? ? ? ? ? FIELD32(0x00080000)
> +#define PLL_LPF_C1_CTRL ? ? ? ?FIELD32(0x00300000)
> +#define PLL_LPF_C2_CTRL ? ? ? ?FIELD32(0x00c00000)
> +#define PLL_CP_CURRENT_CTRL ? ?FIELD32(0x03000000)
> +#define PLL_PFD_DELAY_CTRL ? ? FIELD32(0x0c000000)
> +#define PLL_LOCK_CTRL ? ? ? ? ?FIELD32(0x70000000)
> +#define PLL_VBGBK_EN ? ? ? ? ? FIELD32(0x80000000)
> +
> +/*
> + * COEX_CFG_0
> + */
> +#define COEX_CFG0 ? ? ? ? ? ? ? ? ? ? ?0x40
> +
> +/*
> + * COEX_CFG_1
> + */
> +#define COEX_CFG1 ? ? ? ? ? ? ? ? ? ? ?0x44
> +
> +/*
> + * COEX_CFG_2
> + */
> +#define COEX_CFG2 ? ? ? ? ? ? ? ? ? ? ?0x48
> +
> +/*
> ?* MCU_CMD_CFG
> ?*/
> ?#define MCU_CMD_CFG ? ? ? ? ? ? ? ? ? ?0x022c
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index 1cd16b4..7753791 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ?multiple = true;
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?fw_len = 8192;
> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? fw_len = 4096;
> +
> ? ? ? ? ? ? ? ?multiple = true;
> ? ? ? ?}
>

It would look better to create an else-branch for the fw_len = 8192
assignment. Now it looks odd with overwriting the earlier given value.

> @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?if (rt2x00_is_pci(rt2x00dev)) {
> ? ? ? ? ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);

I will just mention this once, but this applies for the whole patch:
Please include the condition in the correct numerical order. It just
makes it easier to look through the code if the RT chipset checks are
in numerical order.

> @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
> ?{
> ? ? ? ?u32 reg;
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> + ? ? ? ? ? ? ? return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> + ? ? ? } else
> ? ? ? ?rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
> ? ? ? ?return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
> ?}

This looks fishy, as I think both the register_read and the return
statement need to be part of the else branch. Technically the code
still behaves correctly, but it just looks fishy.

> @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
>
> ?#define RT5390_POWER_BOUND ? ? 0x27
> ?#define RT5390_FREQ_OFFSET_BOUND ? ? ? 0x5f
> -
> +#define RT3290_POWER_BOUND ? ? 0x27
> +#define RT3290_FREQ_OFFSET_BOUND ? ? ? 0x5f
> ?static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ieee80211_conf *conf,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct rf_channel *rf,

No need to remove the empty line. Also, if these values are the same
as for the RT5390 defines, can we combine these in a more generically
named set of defines?

> @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> ?}
>
> +
> +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct channel_info *info)
> +{
> + ? ? ? u8 rfcsr;
> +
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> + ? ? ? if (info->default_power1 > RT5390_POWER_BOUND)
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> + ? ? ? else
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> + ? ? ? if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RT3290_FREQ_OFFSET_BOUND);
> + ? ? ? else
> + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> +
> + ? ? ? if (rf->channel <= 14) {
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);

Can we create some defines for this RFCSR so that we don't have to do
this bit manipulation magic? That would make the code more readable
and better understandable.

> +
> + ? ? ? ? ? ? ? if (rf->channel == 6)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> +
> + ? ? ? ? ? ? ? if (rf->channel >= 1 && rf->channel <= 6)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> + ? ? ? ? ? ? ? else if (rf->channel >= 7 && rf->channel <= 11)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> + ? ? ? ? ? ? ? else if (rf->channel >= 12 && rf->channel <= 14)
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> + ? ? ? }
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> +
> + ? ? ? rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> + ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> +}
> ?static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,

There is quite a bit of overlap with the already existing
rt2800_config_channel_rf53xx function. Is it possible to share more
code between the two?

> @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> ? ? ? ?case RF5390:
> ? ? ? ? ? ? ? ?rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
> ? ? ? ? ? ? ? ?break;
> + ? ? ? case RF3290:
> + ? ? ? ? ? ? ? rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> + ? ? ? ? ? ? ? break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
> ? ? ? ?}

Again, please put the case in the correct numerical order.

> @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3390) ||
> ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ? ? ? ? ?return 0x1c + (2 * rt2x00dev->lna_gain);
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?return 0x2e + rt2x00dev->lna_gain;
> @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
> ? ? ? ?rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> + ? ? ? ? ? ? ? if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> + ? ? ? ? ? ? ? if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO0_EN, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> + ? ? ? ? ? ? ? reg &= ~(0xFF000000);
> + ? ? ? ? ? ? ? reg |= 0x5E000000;
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> + ? ? ? }
> +
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3071) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390)) {
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x00000404);
> + ? ? ? ? ? ? ? else
> ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
> ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
> ? ? ? ? ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?return -EACCES;
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ? ?||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_read(rt2x00dev, 4, &value);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 4, value);
> @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 31, 0x08);
>
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 65, 0x2c);
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 66, 0x38);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 68, 0x0b);
>
> ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x16);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x12);
> ? ? ? ?} else if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x13);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 75, 0x46);
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 76, 0x28);
> +
> + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 77, 0x58);
> + ? ? ? ? ? ? ? else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 77, 0x59);
> ? ? ? ?} else {
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);

Please adjust the indentation of the else branch. You can't just
insert the else and leave the code that is now in the else branch at
its old indentation level.

> @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 81, 0x37);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 79, 0x18);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 80, 0x09);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 81, 0x33);
> + ? ? ? }
> +
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 82, 0x62);
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x7a);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x19);
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x9a);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x99);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x38);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x00);
> @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?rt2800_bbp_write(rt2x00dev, 91, 0x04);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x02);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x00);
> @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290) ||
> ? ? ? ? ? ?rt2800_is_305x_soc(rt2x00dev))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0xc0);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0x00);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 104, 0x92);
>
> ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev))
> @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> + ? ? ? else if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 105, 0x1c);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x05);
>
> - ? ? ? if (rt2x00_rt(rt2x00dev, RT5390))
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT5390) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x03);
> ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5392))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x12);
> @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x35);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 128, 0x12);
>
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5392)) {
> @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 138, value);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 67, 0x24);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 143, 0x04);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 142, 0x99);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 150, 0x30);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 152, 0x20);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 153, 0x34);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 154, 0x40);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 253, 0x04);
> +
> + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 47, &value);
> + ? ? ? ? ? ? ? rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 47, value);
> +
> + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 3, &value);
> + ? ? ? ? ? ? ? value &= (~0xc0);
> + ? ? ? ? ? ? ? value |= 0xc0;
> + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 3, value);
> + ? ? ? }

Again, please introduce some define so that we do not have to do this
bit manipulation magic.

> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> ? ? ? ? ? ? ? ?int ant, div_mode;
> @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT3572) &&
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5390) &&
> ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5392) &&
> + ? ? ? ? ? !rt2x00_rt(rt2x00dev, RT3290) &&
> ? ? ? ? ? ?!rt2800_is_305x_soc(rt2x00dev))
> ? ? ? ? ? ? ? ?return 0;
>
> @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? * Init RF calibration.
> ? ? ? ? */
> ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
> ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
> ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> + ? ? ? } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
> ? ? ? ?}
>
> ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> ? ? ? ?}
>
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> + ? ? ? ? ? ? ? rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> + ? ? ? }
> +
> ? ? ? ?return 0;
> ?}

More bit manipulation magic.

>
> @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
> ?int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
> ?{
> ? ? ? ?u32 reg;
> + ? ? ? u16 efuse_ctrl_reg;
> + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
>
> - ? ? ? rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;
>
> + ? ? ? rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
> ? ? ? ?return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
> ?}
> ?EXPORT_SYMBOL_GPL(rt2800_efuse_detect);

Can you explain why we need the chip.mac_version check here instead of
just doing a check for rt2x00_rt(rt2x00dev, RT3290)?
That way we would not have to add this mac_version field.

> @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
> ?{
> ? ? ? ?u32 reg;
>
> + ? ? ? u16 efuse_ctrl_reg;
> + ? ? ? u16 efuse_data0_reg;
> + ? ? ? u16 efuse_data1_reg;
> + ? ? ? u16 efuse_data2_reg;
> + ? ? ? u16 efuse_data3_reg;
> +
> + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
> + ? ? ? efuse_data0_reg = EFUSE_DATA0;
> + ? ? ? efuse_data1_reg = EFUSE_DATA1;
> + ? ? ? efuse_data2_reg = EFUSE_DATA2;
> + ? ? ? efuse_data3_reg = EFUSE_DATA3;
> +
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290) {
> + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;
> + ? ? ? ? ? ? ? efuse_data3_reg = 0x28;
> + ? ? ? ? ? ? ? efuse_data2_reg = efuse_data3_reg + 4;
> + ? ? ? ? ? ? ? efuse_data1_reg = efuse_data2_reg + 4;
> + ? ? ? ? ? ? ? efuse_data0_reg = efuse_data1_reg + 4;
> + ? ? ? }
> ? ? ? ?mutex_lock(&rt2x00dev->csr_mutex);
>
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
> ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> - ? ? ? rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> + ? ? ? rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
>
> ? ? ? ?/* Wait until the EEPROM has been loaded */
> - ? ? ? rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> -
> + ? ? ? rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
> ? ? ? ?/* Apparently the data is read from end to start */
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
> ? ? ? ?/* The returned value is in CPU order, but eeprom is le */
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
> ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
>
> ? ? ? ?mutex_unlock(&rt2x00dev->csr_mutex);
> @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
> ? ? ? ? * RT53xx: defined in "EEPROM_CHIP_ID" field
> ? ? ? ? */
> + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> + ? ? ? else
> ? ? ? ?rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
> ? ? ? ?if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> - ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
> ? ? ? ? ? ? ? ?rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
> ? ? ? ?else
> ? ? ? ? ? ? ? ?value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RT3572:
> ? ? ? ?case RT5390:
> ? ? ? ?case RT5392:
> + ? ? ? case RT3290:
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF3320) ||
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5370) ||
> ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5372) ||
> - ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390)) {
> + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390) ||
> + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF3290)) {
> ? ? ? ? ? ? ? ?spec->num_channels = 14;
> ? ? ? ? ? ? ? ?spec->channels = rf_vals_3x;
> ? ? ? ?} else if (rt2x00_rf(rt2x00dev, RF3052)) {
> @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> ? ? ? ?case RF5370:
> ? ? ? ?case RF5372:
> ? ? ? ?case RF5390:
> + ? ? ? case RF3290:
> ? ? ? ? ? ? ? ?__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> ?}
> ?EXPORT_SYMBOL_GPL(rt2800_get_survey);
>
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> + ? ? ? u32 wlanfunctrl;
> + ? ? ? u32 glocfg;
> + ? ? ? u32 cmbctrl;
> + ? ? ? u8 index;
> + ? ? ? int i;
> +
> + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> + ? ? ? if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> + ? ? ? ? ? ? ? return 0;
> +
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> +
> + ? ? ? index = 0;
> + ? ? ? cmbctrl = 0;
> + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> + ? ? ? ? ? ? ? if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> + ? ? ? ? ? ? ? ? ? ? ? (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? }
> +
> + ? ? ? if (index >= REGISTER_BUSY_COUNT) {
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x018);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x418);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x618);
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? } else {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev,
> + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG, &glocfg);
> + ? ? ? }
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> +
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> + ? ? ? udelay(2);
> + ? ? ? rt2800_register_write(rt2x00dev,
> + ? ? ? ? ? ? ? INT_SOURCE_CSR, 0x7fffffff);
> + ? ? ? return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> +
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> +{
> + ? ? ? u32 wlanfunctrl;
> + ? ? ? u32 glocfg;
> + ? ? ? u32 reg;
> + ? ? ? int i;
> +
> + ? ? ? /* Change Interrupt bitmask. */
> + ? ? ? rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> + ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> + ? ? ? rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> + ? ? ? rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> +
> + ? ? ? /* wait RX DMA idle */
> + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> + ? ? ? ? ? ? ? if ((rt2x00_get_field32(glocfg,
> + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> + ? ? ? ? ? ? ? ? ? ? ? (glocfg == 0xFFFFFFFF))
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? }
> +
> + ? ? ? if (i >= REGISTER_BUSY_COUNT) {
> + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> + ? ? ? udelay(REGISTER_BUSY_DELAY);
> + ? ? ? return 0;
> +}
> +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);

These two functions seems to be pci specific, shouldn't they be in
rt2800pci.c then?


> ?MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
> ?MODULE_VERSION(DRV_VERSION);
> ?MODULE_DESCRIPTION("Ralink RT2800 library");
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> index 18a0b67..22d7cbb 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> ?int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> ? ? ? ? ? ? ? ? ? ? ?struct survey_info *survey);
> ?void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> -
> +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
> ?#endif /* RT2800LIB_H */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> index 931331d..9251f2d 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
> ?*/
> ?static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
> ?{
> +
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? return FIRMWARE_RT3290;
> +
> ? ? ? ?return FIRMWARE_RT2860;
> ?}
>

OK. Since this is a different firmware file, I assume you will be
submitting this firmware to the linux-firmware repository, right?

> @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
> ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
> ? ? ? ?}
> +
> + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> + ? ? ? ? ? ? ? rt2800pci_3290_disable_wlan(rt2x00dev);
> ?}
>
> ?static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
> ? ? ? ? */
> ? ? ? ?rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
>
> + ? ? ? if (rt2x00_rf(rt2x00dev, RF3290))
> + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);
> ? ? ? ?return 0;
> ?}
>
> @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
> ? ? ? ?{ PCI_DEVICE(0x1814, 0x539a) },
> ? ? ? ?{ PCI_DEVICE(0x1814, 0x539f) },
> ?#endif
> +#ifdef CONFIG_RT2800PCI_RT3290
> + ? ? ? { PCI_DEVICE(0x1814, 0x3290) },
> +#endif
> ? ? ? ?{ 0, }
> ?};

Numerical order, please.

> ?#endif /* CONFIG_PCI */
> diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> index 70e050d..dd043c7 100644
> --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> @@ -49,6 +49,9 @@
> ?#define FIRMWARE_RT2860 ? ? ? ? ? ? ? ? ? ? ? ?"rt2860.bin"
> ?#define FIRMWARE_IMAGE_BASE ? ? ? ? ? ?0x2000
>
> +
> +#define FIRMWARE_RT3290 ? ? ? ? ? ? ? ? ? ? ? ?"rt3290.bin"
> +
> ?/*
> ?* DMA descriptor defines.
> ?*/

Please move the define next to the order firmware filename definition.

> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index ca36ccc..ee770e7 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -193,10 +193,11 @@ struct rt2x00_chip {
> ?#define RT3883 ? ? ? ? 0x3883 ?/* WSOC */
> ?#define RT5390 ? ? ? ? 0x5390 ?/* 2.4GHz */
> ?#define RT5392 ? ? ? ? 0x5392 ?/* 2.4GHz */
> +#define RT3290 ? ? ? ? 0x3290
>
> ? ? ? ?u16 rf;
> ? ? ? ?u16 rev;
> -
> + ? ? ? u16 mac_version;
> ? ? ? ?enum rt2x00_chip_intf intf;
> ?};
>

As mentioned before, please explain why this new field is needed.

> diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> index 0a4653a..9bbd9a3 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> ? ? ? ?struct ieee80211_hw *hw;
> ? ? ? ?struct rt2x00_dev *rt2x00dev;
> ? ? ? ?int retval;
> + ? ? ? u16 device_id;
>
> ? ? ? ?retval = pci_enable_device(pci_dev);
> ? ? ? ?if (retval) {
> @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> ? ? ? ?if (retval)
> ? ? ? ? ? ? ? ?goto exit_free_device;
>
> +
> + ? ? ? pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> + ? ? ? if (device_id == 0x3290)
> + ? ? ? ? ? ? ? rt2x00dev->chip.mac_version = 0x3290;
> +
> ? ? ? ?retval = rt2x00lib_probe_dev(rt2x00dev);
> ? ? ? ?if (retval)
> ? ? ? ? ? ? ? ?goto exit_free_reg;
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html



--
---
Gertjan

2012-05-03 01:12:52

by Woody Hung

[permalink] [raw]
Subject: RE: [PATCH] rt2x00 : RT3290 chip support

R290IGl0LCBJIHdpbGwgcmUtd3JpdGUgaXR+fn4NCg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0t
LS0NCkZyb206IEpvaG4gVy4gTGludmlsbGUgW21haWx0bzpsaW52aWxsZUB0dXhkcml2ZXIuY29t
XQ0KU2VudDogVGh1cnNkYXksIE1heSAwMywgMjAxMiAyOjEzIEFNDQpUbzogSGVsbXV0IFNjaGFh
DQpDYzogV29vZHkgSHVuZyAo5rSq56eL56u5KTsgbGludXgtd2lyZWxlc3NAdmdlci5rZXJuZWwu
b3JnOyBKYXkgSHVuZyAo5rSq5YGJ5YKRKTsgUG9oc3VuIFlhbmcgKOaliuS8r+WLsyk7IERlbm5p
cyBMZWUgKOadjuaYjumBlCk7IEl2byBWYW4gRG9vcm47IEdlcnRqYW4gdmFuIFdpbmdlcmRlDQpT
dWJqZWN0OiBSZTogW1BBVENIXSBydDJ4MDAgOiBSVDMyOTAgY2hpcCBzdXBwb3J0DQoNClBsZWFz
ZSByZXNwb25kIHRvIEhlbG11dCdzIGNvbW1lbnRhcnkuLi4NCg0KT24gRnJpLCBBcHIgMjcsIDIw
MTIgYXQgMDk6NDA6MjhBTSArMDIwMCwgSGVsbXV0IFNjaGFhIHdyb3RlOg0KPiBIaSBXb29keSwN
Cj4NCj4gQSBiaXQgbW9yZSB2ZXJib3NlIHBhdGNoIGRlc2NyaXB0aW9uIHdvdWxkIGJlIGhpZ2hs
eSBhcHByZWNpYXRlZC4gQWxzbw0KPiBzZWUgc29tZSBpbmxpbmUgY29tbWVudHMgYWJvdXQgdGhl
IHBhdGNoIGl0c2VsZi4gSG93ZXZlciwgSSBvbmx5IGhhZCBhDQo+IHF1aWNrIGxvb2ssIHNvIGV4
cGVjdCBhIGZldyBtb3JlIGNvbW1lbnRzIGZyb20gb3RoZXJzIHRvbyAuLi4NCj4NCj4gQWxzbywg
cGxlYXNlIGFsd2F5cyBjaGVjayB5b3VyIHBhdGNoIGJ5IHJ1bm5pbmcgc2NyaXB0cy9jaGVja3Bh
dGNoLnBsDQo+IGZyb20geW91ciBrZXJuZWwgdHJlZSBvbnRvIGl0Lg0KPg0KPiBIZWxtdXQNCj4N
Cj4gT24gRnJpLCBBcHIgMjcsIDIwMTIgYXQgNDoyMiBBTSwgV29vZHkgSHVuZyA8V29vZHkuSHVu
Z0BtZWRpYXRlay5jb20+IHdyb3RlOg0KPiA+IFRoaXMgc3VwcG9ydCBSVDMyOTAgY2hpcA0KPiA+
DQo+ID4gU2lnbmVkLW9mZi1ieTogV29vZHkgSHVuZyA8V29vZHkuSHVuZ0BtZWRpYXRlay5jb20+
DQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnICAgICB8
ICAgIDggKw0KPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwLmggICAgfCAg
MTIwICsrKysrKysrKy0NCj4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMGxp
Yi5jIHwgIDM5NQ0KPiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKystLQ0KPiA+ICBkcml2
ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwbGliLmggfCAgICAzICstDQo+ID4gIGRyaXZl
cnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuYyB8ICAgMTIgKw0KPiA+ICBkcml2ZXJz
L25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNpLmggfCAgICAzICsNCj4gPiAgZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMC5oICAgIHwgICAgMyArLQ0KPiA+ICBkcml2ZXJzL25l
dC93aXJlbGVzcy9ydDJ4MDAvcnQyeDAwcGNpLmMgfCAgICA2ICsNCj4gPiAgOCBmaWxlcyBjaGFu
Z2VkLCA1MjAgaW5zZXJ0aW9ucygrKSwgMzAgZGVsZXRpb25zKC0pDQo+ID4NCj4gPiBkaWZmIC0t
Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL0tjb25maWcNCj4gPiBiL2RyaXZlcnMv
bmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnDQo+ID4gaW5kZXggMjk5YzM4Ny4uYzc1NDhkYSAx
MDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvS2NvbmZpZw0KPiA+
ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9LY29uZmlnDQo+ID4gQEAgLTk5LDYg
Kzk5LDE0IEBAIGNvbmZpZyBSVDI4MDBQQ0lfUlQ1M1hYDQo+ID4gICAgICAgICAgcnQyODAwcGNp
IGRyaXZlci4NCj4gPiAgICAgICAgICBTdXBwb3J0ZWQgY2hpcHM6IFJUNTM5MA0KPiA+DQo+ID4g
K2NvbmZpZyBSVDI4MDBQQ0lfUlQzMjkwDQo+ID4gKyAgICAgICBib29sICJydDI4MDBwY2kgLSBJ
bmNsdWRlIHN1cHBvcnQgZm9yIHJ0MzI5MCBkZXZpY2VzIChFWFBFUklNRU5UQUwpIg0KPiA+ICsg
ICAgICAgZGVwZW5kcyBvbiBFWFBFUklNRU5UQUwNCj4gPiArICAgICAgIGRlZmF1bHQgeQ0KPiA+
ICsgICAgICAgLS0taGVscC0tLQ0KPiA+ICsgICAgICAgICBUaGlzIGFkZHMgc3VwcG9ydCBmb3Ig
cnQzMjkwIHdpcmVsZXNzIGNoaXBzZXQgZmFtaWx5IHRvDQo+ID4gK3RoZQ0KPiA+ICsgICAgICAg
ICBydDI4MDBwY2kgZHJpdmVyLg0KPiA+ICsgICAgICAgICBTdXBwb3J0ZWQgY2hpcHM6IFJUMzI5
MA0KPiA+ICBlbmRpZg0KPiA+DQo+ID4gIGNvbmZpZyBSVDI1MDBVU0INCj4gPiBkaWZmIC0tZ2l0
IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMC5oDQo+ID4gYi9kcml2ZXJzL25l
dC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwLmgNCj4gPiBpbmRleCBkOTFmNGY2Li4zOWIxNjg1IDEw
MDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDAuaA0KPiA+
ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDAuaA0KPiA+IEBAIC03MCw3
ICs3MCw3IEBADQo+ID4gICNkZWZpbmUgUkY1MzcwICAgICAgICAgICAgICAgICAgICAgICAgIDB4
NTM3MA0KPiA+ICAjZGVmaW5lIFJGNTM3MiAgICAgICAgICAgICAgICAgICAgICAgICAweDUzNzIN
Cj4gPiAgI2RlZmluZSBSRjUzOTAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1MzkwDQo+ID4g
LQ0KPiA+ICsjZGVmaW5lIFJGMzI5MCAgICAgICAgICAgICAgICAgICAgICAgICAweDMyOTANCj4N
Cj4gVGhlcmUncyBubyBuZWVkIHRvIHJlbW92ZSB0aGUgZW10eSBsaW5lIGhlcmUuDQo+DQo+ID4g
IC8qDQo+ID4gICogQ2hpcHNldCByZXZpc2lvbnMuDQo+ID4gICovDQo+ID4gQEAgLTExMiw2ICsx
MTIsMTIgQEANCj4gPiAgKiBSZWdpc3RlcnMuDQo+ID4gICovDQo+ID4NCj4gPiArDQo+ID4gKy8q
DQo+ID4gKyAqIE1BQ19DU1IwXzMyOTA6IE1BQ19DU1IwIGZvciBydDMyOTAgdG8gaWRlbnRpdHkg
TUFDIHZlcnNpb24gbnVtYmVyLg0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBNQUNfQ1NSMF8zMjkw
ICAgICAgICAgICAgICAgICAgICAgICAgICAweDAwMDANCj4gPiArDQo+DQo+IFRoaXMgc2hvdWxk
IGJlIG1vdmVkIHRvIHRoZSBvdGhlciBNQUMgcmVnaXN0ZXIgZGVmaW5pdGlvbnMuDQo+IElzIHRo
aXMgcmVnaXN0ZXIgb25seSB2YWxpZCBvbiAzMjkwIGNoaXBzZXRzPw0KPg0KPiA+ICAvKg0KPiA+
ICAqIEUyUFJPTV9DU1I6IFBDSSBFRVBST00gY29udHJvbCByZWdpc3Rlci4NCj4gPiAgKiBSRUxP
QUQ6IFdyaXRlIDEgdG8gcmVsb2FkIGVlcHJvbSBjb250ZW50Lg0KPiA+IEBAIC0zMDUsNiArMzEx
LDExOCBAQA0KPiA+ICAjZGVmaW5lIEdQSU9fQ1RSTF9DRkdfR1BJT0RfQklUNyAgICAgICBGSUVM
RDMyKDB4MDAwMDgwMDApDQo+ID4NCj4gPiAgLyoNCj4gPiArICogV0xBTl9DVFJMX0NGRw0KPiA+
ICsgKi8NCj4gPiArI2RlZmluZSBXTEFOX0ZVTl9DVFJMICAgICAgICAgICAgICAgICAgMHg4MCAj
ZGVmaW5lIFdMQU5fRU4NCj4gPiArRklFTEQzMigweDAwMDAwMDAxKSAjZGVmaW5lIFdMQU5fQ0xL
X0VODQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAwMikgI2RlZmluZSBXTEFOX1JTVjENCj4gPiArRklF
TEQzMigweDAwMDAwMDA0KSAjZGVmaW5lIFdMQU5fUkVTRVQNCj4gPiArRklFTEQzMigweDAwMDAw
MDA4KSAjZGVmaW5lIFBDSUVfQVBQMF9DTEtfUkVRDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAxMCkg
I2RlZmluZSBGUkNfV0xfQU5UX1NFVA0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwMjApICNkZWZpbmUg
SU5WX1RSX1NXMA0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwNDApICNkZWZpbmUgV0xBTl9HUElPX0lO
X0JJVDANCj4gPiArRklFTEQzMigweDAwMDAwMTAwKSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQx
DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDIwMCkgI2RlZmluZSBXTEFOX0dQSU9fSU5fQklUMg0KPiA+
ICtGSUVMRDMyKDB4MDAwMDA0MDApICNkZWZpbmUgV0xBTl9HUElPX0lOX0JJVDMNCj4gPiArRklF
TEQzMigweDAwMDAwODAwKSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQ0DQo+ID4gK0ZJRUxEMzIo
MHgwMDAwMTAwMCkgI2RlZmluZSBXTEFOX0dQSU9fSU5fQklUNQ0KPiA+ICtGSUVMRDMyKDB4MDAw
MDIwMDApICNkZWZpbmUgV0xBTl9HUElPX0lOX0JJVDYNCj4gPiArRklFTEQzMigweDAwMDA0MDAw
KSAjZGVmaW5lIFdMQU5fR1BJT19JTl9CSVQ3DQo+ID4gK0ZJRUxEMzIoMHgwMDAwODAwMCkgI2Rl
ZmluZSBXTEFOX0dQSU9fSU5fQklUX0FMTA0KPiA+ICtGSUVMRDMyKDB4MDAwMGZmMDApICNkZWZp
bmUgV0xBTl9HUElPX09VVF9CSVQwDQo+ID4gK0ZJRUxEMzIoMHgwMDAxMDAwMCkgI2RlZmluZSBX
TEFOX0dQSU9fT1VUX0JJVDENCj4gPiArRklFTEQzMigweDAwMDIwMDAwKSAjZGVmaW5lIFdMQU5f
R1BJT19PVVRfQklUMg0KPiA+ICtGSUVMRDMyKDB4MDAwNDAwMDApICNkZWZpbmUgV0xBTl9HUElP
X09VVF9CSVQzDQo+ID4gK0ZJRUxEMzIoMHgwMDA1MDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VU
X0JJVDQNCj4gPiArRklFTEQzMigweDAwMTAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfQklU
NQ0KPiA+ICtGSUVMRDMyKDB4MDAyMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9CSVQ2DQo+
ID4gK0ZJRUxEMzIoMHgwMDQwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX0JJVDcNCj4gPiAr
RklFTEQzMigweDAwODAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfQklUX0FMTA0KPiA+ICtG
SUVMRDMyKDB4MDBmZjAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQwDQo+ID4gK0ZJ
RUxEMzIoMHgwMTAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDENCj4gPiArRklF
TEQzMigweDAyMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUMg0KPiA+ICtGSUVM
RDMyKDB4MDQwMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQzDQo+ID4gK0ZJRUxE
MzIoMHgwODAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDQNCj4gPiArRklFTEQz
MigweDEwMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUNQ0KPiA+ICtGSUVMRDMy
KDB4MjAwMDAwMDApICNkZWZpbmUgV0xBTl9HUElPX09VVF9PRV9CSVQ2DQo+ID4gK0ZJRUxEMzIo
MHg0MDAwMDAwMCkgI2RlZmluZSBXTEFOX0dQSU9fT1VUX09FX0JJVDcNCj4gPiArRklFTEQzMigw
eDgwMDAwMDAwKSAjZGVmaW5lIFdMQU5fR1BJT19PVVRfT0VfQklUX0FMTA0KPiA+ICtGSUVMRDMy
KDB4ZmYwMDAwMDApDQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBDTUJfQ1RSTF9DRkcNCj4gPiAr
ICovDQo+ID4gKyNkZWZpbmUgQ01CX0NUUkwgICAgICAgICAgICAgICAweDIwICNkZWZpbmUgQVVY
X09QVF9CSVQwDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDAwMSkgI2RlZmluZSBBVVhfT1BUX0JJVDEN
Cj4gPiArRklFTEQzMigweDAwMDAwMDAyKSAjZGVmaW5lIEFVWF9PUFRfQklUMg0KPiA+ICtGSUVM
RDMyKDB4MDAwMDAwMDQpICNkZWZpbmUgQVVYX09QVF9CSVQzDQo+ID4gK0ZJRUxEMzIoMHgwMDAw
MDAwOCkgI2RlZmluZSBBVVhfT1BUX0JJVDQNCj4gPiArRklFTEQzMigweDAwMDAwMDEwKSAjZGVm
aW5lIEFVWF9PUFRfQklUNQ0KPiA+ICtGSUVMRDMyKDB4MDAwMDAwMjApICNkZWZpbmUgQVVYX09Q
VF9CSVQ2DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDA0MCkgI2RlZmluZSBBVVhfT1BUX0JJVDcNCj4g
PiArRklFTEQzMigweDAwMDAwMDgwKSAjZGVmaW5lIEFVWF9PUFRfQklUOA0KPiA+ICtGSUVMRDMy
KDB4MDAwMDAxMDApICNkZWZpbmUgQVVYX09QVF9CSVQ5DQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDIw
MCkgI2RlZmluZSBBVVhfT1BUX0JJVDEwDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDQwMCkgI2RlZmlu
ZSBBVVhfT1BUX0JJVDExDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMDgwMCkgI2RlZmluZSBBVVhfT1BU
X0JJVDEyDQo+ID4gK0ZJRUxEMzIoMHgwMDAwMTAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDEzDQo+
ID4gK0ZJRUxEMzIoMHgwMDAwMjAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDE0DQo+ID4gK0ZJRUxE
MzIoMHgwMDAwNDAwMCkgI2RlZmluZSBBVVhfT1BUX0JJVDE1DQo+ID4gK0ZJRUxEMzIoMHgwMDAw
ODAwMCkgI2RlZmluZSBMRE8yNV9MRVZFTA0KPiA+ICtGSUVMRDMyKDB4MDAwMzAwMDApICNkZWZp
bmUgTERPMjVfTEFSR0VBDQo+ID4gK0ZJRUxEMzIoMHgwMDA0MDAwMCkgI2RlZmluZSBMRE8yNV9G
UkNfT04NCj4gPiArRklFTEQzMigweDAwMDgwMDAwKSAjZGVmaW5lIENNQl9SU1YNCj4gPiArRklF
TEQzMigweDAwMzAwMDAwKSAjZGVmaW5lIFhUQUxfUkRZDQo+ID4gK0ZJRUxEMzIoMHgwMDQwMDAw
MCkgI2RlZmluZSBQTExfTEQNCj4gPiArRklFTEQzMigweDAwODAwMDAwKSAjZGVmaW5lIExET19D
T1JFX0xFVkVMDQo+ID4gK0ZJRUxEMzIoMHgwRjAwMDAwMCkgI2RlZmluZSBMRE9fQkdTRUwNCj4g
PiArRklFTEQzMigweDMwMDAwMDAwKSAjZGVmaW5lIExETzNfRU4NCj4gPiArRklFTEQzMigweDQw
MDAwMDAwKSAjZGVmaW5lIExETzBfRU4NCj4gPiArRklFTEQzMigweDgwMDAwMDAwKQ0KPiA+ICsN
Cj4gPiArLyoNCj4gPiArICogT1NDX0NUUkxfQ0ZHDQo+ID4gKyAqLw0KPiA+ICsjZGVmaW5lIE9T
Q19DVFJMICAgICAgICAgICAgICAgMHgzOCAjZGVmaW5lIE9TQ19SRUZfQ1lDTEUNCj4gPiArRklF
TEQzMigweDAwMDAxZmZmKSAjZGVmaW5lIE9TQ19SU1YNCj4gPiArRklFTEQzMigweDAwMDBlMDAw
KSAjZGVmaW5lIE9TQ19DQUxfQ05UDQo+ID4gK0ZJRUxEMzIoMHgwZmZmMDAwMCkgI2RlZmluZSBP
U0NfQ0FMX0FDSw0KPiA+ICtGSUVMRDMyKDB4MTAwMDAwMDApICNkZWZpbmUgT1NDX0NMS18zMktf
VkxEDQo+ID4gK0ZJRUxEMzIoMHgyMDAwMDAwMCkgI2RlZmluZSBPU0NfQ0FMX1JFUQ0KPiA+ICtG
SUVMRDMyKDB4NDAwMDAwMDApICNkZWZpbmUgT1NDX1JPU0NfRU4NCj4gPiArRklFTEQzMigweDgw
MDAwMDAwKQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogUExMX0NUUkxfQ0ZHDQo+ID4gKyAqLw0K
PiA+ICsjZGVmaW5lIFBMTF9DVFJMICAgICAgICAgICAgICAgMHg1MCAjZGVmaW5lIFBMTF9SRVNF
UlZFRF9JTlBVVDENCj4gPiArRklFTEQzMigweDAwMDAwMGZmKSAjZGVmaW5lIFBMTF9SRVNFUlZF
RF9JTlBVVDINCj4gPiArRklFTEQzMigweDAwMDBmZjAwKSAjZGVmaW5lIFBMTF9DT05UUk9MDQo+
ID4gK0ZJRUxEMzIoMHgwMDA3MDAwMCkgI2RlZmluZSBQTExfTFBGX1IxDQo+ID4gK0ZJRUxEMzIo
MHgwMDA4MDAwMCkgI2RlZmluZSBQTExfTFBGX0MxX0NUUkwNCj4gPiArRklFTEQzMigweDAwMzAw
MDAwKSAjZGVmaW5lIFBMTF9MUEZfQzJfQ1RSTA0KPiA+ICtGSUVMRDMyKDB4MDBjMDAwMDApICNk
ZWZpbmUgUExMX0NQX0NVUlJFTlRfQ1RSTA0KPiA+ICtGSUVMRDMyKDB4MDMwMDAwMDApICNkZWZp
bmUgUExMX1BGRF9ERUxBWV9DVFJMDQo+ID4gK0ZJRUxEMzIoMHgwYzAwMDAwMCkgI2RlZmluZSBQ
TExfTE9DS19DVFJMDQo+ID4gK0ZJRUxEMzIoMHg3MDAwMDAwMCkgI2RlZmluZSBQTExfVkJHQktf
RU4NCj4gPiArRklFTEQzMigweDgwMDAwMDAwKQ0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogQ09F
WF9DRkdfMA0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBDT0VYX0NGRzAgICAgICAgICAgICAgICAg
ICAgICAgMHg0MA0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogQ09FWF9DRkdfMQ0KPiA+ICsgKi8N
Cj4gPiArI2RlZmluZSBDT0VYX0NGRzEgICAgICAgICAgICAgICAgICAgICAgMHg0NA0KPiA+ICsN
Cj4gPiArLyoNCj4gPiArICogQ09FWF9DRkdfMg0KPiA+ICsgKi8NCj4gPiArI2RlZmluZSBDT0VY
X0NGRzIgICAgICAgICAgICAgICAgICAgICAgMHg0OA0KPiA+ICsNCj4gPiArLyoNCj4gPiAgKiBN
Q1VfQ01EX0NGRw0KPiA+ICAqLw0KPiA+ICAjZGVmaW5lIE1DVV9DTURfQ0ZHICAgICAgICAgICAg
ICAgICAgICAweDAyMmMgZGlmZiAtLWdpdA0KPiA+IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQy
eDAwL3J0MjgwMGxpYi5jDQo+ID4gYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
bGliLmMNCj4gPiBpbmRleCAxY2QxNmI0Li43NzUzNzkxIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZl
cnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuYw0KPiA+ICsrKyBiL2RyaXZlcnMvbmV0
L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuYw0KPiA+IEBAIC0zNjEsNiArMzYxLDEwIEBAIGlu
dCBydDI4MDBfY2hlY2tfZmlybXdhcmUoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2
LA0KPiA+ICAgICAgICAgICAgICAgIG11bHRpcGxlID0gdHJ1ZTsNCj4gPiAgICAgICAgfSBlbHNl
IHsNCj4gPiAgICAgICAgICAgICAgICBmd19sZW4gPSA4MTkyOw0KPiA+ICsNCj4gPiArICAgICAg
ICAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgZndfbGVuID0gNDA5NjsNCj4gPiArDQo+ID4gICAgICAgICAgICAgICAg
bXVsdGlwbGUgPSB0cnVlOw0KPiA+ICAgICAgICB9DQo+ID4NCj4gPiBAQCAtNDE3LDcgKzQyMSw4
IEBAIGludCBydDI4MDBfbG9hZF9maXJtd2FyZShzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4
MDBkZXYsDQo+ID4gICAgICAgIGlmIChydDJ4MDBfaXNfcGNpKHJ0MngwMGRldikpIHsNCj4gPiAg
ICAgICAgICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSB8fA0KPiA+ICAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKSB7DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIEFVWF9D
VFJMLA0KPiA+ICZyZWcpOw0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9m
aWVsZDMyKCZyZWcsDQo+ID4gQVVYX0NUUkxfRk9SQ0VfUENJRV9DTEssIDEpOw0KPiA+ICAgICAg
ICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsDQo+ID4gQVVYX0NUUkxf
V0FLRV9QQ0lFX0VOLCAxKTsgQEAgLTg0NCw2ICs4NDksMTAgQEAgaW50DQo+ID4gcnQyODAwX3Jm
a2lsbF9wb2xsKHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gIHsNCj4gPiAgICAg
ICAgdTMyIHJlZzsNCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJU
MzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAw
ZGV2LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAgICAgICAgICAgIHJl
dHVybiBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBXTEFOX0dQSU9fSU5fQklUMCk7DQo+ID4gKyAg
ICAgICB9IGVsc2UNCj4gPiAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBH
UElPX0NUUkxfQ0ZHLCAmcmVnKTsNCj4NCj4gVGhpcyBsb29rcyBhd2t3YXJkLCBlaXRoZXIgeW91
IGhhdmUgdG8gdXNlIGNvcnJlY3QgaW5kZW50aW9uIGhlcmUgb3INCj4gZHJvcCB0aGUgZWxzZSBj
b21wbGV0ZWx5Lg0KPg0KPiA+ICAgICAgICByZXR1cm4gcnQyeDAwX2dldF9maWVsZDMyKHJlZywg
R1BJT19DVFJMX0NGR19CSVQyKTsNCj4gPiAgfQ0KPiA+IEBAIC0xOTMwLDcgKzE5MzksOCBAQCBz
dGF0aWMgdm9pZA0KPiA+IHJ0MjgwMF9jb25maWdfY2hhbm5lbF9yZjMwNTIoc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldiwNCj4gPg0KPiA+ICAjZGVmaW5lIFJUNTM5MF9QT1dFUl9CT1VORCAg
ICAgMHgyNw0KPiA+ICAjZGVmaW5lIFJUNTM5MF9GUkVRX09GRlNFVF9CT1VORCAgICAgICAweDVm
DQo+ID4gLQ0KPg0KPiBUaGlzIGVtcHR5IGxpbmUgY2FuIHN0YXkuDQo+DQo+ID4gKyNkZWZpbmUg
UlQzMjkwX1BPV0VSX0JPVU5EICAgICAweDI3ICNkZWZpbmUNCj4gPiArUlQzMjkwX0ZSRVFfT0ZG
U0VUX0JPVU5EICAgICAgIDB4NWYNCj4NCj4gTWlnaHQgYmUgd29ydGggdG8gYWRkIGFub3RoZXIg
ZW1wdHkgbGluZSBoZXJlLg0KPg0KPiA+ICBzdGF0aWMgdm9pZCBydDI4MDBfY29uZmlnX2NoYW5u
ZWxfcmY1M3h4KHN0cnVjdCBydDJ4MDBfZGV2DQo+ID4gKnJ0MngwMGRldiwNCj4gPiAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGllZWU4MDIxMV9jb25mICpj
b25mLA0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qg
cmZfY2hhbm5lbCAqcmYsIEBADQo+ID4gLTIwMjUsNiArMjAzNSw2NyBAQCBzdGF0aWMgdm9pZCBy
dDI4MDBfY29uZmlnX2NoYW5uZWxfcmY1M3h4KHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0Mngw
MGRldiwNCj4gPiAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMywgcmZjc3Ip
Ow0KPiA+ICB9DQo+ID4NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIHJ0MjgwMF9jb25maWdfY2hh
bm5lbF9yZjMyOTAoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiArKnJ0MngwMGRldiwNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBpZWVlODAyMTFfY29u
Zg0KPiA+ICsqY29uZiwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgIHN0cnVjdCByZl9jaGFubmVsICpyZiwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIHN0cnVjdCBjaGFubmVsX2luZm8gKmluZm8pDQo+ID4gK3sNCj4gPiAr
ICAgICAgIHU4IHJmY3NyOw0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDgsIHJmLT5yZjEpOw0KPiA+ICsgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgOSwgcmYtPnJmMyk7DQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4
MDBkZXYsIDExLCAmcmZjc3IpOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDgoJnJmY3Ny
LCBSRkNTUjExX1IsIHJmLT5yZjIpOw0KPiA+ICsgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgMTEsIHJmY3NyKTsNCj4gPiArDQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3JfcmVh
ZChydDJ4MDBkZXYsIDQ5LCAmcmZjc3IpOw0KPiA+ICsgICAgICAgaWYgKGluZm8tPmRlZmF1bHRf
cG93ZXIxID4gUlQ1MzkwX1BPV0VSX0JPVU5EKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBf
c2V0X2ZpZWxkOCgmcmZjc3IsIFJGQ1NSNDlfVFgsDQo+ID4gKyBSVDMyOTBfUE9XRVJfQk9VTkQp
Ow0KPiA+ICsgICAgICAgZWxzZQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxk
OCgmcmZjc3IsIFJGQ1NSNDlfVFgsDQo+ID4gKyBpbmZvLT5kZWZhdWx0X3Bvd2VyMSk7DQo+ID4g
KyAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0OSwgcmZjc3IpOw0KPiA+ICsN
Cj4gPiArICAgICAgIHJ0MjgwMF9yZmNzcl9yZWFkKHJ0MngwMGRldiwgMTcsICZyZmNzcik7DQo+
ID4gKyAgICAgICBpZiAocnQyeDAwZGV2LT5mcmVxX29mZnNldCA+IFJUMzI5MF9GUkVRX09GRlNF
VF9CT1VORCkNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDgoJnJmY3NyLCBS
RkNTUjE3X0NPREUsDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJUMzI5
MF9GUkVRX09GRlNFVF9CT1VORCk7DQo+ID4gKyAgICAgICBlbHNlDQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MngwMF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IxN19DT0RFLA0KPiA+ICsgcnQyeDAw
ZGV2LT5mcmVxX29mZnNldCk7DQo+ID4gKyAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCAxNywgcmZjc3IpOw0KPiA+ICsNCj4gPiArICAgICAgIGlmIChyZi0+Y2hhbm5lbCA8PSAx
NCkgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4MDBkZXYsIDMy
LCAmcmZjc3IpOw0KPiA+ICsgICAgICAgICAgICAgICByZmNzciAmPSB+MHhGODsNCj4gPiArICAg
ICAgICAgICAgICAgcmZjc3IgfD0gKDB4MWYgPDwgMyk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMyLCByZmNzcik7DQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MjgwMF9yZmNzcl9yZWFkKHJ0MngwMGRldiwgMzEsICZyZmNzcik7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJmY3NyICY9IH4weEY4Ow0KPiA+ICsgICAgICAgICAgICAgICByZmNzciB8PSAo
MHgxZiA8PCAzKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0Mngw
MGRldiwgMzEsIHJmY3NyKTsNCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIGlmIChyZi0+Y2hh
bm5lbCA9PSA2KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCA2OCwgMHgwYyk7DQo+ID4gKyAgICAgICAgICAgICAgIGVsc2UNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNjgsIDB4MGIp
Ow0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJmLT5jaGFubmVsID49IDEgJiYgcmYt
PmNoYW5uZWwgPD0gNikNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dy
aXRlKHJ0MngwMGRldiwgNTksIDB4MGYpOw0KPiA+ICsgICAgICAgICAgICAgICBlbHNlIGlmIChy
Zi0+Y2hhbm5lbCA+PSA3ICYmIHJmLT5jaGFubmVsIDw9IDExKQ0KPiA+ICsgICAgICAgICAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA1OSwgMHgwZSk7DQo+ID4gKyAg
ICAgICAgICAgICAgIGVsc2UgaWYgKHJmLT5jaGFubmVsID49IDEyICYmIHJmLT5jaGFubmVsIDw9
IDE0KQ0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAw
ZGV2LCA1OSwgMHgwZCk7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICsgICAgICAgcnQyODAw
X3JmY3NyX3JlYWQocnQyeDAwZGV2LCAzMCwgJnJmY3NyKTsNCj4gPiArICAgICAgIHJ0MngwMF9z
ZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IzMF9UWF9IMjBNLCAwKTsNCj4gPiArICAgICAgIHJ0Mngw
MF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IzMF9SWF9IMjBNLCAwKTsNCj4gPiArICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMwLCByZmNzcik7DQo+ID4gKw0KPiA+ICsgICAg
ICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAwZGV2LCAzLCAmcmZjc3IpOw0KPiA+ICsgICAgICAg
cnQyeDAwX3NldF9maWVsZDgoJnJmY3NyLCBSRkNTUjMwX1JGX0NBTElCUkFUSU9OLCAxKTsNCj4g
PiArICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMsIHJmY3NyKTsgfQ0KPg0K
PiBUaGlzIGZ1bmN0aW9uIGNvdWxkIHJlYWxseSB1c2UgYSBmZXcgY29tbWVudHMuDQo+DQo+ID4g
IHN0YXRpYyB2b2lkIHJ0MjgwMF9jb25maWdfY2hhbm5lbChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2LA0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBpZWVl
ODAyMTFfY29uZiAqY29uZiwNCj4gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBz
dHJ1Y3QgcmZfY2hhbm5lbCAqcmYsIEBAIC0yMDU4LDYNCj4gPiArMjEyOSw5IEBAIHN0YXRpYyB2
b2lkIHJ0MjgwMF9jb25maWdfY2hhbm5lbChzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBk
ZXYsDQo+ID4gICAgICAgIGNhc2UgUkY1MzkwOg0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9j
b25maWdfY2hhbm5lbF9yZjUzeHgocnQyeDAwZGV2LCBjb25mLCByZiwNCj4gPiBpbmZvKTsNCj4g
PiAgICAgICAgICAgICAgICBicmVhazsNCj4gPiArICAgICAgIGNhc2UgUkYzMjkwOg0KPiA+ICsg
ICAgICAgICAgICAgICBydDI4MDBfY29uZmlnX2NoYW5uZWxfcmYzMjkwKHJ0MngwMGRldiwgY29u
ZiwgcmYsDQo+ID4gKyBpbmZvKTsNCj4gPiArICAgICAgICAgICAgICAgYnJlYWs7DQo+ID4gICAg
ICAgIGRlZmF1bHQ6DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2NvbmZpZ19jaGFubmVsX3Jm
Mnh4eChydDJ4MDBkZXYsIGNvbmYsIHJmLA0KPiA+IGluZm8pOw0KPiA+ICAgICAgICB9DQo+ID4g
QEAgLTI1NDUsNiArMjYxOSw3IEBAIHZvaWQgcnQyODAwX3Zjb19jYWxpYnJhdGlvbihzdHJ1Y3Qg
cnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgIGNhc2UgUkY1MzcwOg0KPiA+
ICAgICAgICBjYXNlIFJGNTM3MjoNCj4gPiAgICAgICAgY2FzZSBSRjUzOTA6DQo+ID4gKyAgICAg
ICBjYXNlIFJGMzI5MDoNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3JfcmVhZChydDJ4
MDBkZXYsIDMsICZyZmNzcik7DQo+ID4gICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDgo
JnJmY3NyLCBSRkNTUjMwX1JGX0NBTElCUkFUSU9OLCAxKTsNCj4gPiAgICAgICAgICAgICAgICBy
dDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzLCByZmNzcik7IEBAIC0yNjc3LDcNCj4gPiAr
Mjc1Miw4IEBAIHN0YXRpYyB1OCBydDI4MDBfZ2V0X2RlZmF1bHRfdmdjKHN0cnVjdCBydDJ4MDBf
ZGV2DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0
MngwMGRldiwgUlQzMDkwKSB8fA0KPiA+ICAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQy
eDAwZGV2LCBSVDMzOTApIHx8DQo+ID4gICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDB4MWMgKyAo
MiAqIHJ0MngwMGRldi0+bG5hX2dhaW4pOw0KPiA+ICAgICAgICAgICAgICAgIGVsc2UNCj4gPiAg
ICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAweDJlICsgcnQyeDAwZGV2LT5sbmFfZ2Fpbjsg
QEAgLTI3NzEsOQ0KPiA+ICsyODQ3LDQ3IEBAIHN0YXRpYyBpbnQgcnQyODAwX2luaXRfcmVnaXN0
ZXJzKHN0cnVjdCBydDJ4MDBfZGV2DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgcnQyeDAw
X3NldF9maWVsZDMyKCZyZWcsIEJLT0ZGX1NMT1RfQ0ZHX0NDX0RFTEFZX1RJTUUsIDIpOw0KPiA+
ICAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBCS09GRl9TTE9UX0NGRywg
cmVnKTsNCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkp
IHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4ocnQyeDAw
ZGV2KTsNCj4NCj4gQ2FsbGluZyBhIHJ0MjgwMHBjaSBmdW5jdGlvbiBmcm9tIHdpdGhpbiBydDI4
MDBsaWIgZG9lc24ndCBsb29rDQo+IGNvcnJlY3QuIE1heWJlIHVzZSBhIG5ldyBjYWxsYmFjayBm
dW5jdGlvbiBmb3IgdGhhdD8NCj4NCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWQocnQyeDAwZGV2LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAg
ICAgICAgICAgIGlmIChydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBXTEFOX0VOKSA9PSAxKSB7DQo+
ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIFBDSUVf
QVBQMF9DTEtfUkVRLA0KPiA+ICsgMSk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQy
ODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwNCj4gPiArIFdMQU5fRlVOX0NUUkwsIHJlZyk7
DQo+ID4gKyAgICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIHJ0Mjgw
MF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgQ01CX0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAg
ICAgICAgICBpZiAoIShydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBMRE8wX0VOKSA9PSAxKSkgew0K
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmcmVnLCBMRE8w
X0VOLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIo
JnJlZywgTERPX0JHU0VMLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBf
cmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBDTUJfQ1RSTCwNCj4gPiArIHJlZyk7DQo+ID4gKyAg
ICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rl
cl9yZWFkKHJ0MngwMGRldiwgT1NDX0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBy
dDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywgT1NDX1JPU0NfRU4sIDEpOw0KPiA+ICsgICAgICAgICAg
ICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2LCBPU0NfQ1RSTCwgcmVnKTsNCj4g
PiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9TQ19ST1NDX0VOLCAx
KTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9TQ19DQUxf
UkVRLCAxKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIE9T
Q19SRUZfQ1lDTEUsIDB4MjcpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJf
d3JpdGUocnQyeDAwZGV2LCBPU0NfQ1RSTCwgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAgcnQy
ODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBDT0VYX0NGRzAsICZyZWcpOw0KPiA+ICsgICAg
ICAgICAgICAgICByZWcgJj0gfigweEZGMDAwMDAwKTsNCj4gPiArICAgICAgICAgICAgICAgcmVn
IHw9IDB4NUUwMDAwMDA7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0
ZShydDJ4MDBkZXYsIENPRVhfQ0ZHMCwgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAw
X3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwgQ09FWF9DRkcyLA0KPiA+ICsgMHgwMDE3OTM3Rik7
DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgUExM
X0NUUkwsICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJnJl
ZywgUExMX0NPTlRST0wsIDEpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJf
d3JpdGUocnQyeDAwZGV2LCBQTExfQ1RSTCwgcmVnKTsNCj4gPiArICAgICAgIH0NCj4gPiArDQo+
ID4gICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMwNzEpIHx8DQo+ID4gICAgICAg
ICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMwOTApIHx8DQo+ID4gLSAgICAgICAgICAgcnQy
eDAwX3J0KHJ0MngwMGRldiwgUlQzMzkwKSkgew0KPiA+ICsgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUMzM5MCkgfHwNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0Mngw
MGRldiwgUlQzMjkwKSkgew0KPg0KPiBJbmRlbnRpb24gbG9va3Mgc3RyYW5nZSBoZXJlLg0KPg0K
PiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5
MCkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0
MngwMGRldiwgVFhfU1dfQ0ZHMCwNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
IDB4MDAwMDA0MDQpOw0KPiA+ICsgICAgICAgICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAg
ICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwgVFhfU1dfQ0ZHMCwNCj4gPiAweDAw
MDAwNDAwKTsNCj4NCj4gSW5kZW50aW9uIGFnYWluLg0KPg0KPiA+ICAgICAgICAgICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4MDBkZXYsIFRYX1NXX0NGRzEsDQo+ID4gMHgwMDAwMDAw
MCk7DQo+ID4gICAgICAgICAgICAgICAgaWYgKHJ0MngwMF9ydF9yZXZfbHQocnQyeDAwZGV2LCBS
VDMwNzEsIFJFVl9SVDMwNzFFKQ0KPiA+IHx8IEBAIC0zMTg0LDcgKzMyOTgsOCBAQCBzdGF0aWMg
aW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QNCj4gPiBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+
ID4gICAgICAgICAgICAgICAgcmV0dXJuIC1FQUNDRVM7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgcnQyeDAw
X3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkgew0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQo
cnQyeDAwZGV2LCBSVDUzOTIpICAgIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3JlYWQo
cnQyeDAwZGV2LCA0LCAmdmFsdWUpOw0KPiA+ICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmll
bGQ4KCZ2YWx1ZSwgQkJQNF9NQUNfSUZfQ1RSTCwgMSk7DQo+ID4gICAgICAgICAgICAgICAgcnQy
ODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDQsIHZhbHVlKTsgQEAgLTMxOTMsMjUNCj4gPiArMzMw
OCwzMiBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2KQ0KPiA+ICAgICAgICBpZiAocnQyODAwX2lzXzMwNXhfc29jKHJ0MngwMGRldikgfHwN
Cj4gPiAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzU3MikgfHwNCj4gPiAgICAg
ICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICBy
dDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+ICsgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUNTM5MikgfHwNCj4gPiArICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2
LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCAzMSwgMHgwOCk7DQo+ID4NCj4gPiAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYs
IDY1LCAweDJjKTsNCj4gPiAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY2LCAw
eDM4KTsNCj4gPg0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8
fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAgICAgICAg
ICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY4LCAweDBiKTsNCj4gPg0KPiA+ICAg
ICAgICBpZiAocnQyeDAwX3J0X3JldihydDJ4MDBkZXYsIFJUMjg2MCwgUkVWX1JUMjg2MEMpKSB7
DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDY5LCAweDE2
KTsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNzMsIDB4
MTIpOw0KPiA+ICAgICAgICB9IGVsc2UgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkg
fHwNCj4gPiAtICAgICAgICAgICAgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTIpKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRl
diwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4
MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0
MngwMGRldiwgNjksIDB4MTIpOw0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCA3MywgMHgxMyk7DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0
ZShydDJ4MDBkZXYsIDc1LCAweDQ2KTsNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dy
aXRlKHJ0MngwMGRldiwgNzYsIDB4MjgpOw0KPiA+ICsNCj4gPiArICAgICAgICAgICAgICAgaWYg
KHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDc3LCAweDU4KTsNCj4gPiArICAgICAgICAg
ICAgICAgZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCA3NywgMHg1OSk7DQo+DQo+IEluZGVudGlvbi4NCj4NCj4gPiAgICAgICAgfSBlbHNlIHsNCj4g
PiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgNjksIDB4MTIpOyBA
QCAtMzIzNyw5DQo+ID4gKzMzNTksMTcgQEAgc3RhdGljIGludCBydDI4MDBfaW5pdF9iYnAoc3Ry
dWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJw
X3dyaXRlKHJ0MngwMGRldiwgODEsIDB4MzcpOw0KPiA+ICAgICAgICB9DQo+ID4NCj4gPiArICAg
ICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gKyAgICAgICAgICAg
ICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA3NCwgMHgwYik7DQo+ID4gKyAgICAgICAg
ICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA3OSwgMHgxOCk7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4MCwgMHgwOSk7DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4MSwgMHgzMyk7DQo+ID4g
KyAgICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwg
ODIsIDB4NjIpOw0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8
fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTIpIHx8DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAgICAgICAg
ICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDgzLCAweDdhKTsNCj4gPiAgICAgICAg
ZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4Mywg
MHg2YSk7IEBAIC0zMjQ3LDEzDQo+ID4gKzMzNzcsMTUgQEAgc3RhdGljIGludCBydDI4MDBfaW5p
dF9iYnAoc3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgaWYgKHJ0Mngw
MF9ydF9yZXYocnQyeDAwZGV2LCBSVDI4NjAsIFJFVl9SVDI4NjBEKSkNCj4gPiAgICAgICAgICAg
ICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgODQsIDB4MTkpOw0KPiA+ICAgICAgICBl
bHNlIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAgICAgICAgICAg
ICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAg
ICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAg
ICAgICAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gICAg
ICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDg0LCAweDlhKTsNCj4gPiAg
ICAgICAgZWxzZQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2
LCA4NCwgMHg5OSk7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJU
NTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1Mzky
KSkNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0K
PiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKQ0KPiA+ICAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA4NiwgMHgzOCk7DQo+ID4g
ICAgICAgIGVsc2UNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRl
diwgODYsIDB4MDApOyBAQCAtMzI2NCw3DQo+ID4gKzMzOTYsOCBAQCBzdGF0aWMgaW50IHJ0Mjgw
MF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICBydDI4
MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgOTEsIDB4MDQpOw0KPiA+DQo+ID4gICAgICAgIGlmIChy
dDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gLSAgICAgICAgICAgICAgIHJ0Mngw
MF9ydChydDJ4MDBkZXYsIFJUNTM5MikpDQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChy
dDJ4MDBkZXYsIFJUNTM5MikgfHwNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0Mngw
MGRldiwgUlQzMjkwKSkNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0Mngw
MGRldiwgOTIsIDB4MDIpOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgcnQy
ODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDkyLCAweDAwKTsgQEAgLTMyODEsMTMNCj4gPiArMzQx
NCwxNSBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQy
eDAwZGV2KQ0KPiA+ICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSB8fA0K
PiA+ICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+ICAgICAg
ICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgIHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkgfHwNCj4gPiAgICAgICAgICAgIHJ0MjgwMF9pc18z
MDV4X3NvYyhydDJ4MDBkZXYpKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUo
cnQyeDAwZGV2LCAxMDMsIDB4YzApOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAg
ICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDEwMywgMHgwMCk7DQo+ID4NCj4gPiAgICAg
ICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwNCj4gPiAtICAgICAgICAgICAg
ICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiArICAgICAgICAgICAgICAgcnQy
eDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBf
cnQocnQyeDAwZGV2LCBSVDMyOTApKQ0KPiA+ICAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3Jp
dGUocnQyeDAwZGV2LCAxMDQsIDB4OTIpOw0KPiA+DQo+ID4gICAgICAgIGlmIChydDI4MDBfaXNf
MzA1eF9zb2MocnQyeDAwZGV2KSkgQEAgLTMyOTUsMTAgKzM0MzAsMTMgQEANCj4gPiBzdGF0aWMg
aW50IHJ0MjgwMF9pbml0X2JicChzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAg
ICAgICBlbHNlIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTApIHx8DQo+ID4gICAgICAg
ICAgICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiAgICAg
ICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA1LCAweDNjKTsNCj4gPiAr
ICAgICAgIGVsc2UgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxMDUsIDB4MWMpOw0KPiA+ICAg
ICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYs
IDEwNSwgMHgwNSk7DQo+ID4NCj4gPiAtICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTApKQ0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgfHwN
Cj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzMjkwKSkNCj4gPiAg
ICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA2LCAweDAzKTsNCj4g
PiAgICAgICAgZWxzZSBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSkNCj4gPiAgICAg
ICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTA2LCAweDEyKTsgQEAgLTMz
MDYsNw0KPiA+ICszNDQ0LDggQEAgc3RhdGljIGludCBydDI4MDBfaW5pdF9iYnAoc3RydWN0IHJ0
MngwMF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRl
KHJ0MngwMGRldiwgMTA2LCAweDM1KTsNCj4gPg0KPiA+ICAgICAgICBpZiAocnQyeDAwX3J0KHJ0
MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+IC0gICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAw
ZGV2LCBSVDUzOTIpKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBS
VDUzOTIpIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5
MCkpDQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDEyOCwg
MHgxMik7DQo+ID4NCj4gPiAgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5Mikp
IHsgQEAgLTMzMzEsNiArMzQ3MCwyNyBAQA0KPiA+IHN0YXRpYyBpbnQgcnQyODAwX2luaXRfYmJw
KHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgICAgICAgICAgcnQyODAw
X2JicF93cml0ZShydDJ4MDBkZXYsIDEzOCwgdmFsdWUpOw0KPiA+ICAgICAgICB9DQo+ID4NCj4g
PiArICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gKyAgICAg
ICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCA2NywgMHgyNCk7DQo+ID4gKyAg
ICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxNDMsIDB4MDQpOw0KPiA+
ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwgMTQyLCAweDk5KTsN
Cj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDE1MCwgMHgz
MCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQyeDAwZGV2LCAxNTEs
IDB4MmUpOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRlKHJ0MngwMGRldiwg
MTUyLCAweDIwKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBk
ZXYsIDE1MywgMHgzNCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9iYnBfd3JpdGUocnQy
eDAwZGV2LCAxNTQsIDB4NDApOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3dyaXRl
KHJ0MngwMGRldiwgMTU1LCAweDNiKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX2JicF93
cml0ZShydDJ4MDBkZXYsIDI1MywgMHgwNCk7DQo+ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBy
dDI4MDBfYmJwX3JlYWQocnQyeDAwZGV2LCA0NywgJnZhbHVlKTsNCj4gPiArICAgICAgICAgICAg
ICAgcnQyeDAwX3NldF9maWVsZDgoJnZhbHVlLCBSRkNTUjJfUkVTQ0FMX0VOLCAxKTsNCj4gPiAr
ICAgICAgICAgICAgICAgcnQyODAwX2JicF93cml0ZShydDJ4MDBkZXYsIDQ3LCB2YWx1ZSk7DQo+
ID4gKw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJwX3JlYWQocnQyeDAwZGV2LCAzLCAm
dmFsdWUpOw0KPiA+ICsgICAgICAgICAgICAgICB2YWx1ZSAmPSAofjB4YzApOw0KPiA+ICsgICAg
ICAgICAgICAgICB2YWx1ZSB8PSAweGMwOw0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfYmJw
X3dyaXRlKHJ0MngwMGRldiwgMywgdmFsdWUpOw0KPiA+ICsgICAgICAgfQ0KPiA+ICAgICAgICBp
ZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkwKSB8fA0KPiA+ICAgICAgICAgICAgICAgIHJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpIHsNCj4gPiAgICAgICAgICAgICAgICBpbnQgYW50
LCBkaXZfbW9kZTsNCj4gPiBAQCAtMzQ2Nyw2ICszNjI3LDcgQEAgc3RhdGljIGludCBydDI4MDBf
aW5pdF9yZmNzcihzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAg
ICAgICAhcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzNTcyKSAmJg0KPiA+ICAgICAgICAgICAgIXJ0
MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MCkgJiYNCj4gPiAgICAgICAgICAgICFydDJ4MDBfcnQo
cnQyeDAwZGV2LCBSVDUzOTIpICYmDQo+ID4gKyAgICAgICAgICAgIXJ0MngwMF9ydChydDJ4MDBk
ZXYsIFJUMzI5MCkgJiYNCj4gPiAgICAgICAgICAgICFydDI4MDBfaXNfMzA1eF9zb2MocnQyeDAw
ZGV2KSkNCj4gPiAgICAgICAgICAgICAgICByZXR1cm4gMDsNCj4gPg0KPiA+IEBAIC0zNDc0LDcg
KzM2MzUsOCBAQCBzdGF0aWMgaW50IHJ0MjgwMF9pbml0X3JmY3NyKHN0cnVjdCBydDJ4MDBfZGV2
DQo+ID4gKnJ0MngwMGRldikNCj4gPiAgICAgICAgICogSW5pdCBSRiBjYWxpYnJhdGlvbi4NCj4g
PiAgICAgICAgICovDQo+ID4gICAgICAgIGlmIChydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDUzOTAp
IHx8DQo+ID4gLSAgICAgICAgICAgICAgIHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUNTM5MikpIHsN
Cj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3J0KHJ0MngwMGRldiwgUlQ1MzkyKSB8fA0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfcnQocnQyeDAwZGV2LCBSVDMyOTApKSB7DQo+ID4gICAg
ICAgICAgICAgICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAwZGV2LCAyLCAmcmZjc3IpOw0KPiA+
ICAgICAgICAgICAgICAgIHJ0MngwMF9zZXRfZmllbGQ4KCZyZmNzciwgUkZDU1IyX1JFU0NBTF9F
TiwgMSk7DQo+ID4gICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwg
MiwgcmZjc3IpOyBAQCAtMzc1Miw2DQo+ID4gKzM5MTQsNTMgQEAgc3RhdGljIGludCBydDI4MDBf
aW5pdF9yZmNzcihzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAg
ICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA2MSwgMHg5MSk7
DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2
LCA2MiwgMHgzOSk7DQo+ID4gICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3Jp
dGUocnQyeDAwZGV2LCA2MywgMHgwNyk7DQo+ID4gKyAgICAgICB9IGVsc2UgaWYgKHJ0MngwMF9y
dChydDJ4MDBkZXYsIFJUMzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4
MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxLCAweDBmKTsNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAyLCAweDgwKTsNCj4gPiArICAg
ICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzLCAweDA4
KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCA0LCAweDAwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jf
d3JpdGUocnQyeDAwZGV2LCA2LCAweGEwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBy
dDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA4LCAweGYzKTsNCj4gPiArICAgICAgICAgICAg
ICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA5LCAweDAyKTsNCj4gPiAr
ICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxMCwg
MHg1Myk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0
MngwMGRldiwgMTEsIDB4NGEpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9y
ZmNzcl93cml0ZShydDJ4MDBkZXYsIDEyLCAweDQ2KTsNCj4gPiArICAgICAgICAgICAgICAgICAg
ICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAxMywgMHg5Zik7DQo+ID4gKyAgICAg
ICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMTgsIDB4MDIp
Ow0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBk
ZXYsIDIyLCAweDIwKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jf
d3JpdGUocnQyeDAwZGV2LCAyNSwgMHg4Myk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg
cnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMjYsIDB4ODIpOw0KPiA+ICsgICAgICAgICAg
ICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDI3LCAweDA5KTsNCj4g
PiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAy
OSwgMHgxMCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRl
KHJ0MngwMGRldiwgMzAsIDB4MTApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0Mjgw
MF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMxLCAweDgwKTsNCj4gPiArICAgICAgICAgICAgICAg
ICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCAzMiwgMHg4MCk7DQo+ID4gKyAg
ICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMzMsIDB4
MDApOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4
MDBkZXYsIDM0LCAweDA1KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZj
c3Jfd3JpdGUocnQyeDAwZGV2LCAzNSwgMHgxMik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgMzYsIDB4MDApOw0KPiA+ICsgICAgICAg
ICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDM4LCAweDg1KTsN
Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2
LCAzOSwgMHgxYik7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dy
aXRlKHJ0MngwMGRldiwgNDAsIDB4MGIpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0
MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDQxLCAweGJiKTsNCj4gPiArICAgICAgICAgICAg
ICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0MiwgMHhkNSk7DQo+ID4g
KyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNDMs
IDB4N2IpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDQ0LCAweDBlKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBf
cmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA0NSwgMHhhMik7DQo+ID4gKyAgICAgICAgICAgICAgICAg
ICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNDYsIDB4NzMpOw0KPiA+ICsgICAg
ICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDQ3LCAweDAw
KTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAw
ZGV2LCA0OCwgMHgxMCk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3Ny
X3dyaXRlKHJ0MngwMGRldiwgNDksIDB4OTgpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAg
IHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDUyLCAweDM4KTsNCj4gPiArICAgICAgICAg
ICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA1MywgMHgwMCk7DQo+
ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwg
NTQsIDB4NzgpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0
ZShydDJ4MDBkZXYsIDU1LCAweDQzKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4
MDBfcmZjc3Jfd3JpdGUocnQyeDAwZGV2LCA1NiwgMHgwMik7DQo+ID4gKyAgICAgICAgICAgICAg
ICAgICAgICAgcnQyODAwX3JmY3NyX3dyaXRlKHJ0MngwMGRldiwgNTcsIDB4ODApOw0KPiA+ICsg
ICAgICAgICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDU4LCAw
eDdmKTsNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBydDI4MDBfcmZjc3Jfd3JpdGUocnQy
eDAwZGV2LCA1OSwgMHgwOSk7DQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcnQyODAwX3Jm
Y3NyX3dyaXRlKHJ0MngwMGRldiwgNjAsIDB4NDUpOw0KPiA+ICsgICAgICAgICAgICAgICAgICAg
ICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDYxLCAweGMxKTsNCj4gPiAgICAgICAg
fQ0KPiA+DQo+ID4gICAgICAgIGlmIChydDJ4MDBfcnRfcmV2X2x0KHJ0MngwMGRldiwgUlQzMDcw
LCBSRVZfUlQzMDcwRikpIHsgQEANCj4gPiAtMzkzNSw2ICs0MTQ0LDEyIEBAIHN0YXRpYyBpbnQg
cnQyODAwX2luaXRfcmZjc3Ioc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+
ICAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShydDJ4MDBkZXYsIDMwLCByZmNzcik7
DQo+ID4gICAgICAgIH0NCj4gPg0KPiA+ICsgICAgICAgaWYgKHJ0MngwMF9ydChydDJ4MDBkZXYs
IFJUMzI5MCkpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JmY3NyX3JlYWQocnQyeDAw
ZGV2LCAyOSwgJnJmY3NyKTsNCj4gPiArICAgICAgICAgICAgICAgcmZjc3IgPSAoKHJmY3NyICYg
fjB4YzApIHwgMHhjMCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZmNzcl93cml0ZShy
dDJ4MDBkZXYsIDI5LCByZmNzcik7DQo+ID4gKyAgICAgICB9DQo+ID4gKw0KPiA+ICAgICAgICBy
ZXR1cm4gMDsNCj4gPiAgfQ0KPiA+DQo+ID4gQEAgLTQwMjYsOSArNDI0MSwxMyBAQCBFWFBPUlRf
U1lNQk9MX0dQTChydDI4MDBfZGlzYWJsZV9yYWRpbyk7DQo+ID4gIGludCBydDI4MDBfZWZ1c2Vf
ZGV0ZWN0KHN0cnVjdCBydDJ4MDBfZGV2ICpydDJ4MDBkZXYpDQo+ID4gIHsNCj4gPiAgICAgICAg
dTMyIHJlZzsNCj4gPiArICAgICAgIHUxNiBlZnVzZV9jdHJsX3JlZzsNCj4gPiArICAgICAgIGVm
dXNlX2N0cmxfcmVnID0gRUZVU0VfQ1RSTDsNCj4gPg0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lz
dGVyX3JlYWQocnQyeDAwZGV2LCBFRlVTRV9DVFJMLCAmcmVnKTsNCj4gPiArICAgICAgIGlmIChy
dDJ4MDBkZXYtPmNoaXAubWFjX3ZlcnNpb24gPT0gMHgzMjkwKQ0KPiA+ICsgICAgICAgICAgICAg
ICBlZnVzZV9jdHJsX3JlZyA9IDB4MjQ7DQo+DQo+IFRoaXMgc2hvdWxkbid0IGJlIGhhcmRjb2Rl
ZC4gUGxlYXNlIGFkZCBhIGRlZmluZSB0byBydDI4MDAuaC4NCj4NCj4gPg0KPiA+ICsgICAgICAg
cnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LCBlZnVzZV9jdHJsX3JlZywgJnJlZyk7DQo+
ID4gICAgICAgIHJldHVybiBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBFRlVTRV9DVFJMX1BSRVNF
TlQpOw0KPiA+ICB9DQo+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMF9lZnVzZV9kZXRlY3Qp
Ow0KPiA+IEBAIC00MDM3LDI2ICs0MjU2LDQ0IEBAIHN0YXRpYyB2b2lkIHJ0MjgwMF9lZnVzZV9y
ZWFkKHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0MngwMGRldiwgdW5zaWduZWQgaW50IGkpDQo+
ID4gIHsNCj4gPiAgICAgICAgdTMyIHJlZzsNCj4gPg0KPiA+ICsgICAgICAgdTE2IGVmdXNlX2N0
cmxfcmVnOw0KPiA+ICsgICAgICAgdTE2IGVmdXNlX2RhdGEwX3JlZzsNCj4gPiArICAgICAgIHUx
NiBlZnVzZV9kYXRhMV9yZWc7DQo+ID4gKyAgICAgICB1MTYgZWZ1c2VfZGF0YTJfcmVnOw0KPiA+
ICsgICAgICAgdTE2IGVmdXNlX2RhdGEzX3JlZzsNCj4gPiArDQo+ID4gKyAgICAgICBlZnVzZV9j
dHJsX3JlZyA9IEVGVVNFX0NUUkw7DQo+ID4gKyAgICAgICBlZnVzZV9kYXRhMF9yZWcgPSBFRlVT
RV9EQVRBMDsNCj4gPiArICAgICAgIGVmdXNlX2RhdGExX3JlZyA9IEVGVVNFX0RBVEExOw0KPiA+
ICsgICAgICAgZWZ1c2VfZGF0YTJfcmVnID0gRUZVU0VfREFUQTI7DQo+ID4gKyAgICAgICBlZnVz
ZV9kYXRhM19yZWcgPSBFRlVTRV9EQVRBMzsNCj4gPiArDQo+ID4gKyAgICAgICBpZiAocnQyeDAw
ZGV2LT5jaGlwLm1hY192ZXJzaW9uID09IDB4MzI5MCkgew0KPiA+ICsgICAgICAgICAgICAgICBl
ZnVzZV9jdHJsX3JlZyA9IDB4MjQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEzX3Jl
ZyA9IDB4Mjg7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEyX3JlZyA9IGVmdXNlX2Rh
dGEzX3JlZyArIDQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGExX3JlZyA9IGVmdXNl
X2RhdGEyX3JlZyArIDQ7DQo+ID4gKyAgICAgICAgICAgICAgIGVmdXNlX2RhdGEwX3JlZyA9IGVm
dXNlX2RhdGExX3JlZyArIDQ7DQo+ID4gKyAgICAgICB9DQo+DQo+IFNhbWUgaGVyZSwgdGhlIHJl
Z2lzdGVyIG9mZnNldHMgd291bGQgbWFrZSBzZW5zZSBhcyBkZWZpbmVzLg0KPg0KPiA+ICAgICAg
ICBtdXRleF9sb2NrKCZydDJ4MDBkZXYtPmNzcl9tdXRleCk7DQo+ID4NCj4gPiAtICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBFRlVTRV9DVFJMLCAmcmVnKTsNCj4g
PiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVzZV9jdHJs
X3JlZywgJnJlZyk7DQo+ID4gICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmcmVnLCBFRlVTRV9D
VFJMX0FERFJFU1NfSU4sIGkpOw0KPiA+ICAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywg
RUZVU0VfQ1RSTF9NT0RFLCAwKTsNCj4gPiAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcs
IEVGVVNFX0NUUkxfS0lDSywgMSk7DQo+ID4gLSAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGVf
bG9jayhydDJ4MDBkZXYsIEVGVVNFX0NUUkwsIHJlZyk7DQo+ID4gKyAgICAgICBydDI4MDBfcmVn
aXN0ZXJfd3JpdGVfbG9jayhydDJ4MDBkZXYsIGVmdXNlX2N0cmxfcmVnLCByZWcpOw0KPiA+DQo+
ID4gICAgICAgIC8qIFdhaXQgdW50aWwgdGhlIEVFUFJPTSBoYXMgYmVlbiBsb2FkZWQgKi8NCj4g
PiAtICAgICAgIHJ0MjgwMF9yZWdidXN5X3JlYWQocnQyeDAwZGV2LCBFRlVTRV9DVFJMLCBFRlVT
RV9DVFJMX0tJQ0ssDQo+ID4gJnJlZyk7DQo+ID4gLQ0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2J1
c3lfcmVhZChydDJ4MDBkZXYsIGVmdXNlX2N0cmxfcmVnLA0KPiA+ICsgRUZVU0VfQ1RSTF9LSUNL
LCAmcmVnKTsNCj4gPiAgICAgICAgLyogQXBwYXJlbnRseSB0aGUgZGF0YSBpcyByZWFkIGZyb20g
ZW5kIHRvIHN0YXJ0ICovDQo+ID4gLSAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZF9sb2NrKHJ0
MngwMGRldiwgRUZVU0VfREFUQTMsICZyZWcpOw0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWRfbG9jayhydDJ4MDBkZXYsIGVmdXNlX2RhdGEzX3JlZywgJnJlZyk7DQo+ID4gICAgICAg
IC8qIFRoZSByZXR1cm5lZCB2YWx1ZSBpcyBpbiBDUFUgb3JkZXIsIGJ1dCBlZXByb20gaXMgbGUg
Ki8NCj4gPiAgICAgICAgKih1MzIgKikmcnQyeDAwZGV2LT5lZXByb21baV0gPSBjcHVfdG9fbGUz
MihyZWcpOw0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWRfbG9jayhydDJ4MDBkZXYs
IEVGVVNFX0RBVEEyLCAmcmVnKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xv
Y2socnQyeDAwZGV2LCBlZnVzZV9kYXRhMl9yZWcsICZyZWcpOw0KPiA+ICAgICAgICAqKHUzMiAq
KSZydDJ4MDBkZXYtPmVlcHJvbVtpICsgMl0gPSBjcHVfdG9fbGUzMihyZWcpOw0KPiA+IC0gICAg
ICAgcnQyODAwX3JlZ2lzdGVyX3JlYWRfbG9jayhydDJ4MDBkZXYsIEVGVVNFX0RBVEExLCAmcmVn
KTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVz
ZV9kYXRhMV9yZWcsICZyZWcpOw0KPiA+ICAgICAgICAqKHUzMiAqKSZydDJ4MDBkZXYtPmVlcHJv
bVtpICsgNF0gPSBjcHVfdG9fbGUzMihyZWcpOw0KPiA+IC0gICAgICAgcnQyODAwX3JlZ2lzdGVy
X3JlYWRfbG9jayhydDJ4MDBkZXYsIEVGVVNFX0RBVEEwLCAmcmVnKTsNCj4gPiArICAgICAgIHJ0
MjgwMF9yZWdpc3Rlcl9yZWFkX2xvY2socnQyeDAwZGV2LCBlZnVzZV9kYXRhMF9yZWcsICZyZWcp
Ow0KPiA+ICAgICAgICAqKHUzMiAqKSZydDJ4MDBkZXYtPmVlcHJvbVtpICsgNl0gPSBjcHVfdG9f
bGUzMihyZWcpOw0KPiA+DQo+ID4gICAgICAgIG11dGV4X3VubG9jaygmcnQyeDAwZGV2LT5jc3Jf
bXV0ZXgpOw0KPiA+IEBAIC00MjE4LDkgKzQ0NTUsMTMgQEAgaW50IHJ0MjgwMF9pbml0X2VlcHJv
bShzdHJ1Y3QgcnQyeDAwX2Rldg0KPiA+ICpydDJ4MDBkZXYpDQo+ID4gICAgICAgICAqIFJUMjh4
eC9SVDMweHg6IGRlZmluZWQgaW4gIkVFUFJPTV9OSUNfQ09ORjBfUkZfVFlQRSIgZmllbGQNCj4g
PiAgICAgICAgICogUlQ1M3h4OiBkZWZpbmVkIGluICJFRVBST01fQ0hJUF9JRCIgZmllbGQNCj4g
PiAgICAgICAgICovDQo+ID4gKyAgICAgICBpZiAocnQyeDAwZGV2LT5jaGlwLm1hY192ZXJzaW9u
ID09IDB4MzI5MCkNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQy
eDAwZGV2LCBNQUNfQ1NSMF8zMjkwLA0KPiA+ICsgJnJlZyk7DQo+ID4gKyAgICAgICBlbHNlDQo+
ID4gICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgTUFDX0NTUjAsICZyZWcp
Ow0KPg0KPiBJbmRlbnRpb24uDQo+DQo+ID4gICAgICAgIGlmIChydDJ4MDBfZ2V0X2ZpZWxkMzIo
cmVnLCBNQUNfQ1NSMF9DSElQU0VUKSA9PSBSVDUzOTAgfHwNCj4gPiAtICAgICAgICAgICAgICAg
cnQyeDAwX2dldF9maWVsZDMyKHJlZywgTUFDX0NTUjBfQ0hJUFNFVCkgPT0gUlQ1MzkyKQ0KPiA+
ICsgICAgICAgICAgICAgICBydDJ4MDBfZ2V0X2ZpZWxkMzIocmVnLCBNQUNfQ1NSMF9DSElQU0VU
KSA9PSBSVDUzOTINCj4gPiArIHx8DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MngwMF9nZXRfZmll
bGQzMihyZWcsIE1BQ19DU1IwX0NISVBTRVQpID09IFJUMzI5MCkNCj4gPiAgICAgICAgICAgICAg
ICBydDJ4MDBfZWVwcm9tX3JlYWQocnQyeDAwZGV2LCBFRVBST01fQ0hJUF9JRCwNCj4gPiAmdmFs
dWUpOw0KPiA+ICAgICAgICBlbHNlDQo+ID4gICAgICAgICAgICAgICAgdmFsdWUgPSBydDJ4MDBf
Z2V0X2ZpZWxkMTYoZWVwcm9tLA0KPiA+IEVFUFJPTV9OSUNfQ09ORjBfUkZfVFlQRSk7IEBAIC00
MjM5LDYgKzQ0ODAsNyBAQCBpbnQNCj4gPiBydDI4MDBfaW5pdF9lZXByb20oc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldikNCj4gPiAgICAgICAgY2FzZSBSVDM1NzI6DQo+ID4gICAgICAgIGNh
c2UgUlQ1MzkwOg0KPiA+ICAgICAgICBjYXNlIFJUNTM5MjoNCj4gPiArICAgICAgIGNhc2UgUlQz
MjkwOg0KPiA+ICAgICAgICAgICAgICAgIGJyZWFrOw0KPiA+ICAgICAgICBkZWZhdWx0Og0KPiA+
ICAgICAgICAgICAgICAgIEVSUk9SKHJ0MngwMGRldiwgIkludmFsaWQgUlQgY2hpcHNldCAweCUw
NHgNCj4gPiBkZXRlY3RlZC5cbiIsIHJ0MngwMGRldi0+Y2hpcC5ydCk7IEBAIC00MjU5LDYgKzQ1
MDEsNyBAQCBpbnQNCj4gPiBydDI4MDBfaW5pdF9lZXByb20oc3RydWN0IHJ0MngwMF9kZXYgKnJ0
MngwMGRldikNCj4gPiAgICAgICAgY2FzZSBSRjUzNzA6DQo+ID4gICAgICAgIGNhc2UgUkY1Mzcy
Og0KPiA+ICAgICAgICBjYXNlIFJGNTM5MDoNCj4gPiArICAgICAgIGNhc2UgUkYzMjkwOg0KPiA+
ICAgICAgICAgICAgICAgIGJyZWFrOw0KPiA+ICAgICAgICBkZWZhdWx0Og0KPiA+ICAgICAgICAg
ICAgICAgIEVSUk9SKHJ0MngwMGRldiwgIkludmFsaWQgUkYgY2hpcHNldCAweCUwNHgNCj4gPiBk
ZXRlY3RlZC5cbiIsIEBAIC00NTcyLDcgKzQ4MTUsOCBAQCBpbnQgcnQyODAwX3Byb2JlX2h3X21v
ZGUoc3RydWN0DQo+ID4gcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICAgICAgICAg
ICAgIHJ0MngwMF9yZihydDJ4MDBkZXYsIFJGMzMyMCkgfHwNCj4gPiAgICAgICAgICAgICAgICAg
ICBydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjUzNzApIHx8DQo+ID4gICAgICAgICAgICAgICAgICAg
cnQyeDAwX3JmKHJ0MngwMGRldiwgUkY1MzcyKSB8fA0KPiA+IC0gICAgICAgICAgICAgICAgICBy
dDJ4MDBfcmYocnQyeDAwZGV2LCBSRjUzOTApKSB7DQo+ID4gKyAgICAgICAgICAgICAgICAgIHJ0
MngwMF9yZihydDJ4MDBkZXYsIFJGNTM5MCkgfHwNCj4gPiArICAgICAgICAgICAgICAgICAgcnQy
eDAwX3JmKHJ0MngwMGRldiwgUkYzMjkwKSkgew0KPiA+ICAgICAgICAgICAgICAgIHNwZWMtPm51
bV9jaGFubmVscyA9IDE0Ow0KPiA+ICAgICAgICAgICAgICAgIHNwZWMtPmNoYW5uZWxzID0gcmZf
dmFsc18zeDsNCj4gPiAgICAgICAgfSBlbHNlIGlmIChydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjMw
NTIpKSB7IEBAIC00NjU4LDYgKzQ5MDIsNw0KPiA+IEBAIGludCBydDI4MDBfcHJvYmVfaHdfbW9k
ZShzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KQ0KPiA+ICAgICAgICBjYXNlIFJGNTM3MDoN
Cj4gPiAgICAgICAgY2FzZSBSRjUzNzI6DQo+ID4gICAgICAgIGNhc2UgUkY1MzkwOg0KPiA+ICsg
ICAgICAgY2FzZSBSRjMyOTA6DQo+ID4gICAgICAgICAgICAgICAgX19zZXRfYml0KENBUEFCSUxJ
VFlfVkNPX1JFQ0FMSUJSQVRJT04sDQo+ID4gJnJ0MngwMGRldi0+Y2FwX2ZsYWdzKTsNCj4gPiAg
ICAgICAgICAgICAgICBicmVhazsNCj4gPiAgICAgICAgfQ0KPiA+IEBAIC00ODg1LDYgKzUxMzAs
MTAyIEBAIGludCBydDI4MDBfZ2V0X3N1cnZleShzdHJ1Y3QgaWVlZTgwMjExX2h3DQo+ID4gKmh3
LCBpbnQgaWR4LA0KPiA+ICB9DQo+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMF9nZXRfc3Vy
dmV5KTsNCj4gPg0KPiA+ICtpbnQgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4oc3RydWN0IHJ0
MngwMF9kZXYgKnJ0MngwMGRldikNCj4NCj4gcnQyODAwcGNpIGZ1bmN0aW9ucyBzaG91bGQgbGl2
ZSBpbiBydDI4MDBwY2kuYywgbm90IGluIHJ0MjgwMGxpYi5jLg0KPg0KPiA+ICt7DQo+ID4gKyAg
ICAgICB1MzIgd2xhbmZ1bmN0cmw7DQo+ID4gKyAgICAgICB1MzIgZ2xvY2ZnOw0KPiA+ICsgICAg
ICAgdTMyIGNtYmN0cmw7DQo+ID4gKyAgICAgICB1OCBpbmRleDsNCj4gPiArICAgICAgIGludCBp
Ow0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9yZWFkKHJ0MngwMGRldiwgV0xB
Tl9GVU5fQ1RSTCwNCj4gPiArICZ3bGFuZnVuY3RybCk7DQo+ID4gKyAgICAgICBydDJ4MDBfc2V0
X2ZpZWxkMzIoJndsYW5mdW5jdHJsLCBXTEFOX0dQSU9fT1VUX09FX0JJVF9BTEwsDQo+ID4gKyAw
eGZmKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0cmwsIEZSQ19X
TF9BTlRfU0VULCAxKTsNCj4gPiArICAgICAgIGlmICgocnQyeDAwX2dldF9maWVsZDMyKHdsYW5m
dW5jdHJsLCBXTEFOX0VOKSA9PSAxKSkNCj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIDA7DQo+
ID4gKw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgV0xBTl9D
TEtfRU4sIDApOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwg
V0xBTl9FTiwgMSk7DQo+ID4gKyAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2
LCBXTEFOX0ZVTl9DVFJMLA0KPiA+ICsgd2xhbmZ1bmN0cmwpOw0KPiA+ICsgICAgICAgdWRlbGF5
KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsNCj4gPiArICAgICAgIGluZGV4ID0gMDsNCj4g
PiArICAgICAgIGNtYmN0cmwgPSAwOw0KPiA+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IFJFR0lT
VEVSX0JVU1lfQ09VTlQ7IGkrKykgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0
ZXJfcmVhZChydDJ4MDBkZXYsIENNQl9DVFJMLCAmY21iY3RybCk7DQo+ID4gKyAgICAgICAgICAg
ICAgIGlmICgocnQyeDAwX2dldF9maWVsZDMyKGNtYmN0cmwsIFBMTF9MRCkgPT0gMSkgJiYNCj4g
PiArICAgICAgICAgICAgICAgICAgICAgICAocnQyeDAwX2dldF9maWVsZDMyKGNtYmN0cmwsIFhU
QUxfUkRZKSA9PQ0KPiA+ICsgMSkpDQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7
DQo+ID4gKyAgICAgICAgICAgICAgIHVkZWxheShSRUdJU1RFUl9CVVNZX0RFTEFZKTsNCj4gPiAr
ICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICBpZiAoaW5kZXggPj0gUkVHSVNURVJfQlVTWV9D
T1VOVCkgew0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfd3JpdGUocnQyeDAw
ZGV2LCAweDU4LCAweDAxOCk7DQo+ID4gKyAgICAgICAgICAgICAgIHVkZWxheShSRUdJU1RFUl9C
VVNZX0RFTEFZKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0
MngwMGRldiwgMHg1OCwgMHg0MTgpOw0KPiA+ICsgICAgICAgICAgICAgICB1ZGVsYXkoUkVHSVNU
RVJfQlVTWV9ERUxBWSk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0
ZShydDJ4MDBkZXYsIDB4NTgsIDB4NjE4KTsNCj4gPiArICAgICAgICAgICAgICAgdWRlbGF5KFJF
R0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsgICAgICAgfSBlbHNlIHsNCj4gPiArICAgICAgICAg
ICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAwZGV2LA0KPiA+ICsgICAgICAgICAgICAg
ICAgICAgICAgIFdQRE1BX0dMT19DRkcsICZnbG9jZmcpOw0KPiA+ICsgICAgICAgfQ0KPiA+ICsg
ICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgUENJRV9BUFAwX0NMS19SRVEs
IDApOw0KPiA+ICsgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZ3bGFuZnVuY3RybCwgV0xBTl9D
TEtfRU4sIDEpOw0KPiA+ICsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsDQo+ID4gKyAgICAgICAgICAgICAgIFdMQU5fRlVOX0NUUkwsICh3bGFuZnVuY3RybCB8
IDB4OCkpOw0KPiA+ICsgICAgICAgdWRlbGF5KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0KPiA+ICsg
ICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwNCj4gPiArICAgICAgICAgICAg
ICAgV0xBTl9GVU5fQ1RSTCwgKHdsYW5mdW5jdHJsICY9ICh+MHg4KSkpOw0KPiA+ICsgICAgICAg
dWRlbGF5KDIpOw0KPiA+ICsgICAgICAgcnQyODAwX3JlZ2lzdGVyX3dyaXRlKHJ0MngwMGRldiwN
Cj4gPiArICAgICAgICAgICAgICAgSU5UX1NPVVJDRV9DU1IsIDB4N2ZmZmZmZmYpOw0KPiA+ICsg
ICAgICAgcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJPTF9HUEwocnQyODAwcGNp
XzMyOTBfZW5hYmxlX3dsYW4pOw0KPiA+ICsNCj4gPiAraW50IHJ0MjgwMHBjaV8zMjkwX2Rpc2Fi
bGVfd2xhbihzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2KSB7DQo+ID4gKyAgICAgICB1MzIg
d2xhbmZ1bmN0cmw7DQo+ID4gKyAgICAgICB1MzIgZ2xvY2ZnOw0KPiA+ICsgICAgICAgdTMyIHJl
ZzsNCj4gPiArICAgICAgIGludCBpOw0KPiA+ICsNCj4gPiArICAgICAgIC8qIENoYW5nZSBJbnRl
cnJ1cHQgYml0bWFzay4gKi8NCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsIElOVF9NQVNLX0NTUiwgMHgwKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl9y
ZWFkKHJ0MngwMGRldiwgV1BETUFfR0xPX0NGRywgJmdsb2NmZyk7DQo+ID4gKyAgICAgICBydDJ4
MDBfc2V0X2ZpZWxkMzIoJmdsb2NmZywgV1BETUFfR0xPX0NGR19FTkFCTEVfUlhfRE1BLCAwKTsN
Cj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4MDBkZXYsIFdQRE1BX0dMT19D
RkcsIGdsb2NmZyk7DQo+ID4gKw0KPiA+ICsgICAgICAgLyogd2FpdCBSWCBETUEgaWRsZSAqLw0K
PiA+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IFJFR0lTVEVSX0JVU1lfQ09VTlQ7IGkrKykgew0K
PiA+ICsgICAgICAgICAgICAgICBydDI4MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIFdQRE1B
X0dMT19DRkcsDQo+ID4gKyAmZ2xvY2ZnKTsNCj4gPiArICAgICAgICAgICAgICAgaWYgKChydDJ4
MDBfZ2V0X2ZpZWxkMzIoZ2xvY2ZnLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIFdQRE1B
X0dMT19DRkdfUlhfRE1BX0JVU1kpID09IDApIHx8DQo+ID4gKyAgICAgICAgICAgICAgICAgICAg
ICAgKGdsb2NmZyA9PSAweEZGRkZGRkZGKSkNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBi
cmVhazsNCj4gPiArICAgICAgICAgICAgICAgdWRlbGF5KFJFR0lTVEVSX0JVU1lfREVMQVkpOw0K
PiA+ICsgICAgICAgfQ0KPiA+ICsNCj4gPiArICAgICAgIGlmIChpID49IFJFR0lTVEVSX0JVU1lf
Q09VTlQpIHsNCj4gPiArICAgICAgICAgICAgICAgcnQyODAwX3JlZ2lzdGVyX3JlYWQocnQyeDAw
ZGV2LCBBVVRPV0FLRVVQX0NGRywNCj4gPiArICZyZWcpOw0KPiA+ICsgICAgICAgICAgICAgICBy
dDJ4MDBfc2V0X2ZpZWxkMzIoJnJlZywNCj4gPiArIEFVVE9XQUtFVVBfQ0ZHX0FVVE9fTEVBRF9U
SU1FLCAwKTsNCj4gPiArICAgICAgICAgICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsDQo+
ID4gKyBBVVRPV0FLRVVQX0NGR19UQkNOX0JFRk9SRV9XQUtFLCAwKTsNCj4gPiArICAgICAgICAg
ICAgICAgcnQyeDAwX3NldF9maWVsZDMyKCZyZWcsIEFVVE9XQUtFVVBfQ0ZHX0FVVE9XQUtFLA0K
PiA+ICsgMCk7DQo+ID4gKyAgICAgICAgICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93cml0ZShydDJ4
MDBkZXYsIEFVVE9XQUtFVVBfQ0ZHLA0KPiA+ICsgcmVnKTsNCj4gPiArICAgICAgICAgICAgICAg
cmV0dXJuIDA7DQo+ID4gKyAgICAgICAgICAgICAgIH0NCj4gPiArDQo+ID4gKyAgICAgICBydDI4
MDBfcmVnaXN0ZXJfcmVhZChydDJ4MDBkZXYsIFdMQU5fRlVOX0NUUkwsDQo+ID4gKyZ3bGFuZnVu
Y3RybCk7DQo+ID4gKyAgICAgICBydDJ4MDBfc2V0X2ZpZWxkMzIoJndsYW5mdW5jdHJsLCBXTEFO
X0VOLCAwKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0cmwsIFdM
QU5fQ0xLX0VOLCAwKTsNCj4gPiArICAgICAgIHJ0MngwMF9zZXRfZmllbGQzMigmd2xhbmZ1bmN0
cmwsIFBDSUVfQVBQMF9DTEtfUkVRLCAwKTsNCj4gPiArICAgICAgIHJ0MjgwMF9yZWdpc3Rlcl93
cml0ZShydDJ4MDBkZXYsIFdMQU5fRlVOX0NUUkwsDQo+ID4gK3dsYW5mdW5jdHJsKTsNCj4gPiAr
ICAgICAgIHVkZWxheShSRUdJU1RFUl9CVVNZX0RFTEFZKTsNCj4gPiArICAgICAgIHJldHVybiAw
Ow0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1CT0xfR1BMKHJ0MjgwMHBjaV8zMjkwX2Rpc2FibGVf
d2xhbik7DQo+ID4gIE1PRFVMRV9BVVRIT1IoRFJWX1BST0pFQ1QgIiwgQmFydGxvbWllaiBab2xu
aWVya2lld2ljeiIpOw0KPiA+ICBNT0RVTEVfVkVSU0lPTihEUlZfVkVSU0lPTik7DQo+ID4gIE1P
RFVMRV9ERVNDUklQVElPTigiUmFsaW5rIFJUMjgwMCBsaWJyYXJ5Iik7IGRpZmYgLS1naXQNCj4g
PiBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBsaWIuaA0KPiA+IGIvZHJpdmVy
cy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMGxpYi5oDQo+ID4gaW5kZXggMThhMGI2Ny4uMjJk
N2NiYiAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
bGliLmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwbGliLmgN
Cj4gPiBAQCAtMjA5LDUgKzIwOSw2IEBAIGludCBydDI4MDBfYW1wZHVfYWN0aW9uKHN0cnVjdCBp
ZWVlODAyMTFfaHcgKmh3LA0KPiA+IHN0cnVjdCBpZWVlODAyMTFfdmlmICp2aWYsDQo+ID4gIGlu
dCBydDI4MDBfZ2V0X3N1cnZleShzdHJ1Y3QgaWVlZTgwMjExX2h3ICpodywgaW50IGlkeCwNCj4g
PiAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3Qgc3VydmV5X2luZm8gKnN1cnZleSk7DQo+ID4g
IHZvaWQgcnQyODAwX2Rpc2FibGVfd3BkbWEoc3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldik7
DQo+ID4gLQ0KPiA+ICtpbnQgcnQyODAwcGNpXzMyOTBfZW5hYmxlX3dsYW4oc3RydWN0IHJ0Mngw
MF9kZXYgKnJ0MngwMGRldik7IGludA0KPiA+ICtydDI4MDBwY2lfMzI5MF9kaXNhYmxlX3dsYW4o
c3RydWN0IHJ0MngwMF9kZXYgKnJ0MngwMGRldik7DQo+ID4gICNlbmRpZiAvKiBSVDI4MDBMSUJf
SCAqLw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAw
cGNpLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuYw0KPiA+
IGluZGV4IDkzMTMzMWQuLjkyNTFmMmQgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2ly
ZWxlc3MvcnQyeDAwL3J0MjgwMHBjaS5jDQo+ID4gKysrIGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mv
cnQyeDAwL3J0MjgwMHBjaS5jDQo+ID4gQEAgLTI4MCw2ICsyODAsMTAgQEAgc3RhdGljIHZvaWQg
cnQyODAwcGNpX3N0b3BfcXVldWUoc3RydWN0DQo+ID4gZGF0YV9xdWV1ZSAqcXVldWUpDQo+ID4g
ICovDQo+ID4gIHN0YXRpYyBjaGFyICpydDI4MDBwY2lfZ2V0X2Zpcm13YXJlX25hbWUoc3RydWN0
IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+ICB7DQo+ID4gKw0KPiA+ICsgICAgICAg
aWYgKHJ0MngwMF9ydChydDJ4MDBkZXYsIFJUMzI5MCkpDQo+ID4gKyAgICAgICAgICAgICAgIHJl
dHVybiBGSVJNV0FSRV9SVDMyOTA7DQo+ID4gKw0KPiA+ICAgICAgICByZXR1cm4gRklSTVdBUkVf
UlQyODYwOw0KPiA+ICB9DQo+ID4NCj4gPiBAQCAtNTM2LDYgKzU0MCw5IEBAIHN0YXRpYyB2b2lk
IHJ0MjgwMHBjaV9kaXNhYmxlX3JhZGlvKHN0cnVjdA0KPiA+IHJ0MngwMF9kZXYgKnJ0MngwMGRl
dikNCj4gPiAgICAgICAgICAgICAgICBydDJ4MDBwY2lfcmVnaXN0ZXJfd3JpdGUocnQyeDAwZGV2
LCBQV1JfUElOX0NGRywgMCk7DQo+ID4gICAgICAgICAgICAgICAgcnQyeDAwcGNpX3JlZ2lzdGVy
X3dyaXRlKHJ0MngwMGRldiwgVFhfUElOX0NGRywgMCk7DQo+ID4gICAgICAgIH0NCj4gPiArDQo+
ID4gKyAgICAgICBpZiAocnQyeDAwX3J0KHJ0MngwMGRldiwgUlQzMjkwKSkNCj4gPiArICAgICAg
ICAgICAgICAgcnQyODAwcGNpXzMyOTBfZGlzYWJsZV93bGFuKHJ0MngwMGRldik7DQo+ID4gIH0N
Cj4gPg0KPiA+ICBzdGF0aWMgaW50IHJ0MjgwMHBjaV9zZXRfc3RhdGUoc3RydWN0IHJ0MngwMF9k
ZXYgKnJ0MngwMGRldiwgQEANCj4gPiAtMTAyOCw2ICsxMDM1LDggQEAgc3RhdGljIGludCBydDI4
MDBwY2lfcHJvYmVfaHcoc3RydWN0IHJ0MngwMF9kZXYNCj4gPiAqcnQyeDAwZGV2KQ0KPiA+ICAg
ICAgICAgKi8NCj4gPiAgICAgICAgcnQyeDAwZGV2LT5yc3NpX29mZnNldCA9IERFRkFVTFRfUlNT
SV9PRkZTRVQ7DQo+ID4NCj4gPiArICAgICAgIGlmIChydDJ4MDBfcmYocnQyeDAwZGV2LCBSRjMy
OTApKQ0KPiA+ICsgICAgICAgICAgICAgICBydDI4MDBwY2lfMzI5MF9lbmFibGVfd2xhbihydDJ4
MDBkZXYpOw0KPiA+ICAgICAgICByZXR1cm4gMDsNCj4gPiAgfQ0KPiA+DQo+ID4gQEAgLTExOTQs
NiArMTIwMyw5IEBAIHN0YXRpYw0KPiA+IERFRklORV9QQ0lfREVWSUNFX1RBQkxFKHJ0MjgwMHBj
aV9kZXZpY2VfdGFibGUpID0gew0KPiA+ICAgICAgICB7IFBDSV9ERVZJQ0UoMHgxODE0LCAweDUz
OWEpIH0sDQo+ID4gICAgICAgIHsgUENJX0RFVklDRSgweDE4MTQsIDB4NTM5ZikgfSwNCj4gPiAg
I2VuZGlmDQo+ID4gKyNpZmRlZiBDT05GSUdfUlQyODAwUENJX1JUMzI5MA0KPiA+ICsgICAgICAg
eyBQQ0lfREVWSUNFKDB4MTgxNCwgMHgzMjkwKSB9LCAjZW5kaWYNCj4gPiAgICAgICAgeyAwLCB9
DQo+ID4gIH07DQo+ID4gICNlbmRpZiAvKiBDT05GSUdfUENJICovDQo+ID4gZGlmZiAtLWdpdCBh
L2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDI4MDBwY2kuaA0KPiA+IGIvZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MjgwMHBjaS5oDQo+ID4gaW5kZXggNzBlMDUwZC4uZGQwNDNj
NyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNp
LmgNCj4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyODAwcGNpLmgNCj4g
PiBAQCAtNDksNiArNDksOSBAQA0KPiA+ICAjZGVmaW5lIEZJUk1XQVJFX1JUMjg2MCAgICAgICAg
ICAgICAgICAgICAgICAgICJydDI4NjAuYmluIg0KPiA+ICAjZGVmaW5lIEZJUk1XQVJFX0lNQUdF
X0JBU0UgICAgICAgICAgICAweDIwMDANCj4gPg0KPiA+ICsNCj4gPiArI2RlZmluZSBGSVJNV0FS
RV9SVDMyOTAgICAgICAgICAgICAgICAgICAgICAgICAicnQzMjkwLmJpbiINCj4gPiArDQo+ID4g
IC8qDQo+ID4gICogRE1BIGRlc2NyaXB0b3IgZGVmaW5lcy4NCj4gPiAgKi8NCj4gPiBkaWZmIC0t
Z2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMC5oDQo+ID4gYi9kcml2ZXJz
L25ldC93aXJlbGVzcy9ydDJ4MDAvcnQyeDAwLmgNCj4gPiBpbmRleCBjYTM2Y2NjLi5lZTc3MGU3
IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4MDAuaA0K
PiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4MDAuaA0KPiA+IEBAIC0x
OTMsMTAgKzE5MywxMSBAQCBzdHJ1Y3QgcnQyeDAwX2NoaXAgew0KPiA+ICAjZGVmaW5lIFJUMzg4
MyAgICAgICAgIDB4Mzg4MyAgLyogV1NPQyAqLw0KPiA+ICAjZGVmaW5lIFJUNTM5MCAgICAgICAg
IDB4NTM5MCAgLyogMi40R0h6ICovDQo+ID4gICNkZWZpbmUgUlQ1MzkyICAgICAgICAgMHg1Mzky
ICAvKiAyLjRHSHogKi8NCj4gPiArI2RlZmluZSBSVDMyOTAgICAgICAgICAweDMyOTANCj4gPg0K
PiA+ICAgICAgICB1MTYgcmY7DQo+ID4gICAgICAgIHUxNiByZXY7DQo+ID4gLQ0KPiA+ICsgICAg
ICAgdTE2IG1hY192ZXJzaW9uOw0KPiA+ICAgICAgICBlbnVtIHJ0MngwMF9jaGlwX2ludGYgaW50
ZjsNCj4gPiAgfTsNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL25ldC93aXJlbGVzcy9y
dDJ4MDAvcnQyeDAwcGNpLmMNCj4gPiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3J0MngwMC9ydDJ4
MDBwY2kuYw0KPiA+IGluZGV4IDBhNDY1M2EuLjliYmQ5YTMgMTAwNjQ0DQo+ID4gLS0tIGEvZHJp
dmVycy9uZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMHBjaS5jDQo+ID4gKysrIGIvZHJpdmVycy9u
ZXQvd2lyZWxlc3MvcnQyeDAwL3J0MngwMHBjaS5jDQo+ID4gQEAgLTI1Niw2ICsyNTYsNyBAQCBp
bnQgcnQyeDAwcGNpX3Byb2JlKHN0cnVjdCBwY2lfZGV2ICpwY2lfZGV2LA0KPiA+IGNvbnN0IHN0
cnVjdCBydDJ4MDBfb3BzICpvcHMpDQo+ID4gICAgICAgIHN0cnVjdCBpZWVlODAyMTFfaHcgKmh3
Ow0KPiA+ICAgICAgICBzdHJ1Y3QgcnQyeDAwX2RldiAqcnQyeDAwZGV2Ow0KPiA+ICAgICAgICBp
bnQgcmV0dmFsOw0KPiA+ICsgICAgICAgdTE2IGRldmljZV9pZDsNCj4gPg0KPiA+ICAgICAgICBy
ZXR2YWwgPSBwY2lfZW5hYmxlX2RldmljZShwY2lfZGV2KTsNCj4gPiAgICAgICAgaWYgKHJldHZh
bCkgew0KPiA+IEBAIC0zMDUsNiArMzA2LDExIEBAIGludCBydDJ4MDBwY2lfcHJvYmUoc3RydWN0
IHBjaV9kZXYgKnBjaV9kZXYsDQo+ID4gY29uc3Qgc3RydWN0IHJ0MngwMF9vcHMgKm9wcykNCj4g
PiAgICAgICAgaWYgKHJldHZhbCkNCj4gPiAgICAgICAgICAgICAgICBnb3RvIGV4aXRfZnJlZV9k
ZXZpY2U7DQo+ID4NCj4gPiArDQo+ID4gKyAgICAgICBwY2lfcmVhZF9jb25maWdfd29yZChwY2lf
ZGV2LCBQQ0lfREVWSUNFX0lELCAmZGV2aWNlX2lkKTsNCj4gPiArICAgICAgIGlmIChkZXZpY2Vf
aWQgPT0gMHgzMjkwKQ0KPiA+ICsgICAgICAgICAgICAgICBydDJ4MDBkZXYtPmNoaXAubWFjX3Zl
cnNpb24gPSAweDMyOTA7DQo+ID4gKw0KPiA+ICAgICAgICByZXR2YWwgPSBydDJ4MDBsaWJfcHJv
YmVfZGV2KHJ0MngwMGRldik7DQo+ID4gICAgICAgIGlmIChyZXR2YWwpDQo+ID4gICAgICAgICAg
ICAgICAgZ290byBleGl0X2ZyZWVfcmVnOw0KPiA+IC0tDQo+ID4gMS43LjUuNA0KPiA+DQo+ID4g
LS0NCj4gPiBUbyB1bnN1YnNjcmliZSBmcm9tIHRoaXMgbGlzdDogc2VuZCB0aGUgbGluZSAidW5z
dWJzY3JpYmUNCj4gPiBsaW51eC13aXJlbGVzcyIgaW4gdGhlIGJvZHkgb2YgYSBtZXNzYWdlIHRv
DQo+ID4gbWFqb3Jkb21vQHZnZXIua2VybmVsLm9yZyBNb3JlIG1ham9yZG9tbyBpbmZvIGF0DQo+
ID4gaHR0cDovL3ZnZXIua2VybmVsLm9yZy9tYWpvcmRvbW8taW5mby5odG1sDQo+DQoNCi0tDQpK
b2huIFcuIExpbnZpbGxlICAgICAgICAgICAgICAgIFNvbWVkYXkgdGhlIHdvcmxkIHdpbGwgbmVl
ZCBhIGhlcm8sIGFuZCB5b3UNCmxpbnZpbGxlQHR1eGRyaXZlci5jb20gICAgICAgICAgICAgICAg
ICBtaWdodCBiZSBhbGwgd2UgaGF2ZS4gIEJlIHJlYWR5Lg0KCioqKioqKioqKioqKiogRW1haWwg
Q29uZmlkZW50aWFsaXR5IE5vdGljZSAqKioqKioqKioqKioqKioqKioqKg0KVGhlIGluZm9ybWF0
aW9uIGNvbnRhaW5lZCBpbiB0aGlzIGUtbWFpbCBtZXNzYWdlIChpbmNsdWRpbmcgYW55IA0KYXR0
YWNobWVudHMpIG1heSBiZSBjb25maWRlbnRpYWwsIHByb3ByaWV0YXJ5LCBwcml2aWxlZ2VkLCBv
ciBvdGhlcndpc2UNCmV4ZW1wdCBmcm9tIGRpc2Nsb3N1cmUgdW5kZXIgYXBwbGljYWJsZSBsYXdz
LiBJdCBpcyBpbnRlbmRlZCB0byBiZSANCmNvbnZleWVkIG9ubHkgdG8gdGhlIGRlc2lnbmF0ZWQg
cmVjaXBpZW50KHMpLiBBbnkgdXNlLCBkaXNzZW1pbmF0aW9uLCANCmRpc3RyaWJ1dGlvbiwgcHJp
bnRpbmcsIHJldGFpbmluZyBvciBjb3B5aW5nIG9mIHRoaXMgZS1tYWlsIChpbmNsdWRpbmcgaXRz
IA0KYXR0YWNobWVudHMpIGJ5IHVuaW50ZW5kZWQgcmVjaXBpZW50KHMpIGlzIHN0cmljdGx5IHBy
b2hpYml0ZWQgYW5kIG1heSANCmJlIHVubGF3ZnVsLiBJZiB5b3UgYXJlIG5vdCBhbiBpbnRlbmRl
ZCByZWNpcGllbnQgb2YgdGhpcyBlLW1haWwsIG9yIGJlbGlldmUgDQp0aGF0IHlvdSBoYXZlIHJl
Y2VpdmVkIHRoaXMgZS1tYWlsIGluIGVycm9yLCBwbGVhc2Ugbm90aWZ5IHRoZSBzZW5kZXIgDQpp
bW1lZGlhdGVseSAoYnkgcmVwbHlpbmcgdG8gdGhpcyBlLW1haWwpLCBkZWxldGUgYW55IGFuZCBh
bGwgY29waWVzIG9mIA0KdGhpcyBlLW1haWwgKGluY2x1ZGluZyBhbnkgYXR0YWNobWVudHMpIGZy
b20geW91ciBzeXN0ZW0sIGFuZCBkbyBub3QNCmRpc2Nsb3NlIHRoZSBjb250ZW50IG9mIHRoaXMg
ZS1tYWlsIHRvIGFueSBvdGhlciBwZXJzb24uIFRoYW5rIHlvdSE=


2012-05-02 18:17:54

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH] rt2x00 : RT3290 chip support

Please respond to Helmut's commentary...

On Fri, Apr 27, 2012 at 09:40:28AM +0200, Helmut Schaa wrote:
> Hi Woody,
>
> A bit more verbose patch description would be highly appreciated. Also
> see some inline
> comments about the patch itself. However, I only had a quick look, so
> expect a few more
> comments from others too ...
>
> Also, please always check your patch by running scripts/checkpatch.pl from your
> kernel tree onto it.
>
> Helmut
>
> On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <[email protected]> wrote:
> > This support RT3290 chip
> >
> > Signed-off-by: Woody Hung <[email protected]>
> > ---
> > ?drivers/net/wireless/rt2x00/Kconfig ? ? | ? ?8 +
> > ?drivers/net/wireless/rt2x00/rt2800.h ? ?| ?120 +++++++++-
> > ?drivers/net/wireless/rt2x00/rt2800lib.c | ?395 ++++++++++++++++++++++++++++--
> > ?drivers/net/wireless/rt2x00/rt2800lib.h | ? ?3 +-
> > ?drivers/net/wireless/rt2x00/rt2800pci.c | ? 12 +
> > ?drivers/net/wireless/rt2x00/rt2800pci.h | ? ?3 +
> > ?drivers/net/wireless/rt2x00/rt2x00.h ? ?| ? ?3 +-
> > ?drivers/net/wireless/rt2x00/rt2x00pci.c | ? ?6 +
> > ?8 files changed, 520 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
> > index 299c387..c7548da 100644
> > --- a/drivers/net/wireless/rt2x00/Kconfig
> > +++ b/drivers/net/wireless/rt2x00/Kconfig
> > @@ -99,6 +99,14 @@ config RT2800PCI_RT53XX
> > ? ? ? ? ?rt2800pci driver.
> > ? ? ? ? ?Supported chips: RT5390
> >
> > +config RT2800PCI_RT3290
> > + ? ? ? bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
> > + ? ? ? depends on EXPERIMENTAL
> > + ? ? ? default y
> > + ? ? ? ---help---
> > + ? ? ? ? This adds support for rt3290 wireless chipset family to the
> > + ? ? ? ? rt2800pci driver.
> > + ? ? ? ? Supported chips: RT3290
> > ?endif
> >
> > ?config RT2500USB
> > diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> > index d91f4f6..39b1685 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800.h
> > @@ -70,7 +70,7 @@
> > ?#define RF5370 ? ? ? ? ? ? ? ? ? ? ? ? 0x5370
> > ?#define RF5372 ? ? ? ? ? ? ? ? ? ? ? ? 0x5372
> > ?#define RF5390 ? ? ? ? ? ? ? ? ? ? ? ? 0x5390
> > -
> > +#define RF3290 ? ? ? ? ? ? ? ? ? ? ? ? 0x3290
>
> There's no need to remove the emty line here.
>
> > ?/*
> > ?* Chipset revisions.
> > ?*/
> > @@ -112,6 +112,12 @@
> > ?* Registers.
> > ?*/
> >
> > +
> > +/*
> > + * MAC_CSR0_3290: MAC_CSR0 for rt3290 to identity MAC version number.
> > + */
> > +#define MAC_CSR0_3290 ? ? ? ? ? ? ? ? ? ? ? ? ?0x0000
> > +
>
> This should be moved to the other MAC register definitions.
> Is this register only valid on 3290 chipsets?
>
> > ?/*
> > ?* E2PROM_CSR: PCI EEPROM control register.
> > ?* RELOAD: Write 1 to reload eeprom content.
> > @@ -305,6 +311,118 @@
> > ?#define GPIO_CTRL_CFG_GPIOD_BIT7 ? ? ? FIELD32(0x00008000)
> >
> > ?/*
> > + * WLAN_CTRL_CFG
> > + */
> > +#define WLAN_FUN_CTRL ? ? ? ? ? ? ? ? ?0x80
> > +#define WLAN_EN ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000001)
> > +#define WLAN_CLK_EN ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000002)
> > +#define WLAN_RSV1 ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00000004)
> > +#define WLAN_RESET ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000008)
> > +#define PCIE_APP0_CLK_REQ ? ? ? ? ? ? ?FIELD32(0x00000010)
> > +#define FRC_WL_ANT_SET ? ? ? ? ? ? ? ? FIELD32(0x00000020)
> > +#define INV_TR_SW0 ? ? ? ? ? ? ? ? ? ? FIELD32(0x00000040)
> > +#define WLAN_GPIO_IN_BIT0 ? ? ? ? ? ? ?FIELD32(0x00000100)
> > +#define WLAN_GPIO_IN_BIT1 ? ? ? ? ? ? ?FIELD32(0x00000200)
> > +#define WLAN_GPIO_IN_BIT2 ? ? ? ? ? ? ?FIELD32(0x00000400)
> > +#define WLAN_GPIO_IN_BIT3 ? ? ? ? ? ? ?FIELD32(0x00000800)
> > +#define WLAN_GPIO_IN_BIT4 ? ? ? ? ? ? ?FIELD32(0x00001000)
> > +#define WLAN_GPIO_IN_BIT5 ? ? ? ? ? ? ?FIELD32(0x00002000)
> > +#define WLAN_GPIO_IN_BIT6 ? ? ? ? ? ? ?FIELD32(0x00004000)
> > +#define WLAN_GPIO_IN_BIT7 ? ? ? ? ? ? ?FIELD32(0x00008000)
> > +#define WLAN_GPIO_IN_BIT_ALL ? ? ? ? ? FIELD32(0x0000ff00)
> > +#define WLAN_GPIO_OUT_BIT0 ? ? ? ? ? ? FIELD32(0x00010000)
> > +#define WLAN_GPIO_OUT_BIT1 ? ? ? ? ? ? FIELD32(0x00020000)
> > +#define WLAN_GPIO_OUT_BIT2 ? ? ? ? ? ? FIELD32(0x00040000)
> > +#define WLAN_GPIO_OUT_BIT3 ? ? ? ? ? ? FIELD32(0x00050000)
> > +#define WLAN_GPIO_OUT_BIT4 ? ? ? ? ? ? FIELD32(0x00100000)
> > +#define WLAN_GPIO_OUT_BIT5 ? ? ? ? ? ? FIELD32(0x00200000)
> > +#define WLAN_GPIO_OUT_BIT6 ? ? ? ? ? ? FIELD32(0x00400000)
> > +#define WLAN_GPIO_OUT_BIT7 ? ? ? ? ? ? FIELD32(0x00800000)
> > +#define WLAN_GPIO_OUT_BIT_ALL ? ? ? ? ?FIELD32(0x00ff0000)
> > +#define WLAN_GPIO_OUT_OE_BIT0 ? ? ? ? ?FIELD32(0x01000000)
> > +#define WLAN_GPIO_OUT_OE_BIT1 ? ? ? ? ?FIELD32(0x02000000)
> > +#define WLAN_GPIO_OUT_OE_BIT2 ? ? ? ? ?FIELD32(0x04000000)
> > +#define WLAN_GPIO_OUT_OE_BIT3 ? ? ? ? ?FIELD32(0x08000000)
> > +#define WLAN_GPIO_OUT_OE_BIT4 ? ? ? ? ?FIELD32(0x10000000)
> > +#define WLAN_GPIO_OUT_OE_BIT5 ? ? ? ? ?FIELD32(0x20000000)
> > +#define WLAN_GPIO_OUT_OE_BIT6 ? ? ? ? ?FIELD32(0x40000000)
> > +#define WLAN_GPIO_OUT_OE_BIT7 ? ? ? ? ?FIELD32(0x80000000)
> > +#define WLAN_GPIO_OUT_OE_BIT_ALL ? ? ? FIELD32(0xff000000)
> > +
> > +/*
> > + * CMB_CTRL_CFG
> > + */
> > +#define CMB_CTRL ? ? ? ? ? ? ? 0x20
> > +#define AUX_OPT_BIT0 ? ? ? ? ? FIELD32(0x00000001)
> > +#define AUX_OPT_BIT1 ? ? ? ? ? FIELD32(0x00000002)
> > +#define AUX_OPT_BIT2 ? ? ? ? ? FIELD32(0x00000004)
> > +#define AUX_OPT_BIT3 ? ? ? ? ? FIELD32(0x00000008)
> > +#define AUX_OPT_BIT4 ? ? ? ? ? FIELD32(0x00000010)
> > +#define AUX_OPT_BIT5 ? ? ? ? ? FIELD32(0x00000020)
> > +#define AUX_OPT_BIT6 ? ? ? ? ? FIELD32(0x00000040)
> > +#define AUX_OPT_BIT7 ? ? ? ? ? FIELD32(0x00000080)
> > +#define AUX_OPT_BIT8 ? ? ? ? ? FIELD32(0x00000100)
> > +#define AUX_OPT_BIT9 ? ? ? ? ? FIELD32(0x00000200)
> > +#define AUX_OPT_BIT10 ? ? ? ? ?FIELD32(0x00000400)
> > +#define AUX_OPT_BIT11 ? ? ? ? ?FIELD32(0x00000800)
> > +#define AUX_OPT_BIT12 ? ? ? ? ?FIELD32(0x00001000)
> > +#define AUX_OPT_BIT13 ? ? ? ? ?FIELD32(0x00002000)
> > +#define AUX_OPT_BIT14 ? ? ? ? ?FIELD32(0x00004000)
> > +#define AUX_OPT_BIT15 ? ? ? ? ?FIELD32(0x00008000)
> > +#define LDO25_LEVEL ? ? ? ? ? ?FIELD32(0x00030000)
> > +#define LDO25_LARGEA ? ? ? ? ? FIELD32(0x00040000)
> > +#define LDO25_FRC_ON ? ? ? ? ? FIELD32(0x00080000)
> > +#define CMB_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x00300000)
> > +#define XTAL_RDY ? ? ? ? ? ? ? FIELD32(0x00400000)
> > +#define PLL_LD ? ? ? ? ? ? ? ? FIELD32(0x00800000)
> > +#define LDO_CORE_LEVEL ? ? ? ? FIELD32(0x0F000000)
> > +#define LDO_BGSEL ? ? ? ? ? ? ?FIELD32(0x30000000)
> > +#define LDO3_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x40000000)
> > +#define LDO0_EN ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x80000000)
> > +
> > +/*
> > + * OSC_CTRL_CFG
> > + */
> > +#define OSC_CTRL ? ? ? ? ? ? ? 0x38
> > +#define OSC_REF_CYCLE ? ? ? ? ?FIELD32(0x00001fff)
> > +#define OSC_RSV ? ? ? ? ? ? ? ? ? ? ? ?FIELD32(0x0000e000)
> > +#define OSC_CAL_CNT ? ? ? ? ? ?FIELD32(0x0fff0000)
> > +#define OSC_CAL_ACK ? ? ? ? ? ?FIELD32(0x10000000)
> > +#define OSC_CLK_32K_VLD ? ? ? ? ? ? ? ?FIELD32(0x20000000)
> > +#define OSC_CAL_REQ ? ? ? ? ? ?FIELD32(0x40000000)
> > +#define OSC_ROSC_EN ? ? ? ? ? ?FIELD32(0x80000000)
> > +
> > +/*
> > + * PLL_CTRL_CFG
> > + */
> > +#define PLL_CTRL ? ? ? ? ? ? ? 0x50
> > +#define PLL_RESERVED_INPUT1 ? ?FIELD32(0x000000ff)
> > +#define PLL_RESERVED_INPUT2 ? ?FIELD32(0x0000ff00)
> > +#define PLL_CONTROL ? ? ? ? ? ?FIELD32(0x00070000)
> > +#define PLL_LPF_R1 ? ? ? ? ? ? FIELD32(0x00080000)
> > +#define PLL_LPF_C1_CTRL ? ? ? ?FIELD32(0x00300000)
> > +#define PLL_LPF_C2_CTRL ? ? ? ?FIELD32(0x00c00000)
> > +#define PLL_CP_CURRENT_CTRL ? ?FIELD32(0x03000000)
> > +#define PLL_PFD_DELAY_CTRL ? ? FIELD32(0x0c000000)
> > +#define PLL_LOCK_CTRL ? ? ? ? ?FIELD32(0x70000000)
> > +#define PLL_VBGBK_EN ? ? ? ? ? FIELD32(0x80000000)
> > +
> > +/*
> > + * COEX_CFG_0
> > + */
> > +#define COEX_CFG0 ? ? ? ? ? ? ? ? ? ? ?0x40
> > +
> > +/*
> > + * COEX_CFG_1
> > + */
> > +#define COEX_CFG1 ? ? ? ? ? ? ? ? ? ? ?0x44
> > +
> > +/*
> > + * COEX_CFG_2
> > + */
> > +#define COEX_CFG2 ? ? ? ? ? ? ? ? ? ? ?0x48
> > +
> > +/*
> > ?* MCU_CMD_CFG
> > ?*/
> > ?#define MCU_CMD_CFG ? ? ? ? ? ? ? ? ? ?0x022c
> > diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> > index 1cd16b4..7753791 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> > +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> > @@ -361,6 +361,10 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ? ? ? ? ?multiple = true;
> > ? ? ? ?} else {
> > ? ? ? ? ? ? ? ?fw_len = 8192;
> > +
> > + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? ? ? ? ? fw_len = 4096;
> > +
> > ? ? ? ? ? ? ? ?multiple = true;
> > ? ? ? ?}
> >
> > @@ -417,7 +421,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ?if (rt2x00_is_pci(rt2x00dev)) {
> > ? ? ? ? ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3572) ||
> > ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> > + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
> > @@ -844,6 +849,10 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
> > ?{
> > ? ? ? ?u32 reg;
> >
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> > + ? ? ? ? ? ? ? return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0);
> > + ? ? ? } else
> > ? ? ? ?rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
>
> This looks awkward, either you have to use correct indention here
> or drop the else completely.
>
> > ? ? ? ?return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
> > ?}
> > @@ -1930,7 +1939,8 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev,
> >
> > ?#define RT5390_POWER_BOUND ? ? 0x27
> > ?#define RT5390_FREQ_OFFSET_BOUND ? ? ? 0x5f
> > -
>
> This empty line can stay.
>
> > +#define RT3290_POWER_BOUND ? ? 0x27
> > +#define RT3290_FREQ_OFFSET_BOUND ? ? ? 0x5f
>
> Might be worth to add another empty line here.
>
> > ?static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct ieee80211_conf *conf,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct rf_channel *rf,
> > @@ -2025,6 +2035,67 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> > ?}
> >
> > +
> > +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct channel_info *info)
> > +{
> > + ? ? ? u8 rfcsr;
> > +
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
> > + ? ? ? rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
> > + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
> > +
> > + ? ? ? rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
> > + ? ? ? if (info->default_power1 > RT5390_POWER_BOUND)
> > + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT3290_POWER_BOUND);
> > + ? ? ? else
> > + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
> > +
> > + ? ? ? rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
> > + ? ? ? if (rt2x00dev->freq_offset > RT3290_FREQ_OFFSET_BOUND)
> > + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RT3290_FREQ_OFFSET_BOUND);
> > + ? ? ? else
> > + ? ? ? ? ? ? ? rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
> > +
> > + ? ? ? if (rf->channel <= 14) {
> > + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr);
> > + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> > + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> > + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, rfcsr);
> > + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
> > + ? ? ? ? ? ? ? rfcsr &= ~0xF8;
> > + ? ? ? ? ? ? ? rfcsr |= (0x1f << 3);
> > + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
> > +
> > + ? ? ? ? ? ? ? if (rf->channel == 6)
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0c);
> > + ? ? ? ? ? ? ? else
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> > +
> > + ? ? ? ? ? ? ? if (rf->channel >= 1 && rf->channel <= 6)
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0f);
> > + ? ? ? ? ? ? ? else if (rf->channel >= 7 && rf->channel <= 11)
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0e);
> > + ? ? ? ? ? ? ? else if (rf->channel >= 12 && rf->channel <= 14)
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 59, 0x0d);
> > + ? ? ? }
> > +
> > + ? ? ? rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
> > + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
> > + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> > +
> > + ? ? ? rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> > + ? ? ? rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> > + ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> > +}
>
> This function could really use a few comments.
>
> > ?static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct ieee80211_conf *conf,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct rf_channel *rf,
> > @@ -2058,6 +2129,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> > ? ? ? ?case RF5390:
> > ? ? ? ? ? ? ? ?rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
> > ? ? ? ? ? ? ? ?break;
> > + ? ? ? case RF3290:
> > + ? ? ? ? ? ? ? rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info);
> > + ? ? ? ? ? ? ? break;
> > ? ? ? ?default:
> > ? ? ? ? ? ? ? ?rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
> > ? ? ? ?}
> > @@ -2545,6 +2619,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?case RF5370:
> > ? ? ? ?case RF5372:
> > ? ? ? ?case RF5390:
> > + ? ? ? case RF3290:
> > ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
> > ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
> > ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
> > @@ -2677,7 +2752,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> > ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3390) ||
> > ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ? ? ? ? ?return 0x1c + (2 * rt2x00dev->lna_gain);
> > ? ? ? ? ? ? ? ?else
> > ? ? ? ? ? ? ? ? ? ? ? ?return 0x2e + rt2x00dev->lna_gain;
> > @@ -2771,9 +2847,47 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
> > ? ? ? ?rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
> >
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);
>
> Calling a rt2800pci function from within rt2800lib doesn't look correct. Maybe
> use a new callback function for that?
>
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &reg);
> > + ? ? ? ? ? ? ? if (rt2x00_get_field32(reg, WLAN_EN) == 1) {
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PCIE_APP0_CLK_REQ, 1);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg);
> > + ? ? ? ? ? ? ? }
> > +
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &reg);
> > + ? ? ? ? ? ? ? if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) {
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO0_EN, 1);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_set_field32(&reg, LDO_BGSEL, 1);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, CMB_CTRL, reg);
> > + ? ? ? ? ? ? ? }
> > +
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, OSC_CTRL, &reg);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_ROSC_EN, 1);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_CAL_REQ, 1);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, OSC_REF_CYCLE, 0x27);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, OSC_CTRL, reg);
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, COEX_CFG0, &reg);
> > + ? ? ? ? ? ? ? reg &= ~(0xFF000000);
> > + ? ? ? ? ? ? ? reg |= 0x5E000000;
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG0, reg);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F);
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, PLL_CTRL, &reg);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, PLL_CONTROL, 1);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, PLL_CTRL, reg);
> > + ? ? ? }
> > +
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT3071) ||
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3090) ||
> > - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390)) {
> > + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3390) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
>
> Indention looks strange here.
>
> > +
> > + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, TX_SW_CFG0,
> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0x00000404);
> > + ? ? ? ? ? ? ? else
> > ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
>
> Indention again.
>
> > ? ? ? ? ? ? ? ?rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
> > ? ? ? ? ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
> > @@ -3184,7 +3298,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?return -EACCES;
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ? ?||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> > ? ? ? ? ? ? ? ?rt2800_bbp_read(rt2x00dev, 4, &value);
> > ? ? ? ? ? ? ? ?rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 4, value);
> > @@ -3193,25 +3308,32 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev) ||
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 31, 0x08);
> >
> > ? ? ? ?rt2800_bbp_write(rt2x00dev, 65, 0x2c);
> > ? ? ? ?rt2800_bbp_write(rt2x00dev, 66, 0x38);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 68, 0x0b);
> >
> > ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x16);
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x12);
> > ? ? ? ?} else if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 73, 0x13);
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 75, 0x46);
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 76, 0x28);
> > +
> > + ? ? ? ? ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 77, 0x58);
> > + ? ? ? ? ? ? ? else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 77, 0x59);
>
> Indention.
>
> > ? ? ? ?} else {
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 69, 0x12);
> > @@ -3237,9 +3359,17 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 81, 0x37);
> > ? ? ? ?}
> >
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 74, 0x0b);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 79, 0x18);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 80, 0x09);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 81, 0x33);
> > + ? ? ? }
> > +
> > ? ? ? ?rt2800_bbp_write(rt2x00dev, 82, 0x62);
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x7a);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 83, 0x6a);
> > @@ -3247,13 +3377,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x19);
> > ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x9a);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 84, 0x99);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x38);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 86, 0x00);
> > @@ -3264,7 +3396,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?rt2800_bbp_write(rt2x00dev, 91, 0x04);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x02);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 92, 0x00);
> > @@ -3281,13 +3414,15 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT3572) ||
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5390) ||
> > ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290) ||
> > ? ? ? ? ? ?rt2800_is_305x_soc(rt2x00dev))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0xc0);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 103, 0x00);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 104, 0x92);
> >
> > ? ? ? ?if (rt2800_is_305x_soc(rt2x00dev))
> > @@ -3295,10 +3430,13 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5390) ||
> > ? ? ? ? ? ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x3c);
> > + ? ? ? else if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 105, 0x1c);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 105, 0x05);
> >
> > - ? ? ? if (rt2x00_rt(rt2x00dev, RT5390))
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT5390) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x03);
> > ? ? ? ?else if (rt2x00_rt(rt2x00dev, RT5392))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x12);
> > @@ -3306,7 +3444,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 106, 0x35);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392))
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290))
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 128, 0x12);
> >
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5392)) {
> > @@ -3331,6 +3470,27 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?rt2800_bbp_write(rt2x00dev, 138, value);
> > ? ? ? ?}
> >
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 67, 0x24);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 143, 0x04);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 142, 0x99);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 150, 0x30);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 151, 0x2e);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 152, 0x20);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 153, 0x34);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 154, 0x40);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 155, 0x3b);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 253, 0x04);
> > +
> > + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 47, &value);
> > + ? ? ? ? ? ? ? rt2x00_set_field8(&value, RFCSR2_RESCAL_EN, 1);
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 47, value);
> > +
> > + ? ? ? ? ? ? ? rt2800_bbp_read(rt2x00dev, 3, &value);
> > + ? ? ? ? ? ? ? value &= (~0xc0);
> > + ? ? ? ? ? ? ? value |= 0xc0;
> > + ? ? ? ? ? ? ? rt2800_bbp_write(rt2x00dev, 3, value);
> > + ? ? ? }
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > ? ? ? ? ? ? ? ?rt2x00_rt(rt2x00dev, RT5392)) {
> > ? ? ? ? ? ? ? ?int ant, div_mode;
> > @@ -3467,6 +3627,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT3572) &&
> > ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5390) &&
> > ? ? ? ? ? ?!rt2x00_rt(rt2x00dev, RT5392) &&
> > + ? ? ? ? ? !rt2x00_rt(rt2x00dev, RT3290) &&
> > ? ? ? ? ? ?!rt2800_is_305x_soc(rt2x00dev))
> > ? ? ? ? ? ? ? ?return 0;
> >
> > @@ -3474,7 +3635,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? * Init RF calibration.
> > ? ? ? ? */
> > ? ? ? ?if (rt2x00_rt(rt2x00dev, RT5390) ||
> > - ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392)) {
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT5392) ||
> > + ? ? ? ? ? ? ? rt2x00_rt(rt2x00dev, RT3290)) {
> > ? ? ? ? ? ? ? ?rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
> > ? ? ? ? ? ? ? ?rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
> > ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
> > @@ -3752,6 +3914,53 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 61, 0x91);
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 62, 0x39);
> > ? ? ? ? ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 63, 0x07);
> > + ? ? ? } else if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 3, 0x08);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 8, 0xf3);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 9, 0x02);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 12, 0x46);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 18, 0x02);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 25, 0x83);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 26, 0x82);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 34, 0x05);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 42, 0xd5);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 43, 0x7b);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 49, 0x98);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 55, 0x43);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 56, 0x02);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 59, 0x09);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
> > + ? ? ? ? ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 61, 0xc1);
> > ? ? ? ?}
> >
> > ? ? ? ?if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
> > @@ -3935,6 +4144,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
> > ? ? ? ?}
> >
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290)) {
> > + ? ? ? ? ? ? ? rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr);
> > + ? ? ? ? ? ? ? rfcsr = ((rfcsr & ~0xc0) | 0xc0);
> > + ? ? ? ? ? ? ? rt2800_rfcsr_write(rt2x00dev, 29, rfcsr);
> > + ? ? ? }
> > +
> > ? ? ? ?return 0;
> > ?}
> >
> > @@ -4026,9 +4241,13 @@ EXPORT_SYMBOL_GPL(rt2800_disable_radio);
> > ?int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
> > ?{
> > ? ? ? ?u32 reg;
> > + ? ? ? u16 efuse_ctrl_reg;
> > + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
> >
> > - ? ? ? rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
> > + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> > + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;
>
> This shouldn't be hardcoded. Please add a define to rt2800.h.
>
> >
> > + ? ? ? rt2800_register_read(rt2x00dev, efuse_ctrl_reg, &reg);
> > ? ? ? ?return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
> > ?}
> > ?EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
> > @@ -4037,26 +4256,44 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
> > ?{
> > ? ? ? ?u32 reg;
> >
> > + ? ? ? u16 efuse_ctrl_reg;
> > + ? ? ? u16 efuse_data0_reg;
> > + ? ? ? u16 efuse_data1_reg;
> > + ? ? ? u16 efuse_data2_reg;
> > + ? ? ? u16 efuse_data3_reg;
> > +
> > + ? ? ? efuse_ctrl_reg = EFUSE_CTRL;
> > + ? ? ? efuse_data0_reg = EFUSE_DATA0;
> > + ? ? ? efuse_data1_reg = EFUSE_DATA1;
> > + ? ? ? efuse_data2_reg = EFUSE_DATA2;
> > + ? ? ? efuse_data3_reg = EFUSE_DATA3;
> > +
> > + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290) {
> > + ? ? ? ? ? ? ? efuse_ctrl_reg = 0x24;
> > + ? ? ? ? ? ? ? efuse_data3_reg = 0x28;
> > + ? ? ? ? ? ? ? efuse_data2_reg = efuse_data3_reg + 4;
> > + ? ? ? ? ? ? ? efuse_data1_reg = efuse_data2_reg + 4;
> > + ? ? ? ? ? ? ? efuse_data0_reg = efuse_data1_reg + 4;
> > + ? ? ? }
>
> Same here, the register offsets would make sense as defines.
>
> > ? ? ? ?mutex_lock(&rt2x00dev->csr_mutex);
> >
> > - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
> > + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, &reg);
> > ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
> > ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
> > ? ? ? ?rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
> > - ? ? ? rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
> > + ? ? ? rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);
> >
> > ? ? ? ?/* Wait until the EEPROM has been loaded */
> > - ? ? ? rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
> > -
> > + ? ? ? rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, &reg);
> > ? ? ? ?/* Apparently the data is read from end to start */
> > - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
> > + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, &reg);
> > ? ? ? ?/* The returned value is in CPU order, but eeprom is le */
> > ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
> > - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
> > + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, &reg);
> > ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
> > - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
> > + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, &reg);
> > ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg);
> > - ? ? ? rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, &reg);
> > + ? ? ? rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, &reg);
> > ? ? ? ?*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);
> >
> > ? ? ? ?mutex_unlock(&rt2x00dev->csr_mutex);
> > @@ -4218,9 +4455,13 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
> > ? ? ? ? * RT53xx: defined in "EEPROM_CHIP_ID" field
> > ? ? ? ? */
> > + ? ? ? if (rt2x00dev->chip.mac_version == 0x3290)
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, MAC_CSR0_3290, &reg);
> > + ? ? ? else
> > ? ? ? ?rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
>
> Indention.
>
> > ? ? ? ?if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390 ||
> > - ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392)
> > + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5392 ||
> > + ? ? ? ? ? ? ? rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT3290)
> > ? ? ? ? ? ? ? ?rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
> > ? ? ? ?else
> > ? ? ? ? ? ? ? ?value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
> > @@ -4239,6 +4480,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?case RT3572:
> > ? ? ? ?case RT5390:
> > ? ? ? ?case RT5392:
> > + ? ? ? case RT3290:
> > ? ? ? ? ? ? ? ?break;
> > ? ? ? ?default:
> > ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt);
> > @@ -4259,6 +4501,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?case RF5370:
> > ? ? ? ?case RF5372:
> > ? ? ? ?case RF5390:
> > + ? ? ? case RF3290:
> > ? ? ? ? ? ? ? ?break;
> > ? ? ? ?default:
> > ? ? ? ? ? ? ? ?ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n",
> > @@ -4572,7 +4815,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF3320) ||
> > ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5370) ||
> > ? ? ? ? ? ? ? ? ? rt2x00_rf(rt2x00dev, RF5372) ||
> > - ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390)) {
> > + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF5390) ||
> > + ? ? ? ? ? ? ? ? ?rt2x00_rf(rt2x00dev, RF3290)) {
> > ? ? ? ? ? ? ? ?spec->num_channels = 14;
> > ? ? ? ? ? ? ? ?spec->channels = rf_vals_3x;
> > ? ? ? ?} else if (rt2x00_rf(rt2x00dev, RF3052)) {
> > @@ -4658,6 +4902,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ?case RF5370:
> > ? ? ? ?case RF5372:
> > ? ? ? ?case RF5390:
> > + ? ? ? case RF3290:
> > ? ? ? ? ? ? ? ?__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
> > ? ? ? ? ? ? ? ?break;
> > ? ? ? ?}
> > @@ -4885,6 +5130,102 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> > ?}
> > ?EXPORT_SYMBOL_GPL(rt2800_get_survey);
> >
> > +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev)
>
> rt2800pci functions should live in rt2800pci.c, not in rt2800lib.c.
>
> > +{
> > + ? ? ? u32 wlanfunctrl;
> > + ? ? ? u32 glocfg;
> > + ? ? ? u32 cmbctrl;
> > + ? ? ? u8 index;
> > + ? ? ? int i;
> > +
> > + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, FRC_WL_ANT_SET, 1);
> > + ? ? ? if ((rt2x00_get_field32(wlanfunctrl, WLAN_EN) == 1))
> > + ? ? ? ? ? ? ? return 0;
> > +
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 1);
> > + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> > + ? ? ? udelay(REGISTER_BUSY_DELAY);
> > +
> > + ? ? ? index = 0;
> > + ? ? ? cmbctrl = 0;
> > + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, CMB_CTRL, &cmbctrl);
> > + ? ? ? ? ? ? ? if ((rt2x00_get_field32(cmbctrl, PLL_LD) == 1) &&
> > + ? ? ? ? ? ? ? ? ? ? ? (rt2x00_get_field32(cmbctrl, XTAL_RDY) == 1))
> > + ? ? ? ? ? ? ? ? ? ? ? break;
> > + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? }
> > +
> > + ? ? ? if (index >= REGISTER_BUSY_COUNT) {
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x018);
> > + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x418);
> > + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, 0x58, 0x618);
> > + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? } else {
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev,
> > + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG, &glocfg);
> > + ? ? ? }
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 1);
> > +
> > + ? ? ? rt2800_register_write(rt2x00dev,
> > + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl | 0x8));
> > + ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? rt2800_register_write(rt2x00dev,
> > + ? ? ? ? ? ? ? WLAN_FUN_CTRL, (wlanfunctrl &= (~0x8)));
> > + ? ? ? udelay(2);
> > + ? ? ? rt2800_register_write(rt2x00dev,
> > + ? ? ? ? ? ? ? INT_SOURCE_CSR, 0x7fffffff);
> > + ? ? ? return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rt2800pci_3290_enable_wlan);
> > +
> > +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev)
> > +{
> > + ? ? ? u32 wlanfunctrl;
> > + ? ? ? u32 glocfg;
> > + ? ? ? u32 reg;
> > + ? ? ? int i;
> > +
> > + ? ? ? /* Change Interrupt bitmask. */
> > + ? ? ? rt2800_register_write(rt2x00dev, INT_MASK_CSR, 0x0);
> > + ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> > + ? ? ? rt2x00_set_field32(&glocfg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
> > + ? ? ? rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, glocfg);
> > +
> > + ? ? ? /* wait RX DMA idle */
> > + ? ? ? for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &glocfg);
> > + ? ? ? ? ? ? ? if ((rt2x00_get_field32(glocfg,
> > + ? ? ? ? ? ? ? ? ? ? ? WPDMA_GLO_CFG_RX_DMA_BUSY) == 0) ||
> > + ? ? ? ? ? ? ? ? ? ? ? (glocfg == 0xFFFFFFFF))
> > + ? ? ? ? ? ? ? ? ? ? ? break;
> > + ? ? ? ? ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? }
> > +
> > + ? ? ? if (i >= REGISTER_BUSY_COUNT) {
> > + ? ? ? ? ? ? ? rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
> > + ? ? ? ? ? ? ? rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
> > + ? ? ? ? ? ? ? rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
> > + ? ? ? ? ? ? ? return 0;
> > + ? ? ? ? ? ? ? }
> > +
> > + ? ? ? rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, &wlanfunctrl);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_EN, 0);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, WLAN_CLK_EN, 0);
> > + ? ? ? rt2x00_set_field32(&wlanfunctrl, PCIE_APP0_CLK_REQ, 0);
> > + ? ? ? rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, wlanfunctrl);
> > + ? ? ? udelay(REGISTER_BUSY_DELAY);
> > + ? ? ? return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(rt2800pci_3290_disable_wlan);
> > ?MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
> > ?MODULE_VERSION(DRV_VERSION);
> > ?MODULE_DESCRIPTION("Ralink RT2800 library");
> > diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
> > index 18a0b67..22d7cbb 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800lib.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800lib.h
> > @@ -209,5 +209,6 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> > ?int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
> > ? ? ? ? ? ? ? ? ? ? ?struct survey_info *survey);
> > ?void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev);
> > -
> > +int rt2800pci_3290_enable_wlan(struct rt2x00_dev *rt2x00dev);
> > +int rt2800pci_3290_disable_wlan(struct rt2x00_dev *rt2x00dev);
> > ?#endif /* RT2800LIB_H */
> > diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
> > index 931331d..9251f2d 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800pci.c
> > +++ b/drivers/net/wireless/rt2x00/rt2800pci.c
> > @@ -280,6 +280,10 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
> > ?*/
> > ?static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
> > ?{
> > +
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? return FIRMWARE_RT3290;
> > +
> > ? ? ? ?return FIRMWARE_RT2860;
> > ?}
> >
> > @@ -536,6 +540,9 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
> > ? ? ? ? ? ? ? ?rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
> > ? ? ? ?}
> > +
> > + ? ? ? if (rt2x00_rt(rt2x00dev, RT3290))
> > + ? ? ? ? ? ? ? rt2800pci_3290_disable_wlan(rt2x00dev);
> > ?}
> >
> > ?static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
> > @@ -1028,6 +1035,8 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
> > ? ? ? ? */
> > ? ? ? ?rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
> >
> > + ? ? ? if (rt2x00_rf(rt2x00dev, RF3290))
> > + ? ? ? ? ? ? ? rt2800pci_3290_enable_wlan(rt2x00dev);
> > ? ? ? ?return 0;
> > ?}
> >
> > @@ -1194,6 +1203,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
> > ? ? ? ?{ PCI_DEVICE(0x1814, 0x539a) },
> > ? ? ? ?{ PCI_DEVICE(0x1814, 0x539f) },
> > ?#endif
> > +#ifdef CONFIG_RT2800PCI_RT3290
> > + ? ? ? { PCI_DEVICE(0x1814, 0x3290) },
> > +#endif
> > ? ? ? ?{ 0, }
> > ?};
> > ?#endif /* CONFIG_PCI */
> > diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
> > index 70e050d..dd043c7 100644
> > --- a/drivers/net/wireless/rt2x00/rt2800pci.h
> > +++ b/drivers/net/wireless/rt2x00/rt2800pci.h
> > @@ -49,6 +49,9 @@
> > ?#define FIRMWARE_RT2860 ? ? ? ? ? ? ? ? ? ? ? ?"rt2860.bin"
> > ?#define FIRMWARE_IMAGE_BASE ? ? ? ? ? ?0x2000
> >
> > +
> > +#define FIRMWARE_RT3290 ? ? ? ? ? ? ? ? ? ? ? ?"rt3290.bin"
> > +
> > ?/*
> > ?* DMA descriptor defines.
> > ?*/
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> > index ca36ccc..ee770e7 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00.h
> > +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> > @@ -193,10 +193,11 @@ struct rt2x00_chip {
> > ?#define RT3883 ? ? ? ? 0x3883 ?/* WSOC */
> > ?#define RT5390 ? ? ? ? 0x5390 ?/* 2.4GHz */
> > ?#define RT5392 ? ? ? ? 0x5392 ?/* 2.4GHz */
> > +#define RT3290 ? ? ? ? 0x3290
> >
> > ? ? ? ?u16 rf;
> > ? ? ? ?u16 rev;
> > -
> > + ? ? ? u16 mac_version;
> > ? ? ? ?enum rt2x00_chip_intf intf;
> > ?};
> >
> > diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > index 0a4653a..9bbd9a3 100644
> > --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
> > +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
> > @@ -256,6 +256,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> > ? ? ? ?struct ieee80211_hw *hw;
> > ? ? ? ?struct rt2x00_dev *rt2x00dev;
> > ? ? ? ?int retval;
> > + ? ? ? u16 device_id;
> >
> > ? ? ? ?retval = pci_enable_device(pci_dev);
> > ? ? ? ?if (retval) {
> > @@ -305,6 +306,11 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
> > ? ? ? ?if (retval)
> > ? ? ? ? ? ? ? ?goto exit_free_device;
> >
> > +
> > + ? ? ? pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
> > + ? ? ? if (device_id == 0x3290)
> > + ? ? ? ? ? ? ? rt2x00dev->chip.mac_version = 0x3290;
> > +
> > ? ? ? ?retval = rt2x00lib_probe_dev(rt2x00dev);
> > ? ? ? ?if (retval)
> > ? ? ? ? ? ? ? ?goto exit_free_reg;
> > --
> > 1.7.5.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> > the body of a message to [email protected]
> > More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.