#define FWBUFF_ALIGN_SZ 512
#define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/
-static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
- const u8 **ppmappedfw)
+static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
{
+ struct _adapter *padapter = context;
+
+ complete(&padapter->rtl8712_fw_ready);
+ if (!firmware) {
+ struct usb_device *udev = padapter->dvobjpriv.pusbdev;
+ struct usb_interface *pusb_intf = padapter->pusb_intf;
+ printk(KERN_ERR "r8712u: Firmware request failed\n");
+ padapter->fw_found = false;
+ usb_put_dev(udev);
+ usb_set_intfdata(pusb_intf, NULL);
+ return;
+ }
+ padapter->fw = firmware;
+ padapter->fw_found = true;
+ /* firmware available - start netdev */
+ register_netdev(padapter->pnetdev);
+}
+
+static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+
+int rtl871x_load_fw(struct _adapter *padapter)
+{
+ struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
int rc;
- const char firmware_file[] = "rtlwifi/rtl8712u.bin";
- const struct firmware **praw = (const struct firmware **)
- (pphfwfile_hdl);
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
- (&padapter->dvobjpriv);
- struct usb_device *pusbdev = pdvobjpriv->pusbdev;
+ init_completion(&padapter->rtl8712_fw_ready);
printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
firmware_file);
- rc = request_firmware(praw, firmware_file, &pusbdev->dev);
- if (rc < 0) {
- printk(KERN_ERR "r8712u: Unable to load firmware\n");
- printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+ rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
+ GFP_KERNEL, padapter, rtl871x_load_fw_cb);
+ if (rc)
+ printk(KERN_ERR "r8712u: Firmware request error %d\n", rc);
+ return rc;
+}
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
+
+static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw)
+{
+ const struct firmware **praw = &padapter->fw;
+
+ if (padapter->fw->size > 200000) {
+ printk(KERN_ERR "r8172u: Badfw->size of %d\n",
+ (int)padapter->fw->size);
return 0;
}
*ppmappedfw = (u8 *)((*praw)->data);
return (*praw)->size;
}
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
{
uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
struct fw_hdr fwhdr;
u32 ulfilelength; /* FW file size */
- void *phfwfile_hdl = NULL;
const u8 *pmappedfw = NULL;
u8 *ptmpchar = NULL, *ppayload, *ptr;
struct tx_desc *ptx_desc;
u32 txdscp_sz = sizeof(struct tx_desc);
u8 ret = _FAIL;
- ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw);
+ ulfilelength = rtl871x_open_fw(padapter, &pmappedfw);
if (pmappedfw && (ulfilelength > 0)) {
update_fwhdr(&fwhdr, pmappedfw);
if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
- goto firmware_rel;
+ return ret;
fill_fwpriv(padapter, &fwhdr.fwpriv);
/* firmware check ok */
maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
maxlen += txdscp_sz;
ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ);
if (ptmpchar == NULL)
- goto firmware_rel;
+ return ret;
ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ -
((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1)));
exit_fail:
kfree(ptmpchar);
-firmware_rel:
- release_firmware((struct firmware *)phfwfile_hdl);
return ret;
}
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kthread.h>
+#include <linux/firmware.h>
#include "osdep_service.h"
#include "drv_types.h"
#include "xmit_osdep.h"
void r8712_stop_drv_timers(struct _adapter *padapter)
{
_cancel_timer_ex(&padapter->mlmepriv.assoc_timer);
- _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
- sitesurvey_ctrl_timer);
_cancel_timer_ex(&padapter->securitypriv.tkip_timer);
_cancel_timer_ex(&padapter->mlmepriv.scan_to_timer);
_cancel_timer_ex(&padapter->mlmepriv.dhcp_timer);
_cancel_timer_ex(&padapter->mlmepriv.wdg_timer);
+ _cancel_timer_ex(&padapter->mlmepriv.sitesurveyctrl.
+ sitesurvey_ctrl_timer);
}
static u8 init_default_value(struct _adapter *padapter)
r8712_free_mlme_priv(&padapter->mlmepriv);
r8712_free_io_queue(padapter);
_free_xmit_priv(&padapter->xmitpriv);
- _r8712_free_sta_priv(&padapter->stapriv);
+ if (padapter->fw_found)
+ _r8712_free_sta_priv(&padapter->stapriv);
_r8712_free_recv_priv(&padapter->recvpriv);
mp871xdeinit(padapter);
if (pnetdev)
{
struct _adapter *padapter = (struct _adapter *)netdev_priv(pnetdev);
+ mutex_lock(&padapter->mutex_start);
if (padapter->bup == false) {
padapter->bDriverStopped = false;
padapter->bSurpriseRemoved = false;
/* start driver mlme relation timer */
start_drv_timers(padapter);
padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
+ mutex_unlock(&padapter->mutex_start);
return 0;
netdev_open_error:
padapter->bup = false;
netif_carrier_off(pnetdev);
netif_stop_queue(pnetdev);
+ mutex_unlock(&padapter->mutex_start);
return -1;
}
r8712_free_network_queue(padapter);
/* The interface is no longer Up: */
padapter->bup = false;
+ release_firmware(padapter->fw);
+ /* never exit with a firmware callback pending */
+ wait_for_completion(&padapter->rtl8712_fw_ready);
return 0;
}
pdvobjpriv = &padapter->dvobjpriv;
pdvobjpriv->padapter = padapter;
padapter->dvobjpriv.pusbdev = udev;
+ padapter->pusb_intf = pusb_intf;
usb_set_intfdata(pusb_intf, pnetdev);
SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
/* step 2. */
"%pM\n", mac);
memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
}
- /* step 6. Tell the network stack we exist */
- if (register_netdev(pnetdev) != 0)
+ /* step 6. Load the firmware asynchronously */
+ if (rtl871x_load_fw(padapter))
goto error;
spin_lock_init(&padapter->lockRxFF0Filter);
+ mutex_init(&padapter->mutex_start);
return 0;
error:
usb_put_dev(udev);
flush_scheduled_work();
udelay(1);
/*Stop driver mlme relation timer */
- r8712_stop_drv_timers(padapter);
+ if (padapter->fw_found)
+ r8712_stop_drv_timers(padapter);
r871x_dev_unload(padapter);
r8712_free_drv_sw(padapter);
}