diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-04-23 14:09:39 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-23 14:09:39 -0400 |
commit | ec094144cdd54a36e65a69161e9705959c09cb23 (patch) | |
tree | 5a41c0f766143e462bfde8515ca6547d4ee7f78e /drivers/net/wireless/brcm80211 | |
parent | c43933e61ea9b630521bf0d5cf06c155478308a7 (diff) | |
parent | f09a878511997c25a76bf111a32f6b8345a701a5 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts:
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 265 |
2 files changed, 133 insertions, 139 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 3b3eb94b5472..ba92d6d7dfdd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -4088,10 +4088,6 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = { | |||
4088 | }, | 4088 | }, |
4089 | { | 4089 | { |
4090 | .max = 1, | 4090 | .max = 1, |
4091 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
4092 | }, | ||
4093 | { | ||
4094 | .max = 1, | ||
4095 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4091 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | |
4096 | BIT(NL80211_IFTYPE_P2P_GO) | 4092 | BIT(NL80211_IFTYPE_P2P_GO) |
4097 | }, | 4093 | }, |
@@ -4152,8 +4148,7 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |||
4152 | BIT(NL80211_IFTYPE_ADHOC) | | 4148 | BIT(NL80211_IFTYPE_ADHOC) | |
4153 | BIT(NL80211_IFTYPE_AP) | | 4149 | BIT(NL80211_IFTYPE_AP) | |
4154 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4150 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |
4155 | BIT(NL80211_IFTYPE_P2P_GO) | | 4151 | BIT(NL80211_IFTYPE_P2P_GO); |
4156 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
4157 | wiphy->iface_combinations = brcmf_iface_combos; | 4152 | wiphy->iface_combinations = brcmf_iface_combos; |
4158 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | 4153 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); |
4159 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | 4154 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index db663230088d..2346821667e6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -276,6 +276,130 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br) | |||
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
279 | /** | ||
280 | * This function frees the WL per-device resources. | ||
281 | * | ||
282 | * This function frees resources owned by the WL device pointed to | ||
283 | * by the wl parameter. | ||
284 | * | ||
285 | * precondition: can both be called locked and unlocked | ||
286 | * | ||
287 | */ | ||
288 | static void brcms_free(struct brcms_info *wl) | ||
289 | { | ||
290 | struct brcms_timer *t, *next; | ||
291 | |||
292 | /* free ucode data */ | ||
293 | if (wl->fw.fw_cnt) | ||
294 | brcms_ucode_data_free(&wl->ucode); | ||
295 | if (wl->irq) | ||
296 | free_irq(wl->irq, wl); | ||
297 | |||
298 | /* kill dpc */ | ||
299 | tasklet_kill(&wl->tasklet); | ||
300 | |||
301 | if (wl->pub) { | ||
302 | brcms_debugfs_detach(wl->pub); | ||
303 | brcms_c_module_unregister(wl->pub, "linux", wl); | ||
304 | } | ||
305 | |||
306 | /* free common resources */ | ||
307 | if (wl->wlc) { | ||
308 | brcms_c_detach(wl->wlc); | ||
309 | wl->wlc = NULL; | ||
310 | wl->pub = NULL; | ||
311 | } | ||
312 | |||
313 | /* virtual interface deletion is deferred so we cannot spinwait */ | ||
314 | |||
315 | /* wait for all pending callbacks to complete */ | ||
316 | while (atomic_read(&wl->callbacks) > 0) | ||
317 | schedule(); | ||
318 | |||
319 | /* free timers */ | ||
320 | for (t = wl->timers; t; t = next) { | ||
321 | next = t->next; | ||
322 | #ifdef DEBUG | ||
323 | kfree(t->name); | ||
324 | #endif | ||
325 | kfree(t); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * called from both kernel as from this kernel module (error flow on attach) | ||
331 | * precondition: perimeter lock is not acquired. | ||
332 | */ | ||
333 | static void brcms_remove(struct bcma_device *pdev) | ||
334 | { | ||
335 | struct ieee80211_hw *hw = bcma_get_drvdata(pdev); | ||
336 | struct brcms_info *wl = hw->priv; | ||
337 | |||
338 | if (wl->wlc) { | ||
339 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); | ||
340 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | ||
341 | ieee80211_unregister_hw(hw); | ||
342 | } | ||
343 | |||
344 | brcms_free(wl); | ||
345 | |||
346 | bcma_set_drvdata(pdev, NULL); | ||
347 | ieee80211_free_hw(hw); | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Precondition: Since this function is called in brcms_pci_probe() context, | ||
352 | * no locking is required. | ||
353 | */ | ||
354 | static void brcms_release_fw(struct brcms_info *wl) | ||
355 | { | ||
356 | int i; | ||
357 | for (i = 0; i < MAX_FW_IMAGES; i++) { | ||
358 | release_firmware(wl->fw.fw_bin[i]); | ||
359 | release_firmware(wl->fw.fw_hdr[i]); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Precondition: Since this function is called in brcms_pci_probe() context, | ||
365 | * no locking is required. | ||
366 | */ | ||
367 | static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev) | ||
368 | { | ||
369 | int status; | ||
370 | struct device *device = &pdev->dev; | ||
371 | char fw_name[100]; | ||
372 | int i; | ||
373 | |||
374 | memset(&wl->fw, 0, sizeof(struct brcms_firmware)); | ||
375 | for (i = 0; i < MAX_FW_IMAGES; i++) { | ||
376 | if (brcms_firmwares[i] == NULL) | ||
377 | break; | ||
378 | sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], | ||
379 | UCODE_LOADER_API_VER); | ||
380 | status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); | ||
381 | if (status) { | ||
382 | wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", | ||
383 | KBUILD_MODNAME, fw_name); | ||
384 | return status; | ||
385 | } | ||
386 | sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], | ||
387 | UCODE_LOADER_API_VER); | ||
388 | status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); | ||
389 | if (status) { | ||
390 | wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", | ||
391 | KBUILD_MODNAME, fw_name); | ||
392 | return status; | ||
393 | } | ||
394 | wl->fw.hdr_num_entries[i] = | ||
395 | wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); | ||
396 | } | ||
397 | wl->fw.fw_cnt = i; | ||
398 | status = brcms_ucode_data_init(wl, &wl->ucode); | ||
399 | brcms_release_fw(wl); | ||
400 | return status; | ||
401 | } | ||
402 | |||
279 | static void brcms_ops_tx(struct ieee80211_hw *hw, | 403 | static void brcms_ops_tx(struct ieee80211_hw *hw, |
280 | struct ieee80211_tx_control *control, | 404 | struct ieee80211_tx_control *control, |
281 | struct sk_buff *skb) | 405 | struct sk_buff *skb) |
@@ -308,6 +432,14 @@ static int brcms_ops_start(struct ieee80211_hw *hw) | |||
308 | if (!blocked) | 432 | if (!blocked) |
309 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | 433 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); |
310 | 434 | ||
435 | if (!wl->ucode.bcm43xx_bomminor) { | ||
436 | err = brcms_request_fw(wl, wl->wlc->hw->d11core); | ||
437 | if (err) { | ||
438 | brcms_remove(wl->wlc->hw->d11core); | ||
439 | return -ENOENT; | ||
440 | } | ||
441 | } | ||
442 | |||
311 | spin_lock_bh(&wl->lock); | 443 | spin_lock_bh(&wl->lock); |
312 | /* avoid acknowledging frames before a non-monitor device is added */ | 444 | /* avoid acknowledging frames before a non-monitor device is added */ |
313 | wl->mute_tx = true; | 445 | wl->mute_tx = true; |
@@ -856,129 +988,6 @@ void brcms_dpc(unsigned long data) | |||
856 | wake_up(&wl->tx_flush_wq); | 988 | wake_up(&wl->tx_flush_wq); |
857 | } | 989 | } |
858 | 990 | ||
859 | /* | ||
860 | * Precondition: Since this function is called in brcms_pci_probe() context, | ||
861 | * no locking is required. | ||
862 | */ | ||
863 | static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev) | ||
864 | { | ||
865 | int status; | ||
866 | struct device *device = &pdev->dev; | ||
867 | char fw_name[100]; | ||
868 | int i; | ||
869 | |||
870 | memset(&wl->fw, 0, sizeof(struct brcms_firmware)); | ||
871 | for (i = 0; i < MAX_FW_IMAGES; i++) { | ||
872 | if (brcms_firmwares[i] == NULL) | ||
873 | break; | ||
874 | sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i], | ||
875 | UCODE_LOADER_API_VER); | ||
876 | status = request_firmware(&wl->fw.fw_bin[i], fw_name, device); | ||
877 | if (status) { | ||
878 | wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", | ||
879 | KBUILD_MODNAME, fw_name); | ||
880 | return status; | ||
881 | } | ||
882 | sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i], | ||
883 | UCODE_LOADER_API_VER); | ||
884 | status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device); | ||
885 | if (status) { | ||
886 | wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n", | ||
887 | KBUILD_MODNAME, fw_name); | ||
888 | return status; | ||
889 | } | ||
890 | wl->fw.hdr_num_entries[i] = | ||
891 | wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr)); | ||
892 | } | ||
893 | wl->fw.fw_cnt = i; | ||
894 | return brcms_ucode_data_init(wl, &wl->ucode); | ||
895 | } | ||
896 | |||
897 | /* | ||
898 | * Precondition: Since this function is called in brcms_pci_probe() context, | ||
899 | * no locking is required. | ||
900 | */ | ||
901 | static void brcms_release_fw(struct brcms_info *wl) | ||
902 | { | ||
903 | int i; | ||
904 | for (i = 0; i < MAX_FW_IMAGES; i++) { | ||
905 | release_firmware(wl->fw.fw_bin[i]); | ||
906 | release_firmware(wl->fw.fw_hdr[i]); | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /** | ||
911 | * This function frees the WL per-device resources. | ||
912 | * | ||
913 | * This function frees resources owned by the WL device pointed to | ||
914 | * by the wl parameter. | ||
915 | * | ||
916 | * precondition: can both be called locked and unlocked | ||
917 | * | ||
918 | */ | ||
919 | static void brcms_free(struct brcms_info *wl) | ||
920 | { | ||
921 | struct brcms_timer *t, *next; | ||
922 | |||
923 | /* free ucode data */ | ||
924 | if (wl->fw.fw_cnt) | ||
925 | brcms_ucode_data_free(&wl->ucode); | ||
926 | if (wl->irq) | ||
927 | free_irq(wl->irq, wl); | ||
928 | |||
929 | /* kill dpc */ | ||
930 | tasklet_kill(&wl->tasklet); | ||
931 | |||
932 | if (wl->pub) { | ||
933 | brcms_debugfs_detach(wl->pub); | ||
934 | brcms_c_module_unregister(wl->pub, "linux", wl); | ||
935 | } | ||
936 | |||
937 | /* free common resources */ | ||
938 | if (wl->wlc) { | ||
939 | brcms_c_detach(wl->wlc); | ||
940 | wl->wlc = NULL; | ||
941 | wl->pub = NULL; | ||
942 | } | ||
943 | |||
944 | /* virtual interface deletion is deferred so we cannot spinwait */ | ||
945 | |||
946 | /* wait for all pending callbacks to complete */ | ||
947 | while (atomic_read(&wl->callbacks) > 0) | ||
948 | schedule(); | ||
949 | |||
950 | /* free timers */ | ||
951 | for (t = wl->timers; t; t = next) { | ||
952 | next = t->next; | ||
953 | #ifdef DEBUG | ||
954 | kfree(t->name); | ||
955 | #endif | ||
956 | kfree(t); | ||
957 | } | ||
958 | } | ||
959 | |||
960 | /* | ||
961 | * called from both kernel as from this kernel module (error flow on attach) | ||
962 | * precondition: perimeter lock is not acquired. | ||
963 | */ | ||
964 | static void brcms_remove(struct bcma_device *pdev) | ||
965 | { | ||
966 | struct ieee80211_hw *hw = bcma_get_drvdata(pdev); | ||
967 | struct brcms_info *wl = hw->priv; | ||
968 | |||
969 | if (wl->wlc) { | ||
970 | brcms_led_unregister(wl); | ||
971 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); | ||
972 | wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); | ||
973 | ieee80211_unregister_hw(hw); | ||
974 | } | ||
975 | |||
976 | brcms_free(wl); | ||
977 | |||
978 | bcma_set_drvdata(pdev, NULL); | ||
979 | ieee80211_free_hw(hw); | ||
980 | } | ||
981 | |||
982 | static irqreturn_t brcms_isr(int irq, void *dev_id) | 991 | static irqreturn_t brcms_isr(int irq, void *dev_id) |
983 | { | 992 | { |
984 | struct brcms_info *wl; | 993 | struct brcms_info *wl; |
@@ -1120,18 +1129,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1120 | spin_lock_init(&wl->lock); | 1129 | spin_lock_init(&wl->lock); |
1121 | spin_lock_init(&wl->isr_lock); | 1130 | spin_lock_init(&wl->isr_lock); |
1122 | 1131 | ||
1123 | /* prepare ucode */ | ||
1124 | if (brcms_request_fw(wl, pdev) < 0) { | ||
1125 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " | ||
1126 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); | ||
1127 | brcms_release_fw(wl); | ||
1128 | brcms_remove(pdev); | ||
1129 | return NULL; | ||
1130 | } | ||
1131 | |||
1132 | /* common load-time initialization */ | 1132 | /* common load-time initialization */ |
1133 | wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); | 1133 | wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err); |
1134 | brcms_release_fw(wl); | ||
1135 | if (!wl->wlc) { | 1134 | if (!wl->wlc) { |
1136 | wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", | 1135 | wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n", |
1137 | KBUILD_MODNAME, err); | 1136 | KBUILD_MODNAME, err); |