diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2012-02-05 22:12:26 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-08 17:14:15 -0500 |
commit | 8c213fa59199f9673d66970d6940fa093186642f (patch) | |
tree | e7357cf1101a7b1451ab4b5c05245c34ad97436a /drivers/staging/rtl8712/hal_init.c | |
parent | 737912e11bf5bd4874acc771d8511a6eab891fc5 (diff) |
staging: r8712u: Use asynchronous firmware loading
In https://bugs.archlinux.org/task/27996, failure of driver r8712u is
reported, with a timeout during module loading due to synchronous loading
of the firmware. The code now uses request_firmware_nowait().
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/rtl8712/hal_init.c')
-rw-r--r-- | drivers/staging/rtl8712/hal_init.c | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index d0029aa4cd3..cc893c0f5ad 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c | |||
@@ -42,29 +42,56 @@ | |||
42 | #define FWBUFF_ALIGN_SZ 512 | 42 | #define FWBUFF_ALIGN_SZ 512 |
43 | #define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/ | 43 | #define MAX_DUMP_FWSZ 49152 /*default = 49152 (48k)*/ |
44 | 44 | ||
45 | static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl, | 45 | static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) |
46 | const u8 **ppmappedfw) | ||
47 | { | 46 | { |
47 | struct _adapter *padapter = context; | ||
48 | |||
49 | complete(&padapter->rtl8712_fw_ready); | ||
50 | if (!firmware) { | ||
51 | struct usb_device *udev = padapter->dvobjpriv.pusbdev; | ||
52 | struct usb_interface *pusb_intf = padapter->pusb_intf; | ||
53 | printk(KERN_ERR "r8712u: Firmware request failed\n"); | ||
54 | padapter->fw_found = false; | ||
55 | usb_put_dev(udev); | ||
56 | usb_set_intfdata(pusb_intf, NULL); | ||
57 | return; | ||
58 | } | ||
59 | padapter->fw = firmware; | ||
60 | padapter->fw_found = true; | ||
61 | /* firmware available - start netdev */ | ||
62 | register_netdev(padapter->pnetdev); | ||
63 | } | ||
64 | |||
65 | static const char firmware_file[] = "rtlwifi/rtl8712u.bin"; | ||
66 | |||
67 | int rtl871x_load_fw(struct _adapter *padapter) | ||
68 | { | ||
69 | struct device *dev = &padapter->dvobjpriv.pusbdev->dev; | ||
48 | int rc; | 70 | int rc; |
49 | const char firmware_file[] = "rtlwifi/rtl8712u.bin"; | ||
50 | const struct firmware **praw = (const struct firmware **) | ||
51 | (pphfwfile_hdl); | ||
52 | struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *) | ||
53 | (&padapter->dvobjpriv); | ||
54 | struct usb_device *pusbdev = pdvobjpriv->pusbdev; | ||
55 | 71 | ||
72 | init_completion(&padapter->rtl8712_fw_ready); | ||
56 | printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n", | 73 | printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n", |
57 | firmware_file); | 74 | firmware_file); |
58 | rc = request_firmware(praw, firmware_file, &pusbdev->dev); | 75 | rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev, |
59 | if (rc < 0) { | 76 | GFP_KERNEL, padapter, rtl871x_load_fw_cb); |
60 | printk(KERN_ERR "r8712u: Unable to load firmware\n"); | 77 | if (rc) |
61 | printk(KERN_ERR "r8712u: Install latest linux-firmware\n"); | 78 | printk(KERN_ERR "r8712u: Firmware request error %d\n", rc); |
79 | return rc; | ||
80 | } | ||
81 | MODULE_FIRMWARE("rtlwifi/rtl8712u.bin"); | ||
82 | |||
83 | static u32 rtl871x_open_fw(struct _adapter *padapter, const u8 **ppmappedfw) | ||
84 | { | ||
85 | const struct firmware **praw = &padapter->fw; | ||
86 | |||
87 | if (padapter->fw->size > 200000) { | ||
88 | printk(KERN_ERR "r8172u: Badfw->size of %d\n", | ||
89 | (int)padapter->fw->size); | ||
62 | return 0; | 90 | return 0; |
63 | } | 91 | } |
64 | *ppmappedfw = (u8 *)((*praw)->data); | 92 | *ppmappedfw = (u8 *)((*praw)->data); |
65 | return (*praw)->size; | 93 | return (*praw)->size; |
66 | } | 94 | } |
67 | MODULE_FIRMWARE("rtlwifi/rtl8712u.bin"); | ||
68 | 95 | ||
69 | static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv) | 96 | static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv) |
70 | { | 97 | { |
@@ -142,18 +169,17 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) | |||
142 | uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */ | 169 | uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */ |
143 | struct fw_hdr fwhdr; | 170 | struct fw_hdr fwhdr; |
144 | u32 ulfilelength; /* FW file size */ | 171 | u32 ulfilelength; /* FW file size */ |
145 | void *phfwfile_hdl = NULL; | ||
146 | const u8 *pmappedfw = NULL; | 172 | const u8 *pmappedfw = NULL; |
147 | u8 *ptmpchar = NULL, *ppayload, *ptr; | 173 | u8 *ptmpchar = NULL, *ppayload, *ptr; |
148 | struct tx_desc *ptx_desc; | 174 | struct tx_desc *ptx_desc; |
149 | u32 txdscp_sz = sizeof(struct tx_desc); | 175 | u32 txdscp_sz = sizeof(struct tx_desc); |
150 | u8 ret = _FAIL; | 176 | u8 ret = _FAIL; |
151 | 177 | ||
152 | ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw); | 178 | ulfilelength = rtl871x_open_fw(padapter, &pmappedfw); |
153 | if (pmappedfw && (ulfilelength > 0)) { | 179 | if (pmappedfw && (ulfilelength > 0)) { |
154 | update_fwhdr(&fwhdr, pmappedfw); | 180 | update_fwhdr(&fwhdr, pmappedfw); |
155 | if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) | 181 | if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) |
156 | goto firmware_rel; | 182 | return ret; |
157 | fill_fwpriv(padapter, &fwhdr.fwpriv); | 183 | fill_fwpriv(padapter, &fwhdr.fwpriv); |
158 | /* firmware check ok */ | 184 | /* firmware check ok */ |
159 | maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? | 185 | maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? |
@@ -161,7 +187,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) | |||
161 | maxlen += txdscp_sz; | 187 | maxlen += txdscp_sz; |
162 | ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ); | 188 | ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ); |
163 | if (ptmpchar == NULL) | 189 | if (ptmpchar == NULL) |
164 | goto firmware_rel; | 190 | return ret; |
165 | 191 | ||
166 | ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ - | 192 | ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ - |
167 | ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1))); | 193 | ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1))); |
@@ -297,8 +323,6 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) | |||
297 | 323 | ||
298 | exit_fail: | 324 | exit_fail: |
299 | kfree(ptmpchar); | 325 | kfree(ptmpchar); |
300 | firmware_rel: | ||
301 | release_firmware((struct firmware *)phfwfile_hdl); | ||
302 | return ret; | 326 | return ret; |
303 | } | 327 | } |
304 | 328 | ||