fix: isolate the 0x8820 loader profile per USB device

Derive the FMAC-only profile from each device readback instead of a module-global latch. A regular D80 must still load its patches after another adapter reports product 0x8820. Reject a busy connect with EBUSY without resetting the state of an operation already in flight.

Extracted-function tests cover alternating devices, reprobe, cache setup, configuration errors and unchanged busy states. All three modules build against Linux 6.17 headers. Hardware retest of this revision and Bluetooth remain pending.
This commit is contained in:
Shen Mintao committed 2026-10-28 10:17:39 +08:00
1 parent 73e0a57128
commit 35d815c0ae
6 files changed
+159 -10

No files matched your search

+2 -4
View File
@@ -3207,13 +3207,11 @@ static int rwnx_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
(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__);
/*
* local fix: returning 0 here leaves cfg80211 waiting for a connect
* 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.
* Reject the new request without changing an in-flight operation's state.
*/
rwnx_set_conn_state(rwnx_vif, &rwnx_vif->drv_conn_state,
(int)RWNX_DRV_STATUS_DISCONNECTED);
return -EBUSY;
}
#endif
@@ -18,7 +18,6 @@ void rwnx_release_firmware_common(u32** buffer);
extern int testmode;
extern u8 chip_id;
extern u8 chip_mcu_id;
extern u8 aic8800d80_m80_variant;
typedef u32 (*array2_tbl_t)[2];
@@ -248,6 +247,7 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
}
chip_id = (u8)(rd_mem_addr_cfm.memdata >> 16);
product_id = rd_mem_addr_cfm.memdata & 0xFFFF;
usb_dev->d80_m80_variant = product_id == 0x8820;
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");
@@ -272,7 +272,7 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
* #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) {
if (usb_dev->d80_m80_variant) {
ret = rwnx_send_dbg_mem_write_req(usb_dev, 0x40500010, 0x2);
if (ret) {
printk("0x8820: 40500010 write fail: %d\n", ret);
@@ -283,7 +283,6 @@ int system_config_8800d80(struct aic_usb_dev *usb_dev){
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
@@ -389,7 +388,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
if(testmode == FW_NORMAL_MODE){
if (chip_id != CHIP_REV_U01){
if (!aic8800d80_m80_variant) {
if (!usb_dev->d80_m80_variant) {
if(rwnx_plat_bin_fw_upload_android(usb_dev, patch_info.addr_adid, FW_ADID_BASE_NAME_8800D80_U02)) {
return -1;
}
@@ -422,7 +421,7 @@ int aicfw_download_fw_8800d80(struct aic_usb_dev *usb_dev)
if (rwnx_send_dbg_mem_write_req(usb_dev, 0x40500048, 0x1e0000))
return -1;
#endif
if (!aic8800d80_m80_variant && aicwf_patch_config_8800d80(usb_dev)) {
if (!usb_dev->d80_m80_variant && aicwf_patch_config_8800d80(usb_dev)) {
return -1;
}
if (rwnx_send_dbg_start_app_req(usb_dev, RAM_FMAC_FW_ADDR_8800D80_U02, HOST_START_APP_AUTO)) {
-1
View File
@@ -39,7 +39,6 @@ extern uint32_t gpio_dft_lvl;//0:defalut pull down, 1:default pull up
u8 chip_id = 0;
u8 chip_sub_id = 0;
u8 chip_mcu_id = 0;
u8 aic8800d80_m80_variant = 0; /* product_id == 0x8820 (upstream issue #79) */
int fw_loaded = 0;
void aicwf_usb_tx_flowctrl(struct aic_usb_dev *usb_dev, bool state)
+1
View File
@@ -223,6 +223,7 @@ struct aic_usb_dev {
#endif
u16 chipid;
bool d80_m80_variant; /* D80 product 0x8820: FMAC-only loader sequence */
bool tbusy;
bool app_cmp;
u32 fw_version_uint;