diff options
104 files changed, 3097 insertions, 1621 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 2a479c7005b8..6bd1cd5c60df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5978,7 +5978,7 @@ S: Maintained | |||
5978 | F: drivers/input/misc/wistron_btns.c | 5978 | F: drivers/input/misc/wistron_btns.c |
5979 | 5979 | ||
5980 | WL1251 WIRELESS DRIVER | 5980 | WL1251 WIRELESS DRIVER |
5981 | M: Kalle Valo <kalle.valo@nokia.com> | 5981 | M: Kalle Valo <kalle.valo@iki.fi> |
5982 | L: linux-wireless@vger.kernel.org | 5982 | L: linux-wireless@vger.kernel.org |
5983 | W: http://wireless.kernel.org | 5983 | W: http://wireless.kernel.org |
5984 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | 5984 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 56dd6650c97a..588943660755 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -112,6 +112,7 @@ config AIRO_CS | |||
112 | depends on PCMCIA && (BROKEN || !M32R) | 112 | depends on PCMCIA && (BROKEN || !M32R) |
113 | select WIRELESS_EXT | 113 | select WIRELESS_EXT |
114 | select WEXT_SPY | 114 | select WEXT_SPY |
115 | select WEXT_PRIV | ||
115 | select CRYPTO | 116 | select CRYPTO |
116 | select CRYPTO_AES | 117 | select CRYPTO_AES |
117 | ---help--- | 118 | ---help--- |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index c22a34c7639c..698d5672a070 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/freezer.h> | 51 | #include <linux/freezer.h> |
52 | 52 | ||
53 | #include <linux/ieee80211.h> | 53 | #include <linux/ieee80211.h> |
54 | #include <net/iw_handler.h> | ||
54 | 55 | ||
55 | #include "airo.h" | 56 | #include "airo.h" |
56 | 57 | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 91797cb6e0e8..8a964f130367 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -2329,54 +2329,55 @@ out: | |||
2329 | return err; | 2329 | return err; |
2330 | } | 2330 | } |
2331 | 2331 | ||
2332 | static void ar9170_sta_notify(struct ieee80211_hw *hw, | 2332 | static int ar9170_sta_add(struct ieee80211_hw *hw, |
2333 | struct ieee80211_vif *vif, | 2333 | struct ieee80211_vif *vif, |
2334 | enum sta_notify_cmd cmd, | 2334 | struct ieee80211_sta *sta) |
2335 | struct ieee80211_sta *sta) | ||
2336 | { | 2335 | { |
2337 | struct ar9170 *ar = hw->priv; | 2336 | struct ar9170 *ar = hw->priv; |
2338 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | 2337 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; |
2339 | unsigned int i; | 2338 | unsigned int i; |
2340 | 2339 | ||
2341 | switch (cmd) { | 2340 | memset(sta_info, 0, sizeof(*sta_info)); |
2342 | case STA_NOTIFY_ADD: | ||
2343 | memset(sta_info, 0, sizeof(*sta_info)); | ||
2344 | 2341 | ||
2345 | if (!sta->ht_cap.ht_supported) | 2342 | if (!sta->ht_cap.ht_supported) |
2346 | break; | 2343 | return 0; |
2347 | 2344 | ||
2348 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) | 2345 | if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) |
2349 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; | 2346 | ar->global_ampdu_density = sta->ht_cap.ampdu_density; |
2350 | 2347 | ||
2351 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) | 2348 | if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) |
2352 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; | 2349 | ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; |
2353 | 2350 | ||
2354 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2351 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2355 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; | 2352 | sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; |
2356 | sta_info->agg[i].active = false; | 2353 | sta_info->agg[i].active = false; |
2357 | sta_info->agg[i].ssn = 0; | 2354 | sta_info->agg[i].ssn = 0; |
2358 | sta_info->agg[i].tid = i; | 2355 | sta_info->agg[i].tid = i; |
2359 | INIT_LIST_HEAD(&sta_info->agg[i].list); | 2356 | INIT_LIST_HEAD(&sta_info->agg[i].list); |
2360 | skb_queue_head_init(&sta_info->agg[i].queue); | 2357 | skb_queue_head_init(&sta_info->agg[i].queue); |
2361 | } | 2358 | } |
2362 | 2359 | ||
2363 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); | 2360 | sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); |
2364 | break; | ||
2365 | 2361 | ||
2366 | case STA_NOTIFY_REMOVE: | 2362 | return 0; |
2367 | if (!sta->ht_cap.ht_supported) | 2363 | } |
2368 | break; | ||
2369 | 2364 | ||
2370 | for (i = 0; i < AR9170_NUM_TID; i++) { | 2365 | static int ar9170_sta_remove(struct ieee80211_hw *hw, |
2371 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; | 2366 | struct ieee80211_vif *vif, |
2372 | skb_queue_purge(&sta_info->agg[i].queue); | 2367 | struct ieee80211_sta *sta) |
2373 | } | 2368 | { |
2369 | struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; | ||
2370 | unsigned int i; | ||
2374 | 2371 | ||
2375 | break; | 2372 | if (!sta->ht_cap.ht_supported) |
2373 | return 0; | ||
2376 | 2374 | ||
2377 | default: | 2375 | for (i = 0; i < AR9170_NUM_TID; i++) { |
2378 | break; | 2376 | sta_info->agg[i].state = AR9170_TID_STATE_INVALID; |
2377 | skb_queue_purge(&sta_info->agg[i].queue); | ||
2379 | } | 2378 | } |
2379 | |||
2380 | return 0; | ||
2380 | } | 2381 | } |
2381 | 2382 | ||
2382 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2383 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -2495,7 +2496,8 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2495 | .bss_info_changed = ar9170_op_bss_info_changed, | 2496 | .bss_info_changed = ar9170_op_bss_info_changed, |
2496 | .get_tsf = ar9170_op_get_tsf, | 2497 | .get_tsf = ar9170_op_get_tsf, |
2497 | .set_key = ar9170_set_key, | 2498 | .set_key = ar9170_set_key, |
2498 | .sta_notify = ar9170_sta_notify, | 2499 | .sta_add = ar9170_sta_add, |
2500 | .sta_remove = ar9170_sta_remove, | ||
2499 | .get_stats = ar9170_get_stats, | 2501 | .get_stats = ar9170_get_stats, |
2500 | .ampdu_action = ar9170_ampdu_action, | 2502 | .ampdu_action = ar9170_ampdu_action, |
2501 | }; | 2503 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index d088ebfe63a6..b4a31a43a62c 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
62 | * Beacons are always sent out at the lowest rate, and are not retried. | 62 | * Beacons are always sent out at the lowest rate, and are not retried. |
63 | */ | 63 | */ |
64 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | 64 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, |
65 | struct ath_buf *bf) | 65 | struct ath_buf *bf, int rateidx) |
66 | { | 66 | { |
67 | struct sk_buff *skb = bf->bf_mpdu; | 67 | struct sk_buff *skb = bf->bf_mpdu; |
68 | struct ath_hw *ah = sc->sc_ah; | 68 | struct ath_hw *ah = sc->sc_ah; |
@@ -96,9 +96,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
96 | ds->ds_data = bf->bf_buf_addr; | 96 | ds->ds_data = bf->bf_buf_addr; |
97 | 97 | ||
98 | sband = &sc->sbands[common->hw->conf.channel->band]; | 98 | sband = &sc->sbands[common->hw->conf.channel->band]; |
99 | rate = sband->bitrates[0].hw_value; | 99 | rate = sband->bitrates[rateidx].hw_value; |
100 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) | 100 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) |
101 | rate |= sband->bitrates[0].hw_value_short; | 101 | rate |= sband->bitrates[rateidx].hw_value_short; |
102 | 102 | ||
103 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, | 103 | ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, |
104 | ATH9K_PKT_TYPE_BEACON, | 104 | ATH9K_PKT_TYPE_BEACON, |
@@ -206,7 +206,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
206 | } | 206 | } |
207 | } | 207 | } |
208 | 208 | ||
209 | ath_beacon_setup(sc, avp, bf); | 209 | ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); |
210 | 210 | ||
211 | while (skb) { | 211 | while (skb) { |
212 | ath_tx_cabq(hw, skb); | 212 | ath_tx_cabq(hw, skb); |
@@ -237,7 +237,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
237 | bf = avp->av_bcbuf; | 237 | bf = avp->av_bcbuf; |
238 | skb = bf->bf_mpdu; | 238 | skb = bf->bf_mpdu; |
239 | 239 | ||
240 | ath_beacon_setup(sc, avp, bf); | 240 | ath_beacon_setup(sc, avp, bf, 0); |
241 | 241 | ||
242 | /* NB: caller is known to have already stopped tx dma */ | 242 | /* NB: caller is known to have already stopped tx dma */ |
243 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); | 243 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); |
@@ -526,16 +526,13 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
526 | { | 526 | { |
527 | u32 nexttbtt, intval; | 527 | u32 nexttbtt, intval; |
528 | 528 | ||
529 | /* Configure the timers only when the TSF has to be reset */ | ||
530 | |||
531 | if (!(sc->sc_flags & SC_OP_TSF_RESET)) | ||
532 | return; | ||
533 | |||
534 | /* NB: the beacon interval is kept internally in TU's */ | 529 | /* NB: the beacon interval is kept internally in TU's */ |
535 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 530 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; |
536 | intval /= ATH_BCBUF; /* for staggered beacons */ | 531 | intval /= ATH_BCBUF; /* for staggered beacons */ |
537 | nexttbtt = intval; | 532 | nexttbtt = intval; |
538 | intval |= ATH9K_BEACON_RESET_TSF; | 533 | |
534 | if (sc->sc_flags & SC_OP_TSF_RESET) | ||
535 | intval |= ATH9K_BEACON_RESET_TSF; | ||
539 | 536 | ||
540 | /* | 537 | /* |
541 | * In AP mode we enable the beacon timers and SWBA interrupts to | 538 | * In AP mode we enable the beacon timers and SWBA interrupts to |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9c8f925c2093..67ca4e5a6017 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1684,24 +1684,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
1684 | "Set HW RX filter: 0x%x\n", rfilt); | 1684 | "Set HW RX filter: 0x%x\n", rfilt); |
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | 1687 | static int ath9k_sta_add(struct ieee80211_hw *hw, |
1688 | struct ieee80211_vif *vif, | 1688 | struct ieee80211_vif *vif, |
1689 | enum sta_notify_cmd cmd, | 1689 | struct ieee80211_sta *sta) |
1690 | struct ieee80211_sta *sta) | ||
1691 | { | 1690 | { |
1692 | struct ath_wiphy *aphy = hw->priv; | 1691 | struct ath_wiphy *aphy = hw->priv; |
1693 | struct ath_softc *sc = aphy->sc; | 1692 | struct ath_softc *sc = aphy->sc; |
1694 | 1693 | ||
1695 | switch (cmd) { | 1694 | ath_node_attach(sc, sta); |
1696 | case STA_NOTIFY_ADD: | 1695 | |
1697 | ath_node_attach(sc, sta); | 1696 | return 0; |
1698 | break; | 1697 | } |
1699 | case STA_NOTIFY_REMOVE: | 1698 | |
1700 | ath_node_detach(sc, sta); | 1699 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
1701 | break; | 1700 | struct ieee80211_vif *vif, |
1702 | default: | 1701 | struct ieee80211_sta *sta) |
1703 | break; | 1702 | { |
1704 | } | 1703 | struct ath_wiphy *aphy = hw->priv; |
1704 | struct ath_softc *sc = aphy->sc; | ||
1705 | |||
1706 | ath_node_detach(sc, sta); | ||
1707 | |||
1708 | return 0; | ||
1705 | } | 1709 | } |
1706 | 1710 | ||
1707 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1711 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -2045,7 +2049,8 @@ struct ieee80211_ops ath9k_ops = { | |||
2045 | .remove_interface = ath9k_remove_interface, | 2049 | .remove_interface = ath9k_remove_interface, |
2046 | .config = ath9k_config, | 2050 | .config = ath9k_config, |
2047 | .configure_filter = ath9k_configure_filter, | 2051 | .configure_filter = ath9k_configure_filter, |
2048 | .sta_notify = ath9k_sta_notify, | 2052 | .sta_add = ath9k_sta_add, |
2053 | .sta_remove = ath9k_sta_remove, | ||
2049 | .conf_tx = ath9k_conf_tx, | 2054 | .conf_tx = ath9k_conf_tx, |
2050 | .bss_info_changed = ath9k_bss_info_changed, | 2055 | .bss_info_changed = ath9k_bss_info_changed, |
2051 | .set_key = ath9k_set_key, | 2056 | .set_key = ath9k_set_key, |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 11968843c773..ac34a055c713 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -668,7 +668,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
668 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | 668 | struct ieee80211_tx_rate *rates = tx_info->control.rates; |
669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 669 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
670 | __le16 fc = hdr->frame_control; | 670 | __le16 fc = hdr->frame_control; |
671 | u8 try_per_rate, i = 0, rix, nrix; | 671 | u8 try_per_rate, i = 0, rix; |
672 | int is_probe = 0; | 672 | int is_probe = 0; |
673 | 673 | ||
674 | if (rate_control_send_low(sta, priv_sta, txrc)) | 674 | if (rate_control_send_low(sta, priv_sta, txrc)) |
@@ -688,26 +688,25 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
688 | 688 | ||
689 | rate_table = sc->cur_rate_table; | 689 | rate_table = sc->cur_rate_table; |
690 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); | 690 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); |
691 | nrix = rix; | ||
692 | 691 | ||
693 | if (is_probe) { | 692 | if (is_probe) { |
694 | /* set one try for probe rates. For the | 693 | /* set one try for probe rates. For the |
695 | * probes don't enable rts */ | 694 | * probes don't enable rts */ |
696 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 695 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
697 | 1, nrix, 0); | 696 | 1, rix, 0); |
698 | 697 | ||
699 | /* Get the next tried/allowed rate. No RTS for the next series | 698 | /* Get the next tried/allowed rate. No RTS for the next series |
700 | * after the probe rate | 699 | * after the probe rate |
701 | */ | 700 | */ |
702 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); | 701 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); |
703 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 702 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
704 | try_per_rate, nrix, 0); | 703 | try_per_rate, rix, 0); |
705 | 704 | ||
706 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 705 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
707 | } else { | 706 | } else { |
708 | /* Set the choosen rate. No RTS for first series entry. */ | 707 | /* Set the choosen rate. No RTS for first series entry. */ |
709 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 708 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
710 | try_per_rate, nrix, 0); | 709 | try_per_rate, rix, 0); |
711 | } | 710 | } |
712 | 711 | ||
713 | /* Fill in the other rates for multirate retry */ | 712 | /* Fill in the other rates for multirate retry */ |
@@ -716,10 +715,10 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
716 | if (i + 1 == 4) | 715 | if (i + 1 == 4) |
717 | try_per_rate = 8; | 716 | try_per_rate = 8; |
718 | 717 | ||
719 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix); | 718 | ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); |
720 | /* All other rates in the series have RTS enabled */ | 719 | /* All other rates in the series have RTS enabled */ |
721 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, | 720 | ath_rc_rate_set_series(rate_table, &rates[i], txrc, |
722 | try_per_rate, nrix, 1); | 721 | try_per_rate, rix, 1); |
723 | } | 722 | } |
724 | 723 | ||
725 | /* | 724 | /* |
diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h index 82167a90088f..9ff6750dc57f 100644 --- a/drivers/net/wireless/b43legacy/leds.h +++ b/drivers/net/wireless/b43legacy/leds.h | |||
@@ -45,7 +45,7 @@ enum b43legacy_led_behaviour { | |||
45 | void b43legacy_leds_init(struct b43legacy_wldev *dev); | 45 | void b43legacy_leds_init(struct b43legacy_wldev *dev); |
46 | void b43legacy_leds_exit(struct b43legacy_wldev *dev); | 46 | void b43legacy_leds_exit(struct b43legacy_wldev *dev); |
47 | 47 | ||
48 | #else /* CONFIG_B43EGACY_LEDS */ | 48 | #else /* CONFIG_B43LEGACY_LEDS */ |
49 | /* LED support disabled */ | 49 | /* LED support disabled */ |
50 | 50 | ||
51 | struct b43legacy_led { | 51 | struct b43legacy_led { |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index c9640a3e02c9..d19748d90aaf 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -794,13 +794,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
794 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", | 794 | PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", |
795 | 0x7a954bd9, 0x74be00c6), | 795 | 0x7a954bd9, 0x74be00c6), |
796 | PCMCIA_DEVICE_PROD_ID123( | 796 | PCMCIA_DEVICE_PROD_ID123( |
797 | "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", | ||
798 | 0x4b801a17, 0x6345a0bf, 0xc9049a39), | ||
799 | /* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */ | ||
800 | PCMCIA_DEVICE_PROD_ID123( | ||
801 | "D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", | ||
802 | 0x1a424a1c, 0x6ea57632, 0xdd97a26b), | ||
803 | PCMCIA_DEVICE_PROD_ID123( | ||
804 | "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", | 797 | "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", |
805 | 0xe6ec52ce, 0x08649af2, 0x4b74baa0), | 798 | 0xe6ec52ce, 0x08649af2, 0x4b74baa0), |
806 | PCMCIA_DEVICE_PROD_ID123( | 799 | PCMCIA_DEVICE_PROD_ID123( |
@@ -834,14 +827,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = { | |||
834 | "Ver. 1.00", | 827 | "Ver. 1.00", |
835 | 0x5cd01705, 0x4271660f, 0x9d08ee12), | 828 | 0x5cd01705, 0x4271660f, 0x9d08ee12), |
836 | PCMCIA_DEVICE_PROD_ID123( | 829 | PCMCIA_DEVICE_PROD_ID123( |
837 | "corega", "WL PCCL-11", "ISL37300P", | ||
838 | 0xa21501a, 0x59868926, 0xc9049a39), | ||
839 | PCMCIA_DEVICE_PROD_ID123( | ||
840 | "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", | ||
841 | 0xa5f472c2, 0x9c05598d, 0xc9049a39), | ||
842 | PCMCIA_DEVICE_PROD_ID123( | ||
843 | "Wireless LAN" , "11Mbps PC Card", "Version 01.02", | 830 | "Wireless LAN" , "11Mbps PC Card", "Version 01.02", |
844 | 0x4b8870ff, 0x70e946d1, 0x4b74baa0), | 831 | 0x4b8870ff, 0x70e946d1, 0x4b74baa0), |
832 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), | ||
833 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), | ||
834 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), | ||
835 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), | ||
845 | PCMCIA_DEVICE_NULL | 836 | PCMCIA_DEVICE_NULL |
846 | }; | 837 | }; |
847 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); | 838 | MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 694ceef88590..3bf2e6e9b2d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
246 | .use_rts_for_ht = true, /* use rts/cts protection */ | 246 | .use_rts_for_ht = true, /* use rts/cts protection */ |
247 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 247 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
248 | .support_ct_kill_exit = true, | 248 | .support_ct_kill_exit = true, |
249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 249 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
250 | .chain_noise_scale = 1000, | 250 | .chain_noise_scale = 1000, |
251 | }; | 251 | }; |
252 | 252 | ||
@@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
274 | .led_compensation = 51, | 274 | .led_compensation = 51, |
275 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 275 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
276 | .support_ct_kill_exit = true, | 276 | .support_ct_kill_exit = true, |
277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 277 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
278 | .chain_noise_scale = 1000, | 278 | .chain_noise_scale = 1000, |
279 | }; | 279 | }; |
280 | 280 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 6940f086823c..303cc8193adc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -45,8 +45,8 @@ | |||
45 | #include "iwl-sta.h" | 45 | #include "iwl-sta.h" |
46 | #include "iwl-3945.h" | 46 | #include "iwl-3945.h" |
47 | #include "iwl-eeprom.h" | 47 | #include "iwl-eeprom.h" |
48 | #include "iwl-helpers.h" | ||
49 | #include "iwl-core.h" | 48 | #include "iwl-core.h" |
49 | #include "iwl-helpers.h" | ||
50 | #include "iwl-led.h" | 50 | #include "iwl-led.h" |
51 | #include "iwl-3945-led.h" | 51 | #include "iwl-3945-led.h" |
52 | 52 | ||
@@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2470 | memset((void *)&priv->hw_params, 0, | 2470 | memset((void *)&priv->hw_params, 0, |
2471 | sizeof(struct iwl_hw_params)); | 2471 | sizeof(struct iwl_hw_params)); |
2472 | 2472 | ||
2473 | priv->shared_virt = | 2473 | priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, |
2474 | pci_alloc_consistent(priv->pci_dev, | 2474 | sizeof(struct iwl3945_shared), |
2475 | sizeof(struct iwl3945_shared), | 2475 | &priv->shared_phys, GFP_KERNEL); |
2476 | &priv->shared_phys); | ||
2477 | |||
2478 | if (!priv->shared_virt) { | 2476 | if (!priv->shared_virt) { |
2479 | IWL_ERR(priv, "failed to allocate pci memory\n"); | 2477 | IWL_ERR(priv, "failed to allocate pci memory\n"); |
2480 | mutex_unlock(&priv->mutex); | 2478 | mutex_unlock(&priv->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 8f553f36d270..452dfd5456c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -171,24 +171,6 @@ struct iwl3945_frame { | |||
171 | 171 | ||
172 | #define SCAN_INTERVAL 100 | 172 | #define SCAN_INTERVAL 100 |
173 | 173 | ||
174 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | ||
175 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | ||
176 | #define STATUS_INT_ENABLED 2 | ||
177 | #define STATUS_RF_KILL_HW 3 | ||
178 | #define STATUS_INIT 5 | ||
179 | #define STATUS_ALIVE 6 | ||
180 | #define STATUS_READY 7 | ||
181 | #define STATUS_TEMPERATURE 8 | ||
182 | #define STATUS_GEO_CONFIGURED 9 | ||
183 | #define STATUS_EXIT_PENDING 10 | ||
184 | #define STATUS_STATISTICS 12 | ||
185 | #define STATUS_SCANNING 13 | ||
186 | #define STATUS_SCAN_ABORTING 14 | ||
187 | #define STATUS_SCAN_HW 15 | ||
188 | #define STATUS_POWER_PMI 16 | ||
189 | #define STATUS_FW_ERROR 17 | ||
190 | #define STATUS_CONF_PENDING 18 | ||
191 | |||
192 | #define MAX_TID_COUNT 9 | 174 | #define MAX_TID_COUNT 9 |
193 | 175 | ||
194 | #define IWL_INVALID_RATE 0xFF | 176 | #define IWL_INVALID_RATE 0xFF |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b07874f7da7f..1bd2cd836026 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -581,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
581 | 581 | ||
582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 582 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
583 | 583 | ||
584 | /* make sure all queue are not stopped */ | ||
585 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
586 | for (i = 0; i < 4; i++) | ||
587 | atomic_set(&priv->queue_stop_count[i], 0); | ||
588 | |||
589 | /* reset to 0 to enable all the queue first */ | ||
590 | priv->txq_ctx_active_msk = 0; | ||
584 | /* Map each Tx/cmd queue to its corresponding fifo */ | 591 | /* Map each Tx/cmd queue to its corresponding fifo */ |
585 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { | 592 | for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { |
586 | int ac = default_queue_to_tx_fifo[i]; | 593 | int ac = default_queue_to_tx_fifo[i]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 2cf92a51f041..e476acb53aa7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -648,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
648 | 648 | ||
649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 649 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
650 | 650 | ||
651 | /* make sure all queue are not stopped */ | ||
652 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
653 | for (i = 0; i < 4; i++) | ||
654 | atomic_set(&priv->queue_stop_count[i], 0); | ||
655 | |||
656 | /* reset to 0 to enable all the queue first */ | ||
657 | priv->txq_ctx_active_msk = 0; | ||
651 | /* map qos queues to fifos one-to-one */ | 658 | /* map qos queues to fifos one-to-one */ |
652 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | 659 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { |
653 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | 660 | int ac = iwl5000_default_queue_to_tx_fifo[i]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 782e23a26984..c4844adff92a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -70,6 +70,14 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
70 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | 70 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; |
71 | } | 71 | } |
72 | 72 | ||
73 | /* Indicate calibration version to uCode. */ | ||
74 | static void iwl6050_set_calib_version(struct iwl_priv *priv) | ||
75 | { | ||
76 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) | ||
77 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
78 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||
79 | } | ||
80 | |||
73 | /* NIC configuration for 6000 series */ | 81 | /* NIC configuration for 6000 series */ |
74 | static void iwl6000_nic_config(struct iwl_priv *priv) | 82 | static void iwl6000_nic_config(struct iwl_priv *priv) |
75 | { | 83 | { |
@@ -96,6 +104,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
96 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); | 104 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
97 | } | 105 | } |
98 | /* else do nothing, uCode configured */ | 106 | /* else do nothing, uCode configured */ |
107 | if (priv->cfg->ops->lib->temp_ops.set_calib_version) | ||
108 | priv->cfg->ops->lib->temp_ops.set_calib_version(priv); | ||
99 | } | 109 | } |
100 | 110 | ||
101 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | 111 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { |
@@ -277,6 +287,71 @@ static const struct iwl_ops iwl6000_ops = { | |||
277 | .led = &iwlagn_led_ops, | 287 | .led = &iwlagn_led_ops, |
278 | }; | 288 | }; |
279 | 289 | ||
290 | static struct iwl_lib_ops iwl6050_lib = { | ||
291 | .set_hw_params = iwl6000_hw_set_hw_params, | ||
292 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | ||
293 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | ||
294 | .txq_set_sched = iwl5000_txq_set_sched, | ||
295 | .txq_agg_enable = iwl5000_txq_agg_enable, | ||
296 | .txq_agg_disable = iwl5000_txq_agg_disable, | ||
297 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
298 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
299 | .txq_init = iwl_hw_tx_queue_init, | ||
300 | .rx_handler_setup = iwl5000_rx_handler_setup, | ||
301 | .setup_deferred_work = iwl5000_setup_deferred_work, | ||
302 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | ||
303 | .load_ucode = iwl5000_load_ucode, | ||
304 | .dump_nic_event_log = iwl_dump_nic_event_log, | ||
305 | .dump_nic_error_log = iwl_dump_nic_error_log, | ||
306 | .dump_csr = iwl_dump_csr, | ||
307 | .dump_fh = iwl_dump_fh, | ||
308 | .init_alive_start = iwl5000_init_alive_start, | ||
309 | .alive_notify = iwl5000_alive_notify, | ||
310 | .send_tx_power = iwl5000_send_tx_power, | ||
311 | .update_chain_flags = iwl_update_chain_flags, | ||
312 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
313 | .apm_ops = { | ||
314 | .init = iwl_apm_init, | ||
315 | .stop = iwl_apm_stop, | ||
316 | .config = iwl6000_nic_config, | ||
317 | .set_pwr_src = iwl_set_pwr_src, | ||
318 | }, | ||
319 | .eeprom_ops = { | ||
320 | .regulatory_bands = { | ||
321 | EEPROM_5000_REG_BAND_1_CHANNELS, | ||
322 | EEPROM_5000_REG_BAND_2_CHANNELS, | ||
323 | EEPROM_5000_REG_BAND_3_CHANNELS, | ||
324 | EEPROM_5000_REG_BAND_4_CHANNELS, | ||
325 | EEPROM_5000_REG_BAND_5_CHANNELS, | ||
326 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | ||
327 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | ||
328 | }, | ||
329 | .verify_signature = iwlcore_eeprom_verify_signature, | ||
330 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | ||
331 | .release_semaphore = iwlcore_eeprom_release_semaphore, | ||
332 | .calib_version = iwl5000_eeprom_calib_version, | ||
333 | .query_addr = iwl5000_eeprom_query_addr, | ||
334 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | ||
335 | }, | ||
336 | .post_associate = iwl_post_associate, | ||
337 | .isr = iwl_isr_ict, | ||
338 | .config_ap = iwl_config_ap, | ||
339 | .temp_ops = { | ||
340 | .temperature = iwl5000_temperature, | ||
341 | .set_ct_kill = iwl6000_set_ct_threshold, | ||
342 | .set_calib_version = iwl6050_set_calib_version, | ||
343 | }, | ||
344 | .add_bcast_station = iwl_add_bcast_station, | ||
345 | }; | ||
346 | |||
347 | static const struct iwl_ops iwl6050_ops = { | ||
348 | .ucode = &iwl5000_ucode, | ||
349 | .lib = &iwl6050_lib, | ||
350 | .hcmd = &iwl5000_hcmd, | ||
351 | .utils = &iwl5000_hcmd_utils, | ||
352 | .led = &iwlagn_led_ops, | ||
353 | }; | ||
354 | |||
280 | /* | 355 | /* |
281 | * "i": Internal configuration, use internal Power Amplifier | 356 | * "i": Internal configuration, use internal Power Amplifier |
282 | */ | 357 | */ |
@@ -380,7 +455,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
380 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 455 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
381 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 456 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
382 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 457 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
383 | .ops = &iwl6000_ops, | 458 | .ops = &iwl6050_ops, |
384 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
385 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 460 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
386 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
@@ -412,7 +487,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
412 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 487 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
413 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 488 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
414 | .sku = IWL_SKU_A|IWL_SKU_G, | 489 | .sku = IWL_SKU_A|IWL_SKU_G, |
415 | .ops = &iwl6000_ops, | 490 | .ops = &iwl6050_ops, |
416 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 491 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
417 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 492 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
418 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 493 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 6aebcedaca8d..8bf7c20b9d39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
298 | struct iwl_lq_sta *lq_data, u8 tid, | 298 | struct iwl_lq_sta *lq_data, u8 tid, |
299 | struct ieee80211_sta *sta) | 299 | struct ieee80211_sta *sta) |
300 | { | 300 | { |
301 | int ret; | ||
302 | |||
301 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 303 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
302 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 304 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
303 | sta->addr, tid); | 305 | sta->addr, tid); |
304 | ieee80211_start_tx_ba_session(sta, tid); | 306 | ret = ieee80211_start_tx_ba_session(sta, tid); |
307 | if (ret == -EAGAIN) { | ||
308 | /* | ||
309 | * driver and mac80211 is out of sync | ||
310 | * this might be cause by reloading firmware | ||
311 | * stop the tx ba session here | ||
312 | */ | ||
313 | IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", | ||
314 | tid); | ||
315 | ret = ieee80211_stop_tx_ba_session(sta, tid, | ||
316 | WLAN_BACK_INITIATOR); | ||
317 | } | ||
305 | } | 318 | } |
306 | } | 319 | } |
307 | 320 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1854c720b5e0..af60b178ad4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2941 | return ret; | 2941 | return ret; |
2942 | case IEEE80211_AMPDU_TX_START: | 2942 | case IEEE80211_AMPDU_TX_START: |
2943 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2943 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2944 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2944 | ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); |
2945 | if (ret == 0) { | ||
2946 | priv->agg_tids_count++; | ||
2947 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2948 | priv->agg_tids_count); | ||
2949 | } | ||
2950 | return ret; | ||
2945 | case IEEE80211_AMPDU_TX_STOP: | 2951 | case IEEE80211_AMPDU_TX_STOP: |
2946 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2952 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2947 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 2953 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); |
2954 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | ||
2955 | priv->agg_tids_count--; | ||
2956 | IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", | ||
2957 | priv->agg_tids_count); | ||
2958 | } | ||
2948 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2959 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2949 | return 0; | 2960 | return 0; |
2950 | else | 2961 | else |
@@ -3353,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3353 | INIT_LIST_HEAD(&priv->free_frames); | 3364 | INIT_LIST_HEAD(&priv->free_frames); |
3354 | 3365 | ||
3355 | mutex_init(&priv->mutex); | 3366 | mutex_init(&priv->mutex); |
3367 | mutex_init(&priv->sync_cmd_mutex); | ||
3356 | 3368 | ||
3357 | /* Clear the driver's (not device's) station table */ | 3369 | /* Clear the driver's (not device's) station table */ |
3358 | iwl_clear_stations_table(priv); | 3370 | iwl_clear_stations_table(priv); |
@@ -3364,6 +3376,13 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3364 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3376 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3365 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; | 3377 | priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; |
3366 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3378 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3379 | priv->agg_tids_count = 0; | ||
3380 | |||
3381 | /* initialize force reset */ | ||
3382 | priv->force_reset[IWL_RF_RESET].reset_duration = | ||
3383 | IWL_DELAY_NEXT_FORCE_RF_RESET; | ||
3384 | priv->force_reset[IWL_FW_RESET].reset_duration = | ||
3385 | IWL_DELAY_NEXT_FORCE_FW_RELOAD; | ||
3367 | 3386 | ||
3368 | /* Choose which receivers/antennas to use */ | 3387 | /* Choose which receivers/antennas to use */ |
3369 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3388 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
@@ -3540,6 +3559,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3540 | */ | 3559 | */ |
3541 | spin_lock_init(&priv->reg_lock); | 3560 | spin_lock_init(&priv->reg_lock); |
3542 | spin_lock_init(&priv->lock); | 3561 | spin_lock_init(&priv->lock); |
3562 | |||
3563 | /* | ||
3564 | * stop and reset the on-board processor just in case it is in a | ||
3565 | * strange state ... like being left stranded by a primary kernel | ||
3566 | * and this is now the kdump kernel trying to start up | ||
3567 | */ | ||
3568 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
3569 | |||
3543 | iwl_hw_detect(priv); | 3570 | iwl_hw_detect(priv); |
3544 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", | 3571 | IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", |
3545 | priv->cfg->name, priv->hw_rev); | 3572 | priv->cfg->name, priv->hw_rev); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c2f31eb26bef..ab3c77b92cc8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -3470,11 +3470,7 @@ enum { | |||
3470 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, | 3470 | IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, |
3471 | IWL_PHY_CALIBRATE_DC_CMD = 8, | 3471 | IWL_PHY_CALIBRATE_DC_CMD = 8, |
3472 | IWL_PHY_CALIBRATE_LO_CMD = 9, | 3472 | IWL_PHY_CALIBRATE_LO_CMD = 9, |
3473 | IWL_PHY_CALIBRATE_RX_BB_CMD = 10, | ||
3474 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, | 3473 | IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, |
3475 | IWL_PHY_CALIBRATE_RX_IQ_CMD = 12, | ||
3476 | IWL_PHY_CALIBRATION_NOISE_CMD = 13, | ||
3477 | IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14, | ||
3478 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, | 3474 | IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, |
3479 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, | 3475 | IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, |
3480 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, | 3476 | IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 728410083cb8..112149e9b31e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power); | |||
1670 | void iwl_free_isr_ict(struct iwl_priv *priv) | 1670 | void iwl_free_isr_ict(struct iwl_priv *priv) |
1671 | { | 1671 | { |
1672 | if (priv->ict_tbl_vir) { | 1672 | if (priv->ict_tbl_vir) { |
1673 | pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) + | 1673 | dma_free_coherent(&priv->pci_dev->dev, |
1674 | PAGE_SIZE, priv->ict_tbl_vir, | 1674 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1675 | priv->ict_tbl_dma); | 1675 | priv->ict_tbl_vir, priv->ict_tbl_dma); |
1676 | priv->ict_tbl_vir = NULL; | 1676 | priv->ict_tbl_vir = NULL; |
1677 | } | 1677 | } |
1678 | } | 1678 | } |
@@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv) | |||
1688 | if (priv->cfg->use_isr_legacy) | 1688 | if (priv->cfg->use_isr_legacy) |
1689 | return 0; | 1689 | return 0; |
1690 | /* allocate shrared data table */ | 1690 | /* allocate shrared data table */ |
1691 | priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) * | 1691 | priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, |
1692 | ICT_COUNT) + PAGE_SIZE, | 1692 | (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, |
1693 | &priv->ict_tbl_dma); | 1693 | &priv->ict_tbl_dma, GFP_KERNEL); |
1694 | if (!priv->ict_tbl_vir) | 1694 | if (!priv->ict_tbl_vir) |
1695 | return -ENOMEM; | 1695 | return -ENOMEM; |
1696 | 1696 | ||
@@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | |||
3334 | } | 3334 | } |
3335 | EXPORT_SYMBOL(iwl_dump_fh); | 3335 | EXPORT_SYMBOL(iwl_dump_fh); |
3336 | 3336 | ||
3337 | void iwl_force_rf_reset(struct iwl_priv *priv) | 3337 | static void iwl_force_rf_reset(struct iwl_priv *priv) |
3338 | { | 3338 | { |
3339 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 3339 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
3340 | return; | 3340 | return; |
@@ -3356,7 +3356,50 @@ void iwl_force_rf_reset(struct iwl_priv *priv) | |||
3356 | iwl_internal_short_hw_scan(priv); | 3356 | iwl_internal_short_hw_scan(priv); |
3357 | return; | 3357 | return; |
3358 | } | 3358 | } |
3359 | EXPORT_SYMBOL(iwl_force_rf_reset); | 3359 | |
3360 | |||
3361 | int iwl_force_reset(struct iwl_priv *priv, int mode) | ||
3362 | { | ||
3363 | struct iwl_force_reset *force_reset; | ||
3364 | |||
3365 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
3366 | return -EINVAL; | ||
3367 | |||
3368 | if (mode >= IWL_MAX_FORCE_RESET) { | ||
3369 | IWL_DEBUG_INFO(priv, "invalid reset request.\n"); | ||
3370 | return -EINVAL; | ||
3371 | } | ||
3372 | force_reset = &priv->force_reset[mode]; | ||
3373 | force_reset->reset_request_count++; | ||
3374 | if (force_reset->last_force_reset_jiffies && | ||
3375 | time_after(force_reset->last_force_reset_jiffies + | ||
3376 | force_reset->reset_duration, jiffies)) { | ||
3377 | IWL_DEBUG_INFO(priv, "force reset rejected\n"); | ||
3378 | force_reset->reset_reject_count++; | ||
3379 | return -EAGAIN; | ||
3380 | } | ||
3381 | force_reset->reset_success_count++; | ||
3382 | force_reset->last_force_reset_jiffies = jiffies; | ||
3383 | IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); | ||
3384 | switch (mode) { | ||
3385 | case IWL_RF_RESET: | ||
3386 | iwl_force_rf_reset(priv); | ||
3387 | break; | ||
3388 | case IWL_FW_RESET: | ||
3389 | IWL_ERR(priv, "On demand firmware reload\n"); | ||
3390 | /* Set the FW error flag -- cleared on iwl_down */ | ||
3391 | set_bit(STATUS_FW_ERROR, &priv->status); | ||
3392 | wake_up_interruptible(&priv->wait_command_queue); | ||
3393 | /* | ||
3394 | * Keep the restart process from trying to send host | ||
3395 | * commands by clearing the INIT status bit | ||
3396 | */ | ||
3397 | clear_bit(STATUS_READY, &priv->status); | ||
3398 | queue_work(priv->workqueue, &priv->restart); | ||
3399 | break; | ||
3400 | } | ||
3401 | return 0; | ||
3402 | } | ||
3360 | 3403 | ||
3361 | #ifdef CONFIG_PM | 3404 | #ifdef CONFIG_PM |
3362 | 3405 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1b0701b876c3..4ef7739f9e8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -117,6 +117,7 @@ struct iwl_apm_ops { | |||
117 | struct iwl_temp_ops { | 117 | struct iwl_temp_ops { |
118 | void (*temperature)(struct iwl_priv *priv); | 118 | void (*temperature)(struct iwl_priv *priv); |
119 | void (*set_ct_kill)(struct iwl_priv *priv); | 119 | void (*set_ct_kill)(struct iwl_priv *priv); |
120 | void (*set_calib_version)(struct iwl_priv *priv); | ||
120 | }; | 121 | }; |
121 | 122 | ||
122 | struct iwl_ucode_ops { | 123 | struct iwl_ucode_ops { |
@@ -414,13 +415,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | |||
414 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 415 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
415 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 416 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
416 | void iwl_rx_handle(struct iwl_priv *priv); | 417 | void iwl_rx_handle(struct iwl_priv *priv); |
417 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 418 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
418 | struct iwl_rx_queue *q); | 419 | struct iwl_rx_queue *q); |
419 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 420 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
420 | void iwl_rx_replenish(struct iwl_priv *priv); | 421 | void iwl_rx_replenish(struct iwl_priv *priv); |
421 | void iwl_rx_replenish_now(struct iwl_priv *priv); | 422 | void iwl_rx_replenish_now(struct iwl_priv *priv); |
422 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 423 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
423 | int iwl_rx_queue_restock(struct iwl_priv *priv); | 424 | void iwl_rx_queue_restock(struct iwl_priv *priv); |
424 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 425 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
425 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | 426 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); |
426 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 427 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
@@ -450,9 +451,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | |||
450 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | 451 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); |
451 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 452 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
452 | struct iwl_tx_queue *txq); | 453 | struct iwl_tx_queue *txq); |
453 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
454 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 454 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
455 | int sta_id, int tid, int freed); | 455 | int sta_id, int tid, int freed); |
456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
456 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
457 | int slots_num, u32 txq_id); | 458 | int slots_num, u32 txq_id); |
458 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
@@ -503,7 +504,7 @@ int iwl_scan_cancel(struct iwl_priv *priv); | |||
503 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | 504 | int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); |
504 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); | 505 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); |
505 | int iwl_internal_short_hw_scan(struct iwl_priv *priv); | 506 | int iwl_internal_short_hw_scan(struct iwl_priv *priv); |
506 | void iwl_force_rf_reset(struct iwl_priv *priv); | 507 | int iwl_force_reset(struct iwl_priv *priv, int mode); |
507 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 508 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
508 | const u8 *ie, int ie_len, int left); | 509 | const u8 *ie, int ie_len, int left); |
509 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); | 510 | void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); |
@@ -605,7 +606,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
605 | /*************** DRIVER STATUS FUNCTIONS *****/ | 606 | /*************** DRIVER STATUS FUNCTIONS *****/ |
606 | 607 | ||
607 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | 608 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ |
608 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | 609 | /* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */ |
609 | #define STATUS_INT_ENABLED 2 | 610 | #define STATUS_INT_ENABLED 2 |
610 | #define STATUS_RF_KILL_HW 3 | 611 | #define STATUS_RF_KILL_HW 3 |
611 | #define STATUS_CT_KILL 4 | 612 | #define STATUS_CT_KILL 4 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 1e00720bf8b1..808b7146bead 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -369,7 +369,7 @@ | |||
369 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) | 369 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) |
370 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) | 370 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) |
371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | 371 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) |
372 | 372 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) | |
373 | 373 | ||
374 | /* GIO Chicken Bits (PCI Express bus link power management) */ | 374 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
375 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 375 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index d134301b553c..7bf44f146799 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -530,8 +530,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
530 | 530 | ||
531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", | 531 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", |
532 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); | 532 | test_bit(STATUS_HCMD_ACTIVE, &priv->status)); |
533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", | ||
534 | test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); | ||
535 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", | 533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", |
536 | test_bit(STATUS_INT_ENABLED, &priv->status)); | 534 | test_bit(STATUS_INT_ENABLED, &priv->status)); |
537 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 535 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
@@ -2223,6 +2221,62 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file, | |||
2223 | return count; | 2221 | return count; |
2224 | } | 2222 | } |
2225 | 2223 | ||
2224 | static ssize_t iwl_dbgfs_force_reset_read(struct file *file, | ||
2225 | char __user *user_buf, | ||
2226 | size_t count, loff_t *ppos) { | ||
2227 | |||
2228 | struct iwl_priv *priv = file->private_data; | ||
2229 | int i, pos = 0; | ||
2230 | char buf[300]; | ||
2231 | const size_t bufsz = sizeof(buf); | ||
2232 | struct iwl_force_reset *force_reset; | ||
2233 | |||
2234 | for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { | ||
2235 | force_reset = &priv->force_reset[i]; | ||
2236 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2237 | "Force reset method %d\n", i); | ||
2238 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2239 | "\tnumber of reset request: %d\n", | ||
2240 | force_reset->reset_request_count); | ||
2241 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2242 | "\tnumber of reset request success: %d\n", | ||
2243 | force_reset->reset_success_count); | ||
2244 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2245 | "\tnumber of reset request reject: %d\n", | ||
2246 | force_reset->reset_reject_count); | ||
2247 | pos += scnprintf(buf + pos, bufsz - pos, | ||
2248 | "\treset duration: %lu\n", | ||
2249 | force_reset->reset_duration); | ||
2250 | } | ||
2251 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2252 | } | ||
2253 | |||
2254 | static ssize_t iwl_dbgfs_force_reset_write(struct file *file, | ||
2255 | const char __user *user_buf, | ||
2256 | size_t count, loff_t *ppos) { | ||
2257 | |||
2258 | struct iwl_priv *priv = file->private_data; | ||
2259 | char buf[8]; | ||
2260 | int buf_size; | ||
2261 | int reset, ret; | ||
2262 | |||
2263 | memset(buf, 0, sizeof(buf)); | ||
2264 | buf_size = min(count, sizeof(buf) - 1); | ||
2265 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2266 | return -EFAULT; | ||
2267 | if (sscanf(buf, "%d", &reset) != 1) | ||
2268 | return -EINVAL; | ||
2269 | switch (reset) { | ||
2270 | case IWL_RF_RESET: | ||
2271 | case IWL_FW_RESET: | ||
2272 | ret = iwl_force_reset(priv, reset); | ||
2273 | break; | ||
2274 | default: | ||
2275 | return -EINVAL; | ||
2276 | } | ||
2277 | return ret ? ret : count; | ||
2278 | } | ||
2279 | |||
2226 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2280 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
2227 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2281 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
2228 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2282 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -2243,6 +2297,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg); | |||
2243 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); | 2297 | DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); |
2244 | DEBUGFS_WRITE_FILE_OPS(internal_scan); | 2298 | DEBUGFS_WRITE_FILE_OPS(internal_scan); |
2245 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); | 2299 | DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta); |
2300 | DEBUGFS_READ_WRITE_FILE_OPS(force_reset); | ||
2246 | 2301 | ||
2247 | /* | 2302 | /* |
2248 | * Create the debugfs files and directories | 2303 | * Create the debugfs files and directories |
@@ -2296,6 +2351,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2296 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); | 2351 | DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR); |
2297 | DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); | 2352 | DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR); |
2298 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); | 2353 | DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR); |
2354 | DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); | ||
2299 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 2355 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
2300 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); | 2356 | DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); |
2301 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); | 2357 | DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 55dc5a866542..7914d65a5a55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -1033,8 +1033,26 @@ struct iwl_event_log { | |||
1033 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) | 1033 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0) |
1034 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) | 1034 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50) |
1035 | #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) | 1035 | #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100) |
1036 | #define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200) | ||
1036 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) | 1037 | #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255) |
1037 | 1038 | ||
1039 | #define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3) | ||
1040 | #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5) | ||
1041 | |||
1042 | enum iwl_reset { | ||
1043 | IWL_RF_RESET = 0, | ||
1044 | IWL_FW_RESET, | ||
1045 | IWL_MAX_FORCE_RESET, | ||
1046 | }; | ||
1047 | |||
1048 | struct iwl_force_reset { | ||
1049 | int reset_request_count; | ||
1050 | int reset_success_count; | ||
1051 | int reset_reject_count; | ||
1052 | unsigned long reset_duration; | ||
1053 | unsigned long last_force_reset_jiffies; | ||
1054 | }; | ||
1055 | |||
1038 | struct iwl_priv { | 1056 | struct iwl_priv { |
1039 | 1057 | ||
1040 | /* ieee device used by generic ieee processing code */ | 1058 | /* ieee device used by generic ieee processing code */ |
@@ -1066,6 +1084,12 @@ struct iwl_priv { | |||
1066 | /* storing the jiffies when the plcp error rate is received */ | 1084 | /* storing the jiffies when the plcp error rate is received */ |
1067 | unsigned long plcp_jiffies; | 1085 | unsigned long plcp_jiffies; |
1068 | 1086 | ||
1087 | /* reporting the number of tids has AGG on. 0 means no AGGREGATION */ | ||
1088 | u8 agg_tids_count; | ||
1089 | |||
1090 | /* force reset */ | ||
1091 | struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; | ||
1092 | |||
1069 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. | 1093 | /* we allocate array of iwl4965_channel_info for NIC's valid channels. |
1070 | * Access via channel # using indirect index array */ | 1094 | * Access via channel # using indirect index array */ |
1071 | struct iwl_channel_info *channel_info; /* channel info array */ | 1095 | struct iwl_channel_info *channel_info; /* channel info array */ |
@@ -1087,7 +1111,6 @@ struct iwl_priv { | |||
1087 | unsigned long scan_start; | 1111 | unsigned long scan_start; |
1088 | unsigned long scan_pass_start; | 1112 | unsigned long scan_pass_start; |
1089 | unsigned long scan_start_tsf; | 1113 | unsigned long scan_start_tsf; |
1090 | unsigned long last_internal_scan_jiffies; | ||
1091 | void *scan; | 1114 | void *scan; |
1092 | int scan_bands; | 1115 | int scan_bands; |
1093 | struct cfg80211_scan_request *scan_request; | 1116 | struct cfg80211_scan_request *scan_request; |
@@ -1100,6 +1123,7 @@ struct iwl_priv { | |||
1100 | spinlock_t hcmd_lock; /* protect hcmd */ | 1123 | spinlock_t hcmd_lock; /* protect hcmd */ |
1101 | spinlock_t reg_lock; /* protect hw register access */ | 1124 | spinlock_t reg_lock; /* protect hw register access */ |
1102 | struct mutex mutex; | 1125 | struct mutex mutex; |
1126 | struct mutex sync_cmd_mutex; /* enable serialization of sync commands */ | ||
1103 | 1127 | ||
1104 | /* basic pci-network driver stuff */ | 1128 | /* basic pci-network driver stuff */ |
1105 | struct pci_dev *pci_dev; | 1129 | struct pci_dev *pci_dev; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 86783c27d97c..73681c4fefe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -164,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
164 | /* A synchronous command can not have a callback set. */ | 164 | /* A synchronous command can not have a callback set. */ |
165 | BUG_ON(cmd->callback); | 165 | BUG_ON(cmd->callback); |
166 | 166 | ||
167 | if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { | 167 | IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n", |
168 | IWL_ERR(priv, | ||
169 | "Error sending %s: Already sending a host command\n", | ||
170 | get_cmd_string(cmd->id)); | 168 | get_cmd_string(cmd->id)); |
171 | ret = -EBUSY; | 169 | mutex_lock(&priv->sync_cmd_mutex); |
172 | goto out; | ||
173 | } | ||
174 | 170 | ||
175 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); | 171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", | ||
173 | get_cmd_string(cmd->id)); | ||
176 | 174 | ||
177 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
178 | if (cmd_idx < 0) { | 176 | if (cmd_idx < 0) { |
@@ -193,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
193 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
194 | 192 | ||
195 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | ||
195 | get_cmd_string(cmd->id)); | ||
196 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
197 | goto cancel; | 197 | goto cancel; |
198 | } | 198 | } |
@@ -237,7 +237,7 @@ fail: | |||
237 | cmd->reply_page = 0; | 237 | cmd->reply_page = 0; |
238 | } | 238 | } |
239 | out: | 239 | out: |
240 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); | 240 | mutex_unlock(&priv->sync_cmd_mutex); |
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | EXPORT_SYMBOL(iwl_send_cmd_sync); | 243 | EXPORT_SYMBOL(iwl_send_cmd_sync); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 45af5bbc1c56..51a67fb2e185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h | |||
@@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
80 | struct fw_desc *desc) | 80 | struct fw_desc *desc) |
81 | { | 81 | { |
82 | if (desc->v_addr) | 82 | if (desc->v_addr) |
83 | pci_free_consistent(pci_dev, desc->len, | 83 | dma_free_coherent(&pci_dev->dev, desc->len, |
84 | desc->v_addr, desc->p_addr); | 84 | desc->v_addr, desc->p_addr); |
85 | desc->v_addr = NULL; | 85 | desc->v_addr = NULL; |
86 | desc->len = 0; | 86 | desc->len = 0; |
87 | } | 87 | } |
@@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, | |||
89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, | 89 | static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, |
90 | struct fw_desc *desc) | 90 | struct fw_desc *desc) |
91 | { | 91 | { |
92 | desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr); | 92 | desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, |
93 | &desc->p_addr, GFP_KERNEL); | ||
93 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; | 94 | return (desc->v_addr != NULL) ? 0 : -ENOMEM; |
94 | } | 95 | } |
95 | 96 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0f718f6df5fd..0d09f571e185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); | |||
123 | /** | 123 | /** |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
125 | */ | 125 | */ |
126 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | 126 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
127 | { | 127 | { |
128 | unsigned long flags; | 128 | unsigned long flags; |
129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; | 129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; |
130 | u32 reg; | 130 | u32 reg; |
131 | int ret = 0; | ||
132 | 131 | ||
133 | spin_lock_irqsave(&q->lock, flags); | 132 | spin_lock_irqsave(&q->lock, flags); |
134 | 133 | ||
@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
161 | 160 | ||
162 | exit_unlock: | 161 | exit_unlock: |
163 | spin_unlock_irqrestore(&q->lock, flags); | 162 | spin_unlock_irqrestore(&q->lock, flags); |
164 | return ret; | ||
165 | } | 163 | } |
166 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
167 | /** | 165 | /** |
@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
184 | * also updates the memory address in the firmware to reference the new | 182 | * also updates the memory address in the firmware to reference the new |
185 | * target buffer. | 183 | * target buffer. |
186 | */ | 184 | */ |
187 | int iwl_rx_queue_restock(struct iwl_priv *priv) | 185 | void iwl_rx_queue_restock(struct iwl_priv *priv) |
188 | { | 186 | { |
189 | struct iwl_rx_queue *rxq = &priv->rxq; | 187 | struct iwl_rx_queue *rxq = &priv->rxq; |
190 | struct list_head *element; | 188 | struct list_head *element; |
191 | struct iwl_rx_mem_buffer *rxb; | 189 | struct iwl_rx_mem_buffer *rxb; |
192 | unsigned long flags; | 190 | unsigned long flags; |
193 | int write; | 191 | int write; |
194 | int ret = 0; | ||
195 | 192 | ||
196 | spin_lock_irqsave(&rxq->lock, flags); | 193 | spin_lock_irqsave(&rxq->lock, flags); |
197 | write = rxq->write & ~0x7; | 194 | write = rxq->write & ~0x7; |
@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
220 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
221 | rxq->need_update = 1; | 218 | rxq->need_update = 1; |
222 | spin_unlock_irqrestore(&rxq->lock, flags); | 219 | spin_unlock_irqrestore(&rxq->lock, flags); |
223 | ret = iwl_rx_queue_update_write_ptr(priv, rxq); | 220 | iwl_rx_queue_update_write_ptr(priv, rxq); |
224 | } | 221 | } |
225 | |||
226 | return ret; | ||
227 | } | 222 | } |
228 | EXPORT_SYMBOL(iwl_rx_queue_restock); | 223 | EXPORT_SYMBOL(iwl_rx_queue_restock); |
229 | 224 | ||
@@ -350,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
350 | } | 345 | } |
351 | } | 346 | } |
352 | 347 | ||
353 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 348 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
354 | rxq->dma_addr); | 349 | rxq->dma_addr); |
355 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 350 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
356 | rxq->rb_stts, rxq->rb_stts_dma); | 351 | rxq->rb_stts, rxq->rb_stts_dma); |
357 | rxq->bd = NULL; | 352 | rxq->bd = NULL; |
358 | rxq->rb_stts = NULL; | 353 | rxq->rb_stts = NULL; |
359 | } | 354 | } |
@@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); | |||
362 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 357 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
363 | { | 358 | { |
364 | struct iwl_rx_queue *rxq = &priv->rxq; | 359 | struct iwl_rx_queue *rxq = &priv->rxq; |
365 | struct pci_dev *dev = priv->pci_dev; | 360 | struct device *dev = &priv->pci_dev->dev; |
366 | int i; | 361 | int i; |
367 | 362 | ||
368 | spin_lock_init(&rxq->lock); | 363 | spin_lock_init(&rxq->lock); |
@@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
370 | INIT_LIST_HEAD(&rxq->rx_used); | 365 | INIT_LIST_HEAD(&rxq->rx_used); |
371 | 366 | ||
372 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 367 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
373 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 368 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, |
369 | GFP_KERNEL); | ||
374 | if (!rxq->bd) | 370 | if (!rxq->bd) |
375 | goto err_bd; | 371 | goto err_bd; |
376 | 372 | ||
377 | rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), | 373 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), |
378 | &rxq->rb_stts_dma); | 374 | &rxq->rb_stts_dma, GFP_KERNEL); |
379 | if (!rxq->rb_stts) | 375 | if (!rxq->rb_stts) |
380 | goto err_rb; | 376 | goto err_rb; |
381 | 377 | ||
@@ -392,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
392 | return 0; | 388 | return 0; |
393 | 389 | ||
394 | err_rb: | 390 | err_rb: |
395 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 391 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
396 | rxq->dma_addr); | 392 | rxq->dma_addr); |
397 | err_bd: | 393 | err_bd: |
398 | return -ENOMEM; | 394 | return -ENOMEM; |
399 | } | 395 | } |
@@ -620,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
620 | 616 | ||
621 | #define REG_RECALIB_PERIOD (60) | 617 | #define REG_RECALIB_PERIOD (60) |
622 | 618 | ||
619 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
620 | #define ACK_CNT_RATIO (50) | ||
621 | #define BA_TIMEOUT_CNT (5) | ||
622 | #define BA_TIMEOUT_MAX (16) | ||
623 | |||
623 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | 624 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" |
624 | void iwl_rx_statistics(struct iwl_priv *priv, | 625 | void iwl_rx_statistics(struct iwl_priv *priv, |
625 | struct iwl_rx_mem_buffer *rxb) | 626 | struct iwl_rx_mem_buffer *rxb) |
@@ -629,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
629 | int combined_plcp_delta; | 630 | int combined_plcp_delta; |
630 | unsigned int plcp_msec; | 631 | unsigned int plcp_msec; |
631 | unsigned long plcp_received_jiffies; | 632 | unsigned long plcp_received_jiffies; |
633 | int actual_ack_cnt_delta; | ||
634 | int expected_ack_cnt_delta; | ||
635 | int ba_timeout_delta; | ||
632 | 636 | ||
633 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 637 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
634 | (int)sizeof(priv->statistics), | 638 | (int)sizeof(priv->statistics), |
@@ -643,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
643 | #ifdef CONFIG_IWLWIFI_DEBUG | 647 | #ifdef CONFIG_IWLWIFI_DEBUG |
644 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | 648 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); |
645 | #endif | 649 | #endif |
650 | actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
651 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
652 | expected_ack_cnt_delta = le32_to_cpu( | ||
653 | pkt->u.stats.tx.expected_ack_cnt) - | ||
654 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
655 | ba_timeout_delta = le32_to_cpu( | ||
656 | pkt->u.stats.tx.agg.ba_timeout) - | ||
657 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
658 | if ((priv->agg_tids_count > 0) && | ||
659 | (expected_ack_cnt_delta > 0) && | ||
660 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < | ||
661 | ACK_CNT_RATIO) && | ||
662 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
663 | IWL_DEBUG_RADIO(priv, | ||
664 | "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", | ||
665 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
666 | |||
667 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
668 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
669 | priv->delta_statistics.tx.rx_detected_cnt); | ||
670 | IWL_DEBUG_RADIO(priv, | ||
671 | "ack_or_ba_timeout_collision delta = %d\n", | ||
672 | priv->delta_statistics.tx.ack_or_ba_timeout_collision); | ||
673 | #endif | ||
674 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
675 | ba_timeout_delta); | ||
676 | if ((actual_ack_cnt_delta == 0) && | ||
677 | (ba_timeout_delta >= | ||
678 | BA_TIMEOUT_MAX)) { | ||
679 | IWL_DEBUG_RADIO(priv, | ||
680 | "call iwl_force_reset(IWL_FW_RESET)\n"); | ||
681 | iwl_force_reset(priv, IWL_FW_RESET); | ||
682 | } else { | ||
683 | IWL_DEBUG_RADIO(priv, | ||
684 | "call iwl_force_reset(IWL_RF_RESET)\n"); | ||
685 | iwl_force_reset(priv, IWL_RF_RESET); | ||
686 | } | ||
687 | } | ||
646 | /* | 688 | /* |
647 | * check for plcp_err and trigger radio reset if it exceeds | 689 | * check for plcp_err and trigger radio reset if it exceeds |
648 | * the plcp error threshold plcp_delta. | 690 | * the plcp error threshold plcp_delta. |
@@ -689,7 +731,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
689 | * Reset the RF radio due to the high plcp | 731 | * Reset the RF radio due to the high plcp |
690 | * error rate | 732 | * error rate |
691 | */ | 733 | */ |
692 | iwl_force_rf_reset(priv); | 734 | iwl_force_reset(priv, IWL_RF_RESET); |
693 | } | 735 | } |
694 | } | 736 | } |
695 | 737 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index f786a407638f..dd9ff2ed645a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
250 | 250 | ||
251 | if (!priv->is_internal_short_scan) | 251 | if (!priv->is_internal_short_scan) |
252 | priv->next_scan_jiffies = 0; | 252 | priv->next_scan_jiffies = 0; |
253 | else | ||
254 | priv->last_internal_scan_jiffies = jiffies; | ||
255 | 253 | ||
256 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); | 254 | IWL_DEBUG_INFO(priv, "Setting scan to off\n"); |
257 | 255 | ||
@@ -471,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params); | |||
471 | 469 | ||
472 | static int iwl_scan_initiate(struct iwl_priv *priv) | 470 | static int iwl_scan_initiate(struct iwl_priv *priv) |
473 | { | 471 | { |
474 | if (!iwl_is_ready_rf(priv)) { | ||
475 | IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n"); | ||
476 | return -EIO; | ||
477 | } | ||
478 | |||
479 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
480 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
481 | return -EAGAIN; | ||
482 | } | ||
483 | |||
484 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
485 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
486 | return -EAGAIN; | ||
487 | } | ||
488 | |||
489 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 472 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
490 | set_bit(STATUS_SCANNING, &priv->status); | 473 | set_bit(STATUS_SCANNING, &priv->status); |
491 | priv->is_internal_short_scan = false; | 474 | priv->is_internal_short_scan = false; |
@@ -517,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
517 | goto out_unlock; | 500 | goto out_unlock; |
518 | } | 501 | } |
519 | 502 | ||
503 | if (test_bit(STATUS_SCANNING, &priv->status)) { | ||
504 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
505 | ret = -EAGAIN; | ||
506 | goto out_unlock; | ||
507 | } | ||
508 | |||
509 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
510 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
511 | ret = -EAGAIN; | ||
512 | goto out_unlock; | ||
513 | } | ||
514 | |||
520 | /* We don't schedule scan within next_scan_jiffies period. | 515 | /* We don't schedule scan within next_scan_jiffies period. |
521 | * Avoid scanning during possible EAPOL exchange, return | 516 | * Avoid scanning during possible EAPOL exchange, return |
522 | * success immediately. | 517 | * success immediately. |
@@ -551,8 +546,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); | |||
551 | * internal short scan, this function should only been called while associated. | 546 | * internal short scan, this function should only been called while associated. |
552 | * It will reset and tune the radio to prevent possible RF related problem | 547 | * It will reset and tune the radio to prevent possible RF related problem |
553 | */ | 548 | */ |
554 | #define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1) | ||
555 | |||
556 | int iwl_internal_short_hw_scan(struct iwl_priv *priv) | 549 | int iwl_internal_short_hw_scan(struct iwl_priv *priv) |
557 | { | 550 | { |
558 | int ret = 0; | 551 | int ret = 0; |
@@ -572,12 +565,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
572 | ret = -EAGAIN; | 565 | ret = -EAGAIN; |
573 | goto out; | 566 | goto out; |
574 | } | 567 | } |
575 | if (priv->last_internal_scan_jiffies && | ||
576 | time_after(priv->last_internal_scan_jiffies + | ||
577 | IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) { | ||
578 | IWL_DEBUG_SCAN(priv, "internal scan rejected\n"); | ||
579 | goto out; | ||
580 | } | ||
581 | 568 | ||
582 | priv->scan_bands = 0; | 569 | priv->scan_bands = 0; |
583 | if (priv->band == IEEE80211_BAND_5GHZ) | 570 | if (priv->band == IEEE80211_BAND_5GHZ) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 6eff3d4d0616..10701b8eef23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | 60 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, |
61 | struct iwl_dma_ptr *ptr, size_t size) | 61 | struct iwl_dma_ptr *ptr, size_t size) |
62 | { | 62 | { |
63 | ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); | 63 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, |
64 | GFP_KERNEL); | ||
64 | if (!ptr->addr) | 65 | if (!ptr->addr) |
65 | return -ENOMEM; | 66 | return -ENOMEM; |
66 | ptr->size = size; | 67 | ptr->size = size; |
@@ -73,21 +74,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | |||
73 | if (unlikely(!ptr->addr)) | 74 | if (unlikely(!ptr->addr)) |
74 | return; | 75 | return; |
75 | 76 | ||
76 | pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); | 77 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); |
77 | memset(ptr, 0, sizeof(*ptr)); | 78 | memset(ptr, 0, sizeof(*ptr)); |
78 | } | 79 | } |
79 | 80 | ||
80 | /** | 81 | /** |
81 | * iwl_txq_update_write_ptr - Send new write index to hardware | 82 | * iwl_txq_update_write_ptr - Send new write index to hardware |
82 | */ | 83 | */ |
83 | int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | 84 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) |
84 | { | 85 | { |
85 | u32 reg = 0; | 86 | u32 reg = 0; |
86 | int ret = 0; | ||
87 | int txq_id = txq->q.id; | 87 | int txq_id = txq->q.id; |
88 | 88 | ||
89 | if (txq->need_update == 0) | 89 | if (txq->need_update == 0) |
90 | return ret; | 90 | return; |
91 | 91 | ||
92 | /* if we're trying to save power */ | 92 | /* if we're trying to save power */ |
93 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | 93 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { |
@@ -101,7 +101,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
101 | txq_id, reg); | 101 | txq_id, reg); |
102 | iwl_set_bit(priv, CSR_GP_CNTRL, | 102 | iwl_set_bit(priv, CSR_GP_CNTRL, |
103 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | 103 | CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
104 | return ret; | 104 | return; |
105 | } | 105 | } |
106 | 106 | ||
107 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | 107 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, |
@@ -114,8 +114,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
114 | txq->q.write_ptr | (txq_id << 8)); | 114 | txq->q.write_ptr | (txq_id << 8)); |
115 | 115 | ||
116 | txq->need_update = 0; | 116 | txq->need_update = 0; |
117 | |||
118 | return ret; | ||
119 | } | 117 | } |
120 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); | 118 | EXPORT_SYMBOL(iwl_txq_update_write_ptr); |
121 | 119 | ||
@@ -146,7 +144,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
146 | { | 144 | { |
147 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 145 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
148 | struct iwl_queue *q = &txq->q; | 146 | struct iwl_queue *q = &txq->q; |
149 | struct pci_dev *dev = priv->pci_dev; | 147 | struct device *dev = &priv->pci_dev->dev; |
150 | int i; | 148 | int i; |
151 | 149 | ||
152 | if (q->n_bd == 0) | 150 | if (q->n_bd == 0) |
@@ -163,8 +161,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
163 | 161 | ||
164 | /* De-alloc circular buffer of TFDs */ | 162 | /* De-alloc circular buffer of TFDs */ |
165 | if (txq->q.n_bd) | 163 | if (txq->q.n_bd) |
166 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 164 | dma_free_coherent(dev, priv->hw_params.tfd_size * |
167 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 165 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
168 | 166 | ||
169 | /* De-alloc array of per-TFD driver data */ | 167 | /* De-alloc array of per-TFD driver data */ |
170 | kfree(txq->txb); | 168 | kfree(txq->txb); |
@@ -193,7 +191,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
193 | { | 191 | { |
194 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | 192 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; |
195 | struct iwl_queue *q = &txq->q; | 193 | struct iwl_queue *q = &txq->q; |
196 | struct pci_dev *dev = priv->pci_dev; | 194 | struct device *dev = &priv->pci_dev->dev; |
197 | int i; | 195 | int i; |
198 | 196 | ||
199 | if (q->n_bd == 0) | 197 | if (q->n_bd == 0) |
@@ -205,8 +203,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
205 | 203 | ||
206 | /* De-alloc circular buffer of TFDs */ | 204 | /* De-alloc circular buffer of TFDs */ |
207 | if (txq->q.n_bd) | 205 | if (txq->q.n_bd) |
208 | pci_free_consistent(dev, priv->hw_params.tfd_size * | 206 | dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, |
209 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 207 | txq->tfds, txq->q.dma_addr); |
210 | 208 | ||
211 | /* deallocate arrays */ | 209 | /* deallocate arrays */ |
212 | kfree(txq->cmd); | 210 | kfree(txq->cmd); |
@@ -297,7 +295,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, | |||
297 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, | 295 | static int iwl_tx_queue_alloc(struct iwl_priv *priv, |
298 | struct iwl_tx_queue *txq, u32 id) | 296 | struct iwl_tx_queue *txq, u32 id) |
299 | { | 297 | { |
300 | struct pci_dev *dev = priv->pci_dev; | 298 | struct device *dev = &priv->pci_dev->dev; |
301 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; | 299 | size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; |
302 | 300 | ||
303 | /* Driver private data, only for Tx (not command) queues, | 301 | /* Driver private data, only for Tx (not command) queues, |
@@ -316,8 +314,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv, | |||
316 | 314 | ||
317 | /* Circular buffer of transmit frame descriptors (TFDs), | 315 | /* Circular buffer of transmit frame descriptors (TFDs), |
318 | * shared with device */ | 316 | * shared with device */ |
319 | txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr); | 317 | txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, |
320 | 318 | GFP_KERNEL); | |
321 | if (!txq->tfds) { | 319 | if (!txq->tfds) { |
322 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); | 320 | IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); |
323 | goto error; | 321 | goto error; |
@@ -745,7 +743,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
745 | u8 tid = 0; | 743 | u8 tid = 0; |
746 | u8 *qc = NULL; | 744 | u8 *qc = NULL; |
747 | unsigned long flags; | 745 | unsigned long flags; |
748 | int ret; | ||
749 | 746 | ||
750 | spin_lock_irqsave(&priv->lock, flags); | 747 | spin_lock_irqsave(&priv->lock, flags); |
751 | if (iwl_is_rfkill(priv)) { | 748 | if (iwl_is_rfkill(priv)) { |
@@ -820,8 +817,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
820 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | 817 | hdr->seq_ctrl |= cpu_to_le16(seq_number); |
821 | seq_number += 0x10; | 818 | seq_number += 0x10; |
822 | /* aggregation is on for this <sta,tid> */ | 819 | /* aggregation is on for this <sta,tid> */ |
823 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 820 | if (info->flags & IEEE80211_TX_CTL_AMPDU && |
821 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
824 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | 822 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; |
823 | } | ||
825 | } | 824 | } |
826 | 825 | ||
827 | txq = &priv->txq[txq_id]; | 826 | txq = &priv->txq[txq_id]; |
@@ -963,7 +962,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
963 | 962 | ||
964 | /* Tell device the write index *just past* this latest filled TFD */ | 963 | /* Tell device the write index *just past* this latest filled TFD */ |
965 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 964 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
966 | ret = iwl_txq_update_write_ptr(priv, txq); | 965 | iwl_txq_update_write_ptr(priv, txq); |
967 | spin_unlock_irqrestore(&priv->lock, flags); | 966 | spin_unlock_irqrestore(&priv->lock, flags); |
968 | 967 | ||
969 | /* | 968 | /* |
@@ -977,9 +976,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
977 | if (sta_priv && sta_priv->client) | 976 | if (sta_priv && sta_priv->client) |
978 | atomic_inc(&sta_priv->pending_frames); | 977 | atomic_inc(&sta_priv->pending_frames); |
979 | 978 | ||
980 | if (ret) | ||
981 | return ret; | ||
982 | |||
983 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | 979 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { |
984 | if (wait_write_ptr) { | 980 | if (wait_write_ptr) { |
985 | spin_lock_irqsave(&priv->lock, flags); | 981 | spin_lock_irqsave(&priv->lock, flags); |
@@ -1018,7 +1014,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1018 | struct iwl_cmd_meta *out_meta; | 1014 | struct iwl_cmd_meta *out_meta; |
1019 | dma_addr_t phys_addr; | 1015 | dma_addr_t phys_addr; |
1020 | unsigned long flags; | 1016 | unsigned long flags; |
1021 | int len, ret; | 1017 | int len; |
1022 | u32 idx; | 1018 | u32 idx; |
1023 | u16 fix_size; | 1019 | u16 fix_size; |
1024 | 1020 | ||
@@ -1115,10 +1111,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1115 | 1111 | ||
1116 | /* Increment and update queue's write index */ | 1112 | /* Increment and update queue's write index */ |
1117 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 1113 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
1118 | ret = iwl_txq_update_write_ptr(priv, txq); | 1114 | iwl_txq_update_write_ptr(priv, txq); |
1119 | 1115 | ||
1120 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 1116 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
1121 | return ret ? ret : idx; | 1117 | return idx; |
1122 | } | 1118 | } |
1123 | 1119 | ||
1124 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | 1120 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) |
@@ -1260,6 +1256,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1260 | 1256 | ||
1261 | if (!(meta->flags & CMD_ASYNC)) { | 1257 | if (!(meta->flags & CMD_ASYNC)) { |
1262 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1258 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1259 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | ||
1260 | get_cmd_string(cmd->hdr.cmd)); | ||
1263 | wake_up_interruptible(&priv->wait_command_queue); | 1261 | wake_up_interruptible(&priv->wait_command_queue); |
1264 | } | 1262 | } |
1265 | } | 1263 | } |
@@ -1346,7 +1344,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1346 | { | 1344 | { |
1347 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | 1345 | int tx_fifo_id, txq_id, sta_id, ssn = -1; |
1348 | struct iwl_tid_data *tid_data; | 1346 | struct iwl_tid_data *tid_data; |
1349 | int ret, write_ptr, read_ptr; | 1347 | int write_ptr, read_ptr; |
1350 | unsigned long flags; | 1348 | unsigned long flags; |
1351 | 1349 | ||
1352 | if (!ra) { | 1350 | if (!ra) { |
@@ -1398,13 +1396,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1398 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | 1396 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; |
1399 | 1397 | ||
1400 | spin_lock_irqsave(&priv->lock, flags); | 1398 | spin_lock_irqsave(&priv->lock, flags); |
1401 | ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | 1399 | /* |
1400 | * the only reason this call can fail is queue number out of range, | ||
1401 | * which can happen if uCode is reloaded and all the station | ||
1402 | * information are lost. if it is outside the range, there is no need | ||
1403 | * to deactivate the uCode queue, just return "success" to allow | ||
1404 | * mac80211 to clean up it own data. | ||
1405 | */ | ||
1406 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1402 | tx_fifo_id); | 1407 | tx_fifo_id); |
1403 | spin_unlock_irqrestore(&priv->lock, flags); | 1408 | spin_unlock_irqrestore(&priv->lock, flags); |
1404 | 1409 | ||
1405 | if (ret) | ||
1406 | return ret; | ||
1407 | |||
1408 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | 1410 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1409 | 1411 | ||
1410 | return 0; | 1412 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index eac2b9a95711..54daa38ecba3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -53,8 +53,8 @@ | |||
53 | #include "iwl-commands.h" | 53 | #include "iwl-commands.h" |
54 | #include "iwl-sta.h" | 54 | #include "iwl-sta.h" |
55 | #include "iwl-3945.h" | 55 | #include "iwl-3945.h" |
56 | #include "iwl-helpers.h" | ||
57 | #include "iwl-core.h" | 56 | #include "iwl-core.h" |
57 | #include "iwl-helpers.h" | ||
58 | #include "iwl-dev.h" | 58 | #include "iwl-dev.h" |
59 | #include "iwl-spectrum.h" | 59 | #include "iwl-spectrum.h" |
60 | 60 | ||
@@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) | |||
352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) | 352 | static void iwl3945_unset_hw_params(struct iwl_priv *priv) |
353 | { | 353 | { |
354 | if (priv->shared_virt) | 354 | if (priv->shared_virt) |
355 | pci_free_consistent(priv->pci_dev, | 355 | dma_free_coherent(&priv->pci_dev->dev, |
356 | sizeof(struct iwl3945_shared), | 356 | sizeof(struct iwl3945_shared), |
357 | priv->shared_virt, | 357 | priv->shared_virt, |
358 | priv->shared_phys); | 358 | priv->shared_phys); |
359 | } | 359 | } |
360 | 360 | ||
361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | 361 | static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, |
@@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
478 | u8 wait_write_ptr = 0; | 478 | u8 wait_write_ptr = 0; |
479 | u8 *qc = NULL; | 479 | u8 *qc = NULL; |
480 | unsigned long flags; | 480 | unsigned long flags; |
481 | int rc; | ||
482 | 481 | ||
483 | spin_lock_irqsave(&priv->lock, flags); | 482 | spin_lock_irqsave(&priv->lock, flags); |
484 | if (iwl_is_rfkill(priv)) { | 483 | if (iwl_is_rfkill(priv)) { |
@@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
663 | 662 | ||
664 | /* Tell device the write index *just past* this latest filled TFD */ | 663 | /* Tell device the write index *just past* this latest filled TFD */ |
665 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 664 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
666 | rc = iwl_txq_update_write_ptr(priv, txq); | 665 | iwl_txq_update_write_ptr(priv, txq); |
667 | spin_unlock_irqrestore(&priv->lock, flags); | 666 | spin_unlock_irqrestore(&priv->lock, flags); |
668 | 667 | ||
669 | if (rc) | ||
670 | return rc; | ||
671 | |||
672 | if ((iwl_queue_space(q) < q->high_mark) | 668 | if ((iwl_queue_space(q) < q->high_mark) |
673 | && priv->mac80211_registered) { | 669 | && priv->mac80211_registered) { |
674 | if (wait_write_ptr) { | 670 | if (wait_write_ptr) { |
@@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
1063 | * also updates the memory address in the firmware to reference the new | 1059 | * also updates the memory address in the firmware to reference the new |
1064 | * target buffer. | 1060 | * target buffer. |
1065 | */ | 1061 | */ |
1066 | static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | 1062 | static void iwl3945_rx_queue_restock(struct iwl_priv *priv) |
1067 | { | 1063 | { |
1068 | struct iwl_rx_queue *rxq = &priv->rxq; | 1064 | struct iwl_rx_queue *rxq = &priv->rxq; |
1069 | struct list_head *element; | 1065 | struct list_head *element; |
1070 | struct iwl_rx_mem_buffer *rxb; | 1066 | struct iwl_rx_mem_buffer *rxb; |
1071 | unsigned long flags; | 1067 | unsigned long flags; |
1072 | int write, rc; | 1068 | int write; |
1073 | 1069 | ||
1074 | spin_lock_irqsave(&rxq->lock, flags); | 1070 | spin_lock_irqsave(&rxq->lock, flags); |
1075 | write = rxq->write & ~0x7; | 1071 | write = rxq->write & ~0x7; |
@@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1099 | spin_lock_irqsave(&rxq->lock, flags); | 1095 | spin_lock_irqsave(&rxq->lock, flags); |
1100 | rxq->need_update = 1; | 1096 | rxq->need_update = 1; |
1101 | spin_unlock_irqrestore(&rxq->lock, flags); | 1097 | spin_unlock_irqrestore(&rxq->lock, flags); |
1102 | rc = iwl_rx_queue_update_write_ptr(priv, rxq); | 1098 | iwl_rx_queue_update_write_ptr(priv, rxq); |
1103 | if (rc) | ||
1104 | return rc; | ||
1105 | } | 1099 | } |
1106 | |||
1107 | return 0; | ||
1108 | } | 1100 | } |
1109 | 1101 | ||
1110 | /** | 1102 | /** |
@@ -1249,10 +1241,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1249 | } | 1241 | } |
1250 | } | 1242 | } |
1251 | 1243 | ||
1252 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 1244 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
1253 | rxq->dma_addr); | 1245 | rxq->dma_addr); |
1254 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 1246 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
1255 | rxq->rb_stts, rxq->rb_stts_dma); | 1247 | rxq->rb_stts, rxq->rb_stts_dma); |
1256 | rxq->bd = NULL; | 1248 | rxq->bd = NULL; |
1257 | rxq->rb_stts = NULL; | 1249 | rxq->rb_stts = NULL; |
1258 | } | 1250 | } |
@@ -3855,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3855 | INIT_LIST_HEAD(&priv->free_frames); | 3847 | INIT_LIST_HEAD(&priv->free_frames); |
3856 | 3848 | ||
3857 | mutex_init(&priv->mutex); | 3849 | mutex_init(&priv->mutex); |
3850 | mutex_init(&priv->sync_cmd_mutex); | ||
3858 | 3851 | ||
3859 | /* Clear the driver's (not device's) station table */ | 3852 | /* Clear the driver's (not device's) station table */ |
3860 | iwl_clear_stations_table(priv); | 3853 | iwl_clear_stations_table(priv); |
@@ -4047,6 +4040,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4047 | spin_lock_init(&priv->reg_lock); | 4040 | spin_lock_init(&priv->reg_lock); |
4048 | spin_lock_init(&priv->lock); | 4041 | spin_lock_init(&priv->lock); |
4049 | 4042 | ||
4043 | /* | ||
4044 | * stop and reset the on-board processor just in case it is in a | ||
4045 | * strange state ... like being left stranded by a primary kernel | ||
4046 | * and this is now the kdump kernel trying to start up | ||
4047 | */ | ||
4048 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
4049 | |||
4050 | /*********************** | 4050 | /*********************** |
4051 | * 4. Read EEPROM | 4051 | * 4. Read EEPROM |
4052 | * ********************/ | 4052 | * ********************/ |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 00ffe6dd435e..6ea77e95277b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -771,23 +771,41 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
771 | } | 771 | } |
772 | } | 772 | } |
773 | 773 | ||
774 | static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw, | ||
775 | struct ieee80211_vif *vif, | ||
776 | struct ieee80211_sta *sta) | ||
777 | { | ||
778 | hwsim_check_magic(vif); | ||
779 | hwsim_set_sta_magic(sta); | ||
780 | |||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw, | ||
785 | struct ieee80211_vif *vif, | ||
786 | struct ieee80211_sta *sta) | ||
787 | { | ||
788 | hwsim_check_magic(vif); | ||
789 | hwsim_clear_sta_magic(sta); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
774 | static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, | 794 | static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, |
775 | struct ieee80211_vif *vif, | 795 | struct ieee80211_vif *vif, |
776 | enum sta_notify_cmd cmd, | 796 | enum sta_notify_cmd cmd, |
777 | struct ieee80211_sta *sta) | 797 | struct ieee80211_sta *sta) |
778 | { | 798 | { |
779 | hwsim_check_magic(vif); | 799 | hwsim_check_magic(vif); |
800 | |||
780 | switch (cmd) { | 801 | switch (cmd) { |
781 | case STA_NOTIFY_ADD: | ||
782 | hwsim_set_sta_magic(sta); | ||
783 | break; | ||
784 | case STA_NOTIFY_REMOVE: | ||
785 | hwsim_clear_sta_magic(sta); | ||
786 | break; | ||
787 | case STA_NOTIFY_SLEEP: | 802 | case STA_NOTIFY_SLEEP: |
788 | case STA_NOTIFY_AWAKE: | 803 | case STA_NOTIFY_AWAKE: |
789 | /* TODO: make good use of these flags */ | 804 | /* TODO: make good use of these flags */ |
790 | break; | 805 | break; |
806 | default: | ||
807 | WARN(1, "Invalid sta notify: %d\n", cmd); | ||
808 | break; | ||
791 | } | 809 | } |
792 | } | 810 | } |
793 | 811 | ||
@@ -958,6 +976,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = | |||
958 | .config = mac80211_hwsim_config, | 976 | .config = mac80211_hwsim_config, |
959 | .configure_filter = mac80211_hwsim_configure_filter, | 977 | .configure_filter = mac80211_hwsim_configure_filter, |
960 | .bss_info_changed = mac80211_hwsim_bss_info_changed, | 978 | .bss_info_changed = mac80211_hwsim_bss_info_changed, |
979 | .sta_add = mac80211_hwsim_sta_add, | ||
980 | .sta_remove = mac80211_hwsim_sta_remove, | ||
961 | .sta_notify = mac80211_hwsim_sta_notify, | 981 | .sta_notify = mac80211_hwsim_sta_notify, |
962 | .set_tim = mac80211_hwsim_set_tim, | 982 | .set_tim = mac80211_hwsim_set_tim, |
963 | .conf_tx = mac80211_hwsim_conf_tx, | 983 | .conf_tx = mac80211_hwsim_conf_tx, |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0cfdb9db66f7..ac65e13eb0de 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -188,10 +188,6 @@ struct mwl8k_priv { | |||
188 | bool sniffer_enabled; | 188 | bool sniffer_enabled; |
189 | bool wmm_enabled; | 189 | bool wmm_enabled; |
190 | 190 | ||
191 | struct work_struct sta_notify_worker; | ||
192 | spinlock_t sta_notify_list_lock; | ||
193 | struct list_head sta_notify_list; | ||
194 | |||
195 | /* XXX need to convert this to handle multiple interfaces */ | 191 | /* XXX need to convert this to handle multiple interfaces */ |
196 | bool capture_beacon; | 192 | bool capture_beacon; |
197 | u8 capture_bssid[ETH_ALEN]; | 193 | u8 capture_bssid[ETH_ALEN]; |
@@ -3706,90 +3702,36 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
3706 | return mwl8k_cmd_set_rts_threshold(hw, value); | 3702 | return mwl8k_cmd_set_rts_threshold(hw, value); |
3707 | } | 3703 | } |
3708 | 3704 | ||
3709 | struct mwl8k_sta_notify_item | 3705 | static int mwl8k_sta_remove(struct ieee80211_hw *hw, |
3710 | { | 3706 | struct ieee80211_vif *vif, |
3711 | struct list_head list; | 3707 | struct ieee80211_sta *sta) |
3712 | struct ieee80211_vif *vif; | ||
3713 | enum sta_notify_cmd cmd; | ||
3714 | struct ieee80211_sta sta; | ||
3715 | }; | ||
3716 | |||
3717 | static void | ||
3718 | mwl8k_do_sta_notify(struct ieee80211_hw *hw, struct mwl8k_sta_notify_item *s) | ||
3719 | { | 3708 | { |
3720 | struct mwl8k_priv *priv = hw->priv; | 3709 | struct mwl8k_priv *priv = hw->priv; |
3721 | 3710 | ||
3722 | /* | 3711 | if (priv->ap_fw) |
3723 | * STA firmware uses UPDATE_STADB, AP firmware uses SET_NEW_STN. | 3712 | return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr); |
3724 | */ | 3713 | else |
3725 | if (!priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { | 3714 | return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr); |
3726 | int rc; | ||
3727 | |||
3728 | rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta); | ||
3729 | if (rc >= 0) { | ||
3730 | struct ieee80211_sta *sta; | ||
3731 | |||
3732 | rcu_read_lock(); | ||
3733 | sta = ieee80211_find_sta(s->vif, s->sta.addr); | ||
3734 | if (sta != NULL) | ||
3735 | MWL8K_STA(sta)->peer_id = rc; | ||
3736 | rcu_read_unlock(); | ||
3737 | } | ||
3738 | } else if (!priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { | ||
3739 | mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr); | ||
3740 | } else if (priv->ap_fw && s->cmd == STA_NOTIFY_ADD) { | ||
3741 | mwl8k_cmd_set_new_stn_add(hw, s->vif, &s->sta); | ||
3742 | } else if (priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) { | ||
3743 | mwl8k_cmd_set_new_stn_del(hw, s->vif, s->sta.addr); | ||
3744 | } | ||
3745 | } | ||
3746 | |||
3747 | static void mwl8k_sta_notify_worker(struct work_struct *work) | ||
3748 | { | ||
3749 | struct mwl8k_priv *priv = | ||
3750 | container_of(work, struct mwl8k_priv, sta_notify_worker); | ||
3751 | struct ieee80211_hw *hw = priv->hw; | ||
3752 | |||
3753 | spin_lock_bh(&priv->sta_notify_list_lock); | ||
3754 | while (!list_empty(&priv->sta_notify_list)) { | ||
3755 | struct mwl8k_sta_notify_item *s; | ||
3756 | |||
3757 | s = list_entry(priv->sta_notify_list.next, | ||
3758 | struct mwl8k_sta_notify_item, list); | ||
3759 | list_del(&s->list); | ||
3760 | |||
3761 | spin_unlock_bh(&priv->sta_notify_list_lock); | ||
3762 | |||
3763 | mwl8k_do_sta_notify(hw, s); | ||
3764 | kfree(s); | ||
3765 | |||
3766 | spin_lock_bh(&priv->sta_notify_list_lock); | ||
3767 | } | ||
3768 | spin_unlock_bh(&priv->sta_notify_list_lock); | ||
3769 | } | 3715 | } |
3770 | 3716 | ||
3771 | static void | 3717 | static int mwl8k_sta_add(struct ieee80211_hw *hw, |
3772 | mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 3718 | struct ieee80211_vif *vif, |
3773 | enum sta_notify_cmd cmd, struct ieee80211_sta *sta) | 3719 | struct ieee80211_sta *sta) |
3774 | { | 3720 | { |
3775 | struct mwl8k_priv *priv = hw->priv; | 3721 | struct mwl8k_priv *priv = hw->priv; |
3776 | struct mwl8k_sta_notify_item *s; | 3722 | int ret; |
3777 | |||
3778 | if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE) | ||
3779 | return; | ||
3780 | |||
3781 | s = kmalloc(sizeof(*s), GFP_ATOMIC); | ||
3782 | if (s != NULL) { | ||
3783 | s->vif = vif; | ||
3784 | s->cmd = cmd; | ||
3785 | s->sta = *sta; | ||
3786 | 3723 | ||
3787 | spin_lock(&priv->sta_notify_list_lock); | 3724 | if (!priv->ap_fw) { |
3788 | list_add_tail(&s->list, &priv->sta_notify_list); | 3725 | ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); |
3789 | spin_unlock(&priv->sta_notify_list_lock); | 3726 | if (ret >= 0) { |
3727 | MWL8K_STA(sta)->peer_id = ret; | ||
3728 | return 0; | ||
3729 | } | ||
3790 | 3730 | ||
3791 | ieee80211_queue_work(hw, &priv->sta_notify_worker); | 3731 | return ret; |
3792 | } | 3732 | } |
3733 | |||
3734 | return mwl8k_cmd_set_new_stn_add(hw, vif, sta); | ||
3793 | } | 3735 | } |
3794 | 3736 | ||
3795 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 3737 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -3849,7 +3791,8 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3849 | .prepare_multicast = mwl8k_prepare_multicast, | 3791 | .prepare_multicast = mwl8k_prepare_multicast, |
3850 | .configure_filter = mwl8k_configure_filter, | 3792 | .configure_filter = mwl8k_configure_filter, |
3851 | .set_rts_threshold = mwl8k_set_rts_threshold, | 3793 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3852 | .sta_notify = mwl8k_sta_notify, | 3794 | .sta_add = mwl8k_sta_add, |
3795 | .sta_remove = mwl8k_sta_remove, | ||
3853 | .conf_tx = mwl8k_conf_tx, | 3796 | .conf_tx = mwl8k_conf_tx, |
3854 | .get_stats = mwl8k_get_stats, | 3797 | .get_stats = mwl8k_get_stats, |
3855 | .ampdu_action = mwl8k_ampdu_action, | 3798 | .ampdu_action = mwl8k_ampdu_action, |
@@ -4051,11 +3994,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
4051 | priv->radio_on = 0; | 3994 | priv->radio_on = 0; |
4052 | priv->radio_short_preamble = 0; | 3995 | priv->radio_short_preamble = 0; |
4053 | 3996 | ||
4054 | /* Station database handling */ | ||
4055 | INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker); | ||
4056 | spin_lock_init(&priv->sta_notify_list_lock); | ||
4057 | INIT_LIST_HEAD(&priv->sta_notify_list); | ||
4058 | |||
4059 | /* Finalize join worker */ | 3997 | /* Finalize join worker */ |
4060 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); | 3998 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); |
4061 | 3999 | ||
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index f27bb8367c98..1d4ada188eda 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c | |||
@@ -407,7 +407,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
407 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), | 407 | PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), |
408 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), | 408 | PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), |
409 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), | 409 | PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), |
410 | PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092), | ||
411 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), | 410 | PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), |
412 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), | 411 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), |
413 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), | 412 | PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), |
@@ -417,7 +416,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
417 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), | 416 | PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), |
418 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | 417 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), |
419 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), | 418 | PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), |
420 | PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39), | ||
421 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), | 419 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), |
422 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), | 420 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), |
423 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), | 421 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), |
@@ -432,7 +430,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
432 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), | 430 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), |
433 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), | 431 | PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), |
434 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), | 432 | PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), |
435 | PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), | ||
436 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), | 433 | PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), |
437 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), | 434 | PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), |
438 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), | 435 | PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), |
@@ -445,7 +442,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
445 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), | 442 | PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), |
446 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), | 443 | PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), |
447 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), | 444 | PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), |
448 | PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39), | ||
449 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), | 445 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), |
450 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), | 446 | PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), |
451 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), | 447 | PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), |
@@ -454,8 +450,11 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
454 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), | 450 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), |
455 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), | 451 | PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), |
456 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), | 452 | PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), |
457 | PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), | ||
458 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), | 453 | PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), |
454 | PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092), | ||
455 | PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2), | ||
456 | PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b), | ||
457 | PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39), | ||
459 | PCMCIA_DEVICE_NULL, | 458 | PCMCIA_DEVICE_NULL, |
460 | }; | 459 | }; |
461 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); | 460 | MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 3fe6366e567c..4f752a21495f 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -33,21 +33,29 @@ MODULE_DESCRIPTION("Softmac Prism54 common code"); | |||
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | MODULE_ALIAS("prism54common"); | 34 | MODULE_ALIAS("prism54common"); |
35 | 35 | ||
36 | static int p54_sta_add_remove(struct ieee80211_hw *hw, | ||
37 | struct ieee80211_vif *vif, | ||
38 | struct ieee80211_sta *sta) | ||
39 | { | ||
40 | struct p54_common *priv = hw->priv; | ||
41 | |||
42 | /* | ||
43 | * Notify the firmware that we don't want or we don't | ||
44 | * need to buffer frames for this station anymore. | ||
45 | */ | ||
46 | |||
47 | p54_sta_unlock(priv, sta->addr); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | |||
36 | static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, | 52 | static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, |
37 | enum sta_notify_cmd notify_cmd, | 53 | enum sta_notify_cmd notify_cmd, |
38 | struct ieee80211_sta *sta) | 54 | struct ieee80211_sta *sta) |
39 | { | 55 | { |
40 | struct p54_common *priv = dev->priv; | 56 | struct p54_common *priv = dev->priv; |
41 | switch (notify_cmd) { | ||
42 | case STA_NOTIFY_ADD: | ||
43 | case STA_NOTIFY_REMOVE: | ||
44 | /* | ||
45 | * Notify the firmware that we don't want or we don't | ||
46 | * need to buffer frames for this station anymore. | ||
47 | */ | ||
48 | 57 | ||
49 | p54_sta_unlock(priv, sta->addr); | 58 | switch (notify_cmd) { |
50 | break; | ||
51 | case STA_NOTIFY_AWAKE: | 59 | case STA_NOTIFY_AWAKE: |
52 | /* update the firmware's filter table */ | 60 | /* update the firmware's filter table */ |
53 | p54_sta_unlock(priv, sta->addr); | 61 | p54_sta_unlock(priv, sta->addr); |
@@ -506,6 +514,8 @@ static const struct ieee80211_ops p54_ops = { | |||
506 | .remove_interface = p54_remove_interface, | 514 | .remove_interface = p54_remove_interface, |
507 | .set_tim = p54_set_tim, | 515 | .set_tim = p54_set_tim, |
508 | .sta_notify = p54_sta_notify, | 516 | .sta_notify = p54_sta_notify, |
517 | .sta_add = p54_sta_add_remove, | ||
518 | .sta_remove = p54_sta_add_remove, | ||
509 | .set_key = p54_set_key, | 519 | .set_key = p54_set_key, |
510 | .config = p54_config, | 520 | .config = p54_config, |
511 | .bss_info_changed = p54_bss_info_changed, | 521 | .bss_info_changed = p54_bss_info_changed, |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 92af9b96bb7a..b3c4fbd80d8d 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -36,6 +36,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
36 | /* Version 1 devices (pci chip + net2280) */ | 36 | /* Version 1 devices (pci chip + net2280) */ |
37 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ | 37 | {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ |
38 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ | 38 | {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ |
39 | {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ | ||
39 | {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ | 40 | {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ |
40 | {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ | 41 | {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ |
41 | {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ | 42 | {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ |
@@ -60,6 +61,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { | |||
60 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ | 61 | {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ |
61 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ | 62 | {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ |
62 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ | 63 | {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ |
64 | {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ | ||
63 | {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ | 65 | {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ |
64 | {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ | 66 | {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ |
65 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ | 67 | {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 0e8f69461ffe..66057999a93c 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -186,7 +186,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv, | |||
186 | struct p54_tx_queue_stats *queue; | 186 | struct p54_tx_queue_stats *queue; |
187 | unsigned long flags; | 187 | unsigned long flags; |
188 | 188 | ||
189 | if (WARN_ON(p54_queue > P54_QUEUE_NUM)) | 189 | if (WARN_ON(p54_queue >= P54_QUEUE_NUM)) |
190 | return -EINVAL; | 190 | return -EINVAL; |
191 | 191 | ||
192 | queue = &priv->tx_stats[p54_queue]; | 192 | queue = &priv->tx_stats[p54_queue]; |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 3ca824a91ad9..5239e082cd0f 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -64,7 +64,7 @@ config RT2800PCI_SOC | |||
64 | default y | 64 | default y |
65 | 65 | ||
66 | config RT2800PCI | 66 | config RT2800PCI |
67 | tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)" | 67 | tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)" |
68 | depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL | 68 | depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL |
69 | select RT2800_LIB | 69 | select RT2800_LIB |
70 | select RT2X00_LIB_PCI if RT2800PCI_PCI | 70 | select RT2X00_LIB_PCI if RT2800PCI_PCI |
@@ -75,7 +75,7 @@ config RT2800PCI | |||
75 | select CRC_CCITT | 75 | select CRC_CCITT |
76 | select EEPROM_93CX6 | 76 | select EEPROM_93CX6 |
77 | ---help--- | 77 | ---help--- |
78 | This adds support for rt2800 wireless chipset family. | 78 | This adds support for rt2800/rt3000/rt3500 wireless chipset family. |
79 | Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 | 79 | Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 |
80 | 80 | ||
81 | This driver is non-functional at the moment and is intended for | 81 | This driver is non-functional at the moment and is intended for |
@@ -83,6 +83,32 @@ config RT2800PCI | |||
83 | 83 | ||
84 | When compiled as a module, this driver will be called "rt2800pci.ko". | 84 | When compiled as a module, this driver will be called "rt2800pci.ko". |
85 | 85 | ||
86 | if RT2800PCI | ||
87 | |||
88 | config RT2800PCI_RT30XX | ||
89 | bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" | ||
90 | default n | ||
91 | ---help--- | ||
92 | This adds support for rt30xx wireless chipset family to the | ||
93 | rt2800pci driver. | ||
94 | Supported chips: RT3090, RT3091 & RT3092 | ||
95 | |||
96 | Support for these devices is non-functional at the moment and is | ||
97 | intended for testers and developers. | ||
98 | |||
99 | config RT2800PCI_RT35XX | ||
100 | bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices" | ||
101 | default n | ||
102 | ---help--- | ||
103 | This adds support for rt35xx wireless chipset family to the | ||
104 | rt2800pci driver. | ||
105 | Supported chips: RT3060, RT3062, RT3562, RT3592 | ||
106 | |||
107 | Support for these devices is non-functional at the moment and is | ||
108 | intended for testers and developers. | ||
109 | |||
110 | endif | ||
111 | |||
86 | config RT2500USB | 112 | config RT2500USB |
87 | tristate "Ralink rt2500 (USB) support" | 113 | tristate "Ralink rt2500 (USB) support" |
88 | depends on USB | 114 | depends on USB |
@@ -126,6 +152,43 @@ config RT2800USB | |||
126 | 152 | ||
127 | When compiled as a module, this driver will be called "rt2800usb.ko". | 153 | When compiled as a module, this driver will be called "rt2800usb.ko". |
128 | 154 | ||
155 | if RT2800USB | ||
156 | |||
157 | config RT2800USB_RT30XX | ||
158 | bool "rt2800usb - Include support for rt30xx (USB) devices" | ||
159 | default n | ||
160 | ---help--- | ||
161 | This adds support for rt30xx wireless chipset family to the | ||
162 | rt2800usb driver. | ||
163 | Supported chips: RT3070, RT3071 & RT3072 | ||
164 | |||
165 | Support for these devices is non-functional at the moment and is | ||
166 | intended for testers and developers. | ||
167 | |||
168 | config RT2800USB_RT35XX | ||
169 | bool "rt2800usb - Include support for rt35xx (USB) devices" | ||
170 | default n | ||
171 | ---help--- | ||
172 | This adds support for rt35xx wireless chipset family to the | ||
173 | rt2800usb driver. | ||
174 | Supported chips: RT3572 | ||
175 | |||
176 | Support for these devices is non-functional at the moment and is | ||
177 | intended for testers and developers. | ||
178 | |||
179 | config RT2800USB_UNKNOWN | ||
180 | bool "rt2800usb - Include support for unknown (USB) devices" | ||
181 | default n | ||
182 | ---help--- | ||
183 | This adds support for rt2800 family devices that are known to | ||
184 | have a rt2800 family chipset, but for which the exact chipset | ||
185 | is unknown. | ||
186 | |||
187 | Support status for these devices is unknown, and enabling these | ||
188 | devices may or may not work. | ||
189 | |||
190 | endif | ||
191 | |||
129 | config RT2800_LIB | 192 | config RT2800_LIB |
130 | tristate | 193 | tristate |
131 | 194 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 108982762d45..c22b04042d5c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1340,8 +1340,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1340 | */ | 1340 | */ |
1341 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1341 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1342 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1342 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); |
1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1343 | rt2x00_set_chip(rt2x00dev, RT2460, value, |
1344 | rt2x00_print_chip(rt2x00dev); | 1344 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1345 | 1345 | ||
1346 | if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { | 1346 | if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { |
1347 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1347 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index c3dea697b907..c048b18f4133 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h | |||
@@ -65,6 +65,7 @@ | |||
65 | * CSR0: ASIC revision number. | 65 | * CSR0: ASIC revision number. |
66 | */ | 66 | */ |
67 | #define CSR0 0x0000 | 67 | #define CSR0 0x0000 |
68 | #define CSR0_REVISION FIELD32(0x0000ffff) | ||
68 | 69 | ||
69 | /* | 70 | /* |
70 | * CSR1: System control register. | 71 | * CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index f6440bb0e5f6..52bbcf1bd17c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1503,8 +1503,8 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1503 | */ | 1503 | */ |
1504 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1504 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1505 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); | 1505 | rt2x00pci_register_read(rt2x00dev, CSR0, ®); |
1506 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1506 | rt2x00_set_chip(rt2x00dev, RT2560, value, |
1507 | rt2x00_print_chip(rt2x00dev); | 1507 | rt2x00_get_field32(reg, CSR0_REVISION)); |
1508 | 1508 | ||
1509 | if (!rt2x00_rf(rt2x00dev, RF2522) && | 1509 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1510 | !rt2x00_rf(rt2x00dev, RF2523) && | 1510 | !rt2x00_rf(rt2x00dev, RF2523) && |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index c6bd1fcae7eb..d708031361ac 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h | |||
@@ -76,6 +76,7 @@ | |||
76 | * CSR0: ASIC revision number. | 76 | * CSR0: ASIC revision number. |
77 | */ | 77 | */ |
78 | #define CSR0 0x0000 | 78 | #define CSR0 0x0000 |
79 | #define CSR0_REVISION FIELD32(0x0000ffff) | ||
79 | 80 | ||
80 | /* | 81 | /* |
81 | * CSR1: System control register. | 82 | * CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 81ca4ec068db..ee34c137e7cd 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1408,10 +1408,8 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1408 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1408 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1409 | rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1409 | rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1410 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); | 1410 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); |
1411 | rt2x00_print_chip(rt2x00dev); | ||
1412 | 1411 | ||
1413 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || | 1412 | if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { |
1414 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { | ||
1415 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1413 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1416 | return -ENODEV; | 1414 | return -ENODEV; |
1417 | } | 1415 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 1a7eae357fef..74c0433dba37 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -60,11 +60,11 @@ | |||
60 | /* | 60 | /* |
61 | * Chipset version. | 61 | * Chipset version. |
62 | */ | 62 | */ |
63 | #define RT2860C_VERSION 0x28600100 | 63 | #define RT2860C_VERSION 0x0100 |
64 | #define RT2860D_VERSION 0x28600101 | 64 | #define RT2860D_VERSION 0x0101 |
65 | #define RT2880E_VERSION 0x28720200 | 65 | #define RT2880E_VERSION 0x0200 |
66 | #define RT2883_VERSION 0x28830300 | 66 | #define RT2883_VERSION 0x0300 |
67 | #define RT3070_VERSION 0x30700200 | 67 | #define RT3070_VERSION 0x0200 |
68 | 68 | ||
69 | /* | 69 | /* |
70 | * Signal information. | 70 | * Signal information. |
@@ -408,8 +408,8 @@ | |||
408 | * ASIC_VER: 2860 or 2870 | 408 | * ASIC_VER: 2860 or 2870 |
409 | */ | 409 | */ |
410 | #define MAC_CSR0 0x1000 | 410 | #define MAC_CSR0 0x1000 |
411 | #define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) | 411 | #define MAC_CSR0_REVISION FIELD32(0x0000ffff) |
412 | #define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) | 412 | #define MAC_CSR0_CHIPSET FIELD32(0xffff0000) |
413 | 413 | ||
414 | /* | 414 | /* |
415 | * MAC_SYS_CTRL: | 415 | * MAC_SYS_CTRL: |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index a45e027f2d1f..18d4d8e4ae6b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -40,6 +40,9 @@ | |||
40 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) | 40 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
41 | #include "rt2x00usb.h" | 41 | #include "rt2x00usb.h" |
42 | #endif | 42 | #endif |
43 | #if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) | ||
44 | #include "rt2x00pci.h" | ||
45 | #endif | ||
43 | #include "rt2800lib.h" | 46 | #include "rt2800lib.h" |
44 | #include "rt2800.h" | 47 | #include "rt2800.h" |
45 | #include "rt2800usb.h" | 48 | #include "rt2800usb.h" |
@@ -89,7 +92,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
89 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | 92 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); |
90 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | 93 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); |
91 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); | 94 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); |
92 | if (rt2x00_intf_is_pci(rt2x00dev)) | 95 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
93 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | 96 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); |
94 | 97 | ||
95 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | 98 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); |
@@ -118,7 +121,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
118 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | 121 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); |
119 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | 122 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); |
120 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); | 123 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); |
121 | if (rt2x00_intf_is_pci(rt2x00dev)) | 124 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
122 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | 125 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); |
123 | 126 | ||
124 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); | 127 | rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); |
@@ -218,9 +221,9 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
218 | u32 reg; | 221 | u32 reg; |
219 | 222 | ||
220 | /* | 223 | /* |
221 | * RT2880 and RT3052 don't support MCU requests. | 224 | * SOC devices don't support MCU requests. |
222 | */ | 225 | */ |
223 | if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052)) | 226 | if (rt2x00_is_soc(rt2x00dev)) |
224 | return; | 227 | return; |
225 | 228 | ||
226 | mutex_lock(&rt2x00dev->csr_mutex); | 229 | mutex_lock(&rt2x00dev->csr_mutex); |
@@ -660,7 +663,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) | |||
660 | switch ((int)ant->tx) { | 663 | switch ((int)ant->tx) { |
661 | case 1: | 664 | case 1: |
662 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | 665 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); |
663 | if (rt2x00_intf_is_pci(rt2x00dev)) | 666 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
664 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | 667 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); |
665 | break; | 668 | break; |
666 | case 2: | 669 | case 2: |
@@ -895,7 +898,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
895 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | 898 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); |
896 | rt2800_bbp_write(rt2x00dev, 3, bbp); | 899 | rt2800_bbp_write(rt2x00dev, 3, bbp); |
897 | 900 | ||
898 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { | 901 | if (rt2x00_rt(rt2x00dev, RT2860) && |
902 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | ||
899 | if (conf_is_ht40(conf)) { | 903 | if (conf_is_ht40(conf)) { |
900 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | 904 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); |
901 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 905 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
@@ -1057,8 +1061,9 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); | |||
1057 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | 1061 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) |
1058 | { | 1062 | { |
1059 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 1063 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
1060 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1064 | if (rt2x00_is_usb(rt2x00dev) && |
1061 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) | 1065 | rt2x00_rt(rt2x00dev, RT3070) && |
1066 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) | ||
1062 | return 0x1c + (2 * rt2x00dev->lna_gain); | 1067 | return 0x1c + (2 * rt2x00dev->lna_gain); |
1063 | else | 1068 | else |
1064 | return 0x2e + rt2x00dev->lna_gain; | 1069 | return 0x2e + rt2x00dev->lna_gain; |
@@ -1089,7 +1094,8 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
1089 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 1094 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
1090 | const u32 count) | 1095 | const u32 count) |
1091 | { | 1096 | { |
1092 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) | 1097 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1098 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) | ||
1093 | return; | 1099 | return; |
1094 | 1100 | ||
1095 | /* | 1101 | /* |
@@ -1109,7 +1115,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1109 | u32 reg; | 1115 | u32 reg; |
1110 | unsigned int i; | 1116 | unsigned int i; |
1111 | 1117 | ||
1112 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1118 | if (rt2x00_is_usb(rt2x00dev)) { |
1113 | /* | 1119 | /* |
1114 | * Wait until BBP and RF are ready. | 1120 | * Wait until BBP and RF are ready. |
1115 | */ | 1121 | */ |
@@ -1128,7 +1134,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1128 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | 1134 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); |
1129 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, | 1135 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, |
1130 | reg & ~0x00002000); | 1136 | reg & ~0x00002000); |
1131 | } else if (rt2x00_intf_is_pci(rt2x00dev)) | 1137 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
1132 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | 1138 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); |
1133 | 1139 | ||
1134 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | 1140 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); |
@@ -1136,7 +1142,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1136 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | 1142 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); |
1137 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 1143 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
1138 | 1144 | ||
1139 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1145 | if (rt2x00_is_usb(rt2x00dev)) { |
1140 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | 1146 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); |
1141 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) | 1147 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
1142 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 1148 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
@@ -1174,8 +1180,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1174 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); | 1180 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); |
1175 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1181 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1176 | 1182 | ||
1177 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1183 | if (rt2x00_is_usb(rt2x00dev) && |
1178 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { | 1184 | rt2x00_rt(rt2x00dev, RT3070) && |
1185 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | ||
1179 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1186 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1180 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 1187 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
1181 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1188 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -1202,8 +1209,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1202 | 1209 | ||
1203 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); | 1210 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); |
1204 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | 1211 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); |
1205 | if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION && | 1212 | if ((rt2x00_rt(rt2x00dev, RT2872) && |
1206 | rt2x00_rev(rt2x00dev) < RT3070_VERSION) | 1213 | (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || |
1214 | rt2x00_rt(rt2x00dev, RT2880) || | ||
1215 | rt2x00_rt(rt2x00dev, RT2883) || | ||
1216 | rt2x00_rt(rt2x00dev, RT2890) || | ||
1217 | rt2x00_rt(rt2x00dev, RT3052) || | ||
1218 | (rt2x00_rt(rt2x00dev, RT3070) && | ||
1219 | (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) | ||
1207 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | 1220 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); |
1208 | else | 1221 | else |
1209 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | 1222 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); |
@@ -1293,7 +1306,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1293 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1306 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); |
1294 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | 1307 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); |
1295 | 1308 | ||
1296 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1309 | if (rt2x00_is_usb(rt2x00dev)) { |
1297 | rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); | 1310 | rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); |
1298 | 1311 | ||
1299 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 1312 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); |
@@ -1353,7 +1366,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1353 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); | 1366 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0); |
1354 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); | 1367 | rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0); |
1355 | 1368 | ||
1356 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1369 | if (rt2x00_is_usb(rt2x00dev)) { |
1357 | rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); | 1370 | rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®); |
1358 | rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); | 1371 | rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); |
1359 | rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); | 1372 | rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg); |
@@ -1482,16 +1495,19 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1482 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 1495 | rt2800_bbp_write(rt2x00dev, 103, 0x00); |
1483 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1496 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1484 | 1497 | ||
1485 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { | 1498 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1499 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | ||
1486 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 1500 | rt2800_bbp_write(rt2x00dev, 69, 0x16); |
1487 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 1501 | rt2800_bbp_write(rt2x00dev, 73, 0x12); |
1488 | } | 1502 | } |
1489 | 1503 | ||
1490 | if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) | 1504 | if (rt2x00_rt(rt2x00dev, RT2860) && |
1505 | (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) | ||
1491 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1506 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
1492 | 1507 | ||
1493 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1508 | if (rt2x00_is_usb(rt2x00dev) && |
1494 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { | 1509 | rt2x00_rt(rt2x00dev, RT3070) && |
1510 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | ||
1495 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 1511 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
1496 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1512 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
1497 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1513 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
@@ -1582,11 +1598,12 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1582 | u8 rfcsr; | 1598 | u8 rfcsr; |
1583 | u8 bbp; | 1599 | u8 bbp; |
1584 | 1600 | ||
1585 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1601 | if (rt2x00_is_usb(rt2x00dev) && |
1586 | rt2x00_rev(rt2x00dev) != RT3070_VERSION) | 1602 | rt2x00_rt(rt2x00dev, RT3070) && |
1603 | (rt2x00_rev(rt2x00dev) != RT3070_VERSION)) | ||
1587 | return 0; | 1604 | return 0; |
1588 | 1605 | ||
1589 | if (rt2x00_intf_is_pci(rt2x00dev)) { | 1606 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { |
1590 | if (!rt2x00_rf(rt2x00dev, RF3020) && | 1607 | if (!rt2x00_rf(rt2x00dev, RF3020) && |
1591 | !rt2x00_rf(rt2x00dev, RF3021) && | 1608 | !rt2x00_rf(rt2x00dev, RF3021) && |
1592 | !rt2x00_rf(rt2x00dev, RF3022)) | 1609 | !rt2x00_rf(rt2x00dev, RF3022)) |
@@ -1603,7 +1620,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1603 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | 1620 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); |
1604 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | 1621 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); |
1605 | 1622 | ||
1606 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1623 | if (rt2x00_is_usb(rt2x00dev)) { |
1607 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | 1624 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); |
1608 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | 1625 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); |
1609 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | 1626 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); |
@@ -1624,7 +1641,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1624 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 1641 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); |
1625 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | 1642 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); |
1626 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | 1643 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); |
1627 | } else if (rt2x00_intf_is_pci(rt2x00dev)) { | 1644 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { |
1628 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); | 1645 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); |
1629 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); | 1646 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); |
1630 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); | 1647 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); |
@@ -1754,7 +1771,12 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1754 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); | 1771 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); |
1755 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | 1772 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); |
1756 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | 1773 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); |
1757 | } else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) { | 1774 | } else if (rt2x00_rt(rt2x00dev, RT2860) || |
1775 | rt2x00_rt(rt2x00dev, RT2870) || | ||
1776 | rt2x00_rt(rt2x00dev, RT2872) || | ||
1777 | rt2x00_rt(rt2x00dev, RT2880) || | ||
1778 | (rt2x00_rt(rt2x00dev, RT2883) && | ||
1779 | (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) { | ||
1758 | /* | 1780 | /* |
1759 | * There is a max of 2 RX streams for RT28x0 series | 1781 | * There is a max of 2 RX streams for RT28x0 series |
1760 | */ | 1782 | */ |
@@ -1853,25 +1875,24 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1853 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1875 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1854 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); | 1876 | rt2800_register_read(rt2x00dev, MAC_CSR0, ®); |
1855 | 1877 | ||
1856 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1878 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
1857 | 1879 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); | |
1858 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1880 | |
1859 | /* | 1881 | if (!rt2x00_rt(rt2x00dev, RT2860) && |
1860 | * The check for rt2860 is not a typo, some rt2870 hardware | 1882 | !rt2x00_rt(rt2x00dev, RT2870) && |
1861 | * identifies itself as rt2860 in the CSR register. | 1883 | !rt2x00_rt(rt2x00dev, RT2872) && |
1862 | */ | 1884 | !rt2x00_rt(rt2x00dev, RT2880) && |
1863 | if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) || | 1885 | !rt2x00_rt(rt2x00dev, RT2883) && |
1864 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) || | 1886 | !rt2x00_rt(rt2x00dev, RT2890) && |
1865 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) { | 1887 | !rt2x00_rt(rt2x00dev, RT3052) && |
1866 | rt2x00_set_chip_rt(rt2x00dev, RT2870); | 1888 | !rt2x00_rt(rt2x00dev, RT3070) && |
1867 | } else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) { | 1889 | !rt2x00_rt(rt2x00dev, RT3071) && |
1868 | rt2x00_set_chip_rt(rt2x00dev, RT3070); | 1890 | !rt2x00_rt(rt2x00dev, RT3090) && |
1869 | } else { | 1891 | !rt2x00_rt(rt2x00dev, RT3390) && |
1870 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1892 | !rt2x00_rt(rt2x00dev, RT3572)) { |
1871 | return -ENODEV; | 1893 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1872 | } | 1894 | return -ENODEV; |
1873 | } | 1895 | } |
1874 | rt2x00_print_chip(rt2x00dev); | ||
1875 | 1896 | ||
1876 | if (!rt2x00_rf(rt2x00dev, RF2820) && | 1897 | if (!rt2x00_rf(rt2x00dev, RF2820) && |
1877 | !rt2x00_rf(rt2x00dev, RF2850) && | 1898 | !rt2x00_rf(rt2x00dev, RF2850) && |
@@ -2039,7 +2060,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2039 | /* | 2060 | /* |
2040 | * Disable powersaving as default on PCI devices. | 2061 | * Disable powersaving as default on PCI devices. |
2041 | */ | 2062 | */ |
2042 | if (rt2x00_intf_is_pci(rt2x00dev)) | 2063 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) |
2043 | rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 2064 | rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
2044 | 2065 | ||
2045 | /* | 2066 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index d64181cbc9cb..aca8c124f434 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1041,18 +1041,12 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1041 | /* | 1041 | /* |
1042 | * Read EEPROM into buffer | 1042 | * Read EEPROM into buffer |
1043 | */ | 1043 | */ |
1044 | switch (rt2x00dev->chip.rt) { | 1044 | if (rt2x00_is_soc(rt2x00dev)) |
1045 | case RT2880: | ||
1046 | case RT3052: | ||
1047 | rt2800pci_read_eeprom_soc(rt2x00dev); | 1045 | rt2800pci_read_eeprom_soc(rt2x00dev); |
1048 | break; | 1046 | else if (rt2800pci_efuse_detect(rt2x00dev)) |
1049 | default: | 1047 | rt2800pci_read_eeprom_efuse(rt2x00dev); |
1050 | if (rt2800pci_efuse_detect(rt2x00dev)) | 1048 | else |
1051 | rt2800pci_read_eeprom_efuse(rt2x00dev); | 1049 | rt2800pci_read_eeprom_pci(rt2x00dev); |
1052 | else | ||
1053 | rt2800pci_read_eeprom_pci(rt2x00dev); | ||
1054 | break; | ||
1055 | } | ||
1056 | 1050 | ||
1057 | return rt2800_validate_eeprom(rt2x00dev); | 1051 | return rt2800_validate_eeprom(rt2x00dev); |
1058 | } | 1052 | } |
@@ -1103,7 +1097,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1103 | /* | 1097 | /* |
1104 | * This device requires firmware. | 1098 | * This device requires firmware. |
1105 | */ | 1099 | */ |
1106 | if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052)) | 1100 | if (!rt2x00_is_soc(rt2x00dev)) |
1107 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 1101 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
1108 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 1102 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
1109 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 1103 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
@@ -1191,7 +1185,10 @@ static const struct rt2x00_ops rt2800pci_ops = { | |||
1191 | * RT2800pci module information. | 1185 | * RT2800pci module information. |
1192 | */ | 1186 | */ |
1193 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | 1187 | static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { |
1194 | { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1188 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1189 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1190 | { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1191 | { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1195 | { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1192 | { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1196 | { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1193 | { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1197 | { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1194 | { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
@@ -1199,18 +1196,19 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1199 | { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1196 | { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1200 | { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1197 | { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1201 | { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1198 | { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1202 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1199 | { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1203 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1200 | #ifdef CONFIG_RT2800PCI_RT30XX |
1204 | { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1205 | { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1206 | { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1207 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1208 | { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1201 | { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1209 | { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1202 | { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1210 | { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1203 | { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1204 | { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1205 | #endif | ||
1206 | #ifdef CONFIG_RT2800PCI_RT35XX | ||
1207 | { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1208 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1211 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1209 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1212 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1210 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1213 | { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1211 | #endif |
1214 | { 0, } | 1212 | { 0, } |
1215 | }; | 1213 | }; |
1216 | 1214 | ||
@@ -1225,11 +1223,10 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1225 | MODULE_LICENSE("GPL"); | 1223 | MODULE_LICENSE("GPL"); |
1226 | 1224 | ||
1227 | #ifdef CONFIG_RT2800PCI_SOC | 1225 | #ifdef CONFIG_RT2800PCI_SOC |
1228 | #if defined(CONFIG_RALINK_RT288X) | 1226 | static int rt2800soc_probe(struct platform_device *pdev) |
1229 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); | 1227 | { |
1230 | #elif defined(CONFIG_RALINK_RT305X) | 1228 | return rt2x00soc_probe(pdev, rt2800pci_ops); |
1231 | __rt2x00soc_probe(RT3052, &rt2800pci_ops); | 1229 | } |
1232 | #endif | ||
1233 | 1230 | ||
1234 | static struct platform_driver rt2800soc_driver = { | 1231 | static struct platform_driver rt2800soc_driver = { |
1235 | .driver = { | 1232 | .driver = { |
@@ -1237,7 +1234,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1237 | .owner = THIS_MODULE, | 1234 | .owner = THIS_MODULE, |
1238 | .mod_name = KBUILD_MODNAME, | 1235 | .mod_name = KBUILD_MODNAME, |
1239 | }, | 1236 | }, |
1240 | .probe = __rt2x00soc_probe, | 1237 | .probe = rt2800soc_probe, |
1241 | .remove = __devexit_p(rt2x00soc_remove), | 1238 | .remove = __devexit_p(rt2x00soc_remove), |
1242 | .suspend = rt2x00soc_suspend, | 1239 | .suspend = rt2x00soc_suspend, |
1243 | .resume = rt2x00soc_resume, | 1240 | .resume = rt2x00soc_resume, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 82755cf8b73e..5e4ee2023fcf 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -92,7 +92,6 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | 92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, |
93 | const u8 *data, const size_t len) | 93 | const u8 *data, const size_t len) |
94 | { | 94 | { |
95 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; | ||
96 | size_t offset = 0; | 95 | size_t offset = 0; |
97 | 96 | ||
98 | /* | 97 | /* |
@@ -111,9 +110,9 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
111 | * Check if we need the upper 4kb firmware data or not. | 110 | * Check if we need the upper 4kb firmware data or not. |
112 | */ | 111 | */ |
113 | if ((len == 4096) && | 112 | if ((len == 4096) && |
114 | (chipset != 0x2860) && | 113 | !rt2x00_rt(rt2x00dev, RT2860) && |
115 | (chipset != 0x2872) && | 114 | !rt2x00_rt(rt2x00dev, RT2872) && |
116 | (chipset != 0x3070)) | 115 | !rt2x00_rt(rt2x00dev, RT3070)) |
117 | return FW_BAD_VERSION; | 116 | return FW_BAD_VERSION; |
118 | 117 | ||
119 | /* | 118 | /* |
@@ -138,14 +137,13 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
138 | u32 reg; | 137 | u32 reg; |
139 | u32 offset; | 138 | u32 offset; |
140 | u32 length; | 139 | u32 length; |
141 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; | ||
142 | 140 | ||
143 | /* | 141 | /* |
144 | * Check which section of the firmware we need. | 142 | * Check which section of the firmware we need. |
145 | */ | 143 | */ |
146 | if ((chipset == 0x2860) || | 144 | if (rt2x00_rt(rt2x00dev, RT2860) || |
147 | (chipset == 0x2872) || | 145 | rt2x00_rt(rt2x00dev, RT2872) || |
148 | (chipset == 0x3070)) { | 146 | rt2x00_rt(rt2x00dev, RT3070)) { |
149 | offset = 0; | 147 | offset = 0; |
150 | length = 4096; | 148 | length = 4096; |
151 | } else { | 149 | } else { |
@@ -200,9 +198,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
200 | */ | 198 | */ |
201 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); | 199 | rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); |
202 | 200 | ||
203 | if ((chipset == 0x3070) || | 201 | if (rt2x00_rt(rt2x00dev, RT3070) || |
204 | (chipset == 0x3071) || | 202 | rt2x00_rt(rt2x00dev, RT3071) || |
205 | (chipset == 0x3572)) { | 203 | rt2x00_rt(rt2x00dev, RT3572)) { |
206 | udelay(200); | 204 | udelay(200); |
207 | rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); | 205 | rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); |
208 | udelay(10); | 206 | udelay(10); |
@@ -807,51 +805,27 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
807 | /* Abocom */ | 805 | /* Abocom */ |
808 | { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | 806 | { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, |
809 | { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | 807 | { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, |
810 | { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
811 | { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
812 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
813 | { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 808 | { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
814 | /* AirTies */ | ||
815 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
816 | /* Amigo */ | ||
817 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
818 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
819 | /* Amit */ | 809 | /* Amit */ |
820 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | 810 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, |
821 | /* Askey */ | 811 | /* Askey */ |
822 | { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, | 812 | { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, |
823 | { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
824 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
825 | /* ASUS */ | 813 | /* ASUS */ |
826 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, | 814 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, |
827 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, | 815 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, |
828 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, | 816 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, |
829 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
830 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
831 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
832 | /* AzureWave */ | 817 | /* AzureWave */ |
833 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, | 818 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, |
834 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
835 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
836 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
837 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
838 | /* Belkin */ | 819 | /* Belkin */ |
839 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, | 820 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, |
840 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 821 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
841 | { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 822 | { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
842 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
843 | /* Buffalo */ | 823 | /* Buffalo */ |
844 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, | 824 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, |
845 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
846 | /* Cisco */ | ||
847 | { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
848 | /* Conceptronic */ | 825 | /* Conceptronic */ |
849 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, | 826 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, |
850 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, | 827 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, |
851 | { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
852 | { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 828 | { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
853 | { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
854 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
855 | { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, | 829 | { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, |
856 | { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, | 830 | { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, |
857 | { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, | 831 | { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -860,157 +834,257 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
860 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 834 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
861 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 835 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
862 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 836 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
863 | { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
864 | { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
865 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
866 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
867 | /* D-Link */ | 837 | /* D-Link */ |
868 | { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, | 838 | { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, |
839 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
840 | /* Edimax */ | ||
841 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
842 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
843 | /* EnGenius */ | ||
844 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
845 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
846 | /* Gigabyte */ | ||
847 | { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
848 | /* Hawking */ | ||
849 | { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
850 | { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
851 | /* Linksys */ | ||
852 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
853 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
854 | /* Logitec */ | ||
855 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
856 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
857 | { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
858 | /* Motorola */ | ||
859 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
860 | /* MSI */ | ||
861 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
862 | /* Philips */ | ||
863 | { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
864 | /* Planex */ | ||
865 | { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
866 | /* Ralink */ | ||
867 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
868 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
869 | /* Samsung */ | ||
870 | { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
871 | /* Siemens */ | ||
872 | { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
873 | /* Sitecom */ | ||
874 | { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
875 | { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
876 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
877 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
878 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
879 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
880 | /* SMC */ | ||
881 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
882 | { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
883 | { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
884 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
885 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
886 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
887 | /* Sparklan */ | ||
888 | { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
889 | /* Sweex */ | ||
890 | { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
891 | /* U-Media*/ | ||
892 | { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
893 | /* ZCOM */ | ||
894 | { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
895 | { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
896 | /* Zinwell */ | ||
897 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
898 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
899 | /* Zyxel */ | ||
900 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
901 | #ifdef CONFIG_RT2800USB_RT30XX | ||
902 | /* Abocom */ | ||
903 | { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
904 | { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
905 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
906 | /* AirTies */ | ||
907 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | /* AzureWave */ | ||
909 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
910 | /* Conceptronic */ | ||
911 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
912 | /* Corega */ | ||
913 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
914 | /* D-Link */ | ||
869 | { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 915 | { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
870 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
871 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 916 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
872 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 917 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
873 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 918 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
874 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
875 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
876 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
877 | /* Edimax */ | 919 | /* Edimax */ |
878 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, | 920 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, |
879 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
880 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
881 | /* Encore */ | 921 | /* Encore */ |
882 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, | 922 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, |
883 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
884 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
885 | /* EnGenius */ | 923 | /* EnGenius */ |
886 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
887 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
888 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, | 924 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, |
889 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, | 925 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, |
890 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, | 926 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, |
927 | /* Gigabyte */ | ||
928 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
929 | /* I-O DATA */ | ||
930 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
931 | /* MSI */ | ||
932 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | /* Pegatron */ | ||
934 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
935 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
936 | /* Planex */ | ||
937 | { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
938 | /* Quanta */ | ||
939 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
940 | /* Ralink */ | ||
941 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
942 | { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
943 | { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
944 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
945 | /* Sitecom */ | ||
946 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
947 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
948 | /* SMC */ | ||
949 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
950 | /* Zinwell */ | ||
951 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
952 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
953 | #endif | ||
954 | #ifdef CONFIG_RT2800USB_RT35XX | ||
955 | /* Askey */ | ||
956 | { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
957 | /* Cisco */ | ||
958 | { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | /* EnGenius */ | ||
960 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
961 | /* I-O DATA */ | ||
962 | { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
963 | /* Ralink */ | ||
964 | { USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
965 | { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
966 | { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
967 | /* Sitecom */ | ||
968 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
969 | /* Zinwell */ | ||
970 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
971 | #endif | ||
972 | #ifdef CONFIG_RT2800USB_UNKNOWN | ||
973 | /* | ||
974 | * Unclear what kind of devices these are (they aren't supported by the | ||
975 | * vendor driver). | ||
976 | */ | ||
977 | /* Allwin */ | ||
978 | { USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
979 | { USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
980 | { USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
981 | { USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
982 | { USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
983 | { USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | /* Amigo */ | ||
986 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
987 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
988 | /* Askey */ | ||
989 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
990 | /* ASUS */ | ||
991 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
992 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
993 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
994 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
995 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
996 | /* AzureWave */ | ||
997 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
998 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
999 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1000 | /* Belkin */ | ||
1001 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1002 | /* Buffalo */ | ||
1003 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1004 | { USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1005 | { USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1006 | { USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1007 | /* Conceptronic */ | ||
1008 | { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1009 | { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1010 | /* Corega */ | ||
1011 | { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1012 | { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1013 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1014 | /* D-Link */ | ||
1015 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1016 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1017 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1018 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1019 | /* Encore */ | ||
1020 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1021 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1022 | /* EnGenius */ | ||
891 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1023 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, |
892 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1024 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, |
893 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1025 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, |
894 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
895 | /* Gemtek */ | 1026 | /* Gemtek */ |
896 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1027 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
897 | /* Gigabyte */ | 1028 | /* Gigabyte */ |
898 | { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
899 | { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1029 | { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
900 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
901 | /* Hawking */ | 1030 | /* Hawking */ |
902 | { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
903 | { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
904 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1031 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, |
905 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1032 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
906 | /* I-O DATA */ | 1033 | /* I-O DATA */ |
907 | { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
909 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1034 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, |
910 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1035 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, |
911 | /* LevelOne */ | 1036 | /* LevelOne */ |
912 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1037 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, |
913 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1038 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, |
914 | /* Linksys */ | 1039 | /* Linksys */ |
915 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
916 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
917 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1040 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1041 | { USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
918 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1042 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, |
919 | /* Logitec */ | ||
920 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
921 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
922 | { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
923 | /* Motorola */ | 1043 | /* Motorola */ |
924 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
925 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1044 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, |
926 | /* MSI */ | 1045 | /* MSI */ |
927 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
928 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1046 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1047 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
929 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1048 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, |
930 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1049 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, |
931 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1050 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1051 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
932 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1052 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1053 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1054 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
934 | /* Ovislink */ | 1055 | /* Ovislink */ |
935 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1056 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
936 | /* Para */ | 1057 | /* Para */ |
937 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1058 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, |
938 | /* Pegatron */ | 1059 | /* Pegatron */ |
1060 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
939 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1061 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, |
940 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1062 | { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
941 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
942 | /* Philips */ | ||
943 | { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
944 | /* Planex */ | 1063 | /* Planex */ |
945 | { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
946 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1064 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, |
947 | { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
948 | /* Qcom */ | 1065 | /* Qcom */ |
949 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1066 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, |
950 | /* Quanta */ | ||
951 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
952 | /* Ralink */ | ||
953 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
954 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
955 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
956 | { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
957 | { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
958 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
960 | /* Samsung */ | ||
961 | { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
962 | /* Siemens */ | ||
963 | { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
964 | /* Sitecom */ | 1067 | /* Sitecom */ |
965 | { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
966 | { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
967 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
968 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
969 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
970 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1068 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
971 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1069 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
972 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1070 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
973 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
974 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
975 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1071 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, |
976 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
977 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
978 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1072 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, |
979 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1073 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, |
980 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1074 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
981 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1075 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
982 | /* SMC */ | 1076 | /* SMC */ |
983 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
986 | { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
987 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
988 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1077 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, |
989 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
990 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1078 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, |
991 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1079 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, |
992 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
993 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1080 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
994 | /* Sparklan */ | 1081 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
995 | { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
996 | /* Sweex */ | 1082 | /* Sweex */ |
997 | { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1083 | { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, |
998 | { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
999 | { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1084 | { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1000 | /* U-Media*/ | ||
1001 | { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1002 | /* ZCOM */ | ||
1003 | { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1004 | { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1005 | /* Zinwell */ | ||
1006 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1007 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1008 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1009 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1010 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1011 | /* Zyxel */ | 1085 | /* Zyxel */ |
1012 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1013 | { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1086 | { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1087 | #endif | ||
1014 | { 0, } | 1088 | { 0, } |
1015 | }; | 1089 | }; |
1016 | 1090 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 43b70c6e4e9c..d9daa9c406fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -160,6 +160,7 @@ struct avg_val { | |||
160 | enum rt2x00_chip_intf { | 160 | enum rt2x00_chip_intf { |
161 | RT2X00_CHIP_INTF_PCI, | 161 | RT2X00_CHIP_INTF_PCI, |
162 | RT2X00_CHIP_INTF_USB, | 162 | RT2X00_CHIP_INTF_USB, |
163 | RT2X00_CHIP_INTF_SOC, | ||
163 | }; | 164 | }; |
164 | 165 | ||
165 | /* | 166 | /* |
@@ -169,25 +170,26 @@ enum rt2x00_chip_intf { | |||
169 | */ | 170 | */ |
170 | struct rt2x00_chip { | 171 | struct rt2x00_chip { |
171 | u16 rt; | 172 | u16 rt; |
172 | #define RT2460 0x0101 | 173 | #define RT2460 0x2460 |
173 | #define RT2560 0x0201 | 174 | #define RT2560 0x2560 |
174 | #define RT2570 0x1201 | 175 | #define RT2570 0x2570 |
175 | #define RT2561s 0x0301 /* Turbo */ | 176 | #define RT2661 0x2661 |
176 | #define RT2561 0x0302 | 177 | #define RT2573 0x2573 |
177 | #define RT2661 0x0401 | 178 | #define RT2860 0x2860 /* 2.4GHz PCI/CB */ |
178 | #define RT2571 0x1300 | 179 | #define RT2870 0x2870 |
179 | #define RT2860 0x0601 /* 2.4GHz PCI/CB */ | 180 | #define RT2872 0x2872 |
180 | #define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ | ||
181 | #define RT2890 0x0701 /* 2.4GHz PCIe */ | ||
182 | #define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ | ||
183 | #define RT2880 0x2880 /* WSOC */ | 181 | #define RT2880 0x2880 /* WSOC */ |
182 | #define RT2883 0x2883 /* WSOC */ | ||
183 | #define RT2890 0x2890 /* 2.4GHz PCIe */ | ||
184 | #define RT3052 0x3052 /* WSOC */ | 184 | #define RT3052 0x3052 /* WSOC */ |
185 | #define RT3070 0x3070 | ||
186 | #define RT3071 0x3071 | ||
185 | #define RT3090 0x3090 /* 2.4GHz PCIe */ | 187 | #define RT3090 0x3090 /* 2.4GHz PCIe */ |
186 | #define RT2870 0x1600 | 188 | #define RT3390 0x3390 |
187 | #define RT3070 0x1800 | 189 | #define RT3572 0x3572 |
188 | 190 | ||
189 | u16 rf; | 191 | u16 rf; |
190 | u32 rev; | 192 | u16 rev; |
191 | 193 | ||
192 | enum rt2x00_chip_intf intf; | 194 | enum rt2x00_chip_intf intf; |
193 | }; | 195 | }; |
@@ -917,29 +919,14 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, | |||
917 | * Chipset handlers | 919 | * Chipset handlers |
918 | */ | 920 | */ |
919 | static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, | 921 | static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, |
920 | const u16 rt, const u16 rf, const u32 rev) | 922 | const u16 rt, const u16 rf, const u16 rev) |
921 | { | 923 | { |
922 | rt2x00dev->chip.rt = rt; | 924 | rt2x00dev->chip.rt = rt; |
923 | rt2x00dev->chip.rf = rf; | 925 | rt2x00dev->chip.rf = rf; |
924 | rt2x00dev->chip.rev = rev; | 926 | rt2x00dev->chip.rev = rev; |
925 | } | ||
926 | |||
927 | static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, | ||
928 | const u16 rt) | ||
929 | { | ||
930 | rt2x00dev->chip.rt = rt; | ||
931 | } | ||
932 | |||
933 | static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, | ||
934 | const u16 rf, const u32 rev) | ||
935 | { | ||
936 | rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); | ||
937 | } | ||
938 | 927 | ||
939 | static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) | ||
940 | { | ||
941 | INFO(rt2x00dev, | 928 | INFO(rt2x00dev, |
942 | "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", | 929 | "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n", |
943 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 930 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
944 | } | 931 | } |
945 | 932 | ||
@@ -953,17 +940,11 @@ static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) | |||
953 | return (rt2x00dev->chip.rf == rf); | 940 | return (rt2x00dev->chip.rf == rf); |
954 | } | 941 | } |
955 | 942 | ||
956 | static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev) | 943 | static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) |
957 | { | 944 | { |
958 | return rt2x00dev->chip.rev; | 945 | return rt2x00dev->chip.rev; |
959 | } | 946 | } |
960 | 947 | ||
961 | static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev, | ||
962 | const u32 mask, const u32 rev) | ||
963 | { | ||
964 | return ((rt2x00dev->chip.rev & mask) == rev); | ||
965 | } | ||
966 | |||
967 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | 948 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, |
968 | enum rt2x00_chip_intf intf) | 949 | enum rt2x00_chip_intf intf) |
969 | { | 950 | { |
@@ -976,16 +957,21 @@ static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, | |||
976 | return (rt2x00dev->chip.intf == intf); | 957 | return (rt2x00dev->chip.intf == intf); |
977 | } | 958 | } |
978 | 959 | ||
979 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) | 960 | static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev) |
980 | { | 961 | { |
981 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | 962 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); |
982 | } | 963 | } |
983 | 964 | ||
984 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) | 965 | static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev) |
985 | { | 966 | { |
986 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); | 967 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
987 | } | 968 | } |
988 | 969 | ||
970 | static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) | ||
971 | { | ||
972 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); | ||
973 | } | ||
974 | |||
989 | /** | 975 | /** |
990 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. | 976 | * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. |
991 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 977 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 7d323a763b54..70c04c282efc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c | |||
@@ -184,7 +184,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, | |||
184 | dump_hdr->data_length = cpu_to_le32(skb->len); | 184 | dump_hdr->data_length = cpu_to_le32(skb->len); |
185 | dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); | 185 | dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); |
186 | dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); | 186 | dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); |
187 | dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); | 187 | dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev); |
188 | dump_hdr->type = cpu_to_le16(type); | 188 | dump_hdr->type = cpu_to_le16(type); |
189 | dump_hdr->queue_index = desc->entry->queue->qid; | 189 | dump_hdr->queue_index = desc->entry->queue->qid; |
190 | dump_hdr->entry_index = desc->entry->entry_idx; | 190 | dump_hdr->entry_index = desc->entry->entry_idx; |
@@ -573,7 +573,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, | |||
573 | blob->data = data; | 573 | blob->data = data; |
574 | data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); | 574 | data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); |
575 | data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); | 575 | data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); |
576 | data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev); | 576 | data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev); |
577 | data += sprintf(data, "\n"); | 577 | data += sprintf(data, "\n"); |
578 | data += sprintf(data, "register\tbase\twords\twordsize\n"); | 578 | data += sprintf(data, "register\tbase\twords\twordsize\n"); |
579 | data += sprintf(data, "csr\t%d\t%d\t%d\n", | 579 | data += sprintf(data, "csr\t%d\t%d\t%d\n", |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 801be436cf1d..047123b766fc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -272,7 +272,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
272 | struct ieee80211_hw *hw; | 272 | struct ieee80211_hw *hw; |
273 | struct rt2x00_dev *rt2x00dev; | 273 | struct rt2x00_dev *rt2x00dev; |
274 | int retval; | 274 | int retval; |
275 | u16 chip; | ||
276 | 275 | ||
277 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); | 276 | retval = pci_request_regions(pci_dev, pci_name(pci_dev)); |
278 | if (retval) { | 277 | if (retval) { |
@@ -315,12 +314,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) | |||
315 | 314 | ||
316 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | 315 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); |
317 | 316 | ||
318 | /* | ||
319 | * Determine RT chipset by reading PCI header. | ||
320 | */ | ||
321 | pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); | ||
322 | rt2x00_set_chip_rt(rt2x00dev, chip); | ||
323 | |||
324 | retval = rt2x00pci_alloc_reg(rt2x00dev); | 317 | retval = rt2x00pci_alloc_reg(rt2x00dev); |
325 | if (retval) | 318 | if (retval) |
326 | goto exit_free_device; | 319 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index d4f9449ab0a4..8149ff68410a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define RT2X00PCI_H | 27 | #define RT2X00PCI_H |
28 | 28 | ||
29 | #include <linux/io.h> | 29 | #include <linux/io.h> |
30 | #include <linux/pci.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * This variable should be used with the | 33 | * This variable should be used with the |
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 19e684f8ffa1..4efdc96010f6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c | |||
@@ -71,9 +71,7 @@ exit: | |||
71 | return -ENOMEM; | 71 | return -ENOMEM; |
72 | } | 72 | } |
73 | 73 | ||
74 | int rt2x00soc_probe(struct platform_device *pdev, | 74 | int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops) |
75 | const unsigned short chipset, | ||
76 | const struct rt2x00_ops *ops) | ||
77 | { | 75 | { |
78 | struct ieee80211_hw *hw; | 76 | struct ieee80211_hw *hw; |
79 | struct rt2x00_dev *rt2x00dev; | 77 | struct rt2x00_dev *rt2x00dev; |
@@ -94,12 +92,7 @@ int rt2x00soc_probe(struct platform_device *pdev, | |||
94 | rt2x00dev->irq = platform_get_irq(pdev, 0); | 92 | rt2x00dev->irq = platform_get_irq(pdev, 0); |
95 | rt2x00dev->name = pdev->dev.driver->name; | 93 | rt2x00dev->name = pdev->dev.driver->name; |
96 | 94 | ||
97 | /* | 95 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC); |
98 | * SoC devices mimic PCI behavior. | ||
99 | */ | ||
100 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); | ||
101 | |||
102 | rt2x00_set_chip_rt(rt2x00dev, chipset); | ||
103 | 96 | ||
104 | retval = rt2x00soc_alloc_reg(rt2x00dev); | 97 | retval = rt2x00soc_alloc_reg(rt2x00dev); |
105 | if (retval) | 98 | if (retval) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 8a3416624af5..4739edfe2f00 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h | |||
@@ -28,18 +28,10 @@ | |||
28 | 28 | ||
29 | #define KSEG1ADDR(__ptr) __ptr | 29 | #define KSEG1ADDR(__ptr) __ptr |
30 | 30 | ||
31 | #define __rt2x00soc_probe(__chipset, __ops) \ | ||
32 | static int __rt2x00soc_probe(struct platform_device *pdev) \ | ||
33 | { \ | ||
34 | return rt2x00soc_probe(pdev, (__chipset), (__ops)); \ | ||
35 | } | ||
36 | |||
37 | /* | 31 | /* |
38 | * SoC driver handlers. | 32 | * SoC driver handlers. |
39 | */ | 33 | */ |
40 | int rt2x00soc_probe(struct platform_device *pdev, | 34 | int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops); |
41 | const unsigned short chipset, | ||
42 | const struct rt2x00_ops *ops); | ||
43 | int rt2x00soc_remove(struct platform_device *pdev); | 35 | int rt2x00soc_remove(struct platform_device *pdev); |
44 | #ifdef CONFIG_PM | 36 | #ifdef CONFIG_PM |
45 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); | 37 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 74de53e68b4e..e2da928dd9f0 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1131,16 +1131,18 @@ dynamic_cca_tune: | |||
1131 | */ | 1131 | */ |
1132 | static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | 1132 | static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) |
1133 | { | 1133 | { |
1134 | u16 chip; | ||
1134 | char *fw_name; | 1135 | char *fw_name; |
1135 | 1136 | ||
1136 | switch (rt2x00dev->chip.rt) { | 1137 | pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip); |
1137 | case RT2561: | 1138 | switch (chip) { |
1139 | case RT2561_PCI_ID: | ||
1138 | fw_name = FIRMWARE_RT2561; | 1140 | fw_name = FIRMWARE_RT2561; |
1139 | break; | 1141 | break; |
1140 | case RT2561s: | 1142 | case RT2561s_PCI_ID: |
1141 | fw_name = FIRMWARE_RT2561s; | 1143 | fw_name = FIRMWARE_RT2561s; |
1142 | break; | 1144 | break; |
1143 | case RT2661: | 1145 | case RT2661_PCI_ID: |
1144 | fw_name = FIRMWARE_RT2661; | 1146 | fw_name = FIRMWARE_RT2661; |
1145 | break; | 1147 | break; |
1146 | default: | 1148 | default: |
@@ -2295,8 +2297,8 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2295 | */ | 2297 | */ |
2296 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 2298 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
2297 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | 2299 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); |
2298 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 2300 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
2299 | rt2x00_print_chip(rt2x00dev); | 2301 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
2300 | 2302 | ||
2301 | if (!rt2x00_rf(rt2x00dev, RF5225) && | 2303 | if (!rt2x00_rf(rt2x00dev, RF5225) && |
2302 | !rt2x00_rf(rt2x00dev, RF5325) && | 2304 | !rt2x00_rf(rt2x00dev, RF5325) && |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 8f13810622bd..df80f1af22a4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h | |||
@@ -28,6 +28,13 @@ | |||
28 | #define RT61PCI_H | 28 | #define RT61PCI_H |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * RT chip PCI IDs. | ||
32 | */ | ||
33 | #define RT2561s_PCI_ID 0x0301 | ||
34 | #define RT2561_PCI_ID 0x0302 | ||
35 | #define RT2661_PCI_ID 0x0401 | ||
36 | |||
37 | /* | ||
31 | * RF chip defines. | 38 | * RF chip defines. |
32 | */ | 39 | */ |
33 | #define RF5225 0x0001 | 40 | #define RF5225 0x0001 |
@@ -225,6 +232,8 @@ struct hw_pairwise_ta_entry { | |||
225 | * MAC_CSR0: ASIC revision number. | 232 | * MAC_CSR0: ASIC revision number. |
226 | */ | 233 | */ |
227 | #define MAC_CSR0 0x3000 | 234 | #define MAC_CSR0 0x3000 |
235 | #define MAC_CSR0_REVISION FIELD32(0x0000000f) | ||
236 | #define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) | ||
228 | 237 | ||
229 | /* | 238 | /* |
230 | * MAC_CSR1: System control register. | 239 | * MAC_CSR1: System control register. |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 3781eb7b4aa0..f39a8ed17841 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1820,11 +1820,10 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1820 | */ | 1820 | */ |
1821 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1821 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1822 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1822 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1823 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1823 | rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), |
1824 | rt2x00_print_chip(rt2x00dev); | 1824 | value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); |
1825 | 1825 | ||
1826 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || | 1826 | if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) { |
1827 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { | ||
1828 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1827 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1829 | return -ENODEV; | 1828 | return -ENODEV; |
1830 | } | 1829 | } |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 7942f810e928..7abe7eb14555 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h | |||
@@ -142,6 +142,8 @@ struct hw_pairwise_ta_entry { | |||
142 | * MAC_CSR0: ASIC revision number. | 142 | * MAC_CSR0: ASIC revision number. |
143 | */ | 143 | */ |
144 | #define MAC_CSR0 0x3000 | 144 | #define MAC_CSR0 0x3000 |
145 | #define MAC_CSR0_REVISION FIELD32(0x0000000f) | ||
146 | #define MAC_CSR0_CHIPSET FIELD32(0x000ffff0) | ||
145 | 147 | ||
146 | /* | 148 | /* |
147 | * MAC_CSR1: System control register. | 149 | * MAC_CSR1: System control register. |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index f82aa8b4bdde..4637337d5ce6 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
@@ -241,5 +241,5 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev) | |||
241 | cancel_delayed_work_sync(&priv->led_off); | 241 | cancel_delayed_work_sync(&priv->led_off); |
242 | cancel_delayed_work_sync(&priv->led_on); | 242 | cancel_delayed_work_sync(&priv->led_on); |
243 | } | 243 | } |
244 | #endif /* def CONFIG_RTL8187_LED */ | 244 | #endif /* def CONFIG_RTL8187_LEDS */ |
245 | 245 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h index efe8041bdda4..d743c96d4a20 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h | |||
@@ -54,6 +54,6 @@ struct rtl8187_led { | |||
54 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); | 54 | void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); |
55 | void rtl8187_leds_exit(struct ieee80211_hw *dev); | 55 | void rtl8187_leds_exit(struct ieee80211_hw *dev); |
56 | 56 | ||
57 | #endif /* def CONFIG_RTL8187_LED */ | 57 | #endif /* def CONFIG_RTL8187_LEDS */ |
58 | 58 | ||
59 | #endif /* RTL8187_LED_H */ | 59 | #endif /* RTL8187_LED_H */ |
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 62e37ad01cc0..f47ec94c16dc 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile | |||
@@ -10,5 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o | |||
10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ | 10 | wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ |
11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ | 11 | wl1271_event.o wl1271_tx.o wl1271_rx.o \ |
12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ | 12 | wl1271_ps.o wl1271_acx.o wl1271_boot.o \ |
13 | wl1271_init.o wl1271_debugfs.o | 13 | wl1271_init.o wl1271_debugfs.o wl1271_io.o |
14 | |||
15 | wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o | ||
14 | obj-$(CONFIG_WL1271) += wl1271.o | 16 | obj-$(CONFIG_WL1271) += wl1271.o |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index d0938db043b3..97ea5096bc8c 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -43,7 +43,7 @@ enum { | |||
43 | DEBUG_SPI = BIT(1), | 43 | DEBUG_SPI = BIT(1), |
44 | DEBUG_BOOT = BIT(2), | 44 | DEBUG_BOOT = BIT(2), |
45 | DEBUG_MAILBOX = BIT(3), | 45 | DEBUG_MAILBOX = BIT(3), |
46 | DEBUG_NETLINK = BIT(4), | 46 | DEBUG_TESTMODE = BIT(4), |
47 | DEBUG_EVENT = BIT(5), | 47 | DEBUG_EVENT = BIT(5), |
48 | DEBUG_TX = BIT(6), | 48 | DEBUG_TX = BIT(6), |
49 | DEBUG_RX = BIT(7), | 49 | DEBUG_RX = BIT(7), |
@@ -109,7 +109,33 @@ enum { | |||
109 | 109 | ||
110 | #define WL1271_FW_NAME "wl1271-fw.bin" | 110 | #define WL1271_FW_NAME "wl1271-fw.bin" |
111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | #define WL1271_NVS_LEN 468 | 112 | |
113 | /* NVS data structure */ | ||
114 | #define WL1271_NVS_SECTION_SIZE 468 | ||
115 | |||
116 | #define WL1271_NVS_GENERAL_PARAMS_SIZE 57 | ||
117 | #define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \ | ||
118 | (WL1271_NVS_GENERAL_PARAMS_SIZE + 1) | ||
119 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17 | ||
120 | #define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \ | ||
121 | (WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1) | ||
122 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65 | ||
123 | #define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \ | ||
124 | (WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1) | ||
125 | #define WL1271_NVS_FEM_COUNT 2 | ||
126 | #define WL1271_NVS_INI_SPARE_SIZE 124 | ||
127 | |||
128 | struct wl1271_nvs_file { | ||
129 | /* NVS section */ | ||
130 | u8 nvs[WL1271_NVS_SECTION_SIZE]; | ||
131 | |||
132 | /* INI section */ | ||
133 | u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED]; | ||
134 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED]; | ||
135 | u8 dyn_radio_params[WL1271_NVS_FEM_COUNT] | ||
136 | [WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED]; | ||
137 | u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE]; | ||
138 | } __attribute__ ((packed)); | ||
113 | 139 | ||
114 | /* | 140 | /* |
115 | * Enable/disable 802.11a support for WL1273 | 141 | * Enable/disable 802.11a support for WL1273 |
@@ -342,8 +368,7 @@ struct wl1271 { | |||
342 | 368 | ||
343 | u8 *fw; | 369 | u8 *fw; |
344 | size_t fw_len; | 370 | size_t fw_len; |
345 | u8 *nvs; | 371 | struct wl1271_nvs_file *nvs; |
346 | size_t nvs_len; | ||
347 | 372 | ||
348 | u8 bssid[ETH_ALEN]; | 373 | u8 bssid[ETH_ALEN]; |
349 | u8 mac_addr[ETH_ALEN]; | 374 | u8 mac_addr[ETH_ALEN]; |
@@ -461,6 +486,7 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
461 | 486 | ||
462 | static inline bool wl1271_11a_enabled(void) | 487 | static inline bool wl1271_11a_enabled(void) |
463 | { | 488 | { |
489 | /* FIXME: this could be determined based on the NVS-INI file */ | ||
464 | #ifdef WL1271_80211A_ENABLED | 490 | #ifdef WL1271_80211A_ENABLED |
465 | return true; | 491 | return true; |
466 | #else | 492 | #else |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 0b3434843476..60f10dce4800 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -830,12 +830,14 @@ out: | |||
830 | return ret; | 830 | return ret; |
831 | } | 831 | } |
832 | 832 | ||
833 | int wl1271_acx_ac_cfg(struct wl1271 *wl) | 833 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
834 | u8 aifsn, u16 txop) | ||
834 | { | 835 | { |
835 | struct acx_ac_cfg *acx; | 836 | struct acx_ac_cfg *acx; |
836 | int i, ret = 0; | 837 | int ret = 0; |
837 | 838 | ||
838 | wl1271_debug(DEBUG_ACX, "acx access category config"); | 839 | wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d " |
840 | "aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop); | ||
839 | 841 | ||
840 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 842 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
841 | 843 | ||
@@ -844,21 +846,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl) | |||
844 | goto out; | 846 | goto out; |
845 | } | 847 | } |
846 | 848 | ||
847 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | 849 | acx->ac = ac; |
848 | struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]); | 850 | acx->cw_min = cw_min; |
849 | acx->ac = c->ac; | 851 | acx->cw_max = cpu_to_le16(cw_max); |
850 | acx->cw_min = c->cw_min; | 852 | acx->aifsn = aifsn; |
851 | acx->cw_max = cpu_to_le16(c->cw_max); | 853 | acx->tx_op_limit = cpu_to_le16(txop); |
852 | acx->aifsn = c->aifsn; | ||
853 | acx->reserved = 0; | ||
854 | acx->tx_op_limit = cpu_to_le16(c->tx_op_limit); | ||
855 | 854 | ||
856 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | 855 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); |
857 | if (ret < 0) { | 856 | if (ret < 0) { |
858 | wl1271_warning("Setting of access category " | 857 | wl1271_warning("acx ac cfg failed: %d", ret); |
859 | "config: %d", ret); | 858 | goto out; |
860 | goto out; | ||
861 | } | ||
862 | } | 859 | } |
863 | 860 | ||
864 | out: | 861 | out: |
@@ -866,10 +863,12 @@ out: | |||
866 | return ret; | 863 | return ret; |
867 | } | 864 | } |
868 | 865 | ||
869 | int wl1271_acx_tid_cfg(struct wl1271 *wl) | 866 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
867 | u8 tsid, u8 ps_scheme, u8 ack_policy, | ||
868 | u32 apsd_conf0, u32 apsd_conf1) | ||
870 | { | 869 | { |
871 | struct acx_tid_config *acx; | 870 | struct acx_tid_config *acx; |
872 | int i, ret = 0; | 871 | int ret = 0; |
873 | 872 | ||
874 | wl1271_debug(DEBUG_ACX, "acx tid config"); | 873 | wl1271_debug(DEBUG_ACX, "acx tid config"); |
875 | 874 | ||
@@ -880,21 +879,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl) | |||
880 | goto out; | 879 | goto out; |
881 | } | 880 | } |
882 | 881 | ||
883 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | 882 | acx->queue_id = queue_id; |
884 | struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]); | 883 | acx->channel_type = channel_type; |
885 | acx->queue_id = c->queue_id; | 884 | acx->tsid = tsid; |
886 | acx->channel_type = c->channel_type; | 885 | acx->ps_scheme = ps_scheme; |
887 | acx->tsid = c->tsid; | 886 | acx->ack_policy = ack_policy; |
888 | acx->ps_scheme = c->ps_scheme; | 887 | acx->apsd_conf[0] = cpu_to_le32(apsd_conf0); |
889 | acx->ack_policy = c->ack_policy; | 888 | acx->apsd_conf[1] = cpu_to_le32(apsd_conf1); |
890 | acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]); | ||
891 | acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]); | ||
892 | 889 | ||
893 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | 890 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); |
894 | if (ret < 0) { | 891 | if (ret < 0) { |
895 | wl1271_warning("Setting of tid config failed: %d", ret); | 892 | wl1271_warning("Setting of tid config failed: %d", ret); |
896 | goto out; | 893 | goto out; |
897 | } | ||
898 | } | 894 | } |
899 | 895 | ||
900 | out: | 896 | out: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 1bb63af64f0e..aeccc98581eb 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | 4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. |
5 | * Copyright (C) 2008-2009 Nokia Corporation | 5 | * Copyright (C) 2008-2010 Nokia Corporation |
6 | * | 6 | * |
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
8 | * | 8 | * |
@@ -348,7 +348,7 @@ struct acx_beacon_filter_option { | |||
348 | * ACXBeaconFilterEntry (not 221) | 348 | * ACXBeaconFilterEntry (not 221) |
349 | * Byte Offset Size (Bytes) Definition | 349 | * Byte Offset Size (Bytes) Definition |
350 | * =========== ============ ========== | 350 | * =========== ============ ========== |
351 | * 0 1 IE identifier | 351 | * 0 1 IE identifier |
352 | * 1 1 Treatment bit mask | 352 | * 1 1 Treatment bit mask |
353 | * | 353 | * |
354 | * ACXBeaconFilterEntry (221) | 354 | * ACXBeaconFilterEntry (221) |
@@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table { | |||
381 | struct acx_header header; | 381 | struct acx_header header; |
382 | 382 | ||
383 | u8 num_ie; | 383 | u8 num_ie; |
384 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
385 | u8 pad[3]; | 384 | u8 pad[3]; |
385 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
386 | } __attribute__ ((packed)); | 386 | } __attribute__ ((packed)); |
387 | 387 | ||
388 | struct acx_conn_monit_params { | 388 | struct acx_conn_monit_params { |
@@ -1070,8 +1070,11 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, | |||
1070 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); |
1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, |
1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | u8 aifsn, u16 txop); |
1075 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, | ||
1076 | u8 tsid, u8 ps_scheme, u8 ack_policy, | ||
1077 | u32 apsd_conf0, u32 apsd_conf1); | ||
1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1078 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
1076 | int wl1271_acx_tx_config_options(struct wl1271 *wl); | 1079 | int wl1271_acx_tx_config_options(struct wl1271 *wl); |
1077 | int wl1271_acx_mem_cfg(struct wl1271 *wl); | 1080 | int wl1271_acx_mem_cfg(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index e803b876f3f0..2be76ee42bb9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "wl1271_reg.h" | 27 | #include "wl1271_reg.h" |
28 | #include "wl1271_boot.h" | 28 | #include "wl1271_boot.h" |
29 | #include "wl1271_spi.h" | 29 | #include "wl1271_spi.h" |
30 | #include "wl1271_io.h" | ||
30 | #include "wl1271_event.h" | 31 | #include "wl1271_event.h" |
31 | 32 | ||
32 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | 33 | static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { |
@@ -93,19 +94,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
93 | u32 cpu_ctrl; | 94 | u32 cpu_ctrl; |
94 | 95 | ||
95 | /* 10.5.0 run the firmware (I) */ | 96 | /* 10.5.0 run the firmware (I) */ |
96 | cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL); | 97 | cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL); |
97 | 98 | ||
98 | /* 10.5.1 run the firmware (II) */ | 99 | /* 10.5.1 run the firmware (II) */ |
99 | cpu_ctrl |= flag; | 100 | cpu_ctrl |= flag; |
100 | wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 101 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
101 | } | 102 | } |
102 | 103 | ||
103 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 104 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
104 | { | 105 | { |
105 | struct wl1271_static_data static_data; | 106 | struct wl1271_static_data static_data; |
106 | 107 | ||
107 | wl1271_spi_read(wl, wl->cmd_box_addr, | 108 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), |
108 | &static_data, sizeof(static_data), false); | 109 | false); |
109 | 110 | ||
110 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 111 | strncpy(wl->chip.fw_ver, static_data.fw_version, |
111 | sizeof(wl->chip.fw_ver)); | 112 | sizeof(wl->chip.fw_ver)); |
@@ -164,7 +165,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
164 | memcpy(chunk, p, CHUNK_SIZE); | 165 | memcpy(chunk, p, CHUNK_SIZE); |
165 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 166 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
166 | p, addr); | 167 | p, addr); |
167 | wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false); | 168 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); |
168 | 169 | ||
169 | chunk_num++; | 170 | chunk_num++; |
170 | } | 171 | } |
@@ -175,7 +176,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
175 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | 176 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); |
176 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 177 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
177 | fw_data_len % CHUNK_SIZE, p, addr); | 178 | fw_data_len % CHUNK_SIZE, p, addr); |
178 | wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | 179 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
179 | 180 | ||
180 | kfree(chunk); | 181 | kfree(chunk); |
181 | return 0; | 182 | return 0; |
@@ -219,29 +220,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
219 | size_t nvs_len, burst_len; | 220 | size_t nvs_len, burst_len; |
220 | int i; | 221 | int i; |
221 | u32 dest_addr, val; | 222 | u32 dest_addr, val; |
222 | u8 *nvs_ptr, *nvs, *nvs_aligned; | 223 | u8 *nvs_ptr, *nvs_aligned; |
223 | 224 | ||
224 | nvs = wl->nvs; | 225 | if (wl->nvs == NULL) |
225 | if (nvs == NULL) | ||
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | if (wl->nvs_len < WL1271_NVS_LEN) | ||
229 | return -EINVAL; | ||
230 | |||
231 | nvs_ptr = nvs; | ||
232 | |||
233 | /* only the first part of the NVS needs to be uploaded */ | 228 | /* only the first part of the NVS needs to be uploaded */ |
234 | nvs_len = WL1271_NVS_LEN; | 229 | nvs_len = sizeof(wl->nvs->nvs); |
235 | 230 | nvs_ptr = (u8 *)wl->nvs->nvs; | |
236 | /* FIXME: read init settings from the remaining part of the NVS */ | ||
237 | |||
238 | /* Update the device MAC address into the nvs */ | ||
239 | nvs[11] = wl->mac_addr[0]; | ||
240 | nvs[10] = wl->mac_addr[1]; | ||
241 | nvs[6] = wl->mac_addr[2]; | ||
242 | nvs[5] = wl->mac_addr[3]; | ||
243 | nvs[4] = wl->mac_addr[4]; | ||
244 | nvs[3] = wl->mac_addr[5]; | ||
245 | 231 | ||
246 | /* | 232 | /* |
247 | * Layout before the actual NVS tables: | 233 | * Layout before the actual NVS tables: |
@@ -271,7 +257,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
271 | wl1271_debug(DEBUG_BOOT, | 257 | wl1271_debug(DEBUG_BOOT, |
272 | "nvs burst write 0x%x: 0x%x", | 258 | "nvs burst write 0x%x: 0x%x", |
273 | dest_addr, val); | 259 | dest_addr, val); |
274 | wl1271_spi_write32(wl, dest_addr, val); | 260 | wl1271_write32(wl, dest_addr, val); |
275 | 261 | ||
276 | nvs_ptr += 4; | 262 | nvs_ptr += 4; |
277 | dest_addr += 4; | 263 | dest_addr += 4; |
@@ -283,7 +269,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
283 | * is 7 bytes further. | 269 | * is 7 bytes further. |
284 | */ | 270 | */ |
285 | nvs_ptr += 7; | 271 | nvs_ptr += 7; |
286 | nvs_len -= nvs_ptr - nvs; | 272 | nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs; |
287 | nvs_len = ALIGN(nvs_len, 4); | 273 | nvs_len = ALIGN(nvs_len, 4); |
288 | 274 | ||
289 | /* FIXME: The driver sets the partition here, but this is not needed, | 275 | /* FIXME: The driver sets the partition here, but this is not needed, |
@@ -292,15 +278,20 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
292 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 278 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
293 | 279 | ||
294 | /* Copy the NVS tables to a new block to ensure alignment */ | 280 | /* Copy the NVS tables to a new block to ensure alignment */ |
295 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 281 | /* FIXME: We jump 3 more bytes before uploading the NVS. It seems |
296 | if (!nvs_aligned) | 282 | that our NVS files have three extra zeros here. I'm not sure whether |
297 | return -ENOMEM; | 283 | the problem is in our NVS generation or we should really jumpt these |
284 | 3 bytes here */ | ||
285 | nvs_ptr += 3; | ||
286 | |||
287 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if | ||
288 | (!nvs_aligned) return -ENOMEM; | ||
298 | 289 | ||
299 | /* And finally we upload the NVS tables */ | 290 | /* And finally we upload the NVS tables */ |
300 | /* FIXME: In wl1271, we upload everything at once. | 291 | /* FIXME: In wl1271, we upload everything at once. |
301 | No endianness handling needed here?! The ref driver doesn't do | 292 | No endianness handling needed here?! The ref driver doesn't do |
302 | anything about it at this point */ | 293 | anything about it at this point */ |
303 | wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); | 294 | wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
304 | 295 | ||
305 | kfree(nvs_aligned); | 296 | kfree(nvs_aligned); |
306 | return 0; | 297 | return 0; |
@@ -309,9 +300,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
309 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 300 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
310 | { | 301 | { |
311 | enable_irq(wl->irq); | 302 | enable_irq(wl->irq); |
312 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 303 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
313 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 304 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
314 | wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 305 | wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
315 | } | 306 | } |
316 | 307 | ||
317 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 308 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
@@ -320,13 +311,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
320 | u32 boot_data; | 311 | u32 boot_data; |
321 | 312 | ||
322 | /* perform soft reset */ | 313 | /* perform soft reset */ |
323 | wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET, | 314 | wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
324 | ACX_SLV_SOFT_RESET_BIT); | ||
325 | 315 | ||
326 | /* SOFT_RESET is self clearing */ | 316 | /* SOFT_RESET is self clearing */ |
327 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 317 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
328 | while (1) { | 318 | while (1) { |
329 | boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET); | 319 | boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET); |
330 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 320 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
331 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 321 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
332 | break; | 322 | break; |
@@ -342,10 +332,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
342 | } | 332 | } |
343 | 333 | ||
344 | /* disable Rx/Tx */ | 334 | /* disable Rx/Tx */ |
345 | wl1271_spi_write32(wl, ENABLE, 0x0); | 335 | wl1271_write32(wl, ENABLE, 0x0); |
346 | 336 | ||
347 | /* disable auto calibration on start*/ | 337 | /* disable auto calibration on start*/ |
348 | wl1271_spi_write32(wl, SPARE_A2, 0xffff); | 338 | wl1271_write32(wl, SPARE_A2, 0xffff); |
349 | 339 | ||
350 | return 0; | 340 | return 0; |
351 | } | 341 | } |
@@ -357,7 +347,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
357 | 347 | ||
358 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 348 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
359 | 349 | ||
360 | chip_id = wl1271_spi_read32(wl, CHIP_ID_B); | 350 | chip_id = wl1271_read32(wl, CHIP_ID_B); |
361 | 351 | ||
362 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 352 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
363 | 353 | ||
@@ -370,8 +360,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
370 | loop = 0; | 360 | loop = 0; |
371 | while (loop++ < INIT_LOOP) { | 361 | while (loop++ < INIT_LOOP) { |
372 | udelay(INIT_LOOP_DELAY); | 362 | udelay(INIT_LOOP_DELAY); |
373 | interrupt = wl1271_spi_read32(wl, | 363 | interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
374 | ACX_REG_INTERRUPT_NO_CLEAR); | ||
375 | 364 | ||
376 | if (interrupt == 0xffffffff) { | 365 | if (interrupt == 0xffffffff) { |
377 | wl1271_error("error reading hardware complete " | 366 | wl1271_error("error reading hardware complete " |
@@ -380,8 +369,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
380 | } | 369 | } |
381 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 370 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
382 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { | 371 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { |
383 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, | 372 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
384 | WL1271_ACX_INTR_INIT_COMPLETE); | 373 | WL1271_ACX_INTR_INIT_COMPLETE); |
385 | break; | 374 | break; |
386 | } | 375 | } |
387 | } | 376 | } |
@@ -393,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
393 | } | 382 | } |
394 | 383 | ||
395 | /* get hardware config command mail box */ | 384 | /* get hardware config command mail box */ |
396 | wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR); | 385 | wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR); |
397 | 386 | ||
398 | /* get hardware config event mail box */ | 387 | /* get hardware config event mail box */ |
399 | wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); | 388 | wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
400 | 389 | ||
401 | /* set the working partition to its "running" mode offset */ | 390 | /* set the working partition to its "running" mode offset */ |
402 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 391 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
@@ -469,9 +458,9 @@ int wl1271_boot(struct wl1271 *wl) | |||
469 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | 458 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
470 | } | 459 | } |
471 | 460 | ||
472 | wl1271_spi_write32(wl, PLL_PARAMETERS, clk); | 461 | wl1271_write32(wl, PLL_PARAMETERS, clk); |
473 | 462 | ||
474 | pause = wl1271_spi_read32(wl, PLL_PARAMETERS); | 463 | pause = wl1271_read32(wl, PLL_PARAMETERS); |
475 | 464 | ||
476 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 465 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
477 | 466 | ||
@@ -480,10 +469,10 @@ int wl1271_boot(struct wl1271 *wl) | |||
480 | * 0x3ff (magic number ). How does | 469 | * 0x3ff (magic number ). How does |
481 | * this work?! */ | 470 | * this work?! */ |
482 | pause |= WU_COUNTER_PAUSE_VAL; | 471 | pause |= WU_COUNTER_PAUSE_VAL; |
483 | wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause); | 472 | wl1271_write32(wl, WU_COUNTER_PAUSE, pause); |
484 | 473 | ||
485 | /* Continue the ELP wake up sequence */ | 474 | /* Continue the ELP wake up sequence */ |
486 | wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 475 | wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
487 | udelay(500); | 476 | udelay(500); |
488 | 477 | ||
489 | wl1271_set_partition(wl, &part_table[PART_DRPW]); | 478 | wl1271_set_partition(wl, &part_table[PART_DRPW]); |
@@ -493,18 +482,18 @@ int wl1271_boot(struct wl1271 *wl) | |||
493 | before taking DRPw out of reset */ | 482 | before taking DRPw out of reset */ |
494 | 483 | ||
495 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); | 484 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); |
496 | clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START); | 485 | clk = wl1271_read32(wl, DRPW_SCRATCH_START); |
497 | 486 | ||
498 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 487 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
499 | 488 | ||
500 | /* 2 */ | 489 | /* 2 */ |
501 | clk |= (REF_CLOCK << 1) << 4; | 490 | clk |= (REF_CLOCK << 1) << 4; |
502 | wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk); | 491 | wl1271_write32(wl, DRPW_SCRATCH_START, clk); |
503 | 492 | ||
504 | wl1271_set_partition(wl, &part_table[PART_WORK]); | 493 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
505 | 494 | ||
506 | /* Disable interrupts */ | 495 | /* Disable interrupts */ |
507 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 496 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
508 | 497 | ||
509 | ret = wl1271_boot_soft_reset(wl); | 498 | ret = wl1271_boot_soft_reset(wl); |
510 | if (ret < 0) | 499 | if (ret < 0) |
@@ -519,23 +508,22 @@ int wl1271_boot(struct wl1271 *wl) | |||
519 | * ACX_EEPROMLESS_IND_REG */ | 508 | * ACX_EEPROMLESS_IND_REG */ |
520 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 509 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
521 | 510 | ||
522 | wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG, | 511 | wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); |
523 | ACX_EEPROMLESS_IND_REG); | ||
524 | 512 | ||
525 | tmp = wl1271_spi_read32(wl, CHIP_ID_B); | 513 | tmp = wl1271_read32(wl, CHIP_ID_B); |
526 | 514 | ||
527 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 515 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
528 | 516 | ||
529 | /* 6. read the EEPROM parameters */ | 517 | /* 6. read the EEPROM parameters */ |
530 | tmp = wl1271_spi_read32(wl, SCR_PAD2); | 518 | tmp = wl1271_read32(wl, SCR_PAD2); |
531 | 519 | ||
532 | ret = wl1271_boot_write_irq_polarity(wl); | 520 | ret = wl1271_boot_write_irq_polarity(wl); |
533 | if (ret < 0) | 521 | if (ret < 0) |
534 | goto out; | 522 | goto out; |
535 | 523 | ||
536 | /* FIXME: Need to check whether this is really what we want */ | 524 | /* FIXME: Need to check whether this is really what we want */ |
537 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 525 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
538 | WL1271_ACX_ALL_EVENTS_VECTOR); | 526 | WL1271_ACX_ALL_EVENTS_VECTOR); |
539 | 527 | ||
540 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 528 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
541 | * to upload_fw) */ | 529 | * to upload_fw) */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index a74259bb596b..36a64e06f290 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "wl1271.h" | 30 | #include "wl1271.h" |
31 | #include "wl1271_reg.h" | 31 | #include "wl1271_reg.h" |
32 | #include "wl1271_spi.h" | 32 | #include "wl1271_spi.h" |
33 | #include "wl1271_io.h" | ||
33 | #include "wl1271_acx.h" | 34 | #include "wl1271_acx.h" |
34 | #include "wl12xx_80211.h" | 35 | #include "wl12xx_80211.h" |
35 | #include "wl1271_cmd.h" | 36 | #include "wl1271_cmd.h" |
@@ -57,13 +58,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
57 | 58 | ||
58 | WARN_ON(len % 4 != 0); | 59 | WARN_ON(len % 4 != 0); |
59 | 60 | ||
60 | wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false); | 61 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); |
61 | 62 | ||
62 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | 63 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); |
63 | 64 | ||
64 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 65 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
65 | 66 | ||
66 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 67 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
67 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 68 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
68 | if (time_after(jiffies, timeout)) { | 69 | if (time_after(jiffies, timeout)) { |
69 | wl1271_error("command complete timeout"); | 70 | wl1271_error("command complete timeout"); |
@@ -73,13 +74,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
73 | 74 | ||
74 | msleep(1); | 75 | msleep(1); |
75 | 76 | ||
76 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 77 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
77 | } | 78 | } |
78 | 79 | ||
79 | /* read back the status code of the command */ | 80 | /* read back the status code of the command */ |
80 | if (res_len == 0) | 81 | if (res_len == 0) |
81 | res_len = sizeof(struct wl1271_cmd_header); | 82 | res_len = sizeof(struct wl1271_cmd_header); |
82 | wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 83 | wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); |
83 | 84 | ||
84 | status = le16_to_cpu(cmd->status); | 85 | status = le16_to_cpu(cmd->status); |
85 | if (status != CMD_STATUS_SUCCESS) { | 86 | if (status != CMD_STATUS_SUCCESS) { |
@@ -87,8 +88,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
87 | ret = -EIO; | 88 | ret = -EIO; |
88 | } | 89 | } |
89 | 90 | ||
90 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, | 91 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
91 | WL1271_ACX_INTR_CMD_COMPLETE); | 92 | WL1271_ACX_INTR_CMD_COMPLETE); |
92 | 93 | ||
93 | out: | 94 | out: |
94 | return ret; | 95 | return ret; |
@@ -191,43 +192,19 @@ static int wl1271_cmd_cal(struct wl1271 *wl) | |||
191 | int wl1271_cmd_general_parms(struct wl1271 *wl) | 192 | int wl1271_cmd_general_parms(struct wl1271 *wl) |
192 | { | 193 | { |
193 | struct wl1271_general_parms_cmd *gen_parms; | 194 | struct wl1271_general_parms_cmd *gen_parms; |
194 | struct conf_general_parms *g = &wl->conf.init.genparam; | ||
195 | int ret; | 195 | int ret; |
196 | 196 | ||
197 | if (!wl->nvs) | ||
198 | return -ENODEV; | ||
199 | |||
197 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | 200 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); |
198 | if (!gen_parms) | 201 | if (!gen_parms) |
199 | return -ENOMEM; | 202 | return -ENOMEM; |
200 | 203 | ||
201 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 204 | gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
202 | 205 | ||
203 | gen_parms->ref_clk = g->ref_clk; | 206 | memcpy(gen_parms->params, wl->nvs->general_params, |
204 | gen_parms->settling_time = g->settling_time; | 207 | WL1271_NVS_GENERAL_PARAMS_SIZE); |
205 | gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup; | ||
206 | gen_parms->dc2dcmode = g->dc2dcmode; | ||
207 | gen_parms->single_dual_band = g->single_dual_band; | ||
208 | gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect; | ||
209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; | ||
210 | gen_parms->settings = g->settings; | ||
211 | |||
212 | gen_parms->sr_state = g->sr_state; | ||
213 | |||
214 | memcpy(gen_parms->srf1, | ||
215 | g->srf1, | ||
216 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
217 | memcpy(gen_parms->srf2, | ||
218 | g->srf2, | ||
219 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
220 | memcpy(gen_parms->srf3, | ||
221 | g->srf3, | ||
222 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
223 | memcpy(gen_parms->sr_debug_table, | ||
224 | g->sr_debug_table, | ||
225 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
226 | |||
227 | gen_parms->sr_sen_n_p = g->sr_sen_n_p; | ||
228 | gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; | ||
229 | gen_parms->sr_sen_nrn = g->sr_sen_nrn; | ||
230 | gen_parms->sr_sen_prn = g->sr_sen_prn; | ||
231 | 208 | ||
232 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 209 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
233 | if (ret < 0) | 210 | if (ret < 0) |
@@ -240,8 +217,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
240 | int wl1271_cmd_radio_parms(struct wl1271 *wl) | 217 | int wl1271_cmd_radio_parms(struct wl1271 *wl) |
241 | { | 218 | { |
242 | struct wl1271_radio_parms_cmd *radio_parms; | 219 | struct wl1271_radio_parms_cmd *radio_parms; |
243 | struct conf_radio_parms *r = &wl->conf.init.radioparam; | 220 | struct conf_radio_parms *rparam = &wl->conf.init.radioparam; |
244 | int i, ret; | 221 | int ret; |
222 | |||
223 | if (!wl->nvs) | ||
224 | return -ENODEV; | ||
245 | 225 | ||
246 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | 226 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); |
247 | if (!radio_parms) | 227 | if (!radio_parms) |
@@ -249,73 +229,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
249 | 229 | ||
250 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 230 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
251 | 231 | ||
252 | /* Static radio parameters */ | 232 | memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params, |
253 | radio_parms->rx_trace_loss = r->rx_trace_loss; | 233 | WL1271_NVS_STAT_RADIO_PARAMS_SIZE); |
254 | radio_parms->tx_trace_loss = r->tx_trace_loss; | 234 | memcpy(radio_parms->dyn_radio_params, |
255 | memcpy(radio_parms->rx_rssi_and_proc_compens, | 235 | wl->nvs->dyn_radio_params[rparam->fem], |
256 | r->rx_rssi_and_proc_compens, | 236 | WL1271_NVS_DYN_RADIO_PARAMS_SIZE); |
257 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | 237 | |
258 | 238 | /* FIXME: current NVS is missing 5GHz parameters */ | |
259 | memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5, | ||
260 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
261 | memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5, | ||
262 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
263 | memcpy(radio_parms->rx_rssi_and_proc_compens_5, | ||
264 | r->rx_rssi_and_proc_compens_5, | ||
265 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | ||
266 | |||
267 | /* Dynamic radio parameters */ | ||
268 | radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage); | ||
269 | radio_parms->tx_ref_power = r->tx_ref_power; | ||
270 | radio_parms->tx_offset_db = r->tx_offset_db; | ||
271 | |||
272 | memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal, | ||
273 | CONF_NUMBER_OF_RATE_GROUPS); | ||
274 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, | ||
275 | CONF_NUMBER_OF_RATE_GROUPS); | ||
276 | memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, | ||
277 | CONF_NUMBER_OF_RATE_GROUPS); | ||
278 | |||
279 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, | ||
280 | CONF_NUMBER_OF_CHANNELS_2_4); | ||
281 | memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm, | ||
282 | CONF_NUMBER_OF_CHANNELS_2_4); | ||
283 | memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets, | ||
284 | CONF_NUMBER_OF_RATE_GROUPS); | ||
285 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); | ||
286 | |||
287 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | ||
288 | radio_parms->degraded_low_to_normal_threshold = | ||
289 | r->degraded_low_to_normal_threshold; | ||
290 | radio_parms->degraded_normal_to_high_threshold = | ||
291 | r->degraded_normal_to_high_threshold; | ||
292 | |||
293 | |||
294 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | ||
295 | radio_parms->tx_ref_pd_voltage_5[i] = | ||
296 | cpu_to_le16(r->tx_ref_pd_voltage_5[i]); | ||
297 | memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5, | ||
298 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
299 | memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5, | ||
300 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
301 | memcpy(radio_parms->tx_rate_limits_normal_5, | ||
302 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
303 | memcpy(radio_parms->tx_rate_limits_degraded_5, | ||
304 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
305 | memcpy(radio_parms->tx_rate_limits_extreme_5, | ||
306 | r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
307 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | ||
308 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | ||
309 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | ||
310 | CONF_NUMBER_OF_RATE_GROUPS); | ||
311 | memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5, | ||
312 | CONF_NUMBER_OF_RATE_GROUPS); | ||
313 | memcpy(radio_parms->rx_fem_insertion_loss_5, | ||
314 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | ||
315 | radio_parms->degraded_low_to_normal_threshold_5 = | ||
316 | r->degraded_low_to_normal_threshold_5; | ||
317 | radio_parms->degraded_normal_to_high_threshold_5 = | ||
318 | r->degraded_normal_to_high_threshold_5; | ||
319 | 239 | ||
320 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 240 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
321 | radio_parms, sizeof(*radio_parms)); | 241 | radio_parms, sizeof(*radio_parms)); |
@@ -555,7 +475,7 @@ out: | |||
555 | return ret; | 475 | return ret; |
556 | } | 476 | } |
557 | 477 | ||
558 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | 478 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send) |
559 | { | 479 | { |
560 | struct wl1271_cmd_ps_params *ps_params = NULL; | 480 | struct wl1271_cmd_ps_params *ps_params = NULL; |
561 | int ret = 0; | 481 | int ret = 0; |
@@ -576,7 +496,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | |||
576 | } | 496 | } |
577 | 497 | ||
578 | ps_params->ps_mode = ps_mode; | 498 | ps_params->ps_mode = ps_mode; |
579 | ps_params->send_null_data = 1; | 499 | ps_params->send_null_data = send; |
580 | ps_params->retries = 5; | 500 | ps_params->retries = 5; |
581 | ps_params->hang_over_period = 128; | 501 | ps_params->hang_over_period = 128; |
582 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ | 502 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ |
@@ -1022,7 +942,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
1022 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | 942 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); |
1023 | if (ret < 0) { | 943 | if (ret < 0) { |
1024 | wl1271_warning("could not set keys"); | 944 | wl1271_warning("could not set keys"); |
1025 | goto out; | 945 | goto out; |
1026 | } | 946 | } |
1027 | 947 | ||
1028 | out: | 948 | out: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 09fe91297acf..2dc06c73532b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -38,7 +38,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | |||
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); | 40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 44 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, |
@@ -428,90 +428,24 @@ struct wl1271_general_parms_cmd { | |||
428 | 428 | ||
429 | struct wl1271_cmd_test_header test; | 429 | struct wl1271_cmd_test_header test; |
430 | 430 | ||
431 | u8 ref_clk; | 431 | u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE]; |
432 | u8 settling_time; | 432 | s8 reserved[23]; |
433 | u8 clk_valid_on_wakeup; | ||
434 | u8 dc2dcmode; | ||
435 | u8 single_dual_band; | ||
436 | |||
437 | u8 tx_bip_fem_autodetect; | ||
438 | u8 tx_bip_fem_manufacturer; | ||
439 | u8 settings; | ||
440 | |||
441 | u8 sr_state; | ||
442 | |||
443 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
444 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
445 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
446 | |||
447 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
448 | |||
449 | u8 sr_sen_n_p; | ||
450 | u8 sr_sen_n_p_gain; | ||
451 | u8 sr_sen_nrn; | ||
452 | u8 sr_sen_prn; | ||
453 | |||
454 | u8 padding[3]; | ||
455 | } __attribute__ ((packed)); | 433 | } __attribute__ ((packed)); |
456 | 434 | ||
435 | #define WL1271_STAT_RADIO_PARAMS_5_SIZE 29 | ||
436 | #define WL1271_DYN_RADIO_PARAMS_5_SIZE 104 | ||
437 | |||
457 | struct wl1271_radio_parms_cmd { | 438 | struct wl1271_radio_parms_cmd { |
458 | struct wl1271_cmd_header header; | 439 | struct wl1271_cmd_header header; |
459 | 440 | ||
460 | struct wl1271_cmd_test_header test; | 441 | struct wl1271_cmd_test_header test; |
461 | 442 | ||
462 | /* Static radio parameters */ | 443 | u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE]; |
463 | /* 2.4GHz */ | 444 | u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE]; |
464 | u8 rx_trace_loss; | ||
465 | u8 tx_trace_loss; | ||
466 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
467 | |||
468 | /* 5GHz */ | ||
469 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
470 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
471 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
472 | |||
473 | /* Dynamic radio parameters */ | ||
474 | /* 2.4GHz */ | ||
475 | __le16 tx_ref_pd_voltage; | ||
476 | u8 tx_ref_power; | ||
477 | s8 tx_offset_db; | ||
478 | |||
479 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | ||
480 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | ||
481 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
482 | 445 | ||
483 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 446 | u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE]; |
484 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 447 | u8 reserved; |
485 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; | 448 | u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE]; |
486 | |||
487 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | ||
488 | u8 rx_fem_insertion_loss; | ||
489 | |||
490 | u8 degraded_low_to_normal_threshold; | ||
491 | u8 degraded_normal_to_high_threshold; | ||
492 | |||
493 | u8 padding1; /* our own padding, not in ref driver */ | ||
494 | |||
495 | /* 5GHz */ | ||
496 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
497 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
498 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
499 | |||
500 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
501 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
502 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
503 | |||
504 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | ||
505 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
506 | |||
507 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | ||
508 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
509 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
510 | |||
511 | u8 degraded_low_to_normal_threshold_5; | ||
512 | u8 degraded_normal_to_high_threshold_5; | ||
513 | |||
514 | u8 padding2[2]; | ||
515 | } __attribute__ ((packed)); | 449 | } __attribute__ ((packed)); |
516 | 450 | ||
517 | struct wl1271_cmd_cal_channel_tune { | 451 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 1993d63c214e..6f9e75cc5640 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -735,81 +735,6 @@ enum single_dual_band_enum { | |||
735 | CONF_DUAL_BAND | 735 | CONF_DUAL_BAND |
736 | }; | 736 | }; |
737 | 737 | ||
738 | |||
739 | #define CONF_MAX_SMART_REFLEX_PARAMS 16 | ||
740 | |||
741 | struct conf_general_parms { | ||
742 | /* | ||
743 | * RF Reference Clock type / speed | ||
744 | * | ||
745 | * Range: CONF_REF_CLK_* | ||
746 | */ | ||
747 | u8 ref_clk; | ||
748 | |||
749 | /* | ||
750 | * Settling time of the reference clock after boot. | ||
751 | * | ||
752 | * Range: u8 | ||
753 | */ | ||
754 | u8 settling_time; | ||
755 | |||
756 | /* | ||
757 | * Flag defining whether clock is valid on wakeup. | ||
758 | * | ||
759 | * Range: 0 - not valid on wakeup, 1 - valid on wakeup | ||
760 | */ | ||
761 | u8 clk_valid_on_wakeup; | ||
762 | |||
763 | /* | ||
764 | * DC-to-DC mode. | ||
765 | * | ||
766 | * Range: Unknown | ||
767 | */ | ||
768 | u8 dc2dcmode; | ||
769 | |||
770 | /* | ||
771 | * Flag defining whether used as single or dual-band. | ||
772 | * | ||
773 | * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND | ||
774 | */ | ||
775 | u8 single_dual_band; | ||
776 | |||
777 | /* | ||
778 | * TX bip fem autodetect flag. | ||
779 | * | ||
780 | * Range: Unknown | ||
781 | */ | ||
782 | u8 tx_bip_fem_autodetect; | ||
783 | |||
784 | /* | ||
785 | * TX bip gem manufacturer. | ||
786 | * | ||
787 | * Range: Unknown | ||
788 | */ | ||
789 | u8 tx_bip_fem_manufacturer; | ||
790 | |||
791 | /* | ||
792 | * Settings flags. | ||
793 | * | ||
794 | * Range: Unknown | ||
795 | */ | ||
796 | u8 settings; | ||
797 | |||
798 | /* Smart reflex settings */ | ||
799 | u8 sr_state; | ||
800 | |||
801 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
802 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
803 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
804 | |||
805 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
806 | |||
807 | u8 sr_sen_n_p; | ||
808 | u8 sr_sen_n_p_gain; | ||
809 | u8 sr_sen_nrn; | ||
810 | u8 sr_sen_prn; | ||
811 | }; | ||
812 | |||
813 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | 738 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 |
814 | #define CONF_NUMBER_OF_SUB_BANDS_5 7 | 739 | #define CONF_NUMBER_OF_SUB_BANDS_5 7 |
815 | #define CONF_NUMBER_OF_RATE_GROUPS 6 | 740 | #define CONF_NUMBER_OF_RATE_GROUPS 6 |
@@ -818,78 +743,15 @@ struct conf_general_parms { | |||
818 | 743 | ||
819 | struct conf_radio_parms { | 744 | struct conf_radio_parms { |
820 | /* | 745 | /* |
821 | * Static radio parameters for 2.4GHz | 746 | * FEM parameter set to use |
822 | * | ||
823 | * Range: unknown | ||
824 | */ | ||
825 | u8 rx_trace_loss; | ||
826 | u8 tx_trace_loss; | ||
827 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
828 | |||
829 | /* | ||
830 | * Static radio parameters for 5GHz | ||
831 | * | ||
832 | * Range: unknown | ||
833 | */ | ||
834 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
835 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
836 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
837 | |||
838 | /* | ||
839 | * Dynamic radio parameters for 2.4GHz | ||
840 | * | 747 | * |
841 | * Range: unknown | 748 | * Range: 0 or 1 |
842 | */ | 749 | */ |
843 | u16 tx_ref_pd_voltage; | 750 | u8 fem; |
844 | u8 tx_ref_power; | ||
845 | s8 tx_offset_db; | ||
846 | |||
847 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | ||
848 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | ||
849 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
850 | |||
851 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
852 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
853 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; | ||
854 | |||
855 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | ||
856 | u8 rx_fem_insertion_loss; | ||
857 | |||
858 | u8 degraded_low_to_normal_threshold; | ||
859 | u8 degraded_normal_to_high_threshold; | ||
860 | |||
861 | |||
862 | /* | ||
863 | * Dynamic radio parameters for 5GHz | ||
864 | * | ||
865 | * Range: unknown | ||
866 | */ | ||
867 | u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
868 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
869 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
870 | |||
871 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
872 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
873 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
874 | |||
875 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | ||
876 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
877 | |||
878 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | ||
879 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
880 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
881 | |||
882 | u8 degraded_low_to_normal_threshold_5; | ||
883 | u8 degraded_normal_to_high_threshold_5; | ||
884 | }; | 751 | }; |
885 | 752 | ||
886 | struct conf_init_settings { | 753 | struct conf_init_settings { |
887 | /* | 754 | /* |
888 | * Configure general parameters. | ||
889 | */ | ||
890 | struct conf_general_parms genparam; | ||
891 | |||
892 | /* | ||
893 | * Configure radio parameters. | 755 | * Configure radio parameters. |
894 | */ | 756 | */ |
895 | struct conf_radio_parms radioparam; | 757 | struct conf_radio_parms radioparam; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 0a145afc9905..7468ef10194b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "wl1271.h" | 24 | #include "wl1271.h" |
25 | #include "wl1271_reg.h" | 25 | #include "wl1271_reg.h" |
26 | #include "wl1271_spi.h" | 26 | #include "wl1271_spi.h" |
27 | #include "wl1271_io.h" | ||
27 | #include "wl1271_event.h" | 28 | #include "wl1271_event.h" |
28 | #include "wl1271_ps.h" | 29 | #include "wl1271_ps.h" |
29 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
@@ -78,24 +79,61 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
78 | 79 | ||
79 | switch (mbox->ps_status) { | 80 | switch (mbox->ps_status) { |
80 | case EVENT_ENTER_POWER_SAVE_FAIL: | 81 | case EVENT_ENTER_POWER_SAVE_FAIL: |
82 | wl1271_debug(DEBUG_PSM, "PSM entry failed"); | ||
83 | |||
81 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 84 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
85 | /* remain in active mode */ | ||
82 | wl->psm_entry_retry = 0; | 86 | wl->psm_entry_retry = 0; |
83 | break; | 87 | break; |
84 | } | 88 | } |
85 | 89 | ||
86 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { | 90 | if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { |
87 | wl->psm_entry_retry++; | 91 | wl->psm_entry_retry++; |
88 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 92 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
93 | true); | ||
89 | } else { | 94 | } else { |
90 | wl1271_error("PSM entry failed, giving up.\n"); | 95 | wl1271_error("PSM entry failed, giving up.\n"); |
96 | /* FIXME: this may need to be reconsidered. for now it | ||
97 | is not possible to indicate to the mac80211 | ||
98 | afterwards that PSM entry failed. To maximize | ||
99 | functionality (receiving data and remaining | ||
100 | associated) make sure that we are in sync with the | ||
101 | AP in regard of PSM mode. */ | ||
102 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
103 | false); | ||
91 | wl->psm_entry_retry = 0; | 104 | wl->psm_entry_retry = 0; |
92 | } | 105 | } |
93 | break; | 106 | break; |
94 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 107 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
95 | wl->psm_entry_retry = 0; | 108 | wl->psm_entry_retry = 0; |
109 | |||
110 | /* enable beacon filtering */ | ||
111 | ret = wl1271_acx_beacon_filter_opt(wl, true); | ||
112 | if (ret < 0) | ||
113 | break; | ||
114 | |||
115 | /* enable beacon early termination */ | ||
116 | ret = wl1271_acx_bet_enable(wl, true); | ||
117 | if (ret < 0) | ||
118 | break; | ||
119 | |||
120 | /* go to extremely low power mode */ | ||
121 | wl1271_ps_elp_sleep(wl); | ||
122 | if (ret < 0) | ||
123 | break; | ||
96 | break; | 124 | break; |
97 | case EVENT_EXIT_POWER_SAVE_FAIL: | 125 | case EVENT_EXIT_POWER_SAVE_FAIL: |
98 | wl1271_info("PSM exit failed"); | 126 | wl1271_debug(DEBUG_PSM, "PSM exit failed"); |
127 | |||
128 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
129 | wl->psm_entry_retry = 0; | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | /* make sure the firmware goes to active mode - the frame to | ||
134 | be sent next will indicate to the AP, that we are active. */ | ||
135 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
136 | false); | ||
99 | break; | 137 | break; |
100 | case EVENT_EXIT_POWER_SAVE_SUCCESS: | 138 | case EVENT_EXIT_POWER_SAVE_SUCCESS: |
101 | default: | 139 | default: |
@@ -177,7 +215,7 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
177 | 215 | ||
178 | void wl1271_event_mbox_config(struct wl1271 *wl) | 216 | void wl1271_event_mbox_config(struct wl1271 *wl) |
179 | { | 217 | { |
180 | wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); | 218 | wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); |
181 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 219 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
182 | 220 | ||
183 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", | 221 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", |
@@ -195,8 +233,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
195 | return -EINVAL; | 233 | return -EINVAL; |
196 | 234 | ||
197 | /* first we read the mbox descriptor */ | 235 | /* first we read the mbox descriptor */ |
198 | wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox, | 236 | wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox, |
199 | sizeof(struct event_mailbox), false); | 237 | sizeof(struct event_mailbox), false); |
200 | 238 | ||
201 | /* process the descriptor */ | 239 | /* process the descriptor */ |
202 | ret = wl1271_event_process(wl, &mbox); | 240 | ret = wl1271_event_process(wl, &mbox); |
@@ -204,7 +242,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
204 | return ret; | 242 | return ret; |
205 | 243 | ||
206 | /* then we let the firmware know it can go on...*/ | 244 | /* then we let the firmware know it can go on...*/ |
207 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); | 245 | wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
208 | 246 | ||
209 | return 0; | 247 | return 0; |
210 | } | 248 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index c9848eecb767..86c30a86a456 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
52 | static int wl1271_init_templates_config(struct wl1271 *wl) | 52 | int wl1271_init_templates_config(struct wl1271 *wl) |
53 | { | 53 | { |
54 | int ret; | 54 | int ret; |
55 | 55 | ||
@@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) | |||
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | 115 | ||
116 | static int wl1271_init_phy_config(struct wl1271 *wl) | 116 | int wl1271_init_phy_config(struct wl1271 *wl) |
117 | { | 117 | { |
118 | int ret; | 118 | int ret; |
119 | 119 | ||
@@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl) | |||
156 | return 0; | 156 | return 0; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int wl1271_init_pta(struct wl1271 *wl) | 159 | int wl1271_init_pta(struct wl1271 *wl) |
160 | { | 160 | { |
161 | int ret; | 161 | int ret; |
162 | 162 | ||
@@ -171,7 +171,7 @@ static int wl1271_init_pta(struct wl1271 *wl) | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | static int wl1271_init_energy_detection(struct wl1271 *wl) | 174 | int wl1271_init_energy_detection(struct wl1271 *wl) |
175 | { | 175 | { |
176 | int ret; | 176 | int ret; |
177 | 177 | ||
@@ -195,7 +195,9 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) | |||
195 | 195 | ||
196 | int wl1271_hw_init(struct wl1271 *wl) | 196 | int wl1271_hw_init(struct wl1271 *wl) |
197 | { | 197 | { |
198 | int ret; | 198 | struct conf_tx_ac_category *conf_ac; |
199 | struct conf_tx_tid *conf_tid; | ||
200 | int ret, i; | ||
199 | 201 | ||
200 | ret = wl1271_cmd_general_parms(wl); | 202 | ret = wl1271_cmd_general_parms(wl); |
201 | if (ret < 0) | 203 | if (ret < 0) |
@@ -274,14 +276,28 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
274 | goto out_free_memmap; | 276 | goto out_free_memmap; |
275 | 277 | ||
276 | /* Default TID configuration */ | 278 | /* Default TID configuration */ |
277 | ret = wl1271_acx_tid_cfg(wl); | 279 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
278 | if (ret < 0) | 280 | conf_tid = &wl->conf.tx.tid_conf[i]; |
279 | goto out_free_memmap; | 281 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, |
282 | conf_tid->channel_type, | ||
283 | conf_tid->tsid, | ||
284 | conf_tid->ps_scheme, | ||
285 | conf_tid->ack_policy, | ||
286 | conf_tid->apsd_conf[0], | ||
287 | conf_tid->apsd_conf[1]); | ||
288 | if (ret < 0) | ||
289 | goto out_free_memmap; | ||
290 | } | ||
280 | 291 | ||
281 | /* Default AC configuration */ | 292 | /* Default AC configuration */ |
282 | ret = wl1271_acx_ac_cfg(wl); | 293 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { |
283 | if (ret < 0) | 294 | conf_ac = &wl->conf.tx.ac_conf[i]; |
284 | goto out_free_memmap; | 295 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, |
296 | conf_ac->cw_max, conf_ac->aifsn, | ||
297 | conf_ac->tx_op_limit); | ||
298 | if (ret < 0) | ||
299 | goto out_free_memmap; | ||
300 | } | ||
285 | 301 | ||
286 | /* Configure TX rate classes */ | 302 | /* Configure TX rate classes */ |
287 | ret = wl1271_acx_rate_policies(wl); | 303 | ret = wl1271_acx_rate_policies(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h index 930677fbe852..bc26f8c53b91 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/wl1271_init.h | |||
@@ -27,6 +27,10 @@ | |||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | 28 | ||
29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); | 29 | int wl1271_hw_init_power_auth(struct wl1271 *wl); |
30 | int wl1271_init_templates_config(struct wl1271 *wl); | ||
31 | int wl1271_init_phy_config(struct wl1271 *wl); | ||
32 | int wl1271_init_pta(struct wl1271 *wl); | ||
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | ||
30 | int wl1271_hw_init(struct wl1271 *wl); | 34 | int wl1271_hw_init(struct wl1271 *wl); |
31 | 35 | ||
32 | #endif | 36 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.c b/drivers/net/wireless/wl12xx/wl1271_io.c new file mode 100644 index 000000000000..5cd94d5666c2 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/crc7.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | |||
29 | #include "wl1271.h" | ||
30 | #include "wl12xx_80211.h" | ||
31 | #include "wl1271_spi.h" | ||
32 | #include "wl1271_io.h" | ||
33 | |||
34 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
35 | { | ||
36 | /* | ||
37 | * To translate, first check to which window of addresses the | ||
38 | * particular address belongs. Then subtract the starting address | ||
39 | * of that window from the address. Then, add offset of the | ||
40 | * translated region. | ||
41 | * | ||
42 | * The translated regions occur next to each other in physical device | ||
43 | * memory, so just add the sizes of the preceeding address regions to | ||
44 | * get the offset to the new region. | ||
45 | * | ||
46 | * Currently, only the two first regions are addressed, and the | ||
47 | * assumption is that all addresses will fall into either of those | ||
48 | * two. | ||
49 | */ | ||
50 | if ((addr >= wl->part.reg.start) && | ||
51 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
52 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
53 | else | ||
54 | return addr - wl->part.mem.start; | ||
55 | } | ||
56 | |||
57 | /* Set the SPI partitions to access the chip addresses | ||
58 | * | ||
59 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
60 | * register and memory addresses. Because in the chipset, in different stages | ||
61 | * of operation, those addresses will move around, an address translation | ||
62 | * mechanism is required. | ||
63 | * | ||
64 | * There are four partitions (three memory and one register partition), | ||
65 | * which are mapped to two different areas of the hardware memory. | ||
66 | * | ||
67 | * Virtual address | ||
68 | * space | ||
69 | * | ||
70 | * | | | ||
71 | * ...+----+--> mem.start | ||
72 | * Physical address ... | | | ||
73 | * space ... | | [PART_0] | ||
74 | * ... | | | ||
75 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
76 | * | | ... | | | ||
77 | * |MEM | ... | | | ||
78 | * | | ... | | | ||
79 | * mem.size <--+----+... | | {unused area) | ||
80 | * | | ... | | | ||
81 | * |REG | ... | | | ||
82 | * mem.size | | ... | | | ||
83 | * + <--+----+... ...+----+--> reg.start | ||
84 | * reg.size | | ... | | | ||
85 | * |MEM2| ... | | [PART_1] | ||
86 | * | | ... | | | ||
87 | * ...+----+--> reg.start + reg.size | ||
88 | * | | | ||
89 | * | ||
90 | */ | ||
91 | int wl1271_set_partition(struct wl1271 *wl, | ||
92 | struct wl1271_partition_set *p) | ||
93 | { | ||
94 | /* copy partition info */ | ||
95 | memcpy(&wl->part, p, sizeof(*p)); | ||
96 | |||
97 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
98 | p->mem.start, p->mem.size); | ||
99 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
100 | p->reg.start, p->reg.size); | ||
101 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
102 | p->mem2.start, p->mem2.size); | ||
103 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
104 | p->mem3.start, p->mem3.size); | ||
105 | |||
106 | /* write partition info to the chipset */ | ||
107 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
108 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
109 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
110 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
111 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
112 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
113 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | void wl1271_io_reset(struct wl1271 *wl) | ||
119 | { | ||
120 | wl1271_spi_reset(wl); | ||
121 | } | ||
122 | |||
123 | void wl1271_io_init(struct wl1271 *wl) | ||
124 | { | ||
125 | wl1271_spi_init(wl); | ||
126 | } | ||
127 | |||
128 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
129 | size_t len, bool fixed) | ||
130 | { | ||
131 | wl1271_spi_raw_write(wl, addr, buf, len, fixed); | ||
132 | } | ||
133 | |||
134 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
135 | size_t len, bool fixed) | ||
136 | { | ||
137 | wl1271_spi_raw_read(wl, addr, buf, len, fixed); | ||
138 | } | ||
139 | |||
140 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
141 | bool fixed) | ||
142 | { | ||
143 | int physical; | ||
144 | |||
145 | physical = wl1271_translate_addr(wl, addr); | ||
146 | |||
147 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
148 | } | ||
149 | |||
150 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
151 | bool fixed) | ||
152 | { | ||
153 | int physical; | ||
154 | |||
155 | physical = wl1271_translate_addr(wl, addr); | ||
156 | |||
157 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
158 | } | ||
159 | |||
160 | u32 wl1271_read32(struct wl1271 *wl, int addr) | ||
161 | { | ||
162 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
163 | } | ||
164 | |||
165 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | ||
166 | { | ||
167 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
168 | } | ||
169 | |||
170 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
171 | { | ||
172 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
173 | addr = (addr >> 1) + 0x30000; | ||
174 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
175 | |||
176 | /* write value to OCP_POR_WDATA */ | ||
177 | wl1271_write32(wl, OCP_DATA_WRITE, val); | ||
178 | |||
179 | /* write 1 to OCP_CMD */ | ||
180 | wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
181 | } | ||
182 | |||
183 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
184 | { | ||
185 | u32 val; | ||
186 | int timeout = OCP_CMD_LOOP; | ||
187 | |||
188 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
189 | addr = (addr >> 1) + 0x30000; | ||
190 | wl1271_write32(wl, OCP_POR_CTR, addr); | ||
191 | |||
192 | /* write 2 to OCP_CMD */ | ||
193 | wl1271_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
194 | |||
195 | /* poll for data ready */ | ||
196 | do { | ||
197 | val = wl1271_read32(wl, OCP_DATA_READ); | ||
198 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
199 | |||
200 | if (!timeout) { | ||
201 | wl1271_warning("Top register access timed out."); | ||
202 | return 0xffff; | ||
203 | } | ||
204 | |||
205 | /* check data status and return if OK */ | ||
206 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
207 | return val & 0xffff; | ||
208 | else { | ||
209 | wl1271_warning("Top register access returned error."); | ||
210 | return 0xffff; | ||
211 | } | ||
212 | } | ||
213 | |||
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h new file mode 100644 index 000000000000..fa9a0b35788f --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_io.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. | ||
5 | * Copyright (C) 2008-2010 Nokia Corporation | ||
6 | * | ||
7 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #ifndef __WL1271_IO_H__ | ||
26 | #define __WL1271_IO_H__ | ||
27 | |||
28 | struct wl1271; | ||
29 | |||
30 | void wl1271_io_reset(struct wl1271 *wl); | ||
31 | void wl1271_io_init(struct wl1271 *wl); | ||
32 | |||
33 | /* Raw target IO, address is not translated */ | ||
34 | void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | ||
35 | size_t len, bool fixed); | ||
36 | void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | ||
37 | size_t len, bool fixed); | ||
38 | |||
39 | /* Translated target IO */ | ||
40 | void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
41 | bool fixed); | ||
42 | void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
43 | bool fixed); | ||
44 | u32 wl1271_read32(struct wl1271 *wl, int addr); | ||
45 | void wl1271_write32(struct wl1271 *wl, int addr, u32 val); | ||
46 | |||
47 | /* Top Register IO */ | ||
48 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
49 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
50 | |||
51 | int wl1271_set_partition(struct wl1271 *wl, | ||
52 | struct wl1271_partition_set *p); | ||
53 | |||
54 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | ||
55 | { | ||
56 | wl1271_raw_read(wl, addr, &wl->buffer_32, | ||
57 | sizeof(wl->buffer_32), false); | ||
58 | |||
59 | return wl->buffer_32; | ||
60 | } | ||
61 | |||
62 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | ||
63 | { | ||
64 | wl->buffer_32 = val; | ||
65 | wl1271_raw_write(wl, addr, &wl->buffer_32, | ||
66 | sizeof(wl->buffer_32), false); | ||
67 | } | ||
68 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index e4867b895c43..2a864b24291d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -38,6 +38,7 @@ | |||
38 | #include "wl12xx_80211.h" | 38 | #include "wl12xx_80211.h" |
39 | #include "wl1271_reg.h" | 39 | #include "wl1271_reg.h" |
40 | #include "wl1271_spi.h" | 40 | #include "wl1271_spi.h" |
41 | #include "wl1271_io.h" | ||
41 | #include "wl1271_event.h" | 42 | #include "wl1271_event.h" |
42 | #include "wl1271_tx.h" | 43 | #include "wl1271_tx.h" |
43 | #include "wl1271_rx.h" | 44 | #include "wl1271_rx.h" |
@@ -46,6 +47,7 @@ | |||
46 | #include "wl1271_debugfs.h" | 47 | #include "wl1271_debugfs.h" |
47 | #include "wl1271_cmd.h" | 48 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 49 | #include "wl1271_boot.h" |
50 | #include "wl1271_testmode.h" | ||
49 | 51 | ||
50 | #define WL1271_BOOT_RETRIES 3 | 52 | #define WL1271_BOOT_RETRIES 3 |
51 | 53 | ||
@@ -229,93 +231,8 @@ static struct conf_drv_settings default_conf = { | |||
229 | .psm_entry_retries = 3 | 231 | .psm_entry_retries = 3 |
230 | }, | 232 | }, |
231 | .init = { | 233 | .init = { |
232 | .genparam = { | ||
233 | .ref_clk = CONF_REF_CLK_38_4_E, | ||
234 | .settling_time = 5, | ||
235 | .clk_valid_on_wakeup = 0, | ||
236 | .dc2dcmode = 0, | ||
237 | .single_dual_band = CONF_SINGLE_BAND, | ||
238 | .tx_bip_fem_autodetect = 1, | ||
239 | .tx_bip_fem_manufacturer = 1, | ||
240 | .settings = 1, | ||
241 | .sr_state = 1, | ||
242 | .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
243 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
244 | .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
245 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
246 | .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
247 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
248 | .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, | ||
249 | 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
250 | .sr_sen_n_p = 0, | ||
251 | .sr_sen_n_p_gain = 0, | ||
252 | .sr_sen_nrn = 0, | ||
253 | .sr_sen_prn = 0, | ||
254 | }, | ||
255 | .radioparam = { | 234 | .radioparam = { |
256 | .rx_trace_loss = 0x24, | 235 | .fem = 1, |
257 | .tx_trace_loss = 0x0, | ||
258 | .rx_rssi_and_proc_compens = { | ||
259 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | ||
260 | 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, | ||
261 | 0x00, 0x0a, 0x14 }, | ||
262 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
263 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
264 | .rx_rssi_and_proc_compens_5 = { | ||
265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
267 | 0x00, 0x00, 0x00 }, | ||
268 | .tx_ref_pd_voltage = 0x1a9, | ||
269 | .tx_ref_power = 0x80, | ||
270 | .tx_offset_db = 0x0, | ||
271 | .tx_rate_limits_normal = { | ||
272 | 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, | ||
273 | .tx_rate_limits_degraded = { | ||
274 | 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, | ||
275 | .tx_rate_limits_extreme = { | ||
276 | 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
277 | .tx_channel_limits_11b = { | ||
278 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
279 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | ||
280 | 0x22, 0x50 }, | ||
281 | .tx_channel_limits_ofdm = { | ||
282 | 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
283 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | ||
284 | 0x20, 0x50 }, | ||
285 | .tx_pdv_rate_offsets = { | ||
286 | 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, | ||
287 | .tx_ibias = { | ||
288 | 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, | ||
289 | .rx_fem_insertion_loss = 0x0e, | ||
290 | .degraded_low_to_normal_threshold = 0x1e, | ||
291 | .degraded_normal_to_high_threshold = 0x2d, | ||
292 | .tx_ref_pd_voltage_5 = { | ||
293 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | ||
294 | 0x020a, 0x021c }, | ||
295 | .tx_ref_power_5 = { | ||
296 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, | ||
297 | .tx_offset_db_5 = { | ||
298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
299 | .tx_rate_limits_normal_5 = { | ||
300 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
301 | .tx_rate_limits_degraded_5 = { | ||
302 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
303 | .tx_rate_limits_extreme_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
305 | .tx_channel_limits_ofdm_5 = { | ||
306 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
307 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
310 | 0x50, 0x50, 0x50 }, | ||
311 | .tx_pdv_rate_offsets_5 = { | ||
312 | 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, | ||
313 | .tx_ibias_5 = { | ||
314 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | ||
315 | .rx_fem_insertion_loss_5 = { | ||
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | ||
317 | .degraded_low_to_normal_threshold_5 = 0x00, | ||
318 | .degraded_normal_to_high_threshold_5 = 0x00 | ||
319 | } | 236 | } |
320 | }, | 237 | }, |
321 | .itrim = { | 238 | .itrim = { |
@@ -345,15 +262,14 @@ static void wl1271_conf_init(struct wl1271 *wl) | |||
345 | 262 | ||
346 | /* apply driver default configuration */ | 263 | /* apply driver default configuration */ |
347 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); | 264 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); |
348 | |||
349 | if (wl1271_11a_enabled()) | ||
350 | wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND; | ||
351 | } | 265 | } |
352 | 266 | ||
353 | 267 | ||
354 | static int wl1271_plt_init(struct wl1271 *wl) | 268 | static int wl1271_plt_init(struct wl1271 *wl) |
355 | { | 269 | { |
356 | int ret; | 270 | struct conf_tx_ac_category *conf_ac; |
271 | struct conf_tx_tid *conf_tid; | ||
272 | int ret, i; | ||
357 | 273 | ||
358 | ret = wl1271_cmd_general_parms(wl); | 274 | ret = wl1271_cmd_general_parms(wl); |
359 | if (ret < 0) | 275 | if (ret < 0) |
@@ -363,15 +279,89 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
363 | if (ret < 0) | 279 | if (ret < 0) |
364 | return ret; | 280 | return ret; |
365 | 281 | ||
282 | ret = wl1271_init_templates_config(wl); | ||
283 | if (ret < 0) | ||
284 | return ret; | ||
285 | |||
366 | ret = wl1271_acx_init_mem_config(wl); | 286 | ret = wl1271_acx_init_mem_config(wl); |
367 | if (ret < 0) | 287 | if (ret < 0) |
368 | return ret; | 288 | return ret; |
369 | 289 | ||
290 | /* PHY layer config */ | ||
291 | ret = wl1271_init_phy_config(wl); | ||
292 | if (ret < 0) | ||
293 | goto out_free_memmap; | ||
294 | |||
295 | ret = wl1271_acx_dco_itrim_params(wl); | ||
296 | if (ret < 0) | ||
297 | goto out_free_memmap; | ||
298 | |||
299 | /* Initialize connection monitoring thresholds */ | ||
300 | ret = wl1271_acx_conn_monit_params(wl); | ||
301 | if (ret < 0) | ||
302 | goto out_free_memmap; | ||
303 | |||
304 | /* Bluetooth WLAN coexistence */ | ||
305 | ret = wl1271_init_pta(wl); | ||
306 | if (ret < 0) | ||
307 | goto out_free_memmap; | ||
308 | |||
309 | /* Energy detection */ | ||
310 | ret = wl1271_init_energy_detection(wl); | ||
311 | if (ret < 0) | ||
312 | goto out_free_memmap; | ||
313 | |||
314 | /* Default fragmentation threshold */ | ||
315 | ret = wl1271_acx_frag_threshold(wl); | ||
316 | if (ret < 0) | ||
317 | goto out_free_memmap; | ||
318 | |||
319 | /* Default TID configuration */ | ||
320 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | ||
321 | conf_tid = &wl->conf.tx.tid_conf[i]; | ||
322 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | ||
323 | conf_tid->channel_type, | ||
324 | conf_tid->tsid, | ||
325 | conf_tid->ps_scheme, | ||
326 | conf_tid->ack_policy, | ||
327 | conf_tid->apsd_conf[0], | ||
328 | conf_tid->apsd_conf[1]); | ||
329 | if (ret < 0) | ||
330 | goto out_free_memmap; | ||
331 | } | ||
332 | |||
333 | /* Default AC configuration */ | ||
334 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
335 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
336 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
337 | conf_ac->cw_max, conf_ac->aifsn, | ||
338 | conf_ac->tx_op_limit); | ||
339 | if (ret < 0) | ||
340 | goto out_free_memmap; | ||
341 | } | ||
342 | |||
343 | /* Enable data path */ | ||
370 | ret = wl1271_cmd_data_path(wl, 1); | 344 | ret = wl1271_cmd_data_path(wl, 1); |
371 | if (ret < 0) | 345 | if (ret < 0) |
372 | return ret; | 346 | goto out_free_memmap; |
347 | |||
348 | /* Configure for CAM power saving (ie. always active) */ | ||
349 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
350 | if (ret < 0) | ||
351 | goto out_free_memmap; | ||
352 | |||
353 | /* configure PM */ | ||
354 | ret = wl1271_acx_pm_config(wl); | ||
355 | if (ret < 0) | ||
356 | goto out_free_memmap; | ||
373 | 357 | ||
374 | return 0; | 358 | return 0; |
359 | |||
360 | out_free_memmap: | ||
361 | kfree(wl->target_mem_map); | ||
362 | wl->target_mem_map = NULL; | ||
363 | |||
364 | return ret; | ||
375 | } | 365 | } |
376 | 366 | ||
377 | static void wl1271_disable_interrupts(struct wl1271 *wl) | 367 | static void wl1271_disable_interrupts(struct wl1271 *wl) |
@@ -397,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
397 | u32 total = 0; | 387 | u32 total = 0; |
398 | int i; | 388 | int i; |
399 | 389 | ||
400 | wl1271_spi_read(wl, FW_STATUS_ADDR, status, | 390 | wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false); |
401 | sizeof(*status), false); | ||
402 | 391 | ||
403 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 392 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
404 | "drv_rx_counter = %d, tx_results_counter = %d)", | 393 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -445,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work) | |||
445 | if (ret < 0) | 434 | if (ret < 0) |
446 | goto out; | 435 | goto out; |
447 | 436 | ||
448 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 437 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
449 | 438 | ||
450 | wl1271_fw_status(wl, wl->fw_status); | 439 | wl1271_fw_status(wl, wl->fw_status); |
451 | intr = le32_to_cpu(wl->fw_status->intr); | 440 | intr = le32_to_cpu(wl->fw_status->intr); |
@@ -487,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work) | |||
487 | } | 476 | } |
488 | 477 | ||
489 | out_sleep: | 478 | out_sleep: |
490 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, | 479 | wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, |
491 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
492 | wl1271_ps_elp_sleep(wl); | 481 | wl1271_ps_elp_sleep(wl); |
493 | 482 | ||
494 | out: | 483 | out: |
@@ -555,6 +544,40 @@ out: | |||
555 | return ret; | 544 | return ret; |
556 | } | 545 | } |
557 | 546 | ||
547 | static int wl1271_update_mac_addr(struct wl1271 *wl) | ||
548 | { | ||
549 | int ret = 0; | ||
550 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
551 | |||
552 | /* get mac address from the NVS */ | ||
553 | wl->mac_addr[0] = nvs_ptr[11]; | ||
554 | wl->mac_addr[1] = nvs_ptr[10]; | ||
555 | wl->mac_addr[2] = nvs_ptr[6]; | ||
556 | wl->mac_addr[3] = nvs_ptr[5]; | ||
557 | wl->mac_addr[4] = nvs_ptr[4]; | ||
558 | wl->mac_addr[5] = nvs_ptr[3]; | ||
559 | |||
560 | /* FIXME: if it is a zero-address, we should bail out. Now, instead, | ||
561 | we randomize an address */ | ||
562 | if (is_zero_ether_addr(wl->mac_addr)) { | ||
563 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
564 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
565 | get_random_bytes(wl->mac_addr + 3, 3); | ||
566 | |||
567 | /* update this address to the NVS */ | ||
568 | nvs_ptr[11] = wl->mac_addr[0]; | ||
569 | nvs_ptr[10] = wl->mac_addr[1]; | ||
570 | nvs_ptr[6] = wl->mac_addr[2]; | ||
571 | nvs_ptr[5] = wl->mac_addr[3]; | ||
572 | nvs_ptr[4] = wl->mac_addr[4]; | ||
573 | nvs_ptr[3] = wl->mac_addr[5]; | ||
574 | } | ||
575 | |||
576 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | ||
577 | |||
578 | return ret; | ||
579 | } | ||
580 | |||
558 | static int wl1271_fetch_nvs(struct wl1271 *wl) | 581 | static int wl1271_fetch_nvs(struct wl1271 *wl) |
559 | { | 582 | { |
560 | const struct firmware *fw; | 583 | const struct firmware *fw; |
@@ -567,15 +590,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
567 | return ret; | 590 | return ret; |
568 | } | 591 | } |
569 | 592 | ||
570 | if (fw->size % 4) { | 593 | if (fw->size != sizeof(struct wl1271_nvs_file)) { |
571 | wl1271_error("nvs size is not multiple of 32 bits: %zu", | 594 | wl1271_error("nvs size is not as expected: %zu != %zu", |
572 | fw->size); | 595 | fw->size, sizeof(struct wl1271_nvs_file)); |
573 | ret = -EILSEQ; | 596 | ret = -EILSEQ; |
574 | goto out; | 597 | goto out; |
575 | } | 598 | } |
576 | 599 | ||
577 | wl->nvs_len = fw->size; | 600 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); |
578 | wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); | ||
579 | 601 | ||
580 | if (!wl->nvs) { | 602 | if (!wl->nvs) { |
581 | wl1271_error("could not allocate memory for the nvs file"); | 603 | wl1271_error("could not allocate memory for the nvs file"); |
@@ -583,9 +605,9 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
583 | goto out; | 605 | goto out; |
584 | } | 606 | } |
585 | 607 | ||
586 | memcpy(wl->nvs, fw->data, wl->nvs_len); | 608 | memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file)); |
587 | 609 | ||
588 | ret = 0; | 610 | ret = wl1271_update_mac_addr(wl); |
589 | 611 | ||
590 | out: | 612 | out: |
591 | release_firmware(fw); | 613 | release_firmware(fw); |
@@ -626,8 +648,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
626 | msleep(WL1271_PRE_POWER_ON_SLEEP); | 648 | msleep(WL1271_PRE_POWER_ON_SLEEP); |
627 | wl1271_power_on(wl); | 649 | wl1271_power_on(wl); |
628 | msleep(WL1271_POWER_ON_SLEEP); | 650 | msleep(WL1271_POWER_ON_SLEEP); |
629 | wl1271_spi_reset(wl); | 651 | wl1271_io_reset(wl); |
630 | wl1271_spi_init(wl); | 652 | wl1271_io_init(wl); |
631 | 653 | ||
632 | /* We don't need a real memory partition here, because we only want | 654 | /* We don't need a real memory partition here, because we only want |
633 | * to use the registers at this point. */ | 655 | * to use the registers at this point. */ |
@@ -642,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
642 | /* whal_FwCtrl_BootSm() */ | 664 | /* whal_FwCtrl_BootSm() */ |
643 | 665 | ||
644 | /* 0. read chip id from CHIP_ID */ | 666 | /* 0. read chip id from CHIP_ID */ |
645 | wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B); | 667 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); |
646 | 668 | ||
647 | /* 1. check if chip id is valid */ | 669 | /* 1. check if chip id is valid */ |
648 | 670 | ||
@@ -716,11 +738,6 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
716 | if (ret < 0) | 738 | if (ret < 0) |
717 | goto irq_disable; | 739 | goto irq_disable; |
718 | 740 | ||
719 | /* Make sure power saving is disabled */ | ||
720 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
721 | if (ret < 0) | ||
722 | goto irq_disable; | ||
723 | |||
724 | wl->state = WL1271_STATE_PLT; | 741 | wl->state = WL1271_STATE_PLT; |
725 | wl1271_notice("firmware booted in PLT mode (%s)", | 742 | wl1271_notice("firmware booted in PLT mode (%s)", |
726 | wl->chip.fw_ver); | 743 | wl->chip.fw_ver); |
@@ -1234,8 +1251,16 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1234 | } | 1251 | } |
1235 | 1252 | ||
1236 | /* if the channel changes while joined, join again */ | 1253 | /* if the channel changes while joined, join again */ |
1237 | if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1254 | if (channel != wl->channel && |
1238 | wl1271_join_channel(wl, channel); | 1255 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { |
1256 | wl->channel = channel; | ||
1257 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1258 | ret = wl1271_cmd_join(wl); | ||
1259 | if (ret < 0) | ||
1260 | wl1271_warning("cmd join to update channel failed %d", | ||
1261 | ret); | ||
1262 | } else | ||
1263 | wl->channel = channel; | ||
1239 | 1264 | ||
1240 | if (conf->flags & IEEE80211_CONF_PS && | 1265 | if (conf->flags & IEEE80211_CONF_PS && |
1241 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1266 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
@@ -1248,7 +1273,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1248 | */ | 1273 | */ |
1249 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 1274 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1250 | wl1271_info("psm enabled"); | 1275 | wl1271_info("psm enabled"); |
1251 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1276 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
1277 | true); | ||
1252 | } | 1278 | } |
1253 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1279 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1254 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1280 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
@@ -1257,7 +1283,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1257 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1283 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1258 | 1284 | ||
1259 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) | 1285 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1260 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1286 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, |
1287 | true); | ||
1261 | } | 1288 | } |
1262 | 1289 | ||
1263 | if (conf->power_level != wl->power_level) { | 1290 | if (conf->power_level != wl->power_level) { |
@@ -1449,9 +1476,24 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1449 | wl1271_error("Could not add or replace key"); | 1476 | wl1271_error("Could not add or replace key"); |
1450 | goto out_sleep; | 1477 | goto out_sleep; |
1451 | } | 1478 | } |
1479 | |||
1480 | /* the default WEP key needs to be configured at least once */ | ||
1481 | if (key_type == KEY_WEP) { | ||
1482 | ret = wl1271_cmd_set_default_wep_key(wl, | ||
1483 | wl->default_key); | ||
1484 | if (ret < 0) | ||
1485 | goto out_sleep; | ||
1486 | } | ||
1452 | break; | 1487 | break; |
1453 | 1488 | ||
1454 | case DISABLE_KEY: | 1489 | case DISABLE_KEY: |
1490 | /* The wl1271 does not allow to remove unicast keys - they | ||
1491 | will be cleared automatically on next CMD_JOIN. Ignore the | ||
1492 | request silently, as we dont want the mac80211 to emit | ||
1493 | an error message. */ | ||
1494 | if (!is_broadcast_ether_addr(addr)) | ||
1495 | break; | ||
1496 | |||
1455 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | 1497 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, |
1456 | key_conf->keyidx, key_type, | 1498 | key_conf->keyidx, key_type, |
1457 | key_conf->keylen, key_conf->key, | 1499 | key_conf->keylen, key_conf->key, |
@@ -1539,6 +1581,23 @@ out: | |||
1539 | return ret; | 1581 | return ret; |
1540 | } | 1582 | } |
1541 | 1583 | ||
1584 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon) | ||
1585 | { | ||
1586 | u8 *ptr = beacon->data + | ||
1587 | offsetof(struct ieee80211_mgmt, u.beacon.variable); | ||
1588 | |||
1589 | /* find the location of the ssid in the beacon */ | ||
1590 | while (ptr < beacon->data + beacon->len) { | ||
1591 | if (ptr[0] == WLAN_EID_SSID) { | ||
1592 | wl->ssid_len = ptr[1]; | ||
1593 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | ||
1594 | return; | ||
1595 | } | ||
1596 | ptr += ptr[1]; | ||
1597 | } | ||
1598 | wl1271_error("ad-hoc beacon template has no SSID!\n"); | ||
1599 | } | ||
1600 | |||
1542 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1601 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
1543 | struct ieee80211_vif *vif, | 1602 | struct ieee80211_vif *vif, |
1544 | struct ieee80211_bss_conf *bss_conf, | 1603 | struct ieee80211_bss_conf *bss_conf, |
@@ -1546,6 +1605,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1546 | { | 1605 | { |
1547 | enum wl1271_cmd_ps_mode mode; | 1606 | enum wl1271_cmd_ps_mode mode; |
1548 | struct wl1271 *wl = hw->priv; | 1607 | struct wl1271 *wl = hw->priv; |
1608 | bool do_join = false; | ||
1549 | int ret; | 1609 | int ret; |
1550 | 1610 | ||
1551 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1556,40 +1616,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1556 | if (ret < 0) | 1616 | if (ret < 0) |
1557 | goto out; | 1617 | goto out; |
1558 | 1618 | ||
1559 | if ((changed & BSS_CHANGED_BSSID) && | ||
1560 | /* | ||
1561 | * Now we know the correct bssid, so we send a new join command | ||
1562 | * and enable the BSSID filter | ||
1563 | */ | ||
1564 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1565 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1566 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1567 | ret = wl1271_cmd_build_null_data(wl); | ||
1568 | if (ret < 0) { | ||
1569 | wl1271_warning("cmd buld null data failed %d", | ||
1570 | ret); | ||
1571 | goto out_sleep; | ||
1572 | } | ||
1573 | ret = wl1271_cmd_join(wl); | ||
1574 | if (ret < 0) { | ||
1575 | wl1271_warning("cmd join failed %d", ret); | ||
1576 | goto out_sleep; | ||
1577 | } | ||
1578 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1579 | } | ||
1580 | |||
1581 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1619 | if (wl->bss_type == BSS_TYPE_IBSS) { |
1582 | /* FIXME: This implements rudimentary ad-hoc support - | 1620 | /* FIXME: This implements rudimentary ad-hoc support - |
1583 | proper templates are on the wish list and notification | 1621 | proper templates are on the wish list and notification |
1584 | on when they change. This patch will update the templates | 1622 | on when they change. This patch will update the templates |
1585 | on every call to this function. Also, the firmware will not | 1623 | on every call to this function. */ |
1586 | answer to probe-requests as it does not have the proper | ||
1587 | SSID set in the JOIN command. The probe-response template | ||
1588 | is set nevertheless, as the FW will ASSERT without it */ | ||
1589 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1624 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1590 | 1625 | ||
1591 | if (beacon) { | 1626 | if (beacon) { |
1592 | struct ieee80211_hdr *hdr; | 1627 | struct ieee80211_hdr *hdr; |
1628 | |||
1629 | wl1271_ssid_set(wl, beacon); | ||
1593 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1630 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1594 | beacon->data, | 1631 | beacon->data, |
1595 | beacon->len); | 1632 | beacon->len); |
@@ -1611,9 +1648,31 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1611 | dev_kfree_skb(beacon); | 1648 | dev_kfree_skb(beacon); |
1612 | if (ret < 0) | 1649 | if (ret < 0) |
1613 | goto out_sleep; | 1650 | goto out_sleep; |
1651 | |||
1652 | /* Need to update the SSID (for filtering etc) */ | ||
1653 | do_join = true; | ||
1614 | } | 1654 | } |
1615 | } | 1655 | } |
1616 | 1656 | ||
1657 | if ((changed & BSS_CHANGED_BSSID) && | ||
1658 | /* | ||
1659 | * Now we know the correct bssid, so we send a new join command | ||
1660 | * and enable the BSSID filter | ||
1661 | */ | ||
1662 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1663 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1664 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1665 | ret = wl1271_cmd_build_null_data(wl); | ||
1666 | if (ret < 0) { | ||
1667 | wl1271_warning("cmd buld null data failed %d", | ||
1668 | ret); | ||
1669 | goto out_sleep; | ||
1670 | } | ||
1671 | |||
1672 | /* Need to update the BSSID (for filtering etc) */ | ||
1673 | do_join = true; | ||
1674 | } | ||
1675 | |||
1617 | if (changed & BSS_CHANGED_ASSOC) { | 1676 | if (changed & BSS_CHANGED_ASSOC) { |
1618 | if (bss_conf->assoc) { | 1677 | if (bss_conf->assoc) { |
1619 | wl->aid = bss_conf->aid; | 1678 | wl->aid = bss_conf->aid; |
@@ -1637,7 +1696,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1637 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 1696 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1638 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 1697 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
1639 | mode = STATION_POWER_SAVE_MODE; | 1698 | mode = STATION_POWER_SAVE_MODE; |
1640 | ret = wl1271_ps_set_mode(wl, mode); | 1699 | ret = wl1271_ps_set_mode(wl, mode, true); |
1641 | if (ret < 0) | 1700 | if (ret < 0) |
1642 | goto out_sleep; | 1701 | goto out_sleep; |
1643 | } | 1702 | } |
@@ -1678,11 +1737,57 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1678 | } | 1737 | } |
1679 | } | 1738 | } |
1680 | 1739 | ||
1740 | if (do_join) { | ||
1741 | ret = wl1271_cmd_join(wl); | ||
1742 | if (ret < 0) { | ||
1743 | wl1271_warning("cmd join failed %d", ret); | ||
1744 | goto out_sleep; | ||
1745 | } | ||
1746 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1747 | } | ||
1748 | |||
1749 | out_sleep: | ||
1750 | wl1271_ps_elp_sleep(wl); | ||
1751 | |||
1752 | out: | ||
1753 | mutex_unlock(&wl->mutex); | ||
1754 | } | ||
1755 | |||
1756 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
1757 | const struct ieee80211_tx_queue_params *params) | ||
1758 | { | ||
1759 | struct wl1271 *wl = hw->priv; | ||
1760 | int ret; | ||
1761 | |||
1762 | mutex_lock(&wl->mutex); | ||
1763 | |||
1764 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
1765 | |||
1766 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1767 | if (ret < 0) | ||
1768 | goto out; | ||
1769 | |||
1770 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
1771 | params->cw_min, params->cw_max, | ||
1772 | params->aifs, params->txop); | ||
1773 | if (ret < 0) | ||
1774 | goto out_sleep; | ||
1775 | |||
1776 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
1777 | CONF_CHANNEL_TYPE_EDCF, | ||
1778 | wl1271_tx_get_queue(queue), | ||
1779 | CONF_PS_SCHEME_LEGACY_PSPOLL, | ||
1780 | CONF_ACK_POLICY_LEGACY, 0, 0); | ||
1781 | if (ret < 0) | ||
1782 | goto out_sleep; | ||
1783 | |||
1681 | out_sleep: | 1784 | out_sleep: |
1682 | wl1271_ps_elp_sleep(wl); | 1785 | wl1271_ps_elp_sleep(wl); |
1683 | 1786 | ||
1684 | out: | 1787 | out: |
1685 | mutex_unlock(&wl->mutex); | 1788 | mutex_unlock(&wl->mutex); |
1789 | |||
1790 | return ret; | ||
1686 | } | 1791 | } |
1687 | 1792 | ||
1688 | 1793 | ||
@@ -1850,6 +1955,8 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1850 | .hw_scan = wl1271_op_hw_scan, | 1955 | .hw_scan = wl1271_op_hw_scan, |
1851 | .bss_info_changed = wl1271_op_bss_info_changed, | 1956 | .bss_info_changed = wl1271_op_bss_info_changed, |
1852 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 1957 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
1958 | .conf_tx = wl1271_op_conf_tx, | ||
1959 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | ||
1853 | }; | 1960 | }; |
1854 | 1961 | ||
1855 | static int wl1271_register_hw(struct wl1271 *wl) | 1962 | static int wl1271_register_hw(struct wl1271 *wl) |
@@ -1918,24 +2025,17 @@ static struct platform_device wl1271_device = { | |||
1918 | }; | 2025 | }; |
1919 | 2026 | ||
1920 | #define WL1271_DEFAULT_CHANNEL 0 | 2027 | #define WL1271_DEFAULT_CHANNEL 0 |
1921 | static int __devinit wl1271_probe(struct spi_device *spi) | 2028 | |
2029 | static struct ieee80211_hw *wl1271_alloc_hw(void) | ||
1922 | { | 2030 | { |
1923 | struct wl12xx_platform_data *pdata; | ||
1924 | struct ieee80211_hw *hw; | 2031 | struct ieee80211_hw *hw; |
1925 | struct wl1271 *wl; | 2032 | struct wl1271 *wl; |
1926 | int ret, i; | 2033 | int i; |
1927 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
1928 | |||
1929 | pdata = spi->dev.platform_data; | ||
1930 | if (!pdata) { | ||
1931 | wl1271_error("no platform data"); | ||
1932 | return -ENODEV; | ||
1933 | } | ||
1934 | 2034 | ||
1935 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2035 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
1936 | if (!hw) { | 2036 | if (!hw) { |
1937 | wl1271_error("could not alloc ieee80211_hw"); | 2037 | wl1271_error("could not alloc ieee80211_hw"); |
1938 | return -ENOMEM; | 2038 | return ERR_PTR(-ENOMEM); |
1939 | } | 2039 | } |
1940 | 2040 | ||
1941 | wl = hw->priv; | 2041 | wl = hw->priv; |
@@ -1944,8 +2044,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1944 | INIT_LIST_HEAD(&wl->list); | 2044 | INIT_LIST_HEAD(&wl->list); |
1945 | 2045 | ||
1946 | wl->hw = hw; | 2046 | wl->hw = hw; |
1947 | dev_set_drvdata(&spi->dev, wl); | ||
1948 | wl->spi = spi; | ||
1949 | 2047 | ||
1950 | skb_queue_head_init(&wl->tx_queue); | 2048 | skb_queue_head_init(&wl->tx_queue); |
1951 | 2049 | ||
@@ -1969,16 +2067,57 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1969 | 2067 | ||
1970 | spin_lock_init(&wl->wl_lock); | 2068 | spin_lock_init(&wl->wl_lock); |
1971 | 2069 | ||
1972 | /* | ||
1973 | * In case our MAC address is not correctly set, | ||
1974 | * we use a random but Nokia MAC. | ||
1975 | */ | ||
1976 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
1977 | get_random_bytes(wl->mac_addr + 3, 3); | ||
1978 | |||
1979 | wl->state = WL1271_STATE_OFF; | 2070 | wl->state = WL1271_STATE_OFF; |
1980 | mutex_init(&wl->mutex); | 2071 | mutex_init(&wl->mutex); |
1981 | 2072 | ||
2073 | /* Apply default driver configuration. */ | ||
2074 | wl1271_conf_init(wl); | ||
2075 | |||
2076 | return hw; | ||
2077 | } | ||
2078 | |||
2079 | int wl1271_free_hw(struct wl1271 *wl) | ||
2080 | { | ||
2081 | ieee80211_unregister_hw(wl->hw); | ||
2082 | |||
2083 | wl1271_debugfs_exit(wl); | ||
2084 | |||
2085 | kfree(wl->target_mem_map); | ||
2086 | vfree(wl->fw); | ||
2087 | wl->fw = NULL; | ||
2088 | kfree(wl->nvs); | ||
2089 | wl->nvs = NULL; | ||
2090 | |||
2091 | kfree(wl->fw_status); | ||
2092 | kfree(wl->tx_res_if); | ||
2093 | |||
2094 | ieee80211_free_hw(wl->hw); | ||
2095 | |||
2096 | return 0; | ||
2097 | } | ||
2098 | |||
2099 | static int __devinit wl1271_probe(struct spi_device *spi) | ||
2100 | { | ||
2101 | struct wl12xx_platform_data *pdata; | ||
2102 | struct ieee80211_hw *hw; | ||
2103 | struct wl1271 *wl; | ||
2104 | int ret; | ||
2105 | |||
2106 | pdata = spi->dev.platform_data; | ||
2107 | if (!pdata) { | ||
2108 | wl1271_error("no platform data"); | ||
2109 | return -ENODEV; | ||
2110 | } | ||
2111 | |||
2112 | hw = wl1271_alloc_hw(); | ||
2113 | if (IS_ERR(hw)) | ||
2114 | return PTR_ERR(hw); | ||
2115 | |||
2116 | wl = hw->priv; | ||
2117 | |||
2118 | dev_set_drvdata(&spi->dev, wl); | ||
2119 | wl->spi = spi; | ||
2120 | |||
1982 | /* This is the only SPI value that we need to set here, the rest | 2121 | /* This is the only SPI value that we need to set here, the rest |
1983 | * comes from the board-peripherals file */ | 2122 | * comes from the board-peripherals file */ |
1984 | spi->bits_per_word = 32; | 2123 | spi->bits_per_word = 32; |
@@ -2020,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
2020 | } | 2159 | } |
2021 | dev_set_drvdata(&wl1271_device.dev, wl); | 2160 | dev_set_drvdata(&wl1271_device.dev, wl); |
2022 | 2161 | ||
2023 | /* Apply default driver configuration. */ | ||
2024 | wl1271_conf_init(wl); | ||
2025 | |||
2026 | ret = wl1271_init_ieee80211(wl); | 2162 | ret = wl1271_init_ieee80211(wl); |
2027 | if (ret) | 2163 | if (ret) |
2028 | goto out_platform; | 2164 | goto out_platform; |
@@ -2053,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
2053 | { | 2189 | { |
2054 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); | 2190 | struct wl1271 *wl = dev_get_drvdata(&spi->dev); |
2055 | 2191 | ||
2056 | ieee80211_unregister_hw(wl->hw); | ||
2057 | |||
2058 | wl1271_debugfs_exit(wl); | ||
2059 | platform_device_unregister(&wl1271_device); | 2192 | platform_device_unregister(&wl1271_device); |
2060 | free_irq(wl->irq, wl); | 2193 | free_irq(wl->irq, wl); |
2061 | kfree(wl->target_mem_map); | ||
2062 | vfree(wl->fw); | ||
2063 | wl->fw = NULL; | ||
2064 | kfree(wl->nvs); | ||
2065 | wl->nvs = NULL; | ||
2066 | |||
2067 | kfree(wl->fw_status); | ||
2068 | kfree(wl->tx_res_if); | ||
2069 | 2194 | ||
2070 | ieee80211_free_hw(wl->hw); | 2195 | wl1271_free_hw(wl); |
2071 | 2196 | ||
2072 | return 0; | 2197 | return 0; |
2073 | } | 2198 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index e407790f6771..e2b1ebf096e8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "wl1271_reg.h" | 24 | #include "wl1271_reg.h" |
25 | #include "wl1271_ps.h" | 25 | #include "wl1271_ps.h" |
26 | #include "wl1271_spi.h" | 26 | #include "wl1271_spi.h" |
27 | #include "wl1271_io.h" | ||
27 | 28 | ||
28 | #define WL1271_WAKEUP_TIMEOUT 500 | 29 | #define WL1271_WAKEUP_TIMEOUT 500 |
29 | 30 | ||
@@ -118,7 +119,8 @@ out: | |||
118 | return 0; | 119 | return 0; |
119 | } | 120 | } |
120 | 121 | ||
121 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | 122 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
123 | bool send) | ||
122 | { | 124 | { |
123 | int ret; | 125 | int ret; |
124 | 126 | ||
@@ -126,21 +128,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
126 | case STATION_POWER_SAVE_MODE: | 128 | case STATION_POWER_SAVE_MODE: |
127 | wl1271_debug(DEBUG_PSM, "entering psm"); | 129 | wl1271_debug(DEBUG_PSM, "entering psm"); |
128 | 130 | ||
129 | /* enable beacon filtering */ | 131 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send); |
130 | ret = wl1271_acx_beacon_filter_opt(wl, true); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | /* enable beacon early termination */ | ||
135 | ret = wl1271_acx_bet_enable(wl, true); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); | ||
140 | if (ret < 0) | ||
141 | return ret; | ||
142 | |||
143 | wl1271_ps_elp_sleep(wl); | ||
144 | if (ret < 0) | 132 | if (ret < 0) |
145 | return ret; | 133 | return ret; |
146 | 134 | ||
@@ -163,7 +151,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
163 | if (ret < 0) | 151 | if (ret < 0) |
164 | return ret; | 152 | return ret; |
165 | 153 | ||
166 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); | 154 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send); |
167 | if (ret < 0) | 155 | if (ret < 0) |
168 | return ret; | 156 | return ret; |
169 | 157 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index 779653d0ae85..940276f517a4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h | |||
@@ -27,7 +27,8 @@ | |||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_acx.h" | 28 | #include "wl1271_acx.h" |
29 | 29 | ||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, |
31 | bool send); | ||
31 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 32 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
32 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 33 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); |
33 | void wl1271_elp_work(struct work_struct *work); | 34 | void wl1271_elp_work(struct work_struct *work); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index ca645f38109b..6730f5b96e76 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "wl1271_reg.h" | 26 | #include "wl1271_reg.h" |
27 | #include "wl1271_rx.h" | 27 | #include "wl1271_rx.h" |
28 | #include "wl1271_spi.h" | 28 | #include "wl1271_spi.h" |
29 | #include "wl1271_io.h" | ||
29 | 30 | ||
30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 31 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
31 | u32 drv_rx_counter) | 32 | u32 drv_rx_counter) |
@@ -166,7 +167,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
166 | } | 167 | } |
167 | 168 | ||
168 | buf = skb_put(skb, length); | 169 | buf = skb_put(skb, length); |
169 | wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); | 170 | wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); |
170 | 171 | ||
171 | /* the data read starts with the descriptor */ | 172 | /* the data read starts with the descriptor */ |
172 | desc = (struct wl1271_rx_descriptor *) buf; | 173 | desc = (struct wl1271_rx_descriptor *) buf; |
@@ -210,15 +211,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
210 | wl->rx_mem_pool_addr.addr + 4; | 211 | wl->rx_mem_pool_addr.addr + 4; |
211 | 212 | ||
212 | /* Choose the block we want to read */ | 213 | /* Choose the block we want to read */ |
213 | wl1271_spi_write(wl, WL1271_SLV_REG_DATA, | 214 | wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr, |
214 | &wl->rx_mem_pool_addr, | 215 | sizeof(wl->rx_mem_pool_addr), false); |
215 | sizeof(wl->rx_mem_pool_addr), false); | ||
216 | 216 | ||
217 | wl1271_rx_handle_data(wl, buf_size); | 217 | wl1271_rx_handle_data(wl, buf_size); |
218 | 218 | ||
219 | wl->rx_counter++; | 219 | wl->rx_counter++; |
220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
221 | wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
221 | } | 222 | } |
222 | |||
223 | wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | ||
224 | } | 223 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index ee9564aa6ecc..67a82934f36e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -30,28 +30,6 @@ | |||
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 31 | #include "wl1271_spi.h" |
32 | 32 | ||
33 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) | ||
34 | { | ||
35 | /* | ||
36 | * To translate, first check to which window of addresses the | ||
37 | * particular address belongs. Then subtract the starting address | ||
38 | * of that window from the address. Then, add offset of the | ||
39 | * translated region. | ||
40 | * | ||
41 | * The translated regions occur next to each other in physical device | ||
42 | * memory, so just add the sizes of the preceeding address regions to | ||
43 | * get the offset to the new region. | ||
44 | * | ||
45 | * Currently, only the two first regions are addressed, and the | ||
46 | * assumption is that all addresses will fall into either of those | ||
47 | * two. | ||
48 | */ | ||
49 | if ((addr >= wl->part.reg.start) && | ||
50 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
51 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
52 | else | ||
53 | return addr - wl->part.mem.start; | ||
54 | } | ||
55 | 33 | ||
56 | void wl1271_spi_reset(struct wl1271 *wl) | 34 | void wl1271_spi_reset(struct wl1271 *wl) |
57 | { | 35 | { |
@@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
133 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 111 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
134 | } | 112 | } |
135 | 113 | ||
136 | /* Set the SPI partitions to access the chip addresses | ||
137 | * | ||
138 | * To simplify driver code, a fixed (virtual) memory map is defined for | ||
139 | * register and memory addresses. Because in the chipset, in different stages | ||
140 | * of operation, those addresses will move around, an address translation | ||
141 | * mechanism is required. | ||
142 | * | ||
143 | * There are four partitions (three memory and one register partition), | ||
144 | * which are mapped to two different areas of the hardware memory. | ||
145 | * | ||
146 | * Virtual address | ||
147 | * space | ||
148 | * | ||
149 | * | | | ||
150 | * ...+----+--> mem.start | ||
151 | * Physical address ... | | | ||
152 | * space ... | | [PART_0] | ||
153 | * ... | | | ||
154 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size | ||
155 | * | | ... | | | ||
156 | * |MEM | ... | | | ||
157 | * | | ... | | | ||
158 | * mem.size <--+----+... | | {unused area) | ||
159 | * | | ... | | | ||
160 | * |REG | ... | | | ||
161 | * mem.size | | ... | | | ||
162 | * + <--+----+... ...+----+--> reg.start | ||
163 | * reg.size | | ... | | | ||
164 | * |MEM2| ... | | [PART_1] | ||
165 | * | | ... | | | ||
166 | * ...+----+--> reg.start + reg.size | ||
167 | * | | | ||
168 | * | ||
169 | */ | ||
170 | int wl1271_set_partition(struct wl1271 *wl, | ||
171 | struct wl1271_partition_set *p) | ||
172 | { | ||
173 | /* copy partition info */ | ||
174 | memcpy(&wl->part, p, sizeof(*p)); | ||
175 | |||
176 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
177 | p->mem.start, p->mem.size); | ||
178 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
179 | p->reg.start, p->reg.size); | ||
180 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | ||
181 | p->mem2.start, p->mem2.size); | ||
182 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", | ||
183 | p->mem3.start, p->mem3.size); | ||
184 | |||
185 | /* write partition info to the chipset */ | ||
186 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | ||
187 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | ||
188 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
189 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
190 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
191 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
192 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 114 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
198 | 115 | ||
199 | /* FIXME: Check busy words, removed due to SPI bug */ | 116 | /* FIXME: Check busy words, removed due to SPI bug */ |
@@ -338,77 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
338 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); | 255 | wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); |
339 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 256 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
340 | } | 257 | } |
341 | |||
342 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
343 | bool fixed) | ||
344 | { | ||
345 | int physical; | ||
346 | |||
347 | physical = wl1271_translate_addr(wl, addr); | ||
348 | |||
349 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); | ||
350 | } | ||
351 | |||
352 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
353 | bool fixed) | ||
354 | { | ||
355 | int physical; | ||
356 | |||
357 | physical = wl1271_translate_addr(wl, addr); | ||
358 | |||
359 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); | ||
360 | } | ||
361 | |||
362 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr) | ||
363 | { | ||
364 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); | ||
365 | } | ||
366 | |||
367 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) | ||
368 | { | ||
369 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
370 | } | ||
371 | |||
372 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) | ||
373 | { | ||
374 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
375 | addr = (addr >> 1) + 0x30000; | ||
376 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
377 | |||
378 | /* write value to OCP_POR_WDATA */ | ||
379 | wl1271_spi_write32(wl, OCP_DATA_WRITE, val); | ||
380 | |||
381 | /* write 1 to OCP_CMD */ | ||
382 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
383 | } | ||
384 | |||
385 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) | ||
386 | { | ||
387 | u32 val; | ||
388 | int timeout = OCP_CMD_LOOP; | ||
389 | |||
390 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | ||
391 | addr = (addr >> 1) + 0x30000; | ||
392 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
393 | |||
394 | /* write 2 to OCP_CMD */ | ||
395 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
396 | |||
397 | /* poll for data ready */ | ||
398 | do { | ||
399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); | ||
400 | } while (!(val & OCP_READY_MASK) && --timeout); | ||
401 | |||
402 | if (!timeout) { | ||
403 | wl1271_warning("Top register access timed out."); | ||
404 | return 0xffff; | ||
405 | } | ||
406 | |||
407 | /* check data status and return if OK */ | ||
408 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
409 | return val & 0xffff; | ||
410 | else { | ||
411 | wl1271_warning("Top register access returned error."); | ||
412 | return 0xffff; | ||
413 | } | ||
414 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h index cb7df1c56314..a803596dad4a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ b/drivers/net/wireless/wl12xx/wl1271_spi.h | |||
@@ -90,37 +90,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
91 | size_t len, bool fixed); | 91 | size_t len, bool fixed); |
92 | 92 | ||
93 | /* Translated target IO */ | ||
94 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
95 | bool fixed); | ||
96 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
97 | bool fixed); | ||
98 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr); | ||
99 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val); | ||
100 | |||
101 | /* Top Register IO */ | ||
102 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); | ||
103 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); | ||
104 | |||
105 | /* INIT and RESET words */ | 93 | /* INIT and RESET words */ |
106 | void wl1271_spi_reset(struct wl1271 *wl); | 94 | void wl1271_spi_reset(struct wl1271 *wl); |
107 | void wl1271_spi_init(struct wl1271 *wl); | 95 | void wl1271_spi_init(struct wl1271 *wl); |
108 | int wl1271_set_partition(struct wl1271 *wl, | ||
109 | struct wl1271_partition_set *p); | ||
110 | |||
111 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | ||
112 | { | ||
113 | wl1271_spi_raw_read(wl, addr, &wl->buffer_32, | ||
114 | sizeof(wl->buffer_32), false); | ||
115 | |||
116 | return wl->buffer_32; | ||
117 | } | ||
118 | |||
119 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | ||
120 | { | ||
121 | wl->buffer_32 = val; | ||
122 | wl1271_spi_raw_write(wl, addr, &wl->buffer_32, | ||
123 | sizeof(wl->buffer_32), false); | ||
124 | } | ||
125 | |||
126 | #endif /* __WL1271_SPI_H__ */ | 96 | #endif /* __WL1271_SPI_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c new file mode 100644 index 000000000000..3919102e942e --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c | |||
@@ -0,0 +1,283 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | #include "wl1271_testmode.h" | ||
24 | |||
25 | #include <net/genetlink.h> | ||
26 | |||
27 | #include "wl1271.h" | ||
28 | #include "wl1271_spi.h" | ||
29 | #include "wl1271_acx.h" | ||
30 | |||
31 | #define WL1271_TM_MAX_DATA_LENGTH 1024 | ||
32 | |||
33 | enum wl1271_tm_commands { | ||
34 | WL1271_TM_CMD_UNSPEC, | ||
35 | WL1271_TM_CMD_TEST, | ||
36 | WL1271_TM_CMD_INTERROGATE, | ||
37 | WL1271_TM_CMD_CONFIGURE, | ||
38 | WL1271_TM_CMD_NVS_PUSH, | ||
39 | WL1271_TM_CMD_SET_PLT_MODE, | ||
40 | |||
41 | __WL1271_TM_CMD_AFTER_LAST | ||
42 | }; | ||
43 | #define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1) | ||
44 | |||
45 | enum wl1271_tm_attrs { | ||
46 | WL1271_TM_ATTR_UNSPEC, | ||
47 | WL1271_TM_ATTR_CMD_ID, | ||
48 | WL1271_TM_ATTR_ANSWER, | ||
49 | WL1271_TM_ATTR_DATA, | ||
50 | WL1271_TM_ATTR_IE_ID, | ||
51 | WL1271_TM_ATTR_PLT_MODE, | ||
52 | |||
53 | __WL1271_TM_ATTR_AFTER_LAST | ||
54 | }; | ||
55 | #define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1) | ||
56 | |||
57 | static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = { | ||
58 | [WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 }, | ||
59 | [WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 }, | ||
60 | [WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY, | ||
61 | .len = WL1271_TM_MAX_DATA_LENGTH }, | ||
62 | [WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 }, | ||
63 | [WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 }, | ||
64 | }; | ||
65 | |||
66 | |||
67 | static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) | ||
68 | { | ||
69 | int buf_len, ret, len; | ||
70 | struct sk_buff *skb; | ||
71 | void *buf; | ||
72 | u8 answer = 0; | ||
73 | |||
74 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd test"); | ||
75 | |||
76 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
77 | return -EINVAL; | ||
78 | |||
79 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
80 | buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
81 | |||
82 | if (tb[WL1271_TM_ATTR_ANSWER]) | ||
83 | answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]); | ||
84 | |||
85 | if (buf_len > sizeof(struct wl1271_command)) | ||
86 | return -EMSGSIZE; | ||
87 | |||
88 | mutex_lock(&wl->mutex); | ||
89 | ret = wl1271_cmd_test(wl, buf, buf_len, answer); | ||
90 | mutex_unlock(&wl->mutex); | ||
91 | |||
92 | if (ret < 0) { | ||
93 | wl1271_warning("testmode cmd test failed: %d", ret); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | if (answer) { | ||
98 | len = nla_total_size(buf_len); | ||
99 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); | ||
100 | if (!skb) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); | ||
104 | ret = cfg80211_testmode_reply(skb); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | |||
111 | nla_put_failure: | ||
112 | kfree_skb(skb); | ||
113 | return -EMSGSIZE; | ||
114 | } | ||
115 | |||
116 | static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) | ||
117 | { | ||
118 | int ret; | ||
119 | struct wl1271_command *cmd; | ||
120 | struct sk_buff *skb; | ||
121 | u8 ie_id; | ||
122 | |||
123 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate"); | ||
124 | |||
125 | if (!tb[WL1271_TM_ATTR_IE_ID]) | ||
126 | return -EINVAL; | ||
127 | |||
128 | ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); | ||
129 | |||
130 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
131 | if (!cmd) | ||
132 | return -ENOMEM; | ||
133 | |||
134 | mutex_lock(&wl->mutex); | ||
135 | ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); | ||
136 | mutex_unlock(&wl->mutex); | ||
137 | |||
138 | if (ret < 0) { | ||
139 | wl1271_warning("testmode cmd interrogate failed: %d", ret); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); | ||
144 | if (!skb) | ||
145 | return -ENOMEM; | ||
146 | |||
147 | NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); | ||
148 | |||
149 | return 0; | ||
150 | |||
151 | nla_put_failure: | ||
152 | kfree_skb(skb); | ||
153 | return -EMSGSIZE; | ||
154 | } | ||
155 | |||
156 | static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) | ||
157 | { | ||
158 | int buf_len, ret; | ||
159 | void *buf; | ||
160 | u8 ie_id; | ||
161 | |||
162 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure"); | ||
163 | |||
164 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
165 | return -EINVAL; | ||
166 | if (!tb[WL1271_TM_ATTR_IE_ID]) | ||
167 | return -EINVAL; | ||
168 | |||
169 | ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); | ||
170 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
171 | buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
172 | |||
173 | if (buf_len > sizeof(struct wl1271_command)) | ||
174 | return -EMSGSIZE; | ||
175 | |||
176 | mutex_lock(&wl->mutex); | ||
177 | ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len); | ||
178 | mutex_unlock(&wl->mutex); | ||
179 | |||
180 | if (ret < 0) { | ||
181 | wl1271_warning("testmode cmd configure failed: %d", ret); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[]) | ||
189 | { | ||
190 | int ret = 0; | ||
191 | size_t len; | ||
192 | void *buf; | ||
193 | |||
194 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push"); | ||
195 | |||
196 | if (!tb[WL1271_TM_ATTR_DATA]) | ||
197 | return -EINVAL; | ||
198 | |||
199 | buf = nla_data(tb[WL1271_TM_ATTR_DATA]); | ||
200 | len = nla_len(tb[WL1271_TM_ATTR_DATA]); | ||
201 | |||
202 | if (len != sizeof(struct wl1271_nvs_file)) { | ||
203 | wl1271_error("nvs size is not as expected: %zu != %zu", | ||
204 | len, sizeof(struct wl1271_nvs_file)); | ||
205 | return -EMSGSIZE; | ||
206 | } | ||
207 | |||
208 | mutex_lock(&wl->mutex); | ||
209 | |||
210 | kfree(wl->nvs); | ||
211 | |||
212 | wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL); | ||
213 | if (!wl->nvs) { | ||
214 | wl1271_error("could not allocate memory for the nvs file"); | ||
215 | ret = -ENOMEM; | ||
216 | goto out; | ||
217 | } | ||
218 | |||
219 | memcpy(wl->nvs, buf, len); | ||
220 | |||
221 | wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs"); | ||
222 | |||
223 | out: | ||
224 | mutex_unlock(&wl->mutex); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[]) | ||
230 | { | ||
231 | u32 val; | ||
232 | int ret; | ||
233 | |||
234 | wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode"); | ||
235 | |||
236 | if (!tb[WL1271_TM_ATTR_PLT_MODE]) | ||
237 | return -EINVAL; | ||
238 | |||
239 | val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]); | ||
240 | |||
241 | switch (val) { | ||
242 | case 0: | ||
243 | ret = wl1271_plt_stop(wl); | ||
244 | break; | ||
245 | case 1: | ||
246 | ret = wl1271_plt_start(wl); | ||
247 | break; | ||
248 | default: | ||
249 | ret = -EINVAL; | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
257 | { | ||
258 | struct wl1271 *wl = hw->priv; | ||
259 | struct nlattr *tb[WL1271_TM_ATTR_MAX + 1]; | ||
260 | int err; | ||
261 | |||
262 | err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy); | ||
263 | if (err) | ||
264 | return err; | ||
265 | |||
266 | if (!tb[WL1271_TM_ATTR_CMD_ID]) | ||
267 | return -EINVAL; | ||
268 | |||
269 | switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) { | ||
270 | case WL1271_TM_CMD_TEST: | ||
271 | return wl1271_tm_cmd_test(wl, tb); | ||
272 | case WL1271_TM_CMD_INTERROGATE: | ||
273 | return wl1271_tm_cmd_interrogate(wl, tb); | ||
274 | case WL1271_TM_CMD_CONFIGURE: | ||
275 | return wl1271_tm_cmd_configure(wl, tb); | ||
276 | case WL1271_TM_CMD_NVS_PUSH: | ||
277 | return wl1271_tm_cmd_nvs_push(wl, tb); | ||
278 | case WL1271_TM_CMD_SET_PLT_MODE: | ||
279 | return wl1271_tm_cmd_set_plt_mode(wl, tb); | ||
280 | default: | ||
281 | return -EOPNOTSUPP; | ||
282 | } | ||
283 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.h b/drivers/net/wireless/wl12xx/wl1271_testmode.h new file mode 100644 index 000000000000..c196d28f9d9d --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2010 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_TESTMODE_H__ | ||
25 | #define __WL1271_TESTMODE_H__ | ||
26 | |||
27 | #include <net/mac80211.h> | ||
28 | |||
29 | int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len); | ||
30 | |||
31 | #endif /* __WL1271_TESTMODE_H__ */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index a288cc317d7b..811e739d05bf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "wl1271.h" | 27 | #include "wl1271.h" |
28 | #include "wl1271_spi.h" | 28 | #include "wl1271_spi.h" |
29 | #include "wl1271_io.h" | ||
29 | #include "wl1271_reg.h" | 30 | #include "wl1271_reg.h" |
30 | #include "wl1271_ps.h" | 31 | #include "wl1271_ps.h" |
31 | #include "wl1271_tx.h" | 32 | #include "wl1271_tx.h" |
@@ -87,7 +88,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
87 | u32 extra, struct ieee80211_tx_info *control) | 88 | u32 extra, struct ieee80211_tx_info *control) |
88 | { | 89 | { |
89 | struct wl1271_tx_hw_descr *desc; | 90 | struct wl1271_tx_hw_descr *desc; |
90 | int pad; | 91 | int pad, ac; |
91 | u16 tx_attr; | 92 | u16 tx_attr; |
92 | 93 | ||
93 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 94 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
@@ -107,9 +108,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
107 | 108 | ||
108 | /* configure the tx attributes */ | 109 | /* configure the tx attributes */ |
109 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 110 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
110 | /* FIXME: do we know the packet priority? can we identify mgmt | 111 | |
111 | packets, and use max prio for them at least? */ | 112 | /* queue */ |
112 | desc->tid = 0; | 113 | ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
114 | desc->tid = wl1271_tx_ac_to_tid(ac); | ||
115 | |||
113 | desc->aid = TX_HW_DEFAULT_AID; | 116 | desc->aid = TX_HW_DEFAULT_AID; |
114 | desc->reserved = 0; | 117 | desc->reserved = 0; |
115 | 118 | ||
@@ -163,11 +166,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | |||
163 | len = WL1271_TX_ALIGN(skb->len); | 166 | len = WL1271_TX_ALIGN(skb->len); |
164 | 167 | ||
165 | /* perform a fixed address block write with the packet */ | 168 | /* perform a fixed address block write with the packet */ |
166 | wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); | 169 | wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); |
167 | 170 | ||
168 | /* write packet new counter into the write access register */ | 171 | /* write packet new counter into the write access register */ |
169 | wl->tx_packets_count++; | 172 | wl->tx_packets_count++; |
170 | wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | 173 | wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); |
171 | 174 | ||
172 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 175 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
173 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | 176 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", |
@@ -201,6 +204,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
201 | ret = wl1271_cmd_set_default_wep_key(wl, idx); | 204 | ret = wl1271_cmd_set_default_wep_key(wl, idx); |
202 | if (ret < 0) | 205 | if (ret < 0) |
203 | return ret; | 206 | return ret; |
207 | wl->default_key = idx; | ||
204 | } | 208 | } |
205 | } | 209 | } |
206 | 210 | ||
@@ -372,8 +376,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
372 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
373 | 377 | ||
374 | /* read the tx results from the chipset */ | 378 | /* read the tx results from the chipset */ |
375 | wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result), | 379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
376 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
377 | 381 | ||
378 | /* verify that the result buffer is not getting overrun */ | 382 | /* verify that the result buffer is not getting overrun */ |
379 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 383 | if (count > TX_HW_RESULT_QUEUE_LEN) { |
@@ -394,10 +398,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
394 | } | 398 | } |
395 | 399 | ||
396 | /* write host counter to chipset (to ack) */ | 400 | /* write host counter to chipset (to ack) */ |
397 | wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) + | 401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + |
398 | offsetof(struct wl1271_tx_hw_res_if, | 402 | offsetof(struct wl1271_tx_hw_res_if, |
399 | tx_result_host_counter), | 403 | tx_result_host_counter), |
400 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); |
401 | } | 405 | } |
402 | 406 | ||
403 | /* caller must hold wl->mutex */ | 407 | /* caller must hold wl->mutex */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 416396caf0a0..17e405a09caa 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if { | |||
123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; | 123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; |
124 | } __attribute__ ((packed)); | 124 | } __attribute__ ((packed)); |
125 | 125 | ||
126 | static inline int wl1271_tx_get_queue(int queue) | ||
127 | { | ||
128 | /* FIXME: use best effort until WMM is enabled */ | ||
129 | return CONF_TX_AC_BE; | ||
130 | |||
131 | switch (queue) { | ||
132 | case 0: | ||
133 | return CONF_TX_AC_VO; | ||
134 | case 1: | ||
135 | return CONF_TX_AC_VI; | ||
136 | case 2: | ||
137 | return CONF_TX_AC_BE; | ||
138 | case 3: | ||
139 | return CONF_TX_AC_BK; | ||
140 | default: | ||
141 | return CONF_TX_AC_BE; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* wl1271 tx descriptor needs the tid and we need to convert it from ac */ | ||
146 | static inline int wl1271_tx_ac_to_tid(int ac) | ||
147 | { | ||
148 | switch (ac) { | ||
149 | case 0: | ||
150 | return 0; | ||
151 | case 1: | ||
152 | return 2; | ||
153 | case 2: | ||
154 | return 4; | ||
155 | case 3: | ||
156 | return 6; | ||
157 | default: | ||
158 | return 0; | ||
159 | } | ||
160 | } | ||
161 | |||
126 | void wl1271_tx_work(struct work_struct *work); | 162 | void wl1271_tx_work(struct work_struct *work); |
127 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); | 163 | void wl1271_tx_complete(struct wl1271 *wl, u32 count); |
128 | void wl1271_tx_flush(struct wl1271 *wl); | 164 | void wl1271_tx_flush(struct wl1271 *wl); |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index 64abd11f6fbb..3d551245a4e2 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -332,6 +332,12 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
332 | case 0x5354: | 332 | case 0x5354: |
333 | ssb_pmu0_pllinit_r0(cc, crystalfreq); | 333 | ssb_pmu0_pllinit_r0(cc, crystalfreq); |
334 | break; | 334 | break; |
335 | case 0x4322: | ||
336 | if (cc->pmu.rev == 2) { | ||
337 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A); | ||
338 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); | ||
339 | } | ||
340 | break; | ||
335 | default: | 341 | default: |
336 | ssb_printk(KERN_ERR PFX | 342 | ssb_printk(KERN_ERR PFX |
337 | "ERROR: PLL init unknown for device %04X\n", | 343 | "ERROR: PLL init unknown for device %04X\n", |
@@ -417,6 +423,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
417 | 423 | ||
418 | switch (bus->chip_id) { | 424 | switch (bus->chip_id) { |
419 | case 0x4312: | 425 | case 0x4312: |
426 | case 0x4322: | ||
420 | /* We keep the default settings: | 427 | /* We keep the default settings: |
421 | * min_msk = 0xCBB | 428 | * min_msk = 0xCBB |
422 | * max_msk = 0x7FFFF | 429 | * max_msk = 0x7FFFF |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 56054be4d113..0331139a726f 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -196,7 +196,7 @@ extern int ssb_devices_thaw(struct ssb_freeze_context *ctx); | |||
196 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE | 196 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE |
197 | extern int __init b43_pci_ssb_bridge_init(void); | 197 | extern int __init b43_pci_ssb_bridge_init(void); |
198 | extern void __exit b43_pci_ssb_bridge_exit(void); | 198 | extern void __exit b43_pci_ssb_bridge_exit(void); |
199 | #else /* CONFIG_SSB_B43_PCI_BRIDGR */ | 199 | #else /* CONFIG_SSB_B43_PCI_BRIDGE */ |
200 | static inline int b43_pci_ssb_bridge_init(void) | 200 | static inline int b43_pci_ssb_bridge_init(void) |
201 | { | 201 | { |
202 | return 0; | 202 | return 0; |
@@ -204,6 +204,6 @@ static inline int b43_pci_ssb_bridge_init(void) | |||
204 | static inline void b43_pci_ssb_bridge_exit(void) | 204 | static inline void b43_pci_ssb_bridge_exit(void) |
205 | { | 205 | { |
206 | } | 206 | } |
207 | #endif /* CONFIG_SSB_PCIHOST */ | 207 | #endif /* CONFIG_SSB_B43_PCI_BRIDGE */ |
208 | 208 | ||
209 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 209 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/drivers/staging/rtl8192su/ieee80211/ieee80211.h index 9a4c858b0666..2b8c85556dcb 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211.h | |||
@@ -609,16 +609,6 @@ struct ieee80211_hdr_2addr { | |||
609 | u8 payload[0]; | 609 | u8 payload[0]; |
610 | } __attribute__ ((packed)); | 610 | } __attribute__ ((packed)); |
611 | 611 | ||
612 | struct ieee80211_hdr_3addr { | ||
613 | __le16 frame_ctl; | ||
614 | __le16 duration_id; | ||
615 | u8 addr1[ETH_ALEN]; | ||
616 | u8 addr2[ETH_ALEN]; | ||
617 | u8 addr3[ETH_ALEN]; | ||
618 | __le16 seq_ctl; | ||
619 | u8 payload[0]; | ||
620 | } __attribute__ ((packed)); | ||
621 | |||
622 | struct ieee80211_hdr_4addr { | 612 | struct ieee80211_hdr_4addr { |
623 | __le16 frame_ctl; | 613 | __le16 frame_ctl; |
624 | __le16 duration_id; | 614 | __le16 duration_id; |
@@ -1672,7 +1662,7 @@ static inline u8 *ieee80211_get_payload(struct rtl_ieee80211_hdr *hdr) | |||
1672 | case IEEE80211_2ADDR_LEN: | 1662 | case IEEE80211_2ADDR_LEN: |
1673 | return ((struct ieee80211_hdr_2addr *)hdr)->payload; | 1663 | return ((struct ieee80211_hdr_2addr *)hdr)->payload; |
1674 | case IEEE80211_3ADDR_LEN: | 1664 | case IEEE80211_3ADDR_LEN: |
1675 | return ((struct ieee80211_hdr_3addr *)hdr)->payload; | 1665 | return (void *)hdr+sizeof(struct ieee80211_hdr_3addr); |
1676 | case IEEE80211_4ADDR_LEN: | 1666 | case IEEE80211_4ADDR_LEN: |
1677 | return ((struct ieee80211_hdr_4addr *)hdr)->payload; | 1667 | return ((struct ieee80211_hdr_4addr *)hdr)->payload; |
1678 | } | 1668 | } |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h b/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h index 123abcf0f497..7d6c3bc143ae 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_r8192s.h | |||
@@ -201,7 +201,7 @@ typedef union _frameqos { | |||
201 | static inline u8 Frame_QoSTID(u8 *buf) | 201 | static inline u8 Frame_QoSTID(u8 *buf) |
202 | { | 202 | { |
203 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf; | 203 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf; |
204 | u16 fc = le16_to_cpu(hdr->frame_ctl); | 204 | u16 fc = le16_to_cpu(hdr->frame_control); |
205 | 205 | ||
206 | return (u8)((frameqos *)(buf + | 206 | return (u8)((frameqos *)(buf + |
207 | (((fc & IEEE80211_FCTL_TODS) && | 207 | (((fc & IEEE80211_FCTL_TODS) && |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c index fecfa120ff48..095b8c643146 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c | |||
@@ -744,7 +744,7 @@ u8 parse_subframe(struct sk_buff *skb, | |||
744 | struct ieee80211_rxb *rxb,u8* src,u8* dst) | 744 | struct ieee80211_rxb *rxb,u8* src,u8* dst) |
745 | { | 745 | { |
746 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data; | 746 | struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data; |
747 | u16 fc = le16_to_cpu(hdr->frame_ctl); | 747 | u16 fc = le16_to_cpu(hdr->frame_control); |
748 | 748 | ||
749 | u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr); | 749 | u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr); |
750 | u16 ChkLength; | 750 | u16 ChkLength; |
@@ -756,7 +756,7 @@ u8 parse_subframe(struct sk_buff *skb, | |||
756 | struct sk_buff *sub_skb; | 756 | struct sk_buff *sub_skb; |
757 | u8 *data_ptr; | 757 | u8 *data_ptr; |
758 | /* just for debug purpose */ | 758 | /* just for debug purpose */ |
759 | SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); | 759 | SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctrl)); |
760 | 760 | ||
761 | if((IEEE80211_QOS_HAS_SEQ(fc))&&\ | 761 | if((IEEE80211_QOS_HAS_SEQ(fc))&&\ |
762 | (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) { | 762 | (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) { |
@@ -2370,7 +2370,7 @@ static inline void ieee80211_process_probe_response( | |||
2370 | escape_essid(info_element->data, | 2370 | escape_essid(info_element->data, |
2371 | info_element->len), | 2371 | info_element->len), |
2372 | MAC_ARG(beacon->header.addr3), | 2372 | MAC_ARG(beacon->header.addr3), |
2373 | WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == | 2373 | WLAN_FC_GET_STYPE(beacon->header.frame_control) == |
2374 | IEEE80211_STYPE_PROBE_RESP ? | 2374 | IEEE80211_STYPE_PROBE_RESP ? |
2375 | "PROBE RESPONSE" : "BEACON"); | 2375 | "PROBE RESPONSE" : "BEACON"); |
2376 | return; | 2376 | return; |
@@ -2387,7 +2387,7 @@ static inline void ieee80211_process_probe_response( | |||
2387 | return; | 2387 | return; |
2388 | if(ieee->bGlobalDomain) | 2388 | if(ieee->bGlobalDomain) |
2389 | { | 2389 | { |
2390 | if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) | 2390 | if (WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP) |
2391 | { | 2391 | { |
2392 | // Case 1: Country code | 2392 | // Case 1: Country code |
2393 | if(IS_COUNTRY_IE_VALID(ieee) ) | 2393 | if(IS_COUNTRY_IE_VALID(ieee) ) |
@@ -2454,7 +2454,7 @@ static inline void ieee80211_process_probe_response( | |||
2454 | else | 2454 | else |
2455 | ieee->current_network.buseprotection = false; | 2455 | ieee->current_network.buseprotection = false; |
2456 | } | 2456 | } |
2457 | if(is_beacon(beacon->header.frame_ctl)) | 2457 | if(is_beacon(beacon->header.frame_control)) |
2458 | { | 2458 | { |
2459 | if(ieee->state == IEEE80211_LINKED) | 2459 | if(ieee->state == IEEE80211_LINKED) |
2460 | ieee->LinkDetectInfo.NumRecvBcnInPeriod++; | 2460 | ieee->LinkDetectInfo.NumRecvBcnInPeriod++; |
@@ -2496,7 +2496,7 @@ static inline void ieee80211_process_probe_response( | |||
2496 | escape_essid(network.ssid, | 2496 | escape_essid(network.ssid, |
2497 | network.ssid_len), | 2497 | network.ssid_len), |
2498 | MAC_ARG(network.bssid), | 2498 | MAC_ARG(network.bssid), |
2499 | WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == | 2499 | WLAN_FC_GET_STYPE(beacon->header.frame_control) == |
2500 | IEEE80211_STYPE_PROBE_RESP ? | 2500 | IEEE80211_STYPE_PROBE_RESP ? |
2501 | "PROBE RESPONSE" : "BEACON"); | 2501 | "PROBE RESPONSE" : "BEACON"); |
2502 | #endif | 2502 | #endif |
@@ -2509,7 +2509,7 @@ static inline void ieee80211_process_probe_response( | |||
2509 | escape_essid(target->ssid, | 2509 | escape_essid(target->ssid, |
2510 | target->ssid_len), | 2510 | target->ssid_len), |
2511 | MAC_ARG(target->bssid), | 2511 | MAC_ARG(target->bssid), |
2512 | WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == | 2512 | WLAN_FC_GET_STYPE(beacon->header.frame_control) == |
2513 | IEEE80211_STYPE_PROBE_RESP ? | 2513 | IEEE80211_STYPE_PROBE_RESP ? |
2514 | "PROBE RESPONSE" : "BEACON"); | 2514 | "PROBE RESPONSE" : "BEACON"); |
2515 | 2515 | ||
@@ -2519,7 +2519,7 @@ static inline void ieee80211_process_probe_response( | |||
2519 | */ | 2519 | */ |
2520 | renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); | 2520 | renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); |
2521 | //YJ,add,080819,for hidden ap | 2521 | //YJ,add,080819,for hidden ap |
2522 | if(is_beacon(beacon->header.frame_ctl) == 0) | 2522 | if(is_beacon(beacon->header.frame_control) == 0) |
2523 | network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); | 2523 | network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); |
2524 | //if(strncmp(network.ssid, "linksys-c",9) == 0) | 2524 | //if(strncmp(network.ssid, "linksys-c",9) == 0) |
2525 | // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); | 2525 | // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); |
@@ -2535,7 +2535,7 @@ static inline void ieee80211_process_probe_response( | |||
2535 | } | 2535 | } |
2536 | 2536 | ||
2537 | spin_unlock_irqrestore(&ieee->lock, flags); | 2537 | spin_unlock_irqrestore(&ieee->lock, flags); |
2538 | if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\ | 2538 | if (is_beacon(beacon->header.frame_control)&&is_same_network(&ieee->current_network, &network, ieee)&&\ |
2539 | (ieee->state == IEEE80211_LINKED)) { | 2539 | (ieee->state == IEEE80211_LINKED)) { |
2540 | if(ieee->handle_beacon != NULL) { | 2540 | if(ieee->handle_beacon != NULL) { |
2541 | ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); | 2541 | ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); |
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c index 95d4f84dcf3f..0ba2a01a06a1 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c | |||
@@ -242,7 +242,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee | |||
242 | if(ieee->queue_stop){ | 242 | if(ieee->queue_stop){ |
243 | enqueue_mgmt(ieee,skb); | 243 | enqueue_mgmt(ieee,skb); |
244 | }else{ | 244 | }else{ |
245 | header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); | 245 | header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4); |
246 | 246 | ||
247 | if (ieee->seq_ctrl[0] == 0xFFF) | 247 | if (ieee->seq_ctrl[0] == 0xFFF) |
248 | ieee->seq_ctrl[0] = 0; | 248 | ieee->seq_ctrl[0] = 0; |
@@ -260,7 +260,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee | |||
260 | spin_unlock_irqrestore(&ieee->lock, flags); | 260 | spin_unlock_irqrestore(&ieee->lock, flags); |
261 | spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); | 261 | spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); |
262 | 262 | ||
263 | header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); | 263 | header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); |
264 | 264 | ||
265 | if (ieee->seq_ctrl[0] == 0xFFF) | 265 | if (ieee->seq_ctrl[0] == 0xFFF) |
266 | ieee->seq_ctrl[0] = 0; | 266 | ieee->seq_ctrl[0] = 0; |
@@ -302,7 +302,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i | |||
302 | //printk("=============>%s()\n", __FUNCTION__); | 302 | //printk("=============>%s()\n", __FUNCTION__); |
303 | if(single){ | 303 | if(single){ |
304 | 304 | ||
305 | header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); | 305 | header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); |
306 | 306 | ||
307 | if (ieee->seq_ctrl[0] == 0xFFF) | 307 | if (ieee->seq_ctrl[0] == 0xFFF) |
308 | ieee->seq_ctrl[0] = 0; | 308 | ieee->seq_ctrl[0] = 0; |
@@ -315,7 +315,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i | |||
315 | 315 | ||
316 | }else{ | 316 | }else{ |
317 | 317 | ||
318 | header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); | 318 | header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); |
319 | 319 | ||
320 | if (ieee->seq_ctrl[0] == 0xFFF) | 320 | if (ieee->seq_ctrl[0] == 0xFFF) |
321 | ieee->seq_ctrl[0] = 0; | 321 | ieee->seq_ctrl[0] = 0; |
@@ -347,7 +347,7 @@ inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) | |||
347 | skb_reserve(skb, ieee->tx_headroom); | 347 | skb_reserve(skb, ieee->tx_headroom); |
348 | 348 | ||
349 | req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); | 349 | req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); |
350 | req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); | 350 | req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); |
351 | req->header.duration_id = 0; //FIXME: is this OK ? | 351 | req->header.duration_id = 0; //FIXME: is this OK ? |
352 | 352 | ||
353 | memset(req->header.addr1, 0xff, ETH_ALEN); | 353 | memset(req->header.addr1, 0xff, ETH_ALEN); |
@@ -662,8 +662,8 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be | |||
662 | auth = (struct ieee80211_authentication *) | 662 | auth = (struct ieee80211_authentication *) |
663 | skb_put(skb, sizeof(struct ieee80211_authentication)); | 663 | skb_put(skb, sizeof(struct ieee80211_authentication)); |
664 | 664 | ||
665 | auth->header.frame_ctl = IEEE80211_STYPE_AUTH; | 665 | auth->header.frame_control = IEEE80211_STYPE_AUTH; |
666 | if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP; | 666 | if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP; |
667 | 667 | ||
668 | auth->header.duration_id = 0x013a; //FIXME | 668 | auth->header.duration_id = 0x013a; //FIXME |
669 | 669 | ||
@@ -801,7 +801,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d | |||
801 | beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); | 801 | beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); |
802 | 802 | ||
803 | 803 | ||
804 | beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); | 804 | beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); |
805 | beacon_buf->info_element[0].id = MFIE_TYPE_SSID; | 805 | beacon_buf->info_element[0].id = MFIE_TYPE_SSID; |
806 | beacon_buf->info_element[0].len = ssid_len; | 806 | beacon_buf->info_element[0].len = ssid_len; |
807 | 807 | ||
@@ -880,7 +880,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) | |||
880 | assoc = (struct ieee80211_assoc_response_frame *) | 880 | assoc = (struct ieee80211_assoc_response_frame *) |
881 | skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); | 881 | skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); |
882 | 882 | ||
883 | assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); | 883 | assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); |
884 | memcpy(assoc->header.addr1, dest,ETH_ALEN); | 884 | memcpy(assoc->header.addr1, dest,ETH_ALEN); |
885 | memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); | 885 | memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); |
886 | memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); | 886 | memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); |
@@ -935,7 +935,7 @@ struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 | |||
935 | memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); | 935 | memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); |
936 | memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); | 936 | memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); |
937 | memcpy(auth->header.addr1, dest, ETH_ALEN); | 937 | memcpy(auth->header.addr1, dest, ETH_ALEN); |
938 | auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); | 938 | auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH); |
939 | return skb; | 939 | return skb; |
940 | 940 | ||
941 | 941 | ||
@@ -957,7 +957,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) | |||
957 | memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); | 957 | memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); |
958 | memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); | 958 | memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); |
959 | 959 | ||
960 | hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | 960 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | |
961 | IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | | 961 | IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | |
962 | (pwr ? IEEE80211_FCTL_PM:0)); | 962 | (pwr ? IEEE80211_FCTL_PM:0)); |
963 | 963 | ||
@@ -1083,7 +1083,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco | |||
1083 | skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2); | 1083 | skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2); |
1084 | 1084 | ||
1085 | 1085 | ||
1086 | hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; | 1086 | hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ; |
1087 | hdr->header.duration_id= 37; //FIXME | 1087 | hdr->header.duration_id= 37; //FIXME |
1088 | memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); | 1088 | memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); |
1089 | memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); | 1089 | memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); |
@@ -1940,13 +1940,13 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
1940 | if(!ieee->proto_started) | 1940 | if(!ieee->proto_started) |
1941 | return 0; | 1941 | return 0; |
1942 | 1942 | ||
1943 | switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { | 1943 | switch (WLAN_FC_GET_STYPE(header->frame_control)) { |
1944 | 1944 | ||
1945 | case IEEE80211_STYPE_ASSOC_RESP: | 1945 | case IEEE80211_STYPE_ASSOC_RESP: |
1946 | case IEEE80211_STYPE_REASSOC_RESP: | 1946 | case IEEE80211_STYPE_REASSOC_RESP: |
1947 | 1947 | ||
1948 | IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", | 1948 | IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", |
1949 | WLAN_FC_GET_STYPE(header->frame_ctl)); | 1949 | WLAN_FC_GET_STYPE(header->frame_control)); |
1950 | if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && | 1950 | if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && |
1951 | ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && | 1951 | ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && |
1952 | ieee->iw_mode == IW_MODE_INFRA){ | 1952 | ieee->iw_mode == IW_MODE_INFRA){ |
@@ -2088,7 +2088,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
2088 | if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && | 2088 | if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && |
2089 | ieee->state == IEEE80211_LINKED && | 2089 | ieee->state == IEEE80211_LINKED && |
2090 | ieee->iw_mode == IW_MODE_INFRA){ | 2090 | ieee->iw_mode == IW_MODE_INFRA){ |
2091 | printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason); | 2091 | printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason); |
2092 | ieee->state = IEEE80211_ASSOCIATING; | 2092 | ieee->state = IEEE80211_ASSOCIATING; |
2093 | ieee->softmac_stats.reassoc++; | 2093 | ieee->softmac_stats.reassoc++; |
2094 | ieee->is_roaming = true; | 2094 | ieee->is_roaming = true; |
@@ -2239,7 +2239,7 @@ void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) | |||
2239 | 2239 | ||
2240 | header = (struct ieee80211_hdr_3addr *) skb->data; | 2240 | header = (struct ieee80211_hdr_3addr *) skb->data; |
2241 | 2241 | ||
2242 | header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); | 2242 | header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); |
2243 | 2243 | ||
2244 | if (ieee->seq_ctrl[0] == 0xFFF) | 2244 | if (ieee->seq_ctrl[0] == 0xFFF) |
2245 | ieee->seq_ctrl[0] = 0; | 2245 | ieee->seq_ctrl[0] = 0; |
@@ -2574,7 +2574,7 @@ struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) | |||
2574 | return NULL; | 2574 | return NULL; |
2575 | 2575 | ||
2576 | b = (struct ieee80211_probe_response *) skb->data; | 2576 | b = (struct ieee80211_probe_response *) skb->data; |
2577 | b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); | 2577 | b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON); |
2578 | 2578 | ||
2579 | return skb; | 2579 | return skb; |
2580 | 2580 | ||
@@ -2590,7 +2590,7 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) | |||
2590 | return NULL; | 2590 | return NULL; |
2591 | 2591 | ||
2592 | b = (struct ieee80211_probe_response *) skb->data; | 2592 | b = (struct ieee80211_probe_response *) skb->data; |
2593 | b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); | 2593 | b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); |
2594 | 2594 | ||
2595 | if (ieee->seq_ctrl[0] == 0xFFF) | 2595 | if (ieee->seq_ctrl[0] == 0xFFF) |
2596 | ieee->seq_ctrl[0] = 0; | 2596 | ieee->seq_ctrl[0] = 0; |
@@ -3139,7 +3139,7 @@ inline struct sk_buff *ieee80211_disassociate_skb( | |||
3139 | return NULL; | 3139 | return NULL; |
3140 | 3140 | ||
3141 | disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc)); | 3141 | disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc)); |
3142 | disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC); | 3142 | disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); |
3143 | disass->header.duration_id = 0; | 3143 | disass->header.duration_id = 0; |
3144 | 3144 | ||
3145 | memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); | 3145 | memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); |
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c index 8d12ffca18fa..c6962450e06f 100644 --- a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c | |||
@@ -136,7 +136,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P | |||
136 | 136 | ||
137 | memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); | 137 | memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); |
138 | 138 | ||
139 | BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame | 139 | BAReq->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame |
140 | 140 | ||
141 | //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field | 141 | //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field |
142 | tag = (u8*)skb_put(skb, 9); | 142 | tag = (u8*)skb_put(skb, 9); |
@@ -221,7 +221,7 @@ static struct sk_buff* ieee80211_DELBA( | |||
221 | memcpy(Delba->addr1, dst, ETH_ALEN); | 221 | memcpy(Delba->addr1, dst, ETH_ALEN); |
222 | memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); | 222 | memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); |
223 | memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); | 223 | memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); |
224 | Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame | 224 | Delba->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame |
225 | 225 | ||
226 | tag = (u8*)skb_put(skb, 6); | 226 | tag = (u8*)skb_put(skb, 6); |
227 | 227 | ||
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index ccb9d5b8cd44..6f424fe8a237 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c | |||
@@ -6168,7 +6168,7 @@ void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee802 | |||
6168 | u16 sc ; | 6168 | u16 sc ; |
6169 | unsigned int frag,seq; | 6169 | unsigned int frag,seq; |
6170 | hdr = (struct ieee80211_hdr_3addr *)buffer; | 6170 | hdr = (struct ieee80211_hdr_3addr *)buffer; |
6171 | sc = le16_to_cpu(hdr->seq_ctl); | 6171 | sc = le16_to_cpu(hdr->seq_ctrl); |
6172 | frag = WLAN_GET_SEQ_FRAG(sc); | 6172 | frag = WLAN_GET_SEQ_FRAG(sc); |
6173 | seq = WLAN_GET_SEQ_SEQ(sc); | 6173 | seq = WLAN_GET_SEQ_SEQ(sc); |
6174 | //cosa add 04292008 to record the sequence number | 6174 | //cosa add 04292008 to record the sequence number |
@@ -6827,7 +6827,7 @@ void rtl8192SU_TranslateRxSignalStuff(struct sk_buff *skb, | |||
6827 | tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats); | 6827 | tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats); |
6828 | 6828 | ||
6829 | hdr = (struct ieee80211_hdr_3addr *)tmp_buf; | 6829 | hdr = (struct ieee80211_hdr_3addr *)tmp_buf; |
6830 | fc = le16_to_cpu(hdr->frame_ctl); | 6830 | fc = le16_to_cpu(hdr->frame_control); |
6831 | type = WLAN_FC_GET_TYPE(fc); | 6831 | type = WLAN_FC_GET_TYPE(fc); |
6832 | praddr = hdr->addr1; | 6832 | praddr = hdr->addr1; |
6833 | 6833 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 127a73015760..28ba20fda3e2 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -3,7 +3,7 @@ | |||
3 | /* | 3 | /* |
4 | * 802.11 netlink interface public header | 4 | * 802.11 netlink interface public header |
5 | * | 5 | * |
6 | * Copyright 2006, 2007, 2008 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> | 7 | * Copyright 2008 Michael Wu <flamingice@sourmilk.net> |
8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> | 8 | * Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com> |
9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> | 9 | * Copyright 2008 Michael Buesch <mb@bu3sch.de> |
@@ -299,6 +299,31 @@ | |||
299 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface | 299 | * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface |
300 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. | 300 | * and @NL80211_ATTR_TX_RATES the set of allowed rates. |
301 | * | 301 | * |
302 | * @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames | ||
303 | * (via @NL80211_CMD_ACTION) for processing in userspace. This command | ||
304 | * requires an interface index and a match attribute containing the first | ||
305 | * few bytes of the frame that should match, e.g. a single byte for only | ||
306 | * a category match or four bytes for vendor frames including the OUI. | ||
307 | * The registration cannot be dropped, but is removed automatically | ||
308 | * when the netlink socket is closed. Multiple registrations can be made. | ||
309 | * @NL80211_CMD_ACTION: Action frame TX request and RX notification. This | ||
310 | * command is used both as a request to transmit an Action frame and as an | ||
311 | * event indicating reception of an Action frame that was not processed in | ||
312 | * kernel code, but is for us (i.e., which may need to be processed in a | ||
313 | * user space application). %NL80211_ATTR_FRAME is used to specify the | ||
314 | * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and | ||
315 | * optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on | ||
316 | * which channel the frame is to be transmitted or was received. This | ||
317 | * channel has to be the current channel (remain-on-channel or the | ||
318 | * operational channel). When called, this operation returns a cookie | ||
319 | * (%NL80211_ATTR_COOKIE) that will be included with the TX status event | ||
320 | * pertaining to the TX request. | ||
321 | * @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame | ||
322 | * transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies | ||
323 | * the TX command and %NL80211_ATTR_FRAME includes the contents of the | ||
324 | * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged | ||
325 | * the frame. | ||
326 | * | ||
302 | * @NL80211_CMD_MAX: highest used command number | 327 | * @NL80211_CMD_MAX: highest used command number |
303 | * @__NL80211_CMD_AFTER_LAST: internal use | 328 | * @__NL80211_CMD_AFTER_LAST: internal use |
304 | */ | 329 | */ |
@@ -387,6 +412,13 @@ enum nl80211_commands { | |||
387 | 412 | ||
388 | NL80211_CMD_SET_TX_BITRATE_MASK, | 413 | NL80211_CMD_SET_TX_BITRATE_MASK, |
389 | 414 | ||
415 | NL80211_CMD_REGISTER_ACTION, | ||
416 | NL80211_CMD_ACTION, | ||
417 | NL80211_CMD_ACTION_TX_STATUS, | ||
418 | |||
419 | NL80211_CMD_SET_POWER_SAVE, | ||
420 | NL80211_CMD_GET_POWER_SAVE, | ||
421 | |||
390 | /* add new commands above here */ | 422 | /* add new commands above here */ |
391 | 423 | ||
392 | /* used to define NL80211_CMD_MAX below */ | 424 | /* used to define NL80211_CMD_MAX below */ |
@@ -653,6 +685,12 @@ enum nl80211_commands { | |||
653 | * rates based on negotiated supported rates information. This attribute | 685 | * rates based on negotiated supported rates information. This attribute |
654 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. | 686 | * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. |
655 | * | 687 | * |
688 | * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain | ||
689 | * at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION. | ||
690 | * | ||
691 | * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was | ||
692 | * acknowledged by the recipient. | ||
693 | * | ||
656 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 694 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
657 | * @__NL80211_ATTR_AFTER_LAST: internal use | 695 | * @__NL80211_ATTR_AFTER_LAST: internal use |
658 | */ | 696 | */ |
@@ -798,6 +836,12 @@ enum nl80211_attrs { | |||
798 | 836 | ||
799 | NL80211_ATTR_TX_RATES, | 837 | NL80211_ATTR_TX_RATES, |
800 | 838 | ||
839 | NL80211_ATTR_FRAME_MATCH, | ||
840 | |||
841 | NL80211_ATTR_ACK, | ||
842 | |||
843 | NL80211_ATTR_PS_STATE, | ||
844 | |||
801 | /* add attributes here, update the policy in nl80211.c */ | 845 | /* add attributes here, update the policy in nl80211.c */ |
802 | 846 | ||
803 | __NL80211_ATTR_AFTER_LAST, | 847 | __NL80211_ATTR_AFTER_LAST, |
@@ -1534,4 +1578,9 @@ enum nl80211_band { | |||
1534 | NL80211_BAND_5GHZ, | 1578 | NL80211_BAND_5GHZ, |
1535 | }; | 1579 | }; |
1536 | 1580 | ||
1581 | enum nl80211_ps_state { | ||
1582 | NL80211_PS_DISABLED, | ||
1583 | NL80211_PS_ENABLED, | ||
1584 | }; | ||
1585 | |||
1537 | #endif /* __LINUX_NL80211_H */ | 1586 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5b3569b2a74c..3d134a1fb96b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -3,7 +3,7 @@ | |||
3 | /* | 3 | /* |
4 | * 802.11 device and configuration interface | 4 | * 802.11 device and configuration interface |
5 | * | 5 | * |
6 | * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -998,6 +998,7 @@ struct cfg80211_pmksa { | |||
998 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. | 998 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. |
999 | * This allows the operation to be terminated prior to timeout based on | 999 | * This allows the operation to be terminated prior to timeout based on |
1000 | * the duration value. | 1000 | * the duration value. |
1001 | * @action: Transmit an action frame | ||
1001 | * | 1002 | * |
1002 | * @testmode_cmd: run a test mode command | 1003 | * @testmode_cmd: run a test mode command |
1003 | * | 1004 | * |
@@ -1144,7 +1145,11 @@ struct cfg80211_ops { | |||
1144 | struct net_device *dev, | 1145 | struct net_device *dev, |
1145 | u64 cookie); | 1146 | u64 cookie); |
1146 | 1147 | ||
1147 | /* some temporary stuff to finish wext */ | 1148 | int (*action)(struct wiphy *wiphy, struct net_device *dev, |
1149 | struct ieee80211_channel *chan, | ||
1150 | enum nl80211_channel_type channel_type, | ||
1151 | const u8 *buf, size_t len, u64 *cookie); | ||
1152 | |||
1148 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, | 1153 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, |
1149 | bool enabled, int timeout); | 1154 | bool enabled, int timeout); |
1150 | }; | 1155 | }; |
@@ -1445,6 +1450,8 @@ struct cfg80211_cached_keys; | |||
1445 | * set by driver (if supported) on add_interface BEFORE registering the | 1450 | * set by driver (if supported) on add_interface BEFORE registering the |
1446 | * netdev and may otherwise be used by driver read-only, will be update | 1451 | * netdev and may otherwise be used by driver read-only, will be update |
1447 | * by cfg80211 on change_interface | 1452 | * by cfg80211 on change_interface |
1453 | * @action_registrations: list of registrations for action frames | ||
1454 | * @action_registrations_lock: lock for the list | ||
1448 | */ | 1455 | */ |
1449 | struct wireless_dev { | 1456 | struct wireless_dev { |
1450 | struct wiphy *wiphy; | 1457 | struct wiphy *wiphy; |
@@ -1454,6 +1461,9 @@ struct wireless_dev { | |||
1454 | struct list_head list; | 1461 | struct list_head list; |
1455 | struct net_device *netdev; | 1462 | struct net_device *netdev; |
1456 | 1463 | ||
1464 | struct list_head action_registrations; | ||
1465 | spinlock_t action_registrations_lock; | ||
1466 | |||
1457 | struct mutex mtx; | 1467 | struct mutex mtx; |
1458 | 1468 | ||
1459 | struct work_struct cleanup_work; | 1469 | struct work_struct cleanup_work; |
@@ -1478,6 +1488,9 @@ struct wireless_dev { | |||
1478 | struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; | 1488 | struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; |
1479 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ | 1489 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ |
1480 | 1490 | ||
1491 | bool ps; | ||
1492 | int ps_timeout; | ||
1493 | |||
1481 | #ifdef CONFIG_CFG80211_WEXT | 1494 | #ifdef CONFIG_CFG80211_WEXT |
1482 | /* wext data */ | 1495 | /* wext data */ |
1483 | struct { | 1496 | struct { |
@@ -1489,8 +1502,7 @@ struct wireless_dev { | |||
1489 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 1502 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
1490 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 1503 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
1491 | s8 default_key, default_mgmt_key; | 1504 | s8 default_key, default_mgmt_key; |
1492 | bool ps, prev_bssid_valid; | 1505 | bool prev_bssid_valid; |
1493 | int ps_timeout; | ||
1494 | } wext; | 1506 | } wext; |
1495 | #endif | 1507 | #endif |
1496 | }; | 1508 | }; |
@@ -2291,4 +2303,38 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev, | |||
2291 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | 2303 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, |
2292 | struct station_info *sinfo, gfp_t gfp); | 2304 | struct station_info *sinfo, gfp_t gfp); |
2293 | 2305 | ||
2306 | /** | ||
2307 | * cfg80211_rx_action - notification of received, unprocessed Action frame | ||
2308 | * @dev: network device | ||
2309 | * @freq: Frequency on which the frame was received in MHz | ||
2310 | * @buf: Action frame (header + body) | ||
2311 | * @len: length of the frame data | ||
2312 | * @gfp: context flags | ||
2313 | * Returns %true if a user space application is responsible for rejecting the | ||
2314 | * unrecognized Action frame; %false if no such application is registered | ||
2315 | * (i.e., the driver is responsible for rejecting the unrecognized Action | ||
2316 | * frame) | ||
2317 | * | ||
2318 | * This function is called whenever an Action frame is received for a station | ||
2319 | * mode interface, but is not processed in kernel. | ||
2320 | */ | ||
2321 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | ||
2322 | size_t len, gfp_t gfp); | ||
2323 | |||
2324 | /** | ||
2325 | * cfg80211_action_tx_status - notification of TX status for Action frame | ||
2326 | * @dev: network device | ||
2327 | * @cookie: Cookie returned by cfg80211_ops::action() | ||
2328 | * @buf: Action frame (header + body) | ||
2329 | * @len: length of the frame data | ||
2330 | * @ack: Whether frame was acknowledged | ||
2331 | * @gfp: context flags | ||
2332 | * | ||
2333 | * This function is called whenever an Action frame was requested to be | ||
2334 | * transmitted with cfg80211_ops::action() to report the TX status of the | ||
2335 | * transmission attempt. | ||
2336 | */ | ||
2337 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | ||
2338 | const u8 *buf, size_t len, bool ack, gfp_t gfp); | ||
2339 | |||
2294 | #endif /* __NET_CFG80211_H */ | 2340 | #endif /* __NET_CFG80211_H */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 314e98173166..80eb7cc42ce9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright 2002-2005, Devicescape Software, Inc. | 4 | * Copyright 2002-2005, Devicescape Software, Inc. |
5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 5 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
6 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -264,6 +264,9 @@ struct ieee80211_bss_conf { | |||
264 | * be modified again (no seqno assignment, crypto, etc.) | 264 | * be modified again (no seqno assignment, crypto, etc.) |
265 | * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still | 265 | * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still |
266 | * has a radiotap header at skb->data. | 266 | * has a radiotap header at skb->data. |
267 | * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 | ||
268 | * MLME command (internal to mac80211 to figure out whether to send TX | ||
269 | * status to user space) | ||
267 | */ | 270 | */ |
268 | enum mac80211_tx_control_flags { | 271 | enum mac80211_tx_control_flags { |
269 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 272 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -286,6 +289,7 @@ enum mac80211_tx_control_flags { | |||
286 | IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), | 289 | IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), |
287 | IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), | 290 | IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), |
288 | IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), | 291 | IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20), |
292 | IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), | ||
289 | }; | 293 | }; |
290 | 294 | ||
291 | /** | 295 | /** |
diff --git a/include/pcmcia/device_id.h b/include/pcmcia/device_id.h index c33ea08352b8..63e5b8f6b7dd 100644 --- a/include/pcmcia/device_id.h +++ b/include/pcmcia/device_id.h | |||
@@ -34,6 +34,11 @@ | |||
34 | .prod_id = { NULL, (v2), NULL, NULL }, \ | 34 | .prod_id = { NULL, (v2), NULL, NULL }, \ |
35 | .prod_id_hash = { 0, (vh2), 0, 0 }, } | 35 | .prod_id_hash = { 0, (vh2), 0, 0 }, } |
36 | 36 | ||
37 | #define PCMCIA_DEVICE_PROD_ID3(v3, vh3) { \ | ||
38 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID3, \ | ||
39 | .prod_id = { NULL, NULL, (v3), NULL }, \ | ||
40 | .prod_id_hash = { 0, 0, (vh3), 0 }, } | ||
41 | |||
37 | #define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ | 42 | #define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \ |
38 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ | 43 | .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ |
39 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ | 44 | PCMCIA_DEV_ID_MATCH_PROD_ID2, \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e1731b7c2523..b7116ef84a3b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * mac80211 configuration hooks for cfg80211 | 2 | * mac80211 configuration hooks for cfg80211 |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
5 | * | 5 | * |
6 | * This file is GPLv2 as found in COPYING. | 6 | * This file is GPLv2 as found in COPYING. |
7 | */ | 7 | */ |
@@ -1448,6 +1448,15 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1448 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1448 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev, | ||
1452 | struct ieee80211_channel *chan, | ||
1453 | enum nl80211_channel_type channel_type, | ||
1454 | const u8 *buf, size_t len, u64 *cookie) | ||
1455 | { | ||
1456 | return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan, | ||
1457 | channel_type, buf, len, cookie); | ||
1458 | } | ||
1459 | |||
1451 | struct cfg80211_ops mac80211_config_ops = { | 1460 | struct cfg80211_ops mac80211_config_ops = { |
1452 | .add_virtual_intf = ieee80211_add_iface, | 1461 | .add_virtual_intf = ieee80211_add_iface, |
1453 | .del_virtual_intf = ieee80211_del_iface, | 1462 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1496,4 +1505,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1496 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1505 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1497 | .remain_on_channel = ieee80211_remain_on_channel, | 1506 | .remain_on_channel = ieee80211_remain_on_channel, |
1498 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1507 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1508 | .action = ieee80211_action, | ||
1499 | }; | 1509 | }; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 9dd98b674cbc..241533e1bc03 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -966,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
966 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 966 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
967 | struct cfg80211_disassoc_request *req, | 967 | struct cfg80211_disassoc_request *req, |
968 | void *cookie); | 968 | void *cookie); |
969 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
970 | struct ieee80211_channel *chan, | ||
971 | enum nl80211_channel_type channel_type, | ||
972 | const u8 *buf, size_t len, u64 *cookie); | ||
969 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | 973 | ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, |
970 | struct sk_buff *skb); | 974 | struct sk_buff *skb); |
971 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 975 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09fff4662e80..0793d7a8d743 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1031,7 +1031,7 @@ static int netdev_notify(struct notifier_block *nb, | |||
1031 | 1031 | ||
1032 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1032 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1033 | 1033 | ||
1034 | memcpy(sdata->name, sdata->name, IFNAMSIZ); | 1034 | memcpy(sdata->name, dev->name, IFNAMSIZ); |
1035 | 1035 | ||
1036 | ieee80211_debugfs_rename_netdev(sdata); | 1036 | ieee80211_debugfs_rename_netdev(sdata); |
1037 | return 0; | 1037 | return 0; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bfc4a5070013..41812a15eea0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2084,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2084 | 2084 | ||
2085 | return 0; | 2085 | return 0; |
2086 | } | 2086 | } |
2087 | |||
2088 | int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata, | ||
2089 | struct ieee80211_channel *chan, | ||
2090 | enum nl80211_channel_type channel_type, | ||
2091 | const u8 *buf, size_t len, u64 *cookie) | ||
2092 | { | ||
2093 | struct ieee80211_local *local = sdata->local; | ||
2094 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2095 | struct sk_buff *skb; | ||
2096 | |||
2097 | /* Check that we are on the requested channel for transmission */ | ||
2098 | if ((chan != local->tmp_channel || | ||
2099 | channel_type != local->tmp_channel_type) && | ||
2100 | (chan != local->oper_channel || | ||
2101 | channel_type != local->oper_channel_type)) | ||
2102 | return -EBUSY; | ||
2103 | |||
2104 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + len); | ||
2105 | if (!skb) | ||
2106 | return -ENOMEM; | ||
2107 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
2108 | |||
2109 | memcpy(skb_put(skb, len), buf, len); | ||
2110 | |||
2111 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | ||
2112 | IEEE80211_SKB_CB(skb)->flags |= | ||
2113 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2114 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX | | ||
2115 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
2116 | skb->dev = sdata->dev; | ||
2117 | ieee80211_tx_skb(sdata, skb); | ||
2118 | |||
2119 | *cookie = (unsigned long) skb; | ||
2120 | return 0; | ||
2121 | } | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c9755f3d986c..b5c48de81d8b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -1397,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1397 | ieee80211_is_data(fc) && | 1397 | ieee80211_is_data(fc) && |
1398 | (rx->key || rx->sdata->drop_unencrypted))) | 1398 | (rx->key || rx->sdata->drop_unencrypted))) |
1399 | return -EACCES; | 1399 | return -EACCES; |
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static int | ||
1405 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | ||
1406 | { | ||
1407 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
1408 | __le16 fc = hdr->frame_control; | ||
1409 | int res; | ||
1410 | |||
1411 | res = ieee80211_drop_unencrypted(rx, fc); | ||
1412 | if (unlikely(res)) | ||
1413 | return res; | ||
1414 | |||
1400 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1415 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1401 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1416 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && |
1402 | rx->key)) | 1417 | rx->key)) |
@@ -1855,23 +1870,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1855 | struct ieee80211_local *local = rx->local; | 1870 | struct ieee80211_local *local = rx->local; |
1856 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1871 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1857 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1872 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1873 | struct sk_buff *nskb; | ||
1874 | struct ieee80211_rx_status *status; | ||
1858 | int len = rx->skb->len; | 1875 | int len = rx->skb->len; |
1859 | 1876 | ||
1860 | if (!ieee80211_is_action(mgmt->frame_control)) | 1877 | if (!ieee80211_is_action(mgmt->frame_control)) |
1861 | return RX_CONTINUE; | 1878 | return RX_CONTINUE; |
1862 | 1879 | ||
1863 | if (!rx->sta) | 1880 | /* drop too small frames */ |
1864 | return RX_DROP_MONITOR; | 1881 | if (len < IEEE80211_MIN_ACTION_SIZE) |
1882 | return RX_DROP_UNUSABLE; | ||
1865 | 1883 | ||
1866 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1884 | if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) |
1867 | return RX_DROP_MONITOR; | 1885 | return RX_DROP_UNUSABLE; |
1868 | 1886 | ||
1869 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 1887 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1870 | return RX_DROP_MONITOR; | 1888 | return RX_DROP_UNUSABLE; |
1871 | 1889 | ||
1872 | /* all categories we currently handle have action_code */ | 1890 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
1873 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | 1891 | return RX_DROP_UNUSABLE; |
1874 | return RX_DROP_MONITOR; | ||
1875 | 1892 | ||
1876 | switch (mgmt->u.action.category) { | 1893 | switch (mgmt->u.action.category) { |
1877 | case WLAN_CATEGORY_BACK: | 1894 | case WLAN_CATEGORY_BACK: |
@@ -1884,7 +1901,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1884 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1901 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1885 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1902 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1886 | sdata->vif.type != NL80211_IFTYPE_AP) | 1903 | sdata->vif.type != NL80211_IFTYPE_AP) |
1887 | return RX_DROP_MONITOR; | 1904 | break; |
1905 | |||
1906 | /* verify action_code is present */ | ||
1907 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1908 | break; | ||
1888 | 1909 | ||
1889 | switch (mgmt->u.action.u.addba_req.action_code) { | 1910 | switch (mgmt->u.action.u.addba_req.action_code) { |
1890 | case WLAN_ACTION_ADDBA_REQ: | 1911 | case WLAN_ACTION_ADDBA_REQ: |
@@ -1892,45 +1913,49 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1892 | sizeof(mgmt->u.action.u.addba_req))) | 1913 | sizeof(mgmt->u.action.u.addba_req))) |
1893 | return RX_DROP_MONITOR; | 1914 | return RX_DROP_MONITOR; |
1894 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | 1915 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); |
1895 | break; | 1916 | goto handled; |
1896 | case WLAN_ACTION_ADDBA_RESP: | 1917 | case WLAN_ACTION_ADDBA_RESP: |
1897 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1918 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1898 | sizeof(mgmt->u.action.u.addba_resp))) | 1919 | sizeof(mgmt->u.action.u.addba_resp))) |
1899 | return RX_DROP_MONITOR; | 1920 | break; |
1900 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | 1921 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); |
1901 | break; | 1922 | goto handled; |
1902 | case WLAN_ACTION_DELBA: | 1923 | case WLAN_ACTION_DELBA: |
1903 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1924 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1904 | sizeof(mgmt->u.action.u.delba))) | 1925 | sizeof(mgmt->u.action.u.delba))) |
1905 | return RX_DROP_MONITOR; | 1926 | break; |
1906 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | 1927 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); |
1907 | break; | 1928 | goto handled; |
1908 | } | 1929 | } |
1909 | break; | 1930 | break; |
1910 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 1931 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
1911 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 1932 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) |
1912 | return RX_DROP_MONITOR; | 1933 | break; |
1913 | 1934 | ||
1914 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1935 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1915 | return RX_DROP_MONITOR; | 1936 | break; |
1937 | |||
1938 | /* verify action_code is present */ | ||
1939 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1940 | break; | ||
1916 | 1941 | ||
1917 | switch (mgmt->u.action.u.measurement.action_code) { | 1942 | switch (mgmt->u.action.u.measurement.action_code) { |
1918 | case WLAN_ACTION_SPCT_MSR_REQ: | 1943 | case WLAN_ACTION_SPCT_MSR_REQ: |
1919 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1944 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1920 | sizeof(mgmt->u.action.u.measurement))) | 1945 | sizeof(mgmt->u.action.u.measurement))) |
1921 | return RX_DROP_MONITOR; | 1946 | break; |
1922 | ieee80211_process_measurement_req(sdata, mgmt, len); | 1947 | ieee80211_process_measurement_req(sdata, mgmt, len); |
1923 | break; | 1948 | goto handled; |
1924 | case WLAN_ACTION_SPCT_CHL_SWITCH: | 1949 | case WLAN_ACTION_SPCT_CHL_SWITCH: |
1925 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1950 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1926 | sizeof(mgmt->u.action.u.chan_switch))) | 1951 | sizeof(mgmt->u.action.u.chan_switch))) |
1927 | return RX_DROP_MONITOR; | 1952 | break; |
1928 | 1953 | ||
1929 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1954 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1930 | return RX_DROP_MONITOR; | 1955 | break; |
1931 | 1956 | ||
1932 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) | 1957 | if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) |
1933 | return RX_DROP_MONITOR; | 1958 | break; |
1934 | 1959 | ||
1935 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); | 1960 | return ieee80211_sta_rx_mgmt(sdata, rx->skb); |
1936 | } | 1961 | } |
@@ -1938,30 +1963,64 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1938 | case WLAN_CATEGORY_SA_QUERY: | 1963 | case WLAN_CATEGORY_SA_QUERY: |
1939 | if (len < (IEEE80211_MIN_ACTION_SIZE + | 1964 | if (len < (IEEE80211_MIN_ACTION_SIZE + |
1940 | sizeof(mgmt->u.action.u.sa_query))) | 1965 | sizeof(mgmt->u.action.u.sa_query))) |
1941 | return RX_DROP_MONITOR; | 1966 | break; |
1967 | |||
1942 | switch (mgmt->u.action.u.sa_query.action) { | 1968 | switch (mgmt->u.action.u.sa_query.action) { |
1943 | case WLAN_ACTION_SA_QUERY_REQUEST: | 1969 | case WLAN_ACTION_SA_QUERY_REQUEST: |
1944 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1970 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1945 | return RX_DROP_MONITOR; | 1971 | break; |
1946 | ieee80211_process_sa_query_req(sdata, mgmt, len); | 1972 | ieee80211_process_sa_query_req(sdata, mgmt, len); |
1947 | break; | 1973 | goto handled; |
1948 | case WLAN_ACTION_SA_QUERY_RESPONSE: | ||
1949 | /* | ||
1950 | * SA Query response is currently only used in AP mode | ||
1951 | * and it is processed in user space. | ||
1952 | */ | ||
1953 | return RX_CONTINUE; | ||
1954 | } | 1974 | } |
1955 | break; | 1975 | break; |
1956 | default: | 1976 | } |
1957 | /* do not process rejected action frames */ | ||
1958 | if (mgmt->u.action.category & 0x80) | ||
1959 | return RX_DROP_MONITOR; | ||
1960 | 1977 | ||
1961 | return RX_CONTINUE; | 1978 | /* |
1979 | * For AP mode, hostapd is responsible for handling any action | ||
1980 | * frames that we didn't handle, including returning unknown | ||
1981 | * ones. For all other modes we will return them to the sender, | ||
1982 | * setting the 0x80 bit in the action category, as required by | ||
1983 | * 802.11-2007 7.3.1.11. | ||
1984 | */ | ||
1985 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
1986 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1987 | return RX_DROP_MONITOR; | ||
1988 | |||
1989 | /* | ||
1990 | * Getting here means the kernel doesn't know how to handle | ||
1991 | * it, but maybe userspace does ... include returned frames | ||
1992 | * so userspace can register for those to know whether ones | ||
1993 | * it transmitted were processed or returned. | ||
1994 | */ | ||
1995 | status = IEEE80211_SKB_RXCB(rx->skb); | ||
1996 | |||
1997 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1998 | cfg80211_rx_action(rx->sdata->dev, status->freq, | ||
1999 | rx->skb->data, rx->skb->len, | ||
2000 | GFP_ATOMIC)) | ||
2001 | goto handled; | ||
2002 | |||
2003 | /* do not return rejected action frames */ | ||
2004 | if (mgmt->u.action.category & 0x80) | ||
2005 | return RX_DROP_UNUSABLE; | ||
2006 | |||
2007 | nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, | ||
2008 | GFP_ATOMIC); | ||
2009 | if (nskb) { | ||
2010 | struct ieee80211_mgmt *mgmt = (void *)nskb->data; | ||
2011 | |||
2012 | mgmt->u.action.category |= 0x80; | ||
2013 | memcpy(mgmt->da, mgmt->sa, ETH_ALEN); | ||
2014 | memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN); | ||
2015 | |||
2016 | memset(nskb->cb, 0, sizeof(nskb->cb)); | ||
2017 | |||
2018 | ieee80211_tx_skb(rx->sdata, nskb); | ||
1962 | } | 2019 | } |
1963 | 2020 | ||
1964 | rx->sta->rx_packets++; | 2021 | handled: |
2022 | if (rx->sta) | ||
2023 | rx->sta->rx_packets++; | ||
1965 | dev_kfree_skb(rx->skb); | 2024 | dev_kfree_skb(rx->skb); |
1966 | return RX_QUEUED; | 2025 | return RX_QUEUED; |
1967 | } | 2026 | } |
@@ -1970,14 +2029,13 @@ static ieee80211_rx_result debug_noinline | |||
1970 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 2029 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1971 | { | 2030 | { |
1972 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 2031 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1973 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1974 | ieee80211_rx_result rxs; | 2032 | ieee80211_rx_result rxs; |
1975 | 2033 | ||
1976 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 2034 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1977 | return RX_DROP_MONITOR; | 2035 | return RX_DROP_MONITOR; |
1978 | 2036 | ||
1979 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 2037 | if (ieee80211_drop_unencrypted_mgmt(rx)) |
1980 | return RX_DROP_MONITOR; | 2038 | return RX_DROP_UNUSABLE; |
1981 | 2039 | ||
1982 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | 2040 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); |
1983 | if (rxs != RX_CONTINUE) | 2041 | if (rxs != RX_CONTINUE) |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ded98730c111..56d5b9a6ec5b 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> |
5 | * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> | 5 | * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -288,6 +288,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
288 | msecs_to_jiffies(10)); | 288 | msecs_to_jiffies(10)); |
289 | } | 289 | } |
290 | 290 | ||
291 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | ||
292 | cfg80211_action_tx_status( | ||
293 | skb->dev, (unsigned long) skb, skb->data, skb->len, | ||
294 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | ||
295 | |||
291 | /* this was a transmitted frame, but now we want to reuse it */ | 296 | /* this was a transmitted frame, but now we want to reuse it */ |
292 | skb_orphan(skb); | 297 | skb_orphan(skb); |
293 | 298 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index 71b6b3a9cf1f..7fdb9409ad2a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -677,6 +677,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
677 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | 677 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); |
678 | INIT_LIST_HEAD(&wdev->event_list); | 678 | INIT_LIST_HEAD(&wdev->event_list); |
679 | spin_lock_init(&wdev->event_lock); | 679 | spin_lock_init(&wdev->event_lock); |
680 | INIT_LIST_HEAD(&wdev->action_registrations); | ||
681 | spin_lock_init(&wdev->action_registrations_lock); | ||
682 | |||
680 | mutex_lock(&rdev->devlist_mtx); | 683 | mutex_lock(&rdev->devlist_mtx); |
681 | list_add_rcu(&wdev->list, &rdev->netdev_list); | 684 | list_add_rcu(&wdev->list, &rdev->netdev_list); |
682 | rdev->devlist_generation++; | 685 | rdev->devlist_generation++; |
@@ -695,19 +698,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
695 | wdev->wext.default_key = -1; | 698 | wdev->wext.default_key = -1; |
696 | wdev->wext.default_mgmt_key = -1; | 699 | wdev->wext.default_mgmt_key = -1; |
697 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 700 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
701 | #endif | ||
702 | |||
698 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) | 703 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
699 | wdev->wext.ps = true; | 704 | wdev->ps = true; |
700 | else | 705 | else |
701 | wdev->wext.ps = false; | 706 | wdev->ps = false; |
702 | wdev->wext.ps_timeout = 100; | 707 | wdev->ps_timeout = 100; |
703 | if (rdev->ops->set_power_mgmt) | 708 | if (rdev->ops->set_power_mgmt) |
704 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | 709 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, |
705 | wdev->wext.ps, | 710 | wdev->ps, |
706 | wdev->wext.ps_timeout)) { | 711 | wdev->ps_timeout)) { |
707 | /* assume this means it's off */ | 712 | /* assume this means it's off */ |
708 | wdev->wext.ps = false; | 713 | wdev->ps = false; |
709 | } | 714 | } |
710 | #endif | 715 | |
711 | if (!dev->ethtool_ops) | 716 | if (!dev->ethtool_ops) |
712 | dev->ethtool_ops = &cfg80211_ethtool_ops; | 717 | dev->ethtool_ops = &cfg80211_ethtool_ops; |
713 | 718 | ||
@@ -792,6 +797,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
792 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 797 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
793 | list_del_rcu(&wdev->list); | 798 | list_del_rcu(&wdev->list); |
794 | rdev->devlist_generation++; | 799 | rdev->devlist_generation++; |
800 | cfg80211_mlme_purge_actions(wdev); | ||
795 | #ifdef CONFIG_CFG80211_WEXT | 801 | #ifdef CONFIG_CFG80211_WEXT |
796 | kfree(wdev->wext.keys); | 802 | kfree(wdev->wext.keys); |
797 | #endif | 803 | #endif |
diff --git a/net/wireless/core.h b/net/wireless/core.h index c326a667022a..d52da913145a 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -329,6 +329,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
329 | const u8 *resp_ie, size_t resp_ie_len, | 329 | const u8 *resp_ie, size_t resp_ie_len, |
330 | u16 status, bool wextev, | 330 | u16 status, bool wextev, |
331 | struct cfg80211_bss *bss); | 331 | struct cfg80211_bss *bss); |
332 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | ||
333 | const u8 *match_data, int match_len); | ||
334 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid); | ||
335 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev); | ||
336 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | ||
337 | struct net_device *dev, | ||
338 | struct ieee80211_channel *chan, | ||
339 | enum nl80211_channel_type channel_type, | ||
340 | const u8 *buf, size_t len, u64 *cookie); | ||
332 | 341 | ||
333 | /* SME */ | 342 | /* SME */ |
334 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, | 343 | int __cfg80211_connect(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 94d151f6f73e..62bc8855e123 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -728,3 +728,169 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | |||
728 | nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); | 728 | nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); |
729 | } | 729 | } |
730 | EXPORT_SYMBOL(cfg80211_new_sta); | 730 | EXPORT_SYMBOL(cfg80211_new_sta); |
731 | |||
732 | struct cfg80211_action_registration { | ||
733 | struct list_head list; | ||
734 | |||
735 | u32 nlpid; | ||
736 | |||
737 | int match_len; | ||
738 | |||
739 | u8 match[]; | ||
740 | }; | ||
741 | |||
742 | int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid, | ||
743 | const u8 *match_data, int match_len) | ||
744 | { | ||
745 | struct cfg80211_action_registration *reg, *nreg; | ||
746 | int err = 0; | ||
747 | |||
748 | nreg = kzalloc(sizeof(*reg) + match_len, GFP_KERNEL); | ||
749 | if (!nreg) | ||
750 | return -ENOMEM; | ||
751 | |||
752 | spin_lock_bh(&wdev->action_registrations_lock); | ||
753 | |||
754 | list_for_each_entry(reg, &wdev->action_registrations, list) { | ||
755 | int mlen = min(match_len, reg->match_len); | ||
756 | |||
757 | if (memcmp(reg->match, match_data, mlen) == 0) { | ||
758 | err = -EALREADY; | ||
759 | break; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | if (err) { | ||
764 | kfree(nreg); | ||
765 | goto out; | ||
766 | } | ||
767 | |||
768 | memcpy(nreg->match, match_data, match_len); | ||
769 | nreg->match_len = match_len; | ||
770 | nreg->nlpid = snd_pid; | ||
771 | list_add(&nreg->list, &wdev->action_registrations); | ||
772 | |||
773 | out: | ||
774 | spin_unlock_bh(&wdev->action_registrations_lock); | ||
775 | return err; | ||
776 | } | ||
777 | |||
778 | void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid) | ||
779 | { | ||
780 | struct cfg80211_action_registration *reg, *tmp; | ||
781 | |||
782 | spin_lock_bh(&wdev->action_registrations_lock); | ||
783 | |||
784 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | ||
785 | if (reg->nlpid == nlpid) { | ||
786 | list_del(®->list); | ||
787 | kfree(reg); | ||
788 | } | ||
789 | } | ||
790 | |||
791 | spin_unlock_bh(&wdev->action_registrations_lock); | ||
792 | } | ||
793 | |||
794 | void cfg80211_mlme_purge_actions(struct wireless_dev *wdev) | ||
795 | { | ||
796 | struct cfg80211_action_registration *reg, *tmp; | ||
797 | |||
798 | spin_lock_bh(&wdev->action_registrations_lock); | ||
799 | |||
800 | list_for_each_entry_safe(reg, tmp, &wdev->action_registrations, list) { | ||
801 | list_del(®->list); | ||
802 | kfree(reg); | ||
803 | } | ||
804 | |||
805 | spin_unlock_bh(&wdev->action_registrations_lock); | ||
806 | } | ||
807 | |||
808 | int cfg80211_mlme_action(struct cfg80211_registered_device *rdev, | ||
809 | struct net_device *dev, | ||
810 | struct ieee80211_channel *chan, | ||
811 | enum nl80211_channel_type channel_type, | ||
812 | const u8 *buf, size_t len, u64 *cookie) | ||
813 | { | ||
814 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
815 | const struct ieee80211_mgmt *mgmt; | ||
816 | |||
817 | if (rdev->ops->action == NULL) | ||
818 | return -EOPNOTSUPP; | ||
819 | if (len < 24 + 1) | ||
820 | return -EINVAL; | ||
821 | |||
822 | mgmt = (const struct ieee80211_mgmt *) buf; | ||
823 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
824 | return -EINVAL; | ||
825 | if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC) { | ||
826 | /* Verify that we are associated with the destination AP */ | ||
827 | if (!wdev->current_bss || | ||
828 | memcmp(wdev->current_bss->pub.bssid, mgmt->bssid, | ||
829 | ETH_ALEN) != 0 || | ||
830 | memcmp(wdev->current_bss->pub.bssid, mgmt->da, | ||
831 | ETH_ALEN) != 0) | ||
832 | return -ENOTCONN; | ||
833 | } | ||
834 | |||
835 | if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) | ||
836 | return -EINVAL; | ||
837 | |||
838 | /* Transmit the Action frame as requested by user space */ | ||
839 | return rdev->ops->action(&rdev->wiphy, dev, chan, channel_type, | ||
840 | buf, len, cookie); | ||
841 | } | ||
842 | |||
843 | bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf, | ||
844 | size_t len, gfp_t gfp) | ||
845 | { | ||
846 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
847 | struct wiphy *wiphy = wdev->wiphy; | ||
848 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
849 | struct cfg80211_action_registration *reg; | ||
850 | const u8 *action_data; | ||
851 | int action_data_len; | ||
852 | bool result = false; | ||
853 | |||
854 | /* frame length - min size excluding category */ | ||
855 | action_data_len = len - (IEEE80211_MIN_ACTION_SIZE - 1); | ||
856 | |||
857 | /* action data starts with category */ | ||
858 | action_data = buf + IEEE80211_MIN_ACTION_SIZE - 1; | ||
859 | |||
860 | spin_lock_bh(&wdev->action_registrations_lock); | ||
861 | |||
862 | list_for_each_entry(reg, &wdev->action_registrations, list) { | ||
863 | if (reg->match_len > action_data_len) | ||
864 | continue; | ||
865 | |||
866 | if (memcmp(reg->match, action_data, reg->match_len)) | ||
867 | continue; | ||
868 | |||
869 | /* found match! */ | ||
870 | |||
871 | /* Indicate the received Action frame to user space */ | ||
872 | if (nl80211_send_action(rdev, dev, reg->nlpid, freq, | ||
873 | buf, len, gfp)) | ||
874 | continue; | ||
875 | |||
876 | result = true; | ||
877 | break; | ||
878 | } | ||
879 | |||
880 | spin_unlock_bh(&wdev->action_registrations_lock); | ||
881 | |||
882 | return result; | ||
883 | } | ||
884 | EXPORT_SYMBOL(cfg80211_rx_action); | ||
885 | |||
886 | void cfg80211_action_tx_status(struct net_device *dev, u64 cookie, | ||
887 | const u8 *buf, size_t len, bool ack, gfp_t gfp) | ||
888 | { | ||
889 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
890 | struct wiphy *wiphy = wdev->wiphy; | ||
891 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
892 | |||
893 | /* Indicate TX status of the Action frame to user space */ | ||
894 | nl80211_send_action_tx_status(rdev, dev, cookie, buf, len, ack, gfp); | ||
895 | } | ||
896 | EXPORT_SYMBOL(cfg80211_action_tx_status); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a001ea32cb7d..e447db04cf76 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the new netlink-based wireless configuration interface. | 2 | * This is the new netlink-based wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -145,6 +145,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
145 | [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, | 145 | [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, |
146 | [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, | 146 | [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, |
147 | [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, | 147 | [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED }, |
148 | [NL80211_ATTR_FRAME] = { .type = NLA_BINARY, | ||
149 | .len = IEEE80211_MAX_DATA_LEN }, | ||
150 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, | ||
151 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, | ||
148 | }; | 152 | }; |
149 | 153 | ||
150 | /* policy for the attributes */ | 154 | /* policy for the attributes */ |
@@ -576,6 +580,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
576 | CMD(flush_pmksa, FLUSH_PMKSA); | 580 | CMD(flush_pmksa, FLUSH_PMKSA); |
577 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 581 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
578 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 582 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
583 | CMD(action, ACTION); | ||
579 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 584 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
580 | i++; | 585 | i++; |
581 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 586 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -2009,6 +2014,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2009 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) | 2014 | if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) |
2010 | return -EINVAL; | 2015 | return -EINVAL; |
2011 | 2016 | ||
2017 | if (!info->attrs[NL80211_ATTR_STA_AID]) | ||
2018 | return -EINVAL; | ||
2019 | |||
2012 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 2020 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
2013 | params.supported_rates = | 2021 | params.supported_rates = |
2014 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); | 2022 | nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); |
@@ -2017,11 +2025,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2017 | params.listen_interval = | 2025 | params.listen_interval = |
2018 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 2026 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
2019 | 2027 | ||
2020 | if (info->attrs[NL80211_ATTR_STA_AID]) { | 2028 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
2021 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 2029 | if (!params.aid || params.aid > IEEE80211_MAX_AID) |
2022 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | 2030 | return -EINVAL; |
2023 | return -EINVAL; | ||
2024 | } | ||
2025 | 2031 | ||
2026 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 2032 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
2027 | params.ht_capa = | 2033 | params.ht_capa = |
@@ -2036,6 +2042,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2036 | if (err) | 2042 | if (err) |
2037 | goto out_rtnl; | 2043 | goto out_rtnl; |
2038 | 2044 | ||
2045 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
2046 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | ||
2047 | err = -EINVAL; | ||
2048 | goto out; | ||
2049 | } | ||
2050 | |||
2039 | err = get_vlan(info, rdev, ¶ms.vlan); | 2051 | err = get_vlan(info, rdev, ¶ms.vlan); |
2040 | if (err) | 2052 | if (err) |
2041 | goto out; | 2053 | goto out; |
@@ -2043,35 +2055,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
2043 | /* validate settings */ | 2055 | /* validate settings */ |
2044 | err = 0; | 2056 | err = 0; |
2045 | 2057 | ||
2046 | switch (dev->ieee80211_ptr->iftype) { | ||
2047 | case NL80211_IFTYPE_AP: | ||
2048 | case NL80211_IFTYPE_AP_VLAN: | ||
2049 | /* all ok but must have AID */ | ||
2050 | if (!params.aid) | ||
2051 | err = -EINVAL; | ||
2052 | break; | ||
2053 | case NL80211_IFTYPE_MESH_POINT: | ||
2054 | /* disallow things mesh doesn't support */ | ||
2055 | if (params.vlan) | ||
2056 | err = -EINVAL; | ||
2057 | if (params.aid) | ||
2058 | err = -EINVAL; | ||
2059 | if (params.ht_capa) | ||
2060 | err = -EINVAL; | ||
2061 | if (params.listen_interval >= 0) | ||
2062 | err = -EINVAL; | ||
2063 | if (params.supported_rates) | ||
2064 | err = -EINVAL; | ||
2065 | if (params.sta_flags_mask) | ||
2066 | err = -EINVAL; | ||
2067 | break; | ||
2068 | default: | ||
2069 | err = -EINVAL; | ||
2070 | } | ||
2071 | |||
2072 | if (err) | ||
2073 | goto out; | ||
2074 | |||
2075 | if (!rdev->ops->add_station) { | 2058 | if (!rdev->ops->add_station) { |
2076 | err = -EOPNOTSUPP; | 2059 | err = -EOPNOTSUPP; |
2077 | goto out; | 2060 | goto out; |
@@ -2112,8 +2095,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2112 | goto out_rtnl; | 2095 | goto out_rtnl; |
2113 | 2096 | ||
2114 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2097 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2115 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | 2098 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { |
2116 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2117 | err = -EINVAL; | 2099 | err = -EINVAL; |
2118 | goto out; | 2100 | goto out; |
2119 | } | 2101 | } |
@@ -4545,6 +4527,257 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
4545 | return err; | 4527 | return err; |
4546 | } | 4528 | } |
4547 | 4529 | ||
4530 | static int nl80211_register_action(struct sk_buff *skb, struct genl_info *info) | ||
4531 | { | ||
4532 | struct cfg80211_registered_device *rdev; | ||
4533 | struct net_device *dev; | ||
4534 | int err; | ||
4535 | |||
4536 | if (!info->attrs[NL80211_ATTR_FRAME_MATCH]) | ||
4537 | return -EINVAL; | ||
4538 | |||
4539 | if (nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]) < 1) | ||
4540 | return -EINVAL; | ||
4541 | |||
4542 | rtnl_lock(); | ||
4543 | |||
4544 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4545 | if (err) | ||
4546 | goto unlock_rtnl; | ||
4547 | |||
4548 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | ||
4549 | err = -EOPNOTSUPP; | ||
4550 | goto out; | ||
4551 | } | ||
4552 | |||
4553 | /* not much point in registering if we can't reply */ | ||
4554 | if (!rdev->ops->action) { | ||
4555 | err = -EOPNOTSUPP; | ||
4556 | goto out; | ||
4557 | } | ||
4558 | |||
4559 | err = cfg80211_mlme_register_action(dev->ieee80211_ptr, info->snd_pid, | ||
4560 | nla_data(info->attrs[NL80211_ATTR_FRAME_MATCH]), | ||
4561 | nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH])); | ||
4562 | out: | ||
4563 | cfg80211_unlock_rdev(rdev); | ||
4564 | dev_put(dev); | ||
4565 | unlock_rtnl: | ||
4566 | rtnl_unlock(); | ||
4567 | return err; | ||
4568 | } | ||
4569 | |||
4570 | static int nl80211_action(struct sk_buff *skb, struct genl_info *info) | ||
4571 | { | ||
4572 | struct cfg80211_registered_device *rdev; | ||
4573 | struct net_device *dev; | ||
4574 | struct ieee80211_channel *chan; | ||
4575 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
4576 | u32 freq; | ||
4577 | int err; | ||
4578 | void *hdr; | ||
4579 | u64 cookie; | ||
4580 | struct sk_buff *msg; | ||
4581 | |||
4582 | if (!info->attrs[NL80211_ATTR_FRAME] || | ||
4583 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | ||
4584 | return -EINVAL; | ||
4585 | |||
4586 | rtnl_lock(); | ||
4587 | |||
4588 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4589 | if (err) | ||
4590 | goto unlock_rtnl; | ||
4591 | |||
4592 | if (!rdev->ops->action) { | ||
4593 | err = -EOPNOTSUPP; | ||
4594 | goto out; | ||
4595 | } | ||
4596 | |||
4597 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) { | ||
4598 | err = -EOPNOTSUPP; | ||
4599 | goto out; | ||
4600 | } | ||
4601 | |||
4602 | if (!netif_running(dev)) { | ||
4603 | err = -ENETDOWN; | ||
4604 | goto out; | ||
4605 | } | ||
4606 | |||
4607 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
4608 | channel_type = nla_get_u32( | ||
4609 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
4610 | if (channel_type != NL80211_CHAN_NO_HT && | ||
4611 | channel_type != NL80211_CHAN_HT20 && | ||
4612 | channel_type != NL80211_CHAN_HT40PLUS && | ||
4613 | channel_type != NL80211_CHAN_HT40MINUS) | ||
4614 | err = -EINVAL; | ||
4615 | goto out; | ||
4616 | } | ||
4617 | |||
4618 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
4619 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
4620 | if (chan == NULL) { | ||
4621 | err = -EINVAL; | ||
4622 | goto out; | ||
4623 | } | ||
4624 | |||
4625 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
4626 | if (!msg) { | ||
4627 | err = -ENOMEM; | ||
4628 | goto out; | ||
4629 | } | ||
4630 | |||
4631 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
4632 | NL80211_CMD_ACTION); | ||
4633 | |||
4634 | if (IS_ERR(hdr)) { | ||
4635 | err = PTR_ERR(hdr); | ||
4636 | goto free_msg; | ||
4637 | } | ||
4638 | err = cfg80211_mlme_action(rdev, dev, chan, channel_type, | ||
4639 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | ||
4640 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | ||
4641 | &cookie); | ||
4642 | if (err) | ||
4643 | goto free_msg; | ||
4644 | |||
4645 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | ||
4646 | |||
4647 | genlmsg_end(msg, hdr); | ||
4648 | err = genlmsg_reply(msg, info); | ||
4649 | goto out; | ||
4650 | |||
4651 | nla_put_failure: | ||
4652 | err = -ENOBUFS; | ||
4653 | free_msg: | ||
4654 | nlmsg_free(msg); | ||
4655 | out: | ||
4656 | cfg80211_unlock_rdev(rdev); | ||
4657 | dev_put(dev); | ||
4658 | unlock_rtnl: | ||
4659 | rtnl_unlock(); | ||
4660 | return err; | ||
4661 | } | ||
4662 | |||
4663 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) | ||
4664 | { | ||
4665 | struct cfg80211_registered_device *rdev; | ||
4666 | struct wireless_dev *wdev; | ||
4667 | struct net_device *dev; | ||
4668 | u8 ps_state; | ||
4669 | bool state; | ||
4670 | int err; | ||
4671 | |||
4672 | if (!info->attrs[NL80211_ATTR_PS_STATE]) { | ||
4673 | err = -EINVAL; | ||
4674 | goto out; | ||
4675 | } | ||
4676 | |||
4677 | ps_state = nla_get_u32(info->attrs[NL80211_ATTR_PS_STATE]); | ||
4678 | |||
4679 | if (ps_state != NL80211_PS_DISABLED && ps_state != NL80211_PS_ENABLED) { | ||
4680 | err = -EINVAL; | ||
4681 | goto out; | ||
4682 | } | ||
4683 | |||
4684 | rtnl_lock(); | ||
4685 | |||
4686 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4687 | if (err) | ||
4688 | goto unlock_rdev; | ||
4689 | |||
4690 | wdev = dev->ieee80211_ptr; | ||
4691 | |||
4692 | if (!rdev->ops->set_power_mgmt) { | ||
4693 | err = -EOPNOTSUPP; | ||
4694 | goto unlock_rdev; | ||
4695 | } | ||
4696 | |||
4697 | state = (ps_state == NL80211_PS_ENABLED) ? true : false; | ||
4698 | |||
4699 | if (state == wdev->ps) | ||
4700 | goto unlock_rdev; | ||
4701 | |||
4702 | wdev->ps = state; | ||
4703 | |||
4704 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, wdev->ps, | ||
4705 | wdev->ps_timeout)) | ||
4706 | /* assume this means it's off */ | ||
4707 | wdev->ps = false; | ||
4708 | |||
4709 | unlock_rdev: | ||
4710 | cfg80211_unlock_rdev(rdev); | ||
4711 | dev_put(dev); | ||
4712 | rtnl_unlock(); | ||
4713 | |||
4714 | out: | ||
4715 | return err; | ||
4716 | } | ||
4717 | |||
4718 | static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | ||
4719 | { | ||
4720 | struct cfg80211_registered_device *rdev; | ||
4721 | enum nl80211_ps_state ps_state; | ||
4722 | struct wireless_dev *wdev; | ||
4723 | struct net_device *dev; | ||
4724 | struct sk_buff *msg; | ||
4725 | void *hdr; | ||
4726 | int err; | ||
4727 | |||
4728 | rtnl_lock(); | ||
4729 | |||
4730 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4731 | if (err) | ||
4732 | goto unlock_rtnl; | ||
4733 | |||
4734 | wdev = dev->ieee80211_ptr; | ||
4735 | |||
4736 | if (!rdev->ops->set_power_mgmt) { | ||
4737 | err = -EOPNOTSUPP; | ||
4738 | goto out; | ||
4739 | } | ||
4740 | |||
4741 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
4742 | if (!msg) { | ||
4743 | err = -ENOMEM; | ||
4744 | goto out; | ||
4745 | } | ||
4746 | |||
4747 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
4748 | NL80211_CMD_GET_POWER_SAVE); | ||
4749 | if (!hdr) { | ||
4750 | err = -ENOMEM; | ||
4751 | goto free_msg; | ||
4752 | } | ||
4753 | |||
4754 | if (wdev->ps) | ||
4755 | ps_state = NL80211_PS_ENABLED; | ||
4756 | else | ||
4757 | ps_state = NL80211_PS_DISABLED; | ||
4758 | |||
4759 | NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, ps_state); | ||
4760 | |||
4761 | genlmsg_end(msg, hdr); | ||
4762 | err = genlmsg_reply(msg, info); | ||
4763 | goto out; | ||
4764 | |||
4765 | nla_put_failure: | ||
4766 | err = -ENOBUFS; | ||
4767 | |||
4768 | free_msg: | ||
4769 | nlmsg_free(msg); | ||
4770 | |||
4771 | out: | ||
4772 | cfg80211_unlock_rdev(rdev); | ||
4773 | dev_put(dev); | ||
4774 | |||
4775 | unlock_rtnl: | ||
4776 | rtnl_unlock(); | ||
4777 | |||
4778 | return err; | ||
4779 | } | ||
4780 | |||
4548 | static struct genl_ops nl80211_ops[] = { | 4781 | static struct genl_ops nl80211_ops[] = { |
4549 | { | 4782 | { |
4550 | .cmd = NL80211_CMD_GET_WIPHY, | 4783 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -4825,6 +5058,30 @@ static struct genl_ops nl80211_ops[] = { | |||
4825 | .policy = nl80211_policy, | 5058 | .policy = nl80211_policy, |
4826 | .flags = GENL_ADMIN_PERM, | 5059 | .flags = GENL_ADMIN_PERM, |
4827 | }, | 5060 | }, |
5061 | { | ||
5062 | .cmd = NL80211_CMD_REGISTER_ACTION, | ||
5063 | .doit = nl80211_register_action, | ||
5064 | .policy = nl80211_policy, | ||
5065 | .flags = GENL_ADMIN_PERM, | ||
5066 | }, | ||
5067 | { | ||
5068 | .cmd = NL80211_CMD_ACTION, | ||
5069 | .doit = nl80211_action, | ||
5070 | .policy = nl80211_policy, | ||
5071 | .flags = GENL_ADMIN_PERM, | ||
5072 | }, | ||
5073 | { | ||
5074 | .cmd = NL80211_CMD_SET_POWER_SAVE, | ||
5075 | .doit = nl80211_set_power_save, | ||
5076 | .policy = nl80211_policy, | ||
5077 | .flags = GENL_ADMIN_PERM, | ||
5078 | }, | ||
5079 | { | ||
5080 | .cmd = NL80211_CMD_GET_POWER_SAVE, | ||
5081 | .doit = nl80211_get_power_save, | ||
5082 | .policy = nl80211_policy, | ||
5083 | /* can be retrieved by unprivileged users */ | ||
5084 | }, | ||
4828 | }; | 5085 | }; |
4829 | 5086 | ||
4830 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 5087 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -5497,6 +5754,110 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
5497 | nl80211_mlme_mcgrp.id, gfp); | 5754 | nl80211_mlme_mcgrp.id, gfp); |
5498 | } | 5755 | } |
5499 | 5756 | ||
5757 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | ||
5758 | struct net_device *netdev, u32 nlpid, | ||
5759 | int freq, const u8 *buf, size_t len, gfp_t gfp) | ||
5760 | { | ||
5761 | struct sk_buff *msg; | ||
5762 | void *hdr; | ||
5763 | int err; | ||
5764 | |||
5765 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
5766 | if (!msg) | ||
5767 | return -ENOMEM; | ||
5768 | |||
5769 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION); | ||
5770 | if (!hdr) { | ||
5771 | nlmsg_free(msg); | ||
5772 | return -ENOMEM; | ||
5773 | } | ||
5774 | |||
5775 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5776 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5777 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); | ||
5778 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); | ||
5779 | |||
5780 | err = genlmsg_end(msg, hdr); | ||
5781 | if (err < 0) { | ||
5782 | nlmsg_free(msg); | ||
5783 | return err; | ||
5784 | } | ||
5785 | |||
5786 | err = genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid); | ||
5787 | if (err < 0) | ||
5788 | return err; | ||
5789 | return 0; | ||
5790 | |||
5791 | nla_put_failure: | ||
5792 | genlmsg_cancel(msg, hdr); | ||
5793 | nlmsg_free(msg); | ||
5794 | return -ENOBUFS; | ||
5795 | } | ||
5796 | |||
5797 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | ||
5798 | struct net_device *netdev, u64 cookie, | ||
5799 | const u8 *buf, size_t len, bool ack, | ||
5800 | gfp_t gfp) | ||
5801 | { | ||
5802 | struct sk_buff *msg; | ||
5803 | void *hdr; | ||
5804 | |||
5805 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
5806 | if (!msg) | ||
5807 | return; | ||
5808 | |||
5809 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_ACTION_TX_STATUS); | ||
5810 | if (!hdr) { | ||
5811 | nlmsg_free(msg); | ||
5812 | return; | ||
5813 | } | ||
5814 | |||
5815 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5816 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5817 | NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf); | ||
5818 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | ||
5819 | if (ack) | ||
5820 | NLA_PUT_FLAG(msg, NL80211_ATTR_ACK); | ||
5821 | |||
5822 | if (genlmsg_end(msg, hdr) < 0) { | ||
5823 | nlmsg_free(msg); | ||
5824 | return; | ||
5825 | } | ||
5826 | |||
5827 | genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); | ||
5828 | return; | ||
5829 | |||
5830 | nla_put_failure: | ||
5831 | genlmsg_cancel(msg, hdr); | ||
5832 | nlmsg_free(msg); | ||
5833 | } | ||
5834 | |||
5835 | static int nl80211_netlink_notify(struct notifier_block * nb, | ||
5836 | unsigned long state, | ||
5837 | void *_notify) | ||
5838 | { | ||
5839 | struct netlink_notify *notify = _notify; | ||
5840 | struct cfg80211_registered_device *rdev; | ||
5841 | struct wireless_dev *wdev; | ||
5842 | |||
5843 | if (state != NETLINK_URELEASE) | ||
5844 | return NOTIFY_DONE; | ||
5845 | |||
5846 | rcu_read_lock(); | ||
5847 | |||
5848 | list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) | ||
5849 | list_for_each_entry_rcu(wdev, &rdev->netdev_list, list) | ||
5850 | cfg80211_mlme_unregister_actions(wdev, notify->pid); | ||
5851 | |||
5852 | rcu_read_unlock(); | ||
5853 | |||
5854 | return NOTIFY_DONE; | ||
5855 | } | ||
5856 | |||
5857 | static struct notifier_block nl80211_netlink_notifier = { | ||
5858 | .notifier_call = nl80211_netlink_notify, | ||
5859 | }; | ||
5860 | |||
5500 | /* initialisation/exit functions */ | 5861 | /* initialisation/exit functions */ |
5501 | 5862 | ||
5502 | int nl80211_init(void) | 5863 | int nl80211_init(void) |
@@ -5530,6 +5891,10 @@ int nl80211_init(void) | |||
5530 | goto err_out; | 5891 | goto err_out; |
5531 | #endif | 5892 | #endif |
5532 | 5893 | ||
5894 | err = netlink_register_notifier(&nl80211_netlink_notifier); | ||
5895 | if (err) | ||
5896 | goto err_out; | ||
5897 | |||
5533 | return 0; | 5898 | return 0; |
5534 | err_out: | 5899 | err_out: |
5535 | genl_unregister_family(&nl80211_fam); | 5900 | genl_unregister_family(&nl80211_fam); |
@@ -5538,5 +5903,6 @@ int nl80211_init(void) | |||
5538 | 5903 | ||
5539 | void nl80211_exit(void) | 5904 | void nl80211_exit(void) |
5540 | { | 5905 | { |
5906 | netlink_unregister_notifier(&nl80211_netlink_notifier); | ||
5541 | genl_unregister_family(&nl80211_fam); | 5907 | genl_unregister_family(&nl80211_fam); |
5542 | } | 5908 | } |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 14855b8fb430..4ca511102c6c 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,4 +74,12 @@ void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | |||
74 | struct net_device *dev, const u8 *mac_addr, | 74 | struct net_device *dev, const u8 *mac_addr, |
75 | struct station_info *sinfo, gfp_t gfp); | 75 | struct station_info *sinfo, gfp_t gfp); |
76 | 76 | ||
77 | int nl80211_send_action(struct cfg80211_registered_device *rdev, | ||
78 | struct net_device *netdev, u32 nlpid, int freq, | ||
79 | const u8 *buf, size_t len, gfp_t gfp); | ||
80 | void nl80211_send_action_tx_status(struct cfg80211_registered_device *rdev, | ||
81 | struct net_device *netdev, u64 cookie, | ||
82 | const u8 *buf, size_t len, bool ack, | ||
83 | gfp_t gfp); | ||
84 | |||
77 | #endif /* __NET_WIRELESS_NL80211_H */ | 85 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index b17eeae448d5..9ab51838849e 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -1099,8 +1099,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, | |||
1099 | { | 1099 | { |
1100 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1100 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1101 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 1101 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
1102 | bool ps = wdev->wext.ps; | 1102 | bool ps = wdev->ps; |
1103 | int timeout = wdev->wext.ps_timeout; | 1103 | int timeout = wdev->ps_timeout; |
1104 | int err; | 1104 | int err; |
1105 | 1105 | ||
1106 | if (wdev->iftype != NL80211_IFTYPE_STATION) | 1106 | if (wdev->iftype != NL80211_IFTYPE_STATION) |
@@ -1133,8 +1133,8 @@ int cfg80211_wext_siwpower(struct net_device *dev, | |||
1133 | if (err) | 1133 | if (err) |
1134 | return err; | 1134 | return err; |
1135 | 1135 | ||
1136 | wdev->wext.ps = ps; | 1136 | wdev->ps = ps; |
1137 | wdev->wext.ps_timeout = timeout; | 1137 | wdev->ps_timeout = timeout; |
1138 | 1138 | ||
1139 | return 0; | 1139 | return 0; |
1140 | 1140 | ||
@@ -1147,7 +1147,7 @@ int cfg80211_wext_giwpower(struct net_device *dev, | |||
1147 | { | 1147 | { |
1148 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 1148 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
1149 | 1149 | ||
1150 | wrq->disabled = !wdev->wext.ps; | 1150 | wrq->disabled = !wdev->ps; |
1151 | 1151 | ||
1152 | return 0; | 1152 | return 0; |
1153 | } | 1153 | } |