aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-04-04 06:10:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-08 14:35:04 -0400
commit25b5632fb35ca61b8ae3eee235edcdc2883f7a5e (patch)
treeaf0b4a0b32d6a9d05f8214f825964129658f4c43
parent1527c343c12f3a2aae532aa881d12c6fbf8749f4 (diff)
brcmsmac: request firmware in .start() callback
The firmware is requested from user-space. To assure the request is handled it is recommended to do the request upon IFF_UP. For a mac80211 driver the .start() callback can be considered the equivalent. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Piotr Haber <phaber@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c264
1 files changed, 132 insertions, 132 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c61407a..e2340b231aa1 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -274,6 +274,130 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
274 } 274 }
275} 275}
276 276
277/**
278 * This function frees the WL per-device resources.
279 *
280 * This function frees resources owned by the WL device pointed to
281 * by the wl parameter.
282 *
283 * precondition: can both be called locked and unlocked
284 *
285 */
286static void brcms_free(struct brcms_info *wl)
287{
288 struct brcms_timer *t, *next;
289
290 /* free ucode data */
291 if (wl->fw.fw_cnt)
292 brcms_ucode_data_free(&wl->ucode);
293 if (wl->irq)
294 free_irq(wl->irq, wl);
295
296 /* kill dpc */
297 tasklet_kill(&wl->tasklet);
298
299 if (wl->pub) {
300 brcms_debugfs_detach(wl->pub);
301 brcms_c_module_unregister(wl->pub, "linux", wl);
302 }
303
304 /* free common resources */
305 if (wl->wlc) {
306 brcms_c_detach(wl->wlc);
307 wl->wlc = NULL;
308 wl->pub = NULL;
309 }
310
311 /* virtual interface deletion is deferred so we cannot spinwait */
312
313 /* wait for all pending callbacks to complete */
314 while (atomic_read(&wl->callbacks) > 0)
315 schedule();
316
317 /* free timers */
318 for (t = wl->timers; t; t = next) {
319 next = t->next;
320#ifdef DEBUG
321 kfree(t->name);
322#endif
323 kfree(t);
324 }
325}
326
327/*
328* called from both kernel as from this kernel module (error flow on attach)
329* precondition: perimeter lock is not acquired.
330*/
331static void brcms_remove(struct bcma_device *pdev)
332{
333 struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
334 struct brcms_info *wl = hw->priv;
335
336 if (wl->wlc) {
337 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
338 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
339 ieee80211_unregister_hw(hw);
340 }
341
342 brcms_free(wl);
343
344 bcma_set_drvdata(pdev, NULL);
345 ieee80211_free_hw(hw);
346}
347
348/*
349 * Precondition: Since this function is called in brcms_pci_probe() context,
350 * no locking is required.
351 */
352static void brcms_release_fw(struct brcms_info *wl)
353{
354 int i;
355 for (i = 0; i < MAX_FW_IMAGES; i++) {
356 release_firmware(wl->fw.fw_bin[i]);
357 release_firmware(wl->fw.fw_hdr[i]);
358 }
359}
360
361/*
362 * Precondition: Since this function is called in brcms_pci_probe() context,
363 * no locking is required.
364 */
365static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
366{
367 int status;
368 struct device *device = &pdev->dev;
369 char fw_name[100];
370 int i;
371
372 memset(&wl->fw, 0, sizeof(struct brcms_firmware));
373 for (i = 0; i < MAX_FW_IMAGES; i++) {
374 if (brcms_firmwares[i] == NULL)
375 break;
376 sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
377 UCODE_LOADER_API_VER);
378 status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
379 if (status) {
380 wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
381 KBUILD_MODNAME, fw_name);
382 return status;
383 }
384 sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
385 UCODE_LOADER_API_VER);
386 status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
387 if (status) {
388 wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
389 KBUILD_MODNAME, fw_name);
390 return status;
391 }
392 wl->fw.hdr_num_entries[i] =
393 wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
394 }
395 wl->fw.fw_cnt = i;
396 status = brcms_ucode_data_init(wl, &wl->ucode);
397 brcms_release_fw(wl);
398 return status;
399}
400
277static void brcms_ops_tx(struct ieee80211_hw *hw, 401static void brcms_ops_tx(struct ieee80211_hw *hw,
278 struct ieee80211_tx_control *control, 402 struct ieee80211_tx_control *control,
279 struct sk_buff *skb) 403 struct sk_buff *skb)
@@ -306,6 +430,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
306 if (!blocked) 430 if (!blocked)
307 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); 431 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
308 432
433 if (!wl->ucode.bcm43xx_bomminor) {
434 err = brcms_request_fw(wl, wl->wlc->hw->d11core);
435 if (err) {
436 brcms_remove(wl->wlc->hw->d11core);
437 return -ENOENT;
438 }
439 }
440
309 spin_lock_bh(&wl->lock); 441 spin_lock_bh(&wl->lock);
310 /* avoid acknowledging frames before a non-monitor device is added */ 442 /* avoid acknowledging frames before a non-monitor device is added */
311 wl->mute_tx = true; 443 wl->mute_tx = true;
@@ -793,128 +925,6 @@ void brcms_dpc(unsigned long data)
793 wake_up(&wl->tx_flush_wq); 925 wake_up(&wl->tx_flush_wq);
794} 926}
795 927
796/*
797 * Precondition: Since this function is called in brcms_pci_probe() context,
798 * no locking is required.
799 */
800static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
801{
802 int status;
803 struct device *device = &pdev->dev;
804 char fw_name[100];
805 int i;
806
807 memset(&wl->fw, 0, sizeof(struct brcms_firmware));
808 for (i = 0; i < MAX_FW_IMAGES; i++) {
809 if (brcms_firmwares[i] == NULL)
810 break;
811 sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
812 UCODE_LOADER_API_VER);
813 status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
814 if (status) {
815 wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
816 KBUILD_MODNAME, fw_name);
817 return status;
818 }
819 sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
820 UCODE_LOADER_API_VER);
821 status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
822 if (status) {
823 wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
824 KBUILD_MODNAME, fw_name);
825 return status;
826 }
827 wl->fw.hdr_num_entries[i] =
828 wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
829 }
830 wl->fw.fw_cnt = i;
831 return brcms_ucode_data_init(wl, &wl->ucode);
832}
833
834/*
835 * Precondition: Since this function is called in brcms_pci_probe() context,
836 * no locking is required.
837 */
838static void brcms_release_fw(struct brcms_info *wl)
839{
840 int i;
841 for (i = 0; i < MAX_FW_IMAGES; i++) {
842 release_firmware(wl->fw.fw_bin[i]);
843 release_firmware(wl->fw.fw_hdr[i]);
844 }
845}
846
847/**
848 * This function frees the WL per-device resources.
849 *
850 * This function frees resources owned by the WL device pointed to
851 * by the wl parameter.
852 *
853 * precondition: can both be called locked and unlocked
854 *
855 */
856static void brcms_free(struct brcms_info *wl)
857{
858 struct brcms_timer *t, *next;
859
860 /* free ucode data */
861 if (wl->fw.fw_cnt)
862 brcms_ucode_data_free(&wl->ucode);
863 if (wl->irq)
864 free_irq(wl->irq, wl);
865
866 /* kill dpc */
867 tasklet_kill(&wl->tasklet);
868
869 if (wl->pub) {
870 brcms_debugfs_detach(wl->pub);
871 brcms_c_module_unregister(wl->pub, "linux", wl);
872 }
873
874 /* free common resources */
875 if (wl->wlc) {
876 brcms_c_detach(wl->wlc);
877 wl->wlc = NULL;
878 wl->pub = NULL;
879 }
880
881 /* virtual interface deletion is deferred so we cannot spinwait */
882
883 /* wait for all pending callbacks to complete */
884 while (atomic_read(&wl->callbacks) > 0)
885 schedule();
886
887 /* free timers */
888 for (t = wl->timers; t; t = next) {
889 next = t->next;
890#ifdef DEBUG
891 kfree(t->name);
892#endif
893 kfree(t);
894 }
895}
896
897/*
898* called from both kernel as from this kernel module (error flow on attach)
899* precondition: perimeter lock is not acquired.
900*/
901static void brcms_remove(struct bcma_device *pdev)
902{
903 struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
904 struct brcms_info *wl = hw->priv;
905
906 if (wl->wlc) {
907 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
908 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
909 ieee80211_unregister_hw(hw);
910 }
911
912 brcms_free(wl);
913
914 bcma_set_drvdata(pdev, NULL);
915 ieee80211_free_hw(hw);
916}
917
918static irqreturn_t brcms_isr(int irq, void *dev_id) 928static irqreturn_t brcms_isr(int irq, void *dev_id)
919{ 929{
920 struct brcms_info *wl; 930 struct brcms_info *wl;
@@ -1047,18 +1057,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev)
1047 spin_lock_init(&wl->lock); 1057 spin_lock_init(&wl->lock);
1048 spin_lock_init(&wl->isr_lock); 1058 spin_lock_init(&wl->isr_lock);
1049 1059
1050 /* prepare ucode */
1051 if (brcms_request_fw(wl, pdev) < 0) {
1052 wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
1053 "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
1054 brcms_release_fw(wl);
1055 brcms_remove(pdev);
1056 return NULL;
1057 }
1058
1059 /* common load-time initialization */ 1060 /* common load-time initialization */
1060 wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); 1061 wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
1061 brcms_release_fw(wl);
1062 if (!wl->wlc) { 1062 if (!wl->wlc) {
1063 wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", 1063 wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
1064 KBUILD_MODNAME, err); 1064 KBUILD_MODNAME, err);