* [PATCH] rt2x00 : RT3290 chip support @ 2012-04-27 2:22 Woody Hung 2012-04-27 7:40 ` Helmut Schaa 2012-05-11 12:05 ` Gertjan van Wingerde 0 siblings, 2 replies; 5+ messages in thread From: Woody Hung @ 2012-04-27 2:22 UTC (permalink / raw) To: linville; +Cc: linux-wireless, jay.hung, pohsun.yang, dennis.lee, Woody Hung This support RT3290 chip Signed-off-by: Woody Hung <Woody.Hung@mediatek.com> --- 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, ®); rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); rt2x00_set_field32(®, 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, ®); + return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); + } else rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); 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(®, 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, ®); + if (rt2x00_get_field32(reg, WLAN_EN) == 1) { + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + } + + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); + if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { + rt2x00_set_field32(®, LDO0_EN, 1); + rt2x00_set_field32(®, LDO_BGSEL, 1); + rt2800_register_write(rt2x00dev, CMB_CTRL, reg); + } + + rt2800_register_read(rt2x00dev, OSC_CTRL, ®); + rt2x00_set_field32(®, OSC_ROSC_EN, 1); + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); + rt2x00_set_field32(®, OSC_ROSC_EN, 1); + rt2x00_set_field32(®, OSC_CAL_REQ, 1); + rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); + rt2800_register_read(rt2x00dev, COEX_CFG0, ®); + reg &= ~(0xFF000000); + reg |= 0x5E000000; + rt2800_register_write(rt2x00dev, COEX_CFG0, reg); + rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F); + rt2800_register_read(rt2x00dev, PLL_CTRL, ®); + rt2x00_set_field32(®, 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, ®); + if (rt2x00dev->chip.mac_version == 0x3290) + efuse_ctrl_reg = 0x24; + rt2800_register_read(rt2x00dev, efuse_ctrl_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, ®); + rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); rt2x00_set_field32(®, 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, ®); - + rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); /* Apparently the data is read from end to start */ - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); + rt2800_register_read_lock(rt2x00dev, efuse_data3_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, ®); + rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); + rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); + rt2800_register_read_lock(rt2x00dev, efuse_data0_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, ®); + else rt2800_register_read(rt2x00dev, MAC_CSR0, ®); 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, ®); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); + rt2x00_set_field32(®, 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 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] rt2x00 : RT3290 chip support 2012-04-27 2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung @ 2012-04-27 7:40 ` Helmut Schaa 2012-05-02 18:13 ` John W. Linville 2012-05-11 12:05 ` Gertjan van Wingerde 1 sibling, 1 reply; 5+ messages in thread From: Helmut Schaa @ 2012-04-27 7:40 UTC (permalink / raw) To: Woody Hung Cc: linville, linux-wireless, jay.hung, pohsun.yang, dennis.lee, Ivo Van Doorn, Gertjan van Wingerde 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 <Woody.Hung@mediatek.com> wrote: > This support RT3290 chip > > Signed-off-by: Woody Hung <Woody.Hung@mediatek.com> > --- > 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, ®); > rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); > rt2x00_set_field32(®, 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, ®); > + return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); > + } else > rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); 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(®, 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, ®); > + if (rt2x00_get_field32(reg, WLAN_EN) == 1) { > + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); > + if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { > + rt2x00_set_field32(®, LDO0_EN, 1); > + rt2x00_set_field32(®, LDO_BGSEL, 1); > + rt2800_register_write(rt2x00dev, CMB_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, OSC_CTRL, ®); > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > + rt2x00_set_field32(®, OSC_CAL_REQ, 1); > + rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > + rt2800_register_read(rt2x00dev, COEX_CFG0, ®); > + reg &= ~(0xFF000000); > + reg |= 0x5E000000; > + rt2800_register_write(rt2x00dev, COEX_CFG0, reg); > + rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F); > + rt2800_register_read(rt2x00dev, PLL_CTRL, ®); > + rt2x00_set_field32(®, 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, ®); > + 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, ®); > 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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); > rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); > rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); > rt2x00_set_field32(®, 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, ®); > - > + rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); > /* Apparently the data is read from end to start */ > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data3_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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data0_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, ®); > + else > rt2800_register_read(rt2x00dev, MAC_CSR0, ®); 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, ®); > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); > + rt2x00_set_field32(®, 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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] rt2x00 : RT3290 chip support 2012-04-27 7:40 ` Helmut Schaa @ 2012-05-02 18:13 ` John W. Linville 2012-05-03 1:07 ` Woody Hung (洪秋竹) 0 siblings, 1 reply; 5+ messages in thread From: John W. Linville @ 2012-05-02 18:13 UTC (permalink / raw) To: Helmut Schaa Cc: Woody Hung, linux-wireless, jay.hung, pohsun.yang, dennis.lee, Ivo Van Doorn, Gertjan van Wingerde 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 <Woody.Hung@mediatek.com> wrote: > > This support RT3290 chip > > > > Signed-off-by: Woody Hung <Woody.Hung@mediatek.com> > > --- > > 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, ®); > > rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); > > rt2x00_set_field32(®, 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, ®); > > + return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); > > + } else > > rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); > > 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(®, 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, ®); > > + if (rt2x00_get_field32(reg, WLAN_EN) == 1) { > > + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); > > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > > + } > > + > > + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); > > + if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { > > + rt2x00_set_field32(®, LDO0_EN, 1); > > + rt2x00_set_field32(®, LDO_BGSEL, 1); > > + rt2800_register_write(rt2x00dev, CMB_CTRL, reg); > > + } > > + > > + rt2800_register_read(rt2x00dev, OSC_CTRL, ®); > > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > > + rt2x00_set_field32(®, OSC_CAL_REQ, 1); > > + rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); > > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > > + rt2800_register_read(rt2x00dev, COEX_CFG0, ®); > > + reg &= ~(0xFF000000); > > + reg |= 0x5E000000; > > + rt2800_register_write(rt2x00dev, COEX_CFG0, reg); > > + rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F); > > + rt2800_register_read(rt2x00dev, PLL_CTRL, ®); > > + rt2x00_set_field32(®, 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, ®); > > + 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, ®); > > 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, ®); > > + rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); > > rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); > > rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); > > rt2x00_set_field32(®, 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, ®); > > - > > + rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); > > /* Apparently the data is read from end to start */ > > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); > > + rt2800_register_read_lock(rt2x00dev, efuse_data3_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, ®); > > + rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); > > *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); > > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); > > + rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); > > *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); > > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); > > + rt2800_register_read_lock(rt2x00dev, efuse_data0_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, ®); > > + else > > rt2800_register_read(rt2x00dev, MAC_CSR0, ®); > > 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, ®); > > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); > > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); > > + rt2x00_set_field32(®, 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 majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- John W. Linville Someday the world will need a hero, and you linville@tuxdriver.com might be all we have. Be ready. ^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH] rt2x00 : RT3290 chip support 2012-05-02 18:13 ` John W. Linville @ 2012-05-03 1:07 ` Woody Hung (洪秋竹) 0 siblings, 0 replies; 5+ messages in thread From: Woody Hung (洪秋竹) @ 2012-05-03 1:07 UTC (permalink / raw) To: John W. Linville, Helmut Schaa Cc: linux-wireless@vger.kernel.org, Jay Hung (洪偉傑), Pohsun Yang (楊伯勳), Dennis Lee (李明達), Ivo Van Doorn, Gertjan van Wingerde 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= ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] rt2x00 : RT3290 chip support 2012-04-27 2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung 2012-04-27 7:40 ` Helmut Schaa @ 2012-05-11 12:05 ` Gertjan van Wingerde 1 sibling, 0 replies; 5+ messages in thread From: Gertjan van Wingerde @ 2012-05-11 12:05 UTC (permalink / raw) To: Woody Hung; +Cc: linville, linux-wireless, jay.hung, pohsun.yang, dennis.lee Hi Woody, On Fri, Apr 27, 2012 at 4:22 AM, Woody Hung <Woody.Hung@mediatek.com> wrote: > This support RT3290 chip > > Signed-off-by: Woody Hung <Woody.Hung@mediatek.com> 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, ®); > rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); > rt2x00_set_field32(®, 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, ®); > + return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); > + } else > rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); > 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(®, 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, ®); > + if (rt2x00_get_field32(reg, WLAN_EN) == 1) { > + rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); > + rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, CMB_CTRL, ®); > + if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { > + rt2x00_set_field32(®, LDO0_EN, 1); > + rt2x00_set_field32(®, LDO_BGSEL, 1); > + rt2800_register_write(rt2x00dev, CMB_CTRL, reg); > + } > + > + rt2800_register_read(rt2x00dev, OSC_CTRL, ®); > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > + rt2x00_set_field32(®, OSC_ROSC_EN, 1); > + rt2x00_set_field32(®, OSC_CAL_REQ, 1); > + rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); > + rt2800_register_write(rt2x00dev, OSC_CTRL, reg); > + rt2800_register_read(rt2x00dev, COEX_CFG0, ®); > + reg &= ~(0xFF000000); > + reg |= 0x5E000000; > + rt2800_register_write(rt2x00dev, COEX_CFG0, reg); > + rt2800_register_write(rt2x00dev, COEX_CFG2, 0x0017937F); > + rt2800_register_read(rt2x00dev, PLL_CTRL, ®); > + rt2x00_set_field32(®, 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, ®); > + if (rt2x00dev->chip.mac_version == 0x3290) > + efuse_ctrl_reg = 0x24; > > + rt2800_register_read(rt2x00dev, efuse_ctrl_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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®); > rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); > rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); > rt2x00_set_field32(®, 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, ®); > - > + rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®); > /* Apparently the data is read from end to start */ > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data3_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, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); > *(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); > - rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, ®); > + rt2800_register_read_lock(rt2x00dev, efuse_data0_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, ®); > + else > rt2800_register_read(rt2x00dev, MAC_CSR0, ®); > 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, ®); > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); > + rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); > + rt2x00_set_field32(®, 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 majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- --- Gertjan ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-05-11 12:05 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-04-27 2:22 [PATCH] rt2x00 : RT3290 chip support Woody Hung 2012-04-27 7:40 ` Helmut Schaa 2012-05-02 18:13 ` John W. Linville 2012-05-03 1:07 ` Woody Hung (洪秋竹) 2012-05-11 12:05 ` Gertjan van Wingerde
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox