mirror of
https://github.com/shenmintao/aic8800d80.git
synced 2026-11-10 16:49:17 +00:00
fix(legacy-mcu1): support AIC8800D80 product 0x8820 and unstick cfg80211 connect
Two independent fixes found on a UGREEN a69c:5723 adapter (chip_id=7, chip_mcu_id=1, product_id=0x8820, issue #118): 1) The firmware boots and answers every configuration request, but never confirms MM_START_REQ, so the MAC never starts and wlan0 stays unusable (the symptom reported in #79). The Windows loader (aicloadfw.sys) handles product 0x8820 differently: it writes 0x40500010 = 0x2, masked-writes 0x40506024 (mask 0xff) = 0xdf, and uploads only the FMAC firmware without the adid/patch/patch-table/patch-config layer. Mirror that behaviour, gated on product_id == 0x8820 so that other D80 revisions (for example the a69c:572f from #58) keep uploading the patch layer and stay unaffected. The existing MCU1 cache fix (0x40100020 |= 0x1) is kept for both. 2) rwnx_cfg80211_connect() returned 0 when the state machine was already CONNECTING/DISCONNECTING, without ever reporting a result. cfg80211 then keeps wdev->conn allocated and rejects every later NL80211_CMD_CONNECT with -EALREADY, so the driver's connect op is never called again and NetworkManager loops on the password prompt ("associating -> disconnected" every 5 s) with no driver activity at all. Report the failure instead: reset the state and return -EBUSY. Tested on Ubuntu 26.04 / 7.0.0-14-generic: 5 GHz association, DHCP, IPv6 SLAAC and internet traffic all work, and it survives reboot and USB re-plug. Full logs and analysis: #118
This commit is contained in:
1 parent
a9683a4560
commit
73e0a57128
3 files changed
+41
-3
No files matched your search
@@ -3206,7 +3206,15 @@ static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||||||
if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING||
|
if((int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_DISCONNECTING||
|
||||||
(int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING) {
|
(int)atomic_read(&rwnx_vif->drv_conn_state) == (int)RWNX_DRV_STATUS_CONNECTING) {
|
||||||
AICWFDBG(LOGERROR, "%s driver is disconnecting or connecting ,return it \r\n", __func__);
|
AICWFDBG(LOGERROR, "%s driver is disconnecting or connecting ,return it \r\n", __func__);
|
||||||
return 0;
|
/*
|
||||||
|
* local fix: returning 0 here leaves cfg80211 waiting for a connect
|
||||||
|
* result that never comes, so every later connect fails with -EALREADY
|
||||||
|
* (NetworkManager then loops asking for the password forever).
|
||||||
|
* Report the failure instead so cfg80211 drops its pending request.
|
||||||
|
*/
|
||||||
|
rwnx_set_conn_state(rwnx_vif, &rwnx_vif->drv_conn_state,
|
||||||
|
(int)RWNX_DRV_STATUS_DISCONNECTED);
|
||||||
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ void rwnx_release_firmware_common(u32** buffer);
|
|||||||
extern int testmode;
|
extern int testmode;
|
||||||
extern u8 chip_id;
|
extern u8 chip_id;
|
||||||
extern u8 chip_mcu_id;
|
extern u8 chip_mcu_id;
|
||||||
|
extern u8 aic8800d80_m80_variant;
|
||||||
|
|
||||||
typedef u32 (*array2_tbl_t)[2];
|
typedef u32 (*array2_tbl_t)[2];
|
||||||
|
|
||||||
@@ -233,6 +234,7 @@ int rwnx_plat_userconfig_load_8800d80(struct aic_usb_dev *usb_dev){
|
|||||||
int system_config_8800d80(struct aic_usb_dev *usb_dev){
|
int system_config_8800d80(struct aic_usb_dev *usb_dev){
|
||||||
int syscfg_num;
|
int syscfg_num;
|
||||||
int ret, cnt;
|
int ret, cnt;
|
||||||
|
u32 product_id;
|
||||||
const u32 mem_addr = 0x40500000;
|
const u32 mem_addr = 0x40500000;
|
||||||
const u32 cache_mem_addr = 0x40100020;
|
const u32 cache_mem_addr = 0x40100020;
|
||||||
struct dbg_mem_read_cfm rd_mem_addr_cfm;
|
struct dbg_mem_read_cfm rd_mem_addr_cfm;
|
||||||
@@ -245,7 +247,9 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
|
|||||||
chip_mcu_id = 1;
|
chip_mcu_id = 1;
|
||||||
}
|
}
|
||||||
chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16);
|
chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16);
|
||||||
printk("chip_id=%x, chip_mcu_id = %d\n", chip_id, chip_mcu_id);
|
product_id = rd_mem_addr_cfm.memdata & 0xFFFF;
|
||||||
|
printk("chip_id=%x, chip_mcu_id = %d, product_id=0x%04x\n",
|
||||||
|
chip_id, chip_mcu_id, product_id);
|
||||||
printk("AIC8800D80 legacy: using Radxa SDK V3 loader profile\n");
|
printk("AIC8800D80 legacy: using Radxa SDK V3 loader profile\n");
|
||||||
if (chip_mcu_id == 1) {
|
if (chip_mcu_id == 1) {
|
||||||
ret = rwnx_send_dbg_mem_read_req(usb_dev, cache_mem_addr, &rd_mem_addr_cfm);
|
ret = rwnx_send_dbg_mem_read_req(usb_dev, cache_mem_addr, &rd_mem_addr_cfm);
|
||||||
@@ -261,6 +265,27 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
|
|||||||
}
|
}
|
||||||
printk("AIC8800D80 MCU1: enabled Bluetooth cache fix\n");
|
printk("AIC8800D80 MCU1: enabled Bluetooth cache fix\n");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* product 0x8820: the Windows loader (aicloadfw.sys) performs two extra
|
||||||
|
* system-configuration writes and uploads only the FMAC firmware, without
|
||||||
|
* the adid/patch/patch-table/patch-config layer. Upstream issue #79 and
|
||||||
|
* #118: without this the firmware boots and answers configuration
|
||||||
|
* requests, but never confirms MM_START_REQ, so the MAC never starts.
|
||||||
|
*/
|
||||||
|
if (product_id == 0x8820) {
|
||||||
|
ret = rwnx_send_dbg_mem_write_req(usb_dev, 0x40500010, 0x2);
|
||||||
|
if (ret) {
|
||||||
|
printk("0x8820: 40500010 write fail: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = rwnx_send_dbg_mem_mask_write_req(usb_dev, 0x40506024, 0xff, 0xdf);
|
||||||
|
if (ret) {
|
||||||
|
printk("0x8820: 40506024 mask write fail: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
aic8800d80_m80_variant = 1;
|
||||||
|
printk("AIC8800D80 0x8820: applied vendor syscfg writes, patch layer will be skipped\n");
|
||||||
|
}
|
||||||
#if 1
|
#if 1
|
||||||
syscfg_num = sizeof(syscfg_tbl_8800d80) / sizeof(u32) / 2;
|
syscfg_num = sizeof(syscfg_tbl_8800d80) / sizeof(u32) / 2;
|
||||||
for (cnt = 0; cnt < syscfg_num; cnt++) {
|
for (cnt = 0; cnt < syscfg_num; cnt++) {
|
||||||
@@ -364,6 +389,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
|
|||||||
if(testmode == FW_NORMAL_MODE){
|
if(testmode == FW_NORMAL_MODE){
|
||||||
|
|
||||||
if (chip_id != CHIP_REV_U01){
|
if (chip_id != CHIP_REV_U01){
|
||||||
|
if (!aic8800d80_m80_variant) {
|
||||||
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
|
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -378,6 +404,9 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
|
|||||||
if (aicbt_patch_table_load(usb_dev, head)) {
|
if (aicbt_patch_table_load(usb_dev, head)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
printk("AIC8800D80 0x8820: skipping adid/patch/patch-table upload (vendor loader behaviour)\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (IS_CHIP_ID_H()){
|
if (IS_CHIP_ID_H()){
|
||||||
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_H_U02))
|
if(rwnx_plat_bin_fw_upload_android(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, FW_BASE_NAME_8800D80_H_U02))
|
||||||
@@ -393,7 +422,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
|
|||||||
if (rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, 0x1e0000))
|
if (rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, 0x1e0000))
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
if (aicwf_patch_config_8800d80(usb_dev)) {
|
if (!aic8800d80_m80_variant && aicwf_patch_config_8800d80(usb_dev)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, HOST_START_APP_AUTO)) {
|
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, HOST_START_APP_AUTO)) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ extern uint32_t gpio_dft_lvl;//0:defalut pull down, 1:default pull up
|
|||||||
u8 chip_id = 0;
|
u8 chip_id = 0;
|
||||||
u8 chip_sub_id = 0;
|
u8 chip_sub_id = 0;
|
||||||
u8 chip_mcu_id = 0;
|
u8 chip_mcu_id = 0;
|
||||||
|
u8 aic8800d80_m80_variant = 0; /* product_id == 0x8820 (upstream issue #79) */
|
||||||
int fw_loaded = 0;
|
int fw_loaded = 0;
|
||||||
|
|
||||||
void aicwf_usb_tx_flowctrl(struct aic_usb_dev *usb_dev, bool state)
|
void aicwf_usb_tx_flowctrl(struct aic_usb_dev *usb_dev, bool state)
|
||||||
|
|||||||
Reference in new issue
Block a user