Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: r8188eu: Make firmware buffer persistent

The present code reloads the firmware file from the disk every time the interface
re-inits. Change to hold the firmware in memory, and only download to the
device.

Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Stas Sergeev and committed by
Greg Kroah-Hartman
60800abd f87028f4

+56 -49
+46 -38
drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
··· 584 584 585 585 #define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0) 586 586 587 + static int load_firmware(struct rt_firmware *pFirmware, struct device *device) 588 + { 589 + int rtstatus = _SUCCESS; 590 + const struct firmware *fw; 591 + const char fw_name[] = "rtlwifi/rtl8188eufw.bin"; 592 + 593 + if (request_firmware(&fw, fw_name, device)) { 594 + rtstatus = _FAIL; 595 + goto exit; 596 + } 597 + if (!fw) { 598 + pr_err("Firmware %s not available\n", fw_name); 599 + rtstatus = _FAIL; 600 + goto exit; 601 + } 602 + if (fw->size > FW_8188E_SIZE) { 603 + rtstatus = _FAIL; 604 + RT_TRACE(_module_hal_init_c_, _drv_err_, 605 + ("Firmware size exceed 0x%X. Check it.\n", 606 + FW_8188E_SIZE)); 607 + goto exit; 608 + } 609 + 610 + pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL); 611 + if (!pFirmware->szFwBuffer) { 612 + rtstatus = _FAIL; 613 + goto exit; 614 + } 615 + memcpy(pFirmware->szFwBuffer, fw->data, fw->size); 616 + pFirmware->ulFwLength = fw->size; 617 + release_firmware(fw); 618 + 619 + DBG_88E_LEVEL(_drv_info_, 620 + "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, 621 + pFirmware->ulFwLength); 622 + exit: 623 + return rtstatus; 624 + } 625 + 587 626 s32 rtl8188e_FirmwareDownload(struct adapter *padapter) 588 627 { 589 628 s32 rtStatus = _SUCCESS; ··· 631 592 struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); 632 593 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 633 594 struct device *device = dvobj_to_dev(dvobj); 634 - struct rt_firmware *pFirmware = NULL; 635 - const struct firmware *fw; 636 595 struct rt_firmware_hdr *pFwHdr = NULL; 637 596 u8 *pFirmwareBuf; 638 597 u32 FirmwareLen; 639 - char fw_name[] = "rtlwifi/rtl8188eufw.bin"; 640 598 static int log_version; 641 599 642 600 RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__)); 643 - pFirmware = (struct rt_firmware *)rtw_zmalloc(sizeof(struct rt_firmware)); 644 - if (!pFirmware) { 645 - rtStatus = _FAIL; 601 + if (!dvobj->firmware.szFwBuffer) 602 + rtStatus = load_firmware(&dvobj->firmware, device); 603 + if (rtStatus == _FAIL) { 604 + dvobj->firmware.szFwBuffer = NULL; 646 605 goto Exit; 647 606 } 648 - 649 - if (request_firmware(&fw, fw_name, device)) { 650 - rtStatus = _FAIL; 651 - goto Exit; 652 - } 653 - if (!fw) { 654 - pr_err("Firmware %s not available\n", fw_name); 655 - rtStatus = _FAIL; 656 - goto Exit; 657 - } 658 - if (fw->size > FW_8188E_SIZE) { 659 - rtStatus = _FAIL; 660 - RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE)); 661 - goto Exit; 662 - } 663 - 664 - pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL); 665 - if (!pFirmware->szFwBuffer) { 666 - rtStatus = _FAIL; 667 - goto Exit; 668 - } 669 - memcpy(pFirmware->szFwBuffer, fw->data, fw->size); 670 - pFirmware->ulFwLength = fw->size; 671 - pFirmwareBuf = pFirmware->szFwBuffer; 672 - FirmwareLen = pFirmware->ulFwLength; 673 - release_firmware(fw); 674 - 675 - DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, FirmwareLen); 607 + pFirmwareBuf = dvobj->firmware.szFwBuffer; 608 + FirmwareLen = dvobj->firmware.ulFwLength; 676 609 677 610 /* To Check Fw header. Added by tynli. 2009.12.04. */ 678 - pFwHdr = (struct rt_firmware_hdr *)pFirmware->szFwBuffer; 611 + pFwHdr = (struct rt_firmware_hdr *)dvobj->firmware.szFwBuffer; 679 612 680 613 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version); 681 614 pHalData->FirmwareSubVersion = pFwHdr->Subversion; ··· 699 688 goto Exit; 700 689 } 701 690 RT_TRACE(_module_hal_init_c_, _drv_info_, ("Firmware is ready to run!\n")); 702 - kfree(pFirmware->szFwBuffer); 703 691 Exit: 704 - 705 - kfree(pFirmware); 706 692 return rtStatus; 707 693 } 708 694
+6
drivers/staging/rtl8188eu/include/drv_types.h
··· 159 159 160 160 #define MAX_CONTINUAL_URB_ERR 4 161 161 162 + struct rt_firmware { 163 + u8 *szFwBuffer; 164 + u32 ulFwLength; 165 + }; 166 + 162 167 struct dvobj_priv { 163 168 struct adapter *if1; 164 169 struct adapter *if2; 170 + struct rt_firmware firmware; 165 171 166 172 /* For 92D, DMDP have 2 interface. */ 167 173 u8 InterfaceNumber;
-11
drivers/staging/rtl8188eu/include/rtl8188e_hal.h
··· 76 76 (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x2300 || \ 77 77 (le16_to_cpu(_pFwHdr->Signature)&0xFFF0) == 0x88E0) 78 78 79 - enum firmware_source { 80 - FW_SOURCE_IMG_FILE = 0, 81 - FW_SOURCE_HEADER_FILE = 1, /* from header file */ 82 - }; 83 - 84 - struct rt_firmware { 85 - enum firmware_source eFWSource; 86 - u8 *szFwBuffer; 87 - u32 ulFwLength; 88 - }; 89 - 90 79 /* This structure must be careful with byte-ordering */ 91 80 92 81 struct rt_firmware_hdr {
+4
drivers/staging/rtl8188eu/os_dep/os_intfs.c
··· 1204 1204 int netdev_close(struct net_device *pnetdev) 1205 1205 { 1206 1206 struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); 1207 + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); 1207 1208 1208 1209 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - drv_close\n")); 1209 1210 ··· 1242 1241 #ifdef CONFIG_88EU_P2P 1243 1242 rtw_p2p_enable(padapter, P2P_ROLE_DISABLE); 1244 1243 #endif /* CONFIG_88EU_P2P */ 1244 + 1245 + kfree(dvobj->firmware.szFwBuffer); 1246 + dvobj->firmware.szFwBuffer = NULL; 1245 1247 1246 1248 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n")); 1247 1249 DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup);