diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-08 18:39:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-08 18:39:41 -0400 |
commit | 54dceb008ffcbe003bea9017cad1227a83b6fc3f (patch) | |
tree | d4e3345ead16da19efe38dbf97ade38309f8b4f7 | |
parent | 11a100f844f6096787ab20e19f17d72abc957a8f (diff) | |
parent | b46372710ab536c0967f76be5dc41341583d4a54 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
49 files changed, 1449 insertions, 678 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 865f2980c273..d5b006f5b86f 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -611,14 +611,20 @@ config RTL8180 | |||
611 | Thanks to Realtek for their support! | 611 | Thanks to Realtek for their support! |
612 | 612 | ||
613 | config RTL8187 | 613 | config RTL8187 |
614 | tristate "Realtek 8187 USB support" | 614 | tristate "Realtek 8187 and 8187B USB support" |
615 | depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL | 615 | depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL |
616 | select EEPROM_93CX6 | 616 | select EEPROM_93CX6 |
617 | ---help--- | 617 | ---help--- |
618 | This is a driver for RTL8187 based cards. | 618 | This is a driver for RTL8187 and RTL8187B based cards. |
619 | These are USB based chips found in cards such as: | 619 | These are USB based chips found in devices such as: |
620 | 620 | ||
621 | Netgear WG111v2 | 621 | Netgear WG111v2 |
622 | Level 1 WNC-0301USB | ||
623 | Micronet SP907GK V5 | ||
624 | Encore ENUWI-G2 | ||
625 | Trendnet TEW-424UB | ||
626 | ASUS P5B Deluxe | ||
627 | Toshiba Satellite Pro series of laptops | ||
622 | 628 | ||
623 | Thanks to Realtek for their support! | 629 | Thanks to Realtek for their support! |
624 | 630 | ||
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index eb0243a22691..fb6819e40f38 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -859,6 +859,18 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev) | |||
859 | return DMA_30BIT_MASK; | 859 | return DMA_30BIT_MASK; |
860 | } | 860 | } |
861 | 861 | ||
862 | static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask) | ||
863 | { | ||
864 | if (dmamask == DMA_30BIT_MASK) | ||
865 | return B43legacy_DMA_30BIT; | ||
866 | if (dmamask == DMA_32BIT_MASK) | ||
867 | return B43legacy_DMA_32BIT; | ||
868 | if (dmamask == DMA_64BIT_MASK) | ||
869 | return B43legacy_DMA_64BIT; | ||
870 | B43legacy_WARN_ON(1); | ||
871 | return B43legacy_DMA_30BIT; | ||
872 | } | ||
873 | |||
862 | /* Main initialization function. */ | 874 | /* Main initialization function. */ |
863 | static | 875 | static |
864 | struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, | 876 | struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, |
@@ -1018,6 +1030,43 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) | |||
1018 | dma->tx_ring0 = NULL; | 1030 | dma->tx_ring0 = NULL; |
1019 | } | 1031 | } |
1020 | 1032 | ||
1033 | static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) | ||
1034 | { | ||
1035 | u64 orig_mask = mask; | ||
1036 | bool fallback = 0; | ||
1037 | int err; | ||
1038 | |||
1039 | /* Try to set the DMA mask. If it fails, try falling back to a | ||
1040 | * lower mask, as we can always also support a lower one. */ | ||
1041 | while (1) { | ||
1042 | err = ssb_dma_set_mask(dev->dev, mask); | ||
1043 | if (!err) | ||
1044 | break; | ||
1045 | if (mask == DMA_64BIT_MASK) { | ||
1046 | mask = DMA_32BIT_MASK; | ||
1047 | fallback = 1; | ||
1048 | continue; | ||
1049 | } | ||
1050 | if (mask == DMA_32BIT_MASK) { | ||
1051 | mask = DMA_30BIT_MASK; | ||
1052 | fallback = 1; | ||
1053 | continue; | ||
1054 | } | ||
1055 | b43legacyerr(dev->wl, "The machine/kernel does not support " | ||
1056 | "the required %u-bit DMA mask\n", | ||
1057 | (unsigned int)dma_mask_to_engine_type(orig_mask)); | ||
1058 | return -EOPNOTSUPP; | ||
1059 | } | ||
1060 | if (fallback) { | ||
1061 | b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-" | ||
1062 | "bit\n", | ||
1063 | (unsigned int)dma_mask_to_engine_type(orig_mask), | ||
1064 | (unsigned int)dma_mask_to_engine_type(mask)); | ||
1065 | } | ||
1066 | |||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1021 | int b43legacy_dma_init(struct b43legacy_wldev *dev) | 1070 | int b43legacy_dma_init(struct b43legacy_wldev *dev) |
1022 | { | 1071 | { |
1023 | struct b43legacy_dma *dma = &dev->dma; | 1072 | struct b43legacy_dma *dma = &dev->dma; |
@@ -1027,21 +1076,8 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) | |||
1027 | enum b43legacy_dmatype type; | 1076 | enum b43legacy_dmatype type; |
1028 | 1077 | ||
1029 | dmamask = supported_dma_mask(dev); | 1078 | dmamask = supported_dma_mask(dev); |
1030 | switch (dmamask) { | 1079 | type = dma_mask_to_engine_type(dmamask); |
1031 | default: | 1080 | err = b43legacy_dma_set_mask(dev, dmamask); |
1032 | B43legacy_WARN_ON(1); | ||
1033 | case DMA_30BIT_MASK: | ||
1034 | type = B43legacy_DMA_30BIT; | ||
1035 | break; | ||
1036 | case DMA_32BIT_MASK: | ||
1037 | type = B43legacy_DMA_32BIT; | ||
1038 | break; | ||
1039 | case DMA_64BIT_MASK: | ||
1040 | type = B43legacy_DMA_64BIT; | ||
1041 | break; | ||
1042 | } | ||
1043 | |||
1044 | err = ssb_dma_set_mask(dev->dev, dmamask); | ||
1045 | if (err) { | 1081 | if (err) { |
1046 | #ifdef CONFIG_B43LEGACY_PIO | 1082 | #ifdef CONFIG_B43LEGACY_PIO |
1047 | b43legacywarn(dev->wl, "DMA for this device not supported. " | 1083 | b43legacywarn(dev->wl, "DMA for this device not supported. " |
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 6c158a569485..09004a632ae7 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c | |||
@@ -3417,7 +3417,7 @@ static void prism2_free_local_data(struct net_device *dev) | |||
3417 | } | 3417 | } |
3418 | 3418 | ||
3419 | 3419 | ||
3420 | #ifndef PRISM2_PLX | 3420 | #if (defined(PRISM2_PCI) && defined(CONFIG_PM)) || defined(PRISM2_PCCARD) |
3421 | static void prism2_suspend(struct net_device *dev) | 3421 | static void prism2_suspend(struct net_device *dev) |
3422 | { | 3422 | { |
3423 | struct hostap_interface *iface; | 3423 | struct hostap_interface *iface; |
@@ -3436,7 +3436,7 @@ static void prism2_suspend(struct net_device *dev) | |||
3436 | /* Disable hardware and firmware */ | 3436 | /* Disable hardware and firmware */ |
3437 | prism2_hw_shutdown(dev, 0); | 3437 | prism2_hw_shutdown(dev, 0); |
3438 | } | 3438 | } |
3439 | #endif /* PRISM2_PLX */ | 3439 | #endif /* (PRISM2_PCI && CONFIG_PM) || PRISM2_PCCARD */ |
3440 | 3440 | ||
3441 | 3441 | ||
3442 | /* These might at some point be compiled separately and used as separate | 3442 | /* These might at some point be compiled separately and used as separate |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b628a44057f7..82b66a3d3a5d 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -104,6 +104,7 @@ config IWL3945 | |||
104 | select IWLWIFI | 104 | select IWLWIFI |
105 | select MAC80211_LEDS if IWL3945_LEDS | 105 | select MAC80211_LEDS if IWL3945_LEDS |
106 | select LEDS_CLASS if IWL3945_LEDS | 106 | select LEDS_CLASS if IWL3945_LEDS |
107 | select RFKILL if IWL3945_RFKILL | ||
107 | ---help--- | 108 | ---help--- |
108 | Select to build the driver supporting the: | 109 | Select to build the driver supporting the: |
109 | 110 | ||
@@ -126,6 +127,10 @@ config IWL3945 | |||
126 | say M here and read <file:Documentation/kbuild/modules.txt>. The | 127 | say M here and read <file:Documentation/kbuild/modules.txt>. The |
127 | module will be called iwl3945.ko. | 128 | module will be called iwl3945.ko. |
128 | 129 | ||
130 | config IWL3945_RFKILL | ||
131 | bool "Enable RF kill support in iwl3945 drivers" | ||
132 | depends on IWL3945 | ||
133 | |||
129 | config IWL3945_SPECTRUM_MEASUREMENT | 134 | config IWL3945_SPECTRUM_MEASUREMENT |
130 | bool "Enable Spectrum Measurement in iwl3945 drivers" | 135 | bool "Enable Spectrum Measurement in iwl3945 drivers" |
131 | depends on IWL3945 | 136 | depends on IWL3945 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a77497809d97..9c0a09eaca6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -690,14 +690,9 @@ enum { | |||
690 | 690 | ||
691 | #endif | 691 | #endif |
692 | 692 | ||
693 | #ifdef CONFIG_IWLWIFI_RFKILL | 693 | #ifdef CONFIG_IWL3945_RFKILL |
694 | struct iwl3945_priv; | 694 | struct iwl3945_priv; |
695 | 695 | ||
696 | struct iwl3945_rfkill_mngr { | ||
697 | struct rfkill *rfkill; | ||
698 | struct input_dev *input_dev; | ||
699 | }; | ||
700 | |||
701 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); | 696 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); |
702 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); | 697 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); |
703 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); | 698 | int iwl3945_rfkill_init(struct iwl3945_priv *priv); |
@@ -800,8 +795,8 @@ struct iwl3945_priv { | |||
800 | struct iwl3945_init_alive_resp card_alive_init; | 795 | struct iwl3945_init_alive_resp card_alive_init; |
801 | struct iwl3945_alive_resp card_alive; | 796 | struct iwl3945_alive_resp card_alive; |
802 | 797 | ||
803 | #ifdef CONFIG_IWLWIFI_RFKILL | 798 | #ifdef CONFIG_IWL3945_RFKILL |
804 | struct iwl3945_rfkill_mngr rfkill_mngr; | 799 | struct rfkill *rfkill; |
805 | #endif | 800 | #endif |
806 | 801 | ||
807 | #ifdef CONFIG_IWL3945_LEDS | 802 | #ifdef CONFIG_IWL3945_LEDS |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8c93f8d56a70..04365b39279c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2285,9 +2285,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2285 | 2285 | ||
2286 | iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | 2286 | iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); |
2287 | 2287 | ||
2288 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { | 2288 | /* check if BAR is needed */ |
2289 | /* TODO: send BAR */ | 2289 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) |
2290 | } | 2290 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
2291 | 2291 | ||
2292 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | 2292 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { |
2293 | int freed, ampdu_q; | 2293 | int freed, ampdu_q; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cc73e9a711c..717db0d5ffb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -1278,9 +1278,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | |||
1278 | 1278 | ||
1279 | iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | 1279 | iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); |
1280 | 1280 | ||
1281 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { | 1281 | /* check if BAR is needed */ |
1282 | /* TODO: send BAR */ | 1282 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) |
1283 | } | 1283 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1284 | 1284 | ||
1285 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | 1285 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { |
1286 | int freed, ampdu_q; | 1286 | int freed, ampdu_q; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index eb4abe1ebbdb..dafd62c7dfd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -356,10 +356,19 @@ static inline int iwl_is_init(struct iwl_priv *priv) | |||
356 | return test_bit(STATUS_INIT, &priv->status); | 356 | return test_bit(STATUS_INIT, &priv->status); |
357 | } | 357 | } |
358 | 358 | ||
359 | static inline int iwl_is_rfkill_sw(struct iwl_priv *priv) | ||
360 | { | ||
361 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
362 | } | ||
363 | |||
364 | static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) | ||
365 | { | ||
366 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
367 | } | ||
368 | |||
359 | static inline int iwl_is_rfkill(struct iwl_priv *priv) | 369 | static inline int iwl_is_rfkill(struct iwl_priv *priv) |
360 | { | 370 | { |
361 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | 371 | return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv); |
362 | test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
363 | } | 372 | } |
364 | 373 | ||
365 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) | 374 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1289cfc213c..c8d3d97cf48d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -929,7 +929,7 @@ struct iwl_priv { | |||
929 | struct iwl_init_alive_resp card_alive_init; | 929 | struct iwl_init_alive_resp card_alive_init; |
930 | struct iwl_alive_resp card_alive; | 930 | struct iwl_alive_resp card_alive; |
931 | #ifdef CONFIG_IWLWIFI_RFKILL | 931 | #ifdef CONFIG_IWLWIFI_RFKILL |
932 | struct iwl_rfkill_mngr rfkill_mngr; | 932 | struct rfkill *rfkill; |
933 | #endif | 933 | #endif |
934 | 934 | ||
935 | #ifdef CONFIG_IWLWIFI_LEDS | 935 | #ifdef CONFIG_IWLWIFI_LEDS |
@@ -1103,7 +1103,7 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) | |||
1103 | clear_bit(txq_id, &priv->txq_ctx_active_msk); | 1103 | clear_bit(txq_id, &priv->txq_ctx_active_msk); |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | #ifdef CONFIG_IWLWIF_DEBUG | 1106 | #ifdef CONFIG_IWLWIFI_DEBUG |
1107 | const char *iwl_get_tx_fail_reason(u32 status); | 1107 | const char *iwl_get_tx_fail_reason(u32 status); |
1108 | #else | 1108 | #else |
1109 | static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } | 1109 | static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index aa9f31eadab2..e5e5846e9f25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -44,7 +44,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
44 | struct iwl_priv *priv = data; | 44 | struct iwl_priv *priv = data; |
45 | int err = 0; | 45 | int err = 0; |
46 | 46 | ||
47 | if (!priv->rfkill_mngr.rfkill) | 47 | if (!priv->rfkill) |
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -55,20 +55,20 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
55 | 55 | ||
56 | switch (state) { | 56 | switch (state) { |
57 | case RFKILL_STATE_UNBLOCKED: | 57 | case RFKILL_STATE_UNBLOCKED: |
58 | iwl_radio_kill_sw_enable_radio(priv); | 58 | if (iwl_is_rfkill_hw(priv)) { |
59 | /* if HW rf-kill is set dont allow ON state */ | ||
60 | if (iwl_is_rfkill(priv)) | ||
61 | err = -EBUSY; | 59 | err = -EBUSY; |
60 | goto out_unlock; | ||
61 | } | ||
62 | iwl_radio_kill_sw_enable_radio(priv); | ||
62 | break; | 63 | break; |
63 | case RFKILL_STATE_SOFT_BLOCKED: | 64 | case RFKILL_STATE_SOFT_BLOCKED: |
64 | iwl_radio_kill_sw_disable_radio(priv); | 65 | iwl_radio_kill_sw_disable_radio(priv); |
65 | if (!iwl_is_rfkill(priv)) | ||
66 | err = -EBUSY; | ||
67 | break; | 66 | break; |
68 | default: | 67 | default: |
69 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | 68 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); |
70 | break; | 69 | break; |
71 | } | 70 | } |
71 | out_unlock: | ||
72 | mutex_unlock(&priv->mutex); | 72 | mutex_unlock(&priv->mutex); |
73 | 73 | ||
74 | return err; | 74 | return err; |
@@ -82,39 +82,35 @@ int iwl_rfkill_init(struct iwl_priv *priv) | |||
82 | BUG_ON(device == NULL); | 82 | BUG_ON(device == NULL); |
83 | 83 | ||
84 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | 84 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); |
85 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | 85 | priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); |
86 | if (!priv->rfkill_mngr.rfkill) { | 86 | if (!priv->rfkill) { |
87 | IWL_ERROR("Unable to allocate rfkill device.\n"); | 87 | IWL_ERROR("Unable to allocate rfkill device.\n"); |
88 | ret = -ENOMEM; | 88 | ret = -ENOMEM; |
89 | goto error; | 89 | goto error; |
90 | } | 90 | } |
91 | 91 | ||
92 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | 92 | priv->rfkill->name = priv->cfg->name; |
93 | priv->rfkill_mngr.rfkill->data = priv; | 93 | priv->rfkill->data = priv; |
94 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 94 | priv->rfkill->state = RFKILL_STATE_UNBLOCKED; |
95 | priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; | 95 | priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; |
96 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | 96 | priv->rfkill->user_claim_unsupported = 1; |
97 | 97 | ||
98 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | 98 | priv->rfkill->dev.class->suspend = NULL; |
99 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | 99 | priv->rfkill->dev.class->resume = NULL; |
100 | 100 | ||
101 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | 101 | ret = rfkill_register(priv->rfkill); |
102 | if (ret) { | 102 | if (ret) { |
103 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | 103 | IWL_ERROR("Unable to register rfkill: %d\n", ret); |
104 | goto unregister_rfkill; | 104 | goto free_rfkill; |
105 | } | 105 | } |
106 | 106 | ||
107 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 107 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
108 | return ret; | 108 | return ret; |
109 | 109 | ||
110 | unregister_rfkill: | 110 | free_rfkill: |
111 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 111 | if (priv->rfkill != NULL) |
112 | priv->rfkill_mngr.rfkill = NULL; | 112 | rfkill_free(priv->rfkill); |
113 | 113 | priv->rfkill = NULL; | |
114 | freed_rfkill: | ||
115 | if (priv->rfkill_mngr.rfkill != NULL) | ||
116 | rfkill_free(priv->rfkill_mngr.rfkill); | ||
117 | priv->rfkill_mngr.rfkill = NULL; | ||
118 | 114 | ||
119 | error: | 115 | error: |
120 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 116 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
@@ -125,22 +121,27 @@ EXPORT_SYMBOL(iwl_rfkill_init); | |||
125 | void iwl_rfkill_unregister(struct iwl_priv *priv) | 121 | void iwl_rfkill_unregister(struct iwl_priv *priv) |
126 | { | 122 | { |
127 | 123 | ||
128 | if (priv->rfkill_mngr.rfkill) | 124 | if (priv->rfkill) |
129 | rfkill_unregister(priv->rfkill_mngr.rfkill); | 125 | rfkill_unregister(priv->rfkill); |
130 | 126 | ||
131 | priv->rfkill_mngr.rfkill = NULL; | 127 | priv->rfkill = NULL; |
132 | } | 128 | } |
133 | EXPORT_SYMBOL(iwl_rfkill_unregister); | 129 | EXPORT_SYMBOL(iwl_rfkill_unregister); |
134 | 130 | ||
135 | /* set rf-kill to the right state. */ | 131 | /* set rf-kill to the right state. */ |
136 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) | 132 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv) |
137 | { | 133 | { |
138 | if (!priv->rfkill_mngr.rfkill) | 134 | if (!priv->rfkill) |
139 | return; | 135 | return; |
140 | 136 | ||
141 | if (!iwl_is_rfkill(priv)) | 137 | if (iwl_is_rfkill_hw(priv)) { |
142 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 138 | rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); |
139 | return; | ||
140 | } | ||
141 | |||
142 | if (!iwl_is_rfkill_sw(priv)) | ||
143 | rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); | ||
143 | else | 144 | else |
144 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | 145 | rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); |
145 | } | 146 | } |
146 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); | 147 | EXPORT_SYMBOL(iwl_rfkill_set_hw_state); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index 00692d2e9bd8..402fd4c781da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h | |||
@@ -33,9 +33,6 @@ struct iwl_priv; | |||
33 | #include <linux/rfkill.h> | 33 | #include <linux/rfkill.h> |
34 | 34 | ||
35 | #ifdef CONFIG_IWLWIFI_RFKILL | 35 | #ifdef CONFIG_IWLWIFI_RFKILL |
36 | struct iwl_rfkill_mngr { | ||
37 | struct rfkill *rfkill; | ||
38 | }; | ||
39 | 36 | ||
40 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); | 37 | void iwl_rfkill_set_hw_state(struct iwl_priv *priv); |
41 | void iwl_rfkill_unregister(struct iwl_priv *priv); | 38 | void iwl_rfkill_unregister(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 032641d4c7d1..0be2a71990b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -1493,7 +1493,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1493 | } | 1493 | } |
1494 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); | 1494 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); |
1495 | 1495 | ||
1496 | #ifdef CONFIG_IWLWIF_DEBUG | 1496 | #ifdef CONFIG_IWLWIFI_DEBUG |
1497 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 1497 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x |
1498 | 1498 | ||
1499 | const char *iwl_get_tx_fail_reason(u32 status) | 1499 | const char *iwl_get_tx_fail_reason(u32 status) |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index baa1abd5a14d..1a7d18fea89d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -537,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv) | |||
537 | return test_bit(STATUS_INIT, &priv->status); | 537 | return test_bit(STATUS_INIT, &priv->status); |
538 | } | 538 | } |
539 | 539 | ||
540 | static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) | ||
541 | { | ||
542 | return test_bit(STATUS_RF_KILL_SW, &priv->status); | ||
543 | } | ||
544 | |||
545 | static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) | ||
546 | { | ||
547 | return test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
548 | } | ||
549 | |||
540 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) | 550 | static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) |
541 | { | 551 | { |
542 | return test_bit(STATUS_RF_KILL_HW, &priv->status) || | 552 | return iwl3945_is_rfkill_hw(priv) || |
543 | test_bit(STATUS_RF_KILL_SW, &priv->status); | 553 | iwl3945_is_rfkill_sw(priv); |
544 | } | 554 | } |
545 | 555 | ||
546 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) | 556 | static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) |
@@ -6013,12 +6023,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv) | |||
6013 | else { | 6023 | else { |
6014 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 6024 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
6015 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { | 6025 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { |
6016 | iwl3945_rfkill_set_hw_state(priv); | ||
6017 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); | 6026 | IWL_WARNING("Radio disabled by HW RF Kill switch\n"); |
6018 | return -ENODEV; | 6027 | return -ENODEV; |
6019 | } | 6028 | } |
6020 | } | 6029 | } |
6021 | iwl3945_rfkill_set_hw_state(priv); | 6030 | |
6022 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); | 6031 | iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); |
6023 | 6032 | ||
6024 | rc = iwl3945_hw_nic_init(priv); | 6033 | rc = iwl3945_hw_nic_init(priv); |
@@ -6143,8 +6152,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
6143 | "wireless networking to work.\n"); | 6152 | "wireless networking to work.\n"); |
6144 | } | 6153 | } |
6145 | 6154 | ||
6146 | iwl3945_rfkill_set_hw_state(priv); | ||
6147 | mutex_unlock(&priv->mutex); | 6155 | mutex_unlock(&priv->mutex); |
6156 | iwl3945_rfkill_set_hw_state(priv); | ||
6148 | } | 6157 | } |
6149 | 6158 | ||
6150 | static void iwl3945_bg_set_monitor(struct work_struct *work) | 6159 | static void iwl3945_bg_set_monitor(struct work_struct *work) |
@@ -6398,6 +6407,7 @@ static void iwl3945_bg_up(struct work_struct *data) | |||
6398 | mutex_lock(&priv->mutex); | 6407 | mutex_lock(&priv->mutex); |
6399 | __iwl3945_up(priv); | 6408 | __iwl3945_up(priv); |
6400 | mutex_unlock(&priv->mutex); | 6409 | mutex_unlock(&priv->mutex); |
6410 | iwl3945_rfkill_set_hw_state(priv); | ||
6401 | } | 6411 | } |
6402 | 6412 | ||
6403 | static void iwl3945_bg_restart(struct work_struct *data) | 6413 | static void iwl3945_bg_restart(struct work_struct *data) |
@@ -6618,6 +6628,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
6618 | 6628 | ||
6619 | mutex_unlock(&priv->mutex); | 6629 | mutex_unlock(&priv->mutex); |
6620 | 6630 | ||
6631 | iwl3945_rfkill_set_hw_state(priv); | ||
6632 | |||
6621 | if (ret) | 6633 | if (ret) |
6622 | goto out_release_irq; | 6634 | goto out_release_irq; |
6623 | 6635 | ||
@@ -8276,14 +8288,14 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) | |||
8276 | #endif /* CONFIG_PM */ | 8288 | #endif /* CONFIG_PM */ |
8277 | 8289 | ||
8278 | /*************** RFKILL FUNCTIONS **********/ | 8290 | /*************** RFKILL FUNCTIONS **********/ |
8279 | #ifdef CONFIG_IWLWIFI_RFKILL | 8291 | #ifdef CONFIG_IWL3945_RFKILL |
8280 | /* software rf-kill from user */ | 8292 | /* software rf-kill from user */ |
8281 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | 8293 | static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) |
8282 | { | 8294 | { |
8283 | struct iwl3945_priv *priv = data; | 8295 | struct iwl3945_priv *priv = data; |
8284 | int err = 0; | 8296 | int err = 0; |
8285 | 8297 | ||
8286 | if (!priv->rfkill_mngr.rfkill) | 8298 | if (!priv->rfkill) |
8287 | return 0; | 8299 | return 0; |
8288 | 8300 | ||
8289 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 8301 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
@@ -8294,20 +8306,20 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
8294 | 8306 | ||
8295 | switch (state) { | 8307 | switch (state) { |
8296 | case RFKILL_STATE_UNBLOCKED: | 8308 | case RFKILL_STATE_UNBLOCKED: |
8297 | iwl3945_radio_kill_sw(priv, 0); | 8309 | if (iwl3945_is_rfkill_hw(priv)) { |
8298 | /* if HW rf-kill is set dont allow ON state */ | ||
8299 | if (iwl3945_is_rfkill(priv)) | ||
8300 | err = -EBUSY; | 8310 | err = -EBUSY; |
8311 | goto out_unlock; | ||
8312 | } | ||
8313 | iwl3945_radio_kill_sw(priv, 0); | ||
8301 | break; | 8314 | break; |
8302 | case RFKILL_STATE_SOFT_BLOCKED: | 8315 | case RFKILL_STATE_SOFT_BLOCKED: |
8303 | iwl3945_radio_kill_sw(priv, 1); | 8316 | iwl3945_radio_kill_sw(priv, 1); |
8304 | if (!iwl3945_is_rfkill(priv)) | ||
8305 | err = -EBUSY; | ||
8306 | break; | 8317 | break; |
8307 | default: | 8318 | default: |
8308 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); | 8319 | IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); |
8309 | break; | 8320 | break; |
8310 | } | 8321 | } |
8322 | out_unlock: | ||
8311 | mutex_unlock(&priv->mutex); | 8323 | mutex_unlock(&priv->mutex); |
8312 | 8324 | ||
8313 | return err; | 8325 | return err; |
@@ -8321,64 +8333,35 @@ int iwl3945_rfkill_init(struct iwl3945_priv *priv) | |||
8321 | BUG_ON(device == NULL); | 8333 | BUG_ON(device == NULL); |
8322 | 8334 | ||
8323 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); | 8335 | IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); |
8324 | priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); | 8336 | priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); |
8325 | if (!priv->rfkill_mngr.rfkill) { | 8337 | if (!priv->rfkill) { |
8326 | IWL_ERROR("Unable to allocate rfkill device.\n"); | 8338 | IWL_ERROR("Unable to allocate rfkill device.\n"); |
8327 | ret = -ENOMEM; | 8339 | ret = -ENOMEM; |
8328 | goto error; | 8340 | goto error; |
8329 | } | 8341 | } |
8330 | 8342 | ||
8331 | priv->rfkill_mngr.rfkill->name = priv->cfg->name; | 8343 | priv->rfkill->name = priv->cfg->name; |
8332 | priv->rfkill_mngr.rfkill->data = priv; | 8344 | priv->rfkill->data = priv; |
8333 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 8345 | priv->rfkill->state = RFKILL_STATE_UNBLOCKED; |
8334 | priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; | 8346 | priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; |
8335 | priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; | 8347 | priv->rfkill->user_claim_unsupported = 1; |
8336 | |||
8337 | priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; | ||
8338 | priv->rfkill_mngr.rfkill->dev.class->resume = NULL; | ||
8339 | 8348 | ||
8340 | priv->rfkill_mngr.input_dev = input_allocate_device(); | 8349 | priv->rfkill->dev.class->suspend = NULL; |
8341 | if (!priv->rfkill_mngr.input_dev) { | 8350 | priv->rfkill->dev.class->resume = NULL; |
8342 | IWL_ERROR("Unable to allocate rfkill input device.\n"); | ||
8343 | ret = -ENOMEM; | ||
8344 | goto freed_rfkill; | ||
8345 | } | ||
8346 | 8351 | ||
8347 | priv->rfkill_mngr.input_dev->name = priv->cfg->name; | 8352 | ret = rfkill_register(priv->rfkill); |
8348 | priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); | ||
8349 | priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; | ||
8350 | priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; | ||
8351 | priv->rfkill_mngr.input_dev->dev.parent = device; | ||
8352 | priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); | ||
8353 | set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); | ||
8354 | |||
8355 | ret = rfkill_register(priv->rfkill_mngr.rfkill); | ||
8356 | if (ret) { | 8353 | if (ret) { |
8357 | IWL_ERROR("Unable to register rfkill: %d\n", ret); | 8354 | IWL_ERROR("Unable to register rfkill: %d\n", ret); |
8358 | goto free_input_dev; | 8355 | goto freed_rfkill; |
8359 | } | ||
8360 | |||
8361 | ret = input_register_device(priv->rfkill_mngr.input_dev); | ||
8362 | if (ret) { | ||
8363 | IWL_ERROR("Unable to register rfkill input device: %d\n", ret); | ||
8364 | goto unregister_rfkill; | ||
8365 | } | 8356 | } |
8366 | 8357 | ||
8367 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 8358 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
8368 | return ret; | 8359 | return ret; |
8369 | 8360 | ||
8370 | unregister_rfkill: | ||
8371 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8372 | priv->rfkill_mngr.rfkill = NULL; | ||
8373 | |||
8374 | free_input_dev: | ||
8375 | input_free_device(priv->rfkill_mngr.input_dev); | ||
8376 | priv->rfkill_mngr.input_dev = NULL; | ||
8377 | |||
8378 | freed_rfkill: | 8361 | freed_rfkill: |
8379 | if (priv->rfkill_mngr.rfkill != NULL) | 8362 | if (priv->rfkill != NULL) |
8380 | rfkill_free(priv->rfkill_mngr.rfkill); | 8363 | rfkill_free(priv->rfkill); |
8381 | priv->rfkill_mngr.rfkill = NULL; | 8364 | priv->rfkill = NULL; |
8382 | 8365 | ||
8383 | error: | 8366 | error: |
8384 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); | 8367 | IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); |
@@ -8387,28 +8370,28 @@ error: | |||
8387 | 8370 | ||
8388 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) | 8371 | void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) |
8389 | { | 8372 | { |
8373 | if (priv->rfkill) | ||
8374 | rfkill_unregister(priv->rfkill); | ||
8390 | 8375 | ||
8391 | if (priv->rfkill_mngr.input_dev) | 8376 | priv->rfkill = NULL; |
8392 | input_unregister_device(priv->rfkill_mngr.input_dev); | ||
8393 | |||
8394 | if (priv->rfkill_mngr.rfkill) | ||
8395 | rfkill_unregister(priv->rfkill_mngr.rfkill); | ||
8396 | |||
8397 | priv->rfkill_mngr.input_dev = NULL; | ||
8398 | priv->rfkill_mngr.rfkill = NULL; | ||
8399 | } | 8377 | } |
8400 | 8378 | ||
8401 | /* set rf-kill to the right state. */ | 8379 | /* set rf-kill to the right state. */ |
8402 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) | 8380 | void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) |
8403 | { | 8381 | { |
8404 | 8382 | ||
8405 | if (!priv->rfkill_mngr.rfkill) | 8383 | if (!priv->rfkill) |
8384 | return; | ||
8385 | |||
8386 | if (iwl3945_is_rfkill_hw(priv)) { | ||
8387 | rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); | ||
8406 | return; | 8388 | return; |
8389 | } | ||
8407 | 8390 | ||
8408 | if (!iwl3945_is_rfkill(priv)) | 8391 | if (!iwl3945_is_rfkill_sw(priv)) |
8409 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; | 8392 | rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); |
8410 | else | 8393 | else |
8411 | priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; | 8394 | rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); |
8412 | } | 8395 | } |
8413 | #endif | 8396 | #endif |
8414 | 8397 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 60b7a6498fe8..7f65d9123b2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -2187,13 +2187,11 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
2187 | 2187 | ||
2188 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && | 2188 | if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && |
2189 | iwl_is_rfkill(priv)) { | 2189 | iwl_is_rfkill(priv)) { |
2190 | iwl_rfkill_set_hw_state(priv); | ||
2191 | IWL_WARNING("Radio disabled by %s RF Kill switch\n", | 2190 | IWL_WARNING("Radio disabled by %s RF Kill switch\n", |
2192 | test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); | 2191 | test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); |
2193 | return -ENODEV; | 2192 | return -ENODEV; |
2194 | } | 2193 | } |
2195 | 2194 | ||
2196 | iwl_rfkill_set_hw_state(priv); | ||
2197 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2195 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2198 | 2196 | ||
2199 | ret = priv->cfg->ops->lib->alloc_shared_mem(priv); | 2197 | ret = priv->cfg->ops->lib->alloc_shared_mem(priv); |
@@ -2330,9 +2328,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) | |||
2330 | "Kill switch must be turned off for " | 2328 | "Kill switch must be turned off for " |
2331 | "wireless networking to work.\n"); | 2329 | "wireless networking to work.\n"); |
2332 | } | 2330 | } |
2333 | iwl_rfkill_set_hw_state(priv); | ||
2334 | |||
2335 | mutex_unlock(&priv->mutex); | 2331 | mutex_unlock(&priv->mutex); |
2332 | iwl_rfkill_set_hw_state(priv); | ||
2336 | } | 2333 | } |
2337 | 2334 | ||
2338 | static void iwl4965_bg_set_monitor(struct work_struct *work) | 2335 | static void iwl4965_bg_set_monitor(struct work_struct *work) |
@@ -2390,6 +2387,7 @@ static void iwl4965_bg_up(struct work_struct *data) | |||
2390 | mutex_lock(&priv->mutex); | 2387 | mutex_lock(&priv->mutex); |
2391 | __iwl4965_up(priv); | 2388 | __iwl4965_up(priv); |
2392 | mutex_unlock(&priv->mutex); | 2389 | mutex_unlock(&priv->mutex); |
2390 | iwl_rfkill_set_hw_state(priv); | ||
2393 | } | 2391 | } |
2394 | 2392 | ||
2395 | static void iwl4965_bg_restart(struct work_struct *data) | 2393 | static void iwl4965_bg_restart(struct work_struct *data) |
@@ -2604,6 +2602,8 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) | |||
2604 | 2602 | ||
2605 | mutex_unlock(&priv->mutex); | 2603 | mutex_unlock(&priv->mutex); |
2606 | 2604 | ||
2605 | iwl_rfkill_set_hw_state(priv); | ||
2606 | |||
2607 | if (ret) | 2607 | if (ret) |
2608 | goto out_release_irq; | 2608 | goto out_release_irq; |
2609 | 2609 | ||
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 3a9b1d72caf8..d485a86bba75 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -36,9 +36,7 @@ config RT2X00_LIB_FIRMWARE | |||
36 | config RT2X00_LIB_RFKILL | 36 | config RT2X00_LIB_RFKILL |
37 | boolean | 37 | boolean |
38 | depends on RT2X00_LIB | 38 | depends on RT2X00_LIB |
39 | depends on INPUT | ||
40 | select RFKILL | 39 | select RFKILL |
41 | select INPUT_POLLDEV | ||
42 | 40 | ||
43 | config RT2X00_LIB_LEDS | 41 | config RT2X00_LIB_LEDS |
44 | boolean | 42 | boolean |
@@ -57,7 +55,7 @@ config RT2400PCI | |||
57 | 55 | ||
58 | config RT2400PCI_RFKILL | 56 | config RT2400PCI_RFKILL |
59 | bool "Ralink rt2400 rfkill support" | 57 | bool "Ralink rt2400 rfkill support" |
60 | depends on RT2400PCI && INPUT | 58 | depends on RT2400PCI |
61 | select RT2X00_LIB_RFKILL | 59 | select RT2X00_LIB_RFKILL |
62 | ---help--- | 60 | ---help--- |
63 | This adds support for integrated rt2400 hardware that features a | 61 | This adds support for integrated rt2400 hardware that features a |
@@ -85,7 +83,7 @@ config RT2500PCI | |||
85 | 83 | ||
86 | config RT2500PCI_RFKILL | 84 | config RT2500PCI_RFKILL |
87 | bool "Ralink rt2500 rfkill support" | 85 | bool "Ralink rt2500 rfkill support" |
88 | depends on RT2500PCI && INPUT | 86 | depends on RT2500PCI |
89 | select RT2X00_LIB_RFKILL | 87 | select RT2X00_LIB_RFKILL |
90 | ---help--- | 88 | ---help--- |
91 | This adds support for integrated rt2500 hardware that features a | 89 | This adds support for integrated rt2500 hardware that features a |
@@ -115,7 +113,7 @@ config RT61PCI | |||
115 | 113 | ||
116 | config RT61PCI_RFKILL | 114 | config RT61PCI_RFKILL |
117 | bool "Ralink rt2501/rt61 rfkill support" | 115 | bool "Ralink rt2501/rt61 rfkill support" |
118 | depends on RT61PCI && INPUT | 116 | depends on RT61PCI |
119 | select RT2X00_LIB_RFKILL | 117 | select RT2X00_LIB_RFKILL |
120 | ---help--- | 118 | ---help--- |
121 | This adds support for integrated rt61 hardware that features a | 119 | This adds support for integrated rt61 hardware that features a |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index b3dffcfed835..ee953ca0c6a3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1087,14 +1087,20 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1087 | static void rt2400pci_fill_rxdone(struct queue_entry *entry, | 1087 | static void rt2400pci_fill_rxdone(struct queue_entry *entry, |
1088 | struct rxdone_entry_desc *rxdesc) | 1088 | struct rxdone_entry_desc *rxdesc) |
1089 | { | 1089 | { |
1090 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
1090 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | 1091 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; |
1091 | u32 word0; | 1092 | u32 word0; |
1092 | u32 word2; | 1093 | u32 word2; |
1093 | u32 word3; | 1094 | u32 word3; |
1095 | u32 word4; | ||
1096 | u64 tsf; | ||
1097 | u32 rx_low; | ||
1098 | u32 rx_high; | ||
1094 | 1099 | ||
1095 | rt2x00_desc_read(entry_priv->desc, 0, &word0); | 1100 | rt2x00_desc_read(entry_priv->desc, 0, &word0); |
1096 | rt2x00_desc_read(entry_priv->desc, 2, &word2); | 1101 | rt2x00_desc_read(entry_priv->desc, 2, &word2); |
1097 | rt2x00_desc_read(entry_priv->desc, 3, &word3); | 1102 | rt2x00_desc_read(entry_priv->desc, 3, &word3); |
1103 | rt2x00_desc_read(entry_priv->desc, 4, &word4); | ||
1098 | 1104 | ||
1099 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) | 1105 | if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) |
1100 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | 1106 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; |
@@ -1102,10 +1108,27 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, | |||
1102 | rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; | 1108 | rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; |
1103 | 1109 | ||
1104 | /* | 1110 | /* |
1111 | * We only get the lower 32bits from the timestamp, | ||
1112 | * to get the full 64bits we must complement it with | ||
1113 | * the timestamp from get_tsf(). | ||
1114 | * Note that when a wraparound of the lower 32bits | ||
1115 | * has occurred between the frame arrival and the get_tsf() | ||
1116 | * call, we must decrease the higher 32bits with 1 to get | ||
1117 | * to correct value. | ||
1118 | */ | ||
1119 | tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); | ||
1120 | rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); | ||
1121 | rx_high = upper_32_bits(tsf); | ||
1122 | |||
1123 | if ((u32)tsf <= rx_low) | ||
1124 | rx_high--; | ||
1125 | |||
1126 | /* | ||
1105 | * Obtain the status about this packet. | 1127 | * Obtain the status about this packet. |
1106 | * The signal is the PLCP value, and needs to be stripped | 1128 | * The signal is the PLCP value, and needs to be stripped |
1107 | * of the preamble bit (0x08). | 1129 | * of the preamble bit (0x08). |
1108 | */ | 1130 | */ |
1131 | rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; | ||
1109 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; | 1132 | rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; |
1110 | rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - | 1133 | rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - |
1111 | entry->queue->rt2x00dev->rssi_offset; | 1134 | entry->queue->rt2x00dev->rssi_offset; |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index cb648c30a5b3..42f376929ea9 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h | |||
@@ -751,7 +751,7 @@ | |||
751 | #define LEDCSR_LED_DEFAULT FIELD32(0x00100000) | 751 | #define LEDCSR_LED_DEFAULT FIELD32(0x00100000) |
752 | 752 | ||
753 | /* | 753 | /* |
754 | * AES control register. | 754 | * SECCSR3: AES control register. |
755 | */ | 755 | */ |
756 | #define SECCSR3 0x00fc | 756 | #define SECCSR3 0x00fc |
757 | 757 | ||
@@ -895,7 +895,7 @@ | |||
895 | #define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000) | 895 | #define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000) |
896 | 896 | ||
897 | /* | 897 | /* |
898 | * SECCSR1_RT2509: WEP control register. | 898 | * SECCSR1: WEP control register. |
899 | * KICK_ENCRYPT: Kick encryption engine, self-clear. | 899 | * KICK_ENCRYPT: Kick encryption engine, self-clear. |
900 | * ONE_SHOT: 0: ring mode, 1: One shot only mode. | 900 | * ONE_SHOT: 0: ring mode, 1: One shot only mode. |
901 | * DESC_ADDRESS: Descriptor physical address of frame. | 901 | * DESC_ADDRESS: Descriptor physical address of frame. |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 3e21fdf2b00f..4769ffeb4cc6 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h | |||
@@ -209,7 +209,7 @@ | |||
209 | #define MAC_CSR21_OFF_PERIOD FIELD16(0xff00) | 209 | #define MAC_CSR21_OFF_PERIOD FIELD16(0xff00) |
210 | 210 | ||
211 | /* | 211 | /* |
212 | * Collision window control register. | 212 | * MAC_CSR22: Collision window control register. |
213 | */ | 213 | */ |
214 | #define MAC_CSR22 0x042c | 214 | #define MAC_CSR22 0x042c |
215 | 215 | ||
@@ -296,7 +296,7 @@ | |||
296 | #define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000) | 296 | #define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000) |
297 | 297 | ||
298 | /* | 298 | /* |
299 | * TXRX_CSR5: OFDM TX BBP ID1. | 299 | * TXRX_CSR8: OFDM TX BBP ID1. |
300 | */ | 300 | */ |
301 | #define TXRX_CSR8 0x0450 | 301 | #define TXRX_CSR8 0x0450 |
302 | #define TXRX_CSR8_BBP_ID0 FIELD16(0x007f) | 302 | #define TXRX_CSR8_BBP_ID0 FIELD16(0x007f) |
@@ -370,7 +370,14 @@ | |||
370 | */ | 370 | */ |
371 | 371 | ||
372 | /* | 372 | /* |
373 | * SEC_CSR0-SEC_CSR7: Shared key 0, word 0-7 | 373 | * SEC_CSR0: Shared key 0, word 0 |
374 | * SEC_CSR1: Shared key 0, word 1 | ||
375 | * SEC_CSR2: Shared key 0, word 2 | ||
376 | * SEC_CSR3: Shared key 0, word 3 | ||
377 | * SEC_CSR4: Shared key 0, word 4 | ||
378 | * SEC_CSR5: Shared key 0, word 5 | ||
379 | * SEC_CSR6: Shared key 0, word 6 | ||
380 | * SEC_CSR7: Shared key 0, word 7 | ||
374 | */ | 381 | */ |
375 | #define SEC_CSR0 0x0480 | 382 | #define SEC_CSR0 0x0480 |
376 | #define SEC_CSR1 0x0482 | 383 | #define SEC_CSR1 0x0482 |
@@ -382,7 +389,14 @@ | |||
382 | #define SEC_CSR7 0x048e | 389 | #define SEC_CSR7 0x048e |
383 | 390 | ||
384 | /* | 391 | /* |
385 | * SEC_CSR8-SEC_CSR15: Shared key 1, word 0-7 | 392 | * SEC_CSR8: Shared key 1, word 0 |
393 | * SEC_CSR9: Shared key 1, word 1 | ||
394 | * SEC_CSR10: Shared key 1, word 2 | ||
395 | * SEC_CSR11: Shared key 1, word 3 | ||
396 | * SEC_CSR12: Shared key 1, word 4 | ||
397 | * SEC_CSR13: Shared key 1, word 5 | ||
398 | * SEC_CSR14: Shared key 1, word 6 | ||
399 | * SEC_CSR15: Shared key 1, word 7 | ||
386 | */ | 400 | */ |
387 | #define SEC_CSR8 0x0490 | 401 | #define SEC_CSR8 0x0490 |
388 | #define SEC_CSR9 0x0492 | 402 | #define SEC_CSR9 0x0492 |
@@ -394,7 +408,14 @@ | |||
394 | #define SEC_CSR15 0x049e | 408 | #define SEC_CSR15 0x049e |
395 | 409 | ||
396 | /* | 410 | /* |
397 | * SEC_CSR16-SEC_CSR23: Shared key 2, word 0-7 | 411 | * SEC_CSR16: Shared key 2, word 0 |
412 | * SEC_CSR17: Shared key 2, word 1 | ||
413 | * SEC_CSR18: Shared key 2, word 2 | ||
414 | * SEC_CSR19: Shared key 2, word 3 | ||
415 | * SEC_CSR20: Shared key 2, word 4 | ||
416 | * SEC_CSR21: Shared key 2, word 5 | ||
417 | * SEC_CSR22: Shared key 2, word 6 | ||
418 | * SEC_CSR23: Shared key 2, word 7 | ||
398 | */ | 419 | */ |
399 | #define SEC_CSR16 0x04a0 | 420 | #define SEC_CSR16 0x04a0 |
400 | #define SEC_CSR17 0x04a2 | 421 | #define SEC_CSR17 0x04a2 |
@@ -406,7 +427,14 @@ | |||
406 | #define SEC_CSR23 0x04ae | 427 | #define SEC_CSR23 0x04ae |
407 | 428 | ||
408 | /* | 429 | /* |
409 | * SEC_CSR24-SEC_CSR31: Shared key 3, word 0-7 | 430 | * SEC_CSR24: Shared key 3, word 0 |
431 | * SEC_CSR25: Shared key 3, word 1 | ||
432 | * SEC_CSR26: Shared key 3, word 2 | ||
433 | * SEC_CSR27: Shared key 3, word 3 | ||
434 | * SEC_CSR28: Shared key 3, word 4 | ||
435 | * SEC_CSR29: Shared key 3, word 5 | ||
436 | * SEC_CSR30: Shared key 3, word 6 | ||
437 | * SEC_CSR31: Shared key 3, word 7 | ||
410 | */ | 438 | */ |
411 | #define SEC_CSR24 0x04b0 | 439 | #define SEC_CSR24 0x04b0 |
412 | #define SEC_CSR25 0x04b2 | 440 | #define SEC_CSR25 0x04b2 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6842464dcf3e..c07d9ef383f0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -649,7 +649,7 @@ struct rt2x00_dev { | |||
649 | #define RFKILL_STATE_ALLOCATED 1 | 649 | #define RFKILL_STATE_ALLOCATED 1 |
650 | #define RFKILL_STATE_REGISTERED 2 | 650 | #define RFKILL_STATE_REGISTERED 2 |
651 | struct rfkill *rfkill; | 651 | struct rfkill *rfkill; |
652 | struct input_polled_dev *poll_dev; | 652 | struct delayed_work rfkill_work; |
653 | #endif /* CONFIG_RT2X00_LIB_RFKILL */ | 653 | #endif /* CONFIG_RT2X00_LIB_RFKILL */ |
654 | 654 | ||
655 | /* | 655 | /* |
@@ -787,8 +787,10 @@ struct rt2x00_dev { | |||
787 | 787 | ||
788 | /* | 788 | /* |
789 | * Scheduled work. | 789 | * Scheduled work. |
790 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | ||
791 | * which means it cannot be placed on the hw->workqueue | ||
792 | * due to RTNL locking requirements. | ||
790 | */ | 793 | */ |
791 | struct workqueue_struct *workqueue; | ||
792 | struct work_struct intf_work; | 794 | struct work_struct intf_work; |
793 | struct work_struct filter_work; | 795 | struct work_struct filter_work; |
794 | 796 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index ae8ab71fe474..b48c04e80a38 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -74,7 +74,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) | |||
74 | 74 | ||
75 | rt2x00lib_reset_link_tuner(rt2x00dev); | 75 | rt2x00lib_reset_link_tuner(rt2x00dev); |
76 | 76 | ||
77 | queue_delayed_work(rt2x00dev->workqueue, | 77 | queue_delayed_work(rt2x00dev->hw->workqueue, |
78 | &rt2x00dev->link.work, LINK_TUNE_INTERVAL); | 78 | &rt2x00dev->link.work, LINK_TUNE_INTERVAL); |
79 | } | 79 | } |
80 | 80 | ||
@@ -392,7 +392,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work) | |||
392 | * Increase tuner counter, and reschedule the next link tuner run. | 392 | * Increase tuner counter, and reschedule the next link tuner run. |
393 | */ | 393 | */ |
394 | rt2x00dev->link.count++; | 394 | rt2x00dev->link.count++; |
395 | queue_delayed_work(rt2x00dev->workqueue, | 395 | queue_delayed_work(rt2x00dev->hw->workqueue, |
396 | &rt2x00dev->link.work, LINK_TUNE_INTERVAL); | 396 | &rt2x00dev->link.work, LINK_TUNE_INTERVAL); |
397 | } | 397 | } |
398 | 398 | ||
@@ -496,7 +496,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) | |||
496 | rt2x00lib_beacondone_iter, | 496 | rt2x00lib_beacondone_iter, |
497 | rt2x00dev); | 497 | rt2x00dev); |
498 | 498 | ||
499 | queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); | 499 | schedule_work(&rt2x00dev->intf_work); |
500 | } | 500 | } |
501 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 501 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
502 | 502 | ||
@@ -664,6 +664,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
664 | 664 | ||
665 | rt2x00dev->link.qual.rx_success++; | 665 | rt2x00dev->link.qual.rx_success++; |
666 | 666 | ||
667 | rx_status->mactime = rxdesc.timestamp; | ||
667 | rx_status->rate_idx = idx; | 668 | rx_status->rate_idx = idx; |
668 | rx_status->qual = | 669 | rx_status->qual = |
669 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); | 670 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); |
@@ -1064,10 +1065,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1064 | /* | 1065 | /* |
1065 | * Initialize configuration work. | 1066 | * Initialize configuration work. |
1066 | */ | 1067 | */ |
1067 | rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); | ||
1068 | if (!rt2x00dev->workqueue) | ||
1069 | goto exit; | ||
1070 | |||
1071 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 1068 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
1072 | INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); | 1069 | INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); |
1073 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); | 1070 | INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); |
@@ -1128,13 +1125,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1128 | rt2x00leds_unregister(rt2x00dev); | 1125 | rt2x00leds_unregister(rt2x00dev); |
1129 | 1126 | ||
1130 | /* | 1127 | /* |
1131 | * Stop all queued work. Note that most tasks will already be halted | ||
1132 | * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). | ||
1133 | */ | ||
1134 | flush_workqueue(rt2x00dev->workqueue); | ||
1135 | destroy_workqueue(rt2x00dev->workqueue); | ||
1136 | |||
1137 | /* | ||
1138 | * Free ieee80211_hw memory. | 1128 | * Free ieee80211_hw memory. |
1139 | */ | 1129 | */ |
1140 | rt2x00lib_remove_hw(rt2x00dev); | 1130 | rt2x00lib_remove_hw(rt2x00dev); |
@@ -1179,7 +1169,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) | |||
1179 | * Suspend/disable extra components. | 1169 | * Suspend/disable extra components. |
1180 | */ | 1170 | */ |
1181 | rt2x00leds_suspend(rt2x00dev); | 1171 | rt2x00leds_suspend(rt2x00dev); |
1182 | rt2x00rfkill_suspend(rt2x00dev); | ||
1183 | rt2x00debug_deregister(rt2x00dev); | 1172 | rt2x00debug_deregister(rt2x00dev); |
1184 | 1173 | ||
1185 | exit: | 1174 | exit: |
@@ -1235,7 +1224,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) | |||
1235 | * Restore/enable extra components. | 1224 | * Restore/enable extra components. |
1236 | */ | 1225 | */ |
1237 | rt2x00debug_register(rt2x00dev); | 1226 | rt2x00debug_register(rt2x00dev); |
1238 | rt2x00rfkill_resume(rt2x00dev); | ||
1239 | rt2x00leds_resume(rt2x00dev); | 1227 | rt2x00leds_resume(rt2x00dev); |
1240 | 1228 | ||
1241 | /* | 1229 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 1d1f0749375e..eae5ce1d4de3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -33,7 +33,7 @@ | |||
33 | * Both the link tuner as the rfkill will be called once per second. | 33 | * Both the link tuner as the rfkill will be called once per second. |
34 | */ | 34 | */ |
35 | #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) | 35 | #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) |
36 | #define RFKILL_POLL_INTERVAL ( 1000 ) | 36 | #define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * rt2x00_rate: Per rate device information | 39 | * rt2x00_rate: Per rate device information |
@@ -204,8 +204,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev); | |||
204 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev); | 204 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev); |
205 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev); | 205 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev); |
206 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev); | 206 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev); |
207 | void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev); | ||
208 | void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev); | ||
209 | #else | 207 | #else |
210 | static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | 208 | static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) |
211 | { | 209 | { |
@@ -222,14 +220,6 @@ static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | |||
222 | static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) | 220 | static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) |
223 | { | 221 | { |
224 | } | 222 | } |
225 | |||
226 | static inline void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) | ||
227 | { | ||
228 | } | ||
229 | |||
230 | static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) | ||
231 | { | ||
232 | } | ||
233 | #endif /* CONFIG_RT2X00_LIB_RFKILL */ | 223 | #endif /* CONFIG_RT2X00_LIB_RFKILL */ |
234 | 224 | ||
235 | /* | 225 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 1253da89295b..3a1fb6d47e5d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
431 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 431 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) |
432 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); | 432 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); |
433 | else | 433 | else |
434 | queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); | 434 | queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); |
435 | } | 435 | } |
436 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 436 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
437 | 437 | ||
@@ -512,7 +512,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
512 | memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); | 512 | memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); |
513 | if (delayed) { | 513 | if (delayed) { |
514 | intf->delayed_flags |= delayed; | 514 | intf->delayed_flags |= delayed; |
515 | queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); | 515 | schedule_work(&rt2x00dev->intf_work); |
516 | } | 516 | } |
517 | spin_unlock(&intf->lock); | 517 | spin_unlock(&intf->lock); |
518 | } | 518 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 8e86611791f0..3ddce538ef4a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -45,10 +45,11 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, | |||
45 | frame_size = entry->queue->data_size + entry->queue->desc_size; | 45 | frame_size = entry->queue->data_size + entry->queue->desc_size; |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Reserve a few bytes extra headroom to allow drivers some moving | 48 | * The payload should be aligned to a 4-byte boundary, |
49 | * space (e.g. for alignment), while keeping the skb aligned. | 49 | * this means we need at least 3 bytes for moving the frame |
50 | * into the correct offset. | ||
50 | */ | 51 | */ |
51 | reserved_size = 8; | 52 | reserved_size = 4; |
52 | 53 | ||
53 | /* | 54 | /* |
54 | * Allocate skbuffer. | 55 | * Allocate skbuffer. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 5dd9cca3c62c..8945945c892e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -146,6 +146,7 @@ enum rxdone_entry_desc_flags { | |||
146 | * | 146 | * |
147 | * Summary of information that has been read from the RX frame descriptor. | 147 | * Summary of information that has been read from the RX frame descriptor. |
148 | * | 148 | * |
149 | * @timestamp: RX Timestamp | ||
149 | * @signal: Signal of the received frame. | 150 | * @signal: Signal of the received frame. |
150 | * @rssi: RSSI of the received frame. | 151 | * @rssi: RSSI of the received frame. |
151 | * @size: Data size of the received frame. | 152 | * @size: Data size of the received frame. |
@@ -154,6 +155,7 @@ enum rxdone_entry_desc_flags { | |||
154 | 155 | ||
155 | */ | 156 | */ |
156 | struct rxdone_entry_desc { | 157 | struct rxdone_entry_desc { |
158 | u64 timestamp; | ||
157 | int signal; | 159 | int signal; |
158 | int rssi; | 160 | int rssi; |
159 | int size; | 161 | int size; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 207281cfa8b7..04b29716d356 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -23,7 +23,6 @@ | |||
23 | Abstract: rt2x00 rfkill routines. | 23 | Abstract: rt2x00 rfkill routines. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/input-polldev.h> | ||
27 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 27 | #include <linux/module.h> |
29 | #include <linux/rfkill.h> | 28 | #include <linux/rfkill.h> |
@@ -61,15 +60,35 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | |||
61 | return retval; | 60 | return retval; |
62 | } | 61 | } |
63 | 62 | ||
64 | static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) | 63 | static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) |
65 | { | 64 | { |
66 | struct rt2x00_dev *rt2x00dev = poll_dev->private; | 65 | struct rt2x00_dev *rt2x00dev = data; |
67 | int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); | ||
68 | 66 | ||
69 | if (rt2x00dev->rfkill->state != state) { | 67 | *state = rt2x00dev->rfkill->state; |
70 | input_report_key(poll_dev->input, KEY_WLAN, 1); | 68 | |
71 | input_report_key(poll_dev->input, KEY_WLAN, 0); | 69 | return 0; |
72 | } | 70 | } |
71 | |||
72 | static void rt2x00rfkill_poll(struct work_struct *work) | ||
73 | { | ||
74 | struct rt2x00_dev *rt2x00dev = | ||
75 | container_of(work, struct rt2x00_dev, rfkill_work.work); | ||
76 | int state; | ||
77 | |||
78 | if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | ||
79 | return; | ||
80 | |||
81 | /* | ||
82 | * rfkill_poll reports 1 when the key has been pressed and the | ||
83 | * radio should be blocked. | ||
84 | */ | ||
85 | state = !rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | ||
86 | RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; | ||
87 | |||
88 | rfkill_force_state(rt2x00dev->rfkill, state); | ||
89 | |||
90 | queue_delayed_work(rt2x00dev->hw->workqueue, | ||
91 | &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); | ||
73 | } | 92 | } |
74 | 93 | ||
75 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | 94 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) |
@@ -83,12 +102,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | |||
83 | return; | 102 | return; |
84 | } | 103 | } |
85 | 104 | ||
86 | if (input_register_polled_device(rt2x00dev->poll_dev)) { | ||
87 | ERROR(rt2x00dev, "Failed to register polled device.\n"); | ||
88 | rfkill_unregister(rt2x00dev->rfkill); | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); | 105 | __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); |
93 | 106 | ||
94 | /* | 107 | /* |
@@ -96,7 +109,7 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | |||
96 | * and correctly sends the signal to the rfkill layer about this | 109 | * and correctly sends the signal to the rfkill layer about this |
97 | * state. | 110 | * state. |
98 | */ | 111 | */ |
99 | rt2x00rfkill_poll(rt2x00dev->poll_dev); | 112 | rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); |
100 | } | 113 | } |
101 | 114 | ||
102 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | 115 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) |
@@ -105,38 +118,13 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | |||
105 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | 118 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) |
106 | return; | 119 | return; |
107 | 120 | ||
108 | input_unregister_polled_device(rt2x00dev->poll_dev); | 121 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); |
122 | |||
109 | rfkill_unregister(rt2x00dev->rfkill); | 123 | rfkill_unregister(rt2x00dev->rfkill); |
110 | 124 | ||
111 | __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); | 125 | __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); |
112 | } | 126 | } |
113 | 127 | ||
114 | static struct input_polled_dev * | ||
115 | rt2x00rfkill_allocate_polldev(struct rt2x00_dev *rt2x00dev) | ||
116 | { | ||
117 | struct input_polled_dev *poll_dev; | ||
118 | |||
119 | poll_dev = input_allocate_polled_device(); | ||
120 | if (!poll_dev) | ||
121 | return NULL; | ||
122 | |||
123 | poll_dev->private = rt2x00dev; | ||
124 | poll_dev->poll = rt2x00rfkill_poll; | ||
125 | poll_dev->poll_interval = RFKILL_POLL_INTERVAL; | ||
126 | |||
127 | poll_dev->input->name = rt2x00dev->ops->name; | ||
128 | poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); | ||
129 | poll_dev->input->id.bustype = BUS_HOST; | ||
130 | poll_dev->input->id.vendor = 0x1814; | ||
131 | poll_dev->input->id.product = rt2x00dev->chip.rt; | ||
132 | poll_dev->input->id.version = rt2x00dev->chip.rev; | ||
133 | poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); | ||
134 | poll_dev->input->evbit[0] = BIT(EV_KEY); | ||
135 | set_bit(KEY_WLAN, poll_dev->input->keybit); | ||
136 | |||
137 | return poll_dev; | ||
138 | } | ||
139 | |||
140 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | 128 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) |
141 | { | 129 | { |
142 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | 130 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) |
@@ -153,14 +141,9 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | |||
153 | rt2x00dev->rfkill->data = rt2x00dev; | 141 | rt2x00dev->rfkill->data = rt2x00dev; |
154 | rt2x00dev->rfkill->state = -1; | 142 | rt2x00dev->rfkill->state = -1; |
155 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; | 143 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; |
144 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; | ||
156 | 145 | ||
157 | rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); | 146 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); |
158 | if (!rt2x00dev->poll_dev) { | ||
159 | ERROR(rt2x00dev, "Failed to allocate polled device.\n"); | ||
160 | rfkill_free(rt2x00dev->rfkill); | ||
161 | rt2x00dev->rfkill = NULL; | ||
162 | return; | ||
163 | } | ||
164 | 147 | ||
165 | return; | 148 | return; |
166 | } | 149 | } |
@@ -171,32 +154,8 @@ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) | |||
171 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | 154 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) |
172 | return; | 155 | return; |
173 | 156 | ||
174 | input_free_polled_device(rt2x00dev->poll_dev); | 157 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); |
175 | rt2x00dev->poll_dev = NULL; | ||
176 | 158 | ||
177 | rfkill_free(rt2x00dev->rfkill); | 159 | rfkill_free(rt2x00dev->rfkill); |
178 | rt2x00dev->rfkill = NULL; | 160 | rt2x00dev->rfkill = NULL; |
179 | } | 161 | } |
180 | |||
181 | void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) | ||
182 | { | ||
183 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || | ||
184 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | ||
185 | return; | ||
186 | |||
187 | input_free_polled_device(rt2x00dev->poll_dev); | ||
188 | rt2x00dev->poll_dev = NULL; | ||
189 | } | ||
190 | |||
191 | void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) | ||
192 | { | ||
193 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || | ||
194 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | ||
195 | return; | ||
196 | |||
197 | rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); | ||
198 | if (!rt2x00dev->poll_dev) { | ||
199 | ERROR(rt2x00dev, "Failed to allocate polled device.\n"); | ||
200 | return; | ||
201 | } | ||
202 | } | ||
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index a0cfb666de0e..3afb49f8866a 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h | |||
@@ -44,17 +44,48 @@ struct rtl8187_rx_hdr { | |||
44 | __le64 mac_time; | 44 | __le64 mac_time; |
45 | } __attribute__((packed)); | 45 | } __attribute__((packed)); |
46 | 46 | ||
47 | struct rtl8187_tx_hdr { | 47 | struct rtl8187b_rx_hdr { |
48 | __le32 flags; | 48 | __le32 flags; |
49 | __le64 mac_time; | ||
50 | u8 noise; | ||
51 | u8 signal; | ||
52 | u8 agc; | ||
53 | u8 reserved; | ||
54 | __le32 unused; | ||
55 | } __attribute__((packed)); | ||
56 | |||
57 | /* {rtl8187,rtl8187b}_tx_info is in skb */ | ||
58 | |||
59 | /* Tx flags are common between rtl8187 and rtl8187b */ | ||
49 | #define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15) | 60 | #define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15) |
50 | #define RTL8187_TX_FLAG_MORE_FRAG (1 << 17) | 61 | #define RTL8187_TX_FLAG_MORE_FRAG (1 << 17) |
51 | #define RTL8187_TX_FLAG_CTS (1 << 18) | 62 | #define RTL8187_TX_FLAG_CTS (1 << 18) |
52 | #define RTL8187_TX_FLAG_RTS (1 << 23) | 63 | #define RTL8187_TX_FLAG_RTS (1 << 23) |
64 | |||
65 | struct rtl8187_tx_hdr { | ||
66 | __le32 flags; | ||
53 | __le16 rts_duration; | 67 | __le16 rts_duration; |
54 | __le16 len; | 68 | __le16 len; |
55 | __le32 retry; | 69 | __le32 retry; |
56 | } __attribute__((packed)); | 70 | } __attribute__((packed)); |
57 | 71 | ||
72 | struct rtl8187b_tx_hdr { | ||
73 | __le32 flags; | ||
74 | __le16 rts_duration; | ||
75 | __le16 len; | ||
76 | __le32 unused_1; | ||
77 | __le16 unused_2; | ||
78 | __le16 tx_duration; | ||
79 | __le32 unused_3; | ||
80 | __le32 retry; | ||
81 | __le32 unused_4[2]; | ||
82 | } __attribute__((packed)); | ||
83 | |||
84 | enum { | ||
85 | DEVICE_RTL8187, | ||
86 | DEVICE_RTL8187B | ||
87 | }; | ||
88 | |||
58 | struct rtl8187_priv { | 89 | struct rtl8187_priv { |
59 | /* common between rtl818x drivers */ | 90 | /* common between rtl818x drivers */ |
60 | struct rtl818x_csr *map; | 91 | struct rtl818x_csr *map; |
@@ -70,70 +101,120 @@ struct rtl8187_priv { | |||
70 | u32 rx_conf; | 101 | u32 rx_conf; |
71 | u16 txpwr_base; | 102 | u16 txpwr_base; |
72 | u8 asic_rev; | 103 | u8 asic_rev; |
104 | u8 is_rtl8187b; | ||
105 | enum { | ||
106 | RTL8187BvB, | ||
107 | RTL8187BvD, | ||
108 | RTL8187BvE | ||
109 | } hw_rev; | ||
73 | struct sk_buff_head rx_queue; | 110 | struct sk_buff_head rx_queue; |
111 | u8 signal; | ||
112 | u8 quality; | ||
113 | u8 noise; | ||
74 | }; | 114 | }; |
75 | 115 | ||
76 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); | 116 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); |
77 | 117 | ||
78 | static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) | 118 | static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, |
119 | u8 *addr, u8 idx) | ||
79 | { | 120 | { |
80 | u8 val; | 121 | u8 val; |
81 | 122 | ||
82 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), | 123 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), |
83 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, | 124 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, |
84 | (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); | 125 | (unsigned long)addr, idx & 0x03, &val, |
126 | sizeof(val), HZ / 2); | ||
85 | 127 | ||
86 | return val; | 128 | return val; |
87 | } | 129 | } |
88 | 130 | ||
89 | static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) | 131 | static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) |
132 | { | ||
133 | return rtl818x_ioread8_idx(priv, addr, 0); | ||
134 | } | ||
135 | |||
136 | static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, | ||
137 | __le16 *addr, u8 idx) | ||
90 | { | 138 | { |
91 | __le16 val; | 139 | __le16 val; |
92 | 140 | ||
93 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), | 141 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), |
94 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, | 142 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, |
95 | (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); | 143 | (unsigned long)addr, idx & 0x03, &val, |
144 | sizeof(val), HZ / 2); | ||
96 | 145 | ||
97 | return le16_to_cpu(val); | 146 | return le16_to_cpu(val); |
98 | } | 147 | } |
99 | 148 | ||
100 | static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) | 149 | static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) |
150 | { | ||
151 | return rtl818x_ioread16_idx(priv, addr, 0); | ||
152 | } | ||
153 | |||
154 | static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, | ||
155 | __le32 *addr, u8 idx) | ||
101 | { | 156 | { |
102 | __le32 val; | 157 | __le32 val; |
103 | 158 | ||
104 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), | 159 | usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), |
105 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, | 160 | RTL8187_REQ_GET_REG, RTL8187_REQT_READ, |
106 | (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); | 161 | (unsigned long)addr, idx & 0x03, &val, |
162 | sizeof(val), HZ / 2); | ||
107 | 163 | ||
108 | return le32_to_cpu(val); | 164 | return le32_to_cpu(val); |
109 | } | 165 | } |
110 | 166 | ||
111 | static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, | 167 | static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) |
112 | u8 *addr, u8 val) | 168 | { |
169 | return rtl818x_ioread32_idx(priv, addr, 0); | ||
170 | } | ||
171 | |||
172 | static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, | ||
173 | u8 *addr, u8 val, u8 idx) | ||
113 | { | 174 | { |
114 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), | 175 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), |
115 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, | 176 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, |
116 | (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); | 177 | (unsigned long)addr, idx & 0x03, &val, |
178 | sizeof(val), HZ / 2); | ||
179 | } | ||
180 | |||
181 | static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) | ||
182 | { | ||
183 | rtl818x_iowrite8_idx(priv, addr, val, 0); | ||
117 | } | 184 | } |
118 | 185 | ||
119 | static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, | 186 | static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, |
120 | __le16 *addr, u16 val) | 187 | __le16 *addr, u16 val, u8 idx) |
121 | { | 188 | { |
122 | __le16 buf = cpu_to_le16(val); | 189 | __le16 buf = cpu_to_le16(val); |
123 | 190 | ||
124 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), | 191 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), |
125 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, | 192 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, |
126 | (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); | 193 | (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), |
194 | HZ / 2); | ||
127 | } | 195 | } |
128 | 196 | ||
129 | static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, | 197 | static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, |
130 | __le32 *addr, u32 val) | 198 | u16 val) |
199 | { | ||
200 | rtl818x_iowrite16_idx(priv, addr, val, 0); | ||
201 | } | ||
202 | |||
203 | static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, | ||
204 | __le32 *addr, u32 val, u8 idx) | ||
131 | { | 205 | { |
132 | __le32 buf = cpu_to_le32(val); | 206 | __le32 buf = cpu_to_le32(val); |
133 | 207 | ||
134 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), | 208 | usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), |
135 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, | 209 | RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, |
136 | (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); | 210 | (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), |
211 | HZ / 2); | ||
212 | } | ||
213 | |||
214 | static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, | ||
215 | u32 val) | ||
216 | { | ||
217 | rtl818x_iowrite32_idx(priv, addr, val, 0); | ||
137 | } | 218 | } |
138 | 219 | ||
139 | #endif /* RTL8187_H */ | 220 | #endif /* RTL8187_H */ |
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index bec96d762c6c..33527e58256f 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c | |||
@@ -27,19 +27,21 @@ | |||
27 | 27 | ||
28 | MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); | 28 | MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); |
29 | MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); | 29 | MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); |
30 | MODULE_DESCRIPTION("RTL8187 USB wireless driver"); | 30 | MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
33 | static struct usb_device_id rtl8187_table[] __devinitdata = { | 33 | static struct usb_device_id rtl8187_table[] __devinitdata = { |
34 | /* Realtek */ | 34 | /* Realtek */ |
35 | {USB_DEVICE(0x0bda, 0x8187)}, | 35 | {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, |
36 | {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, | ||
37 | {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, | ||
36 | /* Netgear */ | 38 | /* Netgear */ |
37 | {USB_DEVICE(0x0846, 0x6100)}, | 39 | {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, |
38 | {USB_DEVICE(0x0846, 0x6a00)}, | 40 | {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, |
39 | /* HP */ | 41 | /* HP */ |
40 | {USB_DEVICE(0x03f0, 0xca02)}, | 42 | {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, |
41 | /* Sitecom */ | 43 | /* Sitecom */ |
42 | {USB_DEVICE(0x0df6, 0x000d)}, | 44 | {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, |
43 | {} | 45 | {} |
44 | }; | 46 | }; |
45 | 47 | ||
@@ -153,9 +155,11 @@ static void rtl8187_tx_cb(struct urb *urb) | |||
153 | struct sk_buff *skb = (struct sk_buff *)urb->context; | 155 | struct sk_buff *skb = (struct sk_buff *)urb->context; |
154 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 156 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
155 | struct ieee80211_hw *hw = info->driver_data[0]; | 157 | struct ieee80211_hw *hw = info->driver_data[0]; |
158 | struct rtl8187_priv *priv = hw->priv; | ||
156 | 159 | ||
157 | usb_free_urb(info->driver_data[1]); | 160 | usb_free_urb(info->driver_data[1]); |
158 | skb_pull(skb, sizeof(struct rtl8187_tx_hdr)); | 161 | skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : |
162 | sizeof(struct rtl8187_tx_hdr)); | ||
159 | memset(&info->status, 0, sizeof(info->status)); | 163 | memset(&info->status, 0, sizeof(info->status)); |
160 | info->flags |= IEEE80211_TX_STAT_ACK; | 164 | info->flags |= IEEE80211_TX_STAT_ACK; |
161 | ieee80211_tx_status_irqsafe(hw, skb); | 165 | ieee80211_tx_status_irqsafe(hw, skb); |
@@ -165,7 +169,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
165 | { | 169 | { |
166 | struct rtl8187_priv *priv = dev->priv; | 170 | struct rtl8187_priv *priv = dev->priv; |
167 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 171 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
168 | struct rtl8187_tx_hdr *hdr; | 172 | unsigned int ep; |
173 | void *buf; | ||
169 | struct urb *urb; | 174 | struct urb *urb; |
170 | __le16 rts_dur = 0; | 175 | __le16 rts_dur = 0; |
171 | u32 flags; | 176 | u32 flags; |
@@ -193,16 +198,47 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
193 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; | 198 | flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; |
194 | } | 199 | } |
195 | 200 | ||
196 | hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); | 201 | if (!priv->is_rtl8187b) { |
197 | hdr->flags = cpu_to_le32(flags); | 202 | struct rtl8187_tx_hdr *hdr = |
198 | hdr->len = 0; | 203 | (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); |
199 | hdr->rts_duration = rts_dur; | 204 | hdr->flags = cpu_to_le32(flags); |
200 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | 205 | hdr->len = 0; |
206 | hdr->rts_duration = rts_dur; | ||
207 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | ||
208 | buf = hdr; | ||
209 | |||
210 | ep = 2; | ||
211 | } else { | ||
212 | /* fc needs to be calculated before skb_push() */ | ||
213 | unsigned int epmap[4] = { 6, 7, 5, 4 }; | ||
214 | struct ieee80211_hdr *tx_hdr = | ||
215 | (struct ieee80211_hdr *)(skb->data); | ||
216 | u16 fc = le16_to_cpu(tx_hdr->frame_control); | ||
217 | |||
218 | struct rtl8187b_tx_hdr *hdr = | ||
219 | (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); | ||
220 | struct ieee80211_rate *txrate = | ||
221 | ieee80211_get_tx_rate(dev, info); | ||
222 | memset(hdr, 0, sizeof(*hdr)); | ||
223 | hdr->flags = cpu_to_le32(flags); | ||
224 | hdr->rts_duration = rts_dur; | ||
225 | hdr->retry = cpu_to_le32(info->control.retry_limit << 8); | ||
226 | hdr->tx_duration = | ||
227 | ieee80211_generic_frame_duration(dev, priv->vif, | ||
228 | skb->len, txrate); | ||
229 | buf = hdr; | ||
230 | |||
231 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) | ||
232 | ep = 12; | ||
233 | else | ||
234 | ep = epmap[skb_get_queue_mapping(skb)]; | ||
235 | } | ||
201 | 236 | ||
202 | info->driver_data[0] = dev; | 237 | info->driver_data[0] = dev; |
203 | info->driver_data[1] = urb; | 238 | info->driver_data[1] = urb; |
204 | usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), | 239 | |
205 | hdr, skb->len, rtl8187_tx_cb, skb); | 240 | usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), |
241 | buf, skb->len, rtl8187_tx_cb, skb); | ||
206 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 242 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
207 | if (rc < 0) { | 243 | if (rc < 0) { |
208 | usb_free_urb(urb); | 244 | usb_free_urb(urb); |
@@ -218,7 +254,6 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
218 | struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; | 254 | struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; |
219 | struct ieee80211_hw *dev = info->dev; | 255 | struct ieee80211_hw *dev = info->dev; |
220 | struct rtl8187_priv *priv = dev->priv; | 256 | struct rtl8187_priv *priv = dev->priv; |
221 | struct rtl8187_rx_hdr *hdr; | ||
222 | struct ieee80211_rx_status rx_status = { 0 }; | 257 | struct ieee80211_rx_status rx_status = { 0 }; |
223 | int rate, signal; | 258 | int rate, signal; |
224 | u32 flags; | 259 | u32 flags; |
@@ -239,11 +274,33 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
239 | } | 274 | } |
240 | 275 | ||
241 | skb_put(skb, urb->actual_length); | 276 | skb_put(skb, urb->actual_length); |
242 | hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); | 277 | if (!priv->is_rtl8187b) { |
243 | flags = le32_to_cpu(hdr->flags); | 278 | struct rtl8187_rx_hdr *hdr = |
244 | skb_trim(skb, flags & 0x0FFF); | 279 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
280 | flags = le32_to_cpu(hdr->flags); | ||
281 | signal = hdr->signal & 0x7f; | ||
282 | rx_status.antenna = (hdr->signal >> 7) & 1; | ||
283 | rx_status.signal = signal; | ||
284 | rx_status.noise = hdr->noise; | ||
285 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
286 | priv->signal = signal; | ||
287 | priv->quality = signal; | ||
288 | priv->noise = hdr->noise; | ||
289 | } else { | ||
290 | struct rtl8187b_rx_hdr *hdr = | ||
291 | (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); | ||
292 | flags = le32_to_cpu(hdr->flags); | ||
293 | signal = hdr->agc >> 1; | ||
294 | rx_status.antenna = (hdr->signal >> 7) & 1; | ||
295 | rx_status.signal = 64 - min(hdr->noise, (u8)64); | ||
296 | rx_status.noise = hdr->noise; | ||
297 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
298 | priv->signal = hdr->signal; | ||
299 | priv->quality = hdr->agc >> 1; | ||
300 | priv->noise = hdr->noise; | ||
301 | } | ||
245 | 302 | ||
246 | signal = hdr->agc >> 1; | 303 | skb_trim(skb, flags & 0x0FFF); |
247 | rate = (flags >> 20) & 0xF; | 304 | rate = (flags >> 20) & 0xF; |
248 | if (rate > 3) { /* OFDM rate */ | 305 | if (rate > 3) { /* OFDM rate */ |
249 | if (signal > 90) | 306 | if (signal > 90) |
@@ -259,13 +316,11 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
259 | signal = 95 - signal; | 316 | signal = 95 - signal; |
260 | } | 317 | } |
261 | 318 | ||
262 | rx_status.antenna = (hdr->signal >> 7) & 1; | 319 | rx_status.qual = priv->quality; |
263 | rx_status.qual = 64 - min(hdr->noise, (u8)64); | ||
264 | rx_status.signal = signal; | 320 | rx_status.signal = signal; |
265 | rx_status.rate_idx = rate; | 321 | rx_status.rate_idx = rate; |
266 | rx_status.freq = dev->conf.channel->center_freq; | 322 | rx_status.freq = dev->conf.channel->center_freq; |
267 | rx_status.band = dev->conf.channel->band; | 323 | rx_status.band = dev->conf.channel->band; |
268 | rx_status.mactime = le64_to_cpu(hdr->mac_time); | ||
269 | rx_status.flag |= RX_FLAG_TSFT; | 324 | rx_status.flag |= RX_FLAG_TSFT; |
270 | if (flags & (1 << 13)) | 325 | if (flags & (1 << 13)) |
271 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 326 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
@@ -305,7 +360,8 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) | |||
305 | break; | 360 | break; |
306 | } | 361 | } |
307 | usb_fill_bulk_urb(entry, priv->udev, | 362 | usb_fill_bulk_urb(entry, priv->udev, |
308 | usb_rcvbulkpipe(priv->udev, 1), | 363 | usb_rcvbulkpipe(priv->udev, |
364 | priv->is_rtl8187b ? 3 : 1), | ||
309 | skb_tail_pointer(skb), | 365 | skb_tail_pointer(skb), |
310 | RTL8187_MAX_RX, rtl8187_rx_cb, skb); | 366 | RTL8187_MAX_RX, rtl8187_rx_cb, skb); |
311 | info = (struct rtl8187_rx_info *)skb->cb; | 367 | info = (struct rtl8187_rx_info *)skb->cb; |
@@ -318,29 +374,12 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) | |||
318 | return 0; | 374 | return 0; |
319 | } | 375 | } |
320 | 376 | ||
321 | static int rtl8187_init_hw(struct ieee80211_hw *dev) | 377 | static int rtl8187_cmd_reset(struct ieee80211_hw *dev) |
322 | { | 378 | { |
323 | struct rtl8187_priv *priv = dev->priv; | 379 | struct rtl8187_priv *priv = dev->priv; |
324 | u8 reg; | 380 | u8 reg; |
325 | int i; | 381 | int i; |
326 | 382 | ||
327 | /* reset */ | ||
328 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | ||
329 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | ||
330 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
331 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); | ||
332 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | ||
333 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
334 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | ||
335 | |||
336 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | ||
337 | |||
338 | msleep(200); | ||
339 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); | ||
340 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); | ||
341 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); | ||
342 | msleep(200); | ||
343 | |||
344 | reg = rtl818x_ioread8(priv, &priv->map->CMD); | 383 | reg = rtl818x_ioread8(priv, &priv->map->CMD); |
345 | reg &= (1 << 1); | 384 | reg &= (1 << 1); |
346 | reg |= RTL818X_CMD_RESET; | 385 | reg |= RTL818X_CMD_RESET; |
@@ -376,12 +415,48 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
376 | return -ETIMEDOUT; | 415 | return -ETIMEDOUT; |
377 | } | 416 | } |
378 | 417 | ||
418 | return 0; | ||
419 | } | ||
420 | |||
421 | static int rtl8187_init_hw(struct ieee80211_hw *dev) | ||
422 | { | ||
423 | struct rtl8187_priv *priv = dev->priv; | ||
424 | u8 reg; | ||
425 | int res; | ||
426 | |||
427 | /* reset */ | ||
428 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
429 | RTL818X_EEPROM_CMD_CONFIG); | ||
430 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | ||
431 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | | ||
432 | RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
433 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); | ||
434 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | ||
435 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & | ||
436 | ~RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
437 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
438 | RTL818X_EEPROM_CMD_NORMAL); | ||
439 | |||
440 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | ||
441 | |||
442 | msleep(200); | ||
443 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); | ||
444 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); | ||
445 | rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); | ||
446 | msleep(200); | ||
447 | |||
448 | res = rtl8187_cmd_reset(dev); | ||
449 | if (res) | ||
450 | return res; | ||
451 | |||
379 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 452 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
380 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 453 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
381 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 454 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
455 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
382 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); | 456 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); |
383 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 457 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); |
384 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 458 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
459 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
385 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 460 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
386 | 461 | ||
387 | /* setup card */ | 462 | /* setup card */ |
@@ -426,9 +501,11 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
426 | rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); | 501 | rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); |
427 | rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); | 502 | rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); |
428 | rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); | 503 | rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); |
429 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 504 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, |
505 | RTL818X_EEPROM_CMD_CONFIG); | ||
430 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); | 506 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); |
431 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 507 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, |
508 | RTL818X_EEPROM_CMD_NORMAL); | ||
432 | rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); | 509 | rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); |
433 | msleep(100); | 510 | msleep(100); |
434 | 511 | ||
@@ -445,16 +522,198 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) | |||
445 | return 0; | 522 | return 0; |
446 | } | 523 | } |
447 | 524 | ||
525 | static const u8 rtl8187b_reg_table[][3] = { | ||
526 | {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, | ||
527 | {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, | ||
528 | {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, | ||
529 | {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, | ||
530 | |||
531 | {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, | ||
532 | {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, | ||
533 | {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, | ||
534 | {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, | ||
535 | {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, | ||
536 | {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, | ||
537 | |||
538 | {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, | ||
539 | {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, | ||
540 | {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, | ||
541 | {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, | ||
542 | {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, | ||
543 | {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, | ||
544 | {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, | ||
545 | {0x73, 0x9A, 2}, | ||
546 | |||
547 | {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, | ||
548 | {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, | ||
549 | {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, | ||
550 | {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, | ||
551 | {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, | ||
552 | |||
553 | {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, | ||
554 | {0x8E, 0x08, 0}, {0x8F, 0x00, 0} | ||
555 | }; | ||
556 | |||
557 | static int rtl8187b_init_hw(struct ieee80211_hw *dev) | ||
558 | { | ||
559 | struct rtl8187_priv *priv = dev->priv; | ||
560 | int res, i; | ||
561 | u8 reg; | ||
562 | |||
563 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
564 | RTL818X_EEPROM_CMD_CONFIG); | ||
565 | |||
566 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | ||
567 | reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; | ||
568 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); | ||
569 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52); | ||
570 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658); | ||
571 | rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0); | ||
572 | |||
573 | rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); | ||
574 | reg = rtl818x_ioread8(priv, (u8 *)0xFF62); | ||
575 | rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); | ||
576 | rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); | ||
577 | |||
578 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | ||
579 | reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; | ||
580 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); | ||
581 | |||
582 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
583 | RTL818X_EEPROM_CMD_NORMAL); | ||
584 | |||
585 | res = rtl8187_cmd_reset(dev); | ||
586 | if (res) | ||
587 | return res; | ||
588 | |||
589 | rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); | ||
590 | reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); | ||
591 | reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; | ||
592 | rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); | ||
593 | reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); | ||
594 | reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | | ||
595 | RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; | ||
596 | rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); | ||
597 | |||
598 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); | ||
599 | reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK); | ||
600 | reg |= RTL818X_RATE_FALLBACK_ENABLE; | ||
601 | rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg); | ||
602 | |||
603 | rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); | ||
604 | rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); | ||
605 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); | ||
606 | |||
607 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
608 | RTL818X_EEPROM_CMD_CONFIG); | ||
609 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); | ||
610 | rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); | ||
611 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
612 | RTL818X_EEPROM_CMD_NORMAL); | ||
613 | |||
614 | rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); | ||
615 | for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { | ||
616 | rtl818x_iowrite8_idx(priv, | ||
617 | (u8 *)(uintptr_t) | ||
618 | (rtl8187b_reg_table[i][0] | 0xFF00), | ||
619 | rtl8187b_reg_table[i][1], | ||
620 | rtl8187b_reg_table[i][2]); | ||
621 | } | ||
622 | |||
623 | rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); | ||
624 | rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); | ||
625 | |||
626 | rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); | ||
627 | rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); | ||
628 | rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); | ||
629 | |||
630 | rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); | ||
631 | |||
632 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); | ||
633 | |||
634 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
635 | RTL818X_EEPROM_CMD_CONFIG); | ||
636 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | ||
637 | reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; | ||
638 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); | ||
639 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, | ||
640 | RTL818X_EEPROM_CMD_NORMAL); | ||
641 | |||
642 | rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); | ||
643 | rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); | ||
644 | rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); | ||
645 | msleep(1100); | ||
646 | |||
647 | priv->rf->init(dev); | ||
648 | |||
649 | reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; | ||
650 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); | ||
651 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); | ||
652 | |||
653 | rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); | ||
654 | rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); | ||
655 | rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); | ||
656 | rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); | ||
657 | rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); | ||
658 | rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); | ||
659 | rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); | ||
660 | |||
661 | reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); | ||
662 | rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); | ||
663 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); | ||
664 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); | ||
665 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); | ||
666 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); | ||
667 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); | ||
668 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); | ||
669 | rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); | ||
670 | rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); | ||
671 | rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); | ||
672 | rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); | ||
673 | rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); | ||
674 | |||
675 | rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); | ||
676 | |||
677 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); | ||
678 | |||
679 | return 0; | ||
680 | } | ||
681 | |||
448 | static int rtl8187_start(struct ieee80211_hw *dev) | 682 | static int rtl8187_start(struct ieee80211_hw *dev) |
449 | { | 683 | { |
450 | struct rtl8187_priv *priv = dev->priv; | 684 | struct rtl8187_priv *priv = dev->priv; |
451 | u32 reg; | 685 | u32 reg; |
452 | int ret; | 686 | int ret; |
453 | 687 | ||
454 | ret = rtl8187_init_hw(dev); | 688 | ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : |
689 | rtl8187b_init_hw(dev); | ||
455 | if (ret) | 690 | if (ret) |
456 | return ret; | 691 | return ret; |
457 | 692 | ||
693 | if (priv->is_rtl8187b) { | ||
694 | reg = RTL818X_RX_CONF_MGMT | | ||
695 | RTL818X_RX_CONF_DATA | | ||
696 | RTL818X_RX_CONF_BROADCAST | | ||
697 | RTL818X_RX_CONF_NICMAC | | ||
698 | RTL818X_RX_CONF_BSSID | | ||
699 | (7 << 13 /* RX FIFO threshold NONE */) | | ||
700 | (7 << 10 /* MAX RX DMA */) | | ||
701 | RTL818X_RX_CONF_RX_AUTORESETPHY | | ||
702 | RTL818X_RX_CONF_ONLYERLPKT | | ||
703 | RTL818X_RX_CONF_MULTICAST; | ||
704 | priv->rx_conf = reg; | ||
705 | rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); | ||
706 | |||
707 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, | ||
708 | RTL818X_TX_CONF_HW_SEQNUM | | ||
709 | RTL818X_TX_CONF_DISREQQSIZE | | ||
710 | (7 << 8 /* short retry limit */) | | ||
711 | (7 << 0 /* long retry limit */) | | ||
712 | (7 << 21 /* MAX TX DMA */)); | ||
713 | rtl8187_init_urbs(dev); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
458 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); | 717 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); |
459 | 718 | ||
460 | rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); | 719 | rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); |
@@ -581,18 +840,20 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) | |||
581 | msleep(10); | 840 | msleep(10); |
582 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); | 841 | rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); |
583 | 842 | ||
584 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | 843 | if (!priv->is_rtl8187b) { |
585 | 844 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | |
586 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { | 845 | |
587 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); | 846 | if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { |
588 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); | 847 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); |
589 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); | 848 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); |
590 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); | 849 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); |
591 | } else { | 850 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); |
592 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); | 851 | } else { |
593 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); | 852 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); |
594 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); | 853 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); |
595 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | 854 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); |
855 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | ||
856 | } | ||
596 | } | 857 | } |
597 | 858 | ||
598 | rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); | 859 | rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); |
@@ -608,14 +869,20 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, | |||
608 | { | 869 | { |
609 | struct rtl8187_priv *priv = dev->priv; | 870 | struct rtl8187_priv *priv = dev->priv; |
610 | int i; | 871 | int i; |
872 | u8 reg; | ||
611 | 873 | ||
612 | for (i = 0; i < ETH_ALEN; i++) | 874 | for (i = 0; i < ETH_ALEN; i++) |
613 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); | 875 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); |
614 | 876 | ||
615 | if (is_valid_ether_addr(conf->bssid)) | 877 | if (is_valid_ether_addr(conf->bssid)) { |
616 | rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); | 878 | reg = RTL818X_MSR_INFRA; |
617 | else | 879 | if (priv->is_rtl8187b) |
618 | rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); | 880 | reg |= RTL818X_MSR_ENEDCA; |
881 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
882 | } else { | ||
883 | reg = RTL818X_MSR_NO_LINK; | ||
884 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
885 | } | ||
619 | 886 | ||
620 | return 0; | 887 | return 0; |
621 | } | 888 | } |
@@ -702,6 +969,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
702 | struct rtl8187_priv *priv; | 969 | struct rtl8187_priv *priv; |
703 | struct eeprom_93cx6 eeprom; | 970 | struct eeprom_93cx6 eeprom; |
704 | struct ieee80211_channel *channel; | 971 | struct ieee80211_channel *channel; |
972 | const char *chip_name; | ||
705 | u16 txpwr, reg; | 973 | u16 txpwr, reg; |
706 | int err, i; | 974 | int err, i; |
707 | DECLARE_MAC_BUF(mac); | 975 | DECLARE_MAC_BUF(mac); |
@@ -713,6 +981,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
713 | } | 981 | } |
714 | 982 | ||
715 | priv = dev->priv; | 983 | priv = dev->priv; |
984 | priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); | ||
716 | 985 | ||
717 | SET_IEEE80211_DEV(dev, &intf->dev); | 986 | SET_IEEE80211_DEV(dev, &intf->dev); |
718 | usb_set_intfdata(intf, dev); | 987 | usb_set_intfdata(intf, dev); |
@@ -741,8 +1010,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
741 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1010 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
742 | IEEE80211_HW_RX_INCLUDES_FCS | | 1011 | IEEE80211_HW_RX_INCLUDES_FCS | |
743 | IEEE80211_HW_SIGNAL_UNSPEC; | 1012 | IEEE80211_HW_SIGNAL_UNSPEC; |
744 | dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); | ||
745 | dev->queues = 1; | ||
746 | dev->max_signal = 65; | 1013 | dev->max_signal = 65; |
747 | 1014 | ||
748 | eeprom.data = dev; | 1015 | eeprom.data = dev; |
@@ -777,12 +1044,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
777 | (*channel++).hw_value = txpwr & 0xFF; | 1044 | (*channel++).hw_value = txpwr & 0xFF; |
778 | (*channel++).hw_value = txpwr >> 8; | 1045 | (*channel++).hw_value = txpwr >> 8; |
779 | } | 1046 | } |
780 | for (i = 0; i < 2; i++) { | ||
781 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, | ||
782 | &txpwr); | ||
783 | (*channel++).hw_value = txpwr & 0xFF; | ||
784 | (*channel++).hw_value = txpwr >> 8; | ||
785 | } | ||
786 | 1047 | ||
787 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, | 1048 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, |
788 | &priv->txpwr_base); | 1049 | &priv->txpwr_base); |
@@ -796,7 +1057,90 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
796 | rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); | 1057 | rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); |
797 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1058 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
798 | 1059 | ||
1060 | if (!priv->is_rtl8187b) { | ||
1061 | u32 reg32; | ||
1062 | reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); | ||
1063 | reg32 &= RTL818X_TX_CONF_HWVER_MASK; | ||
1064 | switch (reg32) { | ||
1065 | case RTL818X_TX_CONF_R8187vD_B: | ||
1066 | /* Some RTL8187B devices have a USB ID of 0x8187 | ||
1067 | * detect them here */ | ||
1068 | chip_name = "RTL8187BvB(early)"; | ||
1069 | priv->is_rtl8187b = 1; | ||
1070 | priv->hw_rev = RTL8187BvB; | ||
1071 | break; | ||
1072 | case RTL818X_TX_CONF_R8187vD: | ||
1073 | chip_name = "RTL8187vD"; | ||
1074 | break; | ||
1075 | default: | ||
1076 | chip_name = "RTL8187vB (default)"; | ||
1077 | } | ||
1078 | } else { | ||
1079 | /* | ||
1080 | * Force USB request to write radio registers for 8187B, Realtek | ||
1081 | * only uses it in their sources | ||
1082 | */ | ||
1083 | /*if (priv->asic_rev == 0) { | ||
1084 | printk(KERN_WARNING "rtl8187: Forcing use of USB " | ||
1085 | "requests to write to radio registers\n"); | ||
1086 | priv->asic_rev = 1; | ||
1087 | }*/ | ||
1088 | switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { | ||
1089 | case RTL818X_R8187B_B: | ||
1090 | chip_name = "RTL8187BvB"; | ||
1091 | priv->hw_rev = RTL8187BvB; | ||
1092 | break; | ||
1093 | case RTL818X_R8187B_D: | ||
1094 | chip_name = "RTL8187BvD"; | ||
1095 | priv->hw_rev = RTL8187BvD; | ||
1096 | break; | ||
1097 | case RTL818X_R8187B_E: | ||
1098 | chip_name = "RTL8187BvE"; | ||
1099 | priv->hw_rev = RTL8187BvE; | ||
1100 | break; | ||
1101 | default: | ||
1102 | chip_name = "RTL8187BvB (default)"; | ||
1103 | priv->hw_rev = RTL8187BvB; | ||
1104 | } | ||
1105 | } | ||
1106 | |||
1107 | if (!priv->is_rtl8187b) { | ||
1108 | for (i = 0; i < 2; i++) { | ||
1109 | eeprom_93cx6_read(&eeprom, | ||
1110 | RTL8187_EEPROM_TXPWR_CHAN_6 + i, | ||
1111 | &txpwr); | ||
1112 | (*channel++).hw_value = txpwr & 0xFF; | ||
1113 | (*channel++).hw_value = txpwr >> 8; | ||
1114 | } | ||
1115 | } else { | ||
1116 | eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, | ||
1117 | &txpwr); | ||
1118 | (*channel++).hw_value = txpwr & 0xFF; | ||
1119 | |||
1120 | eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); | ||
1121 | (*channel++).hw_value = txpwr & 0xFF; | ||
1122 | |||
1123 | eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); | ||
1124 | (*channel++).hw_value = txpwr & 0xFF; | ||
1125 | (*channel++).hw_value = txpwr >> 8; | ||
1126 | } | ||
1127 | |||
1128 | if (priv->is_rtl8187b) | ||
1129 | printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " | ||
1130 | "is EXPERIMENTAL, and could damage your\n" | ||
1131 | " hardware, use at your own risk\n"); | ||
1132 | if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) | ||
1133 | printk(KERN_INFO "rtl8187: inconsistency between id with OEM" | ||
1134 | " info!\n"); | ||
1135 | |||
799 | priv->rf = rtl8187_detect_rf(dev); | 1136 | priv->rf = rtl8187_detect_rf(dev); |
1137 | dev->extra_tx_headroom = (!priv->is_rtl8187b) ? | ||
1138 | sizeof(struct rtl8187_tx_hdr) : | ||
1139 | sizeof(struct rtl8187b_tx_hdr); | ||
1140 | if (!priv->is_rtl8187b) | ||
1141 | dev->queues = 1; | ||
1142 | else | ||
1143 | dev->queues = 4; | ||
800 | 1144 | ||
801 | err = ieee80211_register_hw(dev); | 1145 | err = ieee80211_register_hw(dev); |
802 | if (err) { | 1146 | if (err) { |
@@ -804,9 +1148,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
804 | goto err_free_dev; | 1148 | goto err_free_dev; |
805 | } | 1149 | } |
806 | 1150 | ||
807 | printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", | 1151 | printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", |
808 | wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), | 1152 | wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), |
809 | priv->asic_rev, priv->rf->name); | 1153 | chip_name, priv->asic_rev, priv->rf->name); |
810 | 1154 | ||
811 | return 0; | 1155 | return 0; |
812 | 1156 | ||
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index 9146387b4c5e..1e059de97116 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c | |||
@@ -305,9 +305,11 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | |||
305 | /* anaparam2 on */ | 305 | /* anaparam2 on */ |
306 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 306 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
307 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 307 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
308 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 308 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
309 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
309 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 310 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); |
310 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 311 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
312 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
311 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 313 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
312 | 314 | ||
313 | rtl8225_write_phy_ofdm(dev, 2, 0x42); | 315 | rtl8225_write_phy_ofdm(dev, 2, 0x42); |
@@ -471,12 +473,42 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) | |||
471 | rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); | 473 | rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); |
472 | } | 474 | } |
473 | 475 | ||
476 | static const u8 rtl8225z2_agc[] = { | ||
477 | 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, | ||
478 | 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, | ||
479 | 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, | ||
480 | 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, | ||
481 | 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
482 | 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, | ||
483 | 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, | ||
484 | 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, | ||
485 | 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, | ||
486 | 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, | ||
487 | 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 | ||
488 | }; | ||
489 | static const u8 rtl8225z2_ofdm[] = { | ||
490 | 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, | ||
491 | 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, | ||
492 | 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, | ||
493 | 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, | ||
494 | 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, | ||
495 | 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, | ||
496 | 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, | ||
497 | 0x6d, 0x3c, 0xfb, 0x07 | ||
498 | }; | ||
499 | |||
474 | static const u8 rtl8225z2_tx_power_cck_ch14[] = { | 500 | static const u8 rtl8225z2_tx_power_cck_ch14[] = { |
475 | 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 | 501 | 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, |
502 | 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, | ||
503 | 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, | ||
504 | 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 | ||
476 | }; | 505 | }; |
477 | 506 | ||
478 | static const u8 rtl8225z2_tx_power_cck[] = { | 507 | static const u8 rtl8225z2_tx_power_cck[] = { |
479 | 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 | 508 | 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, |
509 | 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, | ||
510 | 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, | ||
511 | 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 | ||
480 | }; | 512 | }; |
481 | 513 | ||
482 | static const u8 rtl8225z2_tx_power_ofdm[] = { | 514 | static const u8 rtl8225z2_tx_power_ofdm[] = { |
@@ -526,9 +558,11 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | |||
526 | /* anaparam2 on */ | 558 | /* anaparam2 on */ |
527 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 559 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
528 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); | 560 | reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); |
529 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | 561 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
562 | reg | RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
530 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); | 563 | rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); |
531 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | 564 | rtl818x_iowrite8(priv, &priv->map->CONFIG3, |
565 | reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); | ||
532 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 566 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
533 | 567 | ||
534 | rtl8225_write_phy_ofdm(dev, 2, 0x42); | 568 | rtl8225_write_phy_ofdm(dev, 2, 0x42); |
@@ -542,6 +576,85 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | |||
542 | msleep(1); | 576 | msleep(1); |
543 | } | 577 | } |
544 | 578 | ||
579 | static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) | ||
580 | { | ||
581 | struct rtl8187_priv *priv = dev->priv; | ||
582 | u8 cck_power, ofdm_power; | ||
583 | const u8 *tmp; | ||
584 | int i; | ||
585 | |||
586 | cck_power = priv->channels[channel - 1].hw_value & 0xF; | ||
587 | ofdm_power = priv->channels[channel - 1].hw_value >> 4; | ||
588 | |||
589 | if (cck_power > 15) | ||
590 | cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; | ||
591 | else | ||
592 | cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; | ||
593 | cck_power += priv->txpwr_base & 0xF; | ||
594 | cck_power = min(cck_power, (u8)35); | ||
595 | |||
596 | if (ofdm_power > 15) | ||
597 | ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; | ||
598 | else | ||
599 | ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; | ||
600 | ofdm_power += (priv->txpwr_base >> 4) & 0xF; | ||
601 | ofdm_power = min(ofdm_power, (u8)35); | ||
602 | |||
603 | if (channel == 14) | ||
604 | tmp = rtl8225z2_tx_power_cck_ch14; | ||
605 | else | ||
606 | tmp = rtl8225z2_tx_power_cck; | ||
607 | |||
608 | if (priv->hw_rev == RTL8187BvB) { | ||
609 | if (cck_power <= 6) | ||
610 | ; /* do nothing */ | ||
611 | else if (cck_power <= 11) | ||
612 | tmp += 8; | ||
613 | else | ||
614 | tmp += 16; | ||
615 | } else { | ||
616 | if (cck_power <= 5) | ||
617 | ; /* do nothing */ | ||
618 | else if (cck_power <= 11) | ||
619 | tmp += 8; | ||
620 | else if (cck_power <= 17) | ||
621 | tmp += 16; | ||
622 | else | ||
623 | tmp += 24; | ||
624 | } | ||
625 | |||
626 | for (i = 0; i < 8; i++) | ||
627 | rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); | ||
628 | |||
629 | rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, | ||
630 | rtl8225z2_tx_gain_cck_ofdm[cck_power]); | ||
631 | msleep(1); | ||
632 | |||
633 | rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, | ||
634 | rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); | ||
635 | if (priv->hw_rev == RTL8187BvB) { | ||
636 | if (ofdm_power <= 11) { | ||
637 | rtl8225_write_phy_ofdm(dev, 0x87, 0x60); | ||
638 | rtl8225_write_phy_ofdm(dev, 0x89, 0x60); | ||
639 | } else { | ||
640 | rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); | ||
641 | rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); | ||
642 | } | ||
643 | } else { | ||
644 | if (ofdm_power <= 11) { | ||
645 | rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); | ||
646 | rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); | ||
647 | } else if (ofdm_power <= 17) { | ||
648 | rtl8225_write_phy_ofdm(dev, 0x87, 0x54); | ||
649 | rtl8225_write_phy_ofdm(dev, 0x89, 0x54); | ||
650 | } else { | ||
651 | rtl8225_write_phy_ofdm(dev, 0x87, 0x50); | ||
652 | rtl8225_write_phy_ofdm(dev, 0x89, 0x50); | ||
653 | } | ||
654 | } | ||
655 | msleep(1); | ||
656 | } | ||
657 | |||
545 | static const u16 rtl8225z2_rxgain[] = { | 658 | static const u16 rtl8225z2_rxgain[] = { |
546 | 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, | 659 | 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, |
547 | 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, | 660 | 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, |
@@ -715,6 +828,81 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) | |||
715 | rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); | 828 | rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); |
716 | } | 829 | } |
717 | 830 | ||
831 | static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) | ||
832 | { | ||
833 | struct rtl8187_priv *priv = dev->priv; | ||
834 | int i; | ||
835 | |||
836 | rtl8225_write(dev, 0x0, 0x0B7); msleep(1); | ||
837 | rtl8225_write(dev, 0x1, 0xEE0); msleep(1); | ||
838 | rtl8225_write(dev, 0x2, 0x44D); msleep(1); | ||
839 | rtl8225_write(dev, 0x3, 0x441); msleep(1); | ||
840 | rtl8225_write(dev, 0x4, 0x8C3); msleep(1); | ||
841 | rtl8225_write(dev, 0x5, 0xC72); msleep(1); | ||
842 | rtl8225_write(dev, 0x6, 0x0E6); msleep(1); | ||
843 | rtl8225_write(dev, 0x7, 0x82A); msleep(1); | ||
844 | rtl8225_write(dev, 0x8, 0x03F); msleep(1); | ||
845 | rtl8225_write(dev, 0x9, 0x335); msleep(1); | ||
846 | rtl8225_write(dev, 0xa, 0x9D4); msleep(1); | ||
847 | rtl8225_write(dev, 0xb, 0x7BB); msleep(1); | ||
848 | rtl8225_write(dev, 0xc, 0x850); msleep(1); | ||
849 | rtl8225_write(dev, 0xd, 0xCDF); msleep(1); | ||
850 | rtl8225_write(dev, 0xe, 0x02B); msleep(1); | ||
851 | rtl8225_write(dev, 0xf, 0x114); msleep(1); | ||
852 | |||
853 | rtl8225_write(dev, 0x0, 0x1B7); msleep(1); | ||
854 | |||
855 | for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { | ||
856 | rtl8225_write(dev, 0x1, i + 1); msleep(1); | ||
857 | rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1); | ||
858 | } | ||
859 | |||
860 | rtl8225_write(dev, 0x3, 0x080); msleep(1); | ||
861 | rtl8225_write(dev, 0x5, 0x004); msleep(1); | ||
862 | rtl8225_write(dev, 0x0, 0x0B7); msleep(1); | ||
863 | msleep(3000); | ||
864 | |||
865 | rtl8225_write(dev, 0x2, 0xC4D); msleep(1); | ||
866 | msleep(2000); | ||
867 | |||
868 | rtl8225_write(dev, 0x2, 0x44D); msleep(1); | ||
869 | rtl8225_write(dev, 0x0, 0x2BF); msleep(1); | ||
870 | |||
871 | rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); | ||
872 | rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); | ||
873 | rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); | ||
874 | |||
875 | rtl8225_write_phy_ofdm(dev, 0x80, 0x12); | ||
876 | for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { | ||
877 | rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); | ||
878 | rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); | ||
879 | rtl8225_write_phy_ofdm(dev, 0xE, 0); | ||
880 | } | ||
881 | rtl8225_write_phy_ofdm(dev, 0x80, 0x10); | ||
882 | |||
883 | for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) | ||
884 | rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); | ||
885 | |||
886 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | ||
887 | rtl818x_iowrite8(priv, &priv->map->SLOT, 9); | ||
888 | rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28); | ||
889 | rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28); | ||
890 | rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28); | ||
891 | rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28); | ||
892 | rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B); | ||
893 | rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B); | ||
894 | rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28); | ||
895 | rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28); | ||
896 | rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28); | ||
897 | rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28); | ||
898 | rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); | ||
899 | |||
900 | rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1); | ||
901 | rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1); | ||
902 | rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1); | ||
903 | rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1); | ||
904 | } | ||
905 | |||
718 | static void rtl8225_rf_stop(struct ieee80211_hw *dev) | 906 | static void rtl8225_rf_stop(struct ieee80211_hw *dev) |
719 | { | 907 | { |
720 | u8 reg; | 908 | u8 reg; |
@@ -739,8 +927,10 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, | |||
739 | 927 | ||
740 | if (priv->rf->init == rtl8225_rf_init) | 928 | if (priv->rf->init == rtl8225_rf_init) |
741 | rtl8225_rf_set_tx_power(dev, chan); | 929 | rtl8225_rf_set_tx_power(dev, chan); |
742 | else | 930 | else if (priv->rf->init == rtl8225z2_rf_init) |
743 | rtl8225z2_rf_set_tx_power(dev, chan); | 931 | rtl8225z2_rf_set_tx_power(dev, chan); |
932 | else | ||
933 | rtl8225z2_b_rf_set_tx_power(dev, chan); | ||
744 | 934 | ||
745 | rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); | 935 | rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); |
746 | msleep(10); | 936 | msleep(10); |
@@ -760,19 +950,30 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = { | |||
760 | .set_chan = rtl8225_rf_set_channel | 950 | .set_chan = rtl8225_rf_set_channel |
761 | }; | 951 | }; |
762 | 952 | ||
953 | static const struct rtl818x_rf_ops rtl8225z2_b_ops = { | ||
954 | .name = "rtl8225z2", | ||
955 | .init = rtl8225z2_b_rf_init, | ||
956 | .stop = rtl8225_rf_stop, | ||
957 | .set_chan = rtl8225_rf_set_channel | ||
958 | }; | ||
959 | |||
763 | const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) | 960 | const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) |
764 | { | 961 | { |
765 | u16 reg8, reg9; | 962 | u16 reg8, reg9; |
963 | struct rtl8187_priv *priv = dev->priv; | ||
766 | 964 | ||
767 | rtl8225_write(dev, 0, 0x1B7); | 965 | if (!priv->is_rtl8187b) { |
966 | rtl8225_write(dev, 0, 0x1B7); | ||
768 | 967 | ||
769 | reg8 = rtl8225_read(dev, 8); | 968 | reg8 = rtl8225_read(dev, 8); |
770 | reg9 = rtl8225_read(dev, 9); | 969 | reg9 = rtl8225_read(dev, 9); |
771 | 970 | ||
772 | rtl8225_write(dev, 0, 0x0B7); | 971 | rtl8225_write(dev, 0, 0x0B7); |
773 | 972 | ||
774 | if (reg8 != 0x588 || reg9 != 0x700) | 973 | if (reg8 != 0x588 || reg9 != 0x700) |
775 | return &rtl8225_ops; | 974 | return &rtl8225_ops; |
776 | 975 | ||
777 | return &rtl8225z2_ops; | 976 | return &rtl8225z2_ops; |
977 | } else | ||
978 | return &rtl8225z2_b_ops; | ||
778 | } | 979 | } |
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 4f7d38f506eb..00900fe16fce 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h | |||
@@ -66,7 +66,10 @@ struct rtl818x_csr { | |||
66 | #define RTL818X_TX_CONF_R8180_F (3 << 25) | 66 | #define RTL818X_TX_CONF_R8180_F (3 << 25) |
67 | #define RTL818X_TX_CONF_R8185_ABC (4 << 25) | 67 | #define RTL818X_TX_CONF_R8185_ABC (4 << 25) |
68 | #define RTL818X_TX_CONF_R8185_D (5 << 25) | 68 | #define RTL818X_TX_CONF_R8185_D (5 << 25) |
69 | #define RTL818X_TX_CONF_R8187vD (5 << 25) | ||
70 | #define RTL818X_TX_CONF_R8187vD_B (6 << 25) | ||
69 | #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) | 71 | #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) |
72 | #define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) | ||
70 | #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) | 73 | #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) |
71 | #define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) | 74 | #define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) |
72 | #define RTL818X_TX_CONF_CW_MIN (1 << 31) | 75 | #define RTL818X_TX_CONF_CW_MIN (1 << 31) |
@@ -106,8 +109,11 @@ struct rtl818x_csr { | |||
106 | #define RTL818X_MSR_NO_LINK (0 << 2) | 109 | #define RTL818X_MSR_NO_LINK (0 << 2) |
107 | #define RTL818X_MSR_ADHOC (1 << 2) | 110 | #define RTL818X_MSR_ADHOC (1 << 2) |
108 | #define RTL818X_MSR_INFRA (2 << 2) | 111 | #define RTL818X_MSR_INFRA (2 << 2) |
112 | #define RTL818X_MSR_MASTER (3 << 2) | ||
113 | #define RTL818X_MSR_ENEDCA (4 << 2) | ||
109 | u8 CONFIG3; | 114 | u8 CONFIG3; |
110 | #define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) | 115 | #define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) |
116 | #define RTL818X_CONFIG3_GNT_SELECT (1 << 7) | ||
111 | u8 CONFIG4; | 117 | u8 CONFIG4; |
112 | #define RTL818X_CONFIG4_POWEROFF (1 << 6) | 118 | #define RTL818X_CONFIG4_POWEROFF (1 << 6) |
113 | #define RTL818X_CONFIG4_VCOOFF (1 << 7) | 119 | #define RTL818X_CONFIG4_VCOOFF (1 << 7) |
@@ -133,7 +139,9 @@ struct rtl818x_csr { | |||
133 | __le32 RF_TIMING; | 139 | __le32 RF_TIMING; |
134 | u8 GP_ENABLE; | 140 | u8 GP_ENABLE; |
135 | u8 GPIO; | 141 | u8 GPIO; |
136 | u8 reserved_12[10]; | 142 | u8 reserved_12[2]; |
143 | __le32 HSSI_PARA; | ||
144 | u8 reserved_13[4]; | ||
137 | u8 TX_AGC_CTL; | 145 | u8 TX_AGC_CTL; |
138 | #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) | 146 | #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) |
139 | #define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) | 147 | #define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) |
@@ -141,29 +149,39 @@ struct rtl818x_csr { | |||
141 | u8 TX_GAIN_CCK; | 149 | u8 TX_GAIN_CCK; |
142 | u8 TX_GAIN_OFDM; | 150 | u8 TX_GAIN_OFDM; |
143 | u8 TX_ANTENNA; | 151 | u8 TX_ANTENNA; |
144 | u8 reserved_13[16]; | 152 | u8 reserved_14[16]; |
145 | u8 WPA_CONF; | 153 | u8 WPA_CONF; |
146 | u8 reserved_14[3]; | 154 | u8 reserved_15[3]; |
147 | u8 SIFS; | 155 | u8 SIFS; |
148 | u8 DIFS; | 156 | u8 DIFS; |
149 | u8 SLOT; | 157 | u8 SLOT; |
150 | u8 reserved_15[5]; | 158 | u8 reserved_16[5]; |
151 | u8 CW_CONF; | 159 | u8 CW_CONF; |
152 | #define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) | 160 | #define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) |
153 | #define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) | 161 | #define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) |
154 | u8 CW_VAL; | 162 | u8 CW_VAL; |
155 | u8 RATE_FALLBACK; | 163 | u8 RATE_FALLBACK; |
156 | u8 reserved_16[25]; | 164 | #define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) |
165 | u8 ACM_CONTROL; | ||
166 | u8 reserved_17[24]; | ||
157 | u8 CONFIG5; | 167 | u8 CONFIG5; |
158 | u8 TX_DMA_POLLING; | 168 | u8 TX_DMA_POLLING; |
159 | u8 reserved_17[2]; | 169 | u8 reserved_18[2]; |
160 | __le16 CWR; | 170 | __le16 CWR; |
161 | u8 RETRY_CTR; | 171 | u8 RETRY_CTR; |
162 | u8 reserved_18[5]; | 172 | u8 reserved_19[3]; |
173 | __le16 INT_MIG; | ||
174 | /* RTL818X_R8187B_*: magic numbers from ioregisters */ | ||
175 | #define RTL818X_R8187B_B 0 | ||
176 | #define RTL818X_R8187B_D 1 | ||
177 | #define RTL818X_R8187B_E 2 | ||
163 | __le32 RDSAR; | 178 | __le32 RDSAR; |
164 | u8 reserved_19[12]; | 179 | __le16 TID_AC_MAP; |
165 | __le16 FEMR; | ||
166 | u8 reserved_20[4]; | 180 | u8 reserved_20[4]; |
181 | u8 ANAPARAM3; | ||
182 | u8 reserved_21[5]; | ||
183 | __le16 FEMR; | ||
184 | u8 reserved_22[4]; | ||
167 | __le16 TALLY_CNT; | 185 | __le16 TALLY_CNT; |
168 | u8 TALLY_SEL; | 186 | u8 TALLY_SEL; |
169 | } __attribute__((packed)); | 187 | } __attribute__((packed)); |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 317c5e24f80c..665f76af2fec 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -405,43 +405,66 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
405 | /* FIXME: Management frame? */ | 405 | /* FIXME: Management frame? */ |
406 | } | 406 | } |
407 | 407 | ||
408 | void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) | 408 | static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) |
409 | { | 409 | { |
410 | struct zd_mac *mac = zd_hw_mac(hw); | 410 | struct zd_mac *mac = zd_hw_mac(hw); |
411 | int r; | ||
411 | u32 tmp, j = 0; | 412 | u32 tmp, j = 0; |
412 | /* 4 more bytes for tail CRC */ | 413 | /* 4 more bytes for tail CRC */ |
413 | u32 full_len = beacon->len + 4; | 414 | u32 full_len = beacon->len + 4; |
414 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); | 415 | |
415 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | 416 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); |
417 | if (r < 0) | ||
418 | return r; | ||
419 | r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | ||
420 | if (r < 0) | ||
421 | return r; | ||
422 | |||
416 | while (tmp & 0x2) { | 423 | while (tmp & 0x2) { |
417 | zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | 424 | r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); |
425 | if (r < 0) | ||
426 | return r; | ||
418 | if ((++j % 100) == 0) { | 427 | if ((++j % 100) == 0) { |
419 | printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); | 428 | printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); |
420 | if (j >= 500) { | 429 | if (j >= 500) { |
421 | printk(KERN_ERR "Giving up beacon config.\n"); | 430 | printk(KERN_ERR "Giving up beacon config.\n"); |
422 | return; | 431 | return -ETIMEDOUT; |
423 | } | 432 | } |
424 | } | 433 | } |
425 | msleep(1); | 434 | msleep(1); |
426 | } | 435 | } |
427 | 436 | ||
428 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); | 437 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); |
429 | if (zd_chip_is_zd1211b(&mac->chip)) | 438 | if (r < 0) |
430 | zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); | 439 | return r; |
440 | if (zd_chip_is_zd1211b(&mac->chip)) { | ||
441 | r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); | ||
442 | if (r < 0) | ||
443 | return r; | ||
444 | } | ||
431 | 445 | ||
432 | for (j = 0 ; j < beacon->len; j++) | 446 | for (j = 0 ; j < beacon->len; j++) { |
433 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, | 447 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, |
434 | *((u8 *)(beacon->data + j))); | 448 | *((u8 *)(beacon->data + j))); |
449 | if (r < 0) | ||
450 | return r; | ||
451 | } | ||
435 | 452 | ||
436 | for (j = 0; j < 4; j++) | 453 | for (j = 0; j < 4; j++) { |
437 | zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); | 454 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); |
455 | if (r < 0) | ||
456 | return r; | ||
457 | } | ||
458 | |||
459 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); | ||
460 | if (r < 0) | ||
461 | return r; | ||
438 | 462 | ||
439 | zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); | ||
440 | /* 802.11b/g 2.4G CCK 1Mb | 463 | /* 802.11b/g 2.4G CCK 1Mb |
441 | * 802.11a, not yet implemented, uses different values (see GPL vendor | 464 | * 802.11a, not yet implemented, uses different values (see GPL vendor |
442 | * driver) | 465 | * driver) |
443 | */ | 466 | */ |
444 | zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | | 467 | return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | |
445 | (full_len << 19)); | 468 | (full_len << 19)); |
446 | } | 469 | } |
447 | 470 | ||
@@ -699,15 +722,20 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, | |||
699 | { | 722 | { |
700 | struct zd_mac *mac = zd_hw_mac(hw); | 723 | struct zd_mac *mac = zd_hw_mac(hw); |
701 | int associated; | 724 | int associated; |
725 | int r; | ||
702 | 726 | ||
703 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || | 727 | if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || |
704 | mac->type == IEEE80211_IF_TYPE_IBSS) { | 728 | mac->type == IEEE80211_IF_TYPE_IBSS) { |
705 | associated = true; | 729 | associated = true; |
706 | if (conf->beacon) { | 730 | if (conf->beacon) { |
707 | zd_mac_config_beacon(hw, conf->beacon); | 731 | r = zd_mac_config_beacon(hw, conf->beacon); |
708 | kfree_skb(conf->beacon); | 732 | if (r < 0) |
709 | zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | 733 | return r; |
734 | r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | | ||
710 | hw->conf.beacon_int); | 735 | hw->conf.beacon_int); |
736 | if (r < 0) | ||
737 | return r; | ||
738 | kfree_skb(conf->beacon); | ||
711 | } | 739 | } |
712 | } else | 740 | } else |
713 | associated = is_valid_ether_addr(conf->bssid); | 741 | associated = is_valid_ether_addr(conf->bssid); |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index cffd6d0094f9..a1630ba0b87c 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -99,6 +99,8 @@ | |||
99 | #define IEEE80211_MAX_SSID_LEN 32 | 99 | #define IEEE80211_MAX_SSID_LEN 32 |
100 | #define IEEE80211_MAX_MESH_ID_LEN 32 | 100 | #define IEEE80211_MAX_MESH_ID_LEN 32 |
101 | #define IEEE80211_QOS_CTL_LEN 2 | 101 | #define IEEE80211_QOS_CTL_LEN 2 |
102 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F | ||
103 | #define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 | ||
102 | 104 | ||
103 | struct ieee80211_hdr { | 105 | struct ieee80211_hdr { |
104 | __le16 frame_control; | 106 | __le16 frame_control; |
@@ -658,6 +660,10 @@ struct ieee80211_bar { | |||
658 | __le16 start_seq_num; | 660 | __le16 start_seq_num; |
659 | } __attribute__((packed)); | 661 | } __attribute__((packed)); |
660 | 662 | ||
663 | /* 802.11 BAR control masks */ | ||
664 | #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 | ||
665 | #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 | ||
666 | |||
661 | /** | 667 | /** |
662 | * struct ieee80211_ht_cap - HT capabilities | 668 | * struct ieee80211_ht_cap - HT capabilities |
663 | * | 669 | * |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3a204acad901..656442c6b1c3 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -42,7 +42,7 @@ | |||
42 | * tasklet function. | 42 | * tasklet function. |
43 | * | 43 | * |
44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also | 44 | * NOTE: If the driver opts to use the _irqsafe() functions, it may not also |
45 | * use the non-irqsafe functions! | 45 | * use the non-IRQ-safe functions! |
46 | */ | 46 | */ |
47 | 47 | ||
48 | /** | 48 | /** |
@@ -85,7 +85,7 @@ enum ieee80211_notification_types { | |||
85 | * struct ieee80211_ht_bss_info - describing BSS's HT characteristics | 85 | * struct ieee80211_ht_bss_info - describing BSS's HT characteristics |
86 | * | 86 | * |
87 | * This structure describes most essential parameters needed | 87 | * This structure describes most essential parameters needed |
88 | * to describe 802.11n HT characteristics in a BSS | 88 | * to describe 802.11n HT characteristics in a BSS. |
89 | * | 89 | * |
90 | * @primary_channel: channel number of primery channel | 90 | * @primary_channel: channel number of primery channel |
91 | * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) | 91 | * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) |
@@ -201,9 +201,9 @@ struct ieee80211_bss_conf { | |||
201 | }; | 201 | }; |
202 | 202 | ||
203 | /** | 203 | /** |
204 | * enum mac80211_tx_flags - flags to transmission information/status | 204 | * enum mac80211_tx_control_flags - flags to describe transmission information/status |
205 | * | 205 | * |
206 | * These flags are used with the @flags member of &ieee80211_tx_info | 206 | * These flags are used with the @flags member of &ieee80211_tx_info. |
207 | * | 207 | * |
208 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. | 208 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. |
209 | * @IEEE80211_TX_CTL_DO_NOT_ENCRYPT: send this frame without encryption; | 209 | * @IEEE80211_TX_CTL_DO_NOT_ENCRYPT: send this frame without encryption; |
@@ -212,11 +212,12 @@ struct ieee80211_bss_conf { | |||
212 | * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g., | 212 | * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g., |
213 | * for combined 802.11g / 802.11b networks) | 213 | * for combined 802.11g / 802.11b networks) |
214 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack | 214 | * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack |
215 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE | 215 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: TBD |
216 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination | 216 | * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination |
217 | * station | 217 | * station |
218 | * @IEEE80211_TX_CTL_REQUEUE: | 218 | * @IEEE80211_TX_CTL_REQUEUE: TBD |
219 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame | 219 | * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame |
220 | * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD | ||
220 | * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the | 221 | * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the |
221 | * through set_retry_limit configured long retry value | 222 | * through set_retry_limit configured long retry value |
222 | * @IEEE80211_TX_CTL_EAPOL_FRAME: internal to mac80211 | 223 | * @IEEE80211_TX_CTL_EAPOL_FRAME: internal to mac80211 |
@@ -230,11 +231,14 @@ struct ieee80211_bss_conf { | |||
230 | * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width | 231 | * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width |
231 | * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels | 232 | * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels |
232 | * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval | 233 | * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval |
234 | * @IEEE80211_TX_CTL_INJECTED: TBD | ||
233 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted | 235 | * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted |
234 | * because the destination STA was in powersave mode. | 236 | * because the destination STA was in powersave mode. |
235 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged | 237 | * @IEEE80211_TX_STAT_ACK: Frame was acknowledged |
236 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status | 238 | * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status |
237 | * is for the whole aggregation. | 239 | * is for the whole aggregation. |
240 | * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, | ||
241 | * so consider using block ack request (BAR). | ||
238 | */ | 242 | */ |
239 | enum mac80211_tx_control_flags { | 243 | enum mac80211_tx_control_flags { |
240 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), | 244 | IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), |
@@ -260,6 +264,7 @@ enum mac80211_tx_control_flags { | |||
260 | IEEE80211_TX_STAT_TX_FILTERED = BIT(20), | 264 | IEEE80211_TX_STAT_TX_FILTERED = BIT(20), |
261 | IEEE80211_TX_STAT_ACK = BIT(21), | 265 | IEEE80211_TX_STAT_ACK = BIT(21), |
262 | IEEE80211_TX_STAT_AMPDU = BIT(22), | 266 | IEEE80211_TX_STAT_AMPDU = BIT(22), |
267 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), | ||
263 | }; | 268 | }; |
264 | 269 | ||
265 | 270 | ||
@@ -277,6 +282,12 @@ enum mac80211_tx_control_flags { | |||
277 | * (3) TX status information - driver tells mac80211 what happened | 282 | * (3) TX status information - driver tells mac80211 what happened |
278 | * | 283 | * |
279 | * @flags: transmit info flags, defined above | 284 | * @flags: transmit info flags, defined above |
285 | * @band: TBD | ||
286 | * @tx_rate_idx: TBD | ||
287 | * @antenna_sel_tx: TBD | ||
288 | * @control: union for control data | ||
289 | * @status: union for status data | ||
290 | * @driver_data: array of driver_data pointers | ||
280 | * @retry_count: number of retries | 291 | * @retry_count: number of retries |
281 | * @excessive_retries: set to 1 if the frame was retried many times | 292 | * @excessive_retries: set to 1 if the frame was retried many times |
282 | * but not acknowledged | 293 | * but not acknowledged |
@@ -559,8 +570,8 @@ enum ieee80211_key_alg { | |||
559 | 570 | ||
560 | /** | 571 | /** |
561 | * enum ieee80211_key_len - key length | 572 | * enum ieee80211_key_len - key length |
562 | * @WEP40: WEP 5 byte long key | 573 | * @LEN_WEP40: WEP 5-byte long key |
563 | * @WEP104: WEP 13 byte long key | 574 | * @LEN_WEP104: WEP 13-byte long key |
564 | */ | 575 | */ |
565 | enum ieee80211_key_len { | 576 | enum ieee80211_key_len { |
566 | LEN_WEP40 = 5, | 577 | LEN_WEP40 = 5, |
@@ -637,7 +648,7 @@ enum set_key_cmd { | |||
637 | * enum sta_notify_cmd - sta notify command | 648 | * enum sta_notify_cmd - sta notify command |
638 | * | 649 | * |
639 | * Used with the sta_notify() callback in &struct ieee80211_ops, this | 650 | * Used with the sta_notify() callback in &struct ieee80211_ops, this |
640 | * indicates addition and removal of a station to station table | 651 | * indicates addition and removal of a station to station table. |
641 | * | 652 | * |
642 | * @STA_NOTIFY_ADD: a station was added to the station table | 653 | * @STA_NOTIFY_ADD: a station was added to the station table |
643 | * @STA_NOTIFY_REMOVE: a station being removed from the station table | 654 | * @STA_NOTIFY_REMOVE: a station being removed from the station table |
@@ -1337,7 +1348,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw); | |||
1337 | * | 1348 | * |
1338 | * This function frees everything that was allocated, including the | 1349 | * This function frees everything that was allocated, including the |
1339 | * private data for the driver. You must call ieee80211_unregister_hw() | 1350 | * private data for the driver. You must call ieee80211_unregister_hw() |
1340 | * before calling this function | 1351 | * before calling this function. |
1341 | * | 1352 | * |
1342 | * @hw: the hardware to free | 1353 | * @hw: the hardware to free |
1343 | */ | 1354 | */ |
@@ -1408,7 +1419,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, | |||
1408 | struct sk_buff *skb); | 1419 | struct sk_buff *skb); |
1409 | 1420 | ||
1410 | /** | 1421 | /** |
1411 | * ieee80211_tx_status_irqsafe - irq-safe transmit status callback | 1422 | * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback |
1412 | * | 1423 | * |
1413 | * Like ieee80211_tx_status() but can be called in IRQ context | 1424 | * Like ieee80211_tx_status() but can be called in IRQ context |
1414 | * (internally defers to a tasklet.) | 1425 | * (internally defers to a tasklet.) |
@@ -1586,6 +1597,8 @@ unsigned int ieee80211_hdrlen(__le16 fc); | |||
1586 | * @keyconf: the parameter passed with the set key | 1597 | * @keyconf: the parameter passed with the set key |
1587 | * @skb: the skb for which the key is needed | 1598 | * @skb: the skb for which the key is needed |
1588 | * @rc4key: a buffer to which the key will be written | 1599 | * @rc4key: a buffer to which the key will be written |
1600 | * @type: TBD | ||
1601 | * @key: TBD | ||
1589 | */ | 1602 | */ |
1590 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | 1603 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, |
1591 | struct sk_buff *skb, | 1604 | struct sk_buff *skb, |
@@ -1636,7 +1649,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); | |||
1636 | void ieee80211_scan_completed(struct ieee80211_hw *hw); | 1649 | void ieee80211_scan_completed(struct ieee80211_hw *hw); |
1637 | 1650 | ||
1638 | /** | 1651 | /** |
1639 | * ieee80211_iterate_active_interfaces- iterate active interfaces | 1652 | * ieee80211_iterate_active_interfaces - iterate active interfaces |
1640 | * | 1653 | * |
1641 | * This function iterates over the interfaces associated with a given | 1654 | * This function iterates over the interfaces associated with a given |
1642 | * hardware that are currently active and calls the callback for them. | 1655 | * hardware that are currently active and calls the callback for them. |
@@ -1703,7 +1716,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); | |||
1703 | * | 1716 | * |
1704 | * This function must be called by low level driver once it has | 1717 | * This function must be called by low level driver once it has |
1705 | * finished with preparations for the BA session. | 1718 | * finished with preparations for the BA session. |
1706 | * This version of the function is irq safe. | 1719 | * This version of the function is IRQ-safe. |
1707 | */ | 1720 | */ |
1708 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1721 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1709 | u16 tid); | 1722 | u16 tid); |
@@ -1743,7 +1756,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); | |||
1743 | * | 1756 | * |
1744 | * This function must be called by low level driver once it has | 1757 | * This function must be called by low level driver once it has |
1745 | * finished with preparations for the BA session tear down. | 1758 | * finished with preparations for the BA session tear down. |
1746 | * This version of the function is irq safe. | 1759 | * This version of the function is IRQ-safe. |
1747 | */ | 1760 | */ |
1748 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 1761 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, |
1749 | u16 tid); | 1762 | u16 tid); |
@@ -1751,7 +1764,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | |||
1751 | /** | 1764 | /** |
1752 | * ieee80211_notify_mac - low level driver notification | 1765 | * ieee80211_notify_mac - low level driver notification |
1753 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1766 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1754 | * @notification_types: enum ieee80211_notification_types | 1767 | * @notif_type: enum ieee80211_notification_types |
1755 | * | 1768 | * |
1756 | * This function must be called by low level driver to inform mac80211 of | 1769 | * This function must be called by low level driver to inform mac80211 of |
1757 | * low level driver status change or force mac80211 to re-assoc for low | 1770 | * low level driver status change or force mac80211 to re-assoc for low |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 11a1e7fa195d..40f1add17753 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -207,7 +207,6 @@ config MAC80211_LOWTX_FRAME_DUMP | |||
207 | 207 | ||
208 | config MAC80211_DEBUG_COUNTERS | 208 | config MAC80211_DEBUG_COUNTERS |
209 | bool "Extra statistics for TX/RX debugging" | 209 | bool "Extra statistics for TX/RX debugging" |
210 | depends on MAC80211_DEBUG | ||
211 | depends on MAC80211_DEBUG_MENU | 210 | depends on MAC80211_DEBUG_MENU |
212 | depends on MAC80211_DEBUGFS | 211 | depends on MAC80211_DEBUGFS |
213 | ---help--- | 212 | ---help--- |
@@ -219,7 +218,7 @@ config MAC80211_DEBUG_COUNTERS | |||
219 | 218 | ||
220 | config MAC80211_VERBOSE_SPECT_MGMT_DEBUG | 219 | config MAC80211_VERBOSE_SPECT_MGMT_DEBUG |
221 | bool "Verbose Spectrum Management (IEEE 802.11h)debugging" | 220 | bool "Verbose Spectrum Management (IEEE 802.11h)debugging" |
222 | depends on MAC80211_DEBUG | 221 | depends on MAC80211_DEBUG_MENU |
223 | ---help--- | 222 | ---help--- |
224 | Say Y here to print out verbose Spectrum Management (IEEE 802.11h) | 223 | Say Y here to print out verbose Spectrum Management (IEEE 802.11h) |
225 | debug messages. | 224 | debug messages. |
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 4d4c2dfcf9a0..a87cb3ba2df6 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -16,31 +16,28 @@ | |||
16 | #include "key.h" | 16 | #include "key.h" |
17 | #include "aes_ccm.h" | 17 | #include "aes_ccm.h" |
18 | 18 | ||
19 | 19 | static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) | |
20 | static void ieee80211_aes_encrypt(struct crypto_cipher *tfm, | ||
21 | const u8 pt[16], u8 ct[16]) | ||
22 | { | ||
23 | crypto_cipher_encrypt_one(tfm, ct, pt); | ||
24 | } | ||
25 | |||
26 | |||
27 | static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, | ||
28 | u8 *b, u8 *s_0, u8 *a) | ||
29 | { | 20 | { |
30 | int i; | 21 | int i; |
22 | u8 *b_0, *aad, *b, *s_0; | ||
31 | 23 | ||
32 | ieee80211_aes_encrypt(tfm, b_0, b); | 24 | b_0 = scratch + 3 * AES_BLOCK_LEN; |
25 | aad = scratch + 4 * AES_BLOCK_LEN; | ||
26 | b = scratch; | ||
27 | s_0 = scratch + AES_BLOCK_LEN; | ||
28 | |||
29 | crypto_cipher_encrypt_one(tfm, b, b_0); | ||
33 | 30 | ||
34 | /* Extra Authenticate-only data (always two AES blocks) */ | 31 | /* Extra Authenticate-only data (always two AES blocks) */ |
35 | for (i = 0; i < AES_BLOCK_LEN; i++) | 32 | for (i = 0; i < AES_BLOCK_LEN; i++) |
36 | aad[i] ^= b[i]; | 33 | aad[i] ^= b[i]; |
37 | ieee80211_aes_encrypt(tfm, aad, b); | 34 | crypto_cipher_encrypt_one(tfm, b, aad); |
38 | 35 | ||
39 | aad += AES_BLOCK_LEN; | 36 | aad += AES_BLOCK_LEN; |
40 | 37 | ||
41 | for (i = 0; i < AES_BLOCK_LEN; i++) | 38 | for (i = 0; i < AES_BLOCK_LEN; i++) |
42 | aad[i] ^= b[i]; | 39 | aad[i] ^= b[i]; |
43 | ieee80211_aes_encrypt(tfm, aad, a); | 40 | crypto_cipher_encrypt_one(tfm, a, aad); |
44 | 41 | ||
45 | /* Mask out bits from auth-only-b_0 */ | 42 | /* Mask out bits from auth-only-b_0 */ |
46 | b_0[0] &= 0x07; | 43 | b_0[0] &= 0x07; |
@@ -48,24 +45,26 @@ static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, | |||
48 | /* S_0 is used to encrypt T (= MIC) */ | 45 | /* S_0 is used to encrypt T (= MIC) */ |
49 | b_0[14] = 0; | 46 | b_0[14] = 0; |
50 | b_0[15] = 0; | 47 | b_0[15] = 0; |
51 | ieee80211_aes_encrypt(tfm, b_0, s_0); | 48 | crypto_cipher_encrypt_one(tfm, s_0, b_0); |
52 | } | 49 | } |
53 | 50 | ||
54 | 51 | ||
55 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 52 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, |
56 | u8 *b_0, u8 *aad, u8 *data, size_t data_len, | 53 | u8 *data, size_t data_len, |
57 | u8 *cdata, u8 *mic) | 54 | u8 *cdata, u8 *mic) |
58 | { | 55 | { |
59 | int i, j, last_len, num_blocks; | 56 | int i, j, last_len, num_blocks; |
60 | u8 *pos, *cpos, *b, *s_0, *e; | 57 | u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad; |
61 | 58 | ||
62 | b = scratch; | 59 | b = scratch; |
63 | s_0 = scratch + AES_BLOCK_LEN; | 60 | s_0 = scratch + AES_BLOCK_LEN; |
64 | e = scratch + 2 * AES_BLOCK_LEN; | 61 | e = scratch + 2 * AES_BLOCK_LEN; |
62 | b_0 = scratch + 3 * AES_BLOCK_LEN; | ||
63 | aad = scratch + 4 * AES_BLOCK_LEN; | ||
65 | 64 | ||
66 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 65 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); |
67 | last_len = data_len % AES_BLOCK_LEN; | 66 | last_len = data_len % AES_BLOCK_LEN; |
68 | aes_ccm_prepare(tfm, b_0, aad, b, s_0, b); | 67 | aes_ccm_prepare(tfm, scratch, b); |
69 | 68 | ||
70 | /* Process payload blocks */ | 69 | /* Process payload blocks */ |
71 | pos = data; | 70 | pos = data; |
@@ -77,11 +76,11 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
77 | /* Authentication followed by encryption */ | 76 | /* Authentication followed by encryption */ |
78 | for (i = 0; i < blen; i++) | 77 | for (i = 0; i < blen; i++) |
79 | b[i] ^= pos[i]; | 78 | b[i] ^= pos[i]; |
80 | ieee80211_aes_encrypt(tfm, b, b); | 79 | crypto_cipher_encrypt_one(tfm, b, b); |
81 | 80 | ||
82 | b_0[14] = (j >> 8) & 0xff; | 81 | b_0[14] = (j >> 8) & 0xff; |
83 | b_0[15] = j & 0xff; | 82 | b_0[15] = j & 0xff; |
84 | ieee80211_aes_encrypt(tfm, b_0, e); | 83 | crypto_cipher_encrypt_one(tfm, e, b_0); |
85 | for (i = 0; i < blen; i++) | 84 | for (i = 0; i < blen; i++) |
86 | *cpos++ = *pos++ ^ e[i]; | 85 | *cpos++ = *pos++ ^ e[i]; |
87 | } | 86 | } |
@@ -92,19 +91,20 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
92 | 91 | ||
93 | 92 | ||
94 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | 93 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, |
95 | u8 *b_0, u8 *aad, u8 *cdata, size_t data_len, | 94 | u8 *cdata, size_t data_len, u8 *mic, u8 *data) |
96 | u8 *mic, u8 *data) | ||
97 | { | 95 | { |
98 | int i, j, last_len, num_blocks; | 96 | int i, j, last_len, num_blocks; |
99 | u8 *pos, *cpos, *b, *s_0, *a; | 97 | u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad; |
100 | 98 | ||
101 | b = scratch; | 99 | b = scratch; |
102 | s_0 = scratch + AES_BLOCK_LEN; | 100 | s_0 = scratch + AES_BLOCK_LEN; |
103 | a = scratch + 2 * AES_BLOCK_LEN; | 101 | a = scratch + 2 * AES_BLOCK_LEN; |
102 | b_0 = scratch + 3 * AES_BLOCK_LEN; | ||
103 | aad = scratch + 4 * AES_BLOCK_LEN; | ||
104 | 104 | ||
105 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); | 105 | num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); |
106 | last_len = data_len % AES_BLOCK_LEN; | 106 | last_len = data_len % AES_BLOCK_LEN; |
107 | aes_ccm_prepare(tfm, b_0, aad, b, s_0, a); | 107 | aes_ccm_prepare(tfm, scratch, a); |
108 | 108 | ||
109 | /* Process payload blocks */ | 109 | /* Process payload blocks */ |
110 | cpos = cdata; | 110 | cpos = cdata; |
@@ -116,13 +116,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | |||
116 | /* Decryption followed by authentication */ | 116 | /* Decryption followed by authentication */ |
117 | b_0[14] = (j >> 8) & 0xff; | 117 | b_0[14] = (j >> 8) & 0xff; |
118 | b_0[15] = j & 0xff; | 118 | b_0[15] = j & 0xff; |
119 | ieee80211_aes_encrypt(tfm, b_0, b); | 119 | crypto_cipher_encrypt_one(tfm, b, b_0); |
120 | for (i = 0; i < blen; i++) { | 120 | for (i = 0; i < blen; i++) { |
121 | *pos = *cpos++ ^ b[i]; | 121 | *pos = *cpos++ ^ b[i]; |
122 | a[i] ^= *pos++; | 122 | a[i] ^= *pos++; |
123 | } | 123 | } |
124 | 124 | crypto_cipher_encrypt_one(tfm, a, a); | |
125 | ieee80211_aes_encrypt(tfm, a, a); | ||
126 | } | 125 | } |
127 | 126 | ||
128 | for (i = 0; i < CCMP_MIC_LEN; i++) { | 127 | for (i = 0; i < CCMP_MIC_LEN; i++) { |
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 8cd0f14aab4d..6e7820ef3448 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -16,10 +16,10 @@ | |||
16 | 16 | ||
17 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); | 17 | struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); |
18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, | 18 | void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, |
19 | u8 *b_0, u8 *aad, u8 *data, size_t data_len, | 19 | u8 *data, size_t data_len, |
20 | u8 *cdata, u8 *mic); | 20 | u8 *cdata, u8 *mic); |
21 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, | 21 | int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, |
22 | u8 *b_0, u8 *aad, u8 *cdata, size_t data_len, | 22 | u8 *cdata, size_t data_len, |
23 | u8 *mic, u8 *data); | 23 | u8 *mic, u8 *data); |
24 | void ieee80211_aes_key_free(struct crypto_cipher *tfm); | 24 | void ieee80211_aes_key_free(struct crypto_cipher *tfm); |
25 | 25 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f90da1bbec49..02a8753a4eca 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -893,7 +893,7 @@ int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); | |||
893 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); | 893 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); |
894 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 894 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, |
895 | u32 changed); | 895 | u32 changed); |
896 | void ieee80211_reset_erp_info(struct net_device *dev); | 896 | u32 ieee80211_reset_erp_info(struct net_device *dev); |
897 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | 897 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, |
898 | struct ieee80211_ht_info *ht_info); | 898 | struct ieee80211_ht_info *ht_info); |
899 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | 899 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( |
@@ -904,6 +904,7 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | |||
904 | u16 agg_size, u16 timeout); | 904 | u16 agg_size, u16 timeout); |
905 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | 905 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, |
906 | u16 initiator, u16 reason_code); | 906 | u16 initiator, u16 reason_code); |
907 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); | ||
907 | 908 | ||
908 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, | 909 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, |
909 | u16 tid, u16 initiator, u16 reason); | 910 | u16 tid, u16 initiator, u16 reason); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f18cfd727872..cc756e93e6c8 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -182,10 +182,11 @@ static int ieee80211_open(struct net_device *dev) | |||
182 | { | 182 | { |
183 | struct ieee80211_sub_if_data *sdata, *nsdata; | 183 | struct ieee80211_sub_if_data *sdata, *nsdata; |
184 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 184 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
185 | struct sta_info *sta; | ||
185 | struct ieee80211_if_init_conf conf; | 186 | struct ieee80211_if_init_conf conf; |
187 | u32 changed = 0; | ||
186 | int res; | 188 | int res; |
187 | bool need_hw_reconfig = 0; | 189 | bool need_hw_reconfig = 0; |
188 | struct sta_info *sta; | ||
189 | 190 | ||
190 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 191 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
191 | 192 | ||
@@ -329,7 +330,8 @@ static int ieee80211_open(struct net_device *dev) | |||
329 | goto err_stop; | 330 | goto err_stop; |
330 | 331 | ||
331 | ieee80211_if_config(dev); | 332 | ieee80211_if_config(dev); |
332 | ieee80211_reset_erp_info(dev); | 333 | changed |= ieee80211_reset_erp_info(dev); |
334 | ieee80211_bss_info_change_notify(sdata, changed); | ||
333 | ieee80211_enable_keys(sdata); | 335 | ieee80211_enable_keys(sdata); |
334 | 336 | ||
335 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 337 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && |
@@ -1190,15 +1192,13 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1190 | changed); | 1192 | changed); |
1191 | } | 1193 | } |
1192 | 1194 | ||
1193 | void ieee80211_reset_erp_info(struct net_device *dev) | 1195 | u32 ieee80211_reset_erp_info(struct net_device *dev) |
1194 | { | 1196 | { |
1195 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1197 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1196 | 1198 | ||
1197 | sdata->bss_conf.use_cts_prot = 0; | 1199 | sdata->bss_conf.use_cts_prot = 0; |
1198 | sdata->bss_conf.use_short_preamble = 0; | 1200 | sdata->bss_conf.use_short_preamble = 0; |
1199 | ieee80211_bss_info_change_notify(sdata, | 1201 | return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; |
1200 | BSS_CHANGED_ERP_CTS_PROT | | ||
1201 | BSS_CHANGED_ERP_PREAMBLE); | ||
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | 1204 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, |
@@ -1404,14 +1404,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1404 | struct ieee80211_local *local = hw_to_local(hw); | 1404 | struct ieee80211_local *local = hw_to_local(hw); |
1405 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1405 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1406 | u16 frag, type; | 1406 | u16 frag, type; |
1407 | __le16 fc; | ||
1407 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 1408 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
1408 | struct ieee80211_sub_if_data *sdata; | 1409 | struct ieee80211_sub_if_data *sdata; |
1409 | struct net_device *prev_dev = NULL; | 1410 | struct net_device *prev_dev = NULL; |
1411 | struct sta_info *sta; | ||
1410 | 1412 | ||
1411 | rcu_read_lock(); | 1413 | rcu_read_lock(); |
1412 | 1414 | ||
1413 | if (info->status.excessive_retries) { | 1415 | if (info->status.excessive_retries) { |
1414 | struct sta_info *sta; | ||
1415 | sta = sta_info_get(local, hdr->addr1); | 1416 | sta = sta_info_get(local, hdr->addr1); |
1416 | if (sta) { | 1417 | if (sta) { |
1417 | if (test_sta_flags(sta, WLAN_STA_PS)) { | 1418 | if (test_sta_flags(sta, WLAN_STA_PS)) { |
@@ -1426,8 +1427,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1426 | } | 1427 | } |
1427 | } | 1428 | } |
1428 | 1429 | ||
1430 | fc = hdr->frame_control; | ||
1431 | |||
1432 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
1433 | (ieee80211_is_data_qos(fc))) { | ||
1434 | u16 tid, ssn; | ||
1435 | u8 *qc; | ||
1436 | sta = sta_info_get(local, hdr->addr1); | ||
1437 | if (sta) { | ||
1438 | qc = ieee80211_get_qos_ctl(hdr); | ||
1439 | tid = qc[0] & 0xf; | ||
1440 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | ||
1441 | & IEEE80211_SCTL_SEQ); | ||
1442 | ieee80211_send_bar(sta->sdata->dev, hdr->addr1, | ||
1443 | tid, ssn); | ||
1444 | } | ||
1445 | } | ||
1446 | |||
1429 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 1447 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
1430 | struct sta_info *sta; | ||
1431 | sta = sta_info_get(local, hdr->addr1); | 1448 | sta = sta_info_get(local, hdr->addr1); |
1432 | if (sta) { | 1449 | if (sta) { |
1433 | ieee80211_handle_filtered_frame(local, sta, skb); | 1450 | ieee80211_handle_filtered_frame(local, sta, skb); |
diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c index 1fcdf38cf60c..408649bd4702 100644 --- a/net/mac80211/michael.c +++ b/net/mac80211/michael.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
11 | #include <linux/ieee80211.h> | ||
11 | #include <asm/unaligned.h> | 12 | #include <asm/unaligned.h> |
12 | 13 | ||
13 | #include "michael.h" | 14 | #include "michael.h" |
@@ -26,9 +27,18 @@ static void michael_block(struct michael_mic_ctx *mctx, u32 val) | |||
26 | mctx->l += mctx->r; | 27 | mctx->l += mctx->r; |
27 | } | 28 | } |
28 | 29 | ||
29 | static void michael_mic_hdr(struct michael_mic_ctx *mctx, | 30 | static void michael_mic_hdr(struct michael_mic_ctx *mctx, const u8 *key, |
30 | const u8 *key, const u8 *da, const u8 *sa, u8 priority) | 31 | struct ieee80211_hdr *hdr) |
31 | { | 32 | { |
33 | u8 *da, *sa, tid; | ||
34 | |||
35 | da = ieee80211_get_DA(hdr); | ||
36 | sa = ieee80211_get_SA(hdr); | ||
37 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
38 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
39 | else | ||
40 | tid = 0; | ||
41 | |||
32 | mctx->l = get_unaligned_le32(key); | 42 | mctx->l = get_unaligned_le32(key); |
33 | mctx->r = get_unaligned_le32(key + 4); | 43 | mctx->r = get_unaligned_le32(key + 4); |
34 | 44 | ||
@@ -40,17 +50,17 @@ static void michael_mic_hdr(struct michael_mic_ctx *mctx, | |||
40 | michael_block(mctx, get_unaligned_le16(&da[4]) | | 50 | michael_block(mctx, get_unaligned_le16(&da[4]) | |
41 | (get_unaligned_le16(sa) << 16)); | 51 | (get_unaligned_le16(sa) << 16)); |
42 | michael_block(mctx, get_unaligned_le32(&sa[2])); | 52 | michael_block(mctx, get_unaligned_le32(&sa[2])); |
43 | michael_block(mctx, priority); | 53 | michael_block(mctx, tid); |
44 | } | 54 | } |
45 | 55 | ||
46 | void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, | 56 | void michael_mic(const u8 *key, struct ieee80211_hdr *hdr, |
47 | const u8 *data, size_t data_len, u8 *mic) | 57 | const u8 *data, size_t data_len, u8 *mic) |
48 | { | 58 | { |
49 | u32 val; | 59 | u32 val; |
50 | size_t block, blocks, left; | 60 | size_t block, blocks, left; |
51 | struct michael_mic_ctx mctx; | 61 | struct michael_mic_ctx mctx; |
52 | 62 | ||
53 | michael_mic_hdr(&mctx, key, da, sa, priority); | 63 | michael_mic_hdr(&mctx, key, hdr); |
54 | 64 | ||
55 | /* Real data */ | 65 | /* Real data */ |
56 | blocks = data_len / 4; | 66 | blocks = data_len / 4; |
diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h index 69b4501f13ba..3b848dad9587 100644 --- a/net/mac80211/michael.h +++ b/net/mac80211/michael.h | |||
@@ -18,7 +18,7 @@ struct michael_mic_ctx { | |||
18 | u32 l, r; | 18 | u32 l, r; |
19 | }; | 19 | }; |
20 | 20 | ||
21 | void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, | 21 | void michael_mic(const u8 *key, struct ieee80211_hdr *hdr, |
22 | const u8 *data, size_t data_len, u8 *mic); | 22 | const u8 *data, size_t data_len, u8 *mic); |
23 | 23 | ||
24 | #endif /* MICHAEL_H */ | 24 | #endif /* MICHAEL_H */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4a3bddd206d8..37ea04f5bab9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -366,8 +366,10 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | |||
366 | bool use_short_preamble) | 366 | bool use_short_preamble) |
367 | { | 367 | { |
368 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | 368 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; |
369 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
369 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 370 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
370 | DECLARE_MAC_BUF(mac); | 371 | DECLARE_MAC_BUF(mac); |
372 | #endif | ||
371 | u32 changed = 0; | 373 | u32 changed = 0; |
372 | 374 | ||
373 | if (use_protection != bss_conf->use_cts_prot) { | 375 | if (use_protection != bss_conf->use_cts_prot) { |
@@ -571,7 +573,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
571 | ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); | 573 | ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); |
572 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 574 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
573 | netif_carrier_off(dev); | 575 | netif_carrier_off(dev); |
574 | ieee80211_reset_erp_info(dev); | 576 | changed |= ieee80211_reset_erp_info(dev); |
575 | 577 | ||
576 | sdata->bss_conf.assoc_ht = 0; | 578 | sdata->bss_conf.assoc_ht = 0; |
577 | sdata->bss_conf.ht_conf = NULL; | 579 | sdata->bss_conf.ht_conf = NULL; |
@@ -1536,6 +1538,35 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | |||
1536 | ieee80211_sta_tx(dev, skb, 0); | 1538 | ieee80211_sta_tx(dev, skb, 0); |
1537 | } | 1539 | } |
1538 | 1540 | ||
1541 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) | ||
1542 | { | ||
1543 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1544 | struct sk_buff *skb; | ||
1545 | struct ieee80211_bar *bar; | ||
1546 | u16 bar_control = 0; | ||
1547 | |||
1548 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | ||
1549 | if (!skb) { | ||
1550 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
1551 | "bar frame\n", dev->name); | ||
1552 | return; | ||
1553 | } | ||
1554 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1555 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
1556 | memset(bar, 0, sizeof(*bar)); | ||
1557 | bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, | ||
1558 | IEEE80211_STYPE_BACK_REQ); | ||
1559 | memcpy(bar->ra, ra, ETH_ALEN); | ||
1560 | memcpy(bar->ta, dev->dev_addr, ETH_ALEN); | ||
1561 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
1562 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
1563 | bar_control |= (u16)(tid << 12); | ||
1564 | bar->control = cpu_to_le16(bar_control); | ||
1565 | bar->start_seq_num = cpu_to_le16(ssn); | ||
1566 | |||
1567 | ieee80211_sta_tx(dev, skb, 0); | ||
1568 | } | ||
1569 | |||
1539 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | 1570 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, |
1540 | u16 initiator, u16 reason) | 1571 | u16 initiator, u16 reason) |
1541 | { | 1572 | { |
@@ -2481,6 +2512,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2481 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | 2512 | control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
2482 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 2513 | control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
2483 | control->flags |= IEEE80211_TX_CTL_NO_ACK; | 2514 | control->flags |= IEEE80211_TX_CTL_NO_ACK; |
2515 | control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; | ||
2484 | control->control.retry_limit = 1; | 2516 | control->control.retry_limit = 1; |
2485 | 2517 | ||
2486 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); | 2518 | ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6a88e8f9bff0..fab443d717eb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -321,20 +321,20 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
321 | 321 | ||
322 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | 322 | static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) |
323 | { | 323 | { |
324 | u8 *data = rx->skb->data; | 324 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
325 | int tid; | 325 | int tid; |
326 | 326 | ||
327 | /* does the frame have a qos control field? */ | 327 | /* does the frame have a qos control field? */ |
328 | if (WLAN_FC_IS_QOS_DATA(rx->fc)) { | 328 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
329 | u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN; | 329 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
330 | /* frame has qos control */ | 330 | /* frame has qos control */ |
331 | tid = qc[0] & QOS_CONTROL_TID_MASK; | 331 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
332 | if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | 332 | if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) |
333 | rx->flags |= IEEE80211_RX_AMSDU; | 333 | rx->flags |= IEEE80211_RX_AMSDU; |
334 | else | 334 | else |
335 | rx->flags &= ~IEEE80211_RX_AMSDU; | 335 | rx->flags &= ~IEEE80211_RX_AMSDU; |
336 | } else { | 336 | } else { |
337 | if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) { | 337 | if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { |
338 | /* Separate TID for management frames */ | 338 | /* Separate TID for management frames */ |
339 | tid = NUM_RX_DATA_QUEUES - 1; | 339 | tid = NUM_RX_DATA_QUEUES - 1; |
340 | } else { | 340 | } else { |
@@ -352,9 +352,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
352 | static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) | 352 | static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) |
353 | { | 353 | { |
354 | #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT | 354 | #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT |
355 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
355 | int hdrlen; | 356 | int hdrlen; |
356 | 357 | ||
357 | if (!WLAN_FC_DATA_PRESENT(rx->fc)) | 358 | if (!ieee80211_is_data_present(hdr->frame_control)) |
358 | return; | 359 | return; |
359 | 360 | ||
360 | /* | 361 | /* |
@@ -376,7 +377,7 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) | |||
376 | * header and the payload is not supported, the driver is required | 377 | * header and the payload is not supported, the driver is required |
377 | * to move the 802.11 header further back in that case. | 378 | * to move the 802.11 header further back in that case. |
378 | */ | 379 | */ |
379 | hdrlen = ieee80211_get_hdrlen(rx->fc); | 380 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
380 | if (rx->flags & IEEE80211_RX_AMSDU) | 381 | if (rx->flags & IEEE80211_RX_AMSDU) |
381 | hdrlen += ETH_HLEN; | 382 | hdrlen += ETH_HLEN; |
382 | WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); | 383 | WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); |
@@ -415,14 +416,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
415 | static ieee80211_rx_result | 416 | static ieee80211_rx_result |
416 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | 417 | ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) |
417 | { | 418 | { |
418 | int hdrlen = ieee80211_get_hdrlen(rx->fc); | 419 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
419 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 420 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
420 | 421 | ||
421 | #define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) | 422 | if (ieee80211_is_data(hdr->frame_control)) { |
422 | 423 | if (!ieee80211_has_a4(hdr->frame_control)) | |
423 | if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { | ||
424 | if (!((rx->fc & IEEE80211_FCTL_FROMDS) && | ||
425 | (rx->fc & IEEE80211_FCTL_TODS))) | ||
426 | return RX_DROP_MONITOR; | 424 | return RX_DROP_MONITOR; |
427 | if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) | 425 | if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) |
428 | return RX_DROP_MONITOR; | 426 | return RX_DROP_MONITOR; |
@@ -435,27 +433,30 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
435 | if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { | 433 | if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { |
436 | struct ieee80211_mgmt *mgmt; | 434 | struct ieee80211_mgmt *mgmt; |
437 | 435 | ||
438 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) | 436 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
439 | return RX_DROP_MONITOR; | 437 | return RX_DROP_MONITOR; |
440 | 438 | ||
441 | switch (rx->fc & IEEE80211_FCTL_STYPE) { | 439 | if (ieee80211_is_action(hdr->frame_control)) { |
442 | case IEEE80211_STYPE_ACTION: | ||
443 | mgmt = (struct ieee80211_mgmt *)hdr; | 440 | mgmt = (struct ieee80211_mgmt *)hdr; |
444 | if (mgmt->u.action.category != PLINK_CATEGORY) | 441 | if (mgmt->u.action.category != PLINK_CATEGORY) |
445 | return RX_DROP_MONITOR; | 442 | return RX_DROP_MONITOR; |
446 | /* fall through on else */ | ||
447 | case IEEE80211_STYPE_PROBE_REQ: | ||
448 | case IEEE80211_STYPE_PROBE_RESP: | ||
449 | case IEEE80211_STYPE_BEACON: | ||
450 | return RX_CONTINUE; | 443 | return RX_CONTINUE; |
451 | break; | ||
452 | default: | ||
453 | return RX_DROP_MONITOR; | ||
454 | } | 444 | } |
455 | 445 | ||
456 | } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 446 | if (ieee80211_is_probe_req(hdr->frame_control) || |
457 | is_multicast_ether_addr(hdr->addr1) && | 447 | ieee80211_is_probe_resp(hdr->frame_control) || |
458 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) | 448 | ieee80211_is_beacon(hdr->frame_control)) |
449 | return RX_CONTINUE; | ||
450 | |||
451 | return RX_DROP_MONITOR; | ||
452 | |||
453 | } | ||
454 | |||
455 | #define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) | ||
456 | |||
457 | if (ieee80211_is_data(hdr->frame_control) && | ||
458 | is_multicast_ether_addr(hdr->addr1) && | ||
459 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) | ||
459 | return RX_DROP_MONITOR; | 460 | return RX_DROP_MONITOR; |
460 | #undef msh_h_get | 461 | #undef msh_h_get |
461 | 462 | ||
@@ -466,13 +467,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
466 | static ieee80211_rx_result debug_noinline | 467 | static ieee80211_rx_result debug_noinline |
467 | ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | 468 | ieee80211_rx_h_check(struct ieee80211_rx_data *rx) |
468 | { | 469 | { |
469 | struct ieee80211_hdr *hdr; | 470 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
470 | |||
471 | hdr = (struct ieee80211_hdr *) rx->skb->data; | ||
472 | 471 | ||
473 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ | 472 | /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ |
474 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { | 473 | if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { |
475 | if (unlikely(rx->fc & IEEE80211_FCTL_RETRY && | 474 | if (unlikely(ieee80211_has_retry(hdr->frame_control) && |
476 | rx->sta->last_seq_ctrl[rx->queue] == | 475 | rx->sta->last_seq_ctrl[rx->queue] == |
477 | hdr->seq_ctrl)) { | 476 | hdr->seq_ctrl)) { |
478 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 477 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
@@ -501,15 +500,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
501 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) | 500 | if (ieee80211_vif_is_mesh(&rx->sdata->vif)) |
502 | return ieee80211_rx_mesh_check(rx); | 501 | return ieee80211_rx_mesh_check(rx); |
503 | 502 | ||
504 | if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA || | 503 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
505 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && | 504 | ieee80211_is_pspoll(hdr->frame_control)) && |
506 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && | ||
507 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 505 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
508 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 506 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
509 | if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && | 507 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
510 | !(rx->fc & IEEE80211_FCTL_TODS) && | 508 | !ieee80211_has_tods(hdr->frame_control) && |
511 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) | 509 | ieee80211_is_data(hdr->frame_control)) || |
512 | || !(rx->flags & IEEE80211_RX_RA_MATCH)) { | 510 | !(rx->flags & IEEE80211_RX_RA_MATCH)) { |
513 | /* Drop IBSS frames and frames for other hosts | 511 | /* Drop IBSS frames and frames for other hosts |
514 | * silently. */ | 512 | * silently. */ |
515 | return RX_DROP_MONITOR; | 513 | return RX_DROP_MONITOR; |
@@ -525,7 +523,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
525 | static ieee80211_rx_result debug_noinline | 523 | static ieee80211_rx_result debug_noinline |
526 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | 524 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) |
527 | { | 525 | { |
528 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 526 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
529 | int keyidx; | 527 | int keyidx; |
530 | int hdrlen; | 528 | int hdrlen; |
531 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 529 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
@@ -557,7 +555,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
557 | * possible. | 555 | * possible. |
558 | */ | 556 | */ |
559 | 557 | ||
560 | if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) | 558 | if (!ieee80211_has_protected(hdr->frame_control)) |
561 | return RX_CONTINUE; | 559 | return RX_CONTINUE; |
562 | 560 | ||
563 | /* | 561 | /* |
@@ -586,7 +584,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
586 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 584 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) |
587 | return RX_CONTINUE; | 585 | return RX_CONTINUE; |
588 | 586 | ||
589 | hdrlen = ieee80211_get_hdrlen(rx->fc); | 587 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
590 | 588 | ||
591 | if (rx->skb->len < 8 + hdrlen) | 589 | if (rx->skb->len < 8 + hdrlen) |
592 | return RX_DROP_UNUSABLE; /* TODO: count this? */ | 590 | return RX_DROP_UNUSABLE; /* TODO: count this? */ |
@@ -618,7 +616,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
618 | 616 | ||
619 | /* Check for weak IVs if possible */ | 617 | /* Check for weak IVs if possible */ |
620 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 618 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
621 | ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | 619 | ieee80211_is_data(hdr->frame_control) && |
622 | (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || | 620 | (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || |
623 | !(rx->status->flag & RX_FLAG_DECRYPTED)) && | 621 | !(rx->status->flag & RX_FLAG_DECRYPTED)) && |
624 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | 622 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) |
@@ -710,7 +708,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
710 | { | 708 | { |
711 | struct sta_info *sta = rx->sta; | 709 | struct sta_info *sta = rx->sta; |
712 | struct net_device *dev = rx->dev; | 710 | struct net_device *dev = rx->dev; |
713 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
714 | 712 | ||
715 | if (!sta) | 713 | if (!sta) |
716 | return RX_CONTINUE; | 714 | return RX_CONTINUE; |
@@ -744,21 +742,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
744 | sta->last_qual = rx->status->qual; | 742 | sta->last_qual = rx->status->qual; |
745 | sta->last_noise = rx->status->noise; | 743 | sta->last_noise = rx->status->noise; |
746 | 744 | ||
747 | if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { | 745 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
748 | /* Change STA power saving mode only in the end of a frame | 746 | /* Change STA power saving mode only in the end of a frame |
749 | * exchange sequence */ | 747 | * exchange sequence */ |
750 | if (test_sta_flags(sta, WLAN_STA_PS) && | 748 | if (test_sta_flags(sta, WLAN_STA_PS) && |
751 | !(rx->fc & IEEE80211_FCTL_PM)) | 749 | !ieee80211_has_pm(hdr->frame_control)) |
752 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 750 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); |
753 | else if (!test_sta_flags(sta, WLAN_STA_PS) && | 751 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
754 | (rx->fc & IEEE80211_FCTL_PM)) | 752 | ieee80211_has_pm(hdr->frame_control)) |
755 | ap_sta_ps_start(dev, sta); | 753 | ap_sta_ps_start(dev, sta); |
756 | } | 754 | } |
757 | 755 | ||
758 | /* Drop data::nullfunc frames silently, since they are used only to | 756 | /* Drop data::nullfunc frames silently, since they are used only to |
759 | * control station power saving mode. */ | 757 | * control station power saving mode. */ |
760 | if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 758 | if (ieee80211_is_nullfunc(hdr->frame_control)) { |
761 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) { | ||
762 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); | 759 | I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); |
763 | /* Update counter and free packet here to avoid counting this | 760 | /* Update counter and free packet here to avoid counting this |
764 | * as a dropped packed. */ | 761 | * as a dropped packed. */ |
@@ -1037,19 +1034,19 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1037 | static ieee80211_rx_result debug_noinline | 1034 | static ieee80211_rx_result debug_noinline |
1038 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | 1035 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) |
1039 | { | 1036 | { |
1040 | u16 fc = rx->fc; | ||
1041 | u8 *data = rx->skb->data; | 1037 | u8 *data = rx->skb->data; |
1042 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data; | 1038 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; |
1043 | 1039 | ||
1044 | if (!WLAN_FC_IS_QOS_DATA(fc)) | 1040 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
1045 | return RX_CONTINUE; | 1041 | return RX_CONTINUE; |
1046 | 1042 | ||
1047 | /* remove the qos control field, update frame type and meta-data */ | 1043 | /* remove the qos control field, update frame type and meta-data */ |
1048 | memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2); | 1044 | memmove(data + IEEE80211_QOS_CTL_LEN, data, |
1049 | hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2); | 1045 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); |
1046 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | ||
1050 | /* change frame type to non QOS */ | 1047 | /* change frame type to non QOS */ |
1051 | rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA; | 1048 | rx->fc &= ~IEEE80211_STYPE_QOS_DATA; |
1052 | hdr->frame_control = cpu_to_le16(fc); | 1049 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1053 | 1050 | ||
1054 | return RX_CONTINUE; | 1051 | return RX_CONTINUE; |
1055 | } | 1052 | } |
@@ -1465,15 +1462,15 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1465 | struct ieee80211_local *local = rx->local; | 1462 | struct ieee80211_local *local = rx->local; |
1466 | struct ieee80211_hw *hw = &local->hw; | 1463 | struct ieee80211_hw *hw = &local->hw; |
1467 | struct sk_buff *skb = rx->skb; | 1464 | struct sk_buff *skb = rx->skb; |
1468 | struct ieee80211_bar *bar = (struct ieee80211_bar *) skb->data; | 1465 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; |
1469 | struct tid_ampdu_rx *tid_agg_rx; | 1466 | struct tid_ampdu_rx *tid_agg_rx; |
1470 | u16 start_seq_num; | 1467 | u16 start_seq_num; |
1471 | u16 tid; | 1468 | u16 tid; |
1472 | 1469 | ||
1473 | if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL)) | 1470 | if (likely(!ieee80211_is_ctl(bar->frame_control))) |
1474 | return RX_CONTINUE; | 1471 | return RX_CONTINUE; |
1475 | 1472 | ||
1476 | if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) { | 1473 | if (ieee80211_is_back_req(bar->frame_control)) { |
1477 | if (!rx->sta) | 1474 | if (!rx->sta) |
1478 | return RX_CONTINUE; | 1475 | return RX_CONTINUE; |
1479 | tid = le16_to_cpu(bar->control) >> 12; | 1476 | tid = le16_to_cpu(bar->control) >> 12; |
@@ -1527,11 +1524,12 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1527 | struct ieee80211_hdr *hdr, | 1524 | struct ieee80211_hdr *hdr, |
1528 | struct ieee80211_rx_data *rx) | 1525 | struct ieee80211_rx_data *rx) |
1529 | { | 1526 | { |
1530 | int keyidx, hdrlen; | 1527 | int keyidx; |
1528 | unsigned int hdrlen; | ||
1531 | DECLARE_MAC_BUF(mac); | 1529 | DECLARE_MAC_BUF(mac); |
1532 | DECLARE_MAC_BUF(mac2); | 1530 | DECLARE_MAC_BUF(mac2); |
1533 | 1531 | ||
1534 | hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb); | 1532 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1535 | if (rx->skb->len >= hdrlen + 4) | 1533 | if (rx->skb->len >= hdrlen + 4) |
1536 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 1534 | keyidx = rx->skb->data[hdrlen + 3] >> 6; |
1537 | else | 1535 | else |
@@ -1545,7 +1543,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1545 | goto ignore; | 1543 | goto ignore; |
1546 | } | 1544 | } |
1547 | 1545 | ||
1548 | if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) | 1546 | if (!ieee80211_has_protected(hdr->frame_control)) |
1549 | goto ignore; | 1547 | goto ignore; |
1550 | 1548 | ||
1551 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { | 1549 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { |
@@ -1558,9 +1556,8 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1558 | goto ignore; | 1556 | goto ignore; |
1559 | } | 1557 | } |
1560 | 1558 | ||
1561 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && | 1559 | if (!ieee80211_is_data(hdr->frame_control) && |
1562 | ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || | 1560 | !ieee80211_is_auth(hdr->frame_control)) |
1563 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) | ||
1564 | goto ignore; | 1561 | goto ignore; |
1565 | 1562 | ||
1566 | mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); | 1563 | mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); |
@@ -1731,8 +1728,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1731 | case IEEE80211_IF_TYPE_IBSS: | 1728 | case IEEE80211_IF_TYPE_IBSS: |
1732 | if (!bssid) | 1729 | if (!bssid) |
1733 | return 0; | 1730 | return 0; |
1734 | if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && | 1731 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1735 | (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { | ||
1736 | if (!rx->sta) | 1732 | if (!rx->sta) |
1737 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, | 1733 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, |
1738 | rx->skb, bssid, hdr->addr2, | 1734 | rx->skb, bssid, hdr->addr2, |
@@ -1783,8 +1779,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1783 | return 0; | 1779 | return 0; |
1784 | break; | 1780 | break; |
1785 | case IEEE80211_IF_TYPE_WDS: | 1781 | case IEEE80211_IF_TYPE_WDS: |
1786 | if (bssid || | 1782 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
1787 | (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | ||
1788 | return 0; | 1783 | return 0; |
1789 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 1784 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
1790 | return 0; | 1785 | return 0; |
@@ -2044,7 +2039,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2044 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 2039 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
2045 | goto end_reorder; | 2040 | goto end_reorder; |
2046 | 2041 | ||
2047 | tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK; | 2042 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
2048 | 2043 | ||
2049 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 2044 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2050 | goto end_reorder; | 2045 | goto end_reorder; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d8a16b7f6a6b..47d2c1bbfcaa 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -135,6 +135,7 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | |||
135 | /** | 135 | /** |
136 | * __sta_info_free - internal STA free helper | 136 | * __sta_info_free - internal STA free helper |
137 | * | 137 | * |
138 | * @local: pointer to the global information | ||
138 | * @sta: STA info to free | 139 | * @sta: STA info to free |
139 | * | 140 | * |
140 | * This function must undo everything done by sta_info_alloc() | 141 | * This function must undo everything done by sta_info_alloc() |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index fd228c198e31..94311dcfe043 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -160,11 +160,21 @@ struct sta_ampdu_mlme { | |||
160 | * @list: global linked list entry | 160 | * @list: global linked list entry |
161 | * @hnext: hash table linked list pointer | 161 | * @hnext: hash table linked list pointer |
162 | * @local: pointer to the global information | 162 | * @local: pointer to the global information |
163 | * @sdata: TBD | ||
164 | * @key: TBD | ||
165 | * @rate_ctrl: TBD | ||
166 | * @rate_ctrl_priv: TBD | ||
167 | * @lock: used for locking all fields that require locking, see comments | ||
168 | * in the header file. | ||
169 | * @flaglock: spinlock for flags accesses | ||
170 | * @ht_info: HT capabilities of this STA | ||
171 | * @supp_rates: Bitmap of supported rates (per band) | ||
163 | * @addr: MAC address of this STA | 172 | * @addr: MAC address of this STA |
164 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), | 173 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), |
165 | * only used in AP (and IBSS?) mode | 174 | * only used in AP (and IBSS?) mode |
175 | * @listen_interval: TBD | ||
176 | * @pin_status: TBD | ||
166 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 177 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
167 | * @flaglock: spinlock for flags accesses | ||
168 | * @ps_tx_buf: buffer of frames to transmit to this station | 178 | * @ps_tx_buf: buffer of frames to transmit to this station |
169 | * when it leaves power saving state | 179 | * when it leaves power saving state |
170 | * @tx_filtered: buffer of frames we already tried to transmit | 180 | * @tx_filtered: buffer of frames we already tried to transmit |
@@ -172,10 +182,41 @@ struct sta_ampdu_mlme { | |||
172 | * power saving state | 182 | * power saving state |
173 | * @rx_packets: Number of MSDUs received from this STA | 183 | * @rx_packets: Number of MSDUs received from this STA |
174 | * @rx_bytes: Number of bytes received from this STA | 184 | * @rx_bytes: Number of bytes received from this STA |
175 | * @supp_rates: Bitmap of supported rates (per band) | 185 | * @wep_weak_iv_count: TBD |
176 | * @ht_info: HT capabilities of this STA | 186 | * @last_rx: TBD |
177 | * @lock: used for locking all fields that require locking, see comments | 187 | * @num_duplicates: number of duplicate frames received from this STA |
178 | * in the header file. | 188 | * @rx_fragments: number of received MPDUs |
189 | * @rx_dropped: number of dropped MPDUs from this STA | ||
190 | * @last_signal: signal of last received frame from this STA | ||
191 | * @last_qual: qual of last received frame from this STA | ||
192 | * @last_noise: noise of last received frame from this STA | ||
193 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | ||
194 | * @wme_rx_queue: TBD | ||
195 | * @tx_filtered_count: TBD | ||
196 | * @tx_retry_failed: TBD | ||
197 | * @tx_retry_count: TBD | ||
198 | * @tx_num_consecutive_failures: TBD | ||
199 | * @tx_num_mpdu_ok: TBD | ||
200 | * @tx_num_mpdu_fail: TBD | ||
201 | * @fail_avg: moving percentage of failed MSDUs | ||
202 | * @tx_packets: number of RX/TX MSDUs | ||
203 | * @tx_bytes: TBD | ||
204 | * @tx_fragments: number of transmitted MPDUs | ||
205 | * @txrate_idx: TBD | ||
206 | * @last_txrate_idx: TBD | ||
207 | * @wme_tx_queue: TBD | ||
208 | * @ampdu_mlme: TBD | ||
209 | * @timer_to_tid: identity mapping to ID timers | ||
210 | * @tid_to_tx_q: map tid to tx queue | ||
211 | * @llid: Local link ID | ||
212 | * @plid: Peer link ID | ||
213 | * @reason: Cancel reason on PLINK_HOLDING state | ||
214 | * @plink_retries: Retries in establishment | ||
215 | * @ignore_plink_timer: TBD | ||
216 | * @plink_state plink_state: TBD | ||
217 | * @plink_timeout: TBD | ||
218 | * @plink_timer: TBD | ||
219 | * @debugfs: debug filesystem info | ||
179 | */ | 220 | */ |
180 | struct sta_info { | 221 | struct sta_info { |
181 | /* General information, mostly static */ | 222 | /* General information, mostly static */ |
@@ -217,14 +258,12 @@ struct sta_info { | |||
217 | unsigned long rx_packets, rx_bytes; | 258 | unsigned long rx_packets, rx_bytes; |
218 | unsigned long wep_weak_iv_count; | 259 | unsigned long wep_weak_iv_count; |
219 | unsigned long last_rx; | 260 | unsigned long last_rx; |
220 | unsigned long num_duplicates; /* number of duplicate frames received | 261 | unsigned long num_duplicates; |
221 | * from this STA */ | 262 | unsigned long rx_fragments; |
222 | unsigned long rx_fragments; /* number of received MPDUs */ | 263 | unsigned long rx_dropped; |
223 | unsigned long rx_dropped; /* number of dropped MPDUs from this STA */ | 264 | int last_signal; |
224 | int last_signal; /* signal of last received frame from this STA */ | 265 | int last_qual; |
225 | int last_qual; /* qual of last received frame from this STA */ | 266 | int last_noise; |
226 | int last_noise; /* noise of last received frame from this STA */ | ||
227 | /* last received seq/frag number from this STA (per RX queue) */ | ||
228 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 267 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
229 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 268 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
230 | unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; | 269 | unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; |
@@ -241,9 +280,9 @@ struct sta_info { | |||
241 | unsigned int fail_avg; | 280 | unsigned int fail_avg; |
242 | 281 | ||
243 | /* Updated from TX path only, no locking requirements */ | 282 | /* Updated from TX path only, no locking requirements */ |
244 | unsigned long tx_packets; /* number of RX/TX MSDUs */ | 283 | unsigned long tx_packets; |
245 | unsigned long tx_bytes; | 284 | unsigned long tx_bytes; |
246 | unsigned long tx_fragments; /* number of transmitted MPDUs */ | 285 | unsigned long tx_fragments; |
247 | int txrate_idx; | 286 | int txrate_idx; |
248 | int last_txrate_idx; | 287 | int last_txrate_idx; |
249 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 288 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
@@ -254,18 +293,18 @@ struct sta_info { | |||
254 | * Aggregation information, locked with lock. | 293 | * Aggregation information, locked with lock. |
255 | */ | 294 | */ |
256 | struct sta_ampdu_mlme ampdu_mlme; | 295 | struct sta_ampdu_mlme ampdu_mlme; |
257 | u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ | 296 | u8 timer_to_tid[STA_TID_NUM]; |
258 | u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */ | 297 | u8 tid_to_tx_q[STA_TID_NUM]; |
259 | 298 | ||
260 | #ifdef CONFIG_MAC80211_MESH | 299 | #ifdef CONFIG_MAC80211_MESH |
261 | /* | 300 | /* |
262 | * Mesh peer link attributes | 301 | * Mesh peer link attributes |
263 | * TODO: move to a sub-structure that is referenced with pointer? | 302 | * TODO: move to a sub-structure that is referenced with pointer? |
264 | */ | 303 | */ |
265 | __le16 llid; /* Local link ID */ | 304 | __le16 llid; |
266 | __le16 plid; /* Peer link ID */ | 305 | __le16 plid; |
267 | __le16 reason; /* Cancel reason on PLINK_HOLDING state */ | 306 | __le16 reason; |
268 | u8 plink_retries; /* Retries in establishment */ | 307 | u8 plink_retries; |
269 | bool ignore_plink_timer; | 308 | bool ignore_plink_timer; |
270 | enum plink_state plink_state; | 309 | enum plink_state plink_state; |
271 | u32 plink_timeout; | 310 | u32 plink_timeout; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1babb979fe00..736c32e340f2 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -800,6 +800,8 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, | |||
800 | 800 | ||
801 | if (frag->disabled) | 801 | if (frag->disabled) |
802 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 802 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; |
803 | else if (!frag->fixed) | ||
804 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | ||
803 | else if (frag->value < 256 || | 805 | else if (frag->value < 256 || |
804 | frag->value > IEEE80211_MAX_FRAG_THRESHOLD) | 806 | frag->value > IEEE80211_MAX_FRAG_THRESHOLD) |
805 | return -EINVAL; | 807 | return -EINVAL; |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index ffe1af82fa4d..5c666f7eda8f 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -154,7 +154,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
154 | queue = skb_get_queue_mapping(skb); | 154 | queue = skb_get_queue_mapping(skb); |
155 | rcu_read_lock(); | 155 | rcu_read_lock(); |
156 | sta = sta_info_get(local, hdr->addr1); | 156 | sta = sta_info_get(local, hdr->addr1); |
157 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 157 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
158 | if (sta) { | 158 | if (sta) { |
159 | int ampdu_queue = sta->tid_to_tx_q[tid]; | 159 | int ampdu_queue = sta->tid_to_tx_q[tid]; |
160 | if ((ampdu_queue < QD_NUM(hw)) && | 160 | if ((ampdu_queue < QD_NUM(hw)) && |
@@ -181,7 +181,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
181 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 181 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
182 | u8 *p = ieee80211_get_qos_ctl(hdr); | 182 | u8 *p = ieee80211_get_qos_ctl(hdr); |
183 | u8 ack_policy = 0; | 183 | u8 ack_policy = 0; |
184 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | 184 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
185 | if (local->wifi_wme_noack_test) | 185 | if (local->wifi_wme_noack_test) |
186 | ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << | 186 | ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << |
187 | QOS_CONTROL_ACK_POLICY_SHIFT; | 187 | QOS_CONTROL_ACK_POLICY_SHIFT; |
@@ -210,7 +210,6 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) | |||
210 | kfree_skb(skb); | 210 | kfree_skb(skb); |
211 | err = NET_XMIT_DROP; | 211 | err = NET_XMIT_DROP; |
212 | } else { | 212 | } else { |
213 | tid = skb->priority & QOS_CONTROL_TAG1D_MASK; | ||
214 | skb_set_queue_mapping(skb, queue); | 213 | skb_set_queue_mapping(skb, queue); |
215 | qdisc = q->queues[queue]; | 214 | qdisc = q->queues[queue]; |
216 | err = qdisc->enqueue(skb, qdisc); | 215 | err = qdisc->enqueue(skb, qdisc); |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index bbdb53344817..1aca609eccfc 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -19,18 +19,10 @@ | |||
19 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 | 19 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 |
20 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 | 20 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 |
21 | 21 | ||
22 | #define QOS_CONTROL_TID_MASK 0x0f | ||
23 | #define QOS_CONTROL_ACK_POLICY_SHIFT 5 | 22 | #define QOS_CONTROL_ACK_POLICY_SHIFT 5 |
24 | 23 | ||
25 | #define QOS_CONTROL_TAG1D_MASK 0x07 | ||
26 | |||
27 | extern const int ieee802_1d_to_ac[8]; | 24 | extern const int ieee802_1d_to_ac[8]; |
28 | 25 | ||
29 | static inline int WLAN_FC_IS_QOS_DATA(u16 fc) | ||
30 | { | ||
31 | return (fc & 0x8C) == 0x88; | ||
32 | } | ||
33 | |||
34 | #ifdef CONFIG_MAC80211_QOS | 26 | #ifdef CONFIG_MAC80211_QOS |
35 | void ieee80211_install_qdisc(struct net_device *dev); | 27 | void ieee80211_install_qdisc(struct net_device *dev); |
36 | int ieee80211_qdisc_installed(struct net_device *dev); | 28 | int ieee80211_qdisc_installed(struct net_device *dev); |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b414d5d92f38..2f33df0dcccf 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/compiler.h> | 13 | #include <linux/compiler.h> |
14 | #include <linux/ieee80211.h> | ||
15 | #include <asm/unaligned.h> | ||
14 | #include <net/mac80211.h> | 16 | #include <net/mac80211.h> |
15 | 17 | ||
16 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
@@ -19,53 +21,30 @@ | |||
19 | #include "aes_ccm.h" | 21 | #include "aes_ccm.h" |
20 | #include "wpa.h" | 22 | #include "wpa.h" |
21 | 23 | ||
22 | static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, | ||
23 | u8 *qos_tid, u8 **data, size_t *data_len) | ||
24 | { | ||
25 | struct ieee80211_hdr *hdr; | ||
26 | size_t hdrlen; | ||
27 | __le16 fc; | ||
28 | |||
29 | hdr = (struct ieee80211_hdr *)skb->data; | ||
30 | fc = hdr->frame_control; | ||
31 | |||
32 | hdrlen = ieee80211_hdrlen(fc); | ||
33 | |||
34 | *sa = ieee80211_get_SA(hdr); | ||
35 | *da = ieee80211_get_DA(hdr); | ||
36 | |||
37 | *data = skb->data + hdrlen; | ||
38 | *data_len = skb->len - hdrlen; | ||
39 | |||
40 | if (ieee80211_is_data_qos(fc)) | ||
41 | *qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80; | ||
42 | else | ||
43 | *qos_tid = 0; | ||
44 | |||
45 | return skb->len < hdrlen ? -1 : 0; | ||
46 | } | ||
47 | |||
48 | |||
49 | ieee80211_tx_result | 24 | ieee80211_tx_result |
50 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | 25 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
51 | { | 26 | { |
52 | u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset; | 27 | u8 *data, *key, *mic, key_offset; |
53 | size_t data_len; | 28 | size_t data_len; |
54 | u16 fc; | 29 | unsigned int hdrlen; |
30 | struct ieee80211_hdr *hdr; | ||
55 | struct sk_buff *skb = tx->skb; | 31 | struct sk_buff *skb = tx->skb; |
56 | int authenticator; | 32 | int authenticator; |
57 | int wpa_test = 0; | 33 | int wpa_test = 0; |
58 | int tail; | 34 | int tail; |
59 | 35 | ||
60 | fc = tx->fc; | 36 | hdr = (struct ieee80211_hdr *)skb->data; |
61 | |||
62 | if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || | 37 | if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || |
63 | !WLAN_FC_DATA_PRESENT(fc)) | 38 | !ieee80211_is_data_present(hdr->frame_control)) |
64 | return TX_CONTINUE; | 39 | return TX_CONTINUE; |
65 | 40 | ||
66 | if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) | 41 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
42 | if (skb->len < hdrlen) | ||
67 | return TX_DROP; | 43 | return TX_DROP; |
68 | 44 | ||
45 | data = skb->data + hdrlen; | ||
46 | data_len = skb->len - hdrlen; | ||
47 | |||
69 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 48 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
70 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 49 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
71 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && | 50 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && |
@@ -95,7 +74,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
95 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | 74 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; |
96 | key = &tx->key->conf.key[key_offset]; | 75 | key = &tx->key->conf.key[key_offset]; |
97 | mic = skb_put(skb, MICHAEL_MIC_LEN); | 76 | mic = skb_put(skb, MICHAEL_MIC_LEN); |
98 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 77 | michael_mic(key, hdr, data, data_len, mic); |
99 | 78 | ||
100 | return TX_CONTINUE; | 79 | return TX_CONTINUE; |
101 | } | 80 | } |
@@ -104,31 +83,33 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
104 | ieee80211_rx_result | 83 | ieee80211_rx_result |
105 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | 84 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
106 | { | 85 | { |
107 | u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset; | 86 | u8 *data, *key = NULL, key_offset; |
108 | size_t data_len; | 87 | size_t data_len; |
109 | u16 fc; | 88 | unsigned int hdrlen; |
89 | struct ieee80211_hdr *hdr; | ||
110 | u8 mic[MICHAEL_MIC_LEN]; | 90 | u8 mic[MICHAEL_MIC_LEN]; |
111 | struct sk_buff *skb = rx->skb; | 91 | struct sk_buff *skb = rx->skb; |
112 | int authenticator = 1, wpa_test = 0; | 92 | int authenticator = 1, wpa_test = 0; |
113 | DECLARE_MAC_BUF(mac); | 93 | DECLARE_MAC_BUF(mac); |
114 | 94 | ||
115 | fc = rx->fc; | ||
116 | |||
117 | /* | 95 | /* |
118 | * No way to verify the MIC if the hardware stripped it | 96 | * No way to verify the MIC if the hardware stripped it |
119 | */ | 97 | */ |
120 | if (rx->status->flag & RX_FLAG_MMIC_STRIPPED) | 98 | if (rx->status->flag & RX_FLAG_MMIC_STRIPPED) |
121 | return RX_CONTINUE; | 99 | return RX_CONTINUE; |
122 | 100 | ||
101 | hdr = (struct ieee80211_hdr *)skb->data; | ||
123 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || | 102 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || |
124 | !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc)) | 103 | !ieee80211_has_protected(hdr->frame_control) || |
104 | !ieee80211_is_data_present(hdr->frame_control)) | ||
125 | return RX_CONTINUE; | 105 | return RX_CONTINUE; |
126 | 106 | ||
127 | if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len) | 107 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
128 | || data_len < MICHAEL_MIC_LEN) | 108 | if (skb->len < hdrlen + MICHAEL_MIC_LEN) |
129 | return RX_DROP_UNUSABLE; | 109 | return RX_DROP_UNUSABLE; |
130 | 110 | ||
131 | data_len -= MICHAEL_MIC_LEN; | 111 | data = skb->data + hdrlen; |
112 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; | ||
132 | 113 | ||
133 | #if 0 | 114 | #if 0 |
134 | authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ | 115 | authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ |
@@ -141,7 +122,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
141 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : | 122 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : |
142 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | 123 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; |
143 | key = &rx->key->conf.key[key_offset]; | 124 | key = &rx->key->conf.key[key_offset]; |
144 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 125 | michael_mic(key, hdr, data, data_len, mic); |
145 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { | 126 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { |
146 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 127 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
147 | return RX_DROP_UNUSABLE; | 128 | return RX_DROP_UNUSABLE; |
@@ -253,7 +234,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
253 | 234 | ||
254 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 235 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
255 | 236 | ||
256 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | 237 | if (!ieee80211_is_data(hdr->frame_control)) |
257 | return RX_CONTINUE; | 238 | return RX_CONTINUE; |
258 | 239 | ||
259 | if (!rx->sta || skb->len - hdrlen < 12) | 240 | if (!rx->sta || skb->len - hdrlen < 12) |
@@ -293,70 +274,68 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
293 | } | 274 | } |
294 | 275 | ||
295 | 276 | ||
296 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, | 277 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, |
297 | int encrypted) | 278 | int encrypted) |
298 | { | 279 | { |
299 | u16 fc; | 280 | __le16 mask_fc; |
300 | int a4_included, qos_included; | 281 | int a4_included; |
301 | u8 qos_tid, *fc_pos, *data, *sa, *da; | 282 | u8 qos_tid; |
302 | int len_a; | 283 | u8 *b_0, *aad; |
303 | size_t data_len; | 284 | u16 data_len, len_a; |
304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 285 | unsigned int hdrlen; |
286 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
305 | 287 | ||
306 | fc_pos = (u8 *) &hdr->frame_control; | 288 | b_0 = scratch + 3 * AES_BLOCK_LEN; |
307 | fc = fc_pos[0] ^ (fc_pos[1] << 8); | 289 | aad = scratch + 4 * AES_BLOCK_LEN; |
308 | a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == | 290 | |
309 | (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); | 291 | /* |
310 | 292 | * Mask FC: zero subtype b4 b5 b6 | |
311 | ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len); | 293 | * Retry, PwrMgt, MoreData; set Protected |
312 | data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0); | 294 | */ |
313 | if (qos_tid & 0x80) { | 295 | mask_fc = hdr->frame_control; |
314 | qos_included = 1; | 296 | mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY | |
315 | qos_tid &= 0x0f; | 297 | IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); |
316 | } else | 298 | mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
317 | qos_included = 0; | 299 | |
318 | /* First block, b_0 */ | 300 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
301 | len_a = hdrlen - 2; | ||
302 | a4_included = ieee80211_has_a4(hdr->frame_control); | ||
303 | |||
304 | if (ieee80211_is_data_qos(hdr->frame_control)) | ||
305 | qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | ||
306 | else | ||
307 | qos_tid = 0; | ||
319 | 308 | ||
309 | data_len = skb->len - hdrlen - CCMP_HDR_LEN; | ||
310 | if (encrypted) | ||
311 | data_len -= CCMP_MIC_LEN; | ||
312 | |||
313 | /* First block, b_0 */ | ||
320 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ | 314 | b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ |
321 | /* Nonce: QoS Priority | A2 | PN */ | 315 | /* Nonce: QoS Priority | A2 | PN */ |
322 | b_0[1] = qos_tid; | 316 | b_0[1] = qos_tid; |
323 | memcpy(&b_0[2], hdr->addr2, 6); | 317 | memcpy(&b_0[2], hdr->addr2, ETH_ALEN); |
324 | memcpy(&b_0[8], pn, CCMP_PN_LEN); | 318 | memcpy(&b_0[8], pn, CCMP_PN_LEN); |
325 | /* l(m) */ | 319 | /* l(m) */ |
326 | b_0[14] = (data_len >> 8) & 0xff; | 320 | put_unaligned_be16(data_len, &b_0[14]); |
327 | b_0[15] = data_len & 0xff; | ||
328 | |||
329 | 321 | ||
330 | /* AAD (extra authenticate-only data) / masked 802.11 header | 322 | /* AAD (extra authenticate-only data) / masked 802.11 header |
331 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ | 323 | * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ |
332 | 324 | put_unaligned_be16(len_a, &aad[0]); | |
333 | len_a = a4_included ? 28 : 22; | 325 | put_unaligned(mask_fc, (__le16 *)&aad[2]); |
334 | if (qos_included) | 326 | memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); |
335 | len_a += 2; | ||
336 | |||
337 | aad[0] = 0; /* (len_a >> 8) & 0xff; */ | ||
338 | aad[1] = len_a & 0xff; | ||
339 | /* Mask FC: zero subtype b4 b5 b6 */ | ||
340 | aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6)); | ||
341 | /* Retry, PwrMgt, MoreData; set Protected */ | ||
342 | aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6); | ||
343 | memcpy(&aad[4], &hdr->addr1, 18); | ||
344 | 327 | ||
345 | /* Mask Seq#, leave Frag# */ | 328 | /* Mask Seq#, leave Frag# */ |
346 | aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; | 329 | aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; |
347 | aad[23] = 0; | 330 | aad[23] = 0; |
331 | |||
348 | if (a4_included) { | 332 | if (a4_included) { |
349 | memcpy(&aad[24], hdr->addr4, 6); | 333 | memcpy(&aad[24], hdr->addr4, ETH_ALEN); |
350 | aad[30] = 0; | 334 | aad[30] = qos_tid; |
351 | aad[31] = 0; | 335 | aad[31] = 0; |
352 | } else | 336 | } else { |
353 | memset(&aad[24], 0, 8); | 337 | memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); |
354 | if (qos_included) { | 338 | aad[24] = qos_tid; |
355 | u8 *dpos = &aad[a4_included ? 30 : 24]; | ||
356 | |||
357 | /* Mask QoS Control field */ | ||
358 | dpos[0] = qos_tid; | ||
359 | dpos[1] = 0; | ||
360 | } | 339 | } |
361 | } | 340 | } |
362 | 341 | ||
@@ -392,7 +371,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
392 | struct ieee80211_key *key = tx->key; | 371 | struct ieee80211_key *key = tx->key; |
393 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 372 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
394 | int hdrlen, len, tail; | 373 | int hdrlen, len, tail; |
395 | u8 *pos, *pn, *b_0, *aad, *scratch; | 374 | u8 *pos, *pn; |
396 | int i; | 375 | int i; |
397 | 376 | ||
398 | info->control.icv_len = CCMP_MIC_LEN; | 377 | info->control.icv_len = CCMP_MIC_LEN; |
@@ -406,10 +385,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
406 | return 0; | 385 | return 0; |
407 | } | 386 | } |
408 | 387 | ||
409 | scratch = key->u.ccmp.tx_crypto_buf; | ||
410 | b_0 = scratch + 3 * AES_BLOCK_LEN; | ||
411 | aad = scratch + 4 * AES_BLOCK_LEN; | ||
412 | |||
413 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 388 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
414 | len = skb->len - hdrlen; | 389 | len = skb->len - hdrlen; |
415 | 390 | ||
@@ -445,8 +420,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
445 | } | 420 | } |
446 | 421 | ||
447 | pos += CCMP_HDR_LEN; | 422 | pos += CCMP_HDR_LEN; |
448 | ccmp_special_blocks(skb, pn, b_0, aad, 0); | 423 | ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); |
449 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, len, | 424 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, |
450 | pos, skb_put(skb, CCMP_MIC_LEN)); | 425 | pos, skb_put(skb, CCMP_MIC_LEN)); |
451 | 426 | ||
452 | return 0; | 427 | return 0; |
@@ -478,7 +453,7 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | |||
478 | ieee80211_rx_result | 453 | ieee80211_rx_result |
479 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | 454 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) |
480 | { | 455 | { |
481 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 456 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
482 | int hdrlen; | 457 | int hdrlen; |
483 | struct ieee80211_key *key = rx->key; | 458 | struct ieee80211_key *key = rx->key; |
484 | struct sk_buff *skb = rx->skb; | 459 | struct sk_buff *skb = rx->skb; |
@@ -488,7 +463,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
488 | 463 | ||
489 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 464 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
490 | 465 | ||
491 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) | 466 | if (!ieee80211_is_data(hdr->frame_control)) |
492 | return RX_CONTINUE; | 467 | return RX_CONTINUE; |
493 | 468 | ||
494 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; | 469 | data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; |
@@ -508,16 +483,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
508 | 483 | ||
509 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 484 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { |
510 | /* hardware didn't decrypt/verify MIC */ | 485 | /* hardware didn't decrypt/verify MIC */ |
511 | u8 *scratch, *b_0, *aad; | 486 | ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); |
512 | |||
513 | scratch = key->u.ccmp.rx_crypto_buf; | ||
514 | b_0 = scratch + 3 * AES_BLOCK_LEN; | ||
515 | aad = scratch + 4 * AES_BLOCK_LEN; | ||
516 | |||
517 | ccmp_special_blocks(skb, pn, b_0, aad, 1); | ||
518 | 487 | ||
519 | if (ieee80211_aes_ccm_decrypt( | 488 | if (ieee80211_aes_ccm_decrypt( |
520 | key->u.ccmp.tfm, scratch, b_0, aad, | 489 | key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, |
521 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, | 490 | skb->data + hdrlen + CCMP_HDR_LEN, data_len, |
522 | skb->data + skb->len - CCMP_MIC_LEN, | 491 | skb->data + skb->len - CCMP_MIC_LEN, |
523 | skb->data + hdrlen + CCMP_HDR_LEN)) { | 492 | skb->data + hdrlen + CCMP_HDR_LEN)) { |
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index ce0e23148cdd..7a560b785097 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -130,17 +130,19 @@ static void update_rfkill_state(struct rfkill *rfkill) | |||
130 | 130 | ||
131 | /** | 131 | /** |
132 | * rfkill_toggle_radio - wrapper for toggle_radio hook | 132 | * rfkill_toggle_radio - wrapper for toggle_radio hook |
133 | * calls toggle_radio taking into account a lot of "small" | 133 | * |
134 | * details. | ||
135 | * @rfkill: the rfkill struct to use | 134 | * @rfkill: the rfkill struct to use |
136 | * @force: calls toggle_radio even if cache says it is not needed, | 135 | * @force: calls toggle_radio even if cache says it is not needed, |
137 | * and also makes sure notifications of the state will be | 136 | * and also makes sure notifications of the state will be |
138 | * sent even if it didn't change | 137 | * sent even if it didn't change |
139 | * @state: the new state to call toggle_radio() with | 138 | * @state: the new state to call toggle_radio() with |
140 | * | 139 | * |
141 | * This wrappen protects and enforces the API for toggle_radio | 140 | * Calls rfkill->toggle_radio, enforcing the API for toggle_radio |
142 | * calls. Note that @force cannot override a (possibly cached) | 141 | * calls and handling all the red tape such as issuing notifications |
143 | * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of | 142 | * if the call is successful. |
143 | * | ||
144 | * Note that @force cannot override a (possibly cached) state of | ||
145 | * RFKILL_STATE_HARD_BLOCKED. Any device making use of | ||
144 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or | 146 | * RFKILL_STATE_HARD_BLOCKED implements either get_state() or |
145 | * rfkill_force_state(), so the cache either is bypassed or valid. | 147 | * rfkill_force_state(), so the cache either is bypassed or valid. |
146 | * | 148 | * |
@@ -499,17 +501,15 @@ static struct class rfkill_class = { | |||
499 | 501 | ||
500 | static int rfkill_add_switch(struct rfkill *rfkill) | 502 | static int rfkill_add_switch(struct rfkill *rfkill) |
501 | { | 503 | { |
502 | int error; | ||
503 | |||
504 | mutex_lock(&rfkill_mutex); | 504 | mutex_lock(&rfkill_mutex); |
505 | 505 | ||
506 | error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); | 506 | rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); |
507 | if (!error) | 507 | |
508 | list_add_tail(&rfkill->node, &rfkill_list); | 508 | list_add_tail(&rfkill->node, &rfkill_list); |
509 | 509 | ||
510 | mutex_unlock(&rfkill_mutex); | 510 | mutex_unlock(&rfkill_mutex); |
511 | 511 | ||
512 | return error; | 512 | return 0; |
513 | } | 513 | } |
514 | 514 | ||
515 | static void rfkill_remove_switch(struct rfkill *rfkill) | 515 | static void rfkill_remove_switch(struct rfkill *rfkill) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fb75f265b39c..b7fefffd2d0d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -199,12 +199,14 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
199 | 199 | ||
200 | mutex_lock(&cfg80211_drv_mutex); | 200 | mutex_lock(&cfg80211_drv_mutex); |
201 | list_for_each_entry(dev, &cfg80211_drv_list, list) { | 201 | list_for_each_entry(dev, &cfg80211_drv_list, list) { |
202 | if (++idx < start) | 202 | if (++idx <= start) |
203 | continue; | 203 | continue; |
204 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, | 204 | if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, |
205 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 205 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
206 | dev) < 0) | 206 | dev) < 0) { |
207 | idx--; | ||
207 | break; | 208 | break; |
209 | } | ||
208 | } | 210 | } |
209 | mutex_unlock(&cfg80211_drv_mutex); | 211 | mutex_unlock(&cfg80211_drv_mutex); |
210 | 212 | ||