diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/Makefile b/drivers/net/wireless/aic8800/aic8800_bsp/Makefile index 2382d0886..d25be5ff3 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/Makefile +++ b/drivers/net/wireless/aic8800/aic8800_bsp/Makefile @@ -10,6 +10,8 @@ obj-m := aic8800_bsp.o aic8800_bsp-y := \ aic_bsp_main.o \ aic_bsp_driver.o \ + aic_bsp_8800d.o \ + aic_bsp_8800dc.o \ aicsdio.o \ aicsdio_txrxif.o diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800d.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800d.c new file mode 100644 index 000000000..2c96ee9e5 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800d.c @@ -0,0 +1,336 @@ +/** + ****************************************************************************** + * + * aic_bsp_8800d.c + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#include +#include +#include +#include "aicsdio_txrxif.h" +#include "aicsdio.h" +#include "aic_bsp_driver.h" + +#define RAM_FMAC_FW_ADDR 0x00120000 +#define FW_RAM_ADID_BASE_ADDR 0x00161928 +#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 +#define FW_RAM_PATCH_BASE_ADDR 0x00100000 + +static u32 patch_tbl[][2] = { +}; + +static u32 syscfg_tbl_masked[][3] = { + {0x40506024, 0x000000FF, 0x000000DF}, // for clk gate lp_level +}; + +static u32 rf_tbl_masked[][3] = { + {0x40344058, 0x00800000, 0x00000000},// pll trx +}; + +static u32 aicbsp_syscfg_tbl[][2] = { + {0x40500014, 0x00000101}, // 1) + {0x40500018, 0x00000109}, // 2) + {0x40500004, 0x00000010}, // 3) the order should not be changed + + // def CONFIG_PMIC_SETTING + // U02 bootrom only + {0x40040000, 0x00001AC8}, // 1) fix panic + {0x40040084, 0x00011580}, + {0x40040080, 0x00000001}, + {0x40100058, 0x00000000}, + + {0x50000000, 0x03220204}, // 2) pmic interface init + {0x50019150, 0x00000002}, // 3) for 26m xtal, set div1 + {0x50017008, 0x00000000}, // 4) stop wdg +}; + +static const struct aicbsp_firmware fw_u02[] = { + [AICBSP_CPMODE_WORK] = { + .desc = "normal work mode(sdio u02)", + .bt_adid = "fw_adid.bin", + .bt_patch = "fw_patch.bin", + .bt_table = "fw_patch_table.bin", + .wl_fw = "fmacfw.bin" + }, + + [AICBSP_CPMODE_TEST] = { + .desc = "rf test mode(sdio u02)", + .bt_adid = "fw_adid.bin", + .bt_patch = "fw_patch.bin", + .bt_table = "fw_patch_table.bin", + .wl_fw = "fmacfw_rf.bin" + }, +}; + +static const struct aicbsp_firmware fw_u03[] = { + [AICBSP_CPMODE_WORK] = { + .desc = "normal work mode(sdio u03/u04)", + .bt_adid = "fw_adid_u03.bin", + .bt_patch = "fw_patch_u03.bin", + .bt_table = "fw_patch_table_u03.bin", + .wl_fw = "fmacfw.bin" + }, + + [AICBSP_CPMODE_TEST] = { + .desc = "rf test mode(sdio u03/u04)", + .bt_adid = "fw_adid_u03.bin", + .bt_patch = "fw_patch_u03.bin", + .bt_table = "fw_patch_table_u03.bin", + .wl_fw = "fmacfw_rf.bin" + }, +}; + +static int aicbt_init(struct aic_sdio_dev *sdiodev) +{ + struct aicbt_info_t btcfg = { + .btmode = AICBT_BTMODE_DEFAULT, + .btport = AICBT_BTPORT_DEFAULT, + .uart_baud = AICBT_UART_BAUD_DEFAULT, + .uart_flowctrl = AICBT_UART_FC_DEFAULT, + .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, + .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT, + }; + + struct aicbt_patch_table *head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); + int ret = aicbt_patch_info_unpack(head, &btcfg); + + if (head == NULL) + return -1; + + if (ret) { + btcfg.addr_adid = FW_RAM_ADID_BASE_ADDR; + btcfg.addr_patch = FW_RAM_PATCH_BASE_ADDR; + if (aicbsp_info.chipinfo->rev != CHIP_REV_U02) + btcfg.addr_adid = FW_RAM_ADID_BASE_ADDR_U03; + } + + ret = rwnx_plat_bin_fw_upload_android(sdiodev, btcfg.addr_adid, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid); + if (ret) + goto err; + + ret = rwnx_plat_bin_fw_upload_android(sdiodev, btcfg.addr_patch, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch); + if (ret) + goto err; + + ret = aicbt_patch_table_load(sdiodev, &btcfg, head); + if (ret) + printk("aicbt_patch_table_load fail\n"); + +err: + aicbt_patch_table_free(&head); + return ret; +} + +static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev) +{ + int ret = 0; + + /* memory access */ + const u32 fw_addr = RAM_FMAC_FW_ADDR; + struct dbg_start_app_cfm start_app_cfm; + + /* fw start */ + ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm); + if (ret) { + return -1; + } + aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF; + + return 0; +} + +static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev) +{ + int ret, cnt; + int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3; + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, + syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]); + if (ret) { + printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret); + return ret; + } + } + + ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, + rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]); + if (ret) { + printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret); + return ret; + } + + return 0; +} + +static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev) +{ + const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180; + u32 config_base; + uint32_t start_addr = 0x1e6000; + u32 patch_addr = start_addr; + u32 patch_num = sizeof(patch_tbl)/4; + struct dbg_mem_read_cfm rd_patch_addr_cfm; + int ret = 0; + u16 cnt = 0; + u32 patch_addr_reg = 0x1e5318; + u32 patch_num_reg = 0x1e531c; + + if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { + patch_addr_reg = 0x1e5304; + patch_num_reg = 0x1e5308; + } + + ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); + if (ret) { + printk("patch rd fail\n"); + return ret; + } + + config_base = rd_patch_addr_cfm.memdata; + + ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr); + if (ret) { + printk("0x%x write fail\n", patch_addr_reg); + return ret; + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num); + if (ret) { + printk("0x%x write fail\n", patch_num_reg); + return ret; + } + + for (cnt = 0; cnt < patch_num/2; cnt += 1) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base); + if (ret) { + printk("%x write fail\n", start_addr+8*cnt); + return ret; + } + + ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]); + if (ret) { + printk("%x write fail\n", start_addr+8*cnt+4); + return ret; + } + } + + return 0; +} + +static int aicwifi_init(struct aic_sdio_dev *sdiodev) +{ + if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { + printk("download wifi fw fail\n"); + return -1; + } + + if (aicwifi_patch_config(sdiodev)) { + printk("aicwifi_patch_config fail\n"); + return -1; + } + + if (aicwifi_sys_config(sdiodev)) { + printk("aicwifi_sys_config fail\n"); + return -1; + } + + if (aicwifi_start_from_bootrom(sdiodev)) { + printk("wifi start fail\n"); + return -1; + } + + return 0; +} + +static int aicbsp_system_config(struct aic_sdio_dev *sdiodev) +{ + int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2; + int ret, cnt; + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]); + if (ret) { + sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret); + return ret; + } + } + return 0; +} + +int aicbsp_8800d_fw_init(struct aic_sdio_dev *sdiodev) +{ + const u32 mem_addr = 0x40500000; + struct dbg_mem_read_cfm rd_mem_addr_cfm; + + uint8_t binding_status; + uint8_t dout[16]; + + need_binding_verify = false; + aicbsp_firmware_list = fw_u02; + + if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) + return -1; + + aicbsp_info.chipinfo->rev = (u8)(rd_mem_addr_cfm.memdata >> 16); + if (aicbsp_info.chipinfo->rev != CHIP_REV_U02 && + aicbsp_info.chipinfo->rev != CHIP_REV_U03 && + aicbsp_info.chipinfo->rev != CHIP_REV_U04) { + pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chipinfo->rev); + return -1; + } + + printk("aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chipinfo->rev); + + if (aicbsp_info.chipinfo->rev != CHIP_REV_U02) + aicbsp_firmware_list = fw_u03; + + if (aicbsp_system_config(sdiodev)) + return -1; + + if (aicbt_init(sdiodev)) + return -1; + + if (aicwifi_init(sdiodev)) + return -1; + + if (need_binding_verify) { + printk("aicbsp: crypto data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", + binding_enc_data[0], binding_enc_data[1], binding_enc_data[2], binding_enc_data[3], + binding_enc_data[4], binding_enc_data[5], binding_enc_data[6], binding_enc_data[7], + binding_enc_data[8], binding_enc_data[9], binding_enc_data[10], binding_enc_data[11], + binding_enc_data[12], binding_enc_data[13], binding_enc_data[14], binding_enc_data[15]); + + /* calculate verify data from crypto data */ + if (wcn_bind_verify_calculate_verify_data(binding_enc_data, dout)) { + pr_err("aicbsp: %s, binding encrypt data incorrect\n", __func__); + return -1; + } + + printk("aicbsp: verify data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", + dout[0], dout[1], dout[2], dout[3], + dout[4], dout[5], dout[6], dout[7], + dout[8], dout[9], dout[10], dout[11], + dout[12], dout[13], dout[14], dout[15]); + + if (rwnx_send_dbg_binding_req(sdiodev, dout, &binding_status)) { + pr_err("aicbsp: %s, send binding request failn", __func__); + return -1; + } + + if (binding_status) { + pr_err("aicbsp: %s, binding verify fail\n", __func__); + return -1; + } + } + + if (aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_WAKEUP_REG, 4)) { + sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); + return -1; + } + + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800dc.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800dc.c new file mode 100644 index 000000000..62e7e716c --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_8800dc.c @@ -0,0 +1,791 @@ +/** + ****************************************************************************** + * + * aic_bsp_8800dc.c + * + * Copyright (C) RivieraWaves 2014-2019 + * + ****************************************************************************** + */ + +#include +#include +#include +#include "aicsdio_txrxif.h" +#include "aicsdio.h" +#include "aic_bsp_driver.h" + +#define RAM_LMAC_FW_ADDR 0x00150000 +#define RAM_FMAC_FW_ADDR 0x00120000 +#define ROM_FMAC_PATCH_ADDR 0x00180000 +#define RAM_8800DC_ADID_ADDR 0x001017d8 +#define RAM_8800DC_FW_PATCH_ADDR 0x00184000 +#define RF_PATCH_NAME_8800DC "aic8800dc/fmacfw_rf_patch.bin" + +typedef u32 (*array2_tbl_t)[2]; + +static u32 syscfg_tbl_masked_8800dc[][3] = { + //#ifdef CONFIG_PMIC_SETTING +#if defined(CONFIG_VRF_DCDC_MODE) + {0x7000216C, (0x3 << 2), (0x1 << 2)}, // pmic_pmu_init + {0x700021BC, (0x3 << 2), (0x1 << 2)}, + {0x70002118, ((0x7 << 4) | (0x1 << 7)), ((0x2 << 4) | (0x1 << 7))}, + {0x70002104, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, + {0x7000210C, ((0x3F << 0) | (0x1 << 6)), ((0x2 << 0) | (0x1 << 6))}, + {0x70002190, (0x3F << 0), (24 << 0)}, + {0x700021CC, ((0x7 << 4) | (0x1 << 7)), ((0x0 << 4) | (0x0 << 7))}, + {0x700010A0, (0x1 << 11), (0x1 << 11)}, + {0x70001038, (0x1 << 8), (0x1 << 8)}, + {0x70001094, (0x3 << 2), (0x0 << 2)}, + {0x700021D0, ((0x1 << 5) | (0x1 << 6)), ((0x1 << 5) | (0x1 << 6))}, + {0x70001000, ((0x1 << 0) | (0x1 << 20) | (0x1 << 22)), + ((0x1 << 0) | (0x1 << 20) | (0x0 << 22))}, +#endif + //#endif /* CONFIG_PMIC_SETTING */ + {0x00000000, 0x00000000, 0x00000000}, // last one +}; + +static u32 syscfg_tbl_masked_8800dc_u01[][3] = { + //#ifdef CONFIG_PMIC_SETTING + {0x70001000, (0x1 << 16), (0x1 << 16)}, // for low temperature + {0x70001028, (0x1 << 6), (0x1 << 6)}, + {0x70001000, (0x1 << 16), (0x0 << 16)}, + //#endif /* CONFIG_PMIC_SETTING */ +}; + +static u32 syscfg_tbl_8800dc[][2] = { + {0x40500010, 0x00000004}, + {0x40500010, 0x00000006},//160m clk +}; + +static u32 syscfg_tbl_8800dc_sdio_u01[][2] = { + {0x40030000, 0x00036724}, // loop forever after assert_err + {0x0011E800, 0xE7FE4070}, + {0x40030084, 0x0011E800}, + {0x40030080, 0x00000001}, + {0x4010001C, 0x00000000}, +}; + +static u32 syscfg_tbl_8800dc_sdio_u02[][2] = { + {0x40030000, 0x00036DA4}, // loop forever after assert_err + {0x0011E800, 0xE7FE4070}, + {0x40030084, 0x0011E800}, + {0x40030080, 0x00000001}, + {0x4010001C, 0x00000000}, +}; + +static u32 patch_tbl_wifisetting_8800dc_u01[][2] = { + {0x010c, 0x01001E01} +}; + +static u32 patch_tbl_wifisetting_8800dc_u02[][2] = { + {0x0124, 0x01001E01} +}; + +static u32 jump_tbl[][2] = { +#ifndef CONFIG_FOR_IPCOM + {296, 0x180001}, + {137, 0x180011}, + {303, 0x1810f9}, + {168, 0x18186d}, + {308, 0x181bbd}, + {288, 0x1820c1}, +#else + {308, 0x181001}, + {288, 0x181031}, + {296, 0x18120d}, + {137, 0x18121d}, + {303, 0x182305}, + {168, 0x182a79}, + {258, 0x182ae1}, +#endif +}; + +static uint32_t ldpc_cfg_ram[] = { +#ifdef CONFIG_FPGA_VERIFICATION + 0x00363638, 0x1DF8F834, 0x1DF8F834, 0x1DF8F834, 0x1DF8F834, 0x002F2F31, 0x1DF8F82C, 0x1DF8F82C, + 0x1DF8F82C, 0x1DF8F82C, 0x00363639, 0x1AA5F834, 0x1AA5F834, 0x1ADEF834, 0x1ADEF834, 0x003A3A3E, + 0x1578F436, 0x1578F436, 0x1578F436, 0x15B6F436, 0x003B3B40, 0x1DF8F838, 0x1DF8F838, 0x1DF8F838, + 0x1DF8F838, 0x003B3B41, 0x1DC4F838, 0x1DC4F838, 0x1DF8F838, 0x1DF8F838, 0x003B3B40, 0x1781F838, + 0x1781F838, 0x1781F838, 0x17C4F838, 0x003B3B40, 0x0E81F838, 0x0E81F838, 0x0E81F838, 0x0E82F838, + 0x003F3F43, 0x1A92F83D, 0x1A92F83E, 0x1A92F83D, 0x1ADDF83D, 0x00272729, 0x1DF8F824, 0x1DF8F824, + 0x1DF8F843, 0x1DF8F843, 0x00272729, 0x1DF8F824, 0x1DF8F824, 0x1DF8F842, 0x1DF8F842, 0x00262628, + 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x00252528, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, + 0x1DF8F823, 0x00262628, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x00242427, 0x1DF8F821, + 0x1DF8F821, 0x1DF8F821, 0x1DF8F821, 0x00232326, 0x1DF8F821, 0x1DF8F820, 0x1DF8F820, 0x1DF8F820, + 0x00262628, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, 0x00242427, 0x1DF8F821, 0x1DF8F821, + 0x1DF8F821, 0x1DF8F821, 0x001F1F21, 0x1DF8F81D, 0x1DF8F81D, 0x1DF8F81D, 0x1DF8F81D, 0x00262643, + 0x1DF8F822, 0x1DF8F821, 0x1DF8F821, 0x1DF8F821, 0x0018182B, 0x1DF8F816, 0x1DBDF815, 0x1DF8F815, + 0x1DF8F815, 0x0018182A, 0x1195F836, 0x1195F815, 0x1195F815, 0x1196F815, 0x0028282C, 0x1DF8F824, + 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, 0x0027272C, 0x1DF8F824, 0x1DF8F823, 0x1DF8F823, 0x1DF8F823, + 0x0082824A, 0x1ADFF841, 0x1ADDF822, 0x1ADEF822, 0x1ADFF822, 0x003E3E40, 0x09D1F81D, 0x095BF81D, + 0x095BF81D, 0x095BF81D, 0x0029292D, 0x1DF8F825, 0x1DF8F825, 0x1DF8F825, 0x1DF8F825, 0x0028282C, + 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, 0x0029292D, 0x1DF8F825, 0x1DF8F825, 0x1DF8F825, + 0x1DF8F825, 0x0028282E, 0x1DF8F825, 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, 0x0026262C, 0x1DF8F823, + 0x1DF8F822, 0x1DF8F822, 0x1DF8F822, 0x0028282D, 0x1DF8F825, 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, + 0x00282852, 0x1DF8F827, 0x1DF8F824, 0x1DF8F824, 0x1DF8F824, 0x0029294E, 0x1DF8F823, 0x1DF8F822, + 0x1DF8F822, 0x1DF8F822, 0x00212143, 0x1DF8F821, 0x1DECF81D, 0x1DF4F81D, 0x1DF8F81D, 0x0086864D, + 0x1CF0F844, 0x1CEDF823, 0x1CEFF822, 0x1CF0F822, 0x0047474D, 0x1BE8F823, 0x1BE8F823, 0x1BE9F822, + 0x1BEAF822, 0x0018182F, 0x14B0F83C, 0x14B0F814, 0x14B0F814, 0x14B0F814, 0x00404040, 0x0AE1F81E, + 0x0A61F81D, 0x0A61F81D, 0x0A61F81D, 0x002C2C40, 0x09555526, 0x09555512, 0x09555513, 0x09555512, + 0x00181840, 0x06333329, 0x06333314, 0x06333314, 0x06333314, 0x002B2B2F, 0x1DF8F828, 0x1DF8F828, + 0x1DF8F828, 0x1DF8F828, 0x002B2B32, 0x1DF8F829, 0x1DF8F828, 0x1DF8F828, 0x1DF8F828, 0x002A2A2F, + 0x1DF8F827, 0x1DF8F827, 0x1DF8F827, 0x1DF8F827, 0x002A2A57, 0x1DF8F82B, 0x1DF8F827, 0x1DF8F827, + 0x1DF8F827, 0x00919152, 0x1DF8F84B, 0x1DF8F825, 0x1DF8F825, 0x1DF8F825, 0x004C4C51, 0x1DF8F826, + 0x1DF8F825, 0x1DF8F825, 0x1DF8F825, 0x00444440, 0x0CF8F820, 0x0C6EF81F, 0x0C6EF81F, 0x0C6EF81F, + 0x00424240, 0x0D75753E, 0x0D75751E, 0x0D75751E, 0x0D75751E, 0x00191940, 0x0539392E, 0x05393914, + 0x05393914, 0x05393914, 0x002F2F32, 0x1AA5F82C, 0x1AA5F82C, 0x1ADEF82C, 0x1ADEF82C, 0x002F2F40, + 0x0C6EDE2C, 0x0C6EDE2C, 0x0C6EDE2C, 0x0C6EDE2C, 0x00323240, 0x053BB62E, 0x053BB62E, 0x053BB62E, + 0x053BB62E, 0x00333339, 0x1DC4F82F, 0x1DC4F82F, 0x1DF8F82F, 0x1DF8F82F, 0x00333340, 0x0E81F82F, + 0x0E81F82F, 0x0E81F82F, 0x0E82F82F, 0x00333340, 0x063FC42F, 0x063FC42F, 0x063FC42F, 0x063FC42F, + 0x00404040, 0x063FC42F, 0x063FC42F, 0x063FC42F, 0x063FC42F, 0x00363640, 0x0747DD33, 0x0747DD33, + 0x0747DD33, 0x0747DD33, 0x00404040, 0x0747DD33, 0x0747DD33, 0x0747DD33, 0x0747DD33, 0x00292940, + 0x07484825, 0x07484812, 0x07484812, 0x07484812, 0x00404040, 0x07343428, 0x07343414, 0x07343414, + 0x07343414, 0x00404040, 0x0538382A, 0x05383814, 0x05383814, 0x05383814, 0x00404040, 0x05292914, + 0x05292909, 0x05292909, 0x05292909, 0x000B0B40, 0x02111108, 0x0211110E, 0x02111108, 0x02111108, + 0x00404040, 0x063E3E2E, 0x063E3E15, 0x063E3E14, 0x063E3E14, 0x00404040, 0x062E2E14, 0x062E2E09, + 0x062E2E09, 0x062E2E09, 0x000B0B40, 0x02131308, 0x0213130F, 0x02131308, 0x02131308, +#else + 0x00767679, 0x1DF8F870, 0x1DF8F870, 0x1DF8F870, 0x1DF8F870, 0x006E6E72, 0x1DF8F869, 0x1DF8F869, + 0x1DF8F869, 0x1DF8F869, 0x0076767B, 0x1DF8F870, 0x1DF8F870, 0x1DF8F870, 0x1DF8F870, 0x007E7E85, + 0x1DF4F876, 0x1DF4F876, 0x1DF4F876, 0x1DF8F876, 0x0081818A, 0x1DF8F87B, 0x1DF8F87B, 0x1DF8F87B, + 0x1DF8F87B, 0x0081818D, 0x1DF8F87B, 0x1DF8F87B, 0x1DF8F87B, 0x1DF8F87B, 0x0081818A, 0x1DF8F87B, + 0x1DF8F87C, 0x1DF8F87B, 0x1DF8F87B, 0x007E7E40, 0x1DF8F87B, 0x1DF8F87B, 0x1DF8F87B, 0x1DF8F87B, + 0x008B8B92, 0x1DF8F887, 0x1DF8F889, 0x1DF8F887, 0x1DF8F887, 0x00515155, 0x1DF8F84C, 0x1DF8F84C, + 0x1DF8F889, 0x1DF8F889, 0x00515154, 0x1DF8F84C, 0x1DF8F84C, 0x1DF8F888, 0x1DF8F888, 0x004F4F53, + 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x004F4F53, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, + 0x1DF8F84A, 0x004F4F53, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x004E4E53, 0x1DF8F849, + 0x1DF8F848, 0x1DF8F848, 0x1DF8F848, 0x004D4D52, 0x1DF8F847, 0x1DF8F847, 0x1DF8F847, 0x1DF8F847, + 0x004F4F55, 0x1DF8F84B, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x004E4E53, 0x1DF8F849, 0x1DF8F848, + 0x1DF8F848, 0x1DF8F848, 0x0049494D, 0x1DF8F844, 0x1DF8F844, 0x1DF8F844, 0x1DF8F844, 0x0051518F, + 0x1DF8F849, 0x1DF8F848, 0x1DF8F848, 0x1DF8F848, 0x00424277, 0x1DF8F83F, 0x1DF8F83C, 0x1DF8F83C, + 0x1DF8F83C, 0x00424275, 0x1DF8F89E, 0x1DF8F83C, 0x1DF8F83C, 0x1DF8F83C, 0x0055555C, 0x1DF8F84C, + 0x1DF8F84C, 0x1DF8F84C, 0x1DF8F84C, 0x0053535C, 0x1DF8F84C, 0x1DF8F84B, 0x1DF8F84B, 0x1DF8F84B, + 0x00F8F89E, 0x1DF8F88C, 0x1DF8F84A, 0x1DF8F84A, 0x1DF8F84A, 0x00898940, 0x18F8F846, 0x18CFF845, + 0x18CFF844, 0x18CFF844, 0x0056565F, 0x1DF8F84F, 0x1DF8F84F, 0x1DF8F84F, 0x1DF8F84F, 0x0055555E, + 0x1DF8F84E, 0x1DF8F84E, 0x1DF8F84E, 0x1DF8F84E, 0x0056565F, 0x1DF8F84F, 0x1DF8F84F, 0x1DF8F84F, + 0x1DF8F84F, 0x00555561, 0x1DF8F850, 0x1DF8F84E, 0x1DF8F84E, 0x1DF8F84E, 0x0053535F, 0x1DF8F84D, + 0x1DF8F84C, 0x1DF8F84C, 0x1DF8F84C, 0x0055555F, 0x1DF8F84F, 0x1DF8F84E, 0x1DF8F84E, 0x1DF8F84E, + 0x005555AA, 0x1DF8F854, 0x1DF8F84E, 0x1DF8F84E, 0x1DF8F84E, 0x005959A6, 0x1DF8F84D, 0x1DF8F84C, + 0x1DF8F84C, 0x1DF8F84C, 0x004F4F9B, 0x1DF8F84E, 0x1DF8F846, 0x1DF8F846, 0x1DF8F846, 0x00F8F8A5, + 0x1DF8F894, 0x1DF8F84C, 0x1DF8F84C, 0x1DF8F84C, 0x009898A4, 0x1DF8F84D, 0x1DF8F84C, 0x1DF8F84C, + 0x1DF8F84C, 0x00464686, 0x1DF8F8B3, 0x1DF8F83D, 0x1DF8F83D, 0x1DF8F83D, 0x008E8E40, 0x1AF8F848, + 0x1ADFF848, 0x1ADFF846, 0x1ADFF846, 0x007F7F40, 0x18D2D275, 0x18D2D23A, 0x18D2D23A, 0x18D2D239, + 0x00454540, 0x0F868664, 0x0F86863E, 0x0F86863D, 0x0F86863D, 0x005C5C64, 0x1DF8F856, 0x1DF8F855, + 0x1DF8F855, 0x1DF8F855, 0x005B5B68, 0x1DF8F858, 0x1DF8F855, 0x1DF8F855, 0x1DF8F855, 0x005A5A64, + 0x1DF8F855, 0x1DF8F854, 0x1DF8F854, 0x1DF8F854, 0x005A5AB5, 0x1DF8F85B, 0x1DF8F855, 0x1DF8F854, + 0x1DF8F854, 0x00F8F8B0, 0x1DF8F8A3, 0x1DF8F852, 0x1DF8F852, 0x1DF8F852, 0x00A4A4AE, 0x1DF8F854, + 0x1DF8F852, 0x1DF8F852, 0x1DF8F852, 0x009A9A40, 0x1DF8F84E, 0x1DF8F84D, 0x1DF8F84C, 0x1DF8F84C, + 0x009C9C40, 0x1DF8F895, 0x1DF8F849, 0x1DF8F84A, 0x1DF8F84A, 0x00494940, 0x1197976F, 0x11979742, + 0x11979741, 0x11979741, 0x006E6E74, 0x1DF8F869, 0x1DF8F869, 0x1DF8F869, 0x1DF8F869, 0x006E6E40, + 0x1ADEF869, 0x1ADEF869, 0x1ADEF869, 0x1ADEF869, 0x00757540, 0x0D78F86E, 0x0D78F86E, 0x0D78F86E, + 0x0D79F86E, 0x00787885, 0x1DF8F873, 0x1DF8F873, 0x1DF8F873, 0x1DF8F873, 0x00787840, 0x1DF8F873, + 0x1DF8F873, 0x1DF8F873, 0x1DF8F873, 0x00787840, 0x0E81F873, 0x0E81F873, 0x0E81F873, 0x0E82F873, + 0x00404040, 0x0E82F873, 0x0E82F873, 0x0E82F873, 0x0E82F873, 0x00818140, 0x1092F87E, 0x1092F87E, + 0x1092F87E, 0x1092F87E, 0x00404040, 0x1092F87E, 0x1092F87E, 0x1092F87E, 0x1092F87E, 0x00737340, + 0x14B2B26B, 0x14B2B235, 0x14B2B235, 0x14B2B235, 0x00404040, 0x0E828260, 0x0E82823D, 0x0E82823C, + 0x0E82823C, 0x00404040, 0x0F8B8B66, 0x0F8B8B3F, 0x0F8B8B3D, 0x0F8B8B3D, 0x00404040, 0x0B68683D, + 0x0B68681E, 0x0B68681E, 0x0B68681E, 0x00222240, 0x06434318, 0x06434329, 0x06434318, 0x06434318, + 0x00404040, 0x129D9D72, 0x129D9D43, 0x129D9D41, 0x129D9D41, 0x00404040, 0x0D757542, 0x0D757520, + 0x0D757520, 0x0D757520, 0x00232340, 0x084C4C19, 0x084C4C2C, 0x084C4C19, 0x084C4C19, +#endif +}; + +static uint32_t agc_cfg_ram[] = { + 0x20000000, 0x0400000E, 0x3000200E, 0x5B000000, 0x0400004B, 0x3000008E, 0x32000000, 0x0400007B, + 0x40000000, 0xF8000026, 0x04000011, 0x4819008E, 0x9C000020, 0x08000191, 0x38008000, 0x0A000000, + 0x08104411, 0x38018000, 0x0C004641, 0x08D00014, 0x30000000, 0x01000000, 0x04000017, 0x30000000, + 0x3C000000, 0x0400001A, 0x38020000, 0x40000001, 0x0800001D, 0x3808008E, 0x14000050, 0x08000020, + 0x4000008E, 0xA400007B, 0x00000101, 0x3000339F, 0x41000700, 0x04104420, 0x90000000, 0x49000000, + 0xF00E842F, 0xEC0E842C, 0xEC0E842C, 0x04000032, 0x30000000, 0x48000101, 0x04000032, 0x30000000, + 0x48000202, 0x04000032, 0x30000000, 0x46000000, 0x04000011, 0x58010006, 0x3D040472, 0xDC204439, + 0x081DD4D2, 0x480A0006, 0xDC2044DC, 0x081DD43C, 0x38050004, 0x0EF1F1C3, 0x342044DC, 0x30000000, + 0x01000000, 0x04000042, 0x30000000, 0x33000000, 0x04104445, 0x38008000, 0x2200109C, 0x08104448, + 0x38008000, 0x23D4509C, 0x08104417, 0x9000A000, 0x32000000, 0x18000063, 0x14000060, 0x1C000051, + 0x10000057, 0x38028000, 0x0C000001, 0x08D04466, 0x3000200F, 0x00000000, 0x00000000, 0x38030000, + 0x0C002601, 0x08D0445A, 0x30000000, 0x3D020230, 0x0400005D, 0x30000000, 0x3E000100, 0x04000066, + 0x38028000, 0x0C001601, 0x34204466, 0x38028000, 0x0C000A01, 0x34204466, 0x38008004, 0xFF000000, + 0x0800007B, 0x3800802F, 0x26000000, 0x0800006C, 0x380404AF, 0x1F191010, 0x0800006F, 0x20000CAF, + 0x04000071, 0x60000CAF, 0x18700079, 0x14000077, 0x10000075, 0x28140CAF, 0x09B00084, 0x280A0CAF, + 0x09B00084, 0x28060CAF, 0x09B00084, 0x28048086, 0x0800007D, 0x38000086, 0x22800000, 0x04000080, + 0x30000000, 0x0EF1F101, 0x36004883, 0x28020000, 0x08000085, 0x3802008E, 0x3D040431, 0x08000088, + 0x3805008E, 0x1F241821, 0x0800008B, 0x3000008E, 0xA0163021, 0x0400008E, 0x3000008E, 0x0EF10012, + 0x34000091, 0x300000CC, 0x50000000, 0x04000094, 0x380095FE, 0x32010000, 0x04000097, 0x50001FFE, + 0x5A010000, 0x6DC9989B, 0xFC19D4B9, 0x30000186, 0x3D840373, 0x0400009E, 0x3000008E, 0x0A000000, + 0x040000A1, 0x3000008E, 0x22C00000, 0x040000A4, 0x9000028E, 0x32010001, 0x8E4000AA, 0xC80000B0, + 0x00000000, 0x00000000, 0x3000008E, 0x32010001, 0x040000CB, 0x3000008E, 0x29000000, 0x94045011, + 0x300019B6, 0x32010000, 0x040000B3, 0x300019B6, 0x3D040431, 0x040000B6, 0x300019B6, 0x22800000, + 0x04000097, 0x30000186, 0x3D840473, 0x040000BC, 0x3000008E, 0x29030000, 0x040000BF, 0x9AEE028E, + 0x32010100, 0x7C0000C5, 0xCC0000B0, 0x080000B0, 0x00000000, 0x3000008E, 0x32010100, 0x040000C8, + 0x3000028E, 0x29000000, 0x94045011, 0x5000038E, 0x29000000, 0x94045011, 0xC0000035, 0x38010006, + 0x3D040472, 0x080000D2, 0x30000004, 0x0EF1F141, 0x340000D5, 0x28040004, 0x080000D7, 0x2808000E, + 0x080000D9, 0x3000018E, 0x0EF10052, 0x340000DC, 0x3000038E, 0x29000000, 0x94045011, 0x38020000, + 0x32000000, 0x080000E2, 0x60000000, 0xD80000E6, 0xD40000E9, 0x040000EC, 0x30000000, 0x0EF1F121, + 0x360048EF, 0x30000000, 0x0C002421, 0x360048EF, 0x30000000, 0x0C000021, 0x360048EF, 0x28020000, + 0x0800007B, 0x50001EFE, 0x5A010000, 0x6DC998F5, 0xFC19D4F8, 0x3000028E, 0x32000040, 0x040000FB, + 0x3AEE028E, 0x32000080, 0x040000FB, 0x30000000, 0x0EF1F101, 0x360048FE, 0x28020000, 0x08000100, + 0x3802008E, 0x3D040431, 0x08000103, 0x3805008E, 0x1F241821, 0x08000106, 0x3000008E, 0xA0163021, + 0x04000109, 0x3000008E, 0x0EF10012, 0x3400010C, 0x300014F6, 0x32010000, 0x04000114, 0x20000000, + 0x04000111, 0x300000EC, 0x50000000, 0x040000F1, 0x300014F6, 0x32030000, 0x04000117, 0x30001086, + 0x3D840473, 0x0400011A, 0x5000108E, 0x22C00000, 0x8E47C0CB, 0xCB30011E, 0x300019B6, 0x32040000, + 0x04000121, 0x300019B6, 0x3D040431, 0x04000124, 0x300019B6, 0x22800000, 0x04000111, 0x00000000, + 0x00000000, 0x00000000, 0x30000186, 0x3D840473, 0x0400012D, 0x5000038E, 0x29000000, 0x94045011, + 0xC0000131, 0x380C800E, 0xFF000000, 0x08000134, 0x30000004, 0x0FF1F103, 0x34000137, 0x28020000, + 0x08000139, 0x3000038E, 0x29000000, 0x94045011, 0x00000000, 0x00000000, 0x00000000, 0x58010006, + 0x3D040472, 0xDC204543, 0x081DD4D2, 0x480A0006, 0xDC2044DC, 0x081DD546, 0x38050004, 0x0EF1F141, + 0x342044DC, 0x2802800E, 0x080000DC, 0x48000035, 0x0400014A, 0x7896638F, 0x4100000F, 0x8C00014F, + 0x080450C4, 0x90104574, 0x88C8620F, 0xC000015A, 0x90104574, 0x08104554, 0x94104557, 0x3000628F, + 0x29000000, 0x9404517A, 0x3000638F, 0x29000000, 0x0410457A, 0x3800E005, 0x3D010131, 0x0810455D, + 0xA832600F, 0x90104574, 0x08000154, 0x94104557, 0xC6104567, 0xC4185563, 0x5802E00F, 0x0FEEEA07, + 0x80000174, 0x3420456B, 0x5802E00F, 0x0EEEEA07, 0x80000174, 0x3420456B, 0x30004000, 0x33000001, + 0x0400016E, 0x38034005, 0x3D030373, 0x08000171, 0x30006007, 0x33000000, 0x04000174, 0x3000608F, + 0x29000000, 0x94045177, 0x4000608F, 0xA010457D, 0x0410457A, 0x3000608F, 0x64000101, 0x04104411, + 0x3000608F, 0x64000101, 0x04104580, 0x3000618F, 0x42000001, 0x04000183, 0x38028000, 0x32000000, + 0x08104586, 0x280A618F, 0x08000188, 0x480A618F, 0xBC00018B, 0x0800018E, 0x3000618F, 0x34000001, + 0x04000005, 0x3000618F, 0x34000000, 0x04000008, 0x3000008F, 0x0EEAED0F, 0x36000194, 0x38038000, + 0x34000000, 0x08000197, 0x38028005, 0x29010002, 0x0800019A, 0x3000028F, 0x2200209C, 0x0400019D, + 0x3000028F, 0x23D4509C, 0x040001A0, 0x2814028F, 0x080001A2, 0x3000028F, 0x43010201, 0x040001A5, + 0x3000128F, 0x32000100, 0x040001A8, 0x5AEE138F, 0x4100000F, 0x7C0001AC, 0x080000F9, 0x592C138F, + 0x29000000, 0x8C0001B0, 0x080000F9, 0x2000138F, 0x94045011, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static uint32_t txgain_map[96] = { +#ifdef CONFIG_FPGA_VERIFICATION + 0x20c0c971, 0x20c0c980, 0x20c0c992, 0x20c0c9a6, 0x20c0c9bf, 0x20c0caa5, 0x20c0cabd, 0x20c0cba0, + 0x20c0cbb6, 0x20c0cbea, 0x20c0ccc5, 0x20c0cdac, 0x20c0cdd0, 0x20c0ceb2, 0x20c0ceff, 0x20c0cfff, + 0x20c0c922, 0x20c0c922, 0x20c0c922, 0x20c0c922, 0x20c0c922, 0x20c0c922, 0x20c0c922, 0x20c0c927, + 0x20c0c92c, 0x20c0c931, 0x20c0c937, 0x20c0c93f, 0x20c0c946, 0x20c0c94f, 0x20c0c959, 0x20c0c964, + 0x20c0cbee, 0x20c0cce0, 0x20c0ccff, 0x20c0cde2, 0x20c0cdfe, 0x20c0cede, 0x20c0cefc, 0x20c0cfd9, + 0x20c0cff8, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, + 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c98c, + 0x20c0ca79, 0x20c0ca89, 0x20c0cb74, 0x20c0cb84, 0x20c0cb94, 0x20c0cba8, 0x20c0cbbb, 0x20c0cbd2, + 0x20c0cbee, 0x20c0cce0, 0x20c0ccff, 0x20c0cde2, 0x20c0cdfe, 0x20c0cede, 0x20c0cefc, 0x20c0cfd9, + 0x20c0cff8, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, 0x20c0cfff, + 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c97c, 0x20c0c98c, + 0x20c0ca79, 0x20c0ca89, 0x20c0cb74, 0x20c0cb84, 0x20c0cb94, 0x20c0cba8, 0x20c0cbbb, 0x20c0cbd2, +#else + 0x00ffc772, 0x00ffc780, 0x00ffc872, 0x00ffc880, 0x00ffc970, 0x00ffc980, 0x00ffc990, 0x00ffca80, + 0x00ffca9a, 0x00ffcb90, 0x00ffcc95, 0x00ffce80, 0x00ffcf80, 0x00ffcf80, 0x00ffcf80, 0x00ffcf80, + 0x00ffc05b, 0x00ffc066, 0x00ffc070, 0x00ffc080, 0x00ffc175, 0x00ffc185, 0x00ffc272, 0x00ffc280, + 0x00ffc290, 0x00ffc380, 0x00ffc472, 0x00ffc483, 0x00ffc572, 0x00ffc580, 0x00ffc590, 0x00ffc680, + 0x00ffc87d, 0x00ffc88b, 0x00ffc979, 0x00ffc989, 0x00ffca7d, 0x00ffca8d, 0x00ffcb7a, 0x00ffcb8a, + 0x00ffcc7d, 0x00ffcc8d, 0x00ffcd79, 0x00ffcd89, 0x00ffce7d, 0x00ffce8d, 0x00ffcf80, 0x00ffcf99, + 0x00ffc080, 0x00ffc090, 0x00ffc180, 0x00ffc190, 0x00ffc27b, 0x00ffc28b, 0x00ffc37b, 0x00ffc38b, + 0x00ffc480, 0x00ffc490, 0x00ffc579, 0x00ffc589, 0x00ffc679, 0x00ffc689, 0x00ffc780, 0x00ffc790, + 0x00ffc87d, 0x00ffc88b, 0x00ffc979, 0x00ffc989, 0x00ffca7d, 0x00ffca8d, 0x00ffcb7a, 0x00ffcb8a, + 0x00ffcc7d, 0x00ffcc8d, 0x00ffcd79, 0x00ffcd89, 0x00ffce7d, 0x00ffce8d, 0x00ffcf80, 0x00ffcf99, + 0x00ffc080, 0x00ffc090, 0x00ffc180, 0x00ffc190, 0x00ffc27b, 0x00ffc28b, 0x00ffc37b, 0x00ffc38b, + 0x00ffc480, 0x00ffc490, 0x00ffc579, 0x00ffc589, 0x00ffc679, 0x00ffc689, 0x00ffc780, 0x00ffc790, +#endif +}; + +static uint32_t txgain_table[32] = { + 0xA4B22189, 0x00007825, 0xA4B2214B, 0x00007825, 0xA4B2214F, 0x00007825, 0xA4B221D5, 0x00007825, + 0xA4B221DC, 0x00007825, 0xA4B221E5, 0x00007825, 0xAC9221E5, 0x00006825, 0xAC9221EF, 0x00006825, + 0xBC9221EE, 0x00006825, 0xBC9221FF, 0x00006825, 0xBC9221FF, 0x00004025, 0xB792203F, 0x00004026, + 0xDC92203F, 0x00004025, 0xE692203F, 0x00004025, 0xFF92203F, 0x00004035, 0xFFFE203F, 0x00004832, +}; + +static uint32_t rxgain_table_24g_20m[64] = { + 0x82f282d1, 0x9591a324, 0x80808419, 0x000000f0, 0x42f282d1, 0x95923524, 0x80808419, 0x000000f0, + 0x22f282d1, 0x9592c724, 0x80808419, 0x000000f0, 0x02f282d1, 0x9591a324, 0x80808419, 0x000000f0, + 0x06f282d1, 0x9591a324, 0x80808419, 0x000000f0, 0x0ef29ad1, 0x9591a324, 0x80808419, 0x000000f0, + 0x0ef29ad3, 0x95923524, 0x80808419, 0x000000f0, 0x0ef29ad7, 0x9595a324, 0x80808419, 0x000000f0, + 0x06f282d2, 0x95911124, 0x80808419, 0x000000f0, 0x06f282f4, 0x95911124, 0x80808419, 0x000000f0, + 0x06f282e6, 0x9591a324, 0x80808419, 0x000000f0, 0x06f282e6, 0x9595a324, 0x80808419, 0x000000f0, + 0x06f282e6, 0x9599a324, 0x80808419, 0x000000f0, 0x06f282e6, 0x959b5924, 0x80808419, 0x000000f0, + 0x06f282e6, 0x959f5924, 0x80808419, 0x000000f0, 0x0ef29ae6, 0x959f5924, 0x80808419, 0x000000f0, +}; + +static uint32_t rxgain_table_24g_40m[64] = { + 0x83428151, 0x9631a328, 0x80808419, 0x000000f0, 0x43428151, 0x96323528, 0x80808419, 0x000000f0, + 0x23428151, 0x9632c728, 0x80808419, 0x000000f0, 0x03428151, 0x9631a328, 0x80808419, 0x000000f0, + 0x07429951, 0x9631a328, 0x80808419, 0x000000f0, 0x0f42d151, 0x9631a328, 0x80808419, 0x000000f0, + 0x0f42d153, 0x96323528, 0x80808419, 0x000000f0, 0x0f42d157, 0x9635a328, 0x80808419, 0x000000f0, + 0x07429952, 0x96311128, 0x80808419, 0x000000f0, 0x07429974, 0x96311128, 0x80808419, 0x000000f0, + 0x07429966, 0x9631a328, 0x80808419, 0x000000f0, 0x07429966, 0x9635a328, 0x80808419, 0x000000f0, + 0x07429966, 0x9639a328, 0x80808419, 0x000000f0, 0x07429966, 0x963b5928, 0x80808419, 0x000000f0, + 0x07429966, 0x963f5928, 0x80808419, 0x000000f0, 0x0f42d166, 0x963f5928, 0x80808419, 0x000000f0, +}; + +static u32 patch_tbl_func[][2] = { +#ifndef CONFIG_FOR_IPCOM + {0x00110054, 0x0018186D}, // same as jump_tbl idx 168 + {0x0011005C, 0x0018186D}, // same as jump_tbl idx 168 +#else + {0x00110054, 0x00182A79}, // same as jump_tbl idx 168 + {0x0011005C, 0x00182A79}, // same as jump_tbl idx 168 + {0x001118D4, 0x00000011}, +#endif +}; + +static u32 patch_tbl_rf_func[][2] = { + {0x00110bf0, 0x00180001}, +}; + +static const struct aicbsp_firmware fw_u01[] = { + [AICBSP_CPMODE_WORK] = { + .desc = "normal work mode(sdio u01)", + .bt_adid = "aic8800dc/fw_adid.bin", + .bt_patch = "aic8800dc/fw_patch.bin", + .bt_table = "aic8800dc/fw_patch_table.bin", + .wl_fw = "aic8800dc/fmacfw_patch.bin", + .wl_table = "aic8800dc/fmacfw_patch_tbl.bin", + }, + + [AICBSP_CPMODE_TEST] = { + .desc = "rf test mode(sdio u01)", + .bt_adid = "aic8800dc/fw_adid.bin", + .bt_patch = "aic8800dc/fw_patch.bin", + .bt_table = "aic8800dc/fw_patch_table.bin", + .wl_fw = "aic8800dc/lmacfw_rf.bin", + .wl_table = NULL, + }, +}; + +static const struct aicbsp_firmware fw_u02[] = { + [AICBSP_CPMODE_WORK] = { + .desc = "normal work mode(sdio u02)", + .bt_adid = "aic8800dc/fw_adid_u02.bin", + .bt_patch = "aic8800dc/fw_patch_u02.bin", + .bt_table = "aic8800dc/fw_patch_table_u02.bin", + .wl_fw = "aic8800dc/fmacfw_patch_u02.bin", + .wl_table = "aic8800dc/fmacfw_patch_tbl_u02.bin", + }, + + [AICBSP_CPMODE_TEST] = { + .desc = "rf test mode(sdio u02)", + .bt_adid = "aic8800dc/fw_adid_u02.bin", + .bt_patch = "aic8800dc/fw_patch_u02.bin", + .bt_table = "aic8800dc/fw_patch_table_u02.bin", + .wl_fw = "aic8800dc/lmacfw_rf.bin", + .wl_table = NULL, + }, +}; + +static int aic8800dc_wifi_patch_table_load(struct aic_sdio_dev *sdiodev, const char *filename) +{ + unsigned int i = 0; + int size; + u32 *dst = NULL; + int err = 0; + + const struct firmware *fw = NULL; + int ret = request_firmware(&fw, filename, NULL); + + u32 FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE = 0X183E00; + u32 FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_SIZE = 128; + + printk("rwnx_request_firmware, name: %s\n", filename); + if (ret < 0) { + printk("Load %s fail\n", filename); + return ret; + } + + size = fw->size; + dst = (u32 *)fw->data; + + if (size <= 0) { + printk("wrong size of firmware file\n"); + release_firmware(fw); + return -1; + } + + if (!err && (i < size)) { + err = rwnx_send_dbg_mem_block_write_req(sdiodev, FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_BASE, FMACFW_PATCH_TBL_8800DC_U02_DESCRIBE_SIZE, &dst[0]); + if (err) + printk("write describe information fail\n"); + + printk("wifi patch version: %s", (char *)dst); + } + + if (!err && (i < size)) {// <1KB data + for (i = 128 / 4; i < size / 4; i += 2) + err = rwnx_send_dbg_mem_write_req(sdiodev, dst[i], dst[i+1]); + + if (err) + printk("bin upload fail: %x, err:%d\n", dst[i], err); + } + + release_firmware(fw); + return err; +} + +static int aic8800dc_wifi_patch_config(struct aic_sdio_dev *sdiodev) +{ + int ret = 0; + int cnt = 0; + if (aicbsp_info.cpmode == AICBSP_CPMODE_WORK) { + const u32 cfg_base = 0x10164; + + u32 wifisetting_cfg_addr; + u32 ldpc_cfg_addr; + u32 agc_cfg_addr; + u32 txgain_cfg_addr; + u32 jump_tbl_addr; + + u32 patch_tbl_wifisetting_num; + u32 ldpc_cfg_size = sizeof(ldpc_cfg_ram); + u32 agc_cfg_size = sizeof(agc_cfg_ram); + u32 txgain_cfg_size = sizeof(txgain_map); + u32 jump_tbl_size = sizeof(jump_tbl)/2; + u32 patch_tbl_func_num = sizeof(patch_tbl_func)/sizeof(u32)/2; + + struct dbg_mem_read_cfm cfm; + int i; + + array2_tbl_t jump_tbl_base = NULL; + array2_tbl_t patch_tbl_func_base = NULL; + array2_tbl_t patch_tbl_wifisetting_8800dc_base = NULL; + + if (aicbsp_info.chipinfo->subrev == 0) { + jump_tbl_base = jump_tbl; + jump_tbl_size = sizeof(jump_tbl)/2; + patch_tbl_func_base = patch_tbl_func; + patch_tbl_func_num = sizeof(patch_tbl_func)/sizeof(u32)/2; + patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u01)/sizeof(u32)/2; + patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u01; + } else if (aicbsp_info.chipinfo->subrev == 1) { + patch_tbl_wifisetting_num = sizeof(patch_tbl_wifisetting_8800dc_u02)/sizeof(u32)/2; + patch_tbl_wifisetting_8800dc_base = patch_tbl_wifisetting_8800dc_u02; + } else { + printk("unsupported id: %d", aicbsp_info.chipinfo->subrev); + ret = -1; + goto out; + } + + ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base, &cfm); + if (ret) { + pr_err("setting base[0x%x] rd fail: %d\n", cfg_base, ret); + goto out; + } + wifisetting_cfg_addr = cfm.memdata; + + if (aicbsp_info.chipinfo->subrev == 0) { + ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 4, &cfm); + if (ret) { + pr_err("setting base[0x%x] rd fail: %d\n", cfg_base + 4, ret); + goto out; + } + jump_tbl_addr = cfm.memdata; + } + + ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 8, &cfm); + if (ret) { + pr_err("setting base[0x%x] rd fail: %d\n", cfg_base + 8, ret); + goto out; + } + ldpc_cfg_addr = cfm.memdata; + + ret = rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0xc, &cfm); + if (ret) { + pr_err("setting base[0x%x] rd fail: %d\n", cfg_base + 0xc, ret); + goto out; + } + agc_cfg_addr = cfm.memdata; + + if (rwnx_send_dbg_mem_read_req(sdiodev, cfg_base + 0x10, &cfm)) { + pr_err("setting base[0x%x] rd fail: %d\n", cfg_base + 0x10, ret); + goto out; + } + txgain_cfg_addr = cfm.memdata; + + printk("wifisetting_cfg_addr=%x, ldpc_cfg_addr=%x, agc_cfg_addr=%x, txgain_cfg_addr=%x\n", wifisetting_cfg_addr, ldpc_cfg_addr, agc_cfg_addr, txgain_cfg_addr); + + for (cnt = 0; cnt < patch_tbl_wifisetting_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, wifisetting_cfg_addr + patch_tbl_wifisetting_8800dc_base[cnt][0], patch_tbl_wifisetting_8800dc_base[cnt][1]); + if (ret) { + pr_err("wifisetting %x write fail\n", patch_tbl_wifisetting_8800dc_base[cnt][0]); + goto out; + } + } + + if (ldpc_cfg_size > 512) {// > 0.5KB data + for (i = 0; i < (ldpc_cfg_size - 512); i += 512) {//each time write 0.5KB + ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ldpc_cfg_addr + i, 512, ldpc_cfg_ram + i / 4); + if (ret) { + pr_err("ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); + goto out; + } + } + } + + if (!ret && (i < ldpc_cfg_size)) {// < 0.5KB data + ret = rwnx_send_dbg_mem_block_write_req(sdiodev, ldpc_cfg_addr + i, ldpc_cfg_size - i, ldpc_cfg_ram + i / 4); + if (ret) { + pr_err("ldpc upload fail: %x, err:%d\r\n", ldpc_cfg_addr + i, ret); + goto out; + } + } + + if (agc_cfg_size > 512) {// > 0.5KB data + for (i = 0; i < (agc_cfg_size - 512); i += 512) {//each time write 0.5KB + ret = rwnx_send_dbg_mem_block_write_req(sdiodev, agc_cfg_addr + i, 512, agc_cfg_ram + i / 4); + if (ret) { + pr_err("agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); + goto out; + } + } + } + + if (!ret && (i < agc_cfg_size)) {// < 0.5KB data + ret = rwnx_send_dbg_mem_block_write_req(sdiodev, agc_cfg_addr + i, agc_cfg_size - i, agc_cfg_ram + i / 4); + if (ret) { + pr_err("agc upload fail: %x, err:%d\r\n", agc_cfg_addr + i, ret); + goto out; + } + } + +#if !defined(CONFIG_FPGA_VERIFICATION) + ret = rwnx_send_dbg_mem_block_write_req(sdiodev, txgain_cfg_addr, txgain_cfg_size, txgain_map); + if (ret) { + pr_err("txgain upload fail: %x, err:%d\r\n", txgain_cfg_addr, ret); + goto out; + } + + if (aicbsp_info.chipinfo->subrev == 0) { + for (cnt = 0; cnt < jump_tbl_size/4; cnt += 1) { + //printk("%x = %x\n", jump_tbl[cnt][0]*4+jump_tbl_addr, jump_tbl[cnt][1]); + ret = rwnx_send_dbg_mem_write_req(sdiodev, jump_tbl_base[cnt][0]*4+jump_tbl_addr, jump_tbl_base[cnt][1]); + if (ret) { + pr_err("%x write fail\n", jump_tbl_addr+8*cnt); + goto out; + } + } + for (cnt = 0; cnt < patch_tbl_func_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_tbl_func_base[cnt][0], patch_tbl_func_base[cnt][1]); + if (ret) { + pr_err("patch_tbl_func %x write fail\n", patch_tbl_func_base[cnt][0]); + goto out; + } + } + } else { + ret = aic8800dc_wifi_patch_table_load(sdiodev, aicbsp_firmware_list[aicbsp_info.cpmode].wl_table); + if (ret) { + printk("patch_tbl upload fail: err:%d\r\n", ret); + goto out; + } + } +#endif + ret = rwnx_send_rf_config_req(sdiodev, 0, 1, (u8 *)txgain_table, 128); + if (ret) + goto out; + + ret = rwnx_send_rf_config_req(sdiodev, 0, 0, (u8 *)rxgain_table_24g_20m, 256); + if (ret) + goto out; + + ret = rwnx_send_rf_config_req(sdiodev, 32, 0, (u8 *)rxgain_table_24g_40m, 256); + } else { + if (aicbsp_info.chipinfo->subrev == 0) { + u32 patch_tbl_rf_func_num = sizeof(patch_tbl_rf_func)/sizeof(u32)/2; + for (cnt = 0; cnt < patch_tbl_rf_func_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_tbl_rf_func[cnt][0], patch_tbl_rf_func[cnt][1]); + if (ret) { + pr_err("patch_tbl_rf_func %x write fail\n", patch_tbl_rf_func[cnt][0]); + goto out; + } + } + } + } + +out: + return ret; +} + +static int aic8800dc_bt_patch_config(struct aic_sdio_dev *sdiodev) +{ + struct aicbt_info_t btcfg = { + .btmode = AICBT_BTMODE_BT_WIFI_COMBO, + .btport = AICBT_BTPORT_DEFAULT, + .uart_baud = AICBT_UART_BAUD_DEFAULT, + .uart_flowctrl = AICBT_UART_FC_DEFAULT, + .lpm_enable = AICBT_LPM_ENABLE_DEFAULT, + .txpwr_lvl = AICBT_TXPWR_LVL_DEFAULT, + }; + + struct aicbt_patch_table *head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); + int ret = aicbt_patch_info_unpack(head, &btcfg); + + if (head == NULL) + return -1; + + if (ret) { + btcfg.addr_adid = RAM_8800DC_ADID_ADDR; + btcfg.addr_patch = RAM_8800DC_FW_PATCH_ADDR; + } + + ret = rwnx_plat_bin_fw_upload_android(sdiodev, btcfg.addr_adid, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid); + if (ret) + goto err; + + ret = rwnx_plat_bin_fw_upload_android(sdiodev, btcfg.addr_patch, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch); + if (ret) + goto err; + + ret = aicbt_patch_table_load(sdiodev, &btcfg, head); + if (ret) + printk("aicbt_patch_table_load fail\n"); + +err: + aicbt_patch_table_free(&head); + return ret; +} + +int aicbsp_8800dc_fw_init(struct aic_sdio_dev *sdiodev) +{ + u32 mem_addr = 0x40500000; + struct dbg_mem_read_cfm rd_mem_addr_cfm; + + int syscfg_num, cnt, ret; + u32 boot_type = HOST_START_APP_DUMMY; + u32 rd_addr, fw_addr, ld_addr; + + if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { + rd_addr = RAM_LMAC_FW_ADDR; + fw_addr = RAM_LMAC_FW_ADDR; + ld_addr = RAM_LMAC_FW_ADDR; + } else { + rd_addr = RAM_FMAC_FW_ADDR; + fw_addr = RAM_FMAC_FW_ADDR; + ld_addr = ROM_FMAC_PATCH_ADDR; + } + + aicbsp_firmware_list = fw_u01; + + if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) + return -1; + aicbsp_info.chipinfo->rev = (u8)(rd_mem_addr_cfm.memdata >> 16); + + aicbsp_info.chipinfo->mcuid = 0; + if (((rd_mem_addr_cfm.memdata >> 25) & 0x01UL) == 0x00UL) + aicbsp_info.chipinfo->mcuid = 1; + + mem_addr = 0x00000020; + if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) + return -1; + aicbsp_info.chipinfo->subrev = (u8)rd_mem_addr_cfm.memdata; + + printk("%s(%d), rev: %d, subrev: %d, mucid: %d\n", __func__, __LINE__, + aicbsp_info.chipinfo->rev, aicbsp_info.chipinfo->subrev, aicbsp_info.chipinfo->mcuid); + + if (aicbsp_info.chipinfo->subrev != 0 && aicbsp_info.chipinfo->subrev != 1) { + printk("%s(%d), unsupported subrev: %d\n", __func__, __LINE__, aicbsp_info.chipinfo->subrev); + return -1; + } + + if (aicbsp_info.chipinfo->rev == CHIP_REV_U02) + aicbsp_firmware_list = fw_u02; + + mem_addr = 0x40500010; + if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) + return -1; + + aic8800dc_bt_patch_config(sdiodev); + + syscfg_num = sizeof(syscfg_tbl_8800dc) / sizeof(u32) / 2; + + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, syscfg_tbl_8800dc[cnt][0], syscfg_tbl_8800dc[cnt][1]); + if (ret) { + sdio_err("%x write fail: %d\n", syscfg_tbl_8800dc[cnt][0], ret); + return ret; + } + } + + if (aicbsp_info.chipinfo->mcuid == 0) { + if (aicbsp_info.chipinfo->subrev == 0) { + syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u01) / sizeof(u32) / 2; + + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, syscfg_tbl_8800dc_sdio_u01[cnt][0], syscfg_tbl_8800dc_sdio_u01[cnt][1]); + if (ret) { + printk("%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u01[cnt][0], ret); + return ret; + } + } + } else if (aicbsp_info.chipinfo->subrev == 1) { + syscfg_num = sizeof(syscfg_tbl_8800dc_sdio_u02) / sizeof(u32) / 2; + + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_write_req(sdiodev, syscfg_tbl_8800dc_sdio_u02[cnt][0], syscfg_tbl_8800dc_sdio_u02[cnt][1]); + if (ret) { + printk("%x write fail: %d\n", syscfg_tbl_8800dc_sdio_u02[cnt][0], ret); + return ret; + } + } + } + } + + syscfg_num = sizeof(syscfg_tbl_masked_8800dc) / sizeof(u32) / 3; + + for (cnt = 0; cnt < syscfg_num; cnt++) { + if (syscfg_tbl_masked_8800dc[cnt][0] == 0x00000000) + break; + + if (syscfg_tbl_masked_8800dc[cnt][0] == 0x70001000) { + if (aicbsp_info.chipinfo->mcuid == 0) { + syscfg_tbl_masked_8800dc[cnt][1] |= ((0x1 << 8) | (0x1 << 15)); // mask + syscfg_tbl_masked_8800dc[cnt][2] |= ((0x1 << 8) | (0x1 << 15)); + } + } + + ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, + syscfg_tbl_masked_8800dc[cnt][0], syscfg_tbl_masked_8800dc[cnt][1], syscfg_tbl_masked_8800dc[cnt][2]); + if (ret) { + printk("%x mask write fail: %d\n", syscfg_tbl_masked_8800dc[cnt][0], ret); + return ret; + } + } + + if (aicbsp_info.chipinfo->subrev == 0) { + syscfg_num = sizeof(syscfg_tbl_masked_8800dc_u01) / sizeof(u32) / 3; + for (cnt = 0; cnt < syscfg_num; cnt++) { + ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, + syscfg_tbl_masked_8800dc_u01[cnt][0], syscfg_tbl_masked_8800dc_u01[cnt][1], syscfg_tbl_masked_8800dc_u01[cnt][2]); + if (ret) { + printk("%x mask write fail: %d\n", syscfg_tbl_masked_8800dc_u01[cnt][0], ret); + return ret; + } + } + } + + if (aicbsp_info.chipinfo->subrev == 0 && aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { + ret = rwnx_plat_bin_fw_upload_android(sdiodev, ROM_FMAC_PATCH_ADDR, RF_PATCH_NAME_8800DC); + if (ret) + return ret; + } + + ret = rwnx_plat_bin_fw_upload_android(sdiodev, ld_addr, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw); + if (ret) + return ret; + + aic8800dc_wifi_patch_config(sdiodev); + + printk("Read FW mem: %08x\n", rd_addr); + if (rwnx_send_dbg_mem_read_req(sdiodev, rd_addr, &rd_mem_addr_cfm)) + return -1; + + printk("cfm: [%08x] = %08x\n", rd_mem_addr_cfm.memaddr, rd_mem_addr_cfm.memdata); + + boot_type = HOST_START_APP_DUMMY; + if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) + boot_type = HOST_START_APP_AUTO; + + /* fw start */ + printk("Start app: %08x, %d\n", fw_addr, boot_type); + if (rwnx_send_dbg_start_app_req(sdiodev, fw_addr, boot_type, NULL)) + return -1; + + return 0; +} + diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c index a198b3f45..8e38d6422 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c @@ -1,10 +1,7 @@ /** ****************************************************************************** * - * rwnx_cmds.c - * - * Handles queueing (push to IPC, ack/cfm from IPC) of commands issued to - * LMAC FW + * aic_bsp_driver.c * * Copyright (C) RivieraWaves 2014-2019 * @@ -18,10 +15,9 @@ #include "aicsdio.h" #include "aic_bsp_driver.h" -static u8 binding_enc_data[16]; -static bool need_binding_verify; +u8 binding_enc_data[16]; +bool need_binding_verify; -int wcn_bind_verify_calculate_verify_data(uint8_t *din, uint8_t *dout); #ifndef CONFIG_PLATFORM_ALLWINNER int wcn_bind_verify_calculate_verify_data(uint8_t *din, uint8_t *dout) { @@ -460,6 +456,32 @@ int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 return rwnx_send_msg(sdiodev, start_app_req, 1, DBG_START_APP_CFM, start_app_cfm); } +int rwnx_send_rf_config_req(struct aic_sdio_dev *sdiodev, u8 ofst, u8 sel, u8 *tbl, u16 len) +{ + struct mm_set_rf_config_req *rf_config_req; + int error; + + /* Build the MM_SET_RF_CONFIG_REQ message */ + rf_config_req = rwnx_msg_zalloc(MM_SET_RF_CONFIG_REQ, TASK_MM, DRV_TASK_ID, + sizeof(struct mm_set_rf_config_req)); + + if (!rf_config_req) { + return -ENOMEM; + } + + rf_config_req->table_sel = sel; + rf_config_req->table_ofst = ofst; + rf_config_req->table_num = 16; + rf_config_req->deft_page = 0; + + memcpy(rf_config_req->data, tbl, len); + + /* Send the MM_SET_RF_CONFIG_REQ message to UMAC FW */ + error = rwnx_send_msg(sdiodev, rf_config_req, 1, MM_SET_RF_CONFIG_CFM, NULL); + + return error; +}; + static inline int dbg_binding_ind(struct rwnx_cmd *cmd, struct ipc_e2a_msg *msg) { struct dbg_binding_ind *ind = (struct dbg_binding_ind *)msg->param; @@ -473,7 +495,11 @@ static msg_cb_fct dbg_hdlrs[MSG_I(DBG_MAX)] = { [MSG_I(DBG_BINDING_IND)] = (msg_cb_fct)dbg_binding_ind, }; +static msg_cb_fct mm_hdlrs[MSG_I(MM_MAX)] = { +}; + static msg_cb_fct *msg_hdlrs[] = { + [TASK_MM] = mm_hdlrs, [TASK_DBG] = dbg_hdlrs, }; @@ -609,32 +635,36 @@ err: return NULL; } -int aicbt_patch_trap_data_load(struct aic_sdio_dev *sdiodev) +int aicbt_patch_info_unpack(struct aicbt_patch_table *head, struct aicbt_info_t *aicbt_info) { - uint32_t fw_ram_adid_base_addr = FW_RAM_ADID_BASE_ADDR; - if (aicbsp_info.chip_rev != CHIP_REV_U02) - fw_ram_adid_base_addr = FW_RAM_ADID_BASE_ADDR_U03; + struct aicbt_patch_table *p; + int ret = -1; - if (rwnx_plat_bin_fw_upload_android(sdiodev, fw_ram_adid_base_addr, aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid)) - return -1; - if (rwnx_plat_bin_fw_upload_android(sdiodev, FW_RAM_PATCH_BASE_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch)) - return -1; - return 0; + for (p = head; p != NULL; p = p->next) { + if (AICBT_PT_INF == p->type) { + aicbt_info->addr_adid = *(p->data + 1); + aicbt_info->addr_patch = *(p->data + 3); + printk("%s bt adid addr: 0x%08x, patch addr: 0x%08x\n", __func__, aicbt_info->addr_adid, aicbt_info->addr_patch); + ret = 0; + } + + if (AICBT_PT_VER == p->type) { + printk("%s bt patch version: %s\n", __func__, (char *)p->data); + } + } + + return ret; } -static struct aicbt_info_t aicbt_info = { - .btmode = AICBT_BTMODE_DEFAULT, - .btport = AICBT_BTPORT_DEFAULT, - .uart_baud = AICBT_UART_BAUD_DEFAULT, - .uart_flowctrl = AICBT_UART_FC_DEFAULT, -}; - -int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev) +int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev, struct aicbt_info_t *aicbt_info, struct aicbt_patch_table *head) { - struct aicbt_patch_table *head, *p; + struct aicbt_patch_table *p; int ret = 0, i; uint32_t *data = NULL; - head = aicbt_patch_table_alloc(aicbsp_firmware_list[aicbsp_info.cpmode].bt_table); + + printk("%s bt uart baud: %d, flowctrl: %d, lpm_enable: %d, tx_pwr: %d\n", __func__, + aicbt_info->uart_baud, aicbt_info->uart_flowctrl, aicbt_info->lpm_enable, aicbt_info->txpwr_lvl); + for (p = head; p != NULL; p = p->next) { data = p->data; if (AICBT_PT_BTMODE == p->type) { @@ -642,14 +672,16 @@ int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev) *(data + 3) = aicbsp_info.hwinfo; *(data + 5) = aicbsp_info.cpmode; - *(data + 7) = aicbt_info.btmode; - *(data + 9) = aicbt_info.btport; - *(data + 11) = aicbt_info.uart_baud; - *(data + 13) = aicbt_info.uart_flowctrl; + *(data + 7) = aicbt_info->btmode; + *(data + 9) = aicbt_info->btport; + *(data + 11) = aicbt_info->uart_baud; + *(data + 13) = aicbt_info->uart_flowctrl; + *(data + 15) = aicbt_info->lpm_enable; + *(data + 17) = aicbt_info->txpwr_lvl; + } if (AICBT_PT_VER == p->type) { - printk("aicbsp: bt patch version: %s\n", (char *)p->data); continue; } @@ -662,185 +694,6 @@ int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev) if (p->type == AICBT_PT_PWRON) udelay(500); } - aicbt_patch_table_free(&head); - return 0; -} - -int aicbt_init(struct aic_sdio_dev *sdiodev) -{ - if (aicbt_patch_trap_data_load(sdiodev)) { - printk("aicbt_patch_trap_data_load fail\n"); - return -1; - } - - if (aicbt_patch_table_load(sdiodev)) { - printk("aicbt_patch_table_load fail\n"); - return -1; - } - - return 0; -} - -static int aicwifi_start_from_bootrom(struct aic_sdio_dev *sdiodev) -{ - int ret = 0; - - /* memory access */ - const u32 fw_addr = RAM_FMAC_FW_ADDR; - struct dbg_start_app_cfm start_app_cfm; - - /* fw start */ - ret = rwnx_send_dbg_start_app_req(sdiodev, fw_addr, HOST_START_APP_AUTO, &start_app_cfm); - if (ret) { - return -1; - } - aicbsp_info.hwinfo_r = start_app_cfm.bootstatus & 0xFF; - - return 0; -} - -u32 patch_tbl[][2] = { -}; - -u32 syscfg_tbl_masked[][3] = { - {0x40506024, 0x000000FF, 0x000000DF}, // for clk gate lp_level -}; - -u32 rf_tbl_masked[][3] = { - {0x40344058, 0x00800000, 0x00000000},// pll trx -}; - -static int aicwifi_sys_config(struct aic_sdio_dev *sdiodev) -{ - int ret, cnt; - int syscfg_num = sizeof(syscfg_tbl_masked) / sizeof(u32) / 3; - for (cnt = 0; cnt < syscfg_num; cnt++) { - ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, - syscfg_tbl_masked[cnt][0], syscfg_tbl_masked[cnt][1], syscfg_tbl_masked[cnt][2]); - if (ret) { - printk("%x mask write fail: %d\n", syscfg_tbl_masked[cnt][0], ret); - return ret; - } - } - - ret = rwnx_send_dbg_mem_mask_write_req(sdiodev, - rf_tbl_masked[0][0], rf_tbl_masked[0][1], rf_tbl_masked[0][2]); - if (ret) { - printk("rf config %x write fail: %d\n", rf_tbl_masked[0][0], ret); - return ret; - } - - return 0; -} - -static int aicwifi_patch_config(struct aic_sdio_dev *sdiodev) -{ - const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0180; - u32 config_base; - uint32_t start_addr = 0x1e6000; - u32 patch_addr = start_addr; - u32 patch_num = sizeof(patch_tbl)/4; - struct dbg_mem_read_cfm rd_patch_addr_cfm; - int ret = 0; - u16 cnt = 0; - u32 patch_addr_reg = 0x1e4d80; - u32 patch_num_reg = 0x1e4d84; - - if (aicbsp_info.cpmode == AICBSP_CPMODE_TEST) { - patch_addr_reg = 0x1e4d74; - patch_num_reg = 0x1e4d78; - } - - ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm); - if (ret) { - printk("patch rd fail\n"); - return ret; - } - - config_base = rd_patch_addr_cfm.memdata; - - ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_addr_reg, patch_addr); - if (ret) { - printk("0x%x write fail\n", patch_addr_reg); - return ret; - } - - ret = rwnx_send_dbg_mem_write_req(sdiodev, patch_num_reg, patch_num); - if (ret) { - printk("0x%x write fail\n", patch_num_reg); - return ret; - } - - for (cnt = 0; cnt < patch_num/2; cnt += 1) { - ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl[cnt][0]+config_base); - if (ret) { - printk("%x write fail\n", start_addr+8*cnt); - return ret; - } - - ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl[cnt][1]); - if (ret) { - printk("%x write fail\n", start_addr+8*cnt+4); - return ret; - } - } - - return 0; -} - -int aicwifi_init(struct aic_sdio_dev *sdiodev) -{ - if (rwnx_plat_bin_fw_upload_android(sdiodev, RAM_FMAC_FW_ADDR, aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw)) { - printk("download wifi fw fail\n"); - return -1; - } - - if (aicwifi_patch_config(sdiodev)) { - printk("aicwifi_patch_config fail\n"); - return -1; - } - - if (aicwifi_sys_config(sdiodev)) { - printk("aicwifi_sys_config fail\n"); - return -1; - } - - if (aicwifi_start_from_bootrom(sdiodev)) { - printk("wifi start fail\n"); - return -1; - } - - return 0; -} - -u32 aicbsp_syscfg_tbl[][2] = { - {0x40500014, 0x00000101}, // 1) - {0x40500018, 0x00000109}, // 2) - {0x40500004, 0x00000010}, // 3) the order should not be changed - - // def CONFIG_PMIC_SETTING - // U02 bootrom only - {0x40040000, 0x00001AC8}, // 1) fix panic - {0x40040084, 0x00011580}, - {0x40040080, 0x00000001}, - {0x40100058, 0x00000000}, - - {0x50000000, 0x03220204}, // 2) pmic interface init - {0x50019150, 0x00000002}, // 3) for 26m xtal, set div1 - {0x50017008, 0x00000000}, // 4) stop wdg -}; - -static int aicbsp_system_config(struct aic_sdio_dev *sdiodev) -{ - int syscfg_num = sizeof(aicbsp_syscfg_tbl) / sizeof(u32) / 2; - int ret, cnt; - for (cnt = 0; cnt < syscfg_num; cnt++) { - ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl[cnt][0], aicbsp_syscfg_tbl[cnt][1]); - if (ret) { - sdio_err("%x write fail: %d\n", aicbsp_syscfg_tbl[cnt][0], ret); - return ret; - } - } return 0; } @@ -858,79 +711,24 @@ void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev) int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev) { - const u32 mem_addr = 0x40500000; - struct dbg_mem_read_cfm rd_mem_addr_cfm; + if (aicbsp_info.chipinfo == NULL) + goto err; - uint8_t binding_status; - uint8_t dout[16]; + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800D) + return aicbsp_8800d_fw_init(sdiodev); - need_binding_verify = false; + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC || aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DW) + return aicbsp_8800dc_fw_init(sdiodev); - if (rwnx_send_dbg_mem_read_req(sdiodev, mem_addr, &rd_mem_addr_cfm)) - return -1; - - aicbsp_info.chip_rev = (u8)(rd_mem_addr_cfm.memdata >> 16); - if (aicbsp_info.chip_rev != CHIP_REV_U02 && - aicbsp_info.chip_rev != CHIP_REV_U03 && - aicbsp_info.chip_rev != CHIP_REV_U04) { - pr_err("aicbsp: %s, unsupport chip rev: %d\n", __func__, aicbsp_info.chip_rev); - return -1; - } - - printk("aicbsp: %s, chip rev: %d\n", __func__, aicbsp_info.chip_rev); - - if (aicbsp_info.chip_rev != CHIP_REV_U02) - aicbsp_firmware_list = fw_u03; - - if (aicbsp_system_config(sdiodev)) - return -1; - - if (aicbt_init(sdiodev)) - return -1; - - if (aicwifi_init(sdiodev)) - return -1; - - if (need_binding_verify) { - printk("aicbsp: crypto data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", - binding_enc_data[0], binding_enc_data[1], binding_enc_data[2], binding_enc_data[3], - binding_enc_data[4], binding_enc_data[5], binding_enc_data[6], binding_enc_data[7], - binding_enc_data[8], binding_enc_data[9], binding_enc_data[10], binding_enc_data[11], - binding_enc_data[12], binding_enc_data[13], binding_enc_data[14], binding_enc_data[15]); - - /* calculate verify data from crypto data */ - if (wcn_bind_verify_calculate_verify_data(binding_enc_data, dout)) { - pr_err("aicbsp: %s, binding encrypt data incorrect\n", __func__); - return -1; - } - - printk("aicbsp: verify data %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", - dout[0], dout[1], dout[2], dout[3], - dout[4], dout[5], dout[6], dout[7], - dout[8], dout[9], dout[10], dout[11], - dout[12], dout[13], dout[14], dout[15]); - - if (rwnx_send_dbg_binding_req(sdiodev, dout, &binding_status)) { - pr_err("aicbsp: %s, send binding request failn", __func__); - return -1; - } - - if (binding_status) { - pr_err("aicbsp: %s, binding verify fail\n", __func__); - return -1; - } - } - - if (aicwf_sdio_writeb(sdiodev, SDIOWIFI_WAKEUP_REG, 4)) { - sdio_err("reg:%d write failed!\n", SDIOWIFI_WAKEUP_REG); - return -1; - } - - return 0; +err: + pr_err("%s no matched chip found\n", __func__); + return -1; } int aicbsp_get_feature(struct aicbsp_feature_t *feature) { + feature->cpmode = aicbsp_info.cpmode; + feature->chipinfo = aicbsp_info.chipinfo; feature->sdio_clock = FEATURE_SDIO_CLOCK; feature->sdio_phase = FEATURE_SDIO_PHASE; feature->hwinfo = aicbsp_info.hwinfo; @@ -938,3 +736,81 @@ int aicbsp_get_feature(struct aicbsp_feature_t *feature) return 0; } EXPORT_SYMBOL_GPL(aicbsp_get_feature); + +#ifdef AICBSP_RESV_MEM_SUPPORT +static struct skb_buff_pool resv_skb[] = { + {AIC_RESV_MEM_TXDATA, 1536*64, "resv_mem_txdata", 0, NULL}, +}; + +int aicbsp_resv_mem_init(void) +{ + int i = 0; + for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { + resv_skb[i].skb = dev_alloc_skb(resv_skb[i].size); + } + return 0; +} + +int aicbsp_resv_mem_deinit(void) +{ + int i = 0; + for (i = 0; i < sizeof(resv_skb) / sizeof(resv_skb[0]); i++) { + if (resv_skb[i].used == 0 && resv_skb[i].skb) + dev_kfree_skb(resv_skb[i].skb); + } + return 0; +} + +struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id) +{ + if (resv_skb[id].size < length) { + pr_err("aicbsp: %s, no enough mem\n", __func__); + goto fail; + } + + if (resv_skb[id].used) { + pr_err("aicbsp: %s, mem in use\n", __func__); + goto fail; + } + + if (resv_skb[id].skb == NULL) { + pr_err("aicbsp: %s, mem not initialazed\n", __func__); + resv_skb[id].skb = dev_alloc_skb(resv_skb[id].size); + if (resv_skb[id].skb == NULL) { + pr_err("aicbsp: %s, mem reinitial still fail\n", __func__); + goto fail; + } + } + + printk("aicbsp: %s, alloc %s succuss, id: %d, size: %d\n", __func__, + resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); + + resv_skb[id].used = 1; + return resv_skb[id].skb; + +fail: + return NULL; +} +EXPORT_SYMBOL_GPL(aicbsp_resv_mem_alloc_skb); + +void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id) +{ + resv_skb[id].used = 0; + printk("aicbsp: %s, free %s succuss, id: %d, size: %d\n", __func__, + resv_skb[id].name, resv_skb[id].id, resv_skb[id].size); +} +EXPORT_SYMBOL_GPL(aicbsp_resv_mem_kfree_skb); + +#else + +int aicbsp_resv_mem_init(void) +{ + return 0; +} + +int aicbsp_resv_mem_deinit(void) +{ + return 0; +} + +#endif diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h index 5bd073143..1a6711f99 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h @@ -201,9 +201,17 @@ enum dbg_msg_tag { DBG_MAX, }; +enum mm_msg_tag { + MM_SET_RF_CONFIG_REQ = 103, + MM_SET_RF_CONFIG_CFM, + MM_MAX +}; + enum { HOST_START_APP_AUTO = 1, - HOST_START_APP_CUSTOM + HOST_START_APP_CUSTOM, + HOST_START_APP_FNCALL = 4, + HOST_START_APP_DUMMY = 5, }; struct dbg_mem_block_write_req { @@ -272,6 +280,14 @@ struct dbg_binding_req { u8 driver_data[16]; }; +struct mm_set_rf_config_req { + u8 table_sel; + u8 table_ofst; + u8 table_num; + u8 deft_page; + u32 data[64]; +}; + int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, struct dbg_mem_read_cfm *cfm); int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, @@ -283,19 +299,18 @@ int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 int rwnx_send_dbg_binding_req(struct aic_sdio_dev *sdiodev, u8 *dout, u8 *binding_status); void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg); +int rwnx_send_rf_config_req(struct aic_sdio_dev *sdiodev, u8 ofst, u8 sel, u8 *tbl, u16 len); int aicbsp_platform_init(struct aic_sdio_dev *sdiodev); void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev); int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev); - -#define RAM_FMAC_FW_ADDR 0x00120000 -#define FW_RAM_ADID_BASE_ADDR 0x00161928 -#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928 -#define FW_RAM_PATCH_BASE_ADDR 0x00100000 +int aicbsp_resv_mem_init(void); +int aicbsp_resv_mem_deinit(void); #define AICBT_PT_TAG "AICBT_PT_TAG" enum aicbt_patch_table_type { + AICBT_PT_INF = 0x0, AICBT_PT_TRAP = 0x1, AICBT_PT_B4, AICBT_PT_BTMODE, @@ -339,18 +354,16 @@ enum aicbt_uart_flowctrl_type { AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl }; -enum aicbsp_cpmode_type { - AICBSP_CPMODE_WORK, - AICBSP_CPMODE_TEST, - AICBSP_CPMODE_MAX, -}; - enum chip_rev { CHIP_REV_U02 = 3, CHIP_REV_U03 = 7, CHIP_REV_U04 = 7, }; +///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl; +///pwr lvl:20(min), 30 , 40 , 50 , 60(max) +#define AICBT_TXPWR_LVL 0x00006020 + #define AICBSP_HWINFO_DEFAULT (-1) #define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK @@ -358,6 +371,8 @@ enum chip_rev { #define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART #define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M #define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE +#define AICBT_LPM_ENABLE_DEFAULT 0 +#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL #define FEATURE_SDIO_CLOCK 70000000 // 0: default, other: target clock rate #define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180° @@ -375,6 +390,10 @@ struct aicbt_info_t { uint32_t btport; uint32_t uart_baud; uint32_t uart_flowctrl; + uint32_t lpm_enable; + uint32_t txpwr_lvl; + uint32_t addr_adid; + uint32_t addr_patch; }; struct aicbsp_firmware { @@ -383,20 +402,32 @@ struct aicbsp_firmware { const char *bt_patch; const char *bt_table; const char *wl_fw; + const char *wl_table; }; struct aicbsp_info_t { int hwinfo; int hwinfo_r; uint32_t cpmode; - uint32_t chip_rev; bool fwlog_en; + struct device_match_entry *chipinfo; }; +int aicbsp_8800d_fw_init(struct aic_sdio_dev *sdiodev); +int aicbsp_8800dc_fw_init(struct aic_sdio_dev *sdiodev); + +int wcn_bind_verify_calculate_verify_data(uint8_t *din, uint8_t *dout); +int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename); +int aicbt_patch_table_free(struct aicbt_patch_table **head); +struct aicbt_patch_table *aicbt_patch_table_alloc(const char *filename); +int aicbt_patch_info_unpack(struct aicbt_patch_table *head, struct aicbt_info_t *aicbt_info); +int aicbt_patch_table_load(struct aic_sdio_dev *sdiodev, struct aicbt_info_t *btcfg, struct aicbt_patch_table *head); + +extern u8 binding_enc_data[16]; +extern bool need_binding_verify; + extern struct aicbsp_info_t aicbsp_info; extern struct mutex aicbsp_power_lock; extern const struct aicbsp_firmware *aicbsp_firmware_list; -extern const struct aicbsp_firmware fw_u02[]; -extern const struct aicbsp_firmware fw_u03[]; #endif diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h index 47aa9bd5e..8e7b90f24 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h @@ -1,6 +1,8 @@ #ifndef __AIC_BSP_EXPORT_H #define __AIC_BSP_EXPORT_H +#define AICBSP_RESV_MEM_SUPPORT + enum aicbsp_subsys { AIC_BLUETOOTH, AIC_WIFI, @@ -11,14 +13,53 @@ enum aicbsp_pwr_state { AIC_PWR_ON, }; +enum skb_buff_id { + AIC_RESV_MEM_TXDATA, +}; + +enum AIC_PRODUCT_ID { + PRODUCT_ID_AIC8800D = 0, + PRODUCT_ID_AIC8800DC, + PRODUCT_ID_AIC8800DW, + PRODUCT_ID_AIC8800D80 +}; + +enum aicbsp_cpmode_type { + AICBSP_CPMODE_WORK, + AICBSP_CPMODE_TEST, + AICBSP_CPMODE_MAX, +}; + +struct device_match_entry { + u16 vid; + u16 pid; + u16 chipid; + char *name; + u16 rev; + u16 subrev; + u16 mcuid; +}; + +struct skb_buff_pool { + uint32_t id; + uint32_t size; + const char *name; + uint8_t used; + struct sk_buff *skb; +}; + struct aicbsp_feature_t { int hwinfo; uint32_t sdio_clock; uint8_t sdio_phase; bool fwlog_en; + struct device_match_entry *chipinfo; + uint8_t cpmode; }; int aicbsp_set_subsys(int, int); int aicbsp_get_feature(struct aicbsp_feature_t *feature); +struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id); +void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id); #endif diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c index 1ec4ca6a9..e31af5adc 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c @@ -13,45 +13,21 @@ #define DRV_AUTHOR "AICSemi" #define DRV_VERS_MOD "1.0" +#if defined(AICWF_SDIO_SUPPORT) +#define DRV_TYPE_NAME "sdio" +#elif defined(AICWF_USB_SUPPORT) +#define DRV_TYPE_NAME "usb" +#else +#define DRV_TYPE_NAME "unknow" +#endif + +#define DRV_RELEASE_DATE "20221108" +#define DRV_PATCH_LEVEL "001" +#define DRV_RELEASE_TAG "aic-bsp-" DRV_TYPE_NAME "-" DRV_RELEASE_DATE "-" DRV_PATCH_LEVEL + static struct platform_device *aicbsp_pdev; -const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02; - -const struct aicbsp_firmware fw_u02[] = { - [AICBSP_CPMODE_WORK] = { - .desc = "normal work mode(sdio u02)", - .bt_adid = "fw_adid.bin", - .bt_patch = "fw_patch.bin", - .bt_table = "fw_patch_table.bin", - .wl_fw = "fmacfw.bin" - }, - - [AICBSP_CPMODE_TEST] = { - .desc = "rf test mode(sdio u02)", - .bt_adid = "fw_adid.bin", - .bt_patch = "fw_patch.bin", - .bt_table = "fw_patch_table.bin", - .wl_fw = "fmacfw_rf.bin" - }, -}; - -const struct aicbsp_firmware fw_u03[] = { - [AICBSP_CPMODE_WORK] = { - .desc = "normal work mode(sdio u03/u04)", - .bt_adid = "fw_adid_u03.bin", - .bt_patch = "fw_patch_u03.bin", - .bt_table = "fw_patch_table_u03.bin", - .wl_fw = "fmacfw.bin" - }, - - [AICBSP_CPMODE_TEST] = { - .desc = "rf test mode(sdio u03/u04)", - .bt_adid = "fw_adid_u03.bin", - .bt_patch = "fw_patch_u03.bin", - .bt_table = "fw_patch_table_u03.bin", - .wl_fw = "fmacfw_rf.bin" - }, -}; +const struct aicbsp_firmware *aicbsp_firmware_list; struct aicbsp_info_t aicbsp_info = { .hwinfo_r = AICBSP_HWINFO_DEFAULT, @@ -80,6 +56,11 @@ static ssize_t cpmode_show(struct device *dev, ssize_t count = 0; uint8_t i = 0; + if (aicbsp_firmware_list == NULL) { + count += sprintf(&buf[count], "Wi-Fi not opened since system power on\n"); + return count; + } + count += sprintf(&buf[count], "Support mode value:\n"); for (i = 0; i < AICBSP_CPMODE_MAX; i++) { @@ -109,7 +90,7 @@ static ssize_t cpmode_store(struct device *dev, } aicbsp_info.cpmode = val; - printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc); + printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list ? aicbsp_firmware_list[val].desc : "unknow"); return count; } @@ -119,11 +100,12 @@ static ssize_t hwinfo_show(struct device *dev, { ssize_t count = 0; - count += sprintf(&buf[count], "chip hw rev: "); - if (aicbsp_info.hwinfo_r < 0) - count += sprintf(&buf[count], "-1(not avalible)\n"); + if (aicbsp_info.chipinfo == NULL) + count += sprintf(&buf[count], "chip info not avalible)\n"); else - count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev); + count += sprintf(&buf[count], "chip name: %s, id: 0x%02X, rev: 0x%02X, subrev: 0x%02X\n", + aicbsp_info.chipinfo->name, aicbsp_info.chipinfo->chipid, + aicbsp_info.chipinfo->rev, aicbsp_info.chipinfo->subrev); count += sprintf(&buf[count], "hwinfo read: "); if (aicbsp_info.hwinfo_r < 0) @@ -270,7 +252,9 @@ static int __init aicbsp_init(void) { int ret; printk("%s\n", __func__); + printk("%s, Driver Release Tag: %s\n", __func__, DRV_RELEASE_TAG); + aicbsp_resv_mem_init(); mutex_init(&aicbsp_power_lock); ret = platform_driver_register(&aicbsp_driver); if (ret) { @@ -312,6 +296,7 @@ err1: platform_driver_unregister(&aicbsp_driver); err0: mutex_destroy(&aicbsp_power_lock); + aicbsp_resv_mem_deinit(); return ret; } @@ -322,6 +307,7 @@ static void __exit aicbsp_exit(void) platform_device_del(aicbsp_pdev); platform_driver_unregister(&aicbsp_driver); mutex_destroy(&aicbsp_power_lock); + aicbsp_resv_mem_deinit(); printk("%s\n", __func__); } diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c index b584f4bf8..830223a3b 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c @@ -33,6 +33,15 @@ static struct aic_sdio_dev *aicbsp_sdiodev; static struct semaphore *aicbsp_notify_semaphore; static const struct sdio_device_id aicbsp_sdmmc_ids[]; +static struct device_match_entry aicdev_match_table[] = { + {0x544a, 0x0146, PRODUCT_ID_AIC8800D, "aic8800d", 0, 0}, // 8800d in bootloader mode + {0xc8a1, 0xc18d, PRODUCT_ID_AIC8800DC, "aic8800dc", 0, 0}, // 8800dc in bootloader mode +// {0x5449, 0x0145, PRODUCT_ID_AIC8800DW, "aic8800dw", 0, 0}, +// {0x5449, 0x0145, PRODUCT_ID_AIC8800D80, "aic8800d80", 0, 0}, +}; + +static struct device_match_entry *aic_matched_ic; + static int aicbsp_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id) { if (func && (func->num != 2)) @@ -142,7 +151,7 @@ void *aicbsp_get_drvdata(void *args) (void)args; if (aicbsp_sdiodev) return aicbsp_sdiodev->bus_if; - return NULL; + return dev_get_drvdata((const struct device *)args); } static int aicbsp_sdio_probe(struct sdio_func *func, @@ -152,12 +161,22 @@ static int aicbsp_sdio_probe(struct sdio_func *func, struct aic_sdio_dev *sdiodev; struct aicwf_bus *bus_if; int err = -ENODEV; + int i = 0; sdio_dbg("%s:%d\n", __func__, func->num); - if (func->num != 2) { - return err; + for (i = 0; i < sizeof(aicdev_match_table) / sizeof(aicdev_match_table[0]); i++) { + if (func->vendor == aicdev_match_table[i].vid && func->device == aicdev_match_table[i].pid) { + aic_matched_ic = &aicdev_match_table[i]; + } } + if (aic_matched_ic == NULL) + return err; + + sdio_dbg("%s:%d, matched chip: %s\n", __func__, func->num, aic_matched_ic ? aic_matched_ic->name : "none"); + if (func->num != 2) + return err; + func = func->card->sdio_func[1 - 1]; //replace 2 with 1 host = func->card->host; sdio_dbg("%s after replace:%d\n", __func__, func->num); @@ -175,9 +194,16 @@ static int aicbsp_sdio_probe(struct sdio_func *func, return -ENOMEM; } - sdiodev->func = func; + aicbsp_info.chipinfo = aic_matched_ic; + sdiodev->func[0] = func; sdiodev->bus_if = bus_if; bus_if->bus_priv.sdio = sdiodev; + + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) { + sdiodev->func[1] = func->card->sdio_func[1]; + dev_set_drvdata(&sdiodev->func[1]->dev, bus_if); + } + dev_set_drvdata(&func->dev, bus_if); sdiodev->dev = &func->dev; err = aicwf_sdio_func_init(sdiodev); @@ -201,6 +227,7 @@ fail: dev_set_drvdata(&func->dev, NULL); kfree(sdiodev); kfree(bus_if); + aic_matched_ic = NULL; return err; } @@ -222,19 +249,20 @@ static void aicbsp_sdio_remove(struct sdio_func *func) goto done; } - func = sdiodev->func; + func = sdiodev->func[0]; host = func->card->host; host->caps &= ~MMC_CAP_NONREMOVABLE; aicwf_sdio_release(sdiodev); aicwf_sdio_func_deinit(sdiodev); - dev_set_drvdata(&sdiodev->func->dev, NULL); + dev_set_drvdata(&sdiodev->func[0]->dev, NULL); kfree(sdiodev); kfree(bus_if); done: aicbsp_sdiodev = NULL; + aic_matched_ic = NULL; sdio_dbg("%s done\n", __func__); } @@ -270,7 +298,8 @@ static int aicbsp_sdio_resume(struct device *dev) } static const struct sdio_device_id aicbsp_sdmmc_ids[] = { - {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, + {SDIO_DEVICE(0x544a, 0x0146)}, // aic8800d in bootloader mode + {SDIO_DEVICE(0xc8a1, 0xc18d)}, // aic8800dc in bootloader mode { }, }; @@ -352,27 +381,34 @@ void aicbsp_sdio_exit(void) void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev) { + int funcnum = 1, i = 0; + + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) + funcnum = 2; + sdiodev->bus_if->state = BUS_DOWN_ST; - sdio_claim_host(sdiodev->func); - sdio_release_irq(sdiodev->func); - sdio_release_host(sdiodev->func); + for (i = 0; i < funcnum; i++) { + sdio_claim_host(sdiodev->func[i]); + sdio_release_irq(sdiodev->func[i]); + sdio_release_host(sdiodev->func[i]); + } } -int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) +int aicwf_sdio_readb(struct sdio_func *func, uint regaddr, u8 *val) { int ret; - sdio_claim_host(sdiodev->func); - *val = sdio_readb(sdiodev->func, regaddr, &ret); - sdio_release_host(sdiodev->func); + sdio_claim_host(func); + *val = sdio_readb(func, regaddr, &ret); + sdio_release_host(func); return ret; } -int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) +int aicwf_sdio_writeb(struct sdio_func *func, uint regaddr, u8 val) { int ret; - sdio_claim_host(sdiodev->func); - sdio_writeb(sdiodev->func, val, regaddr, &ret); - sdio_release_host(sdiodev->func); + sdio_claim_host(func); + sdio_writeb(func, val, regaddr, &ret); + sdio_release_host(func); return ret; } @@ -383,7 +419,7 @@ int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) u32 count = 0; while (true) { - ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_FLOW_CTRL_REG, &fc_reg); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_FLOW_CTRL_REG, &fc_reg); if (ret) { return -1; } @@ -413,9 +449,20 @@ int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) { int ret = 0; - sdio_claim_host(sdiodev->func); - ret = sdio_writesb(sdiodev->func, 7, buf, count); - sdio_release_host(sdiodev->func); + sdio_claim_host(sdiodev->func[0]); + ret = sdio_writesb(sdiodev->func[0], 7, buf, count); + sdio_release_host(sdiodev->func[0]); + + return ret; +} + +int aicwf_sdio_send_msg(struct aic_sdio_dev *sdiodev, u8 *buf, uint count) +{ + int ret = 0; + + sdio_claim_host(sdiodev->func[0]); + ret = sdio_writesb(sdiodev->func[1], 7, buf, count); + sdio_release_host(sdiodev->func[1]); return ret; } @@ -429,9 +476,30 @@ int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, return -EINVAL;; } - sdio_claim_host(sdiodev->func); - ret = sdio_readsb(sdiodev->func, skbbuf->data, 8, size); - sdio_release_host(sdiodev->func); + sdio_claim_host(sdiodev->func[0]); + ret = sdio_readsb(sdiodev->func[0], skbbuf->data, 8, size); + sdio_release_host(sdiodev->func[0]); + + if (ret < 0) { + return ret; + } + skbbuf->len = size; + + return ret; +} + +int aicwf_sdio_recv_msg(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, + u32 size) +{ + int ret; + + if ((!skbbuf) || (!size)) { + return -EINVAL;; + } + + sdio_claim_host(sdiodev->func[1]); + ret = sdio_readsb(sdiodev->func[1], skbbuf->data, 8, size); + sdio_release_host(sdiodev->func[1]); if (ret < 0) { return ret; @@ -451,7 +519,7 @@ int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) //if (sdiodev->rwnx_hw->vif_started) { down(&sdiodev->pwrctl_wakeup_sema); while (write_retry) { - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_WAKEUP_REG, 1); + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_WAKEUP_REG, 1); if (ret) { txrx_err("sdio wakeup fail\n"); ret = -1; @@ -459,7 +527,7 @@ int aicwf_sdio_wakeup(struct aic_sdio_dev *sdiodev) read_retry = 10; while (read_retry) { u8 val; - ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_SLEEP_REG, &val); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_SLEEP_REG, &val); if ((ret == 0) && (val & 0x10)) { break; } @@ -490,7 +558,7 @@ int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) struct aicwf_bus *bus_if = sdiodev->bus_if; if (bus_if->state == BUS_DOWN_ST) { - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_SLEEP_REG, 0x10); + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_SLEEP_REG, 0x10); if (ret) { sdio_err("Write sleep fail!\n"); } @@ -501,7 +569,7 @@ int aicwf_sdio_sleep_allow(struct aic_sdio_dev *sdiodev) if (sdiodev->state == SDIO_ACTIVE_ST) { { sdio_dbg("s\n"); - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_SLEEP_REG, 0x10); + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_SLEEP_REG, 0x10); if (ret) sdio_err("Write sleep fail!\n"); } @@ -573,7 +641,7 @@ static int aicwf_sdio_intr_get_len_bytemode(struct aic_sdio_dev *sdiodev, u8 *by if (sdiodev->bus_if->state == BUS_DOWN_ST) { *byte_len = 0; } else { - ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_BYTEMODE_LEN_REG, byte_len); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_BYTEMODE_LEN_REG, byte_len); sdiodev->rx_priv->data_len = (*byte_len)*4; } @@ -636,6 +704,33 @@ struct sk_buff *aicwf_sdio_readframes(struct aic_sdio_dev *sdiodev) return skb; } +struct sk_buff *aicwf_sdio_readmessages(struct aic_sdio_dev *sdiodev) +{ + int ret = 0; + u32 size = 0; + struct sk_buff *skb = NULL; + struct aicwf_bus *bus_if = dev_get_drvdata(sdiodev->dev); + + if (bus_if->state == BUS_DOWN_ST) { + sdio_dbg("bus down\n"); + return NULL; + } + + size = sdiodev->rx_priv->data_len; + skb = __dev_alloc_skb(size, GFP_KERNEL); + if (!skb) { + return NULL; + } + + ret = aicwf_sdio_recv_msg(sdiodev, skb, size); + if (ret) { + dev_kfree_skb(skb); + skb = NULL; + } + + return skb; +} + static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) { int err = 0; @@ -663,22 +758,31 @@ static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) } else len = payload_len; - buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); - while ((buffer_cnt <= 0 || len > (buffer_cnt * BUFFER_SIZE)) && retry < 5) { - retry++; + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800D) { buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); + while ((buffer_cnt <= 0 || len > (buffer_cnt * BUFFER_SIZE)) && retry < 5) { + retry++; + buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); + } } - down(&sdiodev->tx_priv->cmd_txsema); - if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { - err = aicwf_sdio_send_pkt(sdiodev, payload, len); + + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800D) { + if (buffer_cnt > 0 && len < (buffer_cnt * BUFFER_SIZE)) { + err = aicwf_sdio_send_pkt(sdiodev, payload, len); + if (err) { + sdio_err("aicwf_sdio_send_pkt fail%d\n", err); + } + } else { + up(&sdiodev->tx_priv->cmd_txsema); + sdio_err("tx msg fc retry fail\n"); + return -1; + } + } else if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) { + err = aicwf_sdio_send_msg(sdiodev, payload, len); if (err) { sdio_err("aicwf_sdio_send_pkt fail%d\n", err); } - } else { - up(&sdiodev->tx_priv->cmd_txsema); - sdio_err("tx msg fc retry fail\n"); - return -1; } sdiodev->tx_priv->cmd_txstate = false; @@ -736,7 +840,9 @@ static void aicwf_sdio_tx_process(struct aic_sdio_dev *sdiodev) return; } - sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); + if (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) + sdiodev->tx_priv->fw_avail_bufcnt = aicwf_sdio_flow_ctrl(sdiodev); + while (!aicwf_is_framequeue_empty(&sdiodev->tx_priv->txq)) { aicwf_sdio_send(sdiodev->tx_priv); if (sdiodev->tx_priv->cmd_txstate) @@ -797,7 +903,7 @@ static int aicwf_sdio_bus_txmsg(struct device *dev, u8 *msg, uint msglen) if (sdiodev->tx_priv->cmd_txstate) { int timeout = msecs_to_jiffies(CMD_TX_TIMEOUT); - ret = wait_event_interruptible_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ + ret = wait_event_timeout(sdiodev->tx_priv->cmd_txdone_wait, \ !(sdiodev->tx_priv->cmd_txstate), timeout); } @@ -959,20 +1065,37 @@ static int aicwf_sdio_bus_start(struct device *dev) struct aic_sdio_dev *sdiodev = bus_if->bus_priv.sdio; int ret = 0; -#if 1 - sdio_claim_host(sdiodev->func); - sdio_claim_irq(sdiodev->func, aicwf_sdio_hal_irqhandler); -#else - //since we have func2 we don't register irq handler - sdio_claim_irq(sdiodev->func, NULL); - sdiodev->func->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler; -#endif - //enable sdio interrupt - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x07); - sdio_release_host(sdiodev->func); + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800D) { + sdio_claim_host(sdiodev->func[0]); + sdio_claim_irq(sdiodev->func[0], aicwf_sdio_hal_irqhandler); + //enable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_INTR_CONFIG_REG, 0x07); + if (ret != 0) + sdio_err("intr register failed:%d\n", ret); + sdio_release_host(sdiodev->func[0]); + } else if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) { + sdio_claim_host(sdiodev->func[0]); - if (ret != 0) - sdio_err("intr register failed:%d\n", ret); + //since we have func2 we don't register irq handler + sdio_claim_irq(sdiodev->func[0], NULL); + sdio_claim_irq(sdiodev->func[1], NULL); + + sdiodev->func[0]->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler; + sdiodev->func[1]->irq_handler = (sdio_irq_handler_t *)aicwf_sdio_hal_irqhandler_func2; + sdio_release_host(sdiodev->func[0]); + + //enable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_INTR_CONFIG_REG, 0x07); + + if (ret != 0) + sdio_err("intr register failed:%d\n", ret); + + //enable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev->func[1], SDIOWIFI_INTR_CONFIG_REG, 0x07); + + if (ret != 0) + sdio_err("func2 intr register failed:%d\n", ret); + } bus_if->state = BUS_UP_ST; @@ -1068,10 +1191,10 @@ void aicwf_sdio_hal_irqhandler(struct sdio_func *func) return; } - ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_BLOCK_CNT_REG, &intstatus); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_BLOCK_CNT_REG, &intstatus); while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); - ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_BLOCK_CNT_REG, &intstatus); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_BLOCK_CNT_REG, &intstatus); } sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; @@ -1093,6 +1216,52 @@ void aicwf_sdio_hal_irqhandler(struct sdio_func *func) complete(&bus_if->busrx_trgg); } +void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func) +{ + struct aicwf_bus *bus_if = aicbsp_sdiodev->bus_if; + struct aic_sdio_dev *sdiodev = aicbsp_sdiodev; + u8 intstatus = 0; + u8 byte_len = 0; + struct sk_buff *pkt = NULL; + int ret; + + if (!bus_if || bus_if->state == BUS_DOWN_ST) { + if (!bus_if) + sdio_err("bus if none\n"); + else + sdio_err("bus state down\n"); + sdio_err("bus err\n"); + return; + } + + ret = aicwf_sdio_readb(sdiodev->func[1], SDIOWIFI_BLOCK_CNT_REG, &intstatus); + + while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { + sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); + ret = aicwf_sdio_readb(sdiodev->func[0], SDIOWIFI_BLOCK_CNT_REG, &intstatus); + } + sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; + if (intstatus > 0) { + if (intstatus < 64) { + pkt = aicwf_sdio_readmessages(sdiodev); + } else { + sdio_info("byte mode len=%d\r\n", byte_len); + + aicwf_sdio_intr_get_len_bytemode(sdiodev, &byte_len);//byte_len must<= 128 + pkt = aicwf_sdio_readmessages(sdiodev); + } + } else { + #ifndef CONFIG_PLATFORM_ALLWINNER + sdio_err("Interrupt but no data\n"); + #endif + } + + if (pkt) + aicwf_sdio_enq_rxpkt(sdiodev, pkt); + + complete(&bus_if->busrx_trgg); +} + void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration) { uint timeout; @@ -1123,20 +1292,26 @@ void aicwf_sdio_release(struct aic_sdio_dev *sdiodev) { struct aicwf_bus *bus_if; int ret = 0; + int funcnum = 1, i = 0; sdio_dbg("%s\n", __func__); bus_if = sdiodev->bus_if; bus_if->state = BUS_DOWN_ST; - sdio_claim_host(sdiodev->func); - //disable sdio interrupt - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_INTR_CONFIG_REG, 0x0); - if (ret < 0) { - sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) + funcnum = 2; + + for (i = 0; i < funcnum; i++) { + sdio_claim_host(sdiodev->func[i]); + //disable sdio interrupt + ret = aicwf_sdio_writeb(sdiodev->func[i], SDIOWIFI_INTR_CONFIG_REG, 0x0); + if (ret < 0) { + sdio_err("reg:%d write failed!\n", SDIOWIFI_INTR_CONFIG_REG); + } + sdio_release_irq(sdiodev->func[i]); + sdio_release_host(sdiodev->func[i]); } - sdio_release_irq(sdiodev->func); - sdio_release_host(sdiodev->func); if (sdiodev->dev) aicwf_bus_deinit(sdiodev->dev); @@ -1160,25 +1335,25 @@ int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) struct aicbsp_feature_t feature; aicbsp_get_feature(&feature); - host = sdiodev->func->card->host; + host = sdiodev->func[0]->card->host; - sdio_claim_host(sdiodev->func); - sdiodev->func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - sdio_f0_writeb(sdiodev->func, feature.sdio_phase, 0x13, &ret); + sdio_claim_host(sdiodev->func[0]); + sdiodev->func[0]->card->quirks |= MMC_QUIRK_LENIENT_FN0; + sdio_f0_writeb(sdiodev->func[0], feature.sdio_phase, 0x13, &ret); if (ret < 0) { sdio_err("write func0 fail %d\n", ret); return ret; } - ret = sdio_set_block_size(sdiodev->func, SDIOWIFI_FUNC_BLOCKSIZE); + ret = sdio_set_block_size(sdiodev->func[0], SDIOWIFI_FUNC_BLOCKSIZE); if (ret < 0) { sdio_err("set blocksize fail %d\n", ret); - sdio_release_host(sdiodev->func); + sdio_release_host(sdiodev->func[0]); return ret; } - ret = sdio_enable_func(sdiodev->func); + ret = sdio_enable_func(sdiodev->func[0]); if (ret < 0) { - sdio_release_host(sdiodev->func); + sdio_release_host(sdiodev->func[0]); sdio_err("enable func fail %d.\n", ret); } @@ -1187,16 +1362,49 @@ int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) host->ops->set_ios(host, &host->ios); sdio_dbg("Set SDIO Clock %d MHz\n", host->ios.clock/1000000); } - sdio_release_host(sdiodev->func); + sdio_release_host(sdiodev->func[0]); - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_REGISTER_BLOCK, block_bit0); + if (aicbsp_info.chipinfo->chipid == PRODUCT_ID_AIC8800DC) { + sdio_claim_host(sdiodev->func[1]); + + //set sdio blocksize + ret = sdio_set_block_size(sdiodev->func[1], SDIOWIFI_FUNC_BLOCKSIZE); + if (ret < 0) { + printk("set func2 blocksize fail %d\n", ret); + sdio_release_host(sdiodev->func[1]); + return ret; + } + + //set sdio enable func + ret = sdio_enable_func(sdiodev->func[1]); + if (ret < 0) { + printk("enable func2 fail %d.\n", ret); + } + + sdio_release_host(sdiodev->func[1]); + + ret = aicwf_sdio_writeb(sdiodev->func[1], SDIOWIFI_REGISTER_BLOCK, block_bit0); + if (ret < 0) { + printk("reg:%d write failed!\n", SDIOWIFI_REGISTER_BLOCK); + return ret; + } + + //1: no byte mode + ret = aicwf_sdio_writeb(sdiodev->func[1], SDIOWIFI_BYTEMODE_ENABLE_REG, byte_mode_disable); + if (ret < 0) { + printk("reg:%d write failed!\n", SDIOWIFI_BYTEMODE_ENABLE_REG); + return ret; + } + } + + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_REGISTER_BLOCK, block_bit0); if (ret < 0) { sdio_err("reg:%d write failed!\n", SDIOWIFI_REGISTER_BLOCK); return ret; } //1: no byte mode - ret = aicwf_sdio_writeb(sdiodev, SDIOWIFI_BYTEMODE_ENABLE_REG, byte_mode_disable); + ret = aicwf_sdio_writeb(sdiodev->func[0], SDIOWIFI_BYTEMODE_ENABLE_REG, byte_mode_disable); if (ret < 0) { sdio_err("reg:%d write failed!\n", SDIOWIFI_BYTEMODE_ENABLE_REG); return ret; @@ -1208,9 +1416,9 @@ int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev) { - sdio_claim_host(sdiodev->func); - sdio_disable_func(sdiodev->func); - sdio_release_host(sdiodev->func); + sdio_claim_host(sdiodev->func[0]); + sdio_disable_func(sdiodev->func[0]); + sdio_release_host(sdiodev->func[0]); } void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev) diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h index 9f722c2dc..e954b4be4 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h @@ -49,7 +49,7 @@ typedef enum { struct aic_sdio_dev { struct rwnx_cmd_mgr cmd_mgr; - struct sdio_func *func; + struct sdio_func *func[2]; struct device *dev; struct aicwf_bus *bus_if; @@ -67,8 +67,9 @@ struct aic_sdio_dev { }; void *aicbsp_get_drvdata(void *args); -int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); +int aicwf_sdio_writeb(struct sdio_func *func, uint regaddr, u8 val); void aicwf_sdio_hal_irqhandler(struct sdio_func *func); +void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func); void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration); int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); diff --git a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c index 795383961..0f8550cb9 100644 --- a/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c +++ b/drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c @@ -21,7 +21,8 @@ int aicwf_bus_init(uint bus_hdrlen, struct device *dev) { - int ret = 0; + int ret = -ENOMEM; + int errnum = 0; struct aicwf_bus *bus_if; if (!dev) { @@ -31,7 +32,6 @@ int aicwf_bus_init(uint bus_hdrlen, struct device *dev) bus_if = dev_get_drvdata(dev); bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL); if (!bus_if->cmd_buf) { - ret = -ENOMEM; txrx_err("proto_attach failed\n"); goto fail; } @@ -45,18 +45,20 @@ int aicwf_bus_init(uint bus_hdrlen, struct device *dev) #endif if (IS_ERR(bus_if->bustx_thread)) { + errnum = PTR_ERR(bus_if->bustx_thread); bus_if->bustx_thread = NULL; - txrx_err("aicwf_bustx_thread run fail\n"); + txrx_err("aicwf_bustx_thread run fail, errnum is %d\n", errnum); goto fail; } if (IS_ERR(bus_if->busrx_thread)) { + errnum = PTR_ERR(bus_if->busrx_thread); bus_if->busrx_thread = NULL; - txrx_err("aicwf_bustx_thread run fail\n"); + txrx_err("aicwf_busrx_thread run fail, errnum is %d\n", errnum); goto fail; } - return ret; + return 0; fail: aicwf_bus_deinit(dev); @@ -83,7 +85,7 @@ void aicwf_bus_deinit(struct device *dev) bus_if->cmd_buf = NULL; } - if (bus_if->bustx_thread) { + if (!IS_ERR_OR_NULL(bus_if->bustx_thread)) { complete_all(&bus_if->bustx_trgg); kthread_stop(bus_if->bustx_thread); bus_if->bustx_thread = NULL; @@ -284,7 +286,7 @@ static void aicwf_recvframe_queue_deinit(struct list_head *q) void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) { - if (rx_priv->sdiodev->bus_if->busrx_thread) { + if (!IS_ERR_OR_NULL(rx_priv->sdiodev->bus_if->busrx_thread)) { complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); rx_priv->sdiodev->bus_if->busrx_thread = NULL; diff --git a/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c b/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c index ad4e676b7..d530b15eb 100644 --- a/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c +++ b/drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c @@ -62,9 +62,11 @@ /* * Defines */ - -#define VERSION "1.3.3" -#define PROC_DIR "bluetooth/sleep" +#define DRV_RELEASE_DATE "20220429" +#define DRV_PATCH_LEVEL "003" +#define DRV_RELEASE_TAG "aic-btlpm-" DRV_RELEASE_DATE "-" DRV_PATCH_LEVEL +#define VERSION "1.3.3" +#define PROC_DIR "bluetooth/sleep" #define DEFAULT_UART_INDEX 1 #define BT_BLUEDROID_SUPPORT 1 @@ -107,8 +109,9 @@ DECLARE_DELAYED_WORK(sleep_workqueue, bluesleep_sleep_work); #define BT_PROTO 0x01 #define BT_TXDATA 0x02 #define BT_ASLEEP 0x04 -#define BT_RXTIMER 0x20 #define BT_TXIDLE 0x08 +#define BT_PAUSE 0x09 +#define BT_RXTIMER 0x0a #if BT_BLUEDROID_SUPPORT static bool has_lpm_enabled; @@ -211,7 +214,8 @@ static void bluesleep_sleep_work(struct work_struct *work) BT_DBG("already asleep"); return; } - if (bsi->uport->ops->tx_empty(bsi->uport)) { + if (bsi->uport->ops->tx_empty(bsi->uport) || + (test_bit(BT_PAUSE, &flags) && test_bit(BT_TXIDLE, &flags))) { BT_DBG("going to sleep..."); set_bit(BT_ASLEEP, &flags); /*Deactivating UART */ @@ -242,9 +246,22 @@ static void bluesleep_sleep_work(struct work_struct *work) set_bit(BT_RXTIMER, &flags); hsuart_power(1); } else { + static int tx_idle_cnt; + if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert && test_bit(BT_TXIDLE, &flags)) + tx_idle_cnt++; + else + tx_idle_cnt = 0; + mod_timer(&rx_timer, jiffies + (RX_TIMER_INTERVAL * HZ)); - if (gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert - && !test_bit(BT_TXIDLE, &flags)) { + set_bit(BT_RXTIMER, &flags); + + if (test_bit(BT_PAUSE, &flags)) { + BT_DBG("rx wake du BT_PAUSE:%lx", flags); + ///enable bt sleep immediately + gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); + } else if ((gpio_get_value(bsi->ext_wake) != bsi->ext_wake_assert + && !test_bit(BT_TXIDLE, &flags)) || tx_idle_cnt > 5) { + tx_idle_cnt = 0; BT_DBG("force retrigger bt wake:%lx", flags); gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); msleep(20); @@ -340,11 +357,20 @@ static ssize_t bluesleep_write_proc_lpm(struct file *file, return -EFAULT; if (b == '0') { +#if 1 + set_bit(BT_PAUSE, &flags); + set_bit(BT_TXIDLE, &flags); + clear_bit(BT_TXDATA, &flags); + /* deassert BT_WAKE */ + gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); +#else /* HCI_DEV_UNREG */ bluesleep_stop(); has_lpm_enabled = false; bsi->uport = NULL; +#endif } else { + clear_bit(BT_PAUSE, &flags); /* HCI_DEV_REG */ if (!has_lpm_enabled) { has_lpm_enabled = true; @@ -478,6 +504,7 @@ static void bluesleep_tx_allow_sleep(void) spin_lock_irqsave(&rw_lock, irq_flags); gpio_set_value(bsi->ext_wake, !bsi->ext_wake_assert); set_bit(BT_TXIDLE, &flags); + clear_bit(BT_TXDATA, &flags); bluesleep_tx_idle(); spin_unlock_irqrestore(&rw_lock, irq_flags); } @@ -569,7 +596,7 @@ fail: /** * Stops the Sleep-Mode Protocol on the Host. */ -static void bluesleep_stop(void) +static __attribute__((unused)) void bluesleep_stop(void) { unsigned long irq_flags; @@ -917,8 +944,6 @@ static int bluesleep_remove(struct platform_device *pdev) /* assert bt wake */ gpio_set_value(bsi->ext_wake, bsi->ext_wake_assert); if (test_bit(BT_PROTO, &flags)) { - if (disable_irq_wake(bsi->host_wake_irq)) - BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n"); free_irq(bsi->host_wake_irq, &bsi->pdev->dev); del_timer(&rx_timer); if (test_bit(BT_ASLEEP, &flags)) @@ -966,6 +991,7 @@ static int __init bluesleep_init(void) struct proc_dir_entry *ent; BT_DBG("BlueSleep Mode Driver Ver %s", VERSION); + BT_DBG("Driver Release Tag: %s", DRV_RELEASE_TAG); retval = platform_driver_probe(&bluesleep_driver, bluesleep_probe); if (retval) diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile b/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile index 5571962c8..88f933a4a 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/Makefile @@ -48,6 +48,7 @@ CONFIG_RWNX_BFMER ?= n CONFIG_SDIO_SUPPORT =y CONFIG_USB_SUPPORT =n +CONFIG_PCIE_SUPPORT =n CONFIG_RX_REORDER ?=y CONFIG_ARP_OFFLOAD =y CONFIG_RADAR_OR_IR_DETECT =n @@ -55,6 +56,7 @@ CONFIG_DOWNLOAD_FW =y CONFIG_RFTEST=y CONFIG_USB_BT =n CONFIG_GKI_OPT_FEATURES ?= y +CONFIG_WPA3_FOR_OLD_KERNEL ?= n # Support of MU-MIMO transmission (need FW support) @@ -79,6 +81,7 @@ CONFIG_RWNX_DBG ?= y obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := aic8800_fdrv.o aic8800_fdrv-y := \ + rwnx_wakelock.o \ rwnx_gki.o \ rwnx_msg_tx.o \ rwnx_msg_rx.o \ @@ -94,7 +97,6 @@ aic8800_fdrv-y := \ rwnx_mod_params.o \ rwnx_mesh.o \ rwnx_platform.o \ - rwnx_pci.o \ rwnx_dini.o \ rwnx_v7.o \ ipc_host.o \ @@ -115,6 +117,8 @@ aic8800_fdrv-$(CONFIG_USB_SUPPORT) += usb_host.o aic8800_fdrv-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o aic8800_fdrv-$(CONFIG_USB_SUPPORT) += aicwf_usb.o +aic8800_fdrv-$(CONFIG_PCIE_SUPPORT) += rwnx_pci.o + ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\" ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS @@ -139,11 +143,6 @@ ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN -CURRENT_CODE_VERSION := $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) -MINI_VERSION_REQUEST := 4.14.0 -ifeq ($(shell expr $(CURRENT_CODE_VERSION) \< $(MINI_VERSION_REQUEST)),1) -ccflags-y += -DCONFIG_HE_FOR_OLD_KERNEL -endif ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_COEX ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_COEX @@ -162,6 +161,7 @@ ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST +ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL ifeq ($(CONFIG_SDIO_SUPPORT), y) ccflags-y += -DAICWF_SDIO_SUPPORT @@ -171,6 +171,10 @@ ifeq ($(CONFIG_USB_SUPPORT), y) ccflags-y += -DAICWF_USB_SUPPORT endif +ifeq ($(CONFIG_PCIE_SUPPORT), y) +ccflags-y += -DAICWF_PCIE_SUPPORT +endif + ifeq ($(CONFIG_RWNX_MUMIMO_TX), y) ccflags-y += -DCONFIG_USER_MAX=2 else diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c index abdb59980..a63504801 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c @@ -10,6 +10,7 @@ #include #include "rwnx_version_gen.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) static struct wifi_ring_buffer_status ring_buffer[] = { { .name = "aicwf_ring_buffer0", @@ -843,12 +844,15 @@ const struct wiphy_vendor_command aicwf_vendor_cmd[] = { static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = { }; +#endif int aicwf_vendor_init(struct wiphy *wiphy) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) wiphy->vendor_commands = aicwf_vendor_cmd; wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd); wiphy->vendor_events = aicwf_vendor_events; wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events); +#endif return 0; } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c index 467eec24e..d9f16bb5c 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.c @@ -25,6 +25,7 @@ #include "mach/jzmmc.h" #endif /* CONFIG_INGENIC_T20 */ #include "aic_bsp_export.h" +#include "rwnx_wakelock.h" extern uint8_t scanning; int aicwf_sdio_readb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 *val) @@ -45,7 +46,7 @@ int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val) return ret; } -int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) +int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev) { int ret = -1; u8 fc_reg = 0; @@ -69,9 +70,42 @@ int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) if (count < 30) udelay(200); else if (count < 40) - mdelay(1); + msleep(2); else - mdelay(10); + msleep(10); + } + } + + return ret; +} + +int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev) +{ + int ret = -1; + u8 fc_reg = 0; + u32 count = 0; + + while (true) { + ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_FLOW_CTRL_REG, &fc_reg); + if (ret) { + return -1; + } + + if ((fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG) > DATA_FLOW_CTRL_THRESH) { + ret = fc_reg & SDIOWIFI_FLOWCTRL_MASK_REG; + return ret; + } else { + if (count >= FLOW_CTRL_RETRY_COUNT) { + ret = -fc_reg; + break; + } + count++; + if (count < 30) + udelay(200); + else if (count < 40) + msleep(2); + else + msleep(10); } } @@ -110,8 +144,6 @@ int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, return ret; } -static int wakeup_enable; -static u32 hostwake_irq_num; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) extern int sunxi_wlan_get_oob_irq(int *, int *); #else @@ -119,23 +151,11 @@ extern int sunxi_wlan_get_oob_irq(void); extern int sunxi_wlan_get_oob_irq_flags(void); #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) -static struct wakeup_source *ws; -#else -#include -static struct wake_lock irq_wakelock; -#endif - static irqreturn_t rwnx_hostwake_irq_handler(int irq, void *para) { static int wake_cnt; wake_cnt++; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - __pm_wakeup_event(ws, HZ / 20); -#else - wake_lock_timeout(&irq_wakelock, HZ / 20); -#endif - printk("%s(%d): wake_irq_cnt = %d\n", __func__, __LINE__, wake_cnt); + rwnx_wakeup_lock_timeout(g_rwnx_plat->sdiodev->rwnx_hw->ws_rx, jiffies_to_msecs(5)); return IRQ_HANDLED; } @@ -143,6 +163,8 @@ static int rwnx_register_hostwake_irq(struct device *dev) { int ret = -1; int irq_flags; + int wakeup_enable; + u32 hostwake_irq_num; #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) hostwake_irq_num = sunxi_wlan_get_oob_irq(&irq_flags, &wakeup_enable); #else @@ -152,11 +174,6 @@ static int rwnx_register_hostwake_irq(struct device *dev) #endif if (wakeup_enable) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - ws = wakeup_source_register(dev, "wifisleep"); -#else - wake_lock_init(&irq_wakelock, WAKE_LOCK_SUSPEND, "wifisleep"); -#endif ret = device_init_wakeup(dev, true); if (ret < 0) { pr_err("%s(%d): device init wakeup failed!\n", __func__, __LINE__); @@ -178,7 +195,9 @@ static int rwnx_register_hostwake_irq(struct device *dev) goto fail2; } } - disable_irq(hostwake_irq_num); + g_rwnx_plat->sdiodev->rwnx_hw->wakeup_enable = wakeup_enable; + g_rwnx_plat->sdiodev->rwnx_hw->hostwake_irq_num = hostwake_irq_num; + printk("%s(%d)\n", __func__, __LINE__); return ret; @@ -186,44 +205,22 @@ fail2: dev_pm_clear_wake_irq(dev); fail1: device_init_wakeup(dev, false); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - wakeup_source_unregister(ws); -#else - wake_lock_destroy(&irq_wakelock); -#endif return ret; } static int rwnx_unregister_hostwake_irq(struct device *dev) { + int wakeup_enable = g_rwnx_plat->sdiodev->rwnx_hw->wakeup_enable; + u32 hostwake_irq_num = g_rwnx_plat->sdiodev->rwnx_hw->hostwake_irq_num; if (wakeup_enable) { + free_irq(hostwake_irq_num, NULL); device_init_wakeup(dev, false); dev_pm_clear_wake_irq(dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - wakeup_source_unregister(ws); -#else - wake_lock_destroy(&irq_wakelock); -#endif } - free_irq(hostwake_irq_num, NULL); printk("%s(%d)\n", __func__, __LINE__); return 0; } -static int rwnx_enable_hostwake_irq(void) -{ - enable_irq(hostwake_irq_num); - printk("%s(%d)\n", __func__, __LINE__); - return 0; -} - -static int rwnx_disable_hostwake_irq(void) -{ - printk("%s(%d)\n", __func__, __LINE__); - disable_irq(hostwake_irq_num); - return 0; -} - static int aicwf_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -270,10 +267,11 @@ static int aicwf_sdio_probe(struct sdio_func *func, host->caps |= MMC_CAP_NONREMOVABLE; aicwf_rwnx_sdio_platform_init(sdiodev); - aicwf_hostif_ready(); err = rwnx_register_hostwake_irq(sdiodev->dev); if (err != 0) - return err; + aicwf_hostif_fail(); + else + aicwf_hostif_ready(); return 0; fail: aicwf_sdio_func_deinit(sdiodev); @@ -302,7 +300,6 @@ static void aicwf_sdio_remove(struct sdio_func *func) if (!sdiodev) { return; } - rwnx_unregister_hostwake_irq(sdiodev->dev); sdiodev->bus_if->state = BUS_DOWN_ST; aicwf_sdio_release(sdiodev); aicwf_sdio_func_deinit(sdiodev); @@ -342,7 +339,6 @@ static int aicwf_sdio_suspend(struct device *dev) up(&sdiodev->tx_priv->txctl_sema); break; } - rwnx_enable_hostwake_irq(); return 0; } @@ -354,23 +350,18 @@ static int aicwf_sdio_resume(struct device *dev) struct rwnx_vif *rwnx_vif, *tmp; sdio_dbg("%s\n", __func__); - rwnx_disable_hostwake_irq(); list_for_each_entry_safe(rwnx_vif, tmp, &sdiodev->rwnx_hw->vifs, list) { if (rwnx_vif->ndev) netif_device_attach(rwnx_vif->ndev); } aicwf_sdio_pwr_stctl(sdiodev, SDIO_ACTIVE_ST); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) - __pm_relax(ws); -#else - wake_unlock(&irq_wakelock); -#endif return 0; } static const struct sdio_device_id aicwf_sdmmc_ids[] = { - {SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN)}, + {SDIO_DEVICE(0x5449, 0x0145)}, // 8800d in nomal mode + {SDIO_DEVICE(0xc8a1, 0xc08d)}, // 8800dc in nomal mode { }, }; @@ -429,8 +420,10 @@ void aicwf_sdio_register(void) void aicwf_sdio_exit(void) { - if (g_rwnx_plat && g_rwnx_plat->enabled) + if (g_rwnx_plat && g_rwnx_plat->enabled) { + rwnx_unregister_hostwake_irq(g_rwnx_plat->sdiodev->dev); rwnx_platform_deinit(g_rwnx_plat->sdiodev->rwnx_hw); + } udelay(500); sdio_unregister_driver(&aicwf_sdio_driver); @@ -662,10 +655,10 @@ static int aicwf_sdio_tx_msg(struct aic_sdio_dev *sdiodev) } else len = payload_len; - buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); + buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); while ((buffer_cnt <= 0 || (buffer_cnt > 0 && len > (buffer_cnt * BUFFER_SIZE))) && retry < 10) { retry++; - buffer_cnt = aicwf_sdio_flow_ctrl(sdiodev); + buffer_cnt = aicwf_sdio_flow_ctrl_msg(sdiodev); printk("buffer_cnt = %d\n", buffer_cnt); } @@ -765,7 +758,11 @@ static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) prio = (pkt->priority & 0x7); spin_lock_bh(&sdiodev->tx_priv->txqlock); if (!aicwf_frame_enq(sdiodev->dev, &sdiodev->tx_priv->txq, pkt, prio)) { - aicwf_dev_skb_free(pkt); + struct rwnx_txhdr *txhdr = (struct rwnx_txhdr *)pkt->data; + int headroom = txhdr->sw_hdr->headroom; + kmem_cache_free(txhdr->sw_hdr->rwnx_vif->rwnx_hw->sw_txhdr_cache, txhdr->sw_hdr); + skb_pull(pkt, headroom); + consume_skb(pkt); spin_unlock_bh(&sdiodev->tx_priv->txqlock); return -ENOSR; } else { @@ -780,7 +777,8 @@ static int aicwf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) atomic_inc(&sdiodev->tx_priv->tx_pktcnt); spin_unlock_bh(&sdiodev->tx_priv->txqlock); - complete(&bus_if->bustx_trgg); + if (atomic_read(&sdiodev->tx_priv->tx_pktcnt) == 1) + complete(&bus_if->bustx_trgg); return ret; } @@ -1023,8 +1021,13 @@ int sdio_bustx_thread(void *data) if (sdiodev->bus_if->state == BUS_DOWN_ST) continue; - if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)) + rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_tx); + while ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) > 0) || (sdiodev->tx_priv->cmd_txstate == true)) { aicwf_sdio_tx_process(sdiodev); + if (sdiodev->bus_if->state == BUS_DOWN_ST) + break; + } + rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_tx); } } @@ -1035,6 +1038,7 @@ int sdio_busrx_thread(void *data) { struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; struct aicwf_bus *bus_if = rx_priv->sdiodev->bus_if; + struct aic_sdio_dev *sdiodev = rx_priv->sdiodev; while (1) { if (kthread_should_stop()) { @@ -1044,7 +1048,9 @@ int sdio_busrx_thread(void *data) if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { if (bus_if->state == BUS_DOWN_ST) continue; + rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_rx); aicwf_process_rxframes(rx_priv); + rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_rx); } } @@ -1063,11 +1069,14 @@ static int aicwf_sdio_pwrctl_thread(void *data) if (!wait_for_completion_interruptible(&sdiodev->pwrctrl_trgg)) { if (sdiodev->bus_if->state == BUS_DOWN_ST) continue; + + rwnx_wakeup_lock(sdiodev->rwnx_hw->ws_pwrctrl); if ((int)(atomic_read(&sdiodev->tx_priv->tx_pktcnt) <= 0) && (sdiodev->tx_priv->cmd_txstate == false) && \ atomic_read(&sdiodev->rx_priv->rx_cnt) == 0) aicwf_sdio_pwr_stctl(sdiodev, SDIO_SLEEP_ST); else aicwf_sdio_pwrctl_timer(sdiodev, sdiodev->active_duration); + rwnx_wakeup_unlock(sdiodev->rwnx_hw->ws_pwrctrl); } } @@ -1123,6 +1132,7 @@ void aicwf_sdio_hal_irqhandler(struct sdio_func *func) u8 byte_len = 0; struct sk_buff *pkt = NULL; int ret; + int retry = 10; if (!bus_if || bus_if->state == BUS_DOWN_ST) { sdio_err("bus err\n"); @@ -1133,6 +1143,8 @@ void aicwf_sdio_hal_irqhandler(struct sdio_func *func) while (ret || (intstatus & SDIO_OTHER_INTERRUPT)) { sdio_err("ret=%d, intstatus=%x\r\n", ret, intstatus); ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_BLOCK_CNT_REG, &intstatus); + if (retry-- <= 0) + break; } sdiodev->rx_priv->data_len = intstatus * SDIOWIFI_FUNC_BLOCKSIZE; @@ -1281,7 +1293,7 @@ int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev) return ret; } - mdelay(2); + mdelay(5); ret = aicwf_sdio_readb(sdiodev, SDIOWIFI_SLEEP_REG, &val); if (ret < 0) { sdio_err("reg:%d read failed!\n", SDIOWIFI_SLEEP_REG); diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h index c19765ac7..e62a03851 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_sdio.h @@ -78,6 +78,7 @@ int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target); int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev); void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev); int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev); +int aicwf_sdio_flow_ctrl_msg(struct aic_sdio_dev *sdiodev); int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size); int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count); void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev); diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c index ee5dd1496..7b0690664 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_txrxif.c @@ -25,10 +25,12 @@ #ifdef AICWF_SDIO_SUPPORT #include "sdio_host.h" #endif +#include "aic_bsp_export.h" int aicwf_bus_init(uint bus_hdrlen, struct device *dev) { int ret = 0; + int errnum = 0; struct aicwf_bus *bus_if; if (!dev) { @@ -56,14 +58,16 @@ int aicwf_bus_init(uint bus_hdrlen, struct device *dev) #endif if (IS_ERR(bus_if->bustx_thread)) { + errnum = PTR_ERR(bus_if->bustx_thread); bus_if->bustx_thread = NULL; - txrx_err("aicwf_bustx_thread run fail\n"); + txrx_err("aicwf_bustx_thread run fail, errnum is %d\n", errnum); goto fail; } if (IS_ERR(bus_if->busrx_thread)) { + errnum = PTR_ERR(bus_if->busrx_thread); bus_if->busrx_thread = NULL; - txrx_err("aicwf_bustx_thread run fail\n"); + txrx_err("aicwf_busrx_thread run fail, errnum is %d\n", errnum); goto fail; } @@ -109,7 +113,7 @@ void aicwf_bus_deinit(struct device *dev) bus_if->cmd_buf = NULL; } - if (bus_if->bustx_thread) { + if (!IS_ERR_OR_NULL(bus_if->bustx_thread)) { complete_all(&bus_if->bustx_trgg); kthread_stop(bus_if->bustx_thread); bus_if->bustx_thread = NULL; @@ -150,7 +154,11 @@ struct aicwf_tx_priv *aicwf_tx_init(void *arg) #endif atomic_set(&tx_priv->aggr_count, 0); +#ifdef AICBSP_RESV_MEM_SUPPORT + tx_priv->aggr_buf = aicbsp_resv_mem_alloc_skb(MAX_AGGR_TXPKT_LEN, AIC_RESV_MEM_TXDATA); +#else tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN); +#endif if (!tx_priv->aggr_buf) { txrx_err("Alloc bus->txdata_buf failed!\n"); kfree(tx_priv); @@ -165,7 +173,11 @@ struct aicwf_tx_priv *aicwf_tx_init(void *arg) void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv) { if (tx_priv && tx_priv->aggr_buf) { +#ifdef AICBSP_RESV_MEM_SUPPORT + aicbsp_resv_mem_kfree_skb(tx_priv->aggr_buf, AIC_RESV_MEM_TXDATA); +#else dev_kfree_skb(tx_priv->aggr_buf); +#endif kfree(tx_priv); } } @@ -358,6 +370,7 @@ int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv) skb_put(skb_inblock, aggr_len); memcpy(skb_inblock->data, data, aggr_len); + aicwf_count_rx_tp(rx_priv, aggr_len); rwnx_rxdataind_aicwf(rx_priv->usbdev->rwnx_hw, skb_inblock, (void *)rx_priv); ///TODO: here need to add rx data process @@ -462,23 +475,25 @@ void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv) struct reord_ctrl_info *reord_info, *tmp; txrx_dbg("%s\n", __func__); - + spin_lock_bh(&rx_priv->stas_reord_lock); list_for_each_entry_safe(reord_info, tmp, &rx_priv->stas_reord_list, list) { reord_deinit_sta(rx_priv, reord_info); } + spin_unlock_bh(&rx_priv->stas_reord_lock); #endif #ifdef AICWF_SDIO_SUPPORT txrx_dbg("sdio rx thread\n"); - if (rx_priv->sdiodev->bus_if->busrx_thread) { + if (!IS_ERR_OR_NULL(rx_priv->sdiodev->bus_if->busrx_thread)) { complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg); kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread); rx_priv->sdiodev->bus_if->busrx_thread = NULL; } #endif #ifdef AICWF_USB_SUPPORT - if (rx_priv->usbdev->bus_if->busrx_thread) { + txrx_dbg("usb rx thread\n"); + if (!IS_ERR_OR_NULL(rx_priv->usbdev->bus_if->busrx_thread)) { complete_all(&rx_priv->usbdev->bus_if->busrx_trgg); kthread_stop(rx_priv->usbdev->bus_if->busrx_thread); rx_priv->usbdev->bus_if->busrx_thread = NULL; @@ -608,48 +623,13 @@ struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq) return p; } -static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio) -{ - struct sk_buff_head *q = &pq->queuelist[prio]; - struct sk_buff *p = skb_dequeue_tail(q); - - if (!p) - return NULL; - - pq->qcnt--; - return p; -} - bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio) { - struct sk_buff *p = NULL; - int prio_modified = -1; - if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) { aicwf_frame_queue_penq(q, prio, pkt); return true; - } - if (q->queuelist[prio].qlen >= q->qmax) { - prio_modified = prio; - } else if (q->qcnt >= q->qmax) { - p = aicwf_frame_queue_peek_tail(q, &prio_modified); - if (prio_modified > prio) - return false; - } - - if (prio_modified >= 0) { - if (prio_modified == prio) - return false; - - p = aicwf_skb_dequeue_tail(q, prio_modified); - aicwf_dev_skb_free(p); - - p = aicwf_frame_queue_penq(q, prio_modified, pkt); - if (p == NULL) - txrx_err("failed\n"); - } - - return p != NULL; + } else + return false; } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c index aa694ac74..f6abc15c4 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/aicwf_usb.c @@ -14,6 +14,7 @@ #include "rwnx_defs.h" #include "usb_host.h" #include "rwnx_platform.h" +#include "rwnx_wakelock.h" void aicwf_usb_tx_flowctrl(struct rwnx_hw *rwnx_hw, bool state) { @@ -153,6 +154,7 @@ static void aicwf_usb_rx_complete(struct urb *urb) spin_unlock_irqrestore(&rx_priv->rxqlock, flags); usb_err("rx_priv->rxq is over flow!!!\n"); aicwf_dev_skb_free(skb); + aicwf_usb_rx_buf_put(usb_dev, usb_buf); return; } spin_unlock_irqrestore(&rx_priv->rxqlock, flags); @@ -297,8 +299,10 @@ int usb_bustx_thread(void *data) if (!wait_for_completion_interruptible(&bus->bustx_trgg)) { if (usbdev->bus_if->state == BUS_DOWN_ST) continue; + rwnx_wakeup_lock(usbdev->rwnx_hw->ws_tx); if (usbdev->tx_post_count > 0) aicwf_usb_tx_process(usbdev); + rwnx_wakeup_unlock(usbdev->rwnx_hw->ws_tx); } } @@ -309,6 +313,7 @@ int usb_busrx_thread(void *data) { struct aicwf_rx_priv *rx_priv = (struct aicwf_rx_priv *)data; struct aicwf_bus *bus_if = rx_priv->usbdev->bus_if; + struct aic_usb_dev *usbdev = rx_priv->usbdev; while (1) { if (kthread_should_stop()) { @@ -318,7 +323,9 @@ int usb_busrx_thread(void *data) if (!wait_for_completion_interruptible(&bus_if->busrx_trgg)) { if (bus_if->state == BUS_DOWN_ST) continue; + rwnx_wakeup_lock(usbdev->rwnx_hw->ws_rx); aicwf_process_rxframes(rx_priv); + rwnx_wakeup_unlock(usbdev->rwnx_hw->ws_rx); } } @@ -556,7 +563,7 @@ static int aicwf_usb_bus_txdata(struct device *dev, struct sk_buff *skb) complete(&bus_if->bustx_trgg); ret = 0; - flow_ctrl: +flow_ctrl: spin_lock_irqsave(&usb_dev->tx_flow_lock, flags); if (usb_dev->tx_free_count < AICWF_USB_TX_LOW_WATER) { usb_dev->tbusy = true; @@ -781,8 +788,6 @@ static int aicwf_parse_usb(struct aic_usb_dev *usb_dev, struct usb_interface *in return ret; } - - static struct aicwf_bus_ops aicwf_usb_bus_ops = { .start = aicwf_usb_bus_start, .stop = aicwf_usb_bus_stop, diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h index bca3a2df3..241cca8dc 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/ipc_shared.h @@ -129,19 +129,10 @@ // c.f LMAC/src/tx/tx_swdesc.h /// Descriptor filled by the Host struct hostdesc { -#ifdef CONFIG_RWNX_SPLIT_TX_BUF - /// Pointers to packet payloads - u32_l packet_addr[NX_TX_PAYLOAD_MAX]; - /// Sizes of the MPDU/MSDU payloads - u16_l packet_len[NX_TX_PAYLOAD_MAX]; - /// Number of payloads forming the MPDU - u8_l packet_cnt; -#else /// Pointer to packet payload - u32_l packet_addr; /// Size of the payload u16_l packet_len; -#endif //(NX_AMSDU_TX) + u16_l flags_ext; #ifdef CONFIG_RWNX_FULLMAC /// Address of the status descriptor in host memory (used for confirmation upload) @@ -152,12 +143,6 @@ struct hostdesc { struct mac_addr eth_src_addr; /// Ethernet Type u16_l ethertype; - /// Buffer containing the PN to be used for this packet - u16_l pn[4]; - /// Sequence Number used for transmission of this MPDU - u16_l sn; - /// Timestamp of first transmission of this MPDU - u16_l timestamp; #else /* ! CONFIG_RWNX_FULLMAC */ #ifdef CONFIG_RWNX_AGG_TX ///Sequence Number for AMPDU MPDUs - for quick check if it's allowed within window @@ -166,6 +151,7 @@ struct hostdesc { /// Padding between the buffer control structure and the MPDU in host memory u8_l padding; #endif /* CONFIG_RWNX_FULLMAC */ + u8_l ac; /// Packet TID (0xFF if not a QoS frame) u8_l tid; /// Interface Id diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h index 8ed002b3a..02196ae24 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_mac.h @@ -434,6 +434,12 @@ enum mac_connection_flags { REASSOCIATION = BIT(5), }; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) +#include +#else +#define CONFIG_HE_FOR_OLD_KERNEL 1 +#endif + #ifdef CONFIG_HE_FOR_OLD_KERNEL #define IEEE80211_HE_MAC_CAP2_ALL_ACK 0x02 #define IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G 0x02 @@ -465,9 +471,6 @@ enum mac_connection_flags { #define IEEE80211_HE_PPE_THRES_MAX_LEN 25 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) -#include -#else struct ieee80211_he_cap_elem { u8 mac_cap_info[6]; u8 phy_cap_info[11]; @@ -495,5 +498,4 @@ struct ieee80211_sband_iftype_data { }; #endif -#endif #endif // LMAC_MAC_H_ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h index 8cb1b91b1..c3ed28488 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/lmac_msg.h @@ -364,8 +364,8 @@ enum mm_msg_tag { MM_GET_STA_INFO_REQ, MM_GET_STA_INFO_CFM, - MM_SET_TXPWR_IDX_REQ, - MM_SET_TXPWR_IDX_CFM, + MM_SET_TXPWR_IDX_LVL_REQ, + MM_SET_TXPWR_IDX_LVL_CFM, MM_SET_TXPWR_OFST_REQ, MM_SET_TXPWR_OFST_CFM, @@ -1209,6 +1209,20 @@ struct mm_set_txpwr_idx_req { txpwr_idx_conf_t txpwr_idx; }; +typedef struct { + u8_l enable; + s8_l pwrlvl_11b_11ag_2g4[12]; + s8_l pwrlvl_11n_11ac_2g4[10]; + s8_l pwrlvl_11ax_2g4[12]; +} txpwr_lvl_conf_v2_t; + +struct mm_set_txpwr_lvl_req { + union { + txpwr_idx_conf_t txpwr_lvl; + txpwr_lvl_conf_v2_t txpwr_lvl_v2; + }; +}; + typedef struct { u8_l enable; s8_l chan_1_4; @@ -1220,6 +1234,12 @@ typedef struct { s8_l chan_142_165; } txpwr_ofst_conf_t; +typedef struct { + u8_l enable; + u8_l xtal_cap; + u8_l xtal_cap_fine; +} xtal_cap_conf_t; + struct mm_set_txpwr_ofst_req { txpwr_ofst_conf_t txpwr_ofst; }; diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c index 879fd20b0..d1b9fa74e 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_cmds.c @@ -16,7 +16,7 @@ #include "rwnx_cmds.h" #include "rwnx_defs.h" #include "rwnx_strs.h" -#define CREATE_TRACE_POINTS +//#define CREATE_TRACE_POINTS #include "rwnx_events.h" #include "aicwf_txrxif.h" #ifdef AICWF_SDIO_SUPPORT @@ -29,6 +29,37 @@ */ extern int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val); +static int rwnx_exception_event(struct rwnx_cmd_mgr *cmd_mgr) +{ +#if defined(AICWF_SDIO_SUPPORT) + struct aic_sdio_dev *pdev = container_of(cmd_mgr, struct aic_sdio_dev, cmd_mgr); +#elif defined(AICWF_USB_SUPPORT) + struct aic_usb_dev *pdev = container_of(cmd_mgr, struct aic_usb_dev, cmd_mgr); +#else + struct aic_usb_dev *pdev = NULL; +#endif + + static bool need_send = true; + + char *envp[] = { + "SYSTEM=WIFI", + "EVENT=EXCEPTION", + "SUBEVENT=FW_CRASH", + NULL}; + + if (!need_send) + return 0; + + if (pdev) { + kobject_uevent_env(&pdev->dev->kobj, KOBJ_CHANGE, envp); + need_send = true; + printk(KERN_CRIT "%s send exception uevent to userspace", __func__); + return 0; + } + + return -1; +} + static void cmd_dump(const struct rwnx_cmd *cmd) { printk(KERN_CRIT "tkn[%d] flags:%04x result:%3d cmd:%4d-%-24s - reqcfm(%4d-%-s)\n", @@ -63,8 +94,9 @@ int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd bool defer_push = false; RWNX_DBG(RWNX_FN_ENTRY_STR); +#ifdef CREATE_TRACE_POINTS trace_msg_send(cmd->id); - +#endif spin_lock_bh(&cmd_mgr->lock); if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { @@ -118,8 +150,9 @@ static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) bool defer_push = false; //RWNX_DBG(RWNX_FN_ENTRY_STR); +#ifdef CREATE_TRACE_POINTS trace_msg_send(cmd->id); - +#endif spin_lock_bh(&cmd_mgr->lock); if (cmd_mgr->state == RWNX_CMD_MGR_STATE_CRASHED) { @@ -225,6 +258,7 @@ static int cmd_mgr_queue(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd) cmd_complete(cmd_mgr, cmd); } spin_unlock_bh(&cmd_mgr->lock); + rwnx_exception_event(cmd_mgr); } else { kfree(cmd); if (!list_empty(&cmd_mgr->cmds)) @@ -341,6 +375,7 @@ void cmd_mgr_task_process(struct work_struct *work) cmd_complete(cmd_mgr, next); } spin_unlock_bh(&cmd_mgr->lock); + rwnx_exception_event(cmd_mgr); } else kfree(next); } @@ -358,9 +393,9 @@ static int cmd_mgr_run_callback(struct rwnx_hw *rwnx_hw, struct rwnx_cmd *cmd, return 0; } //RWNX_DBG(RWNX_FN_ENTRY_STR); - spin_lock_bh(&rwnx_hw->cb_lock); + //spin_lock_bh(&rwnx_hw->cb_lock); res = cb(rwnx_hw, cmd, msg); - spin_unlock_bh(&rwnx_hw->cb_lock); + //spin_unlock_bh(&rwnx_hw->cb_lock); return res; } @@ -384,8 +419,9 @@ static int cmd_mgr_msgind(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd_e2amsg * bool found = false; // RWNX_DBG(RWNX_FN_ENTRY_STR); +#ifdef CREATE_TRACE_POINTS trace_msg_recv(msg->id); - +#endif //printk("cmd->id=%x\n", msg->id); spin_lock_bh(&cmd_mgr->lock); list_for_each_entry(cmd, &cmd_mgr->cmds, list) { diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c index 07d17becd..9840fcd30 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_debugfs.c @@ -1225,6 +1225,34 @@ static ssize_t rwnx_dbgfs_set_write(struct file *file, DEBUGFS_READ_WRITE_FILE_OPS(set); #endif /* CONFIG_RWNX_RADAR */ +static ssize_t rwnx_dbgfs_regdbg_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct rwnx_hw *priv = file->private_data; + char buf[32]; + u32 addr, val, oper; + size_t len = min_t(size_t, count, sizeof(buf) - 1); + struct dbg_mem_read_cfm mem_read_cfm; + int ret; + + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + + if (sscanf(buf, "%x %x %x", &oper, &addr, &val) > 0) + printk("addr=%x, val=%x,oper=%d\n", addr, val, oper); + + if (oper == 0) { + ret = rwnx_send_dbg_mem_read_req(priv, addr, &mem_read_cfm); + printk("[0x%x] = [0x%x]\n", mem_read_cfm.memaddr, mem_read_cfm.memdata); + } + + return count; +} + +DEBUGFS_WRITE_FILE_OPS(regdbg); #ifdef CONFIG_RWNX_FULLMAC #define LINE_MAX_SZ 150 diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h index 8d6d51b0d..56e0741c4 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_defs.h @@ -126,6 +126,13 @@ struct rwnx_csa { struct work_struct work; }; +struct apm_probe_sta { + u8 sta_mac_addr[6]; + u8 vif_idx; + u64 probe_id; + struct work_struct apmprobestaWork; + struct workqueue_struct *apmprobesta_wq; +}; /// Possible States of the TDLS link. enum tdls_status_tag { /// TDLS link is not active (no TDLS peer connected) @@ -229,6 +236,7 @@ struct rwnx_vif { u8_l key_has_add; u8_l is_p2p_vif; + struct apm_probe_sta sta_probe; }; #define RWNX_VIF_TYPE(rwnx_vif) (rwnx_vif->wdev.iftype) @@ -508,6 +516,8 @@ struct rwnx_hw { bool band_5g_support; u8_l vendor_info; bool fwlog_en; + u16 chipid; + u8 cpmode; struct list_head defrag_list; spinlock_t defrag_lock; @@ -516,6 +526,13 @@ struct rwnx_hw { struct workqueue_struct *apmStaloss_wq; u8 apm_vif_idx; u8 sta_mac_addr[6]; + + struct wakeup_source *ws_rx; + struct wakeup_source *ws_tx; + struct wakeup_source *ws_pwrctrl; + + u8 wakeup_enable; + u32 hostwake_irq_num; }; u8 *rwnx_build_bcn(struct rwnx_bcn *bcn, struct cfg80211_beacon_data *new); diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c index 46adcbe19..c202aa23a 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_main.c @@ -48,6 +48,7 @@ #include "aicwf_usb.h" #endif #include "aic_bsp_export.h" +#include "rwnx_wakelock.h" #define RW_DRV_DESCRIPTION "RivieraWaves 11nac driver for Linux cfg80211" #define RW_DRV_COPYRIGHT "Copyright(c) 2015-2017 RivieraWaves" @@ -687,18 +688,48 @@ static void rwnx_del_csa(struct rwnx_vif *vif) kfree(csa); vif->ap.csa = NULL; } - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) static void rwnx_csa_finish(struct work_struct *ws) { struct rwnx_csa *csa = container_of(ws, struct rwnx_csa, work); struct rwnx_vif *vif = csa->vif; struct rwnx_hw *rwnx_hw = vif->rwnx_hw; int error = csa->status; + u8 *buf, *pos; - if (!error) + RWNX_DBG(RWNX_FN_ENTRY_STR); + + buf = kmalloc(csa->bcn.len, GFP_KERNEL); + if (!buf) { + printk ("%s buf fail\n", __func__); + return; + } + pos = buf; + + memcpy(pos, csa->bcn.head, csa->bcn.head_len); + pos += csa->bcn.head_len; + *pos++ = WLAN_EID_TIM; + *pos++ = 4; + *pos++ = 0; + *pos++ = csa->bcn.dtim; + *pos++ = 0; + *pos++ = 0; + if (csa->bcn.tail) { + memcpy(pos, csa->bcn.tail, csa->bcn.tail_len); + pos += csa->bcn.tail_len; + } + if (csa->bcn.ies) { + memcpy(pos, csa->bcn.ies, csa->bcn.ies_len); + } + + if (!error) { + error = rwnx_send_bcn(rwnx_hw, buf, vif->vif_index, csa->bcn.len); + if (error) + return; error = rwnx_send_bcn_change(rwnx_hw, vif->vif_index, 0, csa->bcn.len, csa->bcn.head_len, csa->bcn.tim_len, NULL); + } if (error) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) @@ -724,6 +755,7 @@ static void rwnx_csa_finish(struct work_struct *ws) } rwnx_del_csa(vif); } +#endif /** * rwnx_external_auth_enable - Enable external authentication on a vif @@ -1601,7 +1633,7 @@ int handle_private_cmd(struct net_device *net, char *command, u32 cmd_len) } else { printk("wrong args\n"); } - } else if (strcasecmp(argv[0], "SETSUSPENDMODE") == 0) { + } else if (strcasecmp(argv[0], "SETSUSPENDMODE") == 0 && g_rwnx_plat->sdiodev->rwnx_hw->cpmode != AICBSP_CPMODE_TEST) { #ifdef AICWF_SDIO_SUPPORT setsusp_mode = command_strtoul(argv[1], NULL, 10); rwnx_send_me_set_lp_level(g_rwnx_plat->sdiodev->rwnx_hw, setsusp_mode); @@ -2345,7 +2377,6 @@ static int rwnx_cfg80211_change_iface(struct wiphy *wiphy, if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) p2p = true; - if (type == NL80211_IFTYPE_AP || type == NL80211_IFTYPE_P2P_GO) { if (vif->up) { /* Abort scan request on the vif */ if (vif->rwnx_hw->scan_request && @@ -2388,7 +2419,6 @@ static int rwnx_cfg80211_change_iface(struct wiphy *wiphy, vif->vif_index = add_if_cfm.inst_nbr; vif->rwnx_hw->vif_table[add_if_cfm.inst_nbr] = vif; spin_unlock_bh(&vif->rwnx_hw->cb_lock); - } } return 0; } @@ -2465,6 +2495,9 @@ static int rwnx_cfg80211_scan(struct wiphy *wiphy, RWNX_DBG(RWNX_FN_ENTRY_STR); + if (rwnx_hw->cpmode == AICBSP_CPMODE_TEST) + return -EBUSY; + if (scanning) { printk("is scanning, abort\n"); error = rwnx_send_scanu_cancel_req(rwnx_hw, NULL); @@ -2473,12 +2506,11 @@ static int rwnx_cfg80211_scan(struct wiphy *wiphy, msleep(150); } + rwnx_hw->scan_request = request; error = rwnx_send_scanu_req(rwnx_hw, rwnx_vif, request); if (error) return error; - rwnx_hw->scan_request = request; - return 0; } @@ -2703,7 +2735,7 @@ static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, key_params.cipher = sme->crypto.cipher_group; rwnx_cfg80211_add_key(wiphy, dev, sme->key_idx, false, NULL, &key_params); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) else if ((sme->auth_type == NL80211_AUTHTYPE_SAE) && !(sme->flags & CONNECT_REQ_EXTERNAL_AUTH_SUPPORT)) { netdev_err(dev, "Doesn't support SAE without external authentication\n"); @@ -2759,7 +2791,7 @@ static int rwnx_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, return rwnx_send_sm_disconnect_req(rwnx_hw, rwnx_vif, reason_code); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) /** * @external_auth: indicates result of offloaded authentication processing from * user space @@ -2965,6 +2997,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, macaddr = cur->mac_addr; printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ macaddr[3], macaddr[4], macaddr[5]); + spin_lock_bh(&rx_priv->stas_reord_lock); list_for_each_entry_safe(reord_info, reord_tmp, &rx_priv->stas_reord_list, list) { printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ @@ -2974,6 +3007,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, break; } } + spin_unlock_bh(&rx_priv->stas_reord_lock); } #endif @@ -2992,7 +3026,7 @@ static int rwnx_cfg80211_del_station_compat(struct wiphy *wiphy, #ifdef CONFIG_DEBUG_FS rwnx_dbgfs_unregister_rc_stat(rwnx_hw, cur); #endif - found++; + found = true; break; } } @@ -3056,9 +3090,9 @@ void apm_staloss_work_process(struct work_struct *work) } } } - if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { + /*if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP || rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { cfg80211_del_sta(rwnx_vif->ndev, cur->mac_addr, GFP_KERNEL); - } + }*/ #ifdef AICWF_RX_REORDER #ifdef AICWF_SDIO_SUPPORT @@ -3072,6 +3106,7 @@ void apm_staloss_work_process(struct work_struct *work) macaddr = cur->mac_addr; printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ macaddr[3], macaddr[4], macaddr[5]); + spin_lock_bh(&rx_priv->stas_reord_lock); list_for_each_entry_safe(reord_info, reord_tmp, &rx_priv->stas_reord_list, list) { printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ @@ -3081,6 +3116,7 @@ void apm_staloss_work_process(struct work_struct *work) break; } } + spin_unlock_bh(&rx_priv->stas_reord_lock); } #endif @@ -3110,7 +3146,39 @@ void apm_staloss_work_process(struct work_struct *work) rwnx_update_mesh_power_mode(rwnx_vif); } +void apm_probe_sta_work_process(struct work_struct *work) +{ + struct apm_probe_sta *probe_sta = container_of(work, struct apm_probe_sta, apmprobestaWork); + struct rwnx_vif *rwnx_vif = container_of(probe_sta, struct rwnx_vif, sta_probe); + bool found = false; + struct rwnx_sta *cur, *tmp; + u8 *mac = rwnx_vif->sta_probe.sta_mac_addr; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + list_for_each_entry_safe(cur, tmp, &rwnx_vif->ap.sta_list, list) { + if (!memcmp(cur->mac_addr, mac, ETH_ALEN)) { + found = true; + break; + } + } + + printk("sta %pM found = %d\n", mac, found); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) + if (found) + cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, 0, false, GFP_ATOMIC); + else + cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, 0, false, GFP_ATOMIC); +#else + if (found) + cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 1, GFP_ATOMIC); + else + cfg80211_probe_status(rwnx_vif->ndev, mac, (u64)rwnx_vif->sta_probe.probe_id, 0, GFP_ATOMIC); + +#endif + rwnx_vif->sta_probe.probe_id++; +} /** * @change_station: Modify a given station. Note that flags changes are not much * validated in cfg80211, in particular the auth/assoc/authorized flags @@ -3281,6 +3349,12 @@ static int rwnx_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, RWNX_DBG(RWNX_FN_ENTRY_STR); + INIT_WORK(&rwnx_vif->sta_probe.apmprobestaWork, apm_probe_sta_work_process); + rwnx_vif->sta_probe.apmprobesta_wq = create_singlethread_workqueue("apmprobe_wq"); + if (!rwnx_vif->sta_probe.apmprobesta_wq) { + txrx_err("insufficient memory to create apmprobe_wq.\n"); + return -ENOBUFS; + } if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) rwnx_hw->is_p2p_connected = 1; /* Forward the information to the LMAC */ @@ -3412,6 +3486,9 @@ static int rwnx_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) rwnx_del_bcn(&rwnx_vif->ap.bcn); rwnx_del_csa(rwnx_vif); + flush_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); + destroy_workqueue(rwnx_vif->sta_probe.apmprobesta_wq); + netif_tx_stop_all_queues(dev); netif_carrier_off(dev); @@ -3489,6 +3566,29 @@ static int rwnx_cfg80211_set_monitor_channel(struct wiphy *wiphy, int rwnx_cfg80211_probe_client(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u64 *cookie) { + //struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); + struct rwnx_vif *vif = netdev_priv(dev); + struct rwnx_sta *sta = NULL; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + if ((RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP) && (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_P2P_GO) && + (RWNX_VIF_TYPE(vif) != NL80211_IFTYPE_AP_VLAN)) + return -EINVAL; + list_for_each_entry(sta, &vif->ap.sta_list, list) { + if (sta->valid && ether_addr_equal(sta->mac_addr, peer)) + break; + } + + if (!sta) + return -ENOENT; + + + memcpy(vif->sta_probe.sta_mac_addr, peer, 6); + queue_work(vif->sta_probe.apmprobesta_wq, &vif->sta_probe.apmprobestaWork); + + *cookie = vif->sta_probe.probe_id; + return 0; } @@ -3639,8 +3739,9 @@ rwnx_cfg80211_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, RWNX_DBG(RWNX_FN_ENTRY_STR); /* For debug purpose (use ftrace kernel option) */ +#ifdef CREATE_TRACE_POINTS trace_roc(rwnx_vif->vif_index, chan->center_freq, duration); - +#endif /* Check that no other RoC procedure has been launched */ if (rwnx_hw->roc_elem) { msleep(2); @@ -3731,13 +3832,15 @@ static int rwnx_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, u64 cookie) { struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy); +#ifdef CREATE_TRACE_POINTS struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);//netdev_priv(wdev->netdev); - +#endif RWNX_DBG(RWNX_FN_ENTRY_STR); /* For debug purpose (use ftrace kernel option) */ +#ifdef CREATE_TRACE_POINTS trace_cancel_roc(rwnx_vif->vif_index); - +#endif /* Check if a RoC procedure is pending */ if (!rwnx_hw->roc_elem) { return 0; @@ -3885,11 +3988,11 @@ static int rwnx_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, /* Get STA on which management frame has to be sent */ rwnx_sta = rwnx_retrieve_sta(rwnx_hw, rwnx_vif, mgmt->da, mgmt->frame_control, ap); - +#ifdef CREATE_TRACE_POINTS trace_mgmt_tx((channel) ? channel->center_freq : 0, rwnx_vif->vif_index, (rwnx_sta) ? rwnx_sta->sta_idx : 0xFF, mgmt); - +#endif if (ap || rwnx_sta) goto send_frame; @@ -4098,7 +4201,11 @@ int rwnx_cfg80211_channel_switch (struct wiphy *wiphy, goto end; } else { INIT_WORK(&csa->work, rwnx_csa_finish); - rwnx_cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count); + rwnx_cfg80211_ch_switch_started_notify(dev, &csa->chandef, params->count +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) + , params->block_tx +#endif + ); } end: @@ -4471,7 +4578,8 @@ static int rwnx_fill_station_info(struct rwnx_sta *sta, struct rwnx_vif *vif, case FORMATMOD_HE_SU: case FORMATMOD_HE_ER: sinfo->rxrate.flags = RATE_INFO_FLAGS_VHT_MCS; - sinfo->rxrate.mcs = rx_vect1->he.mcs; + sinfo->rxrate.mcs = rx_vect1->he.mcs; + break; #endif default: return -EINVAL; @@ -4527,7 +4635,7 @@ static int rwnx_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev if (sta) return rwnx_fill_station_info(sta, vif, sinfo); - return -EINVAL; + return -ENOENT; } @@ -5031,7 +5139,7 @@ static struct cfg80211_ops rwnx_cfg80211_ops = { .tdls_mgmt = rwnx_cfg80211_tdls_mgmt, .tdls_oper = rwnx_cfg80211_tdls_oper, .change_bss = rwnx_cfg80211_change_bss, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) .external_auth = rwnx_cfg80211_external_auth, #endif }; @@ -5122,7 +5230,6 @@ static const struct wiphy_wowlan_support aic_wowlan_support = { * */ extern int aicwf_vendor_init(struct wiphy *wiphy); -extern txpwr_idx_conf_t nvram_txpwr_idx; int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) { @@ -5158,6 +5265,7 @@ int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) rwnx_hw->wiphy = wiphy; rwnx_hw->plat = rwnx_plat; rwnx_hw->dev = rwnx_platform_get_dev(rwnx_plat); + rwnx_hw->chipid = feature.chipinfo->chipid; #ifdef AICWF_SDIO_SUPPORT rwnx_hw->sdiodev = rwnx_plat->sdiodev; rwnx_plat->sdiodev->rwnx_hw = rwnx_hw; @@ -5170,6 +5278,7 @@ int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) rwnx_hw->mod_params = &rwnx_mod_params; rwnx_hw->tcp_pacing_shift = 7; + aicwf_wakeup_lock_init(rwnx_hw); rwnx_init_aic(rwnx_hw); /* set device pointer for wiphy */ set_wiphy_dev(wiphy, rwnx_hw->dev); @@ -5232,6 +5341,7 @@ int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) wiphy->mgmt_stypes = rwnx_default_mgmt_stypes; rwnx_hw->fwlog_en = feature.fwlog_en; + rwnx_hw->cpmode = feature.cpmode; ret = rwnx_send_set_stack_start_req(rwnx_hw, 1, feature.hwinfo < 0, feature.hwinfo, feature.fwlog_en, &set_start_cfm); if (ret) goto err_lmac_reqs; @@ -5285,7 +5395,7 @@ int rwnx_cfg80211_init(struct rwnx_plat *rwnx_plat, void **platform_data) #endif 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) wiphy->features |= NL80211_FEATURE_SAE; #endif @@ -5450,6 +5560,7 @@ err_platon: //err_config: kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); err_cache: + aicwf_wakeup_lock_deinit(rwnx_hw); wiphy_free(wiphy); err_out: return ret; @@ -5495,6 +5606,7 @@ void rwnx_cfg80211_deinit(struct rwnx_hw *rwnx_hw) rwnx_radar_detection_deinit(&rwnx_hw->radar); rwnx_platform_off(rwnx_hw, NULL); kmem_cache_destroy(rwnx_hw->sw_txhdr_cache); + aicwf_wakeup_lock_deinit(rwnx_hw); wiphy_free(rwnx_hw->wiphy); } @@ -5551,6 +5663,7 @@ static int __init rwnx_mod_init(void) #ifdef AICWF_USB_SUPPORT aicwf_usb_exit(); #endif /*AICWF_USB_SUPPORT */ + aicbsp_set_subsys(AIC_WIFI, AIC_PWR_OFF); return -ENODEV; } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c index 92e922720..7db1f8f97 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_mod_params.c @@ -33,7 +33,7 @@ struct rwnx_mod_params rwnx_mod_params = { COMMON_PARAM(vht_on, true, true) COMMON_PARAM(he_on, true, true) COMMON_PARAM(mcs_map, IEEE80211_VHT_MCS_SUPPORT_0_9, IEEE80211_VHT_MCS_SUPPORT_0_9) - COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_9, IEEE80211_HE_MCS_SUPPORT_0_9) + COMMON_PARAM(he_mcs_map, IEEE80211_HE_MCS_SUPPORT_0_11, IEEE80211_HE_MCS_SUPPORT_0_11) COMMON_PARAM(he_ul_on, false, false) COMMON_PARAM(ldpc_on, true, true) COMMON_PARAM(stbc_on, true, true) @@ -973,9 +973,15 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) #endif if (rwnx_hw->mod_params->stbc_on) he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) + he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | + IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | + IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; +#else he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; +#endif if (rwnx_hw->mod_params->bfmee) { he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; he_cap->he_cap_elem.phy_cap_info[4] |= @@ -983,12 +989,21 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) } he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) + he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | + IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | + IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | + IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | + IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; +#else he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; +#endif he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) @@ -1062,9 +1077,15 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) #endif if (rwnx_hw->mod_params->stbc_on) he_cap->he_cap_elem.phy_cap_info[2] |= IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) + he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | + IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | + IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU; +#else he_cap->he_cap_elem.phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_16_QAM | IEEE80211_HE_PHY_CAP3_DCM_MAX_RX_NSS_1 | IEEE80211_HE_PHY_CAP3_RX_HE_MU_PPDU_FROM_NON_AP_STA; +#endif if (rwnx_hw->mod_params->bfmee) { he_cap->he_cap_elem.phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE; he_cap->he_cap_elem.phy_cap_info[4] |= @@ -1072,12 +1093,21 @@ static void rwnx_set_he_capa(struct rwnx_hw *rwnx_hw, struct wiphy *wiphy) } he_cap->he_cap_elem.phy_cap_info[5] |= IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK | IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 13, 0) + he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | + IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | + IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMING_FB | + IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMING_PARTIAL_BW_FB | + IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | + IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; +#else he_cap->he_cap_elem.phy_cap_info[6] |= IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_42_SU | IEEE80211_HE_PHY_CAP6_CODEBOOK_SIZE_75_MU | IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB | IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT | IEEE80211_HE_PHY_CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO; +#endif he_cap->he_cap_elem.phy_cap_info[7] |= IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI; he_cap->he_cap_elem.phy_cap_info[8] |= IEEE80211_HE_PHY_CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G; #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0) diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c index 90922b3f3..a436750d1 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_rx.c @@ -45,7 +45,7 @@ static int rwnx_freq_to_idx(struct rwnx_hw *rwnx_hw, int freq) } } - BUG_ON(1); + WARN_ON(1); exit: // Channel has been found, return the index @@ -218,8 +218,9 @@ static inline int rwnx_rx_remain_on_channel_exp_ind(struct rwnx_hw *rwnx_hw, rwnx_vif = container_of(roc_elem->wdev, struct rwnx_vif, wdev); /* For debug purpose (use ftrace kernel option) */ +#ifdef CREATE_TRACE_POINTS trace_roc_exp(rwnx_vif->vif_index); - +#endif /* If mgmt_roc is true, remain on channel has been started by ourself */ /* If RoC has been cancelled before we switched on channel, do not call cfg80211 */ if (!roc_elem->mgmt_roc && roc_elem->on_chan) { @@ -506,7 +507,7 @@ static inline int rwnx_rx_ps_change_ind(struct rwnx_hw *rwnx_hw, } else if (rwnx_hw->adding_sta) { sta->ps.active = ind->ps_state ? true : false; } else { - if (rwnx_hw->vif_table[sta->vif_idx]->ndev) + if (rwnx_hw->vif_table[sta->vif_idx] && rwnx_hw->vif_table[sta->vif_idx]->ndev) netdev_err(rwnx_hw->vif_table[sta->vif_idx]->ndev, "Ignore PS mode change on invalid sta\n"); } @@ -572,7 +573,6 @@ static inline int rwnx_rx_scanu_start_cfm(struct rwnx_hw *rwnx_hw, { RWNX_DBG(RWNX_FN_ENTRY_STR); - scanning = 0; if (rwnx_hw->scan_request) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0) struct cfg80211_scan_info info = { @@ -586,6 +586,7 @@ static inline int rwnx_rx_scanu_start_cfm(struct rwnx_hw *rwnx_hw, } rwnx_hw->scan_request = NULL; + scanning = 0; return 0; } @@ -633,7 +634,7 @@ static inline int rwnx_rx_scanu_result_ind(struct rwnx_hw *rwnx_hw, CFG80211_BSS_FTYPE_UNKNOWN, #endif mgmt->bssid, tsf, capability, beacon_interval, - ie, ielen, ind->rssi * 100, GFP_KERNEL); + ie, ielen, ind->rssi * 100, GFP_ATOMIC); } if (bss != NULL) @@ -842,7 +843,7 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, { struct sm_disconnect_ind *ind = (struct sm_disconnect_ind *)msg->param; struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; - struct net_device *dev = rwnx_vif->ndev; + struct net_device *dev; #ifdef AICWF_RX_REORDER struct reord_ctrl_info *reord_info, *tmp; u8 *macaddr; @@ -852,6 +853,10 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, RWNX_DBG(RWNX_FN_ENTRY_STR); dhcped = 0; + if (!rwnx_vif) + return 0; + dev = rwnx_vif->ndev; + if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) rwnx_hw->is_p2p_connected = 0; /* if vif is not up, rwnx_close has already been called */ @@ -879,7 +884,7 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, macaddr = rwnx_vif->ndev->dev_addr; printk("deinit:macaddr:%x,%x,%x,%x,%x,%x\r\n", macaddr[0], macaddr[1], macaddr[2], \ macaddr[3], macaddr[4], macaddr[5]); - + spin_lock_bh(&rx_priv->stas_reord_lock); list_for_each_entry_safe(reord_info, tmp, &rx_priv->stas_reord_list, list) { macaddr = rwnx_vif->ndev->dev_addr; printk("reord_mac:%x,%x,%x,%x,%x,%x\r\n", reord_info->mac_addr[0], reord_info->mac_addr[1], reord_info->mac_addr[2], \ @@ -889,6 +894,7 @@ static inline int rwnx_rx_sm_disconnect_ind(struct rwnx_hw *rwnx_hw, break; } } + spin_unlock_bh(&rx_priv->stas_reord_lock); } else if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_AP) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { BUG();//should be not here: del_sta function } @@ -914,7 +920,7 @@ static inline int rwnx_rx_sm_external_auth_required_ind(struct rwnx_hw *rwnx_hw, struct sm_external_auth_required_ind *ind = (struct sm_external_auth_required_ind *)msg->param; struct rwnx_vif *rwnx_vif = rwnx_hw->vif_table[ind->vif_idx]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) || defined(CONFIG_WPA3_FOR_OLD_KERNEL) struct net_device *dev = rwnx_vif->ndev; struct cfg80211_external_auth_params params; @@ -1090,7 +1096,9 @@ static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, /* Check if element has been deleted */ if (ind->delete) { if (found) { +#ifdef CREATE_TRACE_POINTS trace_mesh_delete_path(mesh_path); +#endif /* Remove element from list */ list_del_init(&mesh_path->list); /* Free the element */ @@ -1100,7 +1108,9 @@ static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, if (found) { // Update the Next Hop STA mesh_path->p_nhop_sta = &rwnx_hw->sta_table[ind->nhop_sta_idx]; +#ifdef CREATE_TRACE_POINTS trace_mesh_update_path(mesh_path); +#endif } else { // Allocate a Mesh Path structure mesh_path = (struct rwnx_mesh_path *)kmalloc(sizeof(struct rwnx_mesh_path), GFP_ATOMIC); @@ -1114,8 +1124,9 @@ static inline int rwnx_rx_mesh_path_update_ind(struct rwnx_hw *rwnx_hw, // Insert the path in the list of path list_add_tail(&mesh_path->list, &rwnx_vif->ap.mpath_list); - +#ifdef CREATE_TRACE_POINTS trace_mesh_create_path(mesh_path); +#endif } } } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c index 1ea0c0124..336c02f2f 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_msg_tx.c @@ -19,6 +19,8 @@ #include "rwnx_compat.h" #include "rwnx_cmds.h" #include "aicwf_txrxif.h" +#include "rwnx_wakelock.h" +#include "aic_bsp_export.h" const struct mac_addr mac_addr_bcst = {{0xFFFF, 0xFFFF, 0xFFFF}}; @@ -227,6 +229,7 @@ static int rwnx_send_msg(struct rwnx_hw *rwnx_hw, const void *msg_params, //RWNX_DBG(RWNX_FN_ENTRY_STR); + rwnx_wakeup_lock_timeout(rwnx_hw->ws_tx, jiffies_to_msecs(5)); #ifdef AICWF_USB_SUPPORT if (rwnx_hw->usbdev->state == USB_DOWN_ST) { rwnx_msg_free(rwnx_hw, msg_params); @@ -325,6 +328,7 @@ static int rwnx_send_msg1(struct rwnx_hw *rwnx_hw, const void *msg_params, RWNX_DBG(RWNX_FN_ENTRY_STR); + rwnx_wakeup_lock_timeout(rwnx_hw->ws_tx, jiffies_to_msecs(5)); msg = container_of((void *)msg_params, struct lmac_msg, param); //nonblock = is_non_blocking_msg(msg->id); @@ -853,6 +857,9 @@ int rwnx_send_coex_req(struct rwnx_hw *rwnx_hw, u8_l disable_coexnull, u8_l enab struct mm_set_coex_req *coex_req; int error; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC && rwnx_hw->cpmode == AICBSP_CPMODE_TEST) + return 0; + RWNX_DBG(RWNX_FN_ENTRY_STR); /* Build the MM_SET_COEX_REQ message */ @@ -908,8 +915,12 @@ int rwnx_send_rf_config_req(struct rwnx_hw *rwnx_hw) int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm) { struct mm_set_rf_calib_req *rf_calib_req; + xtal_cap_conf_t xtal_cap = {0,}; int error; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC && rwnx_hw->cpmode == AICBSP_CPMODE_TEST) + return 0; + RWNX_DBG(RWNX_FN_ENTRY_STR); /* Build the MM_SET_P2P_NOA_REQ message */ @@ -928,6 +939,13 @@ int rwnx_send_rf_calib_req(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm * rf_calib_req->xtal_cap = 0; rf_calib_req->xtal_cap_fine = 0; + get_userconfig_xtal_cap(&xtal_cap); + + if (xtal_cap.enable) { + rf_calib_req->xtal_cap = xtal_cap.xtal_cap; + rf_calib_req->xtal_cap_fine = xtal_cap.xtal_cap_fine; + } + /* Send the MM_SET_RF_CALIB_REQ message to UMAC FW */ error = rwnx_send_msg(rwnx_hw, rf_calib_req, 1, MM_SET_RF_CALIB_CFM, cfm); @@ -1044,6 +1062,52 @@ int rwnx_send_get_fw_version_req(struct rwnx_hw *rwnx_hw, struct mm_get_fw_versi return error; } +int rwnx_send_txpwr_lvl_req(struct rwnx_hw *rwnx_hw) +{ + struct mm_set_txpwr_lvl_req *txpwr_lvl_req; + txpwr_lvl_conf_v2_t txpwr_lvl_v2_tmp; + txpwr_lvl_conf_v2_t *txpwr_lvl_v2; + int error = 0; + + RWNX_DBG(RWNX_FN_ENTRY_STR); + + /* Build the MM_SET_TXPWR_LVL_REQ message */ + txpwr_lvl_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, + sizeof(struct mm_set_txpwr_lvl_req)); + + if (!txpwr_lvl_req) { + return -ENOMEM; + } + + txpwr_lvl_v2 = &txpwr_lvl_v2_tmp; + + get_userconfig_txpwr_lvl_v2(txpwr_lvl_v2); + + if (txpwr_lvl_v2->enable == 0) { + rwnx_msg_free(rwnx_hw, txpwr_lvl_req); + } else { + struct aicbsp_feature_t feature; + aicbsp_get_feature(&feature); + if ((feature.cpmode != AICBSP_CPMODE_TEST) && (feature.chipinfo->subrev == 0)) { + txpwr_lvl_req->txpwr_lvl.enable = txpwr_lvl_v2->enable; + txpwr_lvl_req->txpwr_lvl.dsss = txpwr_lvl_v2->pwrlvl_11b_11ag_2g4[3]; // 11M + txpwr_lvl_req->txpwr_lvl.ofdmlowrate_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[4]; // MCS4 + txpwr_lvl_req->txpwr_lvl.ofdm64qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[7]; // MCS7 + txpwr_lvl_req->txpwr_lvl.ofdm256qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[9]; // MCS9 + txpwr_lvl_req->txpwr_lvl.ofdm1024qam_2g4 = txpwr_lvl_v2->pwrlvl_11ax_2g4[11]; // MCS11 + txpwr_lvl_req->txpwr_lvl.ofdmlowrate_5g = 13; // unused + txpwr_lvl_req->txpwr_lvl.ofdm64qam_5g = 13; // unused + txpwr_lvl_req->txpwr_lvl.ofdm256qam_5g = 13; // unused + txpwr_lvl_req->txpwr_lvl.ofdm1024qam_5g = 13; // unused + } else { + txpwr_lvl_req->txpwr_lvl_v2 = *txpwr_lvl_v2; + } + + /* Send the MM_SET_TXPWR_LVL_REQ message to UMAC FW */ + error = rwnx_send_msg(rwnx_hw, txpwr_lvl_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); + } + return error; +} int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) { @@ -1051,10 +1115,14 @@ int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) txpwr_idx_conf_t *txpwr_idx; int error; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC) { + return rwnx_send_txpwr_lvl_req(rwnx_hw); + } + RWNX_DBG(RWNX_FN_ENTRY_STR); /* Build the MM_SET_TXPWR_IDX_REQ message */ - txpwr_idx_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_REQ, TASK_MM, DRV_TASK_ID, + txpwr_idx_req = rwnx_msg_zalloc(MM_SET_TXPWR_IDX_LVL_REQ, TASK_MM, DRV_TASK_ID, sizeof(struct mm_set_txpwr_idx_req)); if (!txpwr_idx_req) { @@ -1080,7 +1148,7 @@ int rwnx_send_txpwr_idx_req(struct rwnx_hw *rwnx_hw) return 0; } else { /* Send the MM_SET_TXPWR_IDX_REQ message to UMAC FW */ - error = rwnx_send_msg(rwnx_hw, txpwr_idx_req, 1, MM_SET_TXPWR_IDX_CFM, NULL); + error = rwnx_send_msg(rwnx_hw, txpwr_idx_req, 1, MM_SET_TXPWR_IDX_LVL_CFM, NULL); return error; } @@ -1149,6 +1217,8 @@ int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) #endif uint8_t *ht_mcs; int i; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC && rwnx_hw->cpmode == AICBSP_CPMODE_TEST) + return 0; if (rwnx_hw->band_5g_support) { ht_cap = &wiphy->bands[NL80211_BAND_5GHZ]->ht_cap; @@ -1197,8 +1267,6 @@ int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) #if defined(CONFIG_HE_FOR_OLD_KERNEL) if (1) { he_cap = &rwnx_he_capa.he_cap; - #else - { #endif req->he_supp = he_cap->has_he; for (i = 0; i < ARRAY_SIZE(he_cap->he_cap_elem.mac_cap_info); i++) { @@ -1218,7 +1286,6 @@ int rwnx_send_me_config_req(struct rwnx_hw *rwnx_hw) } req->he_ul_on = rwnx_hw->mod_params->he_ul_on; } -} #else req->he_supp = false; req->he_ul_on = false; @@ -1247,6 +1314,9 @@ int rwnx_send_me_chan_config_req(struct rwnx_hw *rwnx_hw) struct wiphy *wiphy = rwnx_hw->wiphy; int i; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC && rwnx_hw->cpmode == AICBSP_CPMODE_TEST) + return 0; + RWNX_DBG(RWNX_FN_ENTRY_STR); /* Build the ME_CHAN_CONFIG_REQ message */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c index 6ca467c7e..25e495283 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.c @@ -16,7 +16,6 @@ #include "reg_access.h" #include "hal_desc.h" #include "rwnx_main.h" -#include "rwnx_pci.h" #ifndef CONFIG_RWNX_FHOST #include "ipc_host.h" #endif /* !CONFIG_RWNX_FHOST */ @@ -30,6 +29,12 @@ #include "aicwf_usb.h" #endif +#ifdef AICWF_PCIE_SUPPORT +#include "rwnx_pci.h" +#endif + +#include "aic_bsp_export.h" + struct rwnx_plat *g_rwnx_plat; #ifdef CONFIG_RWNX_TL4 @@ -224,7 +229,9 @@ static int rwnx_plat_bin_fw_upload_2(struct rwnx_hw *rwnx_hw, u32 fw_addr, typedef struct { txpwr_idx_conf_t txpwr_idx; + txpwr_lvl_conf_v2_t txpwr_lvl_v2; txpwr_ofst_conf_t txpwr_ofst; + xtal_cap_conf_t xtal_cap; } nvram_info_t; nvram_info_t nvram_info = { @@ -240,6 +247,18 @@ nvram_info_t nvram_info = { .ofdm256qam_5g = 9, .ofdm1024qam_5g = 9 }, + .txpwr_lvl_v2 = { + .enable = 1, + .pwrlvl_11b_11ag_2g4 = { + // 1M, 2M, 5M5, 11M, 6M, 9M, 12M, 18M, 24M, 36M, 48M, 54M + 20, 20, 20, 20, 20, 20, 20, 20, 18, 18, 16, 16}, + .pwrlvl_11n_11ac_2g4 = { + // MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9 + 20, 20, 20, 20, 18, 18, 16, 16, 16, 16}, + .pwrlvl_11ax_2g4 = { + // MCS0, MCS1, MCS2, MCS3, MCS4, MCS5, MCS6, MCS7, MCS8, MCS9, MCS10, MCS11 + 20, 20, 20, 20, 18, 18, 16, 16, 16, 16, 15, 15}, + }, .txpwr_ofst = { .enable = 1, .chan_1_4 = 0, @@ -250,8 +269,18 @@ nvram_info_t nvram_info = { .chan_122_140 = 0, .chan_142_165 = 0, }, + .xtal_cap = { + .enable = 0, + .xtal_cap = 24, + .xtal_cap_fine = 31, + }, }; +void get_userconfig_txpwr_lvl_v2(txpwr_lvl_conf_v2_t *txpwr_lvl_v2) +{ + memcpy(txpwr_lvl_v2, &(nvram_info.txpwr_lvl_v2), sizeof(txpwr_lvl_conf_v2_t)); +} + void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx) { memcpy(txpwr_idx, &(nvram_info.txpwr_idx), sizeof(txpwr_idx_conf_t)); @@ -262,6 +291,11 @@ void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst) memcpy(txpwr_ofst, &(nvram_info.txpwr_ofst), sizeof(txpwr_ofst_conf_t)); } +void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap) +{ + memcpy(xtal_cap, &(nvram_info.xtal_cap), sizeof(xtal_cap_conf_t)); +} + #define MATCH_NODE(type, node, cfg_key) {cfg_key, offsetof(type, node)} struct parse_match_t { @@ -272,6 +306,7 @@ struct parse_match_t { static const char *parse_key_prefix[] = { [0x01] = "module0_", [0x21] = "module1_", + [0xFF] = "", }; static const struct parse_match_t parse_match_tab[] = { @@ -286,6 +321,43 @@ static const struct parse_match_t parse_match_tab[] = { MATCH_NODE(nvram_info_t, txpwr_idx.ofdm256qam_5g, "ofdm256qam_5g"), MATCH_NODE(nvram_info_t, txpwr_idx.ofdm1024qam_5g, "ofdm1024qam_5g"), + {"lvl_11b_11ag_1m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 0}, + {"lvl_11b_11ag_2m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 1}, + {"lvl_11b_11ag_5m5_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 2}, + {"lvl_11b_11ag_11m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 3}, + {"lvl_11b_11ag_6m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 4}, + {"lvl_11b_11ag_9m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 5}, + {"lvl_11b_11ag_12m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 6}, + {"lvl_11b_11ag_18m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 7}, + {"lvl_11b_11ag_24m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 8}, + {"lvl_11b_11ag_36m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 9}, + {"lvl_11b_11ag_48m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 10}, + {"lvl_11b_11ag_54m_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11b_11ag_2g4) + 11}, + + {"lvl_11n_11ac_mcs0_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 0}, + {"lvl_11n_11ac_mcs1_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 1}, + {"lvl_11n_11ac_mcs2_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 2}, + {"lvl_11n_11ac_mcs3_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 3}, + {"lvl_11n_11ac_mcs4_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 4}, + {"lvl_11n_11ac_mcs5_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 5}, + {"lvl_11n_11ac_mcs6_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 6}, + {"lvl_11n_11ac_mcs7_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 7}, + {"lvl_11n_11ac_mcs8_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 8}, + {"lvl_11n_11ac_mcs9_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11n_11ac_2g4) + 9}, + + {"lvl_11ax_mcs0_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 0}, + {"lvl_11ax_mcs1_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 1}, + {"lvl_11ax_mcs2_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 2}, + {"lvl_11ax_mcs3_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 3}, + {"lvl_11ax_mcs4_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 4}, + {"lvl_11ax_mcs5_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 5}, + {"lvl_11ax_mcs6_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 6}, + {"lvl_11ax_mcs7_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 7}, + {"lvl_11ax_mcs8_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 8}, + {"lvl_11ax_mcs9_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 9}, + {"lvl_11ax_mcs10_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 10}, + {"lvl_11ax_mcs11_2g4", offsetof(nvram_info_t, txpwr_lvl_v2.pwrlvl_11ax_2g4) + 11}, + MATCH_NODE(nvram_info_t, txpwr_ofst.enable, "ofst_enable"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_1_4, "ofst_chan_1_4"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_5_9, "ofst_chan_5_9"), @@ -294,6 +366,10 @@ static const struct parse_match_t parse_match_tab[] = { MATCH_NODE(nvram_info_t, txpwr_ofst.chan_100_120, "ofst_chan_100_120"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_122_140, "ofst_chan_122_140"), MATCH_NODE(nvram_info_t, txpwr_ofst.chan_142_165, "ofst_chan_142_165"), + + MATCH_NODE(nvram_info_t, xtal_cap.enable, "xtal_enable"), + MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap, "xtal_cap"), + MATCH_NODE(nvram_info_t, xtal_cap.xtal_cap_fine, "xtal_cap_fine"), }; static int parse_key_val(const char *str, const char *key, char *val) @@ -366,6 +442,7 @@ void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int siz char *data; int i = 0, err, len = 0; long val; + u8 efuse_idx = 0; if (size <= 0) { pr_err("Config buffer size %d error\n", size); @@ -377,6 +454,15 @@ void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int siz return; } + efuse_idx = rwnx_hw->vendor_info; + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC || rwnx_hw->chipid == PRODUCT_ID_AIC8800DW) { + printk("AIC8800DC chipset\n"); + efuse_idx = 0xFF; + } else if (rwnx_hw->vendor_info == 0x00) { + printk("Empty efuse, using module0 config\n"); + efuse_idx = 0x01; + } + data = vmalloc(size + 1); if (!data) { pr_err("vmalloc fail\n"); @@ -402,10 +488,10 @@ void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int siz // store value to data struct for (i = 0; i < sizeof(parse_match_tab) / sizeof(parse_match_tab[0]); i++) { - sprintf(&keyname[0], "%s%s", parse_key_prefix[rwnx_hw->vendor_info], parse_match_tab[i].keyname); + sprintf(&keyname[0], "%s%s", parse_key_prefix[efuse_idx], parse_match_tab[i].keyname); if (parse_key_val(line, keyname, conf) == 0) { err = kstrtol(conf, 0, &val); - *(unsigned long *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; + *(unsigned char *)((unsigned long)&nvram_info + parse_match_tab[i].offset) = val; printk("%s, %s = %ld\n", __func__, parse_match_tab[i].keyname, val); break; } @@ -414,7 +500,8 @@ void rwnx_plat_userconfig_parsing(struct rwnx_hw *rwnx_hw, char *buffer, int siz vfree(data); } -#define FW_USERCONFIG_NAME "aic_userconfig.txt" +#define FW_USERCONFIG_NAME_8800D "aic_userconfig.txt" +#define FW_USERCONFIG_NAME_8800DC "aic8800dc/aic_userconfig.txt" int rwnx_plat_userconfig_upload_android(struct rwnx_hw *rwnx_hw, char *filename) { @@ -457,7 +544,11 @@ static int rwnx_plat_fmac_load(struct rwnx_hw *rwnx_hw) int ret = 0; RWNX_DBG(RWNX_FN_ENTRY_STR); - ret = rwnx_plat_userconfig_upload_android(rwnx_hw, FW_USERCONFIG_NAME); + if (rwnx_hw->chipid == PRODUCT_ID_AIC8800D) + ret = rwnx_plat_userconfig_upload_android(rwnx_hw, FW_USERCONFIG_NAME_8800D); + else if (rwnx_hw->chipid == PRODUCT_ID_AIC8800DC) + ret = rwnx_plat_userconfig_upload_android(rwnx_hw, FW_USERCONFIG_NAME_8800DC); + return ret; } #endif /* !CONFIG_ROM_PATCH_EN */ @@ -788,6 +879,7 @@ void rwnx_platform_deinit(struct rwnx_hw *rwnx_hw) #endif } +#ifdef AICWF_PCIE_SUPPORT /** * rwnx_platform_register_drv() - Register all possible platform drivers */ @@ -804,6 +896,23 @@ void rwnx_platform_unregister_drv(void) { return rwnx_pci_unregister_drv(); } +#else +/** + * rwnx_platform_register_drv() - Register all possible platform drivers + */ +int rwnx_platform_register_drv(void) +{ + return 0; +} + + +/** + * rwnx_platform_unregister_drv() - Unegister all platform drivers + */ +void rwnx_platform_unregister_drv(void) +{ +} +#endif struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) { @@ -813,7 +922,9 @@ struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat) #ifdef AICWF_USB_SUPPORT return rwnx_plat->usbdev->dev; #endif +#ifdef AICWF_PCIE_SUPPORT return &(rwnx_plat->pci_dev->dev); +#endif } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h index 751501eeb..9eac49ddb 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_platform.h @@ -111,8 +111,10 @@ void rwnx_platform_off(struct rwnx_hw *rwnx_hw, void **config); int rwnx_platform_register_drv(void); void rwnx_platform_unregister_drv(void); +void get_userconfig_txpwr_lvl_v2(txpwr_lvl_conf_v2_t *txpwr_lvl_v2); void get_userconfig_txpwr_idx(txpwr_idx_conf_t *txpwr_idx); void get_userconfig_txpwr_ofst(txpwr_ofst_conf_t *txpwr_ofst); +void get_userconfig_xtal_cap(xtal_cap_conf_t *xtal_cap); extern struct device *rwnx_platform_get_dev(struct rwnx_plat *rwnx_plat); diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c index 2dd875d4e..c50f2d2b1 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_radar.c @@ -1125,7 +1125,9 @@ static bool dfs_pattern_detector_add_pulse(struct dfs_pattern_detector *dpd, ps = pde->ops->add_pulse(pde, len, dpd->last_pulse_ts, pri); if (ps != NULL) { +#ifdef CREATE_TRACE_POINTS trace_radar_detected(chain, dpd->region, pde->freq, i, ps->pri); +#endif // reset everything instead of just the channel detector dfs_pattern_detector_reset(dpd); return true; @@ -1339,7 +1341,9 @@ static void rwnx_radar_process_pulse(struct work_struct *ws) for (i = 0; i < pulses_count[chain] ; i++) { struct radar_pulse *p = (struct radar_pulse *)&pulses[chain][i]; +#ifdef CREATE_TRACE_POINTS trace_radar_pulse(chain, p); +#endif if (dfs_pattern_detector_add_pulse(radar->dpd[chain], chain, (s16)freq + (2 * p->freq), p->rep, (p->len * 2), now)) { @@ -1444,9 +1448,9 @@ bool rwnx_radar_set_domain(struct rwnx_radar *radar, { if (radar->dpd[0] == NULL) return false; - +#ifdef CREATE_TRACE_POINTS trace_radar_set_region(region); - +#endif return (dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_RIU], region, RWNX_RADAR_RIU) && dfs_pattern_detector_set_domain(radar->dpd[RWNX_RADAR_FCU], @@ -1456,7 +1460,9 @@ bool rwnx_radar_set_domain(struct rwnx_radar *radar, void rwnx_radar_detection_enable(struct rwnx_radar *radar, u8 enable, u8 chain) { if (chain < RWNX_RADAR_LAST) { +#ifdef CREATE_TRACE_POINTS trace_radar_enable_detection(radar->dpd[chain]->region, enable, chain); +#endif spin_lock_bh(&radar->lock); radar->dpd[chain]->enabled = enable; spin_unlock_bh(&radar->lock); diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c index 6ccef4b9e..7c32ca035 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_rx.c @@ -626,10 +626,10 @@ static void rwnx_rx_mgmt_any(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, { struct rwnx_vif *rwnx_vif; int vif_idx = hw_rxhdr->flags_vif_idx; - +#ifdef CREATE_TRACE_POINTS trace_mgmt_rx(hw_rxhdr->phy_info.phy_prim20_freq, vif_idx, hw_rxhdr->flags_sta_idx, (struct ieee80211_mgmt *)skb->data); - +#endif if (vif_idx == RWNX_INVALID_VIF) { list_for_each_entry(rwnx_vif, &rwnx_hw->vifs, list) { if (!rwnx_vif->up) @@ -1264,13 +1264,6 @@ void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reo for (i = 0; i < 8; i++) { struct recv_msdu *req, *next; preorder_ctrl = &reord_info->preorder_ctrl[i]; - if (preorder_ctrl->enable) { - preorder_ctrl->enable = false; - if (timer_pending(&preorder_ctrl->reord_timer)) { - ret = del_timer_sync(&preorder_ctrl->reord_timer); - } - cancel_work_sync(&preorder_ctrl->reord_timer_work); - } spin_lock_irqsave(&preorder_ctrl->reord_list_lock, flags); list_for_each_entry_safe(req, next, &preorder_ctrl->reord_list, reord_pending_list) { list_del_init(&req->reord_pending_list); @@ -1280,11 +1273,13 @@ void reord_deinit_sta(struct aicwf_rx_priv *rx_priv, struct reord_ctrl_info *reo reord_rxframe_free(&rx_priv->freeq_lock, &rx_priv->rxframes_freequeue, &req->rxframe_list); } spin_unlock_irqrestore(&preorder_ctrl->reord_list_lock, flags); + if (timer_pending(&preorder_ctrl->reord_timer)) { + ret = del_timer_sync(&preorder_ctrl->reord_timer); + } + cancel_work_sync(&preorder_ctrl->reord_timer_work); } - spin_lock_bh(&rx_priv->stas_reord_lock); list_del(&reord_info->list); - spin_unlock_bh(&rx_priv->stas_reord_lock); kfree(reord_info); } @@ -1475,7 +1470,7 @@ int reord_process_unit(struct aicwf_rx_priv *rx_priv, struct sk_buff *skb, u16 s pframe->forward = forward; preorder_ctrl = pframe->preorder_ctrl; - if ((ntohs(eh->h_proto) == ETH_P_PAE) || (((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) && is_mcast)) + if ((ntohs(eh->h_proto) == ETH_P_PAE) || is_mcast) return reord_single_frame_ind(rx_priv, pframe); if ((rwnx_vif->wdev.iftype == NL80211_IFTYPE_STATION) || (rwnx_vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)) diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c index fcf7a6ad0..49f137495 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_strs.c @@ -119,8 +119,8 @@ static const char *const rwnx_mmid2str[MSG_I(MM_MAX)] = { [MSG_I(MM_GET_MAC_ADDR_CFM)] = "MM_GET_MAC_ADDR_CFM", [MSG_I(MM_GET_STA_INFO_REQ)] = "MM_GET_STA_INFO_REQ", [MSG_I(MM_GET_STA_INFO_CFM)] = "MM_GET_STA_INFO_CFM", - [MSG_I(MM_SET_TXPWR_IDX_REQ)] = "MM_SET_TXPWR_IDX_REQ", - [MSG_I(MM_SET_TXPWR_IDX_CFM)] = "MM_SET_TXPWR_IDX_CFM", + [MSG_I(MM_SET_TXPWR_IDX_LVL_REQ)] = "MM_SET_TXPWR_IDX_LVL_REQ", + [MSG_I(MM_SET_TXPWR_IDX_LVL_CFM)] = "MM_SET_TXPWR_IDX_LVL_CFM", [MSG_I(MM_SET_TXPWR_OFST_REQ)] = "MM_SET_TXPWR_OFST_REQ", [MSG_I(MM_SET_TXPWR_OFST_CFM)] = "MM_SET_TXPWR_OFST_CFM", [MSG_I(MM_SET_STACK_START_REQ)] = "MM_SET_STACK_START_REQ", @@ -224,6 +224,8 @@ static const char *const rwnx_apmid2str[MSG_I(APM_MAX)] = { [MSG_I(APM_START_CAC_CFM)] = "APM_START_CAC_CFM", [MSG_I(APM_STOP_CAC_REQ)] = "APM_STOP_CAC_REQ", [MSG_I(APM_STOP_CAC_CFM)] = "APM_STOP_CAC_CFM", + [MSG_I(APM_SET_BEACON_IE_REQ)] = "APM_SET_BEACON_IE_REQ", + [MSG_I(APM_SET_BEACON_IE_CFM)] = "APM_SET_BEACON_IE_CFM", }; static const char *const rwnx_meshid2str[MSG_I(MESH_MAX)] = { diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c index 94a0485d9..096ee2345 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_tx.c @@ -41,7 +41,9 @@ void rwnx_set_traffic_status(struct rwnx_hw *rwnx_hw, } else { bool uapsd = (ps_id != LEGACY_PS_ID); rwnx_send_me_traffic_ind(rwnx_hw, sta->sta_idx, uapsd, available); +#ifdef CREATE_TRACE_POINTS trace_ps_traffic_update(sta->sta_idx, available, uapsd); +#endif } } @@ -76,8 +78,9 @@ void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, struct rwnx_txq *txq; if (enable) { +#ifdef CREATE_TRACE_POINTS trace_ps_enable(sta); - +#endif spin_lock_bh(&rwnx_hw->tx_lock); sta->ps.active = true; sta->ps.sp_cnt[LEGACY_PS_ID] = 0; @@ -100,14 +103,15 @@ void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, spin_unlock_bh(&rwnx_hw->tx_lock); - if (sta->ps.pkt_ready[LEGACY_PS_ID]) + /*if (sta->ps.pkt_ready[LEGACY_PS_ID]) rwnx_set_traffic_status(rwnx_hw, sta, true, LEGACY_PS_ID); if (sta->ps.pkt_ready[UAPSD_ID]) - rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID); + rwnx_set_traffic_status(rwnx_hw, sta, true, UAPSD_ID);*/ } else { +#ifdef CREATE_TRACE_POINTS trace_ps_disable(sta->sta_idx); - +#endif spin_lock_bh(&rwnx_hw->tx_lock); sta->ps.active = false; @@ -125,11 +129,11 @@ void rwnx_ps_bh_enable(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, rwnx_txq_sta_start(sta, RWNX_TXQ_STOP_STA_PS, rwnx_hw); spin_unlock_bh(&rwnx_hw->tx_lock); - if (sta->ps.pkt_ready[LEGACY_PS_ID]) + /*if (sta->ps.pkt_ready[LEGACY_PS_ID]) rwnx_set_traffic_status(rwnx_hw, sta, false, LEGACY_PS_ID); if (sta->ps.pkt_ready[UAPSD_ID]) - rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID); + rwnx_set_traffic_status(rwnx_hw, sta, false, UAPSD_ID);*/ tasklet_schedule(&rwnx_hw->task); } @@ -168,9 +172,9 @@ void rwnx_ps_bh_traffic_req(struct rwnx_hw *rwnx_hw, struct rwnx_sta *sta, printk("sta %pM is not in Power Save mode", sta->mac_addr); return; } - +#ifdef CREATE_TRACE_POINTS trace_ps_traffic_req(sta, pkt_req, ps_id); - +#endif spin_lock_bh(&rwnx_hw->tx_lock); /* Fw may ask to stop a service period with PS_SP_INTERRUPTED. This only @@ -446,9 +450,9 @@ static inline void rwnx_set_more_data_flag(struct rwnx_hw *rwnx_hw, if (unlikely(sta->ps.active)) { sta->ps.pkt_ready[txq->ps_id]--; sta->ps.sp_cnt[txq->ps_id]--; - +#ifdef CREATE_TRACE_POINTS trace_ps_push(sta); - +#endif if (((txq->ps_id == UAPSD_ID) || (vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) || (sta->tdls.active)) && !sta->ps.sp_cnt[txq->ps_id]) { sw_txhdr->desc.host.flags |= TXU_CNTRL_EOSP; @@ -578,7 +582,8 @@ void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) between queue and push (because of PS) */ sw_txhdr->hw_queue = hw_queue; - sw_txhdr->desc.host.packet_addr = hw_queue; //use packet_addr field for hw_txq + //sw_txhdr->desc.host.packet_addr = hw_queue; //use packet_addr field for hw_txq + sw_txhdr->desc.host.ac = hw_queue; //use ac field for hw_txq #ifdef CONFIG_RWNX_MUMIMO_TX /* MU group is only selected during hwq processing */ sw_txhdr->desc.host.mumimo_info = txq->mumimo_info; @@ -589,8 +594,9 @@ void rwnx_tx_push(struct rwnx_hw *rwnx_hw, struct rwnx_txhdr *txhdr, int flags) /* only for AP mode */ rwnx_set_more_data_flag(rwnx_hw, sw_txhdr); } - +#ifdef CREATE_TRACE_POINTS trace_push_desc(skb, sw_txhdr, flags); +#endif #if 0 txq->credits--; #endif @@ -674,12 +680,6 @@ static void rwnx_tx_retry(struct rwnx_hw *rwnx_hw, struct sk_buff *skb, if (!sw_retry) { /* update sw desc */ - sw_txhdr->desc.host.sn = cfm->sn; - sw_txhdr->desc.host.pn[0] = cfm->pn[0]; - sw_txhdr->desc.host.pn[1] = cfm->pn[1]; - sw_txhdr->desc.host.pn[2] = cfm->pn[2]; - sw_txhdr->desc.host.pn[3] = cfm->pn[3]; - sw_txhdr->desc.host.timestamp = cfm->timestamp; sw_txhdr->desc.host.flags |= TXU_CNTRL_RETRY; #ifdef CONFIG_RWNX_AMSDUS_TX @@ -1094,7 +1094,7 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) (memcmp(desc->host.eth_dest_addr.array, rwnx_vif->sta.tdls_sta->mac_addr, ETH_ALEN) == 0)) { desc->host.flags |= TXU_CNTRL_TDLS; rwnx_vif->sta.tdls_sta->tdls.last_tid = desc->host.tid; - rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; + //rwnx_vif->sta.tdls_sta->tdls.last_sn = desc->host.sn; } if (rwnx_vif->wdev.iftype == NL80211_IFTYPE_MESH_POINT) { @@ -1121,12 +1121,6 @@ netdev_tx_t rwnx_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Fill-in TX descriptor */ frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr) + hdr_pads;// + sizeof(*eth); -#ifdef CONFIG_RWNX_SPLIT_TX_BUF - desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; - desc->host.packet_cnt = 1; -#else - desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; -#endif desc->host.status_desc_addr = sw_txhdr->dma_addr; spin_lock_bh(&rwnx_hw->tx_lock); @@ -1311,12 +1305,6 @@ int rwnx_start_mgmt_xmit(struct rwnx_vif *vif, struct rwnx_sta *sta, } frame_oft = sizeof(struct rwnx_txhdr) - offsetof(struct rwnx_txhdr, hw_hdr); -#ifdef CONFIG_RWNX_SPLIT_TX_BUF - desc->host.packet_addr[0] = sw_txhdr->dma_addr + frame_oft; - desc->host.packet_cnt = 1; -#else - desc->host.packet_addr = sw_txhdr->dma_addr + frame_oft; -#endif desc->host.status_desc_addr = sw_txhdr->dma_addr; //---------------------------------------------------------------------- @@ -1359,6 +1347,19 @@ int rwnx_txdatacfm(void *pthis, void *host_id) return -1; } +#if defined(AICWF_USB_SUPPORT) + if (rwnx_hw->usbdev->state == USB_DOWN_ST) +#elif defined(AICWF_SDIO_SUPPORT) + if (rwnx_hw->sdiodev->bus_if->state == BUS_DOWN_ST) +#endif + { + headroom = sw_txhdr->headroom; + kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); + skb_pull(skb, headroom); + consume_skb(skb); + return 0; + } + txq = sw_txhdr->txq; /* don't use txq->hwq as it may have changed between push and confirm */ hwq = &rwnx_hw->hwq[sw_txhdr->hw_queue]; @@ -1369,11 +1370,11 @@ int rwnx_txdatacfm(void *pthis, void *host_id) printk("done=%d retry_required=%d sw_retry_required=%d acknowledged=%d\n", rwnx_txst.tx_done, rwnx_txst.retry_required, rwnx_txst.sw_retry_required, rwnx_txst.acknowledged); - +#ifdef CREATE_TRACE_POINTS trace_mgmt_cfm(sw_txhdr->rwnx_vif->vif_index, (sw_txhdr->rwnx_sta) ? sw_txhdr->rwnx_sta->sta_idx : 0xFF, rwnx_txst.acknowledged); - +#endif /* Confirm transmission to CFG80211 */ cfg80211_mgmt_tx_status(&sw_txhdr->rwnx_vif->wdev, (unsigned long)skb, @@ -1393,9 +1394,9 @@ int rwnx_txdatacfm(void *pthis, void *host_id) rwnx_tx_retry(rwnx_hw, skb, txhdr, sw_retry); return 0; } - +#ifdef CREATE_TRACE_POINTS trace_skb_confirm(skb, txq, hwq, &txhdr->hw_hdr.cfm); - +#endif /* STA may have disconnect (and txq stopped) when buffers were stored in fw. In this case do nothing when they're returned */ if (txq->idx != TXQ_INACTIVE) { @@ -1469,7 +1470,9 @@ void rwnx_txq_credit_update(struct rwnx_hw *rwnx_hw, int sta_idx, u8 tid, if (txq->idx != TXQ_INACTIVE) { //txq->credits += update; +#ifdef CREATE_TRACE_POINTS trace_credit_update(txq, update); +#endif if (txq->credits <= 0) rwnx_txq_stop(txq, RWNX_TXQ_STOP_FULL); else diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c index 8fdf86e80..8a43f8a8e 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c @@ -137,15 +137,15 @@ void rwnx_txq_flush(struct rwnx_hw *rwnx_hw, struct rwnx_txq *txq) if (sw_txhdr->desc.host.packet_cnt > 1) { struct rwnx_amsdu_txhdr *amsdu_txhdr; list_for_each_entry(amsdu_txhdr, &sw_txhdr->amsdu.hdrs, list) { - dma_unmap_single(rwnx_hw->dev, amsdu_txhdr->dma_addr, - amsdu_txhdr->map_len, DMA_TO_DEVICE); + //dma_unmap_single(rwnx_hw->dev, amsdu_txhdr->dma_addr, + // amsdu_txhdr->map_len, DMA_TO_DEVICE); dev_kfree_skb_any(amsdu_txhdr->skb); } } #endif kmem_cache_free(rwnx_hw->sw_txhdr_cache, sw_txhdr); - dma_unmap_single(rwnx_hw->dev, sw_txhdr->dma_addr, sw_txhdr->map_len, - DMA_TO_DEVICE); + //dma_unmap_single(rwnx_hw->dev, sw_txhdr->dma_addr, sw_txhdr->map_len, + // DMA_TO_DEVICE); #ifdef CONFIG_RWNX_FULLMAC dev_kfree_skb_any(skb); @@ -384,7 +384,9 @@ void rwnx_txq_tdls_vif_deinit(struct rwnx_vif *rwnx_vif) void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq) { if (!(txq->status & RWNX_TXQ_IN_HWQ_LIST)) { +#ifdef CREATE_TRACE_POINTS trace_txq_add_to_hw(txq); +#endif txq->status |= RWNX_TXQ_IN_HWQ_LIST; list_add_tail(&txq->sched_list, &txq->hwq->list); txq->hwq->need_processing = true; @@ -402,7 +404,9 @@ void rwnx_txq_add_to_hw_list(struct rwnx_txq *txq) void rwnx_txq_del_from_hw_list(struct rwnx_txq *txq) { if (txq->status & RWNX_TXQ_IN_HWQ_LIST) { +#ifdef CREATE_TRACE_POINTS trace_txq_del_from_hw(txq); +#endif txq->status &= ~RWNX_TXQ_IN_HWQ_LIST; list_del(&txq->sched_list); } @@ -440,7 +444,9 @@ void rwnx_txq_start(struct rwnx_txq *txq, u16 reason) { BUG_ON(txq == NULL); if (txq->idx != TXQ_INACTIVE && (txq->status & reason)) { +#ifdef CREATE_TRACE_POINTS trace_txq_start(txq, reason); +#endif txq->status &= ~reason; if (!rwnx_txq_is_stopped(txq) && rwnx_txq_skb_ready(txq)) rwnx_txq_add_to_hw_list(txq); @@ -460,7 +466,9 @@ void rwnx_txq_stop(struct rwnx_txq *txq, u16 reason) { BUG_ON(txq == NULL); if (txq->idx != TXQ_INACTIVE) { +#ifdef CREATE_TRACE_POINTS trace_txq_stop(txq, reason); +#endif txq->status |= reason; rwnx_txq_del_from_hw_list(txq); } @@ -492,8 +500,9 @@ void rwnx_txq_sta_start(struct rwnx_sta *rwnx_sta, u16 reason { struct rwnx_txq *txq; int tid; - +#ifdef CREATE_TRACE_POINTS trace_txq_sta_start(rwnx_sta->sta_idx); +#endif foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { rwnx_txq_start(txq, reason); @@ -528,8 +537,9 @@ void rwnx_txq_sta_stop(struct rwnx_sta *rwnx_sta, u16 reason if (!rwnx_sta) return; - +#ifdef CREATE_TRACE_POINTS trace_txq_sta_stop(rwnx_sta->sta_idx); +#endif foreach_sta_txq(rwnx_sta, txq, tid, rwnx_hw) { rwnx_txq_stop(txq, reason); } @@ -539,7 +549,9 @@ void rwnx_txq_sta_stop(struct rwnx_sta *rwnx_sta, u16 reason void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, struct rwnx_hw *rwnx_hw) { +#ifdef CREATE_TRACE_POINTS trace_txq_vif_start(rwnx_vif->vif_index); +#endif spin_lock_bh(&rwnx_hw->tx_lock); if (rwnx_vif->sta.tdls_sta) @@ -553,7 +565,9 @@ void rwnx_txq_tdls_sta_start(struct rwnx_vif *rwnx_vif, u16 reason, void rwnx_txq_tdls_sta_stop(struct rwnx_vif *rwnx_vif, u16 reason, struct rwnx_hw *rwnx_hw) { +#ifdef CREATE_TRACE_POINTS trace_txq_vif_stop(rwnx_vif->vif_index); +#endif spin_lock_bh(&rwnx_hw->tx_lock); @@ -613,9 +627,9 @@ void rwnx_txq_vif_start(struct rwnx_vif *rwnx_vif, u16 reason, struct rwnx_hw *rwnx_hw) { struct rwnx_txq *txq; - +#ifdef CREATE_TRACE_POINTS trace_txq_vif_start(rwnx_vif->vif_index); - +#endif spin_lock_bh(&rwnx_hw->tx_lock); #ifdef CONFIG_RWNX_FULLMAC @@ -657,8 +671,9 @@ void rwnx_txq_vif_stop(struct rwnx_vif *rwnx_vif, u16 reason, struct rwnx_hw *rwnx_hw) { struct rwnx_txq *txq; - +#ifdef CREATE_TRACE_POINTS trace_txq_vif_stop(rwnx_vif->vif_index); +#endif spin_lock_bh(&rwnx_hw->tx_lock); #ifdef CONFIG_RWNX_FULLMAC @@ -758,8 +773,9 @@ int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, #ifdef CONFIG_RWNX_FULLMAC if (unlikely(txq->sta && txq->sta->ps.active)) { txq->sta->ps.pkt_ready[txq->ps_id]++; +#ifdef CREATE_TRACE_POINTS trace_ps_queue(txq->sta); - +#endif if (txq->sta->ps.pkt_ready[txq->ps_id] == 1) { rwnx_set_traffic_status(rwnx_hw, txq->sta, true, txq->ps_id); } @@ -778,9 +794,9 @@ int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, txq->last_retry_skb = skb; txq->nb_retry++; } - +#ifdef CREATE_TRACE_POINTS trace_txq_queue_skb(skb, txq, retry); - +#endif /* Flowctrl corresponding netdev queue if needed */ #ifdef CONFIG_RWNX_FULLMAC /* If too many buffer are queued for this TXQ stop netdev queue */ @@ -788,7 +804,9 @@ int rwnx_txq_queue_skb(struct sk_buff *skb, struct rwnx_txq *txq, (skb_queue_len(&txq->sk_list) > RWNX_NDEV_FLOW_CTRL_STOP)) { txq->status |= RWNX_TXQ_NDEV_FLOW_CTRL; netif_stop_subqueue(txq->ndev, txq->ndev_idx); +#ifdef CREATE_TRACE_POINTS trace_txq_flowctrl_stop(txq); +#endif } #else /* ! CONFIG_RWNX_FULLMAC */ @@ -1150,9 +1168,9 @@ void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) struct rwnx_txq *txq, *next; int user, credit_map = 0; bool mu_enable; - +#ifdef CREATE_TRACE_POINTS trace_process_hw_queue(hwq); - +#endif hwq->need_processing = false; mu_enable = rwnx_txq_take_mu_lock(rwnx_hw); @@ -1164,10 +1182,15 @@ void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) struct sk_buff_head sk_list_push; struct sk_buff *skb; bool txq_empty; - +#ifdef CREATE_TRACE_POINTS trace_process_txq(txq); +#endif /* sanity check for debug */ BUG_ON(!(txq->status & RWNX_TXQ_IN_HWQ_LIST)); + if (txq->idx == TXQ_INACTIVE) { + printk("%s txq->idx == TXQ_INACTIVE \r\n", __func__); + continue; + } BUG_ON(txq->idx == TXQ_INACTIVE); BUG_ON(txq->credits <= 0); BUG_ON(!rwnx_txq_skb_ready(txq)); @@ -1213,10 +1236,12 @@ void rwnx_hwq_process(struct rwnx_hw *rwnx_hw, struct rwnx_hwq *hwq) /* restart netdev queue if number of queued buffer is below threshold */ if (unlikely(txq->status & RWNX_TXQ_NDEV_FLOW_CTRL) && - skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART) { + (skb_queue_len(&txq->sk_list) < RWNX_NDEV_FLOW_CTRL_RESTART)) { txq->status &= ~RWNX_TXQ_NDEV_FLOW_CTRL; netif_wake_subqueue(txq->ndev, txq->ndev_idx); +#ifdef CREATE_TRACE_POINTS trace_txq_flowctrl_restart(txq); +#endif } #endif /* CONFIG_RWNX_FULLMAC */ } diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h index 639ab9bbb..2b10dac46 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version.h @@ -6,6 +6,7 @@ static inline void rwnx_print_version(void) { printk(RWNX_VERS_BANNER"\n"); + printk("Driver Release Tag: %s\n", DRV_RELEASE_TAG); } #endif /* _RWNX_VERSION_H_ */ diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h index ec36104ce..4f4cae38e 100644 --- a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_version_gen.h @@ -1,3 +1,15 @@ -#define RWNX_VERS_REV "241c091M (master)" -#define RWNX_VERS_MOD "20211129-6.4.3.0" +#define RWNX_VERS_REV "241c091M (master)" +#define DRV_RELEASE_DATE "20221108" +#define DRV_PATCH_LEVEL "004" +#define RWNX_VERS_MOD DRV_RELEASE_DATE "-" DRV_PATCH_LEVEL "-6.4.3.0" #define RWNX_VERS_BANNER "rwnx " RWNX_VERS_MOD " - - " RWNX_VERS_REV + +#if defined(AICWF_SDIO_SUPPORT) +#define DRV_TYPE_NAME "sdio" +#elif defined(AICWF_USB_SUPPORT) +#define DRV_TYPE_NAME "usb" +#else +#define DRV_TYPE_NAME "unknow" +#endif + +#define DRV_RELEASE_TAG "aic-rwnx-" DRV_TYPE_NAME "-" DRV_RELEASE_DATE "-" DRV_PATCH_LEVEL diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c new file mode 100644 index 000000000..6e03941ef --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include "rwnx_defs.h" +#include "rwnx_wakelock.h" + +struct wakeup_source *rwnx_wakeup_init(const char *name) +{ + struct wakeup_source *ws; + ws = wakeup_source_create(name); + wakeup_source_add(ws); + return ws; +} + +void rwnx_wakeup_deinit(struct wakeup_source *ws) +{ + if (ws && ws->active) + __pm_relax(ws); + wakeup_source_remove(ws); + wakeup_source_destroy(ws); +} + +struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0) + return wakeup_source_register(dev, name); +#else + return wakeup_source_register(name); +#endif +} + +void rwnx_wakeup_unregister(struct wakeup_source *ws) +{ + if (ws && ws->active) + __pm_relax(ws); + wakeup_source_unregister(ws); +} + +void rwnx_wakeup_lock(struct wakeup_source *ws) +{ + __pm_stay_awake(ws); +} + +void rwnx_wakeup_unlock(struct wakeup_source *ws) +{ + __pm_relax(ws); +} + +void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec) +{ + __pm_wakeup_event(ws, msec); +} + +void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw) +{ + rwnx_hw->ws_tx = rwnx_wakeup_init("rwnx_tx_wakelock"); + rwnx_hw->ws_rx = rwnx_wakeup_init("rwnx_rx_wakelock"); + rwnx_hw->ws_pwrctrl = rwnx_wakeup_init("rwnx_pwrcrl_wakelock"); +} + +void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw) +{ + rwnx_wakeup_deinit(rwnx_hw->ws_tx); + rwnx_wakeup_deinit(rwnx_hw->ws_rx); + rwnx_wakeup_deinit(rwnx_hw->ws_pwrctrl); +} + diff --git a/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h new file mode 100644 index 000000000..9c9655a46 --- /dev/null +++ b/drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_wakelock.h @@ -0,0 +1,21 @@ +#ifndef __RWNX_WAKELOCK_H +#define __RWNX_WAKELOCK_H + +#include +#include +#include + +struct wakeup_source *rwnx_wakeup_init(const char *name); +void rwnx_wakeup_deinit(struct wakeup_source *ws); + +struct wakeup_source *rwnx_wakeup_register(struct device *dev, const char *name); +void rwnx_wakeup_unregister(struct wakeup_source *ws); + +void rwnx_wakeup_lock(struct wakeup_source *ws); +void rwnx_wakeup_unlock(struct wakeup_source *ws); +void rwnx_wakeup_lock_timeout(struct wakeup_source *ws, unsigned int msec); + +void aicwf_wakeup_lock_init(struct rwnx_hw *rwnx_hw); +void aicwf_wakeup_lock_deinit(struct rwnx_hw *rwnx_hw); + +#endif