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 /drivers | |
parent | 11a100f844f6096787ab20e19f17d72abc957a8f (diff) | |
parent | b46372710ab536c0967f76be5dc41341583d4a54 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers')
30 files changed, 1090 insertions, 395 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); |