diff options
author | David S. Miller <davem@davemloft.net> | 2009-10-29 05:47:13 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-29 05:47:13 -0400 |
commit | ed3f2e40f3d438f4a1ec0a898173116cb26f106a (patch) | |
tree | f50e1c5f5f3511539084d9529e592e3fb0352607 /drivers | |
parent | fb699dfd426a189fe33b91586c15176a75c8aed0 (diff) | |
parent | bd6b4442ff3cee73f73987cf0c0e66ea677aa075 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers')
127 files changed, 13359 insertions, 5923 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 7116a1aa20ce..e265ba14054b 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -5660,7 +5660,8 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
5660 | 5660 | ||
5661 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); | 5661 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); |
5662 | pci_save_state(pdev); | 5662 | pci_save_state(pdev); |
5663 | return pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 5663 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
5664 | return 0; | ||
5664 | } | 5665 | } |
5665 | 5666 | ||
5666 | static int airo_pci_resume(struct pci_dev *pdev) | 5667 | static int airo_pci_resume(struct pci_dev *pdev) |
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index ec034af26980..9f9459860d82 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -231,7 +231,7 @@ struct ar9170 { | |||
231 | struct sk_buff_head tx_status_ampdu; | 231 | struct sk_buff_head tx_status_ampdu; |
232 | spinlock_t tx_ampdu_list_lock; | 232 | spinlock_t tx_ampdu_list_lock; |
233 | struct list_head tx_ampdu_list; | 233 | struct list_head tx_ampdu_list; |
234 | unsigned int tx_ampdu_pending; | 234 | atomic_t tx_ampdu_pending; |
235 | 235 | ||
236 | /* rxstream mpdu merge */ | 236 | /* rxstream mpdu merge */ |
237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; | 237 | struct ar9170_rxstream_mpdu_merge rx_mpdu; |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 88113148331c..701ddb7d8400 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -152,14 +152,14 @@ enum ar9170_cmd { | |||
152 | #define AR9170_MAC_REG_FTF_BIT14 BIT(14) | 152 | #define AR9170_MAC_REG_FTF_BIT14 BIT(14) |
153 | #define AR9170_MAC_REG_FTF_BIT15 BIT(15) | 153 | #define AR9170_MAC_REG_FTF_BIT15 BIT(15) |
154 | #define AR9170_MAC_REG_FTF_BAR BIT(24) | 154 | #define AR9170_MAC_REG_FTF_BAR BIT(24) |
155 | #define AR9170_MAC_REG_FTF_BIT25 BIT(25) | 155 | #define AR9170_MAC_REG_FTF_BA BIT(25) |
156 | #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) | 156 | #define AR9170_MAC_REG_FTF_PSPOLL BIT(26) |
157 | #define AR9170_MAC_REG_FTF_RTS BIT(27) | 157 | #define AR9170_MAC_REG_FTF_RTS BIT(27) |
158 | #define AR9170_MAC_REG_FTF_CTS BIT(28) | 158 | #define AR9170_MAC_REG_FTF_CTS BIT(28) |
159 | #define AR9170_MAC_REG_FTF_ACK BIT(29) | 159 | #define AR9170_MAC_REG_FTF_ACK BIT(29) |
160 | #define AR9170_MAC_REG_FTF_CFE BIT(30) | 160 | #define AR9170_MAC_REG_FTF_CFE BIT(30) |
161 | #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) | 161 | #define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) |
162 | #define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff | 162 | #define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff |
163 | #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff | 163 | #define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff |
164 | 164 | ||
165 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) | 165 | #define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index de0ba2bf7691..7e59b82e64d3 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) | |||
414 | 414 | ||
415 | skb_queue_tail(&ar->tx_status_ampdu, skb); | 415 | skb_queue_tail(&ar->tx_status_ampdu, skb); |
416 | ar9170_tx_fake_ampdu_status(ar); | 416 | ar9170_tx_fake_ampdu_status(ar); |
417 | ar->tx_ampdu_pending--; | ||
418 | 417 | ||
419 | if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) | 418 | if (atomic_dec_and_test(&ar->tx_ampdu_pending) && |
419 | !list_empty(&ar->tx_ampdu_list)) | ||
420 | ar9170_tx_ampdu(ar); | 420 | ar9170_tx_ampdu(ar); |
421 | } | 421 | } |
422 | 422 | ||
@@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1248 | ar->global_ampdu_density = 6; | 1248 | ar->global_ampdu_density = 6; |
1249 | ar->global_ampdu_factor = 3; | 1249 | ar->global_ampdu_factor = 3; |
1250 | 1250 | ||
1251 | atomic_set(&ar->tx_ampdu_pending, 0); | ||
1251 | ar->bad_hw_nagger = jiffies; | 1252 | ar->bad_hw_nagger = jiffies; |
1252 | 1253 | ||
1253 | err = ar->open(ar); | 1254 | err = ar->open(ar); |
@@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1773 | msecs_to_jiffies(AR9170_TX_TIMEOUT); | 1774 | msecs_to_jiffies(AR9170_TX_TIMEOUT); |
1774 | 1775 | ||
1775 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1776 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1776 | ar->tx_ampdu_pending++; | 1777 | atomic_inc(&ar->tx_ampdu_pending); |
1777 | 1778 | ||
1778 | #ifdef AR9170_QUEUE_DEBUG | 1779 | #ifdef AR9170_QUEUE_DEBUG |
1779 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", | 1780 | printk(KERN_DEBUG "%s: send frame q:%d =>\n", |
@@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1784 | err = ar->tx(ar, skb); | 1785 | err = ar->tx(ar, skb); |
1785 | if (unlikely(err)) { | 1786 | if (unlikely(err)) { |
1786 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) | 1787 | if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) |
1787 | ar->tx_ampdu_pending--; | 1788 | atomic_dec(&ar->tx_ampdu_pending); |
1788 | 1789 | ||
1789 | frames_failed++; | 1790 | frames_failed++; |
1790 | dev_kfree_skb_any(skb); | 1791 | dev_kfree_skb_any(skb); |
@@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1931 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | 1932 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { |
1932 | bool run = ar9170_tx_ampdu_queue(ar, skb); | 1933 | bool run = ar9170_tx_ampdu_queue(ar, skb); |
1933 | 1934 | ||
1934 | if (run || !ar->tx_ampdu_pending) | 1935 | if (run || !atomic_read(&ar->tx_ampdu_pending)) |
1935 | ar9170_tx_ampdu(ar); | 1936 | ar9170_tx_ampdu(ar); |
1936 | } else { | 1937 | } else { |
1937 | unsigned int queue = skb_get_queue_mapping(skb); | 1938 | unsigned int queue = skb_get_queue_mapping(skb); |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..6bdcdf6d1cc0 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -108,15 +108,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
108 | return ; | 108 | return ; |
109 | 109 | ||
110 | spin_lock_irqsave(&aru->tx_urb_lock, flags); | 110 | spin_lock_irqsave(&aru->tx_urb_lock, flags); |
111 | if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { | 111 | if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { |
112 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 112 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
113 | return ; | 113 | return ; |
114 | } | 114 | } |
115 | aru->tx_submitted_urbs++; | 115 | atomic_inc(&aru->tx_submitted_urbs); |
116 | 116 | ||
117 | urb = usb_get_from_anchor(&aru->tx_pending); | 117 | urb = usb_get_from_anchor(&aru->tx_pending); |
118 | if (!urb) { | 118 | if (!urb) { |
119 | aru->tx_submitted_urbs--; | 119 | atomic_dec(&aru->tx_submitted_urbs); |
120 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 120 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
121 | 121 | ||
122 | return ; | 122 | return ; |
@@ -133,7 +133,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
133 | err); | 133 | err); |
134 | 134 | ||
135 | usb_unanchor_urb(urb); | 135 | usb_unanchor_urb(urb); |
136 | aru->tx_submitted_urbs--; | 136 | atomic_dec(&aru->tx_submitted_urbs); |
137 | ar9170_tx_callback(&aru->common, urb->context); | 137 | ar9170_tx_callback(&aru->common, urb->context); |
138 | } | 138 | } |
139 | 139 | ||
@@ -151,7 +151,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) | |||
151 | return ; | 151 | return ; |
152 | } | 152 | } |
153 | 153 | ||
154 | aru->tx_submitted_urbs--; | 154 | atomic_dec(&aru->tx_submitted_urbs); |
155 | 155 | ||
156 | ar9170_tx_callback(&aru->common, skb); | 156 | ar9170_tx_callback(&aru->common, skb); |
157 | 157 | ||
@@ -794,7 +794,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
794 | spin_lock_init(&aru->tx_urb_lock); | 794 | spin_lock_init(&aru->tx_urb_lock); |
795 | 795 | ||
796 | aru->tx_pending_urbs = 0; | 796 | aru->tx_pending_urbs = 0; |
797 | aru->tx_submitted_urbs = 0; | 797 | atomic_set(&aru->tx_submitted_urbs, 0); |
798 | 798 | ||
799 | aru->common.stop = ar9170_usb_stop; | 799 | aru->common.stop = ar9170_usb_stop; |
800 | aru->common.flush = ar9170_usb_flush; | 800 | aru->common.flush = ar9170_usb_flush; |
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index d098f4d5d2f2..a2ce3b169ceb 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h | |||
@@ -67,7 +67,7 @@ struct ar9170_usb { | |||
67 | bool req_one_stage_fw; | 67 | bool req_one_stage_fw; |
68 | 68 | ||
69 | spinlock_t tx_urb_lock; | 69 | spinlock_t tx_urb_lock; |
70 | unsigned int tx_submitted_urbs; | 70 | atomic_t tx_submitted_urbs; |
71 | unsigned int tx_pending_urbs; | 71 | unsigned int tx_pending_urbs; |
72 | 72 | ||
73 | struct completion cmd_wait; | 73 | struct completion cmd_wait; |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 647d826bf5fb..6a2a96761111 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -198,6 +198,7 @@ | |||
198 | #define AR5K_TUNE_CWMAX_11B 1023 | 198 | #define AR5K_TUNE_CWMAX_11B 1023 |
199 | #define AR5K_TUNE_CWMAX_XR 7 | 199 | #define AR5K_TUNE_CWMAX_XR 7 |
200 | #define AR5K_TUNE_NOISE_FLOOR -72 | 200 | #define AR5K_TUNE_NOISE_FLOOR -72 |
201 | #define AR5K_TUNE_CCA_MAX_GOOD_VALUE -95 | ||
201 | #define AR5K_TUNE_MAX_TXPOWER 63 | 202 | #define AR5K_TUNE_MAX_TXPOWER 63 |
202 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
203 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
@@ -1006,6 +1007,14 @@ struct ath5k_capabilities { | |||
1006 | } cap_queues; | 1007 | } cap_queues; |
1007 | }; | 1008 | }; |
1008 | 1009 | ||
1010 | /* size of noise floor history (keep it a power of two) */ | ||
1011 | #define ATH5K_NF_CAL_HIST_MAX 8 | ||
1012 | struct ath5k_nfcal_hist | ||
1013 | { | ||
1014 | s16 index; /* current index into nfval */ | ||
1015 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | ||
1016 | }; | ||
1017 | |||
1009 | 1018 | ||
1010 | /***************************************\ | 1019 | /***************************************\ |
1011 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1020 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1112,6 +1121,8 @@ struct ath5k_hw { | |||
1112 | struct ieee80211_channel r_last_channel; | 1121 | struct ieee80211_channel r_last_channel; |
1113 | } ah_radar; | 1122 | } ah_radar; |
1114 | 1123 | ||
1124 | struct ath5k_nfcal_hist ah_nfcal_hist; | ||
1125 | |||
1115 | /* noise floor from last periodic calibration */ | 1126 | /* noise floor from last periodic calibration */ |
1116 | s32 ah_noise_floor; | 1127 | s32 ah_noise_floor; |
1117 | 1128 | ||
@@ -1274,8 +1285,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | |||
1274 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1285 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1275 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1286 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1276 | /* PHY calibration */ | 1287 | /* PHY calibration */ |
1288 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | ||
1277 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1289 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1278 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1290 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); |
1291 | extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); | ||
1279 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | 1292 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); |
1280 | /* Spur mitigation */ | 1293 | /* Spur mitigation */ |
1281 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1294 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 92995adeb5cd..42284445b75e 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -331,6 +331,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
331 | 331 | ||
332 | ath5k_hw_rfgain_opt_init(ah); | 332 | ath5k_hw_rfgain_opt_init(ah); |
333 | 333 | ||
334 | ath5k_hw_init_nfcal_hist(ah); | ||
335 | |||
334 | /* turn on HW LEDs */ | 336 | /* turn on HW LEDs */ |
335 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); | 337 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); |
336 | 338 | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd732..895990751d36 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) | |||
1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | 1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; |
1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | 1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); |
1126 | } | 1126 | } |
1127 | } | ||
1127 | 1128 | ||
1129 | static int sign_extend(int val, const int nbits) | ||
1130 | { | ||
1131 | int order = BIT(nbits-1); | ||
1132 | return (val ^ order) - order; | ||
1128 | } | 1133 | } |
1129 | 1134 | ||
1130 | /** | 1135 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
1131 | * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration | 1136 | { |
1132 | * | 1137 | s32 val; |
1133 | * @ah: struct ath5k_hw pointer we are operating on | 1138 | |
1134 | * @freq: the channel frequency, just used for error logging | 1139 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
1135 | * | 1140 | return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); |
1136 | * This function performs a noise floor calibration of the PHY and waits for | 1141 | } |
1137 | * it to complete. Then the noise floor value is compared to some maximum | 1142 | |
1138 | * noise floor we consider valid. | 1143 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
1139 | * | 1144 | { |
1140 | * Note that this is different from what the madwifi HAL does: it reads the | 1145 | int i; |
1141 | * noise floor and afterwards initiates the calibration. Since the noise floor | 1146 | |
1142 | * calibration can take some time to finish, depending on the current channel | 1147 | ah->ah_nfcal_hist.index = 0; |
1143 | * use, that avoids the occasional timeout warnings we are seeing now. | 1148 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) |
1144 | * | 1149 | ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; |
1145 | * See the following link for an Atheros patent on noise floor calibration: | 1150 | } |
1146 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ | 1151 | |
1147 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 | 1152 | static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) |
1153 | { | ||
1154 | struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; | ||
1155 | hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1); | ||
1156 | hist->nfval[hist->index] = noise_floor; | ||
1157 | } | ||
1158 | |||
1159 | static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | ||
1160 | { | ||
1161 | s16 sort[ATH5K_NF_CAL_HIST_MAX]; | ||
1162 | s16 tmp; | ||
1163 | int i, j; | ||
1164 | |||
1165 | memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort)); | ||
1166 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) { | ||
1167 | for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { | ||
1168 | if (sort[j] > sort[j-1]) { | ||
1169 | tmp = sort[j]; | ||
1170 | sort[j] = sort[j-1]; | ||
1171 | sort[j-1] = tmp; | ||
1172 | } | ||
1173 | } | ||
1174 | } | ||
1175 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { | ||
1176 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1177 | "cal %d:%d\n", i, sort[i]); | ||
1178 | } | ||
1179 | return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2]; | ||
1180 | } | ||
1181 | |||
1182 | /* | ||
1183 | * When we tell the hardware to perform a noise floor calibration | ||
1184 | * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically | ||
1185 | * sample-and-hold the minimum noise level seen at the antennas. | ||
1186 | * This value is then stored in a ring buffer of recently measured | ||
1187 | * noise floor values so we have a moving window of the last few | ||
1188 | * samples. | ||
1148 | * | 1189 | * |
1149 | * XXX: Since during noise floor calibration antennas are detached according to | 1190 | * The median of the values in the history is then loaded into the |
1150 | * the patent, we should stop tx queues here. | 1191 | * hardware for its own use for RSSI and CCA measurements. |
1151 | */ | 1192 | */ |
1152 | int | 1193 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1153 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | ||
1154 | { | 1194 | { |
1155 | int ret; | 1195 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1156 | unsigned int i; | 1196 | u32 val; |
1157 | s32 noise_floor; | 1197 | s16 nf, threshold; |
1198 | u8 ee_mode; | ||
1158 | 1199 | ||
1159 | /* | 1200 | /* keep last value if calibration hasn't completed */ |
1160 | * Enable noise floor calibration | 1201 | if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) { |
1161 | */ | 1202 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, |
1162 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1203 | "NF did not complete in calibration window\n"); |
1163 | AR5K_PHY_AGCCTL_NF); | ||
1164 | 1204 | ||
1165 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | 1205 | return; |
1166 | AR5K_PHY_AGCCTL_NF, 0, false); | ||
1167 | if (ret) { | ||
1168 | ATH5K_ERR(ah->ah_sc, | ||
1169 | "noise floor calibration timeout (%uMHz)\n", freq); | ||
1170 | return -EAGAIN; | ||
1171 | } | 1206 | } |
1172 | 1207 | ||
1173 | /* Wait until the noise floor is calibrated and read the value */ | 1208 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { |
1174 | for (i = 20; i > 0; i--) { | 1209 | case CHANNEL_A: |
1175 | mdelay(1); | 1210 | case CHANNEL_T: |
1176 | noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1211 | case CHANNEL_XR: |
1177 | noise_floor = AR5K_PHY_NF_RVAL(noise_floor); | 1212 | ee_mode = AR5K_EEPROM_MODE_11A; |
1178 | if (noise_floor & AR5K_PHY_NF_ACTIVE) { | 1213 | break; |
1179 | noise_floor = AR5K_PHY_NF_AVAL(noise_floor); | 1214 | case CHANNEL_G: |
1180 | 1215 | case CHANNEL_TG: | |
1181 | if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) | 1216 | ee_mode = AR5K_EEPROM_MODE_11G; |
1182 | break; | 1217 | break; |
1183 | } | 1218 | default: |
1219 | case CHANNEL_B: | ||
1220 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1221 | break; | ||
1184 | } | 1222 | } |
1185 | 1223 | ||
1186 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1187 | "noise floor %d\n", noise_floor); | ||
1188 | 1224 | ||
1189 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { | 1225 | /* completed NF calibration, test threshold */ |
1190 | ATH5K_ERR(ah->ah_sc, | 1226 | nf = ath5k_hw_read_measured_noise_floor(ah); |
1191 | "noise floor calibration failed (%uMHz)\n", freq); | 1227 | threshold = ee->ee_noise_floor_thr[ee_mode]; |
1192 | return -EAGAIN; | 1228 | |
1229 | if (nf > threshold) { | ||
1230 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1231 | "noise floor failure detected; " | ||
1232 | "read %d, threshold %d\n", | ||
1233 | nf, threshold); | ||
1234 | |||
1235 | nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE; | ||
1193 | } | 1236 | } |
1194 | 1237 | ||
1195 | ah->ah_noise_floor = noise_floor; | 1238 | ath5k_hw_update_nfcal_hist(ah, nf); |
1239 | nf = ath5k_hw_get_median_noise_floor(ah); | ||
1196 | 1240 | ||
1197 | return 0; | 1241 | /* load noise floor (in .5 dBm) so the hardware will use it */ |
1242 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M; | ||
1243 | val |= (nf * 2) & AR5K_PHY_NF_M; | ||
1244 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1245 | |||
1246 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1247 | ~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE)); | ||
1248 | |||
1249 | ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1250 | 0, false); | ||
1251 | |||
1252 | /* | ||
1253 | * Load a high max CCA Power value (-50 dBm in .5 dBm units) | ||
1254 | * so that we're not capped by the median we just loaded. | ||
1255 | * This will be used as the initial value for the next noise | ||
1256 | * floor calibration. | ||
1257 | */ | ||
1258 | val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M); | ||
1259 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1260 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1261 | AR5K_PHY_AGCCTL_NF_EN | | ||
1262 | AR5K_PHY_AGCCTL_NF_NOUPDATE | | ||
1263 | AR5K_PHY_AGCCTL_NF); | ||
1264 | |||
1265 | ah->ah_noise_floor = nf; | ||
1266 | |||
1267 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1268 | "noise floor calibrated: %d\n", nf); | ||
1198 | } | 1269 | } |
1199 | 1270 | ||
1200 | /* | 1271 | /* |
@@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1287 | return ret; | 1358 | return ret; |
1288 | } | 1359 | } |
1289 | 1360 | ||
1290 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1361 | ath5k_hw_update_noise_floor(ah); |
1291 | 1362 | ||
1292 | /* | 1363 | /* |
1293 | * Re-enable RX/TX and beacons | 1364 | * Re-enable RX/TX and beacons |
@@ -1360,7 +1431,7 @@ done: | |||
1360 | * since noise floor calibration interrupts rx path while I/Q | 1431 | * since noise floor calibration interrupts rx path while I/Q |
1361 | * calibration doesn't. We don't need to run noise floor calibration | 1432 | * calibration doesn't. We don't need to run noise floor calibration |
1362 | * as often as I/Q calibration.*/ | 1433 | * as often as I/Q calibration.*/ |
1363 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1434 | ath5k_hw_update_noise_floor(ah); |
1364 | 1435 | ||
1365 | /* Initiate a gain_F calibration */ | 1436 | /* Initiate a gain_F calibration */ |
1366 | ath5k_hw_request_rfgain_probe(ah); | 1437 | ath5k_hw_request_rfgain_probe(ah); |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 64227abe3c20..4cb9c5df9f46 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -2033,17 +2033,14 @@ | |||
2033 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ | 2033 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ |
2034 | 2034 | ||
2035 | /* | 2035 | /* |
2036 | * PHY noise floor status register | 2036 | * PHY noise floor status register (CCA = Clear Channel Assessment) |
2037 | */ | 2037 | */ |
2038 | #define AR5K_PHY_NF 0x9864 /* Register address */ | 2038 | #define AR5K_PHY_NF 0x9864 /* Register address */ |
2039 | #define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ | 2039 | #define AR5K_PHY_NF_M 0x000001ff /* Noise floor, written to hardware in 1/2 dBm units */ |
2040 | #define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ | 2040 | #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) |
2041 | #define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) | ||
2042 | #define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) | ||
2043 | #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) | ||
2044 | #define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ | 2041 | #define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ |
2045 | #define AR5K_PHY_NF_THRESH62_S 12 | 2042 | #define AR5K_PHY_NF_THRESH62_S 12 |
2046 | #define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ | 2043 | #define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* Minimum measured noise level, read from hardware in 1 dBm units */ |
2047 | #define AR5K_PHY_NF_MINCCA_PWR_S 19 | 2044 | #define AR5K_PHY_NF_MINCCA_PWR_S 19 |
2048 | 2045 | ||
2049 | /* | 2046 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 3dab3d856d7b..62954fc77869 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -1293,7 +1293,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1293 | * out and/or noise floor calibration might timeout. | 1293 | * out and/or noise floor calibration might timeout. |
1294 | */ | 1294 | */ |
1295 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1295 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
1296 | AR5K_PHY_AGCCTL_CAL); | 1296 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); |
1297 | 1297 | ||
1298 | /* At the same time start I/Q calibration for QAM constellation | 1298 | /* At the same time start I/Q calibration for QAM constellation |
1299 | * -no need for CCK- */ | 1299 | * -no need for CCK- */ |
@@ -1314,21 +1314,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1314 | channel->center_freq); | 1314 | channel->center_freq); |
1315 | } | 1315 | } |
1316 | 1316 | ||
1317 | /* | ||
1318 | * If we run NF calibration before AGC, it always times out. | ||
1319 | * Binary HAL starts NF and AGC calibration at the same time | ||
1320 | * and only waits for AGC to finish. Also if AGC or NF cal. | ||
1321 | * times out, reset doesn't fail on binary HAL. I believe | ||
1322 | * that's wrong because since rx path is routed to a detector, | ||
1323 | * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 | ||
1324 | * enables noise floor calibration after offset calibration and if noise | ||
1325 | * floor calibration fails, reset fails. I believe that's | ||
1326 | * a better approach, we just need to find a polling interval | ||
1327 | * that suits best, even if reset continues we need to make | ||
1328 | * sure that rx path is ready. | ||
1329 | */ | ||
1330 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | ||
1331 | |||
1332 | /* Restore antenna mode */ | 1317 | /* Restore antenna mode */ |
1333 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | 1318 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
1334 | 1319 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 33c9e8167185..25531f231b67 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -29,15 +29,13 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) | |||
29 | 29 | ||
30 | static void ath_ahb_cleanup(struct ath_common *common) | 30 | static void ath_ahb_cleanup(struct ath_common *common) |
31 | { | 31 | { |
32 | struct ath_hw *ah = (struct ath_hw *) common->ah; | 32 | struct ath_softc *sc = (struct ath_softc *)common->priv; |
33 | struct ath_softc *sc = ah->ah_sc; | ||
34 | iounmap(sc->mem); | 33 | iounmap(sc->mem); |
35 | } | 34 | } |
36 | 35 | ||
37 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 36 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
38 | { | 37 | { |
39 | struct ath_hw *ah = (struct ath_hw *) common->ah; | 38 | struct ath_softc *sc = (struct ath_softc *)common->priv; |
40 | struct ath_softc *sc = ah->ah_sc; | ||
41 | struct platform_device *pdev = to_platform_device(sc->dev); | 39 | struct platform_device *pdev = to_platform_device(sc->dev); |
42 | struct ath9k_platform_data *pdata; | 40 | struct ath9k_platform_data *pdata; |
43 | 41 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index f46bd05df443..551f8801459f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -813,7 +813,7 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah) | |||
813 | } | 813 | } |
814 | } | 814 | } |
815 | 815 | ||
816 | static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) | 816 | static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) |
817 | { | 817 | { |
818 | u32 regVal; | 818 | u32 regVal; |
819 | unsigned int i; | 819 | unsigned int i; |
@@ -889,10 +889,19 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) | |||
889 | REG_WRITE(ah, 0x7834, regVal); | 889 | REG_WRITE(ah, 0x7834, regVal); |
890 | } | 890 | } |
891 | 891 | ||
892 | /* Empirical offset correction */ | 892 | regVal = (regVal >>20) & 0x7f; |
893 | #if 0 | 893 | |
894 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20); | 894 | /* Update PA cal info */ |
895 | #endif | 895 | if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { |
896 | if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) | ||
897 | ah->pacal_info.max_skipcount = | ||
898 | 2 * ah->pacal_info.max_skipcount; | ||
899 | ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; | ||
900 | } else { | ||
901 | ah->pacal_info.max_skipcount = 1; | ||
902 | ah->pacal_info.skipcount = 0; | ||
903 | ah->pacal_info.prev_offset = regVal; | ||
904 | } | ||
896 | 905 | ||
897 | regVal = REG_READ(ah, 0x7834); | 906 | regVal = REG_READ(ah, 0x7834); |
898 | regVal |= 0x1; | 907 | regVal |= 0x1; |
@@ -1043,7 +1052,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1043 | if (longcal) { | 1052 | if (longcal) { |
1044 | /* Do periodic PAOffset Cal */ | 1053 | /* Do periodic PAOffset Cal */ |
1045 | if (AR_SREV_9271(ah)) | 1054 | if (AR_SREV_9271(ah)) |
1046 | ath9k_hw_9271_pa_cal(ah); | 1055 | ath9k_hw_9271_pa_cal(ah, false); |
1047 | else if (AR_SREV_9285_11_OR_LATER(ah)) { | 1056 | else if (AR_SREV_9285_11_OR_LATER(ah)) { |
1048 | if (!ah->pacal_info.skipcount) | 1057 | if (!ah->pacal_info.skipcount) |
1049 | ath9k_hw_9285_pa_cal(ah, false); | 1058 | ath9k_hw_9285_pa_cal(ah, false); |
@@ -1070,6 +1079,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1070 | } | 1079 | } |
1071 | EXPORT_SYMBOL(ath9k_hw_calibrate); | 1080 | EXPORT_SYMBOL(ath9k_hw_calibrate); |
1072 | 1081 | ||
1082 | /* Carrier leakage Calibration fix */ | ||
1073 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | 1083 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) |
1074 | { | 1084 | { |
1075 | struct ath_common *common = ath9k_hw_common(ah); | 1085 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1115,7 +1125,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1115 | { | 1125 | { |
1116 | struct ath_common *common = ath9k_hw_common(ah); | 1126 | struct ath_common *common = ath9k_hw_common(ah); |
1117 | 1127 | ||
1118 | if (AR_SREV_9285_12_OR_LATER(ah)) { | 1128 | if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { |
1119 | if (!ar9285_clc(ah, chan)) | 1129 | if (!ar9285_clc(ah, chan)) |
1120 | return false; | 1130 | return false; |
1121 | } else { | 1131 | } else { |
@@ -1151,7 +1161,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1151 | } | 1161 | } |
1152 | 1162 | ||
1153 | /* Do PA Calibration */ | 1163 | /* Do PA Calibration */ |
1154 | if (AR_SREV_9285_11_OR_LATER(ah)) | 1164 | if (AR_SREV_9271(ah)) |
1165 | ath9k_hw_9271_pa_cal(ah, true); | ||
1166 | else if (AR_SREV_9285_11_OR_LATER(ah)) | ||
1155 | ath9k_hw_9285_pa_cal(ah, true); | 1167 | ath9k_hw_9285_pa_cal(ah, true); |
1156 | 1168 | ||
1157 | /* Do NF Calibration after DC offset and other calibrations */ | 1169 | /* Do NF Calibration after DC offset and other calibrations */ |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a8620b1d091b..2a4efcbced60 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -2079,7 +2079,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2079 | if (needreset) { | 2079 | if (needreset) { |
2080 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, | 2080 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, |
2081 | "tx hung, resetting the chip\n"); | 2081 | "tx hung, resetting the chip\n"); |
2082 | ath9k_ps_wakeup(sc); | ||
2082 | ath_reset(sc, false); | 2083 | ath_reset(sc, false); |
2084 | ath9k_ps_restore(sc); | ||
2083 | } | 2085 | } |
2084 | 2086 | ||
2085 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | 2087 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, |
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index c1dd857697a7..a1c39526161a 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h | |||
@@ -65,10 +65,13 @@ enum CountryCode { | |||
65 | CTRY_ALGERIA = 12, | 65 | CTRY_ALGERIA = 12, |
66 | CTRY_ARGENTINA = 32, | 66 | CTRY_ARGENTINA = 32, |
67 | CTRY_ARMENIA = 51, | 67 | CTRY_ARMENIA = 51, |
68 | CTRY_ARUBA = 533, | ||
68 | CTRY_AUSTRALIA = 36, | 69 | CTRY_AUSTRALIA = 36, |
69 | CTRY_AUSTRIA = 40, | 70 | CTRY_AUSTRIA = 40, |
70 | CTRY_AZERBAIJAN = 31, | 71 | CTRY_AZERBAIJAN = 31, |
71 | CTRY_BAHRAIN = 48, | 72 | CTRY_BAHRAIN = 48, |
73 | CTRY_BANGLADESH = 50, | ||
74 | CTRY_BARBADOS = 52, | ||
72 | CTRY_BELARUS = 112, | 75 | CTRY_BELARUS = 112, |
73 | CTRY_BELGIUM = 56, | 76 | CTRY_BELGIUM = 56, |
74 | CTRY_BELIZE = 84, | 77 | CTRY_BELIZE = 84, |
@@ -77,6 +80,7 @@ enum CountryCode { | |||
77 | CTRY_BRAZIL = 76, | 80 | CTRY_BRAZIL = 76, |
78 | CTRY_BRUNEI_DARUSSALAM = 96, | 81 | CTRY_BRUNEI_DARUSSALAM = 96, |
79 | CTRY_BULGARIA = 100, | 82 | CTRY_BULGARIA = 100, |
83 | CTRY_CAMBODIA = 116, | ||
80 | CTRY_CANADA = 124, | 84 | CTRY_CANADA = 124, |
81 | CTRY_CHILE = 152, | 85 | CTRY_CHILE = 152, |
82 | CTRY_CHINA = 156, | 86 | CTRY_CHINA = 156, |
@@ -97,7 +101,11 @@ enum CountryCode { | |||
97 | CTRY_GEORGIA = 268, | 101 | CTRY_GEORGIA = 268, |
98 | CTRY_GERMANY = 276, | 102 | CTRY_GERMANY = 276, |
99 | CTRY_GREECE = 300, | 103 | CTRY_GREECE = 300, |
104 | CTRY_GREENLAND = 304, | ||
105 | CTRY_GRENEDA = 308, | ||
106 | CTRY_GUAM = 316, | ||
100 | CTRY_GUATEMALA = 320, | 107 | CTRY_GUATEMALA = 320, |
108 | CTRY_HAITI = 332, | ||
101 | CTRY_HONDURAS = 340, | 109 | CTRY_HONDURAS = 340, |
102 | CTRY_HONG_KONG = 344, | 110 | CTRY_HONG_KONG = 344, |
103 | CTRY_HUNGARY = 348, | 111 | CTRY_HUNGARY = 348, |
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index 9847af72208c..248c670fdfbe 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h | |||
@@ -288,13 +288,16 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
288 | {CTRY_DEFAULT, FCC1_FCCA, "CO"}, | 288 | {CTRY_DEFAULT, FCC1_FCCA, "CO"}, |
289 | {CTRY_ALBANIA, NULL1_WORLD, "AL"}, | 289 | {CTRY_ALBANIA, NULL1_WORLD, "AL"}, |
290 | {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, | 290 | {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, |
291 | {CTRY_ARGENTINA, APL3_WORLD, "AR"}, | 291 | {CTRY_ARGENTINA, FCC3_WORLD, "AR"}, |
292 | {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, | 292 | {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, |
293 | {CTRY_ARUBA, ETSI1_WORLD, "AW"}, | ||
293 | {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, | 294 | {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, |
294 | {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, | 295 | {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, |
295 | {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, | 296 | {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, |
296 | {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, | 297 | {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, |
297 | {CTRY_BAHRAIN, APL6_WORLD, "BH"}, | 298 | {CTRY_BAHRAIN, APL6_WORLD, "BH"}, |
299 | {CTRY_BANGLADESH, NULL1_WORLD, "BD"}, | ||
300 | {CTRY_BARBADOS, FCC2_WORLD, "BB"}, | ||
298 | {CTRY_BELARUS, ETSI1_WORLD, "BY"}, | 301 | {CTRY_BELARUS, ETSI1_WORLD, "BY"}, |
299 | {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, | 302 | {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, |
300 | {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, | 303 | {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, |
@@ -304,13 +307,14 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
304 | {CTRY_BRAZIL, FCC3_WORLD, "BR"}, | 307 | {CTRY_BRAZIL, FCC3_WORLD, "BR"}, |
305 | {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, | 308 | {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, |
306 | {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, | 309 | {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, |
307 | {CTRY_CANADA, FCC2_FCCA, "CA"}, | 310 | {CTRY_CAMBODIA, ETSI1_WORLD, "KH"}, |
311 | {CTRY_CANADA, FCC3_FCCA, "CA"}, | ||
308 | {CTRY_CANADA2, FCC6_FCCA, "CA"}, | 312 | {CTRY_CANADA2, FCC6_FCCA, "CA"}, |
309 | {CTRY_CHILE, APL6_WORLD, "CL"}, | 313 | {CTRY_CHILE, APL6_WORLD, "CL"}, |
310 | {CTRY_CHINA, APL1_WORLD, "CN"}, | 314 | {CTRY_CHINA, APL1_WORLD, "CN"}, |
311 | {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, | 315 | {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, |
312 | {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, | 316 | {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, |
313 | {CTRY_CROATIA, ETSI3_WORLD, "HR"}, | 317 | {CTRY_CROATIA, ETSI1_WORLD, "HR"}, |
314 | {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, | 318 | {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, |
315 | {CTRY_CZECH, ETSI3_WORLD, "CZ"}, | 319 | {CTRY_CZECH, ETSI3_WORLD, "CZ"}, |
316 | {CTRY_DENMARK, ETSI1_WORLD, "DK"}, | 320 | {CTRY_DENMARK, ETSI1_WORLD, "DK"}, |
@@ -324,18 +328,22 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
324 | {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, | 328 | {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, |
325 | {CTRY_GERMANY, ETSI1_WORLD, "DE"}, | 329 | {CTRY_GERMANY, ETSI1_WORLD, "DE"}, |
326 | {CTRY_GREECE, ETSI1_WORLD, "GR"}, | 330 | {CTRY_GREECE, ETSI1_WORLD, "GR"}, |
331 | {CTRY_GREENLAND, ETSI1_WORLD, "GL"}, | ||
332 | {CTRY_GRENEDA, FCC3_FCCA, "GD"}, | ||
333 | {CTRY_GUAM, FCC1_FCCA, "GU"}, | ||
327 | {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, | 334 | {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, |
335 | {CTRY_HAITI, ETSI1_WORLD, "HT"}, | ||
328 | {CTRY_HONDURAS, NULL1_WORLD, "HN"}, | 336 | {CTRY_HONDURAS, NULL1_WORLD, "HN"}, |
329 | {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, | 337 | {CTRY_HONG_KONG, FCC3_WORLD, "HK"}, |
330 | {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, | 338 | {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, |
331 | {CTRY_ICELAND, ETSI1_WORLD, "IS"}, | 339 | {CTRY_ICELAND, ETSI1_WORLD, "IS"}, |
332 | {CTRY_INDIA, APL6_WORLD, "IN"}, | 340 | {CTRY_INDIA, APL6_WORLD, "IN"}, |
333 | {CTRY_INDONESIA, APL1_WORLD, "ID"}, | 341 | {CTRY_INDONESIA, NULL1_WORLD, "ID"}, |
334 | {CTRY_IRAN, APL1_WORLD, "IR"}, | 342 | {CTRY_IRAN, APL1_WORLD, "IR"}, |
335 | {CTRY_IRELAND, ETSI1_WORLD, "IE"}, | 343 | {CTRY_IRELAND, ETSI1_WORLD, "IE"}, |
336 | {CTRY_ISRAEL, NULL1_WORLD, "IL"}, | 344 | {CTRY_ISRAEL, NULL1_WORLD, "IL"}, |
337 | {CTRY_ITALY, ETSI1_WORLD, "IT"}, | 345 | {CTRY_ITALY, ETSI1_WORLD, "IT"}, |
338 | {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, | 346 | {CTRY_JAMAICA, FCC3_WORLD, "JM"}, |
339 | 347 | ||
340 | {CTRY_JAPAN, MKK1_MKKA, "JP"}, | 348 | {CTRY_JAPAN, MKK1_MKKA, "JP"}, |
341 | {CTRY_JAPAN1, MKK1_MKKB, "JP"}, | 349 | {CTRY_JAPAN1, MKK1_MKKB, "JP"}, |
@@ -402,7 +410,7 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
402 | {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, | 410 | {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, |
403 | {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, | 411 | {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, |
404 | {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, | 412 | {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, |
405 | {CTRY_KUWAIT, NULL1_WORLD, "KW"}, | 413 | {CTRY_KUWAIT, ETSI3_WORLD, "KW"}, |
406 | {CTRY_LATVIA, ETSI1_WORLD, "LV"}, | 414 | {CTRY_LATVIA, ETSI1_WORLD, "LV"}, |
407 | {CTRY_LEBANON, NULL1_WORLD, "LB"}, | 415 | {CTRY_LEBANON, NULL1_WORLD, "LB"}, |
408 | {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, | 416 | {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, |
@@ -414,13 +422,13 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
414 | {CTRY_MALTA, ETSI1_WORLD, "MT"}, | 422 | {CTRY_MALTA, ETSI1_WORLD, "MT"}, |
415 | {CTRY_MEXICO, FCC1_FCCA, "MX"}, | 423 | {CTRY_MEXICO, FCC1_FCCA, "MX"}, |
416 | {CTRY_MONACO, ETSI4_WORLD, "MC"}, | 424 | {CTRY_MONACO, ETSI4_WORLD, "MC"}, |
417 | {CTRY_MOROCCO, NULL1_WORLD, "MA"}, | 425 | {CTRY_MOROCCO, APL4_WORLD, "MA"}, |
418 | {CTRY_NEPAL, APL1_WORLD, "NP"}, | 426 | {CTRY_NEPAL, APL1_WORLD, "NP"}, |
419 | {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, | 427 | {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, |
420 | {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, | 428 | {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, |
421 | {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, | 429 | {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, |
422 | {CTRY_NORWAY, ETSI1_WORLD, "NO"}, | 430 | {CTRY_NORWAY, ETSI1_WORLD, "NO"}, |
423 | {CTRY_OMAN, APL6_WORLD, "OM"}, | 431 | {CTRY_OMAN, FCC3_WORLD, "OM"}, |
424 | {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, | 432 | {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, |
425 | {CTRY_PANAMA, FCC1_FCCA, "PA"}, | 433 | {CTRY_PANAMA, FCC1_FCCA, "PA"}, |
426 | {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, | 434 | {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, |
@@ -429,7 +437,7 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
429 | {CTRY_POLAND, ETSI1_WORLD, "PL"}, | 437 | {CTRY_POLAND, ETSI1_WORLD, "PL"}, |
430 | {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, | 438 | {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, |
431 | {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, | 439 | {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, |
432 | {CTRY_QATAR, NULL1_WORLD, "QA"}, | 440 | {CTRY_QATAR, APL1_WORLD, "QA"}, |
433 | {CTRY_ROMANIA, NULL1_WORLD, "RO"}, | 441 | {CTRY_ROMANIA, NULL1_WORLD, "RO"}, |
434 | {CTRY_RUSSIA, NULL1_WORLD, "RU"}, | 442 | {CTRY_RUSSIA, NULL1_WORLD, "RU"}, |
435 | {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, | 443 | {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, |
@@ -445,7 +453,7 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
445 | {CTRY_SYRIA, NULL1_WORLD, "SY"}, | 453 | {CTRY_SYRIA, NULL1_WORLD, "SY"}, |
446 | {CTRY_TAIWAN, APL3_FCCA, "TW"}, | 454 | {CTRY_TAIWAN, APL3_FCCA, "TW"}, |
447 | {CTRY_THAILAND, FCC3_WORLD, "TH"}, | 455 | {CTRY_THAILAND, FCC3_WORLD, "TH"}, |
448 | {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, | 456 | {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"}, |
449 | {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, | 457 | {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, |
450 | {CTRY_TURKEY, ETSI3_WORLD, "TR"}, | 458 | {CTRY_TURKEY, ETSI3_WORLD, "TR"}, |
451 | {CTRY_UKRAINE, NULL1_WORLD, "UA"}, | 459 | {CTRY_UKRAINE, NULL1_WORLD, "UA"}, |
@@ -456,7 +464,7 @@ static struct country_code_to_enum_rd allCountries[] = { | |||
456 | * would need to assign new special alpha2 to CRDA db as with the world | 464 | * would need to assign new special alpha2 to CRDA db as with the world |
457 | * regdomain and use another alpha2 */ | 465 | * regdomain and use another alpha2 */ |
458 | {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, | 466 | {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, |
459 | {CTRY_URUGUAY, APL2_WORLD, "UY"}, | 467 | {CTRY_URUGUAY, FCC3_WORLD, "UY"}, |
460 | {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, | 468 | {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, |
461 | {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, | 469 | {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, |
462 | {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, | 470 | {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 660716214d49..65b23f725a04 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -749,12 +749,6 @@ struct b43_wldev { | |||
749 | #endif | 749 | #endif |
750 | }; | 750 | }; |
751 | 751 | ||
752 | /* | ||
753 | * Include goes here to avoid a dependency problem. | ||
754 | * A better fix would be to integrate xmit.h into b43.h. | ||
755 | */ | ||
756 | #include "xmit.h" | ||
757 | |||
758 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ | 752 | /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ |
759 | struct b43_wl { | 753 | struct b43_wl { |
760 | /* Pointer to the active wireless device on this chip */ | 754 | /* Pointer to the active wireless device on this chip */ |
@@ -830,13 +824,9 @@ struct b43_wl { | |||
830 | struct b43_leds leds; | 824 | struct b43_leds leds; |
831 | 825 | ||
832 | #ifdef CONFIG_B43_PIO | 826 | #ifdef CONFIG_B43_PIO |
833 | /* | 827 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ |
834 | * RX/TX header/tail buffers used by the frame transmit functions. | 828 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); |
835 | */ | 829 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); |
836 | struct b43_rxhdr_fw4 rxhdr; | ||
837 | struct b43_txhdr txhdr; | ||
838 | u8 rx_tail[4]; | ||
839 | u8 tx_tail[4]; | ||
840 | #endif /* CONFIG_B43_PIO */ | 830 | #endif /* CONFIG_B43_PIO */ |
841 | }; | 831 | }; |
842 | 832 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index df6b26a0c05e..751017b4c3d3 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4671,7 +4671,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4671 | { | 4671 | { |
4672 | struct b43_wl *wl = dev->wl; | 4672 | struct b43_wl *wl = dev->wl; |
4673 | struct ssb_bus *bus = dev->dev->bus; | 4673 | struct ssb_bus *bus = dev->dev->bus; |
4674 | struct pci_dev *pdev = bus->host_pci; | 4674 | struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; |
4675 | int err; | 4675 | int err; |
4676 | bool have_2ghz_phy = 0, have_5ghz_phy = 0; | 4676 | bool have_2ghz_phy = 0, have_5ghz_phy = 0; |
4677 | u32 tmp; | 4677 | u32 tmp; |
@@ -4804,7 +4804,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) | |||
4804 | 4804 | ||
4805 | if (!list_empty(&wl->devlist)) { | 4805 | if (!list_empty(&wl->devlist)) { |
4806 | /* We are not the first core on this chip. */ | 4806 | /* We are not the first core on this chip. */ |
4807 | pdev = dev->bus->host_pci; | 4807 | pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; |
4808 | /* Only special chips support more than one wireless | 4808 | /* Only special chips support more than one wireless |
4809 | * core, although some of the other chips have more than | 4809 | * core, although some of the other chips have more than |
4810 | * one wireless core as well. Check for this and | 4810 | * one wireless core as well. Check for this and |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index dbbf0d11e18e..3105f235303a 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
@@ -341,12 +341,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, | |||
341 | q->mmio_base + B43_PIO_TXDATA, | 341 | q->mmio_base + B43_PIO_TXDATA, |
342 | sizeof(u16)); | 342 | sizeof(u16)); |
343 | if (data_len & 1) { | 343 | if (data_len & 1) { |
344 | u8 *tail = wl->pio_tailspace; | ||
345 | BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); | ||
346 | |||
344 | /* Write the last byte. */ | 347 | /* Write the last byte. */ |
345 | ctl &= ~B43_PIO_TXCTL_WRITEHI; | 348 | ctl &= ~B43_PIO_TXCTL_WRITEHI; |
346 | b43_piotx_write16(q, B43_PIO_TXCTL, ctl); | 349 | b43_piotx_write16(q, B43_PIO_TXCTL, ctl); |
347 | wl->tx_tail[0] = data[data_len - 1]; | 350 | tail[0] = data[data_len - 1]; |
348 | wl->tx_tail[1] = 0; | 351 | tail[1] = 0; |
349 | ssb_block_write(dev->dev, wl->tx_tail, 2, | 352 | ssb_block_write(dev->dev, tail, 2, |
350 | q->mmio_base + B43_PIO_TXDATA, | 353 | q->mmio_base + B43_PIO_TXDATA, |
351 | sizeof(u16)); | 354 | sizeof(u16)); |
352 | } | 355 | } |
@@ -392,31 +395,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, | |||
392 | q->mmio_base + B43_PIO8_TXDATA, | 395 | q->mmio_base + B43_PIO8_TXDATA, |
393 | sizeof(u32)); | 396 | sizeof(u32)); |
394 | if (data_len & 3) { | 397 | if (data_len & 3) { |
395 | wl->tx_tail[3] = 0; | 398 | u8 *tail = wl->pio_tailspace; |
399 | BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); | ||
400 | |||
401 | memset(tail, 0, 4); | ||
396 | /* Write the last few bytes. */ | 402 | /* Write the last few bytes. */ |
397 | ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | | 403 | ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | |
398 | B43_PIO8_TXCTL_24_31); | 404 | B43_PIO8_TXCTL_24_31); |
399 | switch (data_len & 3) { | 405 | switch (data_len & 3) { |
400 | case 3: | 406 | case 3: |
401 | ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; | 407 | ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; |
402 | wl->tx_tail[0] = data[data_len - 3]; | 408 | tail[0] = data[data_len - 3]; |
403 | wl->tx_tail[1] = data[data_len - 2]; | 409 | tail[1] = data[data_len - 2]; |
404 | wl->tx_tail[2] = data[data_len - 1]; | 410 | tail[2] = data[data_len - 1]; |
405 | break; | 411 | break; |
406 | case 2: | 412 | case 2: |
407 | ctl |= B43_PIO8_TXCTL_8_15; | 413 | ctl |= B43_PIO8_TXCTL_8_15; |
408 | wl->tx_tail[0] = data[data_len - 2]; | 414 | tail[0] = data[data_len - 2]; |
409 | wl->tx_tail[1] = data[data_len - 1]; | 415 | tail[1] = data[data_len - 1]; |
410 | wl->tx_tail[2] = 0; | ||
411 | break; | 416 | break; |
412 | case 1: | 417 | case 1: |
413 | wl->tx_tail[0] = data[data_len - 1]; | 418 | tail[0] = data[data_len - 1]; |
414 | wl->tx_tail[1] = 0; | ||
415 | wl->tx_tail[2] = 0; | ||
416 | break; | 419 | break; |
417 | } | 420 | } |
418 | b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); | 421 | b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); |
419 | ssb_block_write(dev->dev, wl->tx_tail, 4, | 422 | ssb_block_write(dev->dev, tail, 4, |
420 | q->mmio_base + B43_PIO8_TXDATA, | 423 | q->mmio_base + B43_PIO8_TXDATA, |
421 | sizeof(u32)); | 424 | sizeof(u32)); |
422 | } | 425 | } |
@@ -455,6 +458,7 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, | |||
455 | int err; | 458 | int err; |
456 | unsigned int hdrlen; | 459 | unsigned int hdrlen; |
457 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 460 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
461 | struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace; | ||
458 | 462 | ||
459 | B43_WARN_ON(list_empty(&q->packets_list)); | 463 | B43_WARN_ON(list_empty(&q->packets_list)); |
460 | pack = list_entry(q->packets_list.next, | 464 | pack = list_entry(q->packets_list.next, |
@@ -462,7 +466,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, | |||
462 | 466 | ||
463 | cookie = generate_cookie(q, pack); | 467 | cookie = generate_cookie(q, pack); |
464 | hdrlen = b43_txhdr_size(dev); | 468 | hdrlen = b43_txhdr_size(dev); |
465 | err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb, | 469 | BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr)); |
470 | B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen); | ||
471 | err = b43_generate_txhdr(dev, (u8 *)txhdr, skb, | ||
466 | info, cookie); | 472 | info, cookie); |
467 | if (err) | 473 | if (err) |
468 | return err; | 474 | return err; |
@@ -476,9 +482,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, | |||
476 | 482 | ||
477 | pack->skb = skb; | 483 | pack->skb = skb; |
478 | if (q->rev >= 8) | 484 | if (q->rev >= 8) |
479 | pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen); | 485 | pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen); |
480 | else | 486 | else |
481 | pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen); | 487 | pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen); |
482 | 488 | ||
483 | /* Remove it from the list of available packet slots. | 489 | /* Remove it from the list of available packet slots. |
484 | * It will be put back when we receive the status report. */ | 490 | * It will be put back when we receive the status report. */ |
@@ -624,8 +630,11 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) | |||
624 | unsigned int i, padding; | 630 | unsigned int i, padding; |
625 | struct sk_buff *skb; | 631 | struct sk_buff *skb; |
626 | const char *err_msg = NULL; | 632 | const char *err_msg = NULL; |
633 | struct b43_rxhdr_fw4 *rxhdr = | ||
634 | (struct b43_rxhdr_fw4 *)wl->pio_scratchspace; | ||
627 | 635 | ||
628 | memset(&wl->rxhdr, 0, sizeof(wl->rxhdr)); | 636 | BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr)); |
637 | memset(rxhdr, 0, sizeof(*rxhdr)); | ||
629 | 638 | ||
630 | /* Check if we have data and wait for it to get ready. */ | 639 | /* Check if we have data and wait for it to get ready. */ |
631 | if (q->rev >= 8) { | 640 | if (q->rev >= 8) { |
@@ -663,16 +672,16 @@ data_ready: | |||
663 | 672 | ||
664 | /* Get the preamble (RX header) */ | 673 | /* Get the preamble (RX header) */ |
665 | if (q->rev >= 8) { | 674 | if (q->rev >= 8) { |
666 | ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr), | 675 | ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), |
667 | q->mmio_base + B43_PIO8_RXDATA, | 676 | q->mmio_base + B43_PIO8_RXDATA, |
668 | sizeof(u32)); | 677 | sizeof(u32)); |
669 | } else { | 678 | } else { |
670 | ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr), | 679 | ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), |
671 | q->mmio_base + B43_PIO_RXDATA, | 680 | q->mmio_base + B43_PIO_RXDATA, |
672 | sizeof(u16)); | 681 | sizeof(u16)); |
673 | } | 682 | } |
674 | /* Sanity checks. */ | 683 | /* Sanity checks. */ |
675 | len = le16_to_cpu(wl->rxhdr.frame_len); | 684 | len = le16_to_cpu(rxhdr->frame_len); |
676 | if (unlikely(len > 0x700)) { | 685 | if (unlikely(len > 0x700)) { |
677 | err_msg = "len > 0x700"; | 686 | err_msg = "len > 0x700"; |
678 | goto rx_error; | 687 | goto rx_error; |
@@ -682,7 +691,7 @@ data_ready: | |||
682 | goto rx_error; | 691 | goto rx_error; |
683 | } | 692 | } |
684 | 693 | ||
685 | macstat = le32_to_cpu(wl->rxhdr.mac_status); | 694 | macstat = le32_to_cpu(rxhdr->mac_status); |
686 | if (macstat & B43_RX_MAC_FCSERR) { | 695 | if (macstat & B43_RX_MAC_FCSERR) { |
687 | if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { | 696 | if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { |
688 | /* Drop frames with failed FCS. */ | 697 | /* Drop frames with failed FCS. */ |
@@ -707,22 +716,25 @@ data_ready: | |||
707 | q->mmio_base + B43_PIO8_RXDATA, | 716 | q->mmio_base + B43_PIO8_RXDATA, |
708 | sizeof(u32)); | 717 | sizeof(u32)); |
709 | if (len & 3) { | 718 | if (len & 3) { |
719 | u8 *tail = wl->pio_tailspace; | ||
720 | BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); | ||
721 | |||
710 | /* Read the last few bytes. */ | 722 | /* Read the last few bytes. */ |
711 | ssb_block_read(dev->dev, wl->rx_tail, 4, | 723 | ssb_block_read(dev->dev, tail, 4, |
712 | q->mmio_base + B43_PIO8_RXDATA, | 724 | q->mmio_base + B43_PIO8_RXDATA, |
713 | sizeof(u32)); | 725 | sizeof(u32)); |
714 | switch (len & 3) { | 726 | switch (len & 3) { |
715 | case 3: | 727 | case 3: |
716 | skb->data[len + padding - 3] = wl->rx_tail[0]; | 728 | skb->data[len + padding - 3] = tail[0]; |
717 | skb->data[len + padding - 2] = wl->rx_tail[1]; | 729 | skb->data[len + padding - 2] = tail[1]; |
718 | skb->data[len + padding - 1] = wl->rx_tail[2]; | 730 | skb->data[len + padding - 1] = tail[2]; |
719 | break; | 731 | break; |
720 | case 2: | 732 | case 2: |
721 | skb->data[len + padding - 2] = wl->rx_tail[0]; | 733 | skb->data[len + padding - 2] = tail[0]; |
722 | skb->data[len + padding - 1] = wl->rx_tail[1]; | 734 | skb->data[len + padding - 1] = tail[1]; |
723 | break; | 735 | break; |
724 | case 1: | 736 | case 1: |
725 | skb->data[len + padding - 1] = wl->rx_tail[0]; | 737 | skb->data[len + padding - 1] = tail[0]; |
726 | break; | 738 | break; |
727 | } | 739 | } |
728 | } | 740 | } |
@@ -731,15 +743,18 @@ data_ready: | |||
731 | q->mmio_base + B43_PIO_RXDATA, | 743 | q->mmio_base + B43_PIO_RXDATA, |
732 | sizeof(u16)); | 744 | sizeof(u16)); |
733 | if (len & 1) { | 745 | if (len & 1) { |
746 | u8 *tail = wl->pio_tailspace; | ||
747 | BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); | ||
748 | |||
734 | /* Read the last byte. */ | 749 | /* Read the last byte. */ |
735 | ssb_block_read(dev->dev, wl->rx_tail, 2, | 750 | ssb_block_read(dev->dev, tail, 2, |
736 | q->mmio_base + B43_PIO_RXDATA, | 751 | q->mmio_base + B43_PIO_RXDATA, |
737 | sizeof(u16)); | 752 | sizeof(u16)); |
738 | skb->data[len + padding - 1] = wl->rx_tail[0]; | 753 | skb->data[len + padding - 1] = tail[0]; |
739 | } | 754 | } |
740 | } | 755 | } |
741 | 756 | ||
742 | b43_rx(q->dev, skb, &wl->rxhdr); | 757 | b43_rx(q->dev, skb, rxhdr); |
743 | 758 | ||
744 | return 1; | 759 | return 1; |
745 | 760 | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index f4e9695ec186..7a5e294be2bc 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "b43.h" | 30 | #include "xmit.h" |
31 | #include "phy_common.h" | 31 | #include "phy_common.h" |
32 | #include "dma.h" | 32 | #include "dma.h" |
33 | #include "pio.h" | 33 | #include "pio.h" |
@@ -690,10 +690,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
690 | } | 690 | } |
691 | 691 | ||
692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 692 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
693 | 693 | ieee80211_rx_ni(dev->wl->hw, skb); | |
694 | local_bh_disable(); | ||
695 | ieee80211_rx(dev->wl->hw, skb); | ||
696 | local_bh_enable(); | ||
697 | 694 | ||
698 | #if B43_DEBUG | 695 | #if B43_DEBUG |
699 | dev->rx_count++; | 696 | dev->rx_count++; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1d9223b3d4c4..0983406f4630 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3592,7 +3592,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) | |||
3592 | { | 3592 | { |
3593 | struct b43legacy_wl *wl = dev->wl; | 3593 | struct b43legacy_wl *wl = dev->wl; |
3594 | struct ssb_bus *bus = dev->dev->bus; | 3594 | struct ssb_bus *bus = dev->dev->bus; |
3595 | struct pci_dev *pdev = bus->host_pci; | 3595 | struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; |
3596 | int err; | 3596 | int err; |
3597 | int have_bphy = 0; | 3597 | int have_bphy = 0; |
3598 | int have_gphy = 0; | 3598 | int have_gphy = 0; |
@@ -3706,7 +3706,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, | |||
3706 | 3706 | ||
3707 | if (!list_empty(&wl->devlist)) { | 3707 | if (!list_empty(&wl->devlist)) { |
3708 | /* We are not the first core on this chip. */ | 3708 | /* We are not the first core on this chip. */ |
3709 | pdev = dev->bus->host_pci; | 3709 | pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; |
3710 | /* Only special chips support more than one wireless | 3710 | /* Only special chips support more than one wireless |
3711 | * core, although some of the other chips have more than | 3711 | * core, although some of the other chips have more than |
3712 | * one wireless core as well. Check for this and | 3712 | * one wireless core as well. Check for this and |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 679a67ff76eb..3a645e485dda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -110,8 +110,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
110 | .send_tx_power = iwl5000_send_tx_power, | 110 | .send_tx_power = iwl5000_send_tx_power, |
111 | .update_chain_flags = iwl_update_chain_flags, | 111 | .update_chain_flags = iwl_update_chain_flags, |
112 | .apm_ops = { | 112 | .apm_ops = { |
113 | .init = iwl5000_apm_init, | 113 | .init = iwl_apm_init, |
114 | .reset = iwl5000_apm_reset, | ||
115 | .stop = iwl_apm_stop, | 114 | .stop = iwl_apm_stop, |
116 | .config = iwl1000_nic_config, | 115 | .config = iwl1000_nic_config, |
117 | .set_pwr_src = iwl_set_pwr_src, | 116 | .set_pwr_src = iwl_set_pwr_src, |
@@ -159,15 +158,20 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
159 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 158 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
160 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 159 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
161 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 160 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
161 | .num_of_queues = IWL50_NUM_QUEUES, | ||
162 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
162 | .mod_params = &iwl50_mod_params, | 163 | .mod_params = &iwl50_mod_params, |
163 | .valid_tx_ant = ANT_A, | 164 | .valid_tx_ant = ANT_A, |
164 | .valid_rx_ant = ANT_AB, | 165 | .valid_rx_ant = ANT_AB, |
165 | .need_pll_cfg = true, | 166 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
167 | .set_l0s = false, | ||
168 | .use_bsm = false, | ||
166 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 169 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
167 | .shadow_ram_support = false, | 170 | .shadow_ram_support = false, |
168 | .ht_greenfield_support = true, | 171 | .ht_greenfield_support = true, |
169 | .led_compensation = 51, | 172 | .led_compensation = 51, |
170 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 173 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
174 | .support_ct_kill_exit = true, | ||
171 | }; | 175 | }; |
172 | 176 | ||
173 | struct iwl_cfg iwl1000_bg_cfg = { | 177 | struct iwl_cfg iwl1000_bg_cfg = { |
@@ -180,15 +184,20 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
180 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 184 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
181 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 185 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
182 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 186 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
187 | .num_of_queues = IWL50_NUM_QUEUES, | ||
188 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
183 | .mod_params = &iwl50_mod_params, | 189 | .mod_params = &iwl50_mod_params, |
184 | .valid_tx_ant = ANT_A, | 190 | .valid_tx_ant = ANT_A, |
185 | .valid_rx_ant = ANT_AB, | 191 | .valid_rx_ant = ANT_AB, |
186 | .need_pll_cfg = true, | 192 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
193 | .set_l0s = false, | ||
194 | .use_bsm = false, | ||
187 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 195 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
188 | .shadow_ram_support = false, | 196 | .shadow_ram_support = false, |
189 | .ht_greenfield_support = true, | 197 | .ht_greenfield_support = true, |
190 | .led_compensation = 51, | 198 | .led_compensation = 51, |
191 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 199 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
200 | .support_ct_kill_exit = true, | ||
192 | }; | 201 | }; |
193 | 202 | ||
194 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 203 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 16772780c5b0..6fd10d443ba3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -71,12 +71,6 @@ | |||
71 | 71 | ||
72 | #include "iwl-eeprom.h" | 72 | #include "iwl-eeprom.h" |
73 | 73 | ||
74 | /* | ||
75 | * uCode queue management definitions ... | ||
76 | * Queue #4 is the command queue for 3945 and 4965. | ||
77 | */ | ||
78 | #define IWL_CMD_QUEUE_NUM 4 | ||
79 | |||
80 | /* Time constants */ | 74 | /* Time constants */ |
81 | #define SHORT_SLOT_TIME 9 | 75 | #define SHORT_SLOT_TIME 9 |
82 | #define LONG_SLOT_TIME 20 | 76 | #define LONG_SLOT_TIME 20 |
@@ -254,12 +248,6 @@ struct iwl3945_eeprom { | |||
254 | #define TFD_CTL_PAD_SET(n) (n << 28) | 248 | #define TFD_CTL_PAD_SET(n) (n << 28) |
255 | #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) | 249 | #define TFD_CTL_PAD_GET(ctl) (ctl >> 28) |
256 | 250 | ||
257 | /* | ||
258 | * RX related structures and functions | ||
259 | */ | ||
260 | #define RX_FREE_BUFFERS 64 | ||
261 | #define RX_LOW_WATERMARK 8 | ||
262 | |||
263 | /* Sizes and addresses for instruction and data memory (SRAM) in | 251 | /* Sizes and addresses for instruction and data memory (SRAM) in |
264 | * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | 252 | * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ |
265 | #define IWL39_RTC_INST_LOWER_BOUND (0x000000) | 253 | #define IWL39_RTC_INST_LOWER_BOUND (0x000000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 4115672e2338..09a7bd2c0be4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, | |||
293 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | 293 | static void iwl3945_rx_reply_tx(struct iwl_priv *priv, |
294 | struct iwl_rx_mem_buffer *rxb) | 294 | struct iwl_rx_mem_buffer *rxb) |
295 | { | 295 | { |
296 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 296 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
297 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 297 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
298 | int txq_id = SEQ_TO_QUEUE(sequence); | 298 | int txq_id = SEQ_TO_QUEUE(sequence); |
299 | int index = SEQ_TO_INDEX(sequence); | 299 | int index = SEQ_TO_INDEX(sequence); |
@@ -353,16 +353,12 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
353 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | 353 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
354 | struct iwl_rx_mem_buffer *rxb) | 354 | struct iwl_rx_mem_buffer *rxb) |
355 | { | 355 | { |
356 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 356 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
357 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 357 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
358 | (int)sizeof(struct iwl3945_notif_statistics), | 358 | (int)sizeof(struct iwl3945_notif_statistics), |
359 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 359 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
360 | 360 | ||
361 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 361 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); |
362 | |||
363 | iwl_leds_background(priv); | ||
364 | |||
365 | priv->last_statistics_time = jiffies; | ||
366 | } | 362 | } |
367 | 363 | ||
368 | /****************************************************************************** | 364 | /****************************************************************************** |
@@ -545,14 +541,18 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
545 | struct iwl_rx_mem_buffer *rxb, | 541 | struct iwl_rx_mem_buffer *rxb, |
546 | struct ieee80211_rx_status *stats) | 542 | struct ieee80211_rx_status *stats) |
547 | { | 543 | { |
548 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 544 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
549 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 545 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
550 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 546 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
551 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 547 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
552 | short len = le16_to_cpu(rx_hdr->len); | 548 | u16 len = le16_to_cpu(rx_hdr->len); |
549 | struct sk_buff *skb; | ||
550 | int ret; | ||
551 | __le16 fc = hdr->frame_control; | ||
553 | 552 | ||
554 | /* We received data from the HW, so stop the watchdog */ | 553 | /* We received data from the HW, so stop the watchdog */ |
555 | if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { | 554 | if (unlikely(len + IWL39_RX_FRAME_SIZE > |
555 | PAGE_SIZE << priv->hw_params.rx_page_order)) { | ||
556 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); | 556 | IWL_DEBUG_DROP(priv, "Corruption detected!\n"); |
557 | return; | 557 | return; |
558 | } | 558 | } |
@@ -564,20 +564,49 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
564 | return; | 564 | return; |
565 | } | 565 | } |
566 | 566 | ||
567 | skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); | 567 | skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC); |
568 | /* Set the size of the skb to the size of the frame */ | 568 | if (!skb) { |
569 | skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); | 569 | IWL_ERR(priv, "alloc_skb failed\n"); |
570 | return; | ||
571 | } | ||
570 | 572 | ||
571 | if (!iwl3945_mod_params.sw_crypto) | 573 | if (!iwl3945_mod_params.sw_crypto) |
572 | iwl_set_decrypted_flag(priv, | 574 | iwl_set_decrypted_flag(priv, |
573 | (struct ieee80211_hdr *)rxb->skb->data, | 575 | (struct ieee80211_hdr *)rxb_addr(rxb), |
574 | le32_to_cpu(rx_end->status), stats); | 576 | le32_to_cpu(rx_end->status), stats); |
575 | 577 | ||
576 | iwl_update_stats(priv, false, hdr->frame_control, len); | 578 | skb_add_rx_frag(skb, 0, rxb->page, |
579 | (void *)rx_hdr->payload - (void *)pkt, len); | ||
580 | |||
581 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
582 | * linear SKB for management frame and data frame requires | ||
583 | * software decryption or software defragementation. */ | ||
584 | if (ieee80211_is_mgmt(fc) || | ||
585 | ieee80211_has_protected(fc) || | ||
586 | ieee80211_has_morefrags(fc) || | ||
587 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
588 | ret = skb_linearize(skb); | ||
589 | else | ||
590 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
591 | 0 : -ENOMEM; | ||
592 | |||
593 | if (ret) { | ||
594 | kfree_skb(skb); | ||
595 | goto out; | ||
596 | } | ||
597 | |||
598 | /* | ||
599 | * XXX: We cannot touch the page and its virtual memory (pkt) after | ||
600 | * here. It might have already been freed by the above skb change. | ||
601 | */ | ||
602 | |||
603 | iwl_update_stats(priv, false, fc, len); | ||
604 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
577 | 605 | ||
578 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 606 | ieee80211_rx(priv->hw, skb); |
579 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 607 | out: |
580 | rxb->skb = NULL; | 608 | priv->alloc_rxb_page--; |
609 | rxb->page = NULL; | ||
581 | } | 610 | } |
582 | 611 | ||
583 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) | 612 | #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) |
@@ -587,7 +616,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
587 | { | 616 | { |
588 | struct ieee80211_hdr *header; | 617 | struct ieee80211_hdr *header; |
589 | struct ieee80211_rx_status rx_status; | 618 | struct ieee80211_rx_status rx_status; |
590 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 619 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
591 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 620 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
592 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 621 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
593 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 622 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
@@ -787,29 +816,31 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
787 | u8 data_retry_limit; | 816 | u8 data_retry_limit; |
788 | __le32 tx_flags; | 817 | __le32 tx_flags; |
789 | __le16 fc = hdr->frame_control; | 818 | __le16 fc = hdr->frame_control; |
790 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 819 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
791 | 820 | ||
792 | rate = iwl3945_rates[rate_index].plcp; | 821 | rate = iwl3945_rates[rate_index].plcp; |
793 | tx_flags = tx->tx_flags; | 822 | tx_flags = tx_cmd->tx_flags; |
794 | 823 | ||
795 | /* We need to figure out how to get the sta->supp_rates while | 824 | /* We need to figure out how to get the sta->supp_rates while |
796 | * in this running context */ | 825 | * in this running context */ |
797 | rate_mask = IWL_RATES_MASK; | 826 | rate_mask = IWL_RATES_MASK; |
798 | 827 | ||
828 | |||
829 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
830 | if (ieee80211_is_probe_resp(fc)) | ||
831 | data_retry_limit = 3; | ||
832 | else | ||
833 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
834 | tx_cmd->data_retry_limit = data_retry_limit; | ||
835 | |||
799 | if (tx_id >= IWL_CMD_QUEUE_NUM) | 836 | if (tx_id >= IWL_CMD_QUEUE_NUM) |
800 | rts_retry_limit = 3; | 837 | rts_retry_limit = 3; |
801 | else | 838 | else |
802 | rts_retry_limit = 7; | 839 | rts_retry_limit = 7; |
803 | 840 | ||
804 | if (ieee80211_is_probe_resp(fc)) { | 841 | if (data_retry_limit < rts_retry_limit) |
805 | data_retry_limit = 3; | 842 | rts_retry_limit = data_retry_limit; |
806 | if (data_retry_limit < rts_retry_limit) | 843 | tx_cmd->rts_retry_limit = rts_retry_limit; |
807 | rts_retry_limit = data_retry_limit; | ||
808 | } else | ||
809 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
810 | |||
811 | if (priv->data_retry_limit != -1) | ||
812 | data_retry_limit = priv->data_retry_limit; | ||
813 | 844 | ||
814 | if (ieee80211_is_mgmt(fc)) { | 845 | if (ieee80211_is_mgmt(fc)) { |
815 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | 846 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { |
@@ -827,22 +858,20 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
827 | } | 858 | } |
828 | } | 859 | } |
829 | 860 | ||
830 | tx->rts_retry_limit = rts_retry_limit; | 861 | tx_cmd->rate = rate; |
831 | tx->data_retry_limit = data_retry_limit; | 862 | tx_cmd->tx_flags = tx_flags; |
832 | tx->rate = rate; | ||
833 | tx->tx_flags = tx_flags; | ||
834 | 863 | ||
835 | /* OFDM */ | 864 | /* OFDM */ |
836 | tx->supp_rates[0] = | 865 | tx_cmd->supp_rates[0] = |
837 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; | 866 | ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; |
838 | 867 | ||
839 | /* CCK */ | 868 | /* CCK */ |
840 | tx->supp_rates[1] = (rate_mask & 0xF); | 869 | tx_cmd->supp_rates[1] = (rate_mask & 0xF); |
841 | 870 | ||
842 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " | 871 | IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " |
843 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, | 872 | "cck/ofdm mask: 0x%x/0x%x\n", sta_id, |
844 | tx->rate, le32_to_cpu(tx->tx_flags), | 873 | tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags), |
845 | tx->supp_rates[1], tx->supp_rates[0]); | 874 | tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]); |
846 | } | 875 | } |
847 | 876 | ||
848 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) | 877 | u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) |
@@ -958,6 +987,11 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
958 | 987 | ||
959 | iwl3945_hw_txq_ctx_free(priv); | 988 | iwl3945_hw_txq_ctx_free(priv); |
960 | 989 | ||
990 | /* allocate tx queue structure */ | ||
991 | rc = iwl_alloc_txq_mem(priv); | ||
992 | if (rc) | ||
993 | return rc; | ||
994 | |||
961 | /* Tx CMD queue */ | 995 | /* Tx CMD queue */ |
962 | rc = iwl3945_tx_reset(priv); | 996 | rc = iwl3945_tx_reset(priv); |
963 | if (rc) | 997 | if (rc) |
@@ -982,42 +1016,25 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) | |||
982 | return rc; | 1016 | return rc; |
983 | } | 1017 | } |
984 | 1018 | ||
1019 | |||
1020 | /* | ||
1021 | * Start up 3945's basic functionality after it has been reset | ||
1022 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
1023 | * NOTE: This does not load uCode nor start the embedded processor | ||
1024 | */ | ||
985 | static int iwl3945_apm_init(struct iwl_priv *priv) | 1025 | static int iwl3945_apm_init(struct iwl_priv *priv) |
986 | { | 1026 | { |
987 | int ret; | 1027 | int ret = iwl_apm_init(priv); |
988 | |||
989 | iwl_power_initialize(priv); | ||
990 | 1028 | ||
991 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | 1029 | /* Clear APMG (NIC's internal power management) interrupts */ |
992 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | 1030 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); |
993 | 1031 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF); | |
994 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
995 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
996 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
997 | |||
998 | /* set "initialization complete" bit to move adapter | ||
999 | * D0U* --> D0A* state */ | ||
1000 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1001 | |||
1002 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
1003 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
1004 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1005 | if (ret < 0) { | ||
1006 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
1007 | goto out; | ||
1008 | } | ||
1009 | |||
1010 | /* enable DMA */ | ||
1011 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
1012 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1013 | |||
1014 | udelay(20); | ||
1015 | 1032 | ||
1016 | /* disable L1-Active */ | 1033 | /* Reset radio chip */ |
1017 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | 1034 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); |
1018 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | 1035 | udelay(5); |
1036 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); | ||
1019 | 1037 | ||
1020 | out: | ||
1021 | return ret; | 1038 | return ret; |
1022 | } | 1039 | } |
1023 | 1040 | ||
@@ -1142,12 +1159,16 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1142 | int txq_id; | 1159 | int txq_id; |
1143 | 1160 | ||
1144 | /* Tx queues */ | 1161 | /* Tx queues */ |
1145 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 1162 | if (priv->txq) |
1146 | if (txq_id == IWL_CMD_QUEUE_NUM) | 1163 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; |
1147 | iwl_cmd_queue_free(priv); | 1164 | txq_id++) |
1148 | else | 1165 | if (txq_id == IWL_CMD_QUEUE_NUM) |
1149 | iwl_tx_queue_free(priv, txq_id); | 1166 | iwl_cmd_queue_free(priv); |
1167 | else | ||
1168 | iwl_tx_queue_free(priv, txq_id); | ||
1150 | 1169 | ||
1170 | /* free tx queue structure */ | ||
1171 | iwl_free_txq_mem(priv); | ||
1151 | } | 1172 | } |
1152 | 1173 | ||
1153 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | 1174 | void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) |
@@ -1156,6 +1177,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1156 | 1177 | ||
1157 | /* stop SCD */ | 1178 | /* stop SCD */ |
1158 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); | 1179 | iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); |
1180 | iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0); | ||
1159 | 1181 | ||
1160 | /* reset TFD queues */ | 1182 | /* reset TFD queues */ |
1161 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 1183 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
@@ -1168,47 +1190,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1168 | iwl3945_hw_txq_ctx_free(priv); | 1190 | iwl3945_hw_txq_ctx_free(priv); |
1169 | } | 1191 | } |
1170 | 1192 | ||
1171 | static int iwl3945_apm_reset(struct iwl_priv *priv) | ||
1172 | { | ||
1173 | iwl_apm_stop_master(priv); | ||
1174 | |||
1175 | |||
1176 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1177 | udelay(10); | ||
1178 | |||
1179 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1180 | |||
1181 | iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
1182 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
1183 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1184 | |||
1185 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, | ||
1186 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1187 | |||
1188 | iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); | ||
1189 | iwl_write_prph(priv, APMG_RTC_INT_STT_REG, | ||
1190 | 0xFFFFFFFF); | ||
1191 | |||
1192 | /* enable DMA */ | ||
1193 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1194 | APMG_CLK_VAL_DMA_CLK_RQT | | ||
1195 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1196 | udelay(10); | ||
1197 | |||
1198 | iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1199 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1200 | udelay(5); | ||
1201 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | ||
1202 | APMG_PS_CTRL_VAL_RESET_REQ); | ||
1203 | |||
1204 | /* Clear the 'host command active' bit... */ | ||
1205 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
1206 | |||
1207 | wake_up_interruptible(&priv->wait_command_queue); | ||
1208 | |||
1209 | return 0; | ||
1210 | } | ||
1211 | |||
1212 | /** | 1193 | /** |
1213 | * iwl3945_hw_reg_adjust_power_by_temp | 1194 | * iwl3945_hw_reg_adjust_power_by_temp |
1214 | * return index delta into power gain settings table | 1195 | * return index delta into power gain settings table |
@@ -1817,7 +1798,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) | |||
1817 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | 1798 | static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) |
1818 | { | 1799 | { |
1819 | int rc = 0; | 1800 | int rc = 0; |
1820 | struct iwl_rx_packet *res = NULL; | 1801 | struct iwl_rx_packet *pkt; |
1821 | struct iwl3945_rxon_assoc_cmd rxon_assoc; | 1802 | struct iwl3945_rxon_assoc_cmd rxon_assoc; |
1822 | struct iwl_host_cmd cmd = { | 1803 | struct iwl_host_cmd cmd = { |
1823 | .id = REPLY_RXON_ASSOC, | 1804 | .id = REPLY_RXON_ASSOC, |
@@ -1846,14 +1827,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) | |||
1846 | if (rc) | 1827 | if (rc) |
1847 | return rc; | 1828 | return rc; |
1848 | 1829 | ||
1849 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 1830 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
1850 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 1831 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
1851 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); | 1832 | IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); |
1852 | rc = -EIO; | 1833 | rc = -EIO; |
1853 | } | 1834 | } |
1854 | 1835 | ||
1855 | priv->alloc_rxb_skb--; | 1836 | priv->alloc_rxb_page--; |
1856 | dev_kfree_skb_any(cmd.reply_skb); | 1837 | free_pages(cmd.reply_page, priv->hw_params.rx_page_order); |
1857 | 1838 | ||
1858 | return rc; | 1839 | return rc; |
1859 | } | 1840 | } |
@@ -2001,12 +1982,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2001 | return 0; | 1982 | return 0; |
2002 | } | 1983 | } |
2003 | 1984 | ||
2004 | /* will add 3945 channel switch cmd handling later */ | ||
2005 | int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
2006 | { | ||
2007 | return 0; | ||
2008 | } | ||
2009 | |||
2010 | /** | 1985 | /** |
2011 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. | 1986 | * iwl3945_reg_txpower_periodic - called when time to check our temperature. |
2012 | * | 1987 | * |
@@ -2516,11 +2491,10 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv) | |||
2516 | } | 2491 | } |
2517 | 2492 | ||
2518 | /* Assign number of Usable TX queues */ | 2493 | /* Assign number of Usable TX queues */ |
2519 | priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; | 2494 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
2520 | 2495 | ||
2521 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); | 2496 | priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); |
2522 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; | 2497 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K); |
2523 | priv->hw_params.max_pkt_size = 2342; | ||
2524 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 2498 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
2525 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 2499 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
2526 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; | 2500 | priv->hw_params.max_stations = IWL3945_STATION_COUNT; |
@@ -2803,7 +2777,6 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2803 | .dump_nic_error_log = iwl3945_dump_nic_error_log, | 2777 | .dump_nic_error_log = iwl3945_dump_nic_error_log, |
2804 | .apm_ops = { | 2778 | .apm_ops = { |
2805 | .init = iwl3945_apm_init, | 2779 | .init = iwl3945_apm_init, |
2806 | .reset = iwl3945_apm_reset, | ||
2807 | .stop = iwl_apm_stop, | 2780 | .stop = iwl_apm_stop, |
2808 | .config = iwl3945_nic_config, | 2781 | .config = iwl3945_nic_config, |
2809 | .set_pwr_src = iwl3945_set_pwr_src, | 2782 | .set_pwr_src = iwl3945_set_pwr_src, |
@@ -2833,6 +2806,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2833 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { | 2806 | static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { |
2834 | .get_hcmd_size = iwl3945_get_hcmd_size, | 2807 | .get_hcmd_size = iwl3945_get_hcmd_size, |
2835 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, | 2808 | .build_addsta_hcmd = iwl3945_build_addsta_hcmd, |
2809 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, | ||
2836 | }; | 2810 | }; |
2837 | 2811 | ||
2838 | static struct iwl_ops iwl3945_ops = { | 2812 | static struct iwl_ops iwl3945_ops = { |
@@ -2852,7 +2826,11 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2852 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2826 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2853 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2827 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2854 | .ops = &iwl3945_ops, | 2828 | .ops = &iwl3945_ops, |
2829 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2855 | .mod_params = &iwl3945_mod_params, | 2830 | .mod_params = &iwl3945_mod_params, |
2831 | .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, | ||
2832 | .set_l0s = false, | ||
2833 | .use_bsm = true, | ||
2856 | .use_isr_legacy = true, | 2834 | .use_isr_legacy = true, |
2857 | .ht_greenfield_support = false, | 2835 | .ht_greenfield_support = false, |
2858 | .led_compensation = 64, | 2836 | .led_compensation = 64, |
@@ -2867,6 +2845,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2867 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, | 2845 | .eeprom_size = IWL3945_EEPROM_IMG_SIZE, |
2868 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2846 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2869 | .ops = &iwl3945_ops, | 2847 | .ops = &iwl3945_ops, |
2848 | .num_of_queues = IWL39_NUM_QUEUES, | ||
2870 | .mod_params = &iwl3945_mod_params, | 2849 | .mod_params = &iwl3945_mod_params, |
2871 | .use_isr_legacy = true, | 2850 | .use_isr_legacy = true, |
2872 | .ht_greenfield_support = false, | 2851 | .ht_greenfield_support = false, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index f3907c1079f5..ebb999a51b58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -130,12 +130,6 @@ struct iwl3945_frame { | |||
130 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | 130 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) |
131 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) | 131 | #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) |
132 | 132 | ||
133 | /* | ||
134 | * RX related structures and functions | ||
135 | */ | ||
136 | #define RX_FREE_BUFFERS 64 | ||
137 | #define RX_LOW_WATERMARK 8 | ||
138 | |||
139 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 133 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
140 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 134 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
141 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 135 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
@@ -280,8 +274,6 @@ extern void iwl3945_config_ap(struct iwl_priv *priv); | |||
280 | */ | 274 | */ |
281 | extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); | 275 | extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); |
282 | 276 | ||
283 | extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel); | ||
284 | |||
285 | /* | 277 | /* |
286 | * Forward declare iwl-3945.c functions for iwl-base.c | 278 | * Forward declare iwl-3945.c functions for iwl-base.c |
287 | */ | 279 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index b34322a32458..c606366b582c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -76,12 +76,9 @@ | |||
76 | 76 | ||
77 | /* | 77 | /* |
78 | * uCode queue management definitions ... | 78 | * uCode queue management definitions ... |
79 | * Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4. | ||
80 | * The first queue used for block-ack aggregation is #7 (4965 only). | 79 | * The first queue used for block-ack aggregation is #7 (4965 only). |
81 | * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. | 80 | * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. |
82 | */ | 81 | */ |
83 | #define IWL_CMD_QUEUE_NUM 4 | ||
84 | #define IWL_CMD_FIFO_NUM 4 | ||
85 | #define IWL49_FIRST_AMPDU_QUEUE 7 | 82 | #define IWL49_FIRST_AMPDU_QUEUE 7 |
86 | 83 | ||
87 | /* Time constants */ | 84 | /* Time constants */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f8eed9a4abc1..1ff465ad40d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -62,8 +62,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
62 | 62 | ||
63 | /* module parameters */ | 63 | /* module parameters */ |
64 | static struct iwl_mod_params iwl4965_mod_params = { | 64 | static struct iwl_mod_params iwl4965_mod_params = { |
65 | .num_of_queues = IWL49_NUM_QUEUES, | ||
66 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
67 | .amsdu_size_8K = 1, | 65 | .amsdu_size_8K = 1, |
68 | .restart_fw = 1, | 66 | .restart_fw = 1, |
69 | /* the rest are 0 by default */ | 67 | /* the rest are 0 by default */ |
@@ -319,64 +317,13 @@ static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) | |||
319 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); | 317 | iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); |
320 | } | 318 | } |
321 | 319 | ||
322 | static int iwl4965_apm_init(struct iwl_priv *priv) | ||
323 | { | ||
324 | int ret = 0; | ||
325 | |||
326 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
327 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
328 | |||
329 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
330 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
331 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
332 | |||
333 | /* set "initialization complete" bit to move adapter | ||
334 | * D0U* --> D0A* state */ | ||
335 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
336 | |||
337 | /* wait for clock stabilization */ | ||
338 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
339 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
340 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
341 | if (ret < 0) { | ||
342 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
343 | goto out; | ||
344 | } | ||
345 | |||
346 | /* enable DMA */ | ||
347 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
348 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
349 | |||
350 | udelay(20); | ||
351 | |||
352 | /* disable L1-Active */ | ||
353 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
354 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
355 | |||
356 | out: | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | |||
361 | static void iwl4965_nic_config(struct iwl_priv *priv) | 320 | static void iwl4965_nic_config(struct iwl_priv *priv) |
362 | { | 321 | { |
363 | unsigned long flags; | 322 | unsigned long flags; |
364 | u16 radio_cfg; | 323 | u16 radio_cfg; |
365 | u16 lctl; | ||
366 | 324 | ||
367 | spin_lock_irqsave(&priv->lock, flags); | 325 | spin_lock_irqsave(&priv->lock, flags); |
368 | 326 | ||
369 | lctl = iwl_pcie_link_ctl(priv); | ||
370 | |||
371 | /* HW bug W/A - negligible power consumption */ | ||
372 | /* L1-ASPM is enabled by BIOS */ | ||
373 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) | ||
374 | /* L1-ASPM enabled: disable L0S */ | ||
375 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
376 | else | ||
377 | /* L1-ASPM disabled: enable L0S */ | ||
378 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
379 | |||
380 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 327 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
381 | 328 | ||
382 | /* write radio config values to register */ | 329 | /* write radio config values to register */ |
@@ -397,46 +344,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
397 | spin_unlock_irqrestore(&priv->lock, flags); | 344 | spin_unlock_irqrestore(&priv->lock, flags); |
398 | } | 345 | } |
399 | 346 | ||
400 | static int iwl4965_apm_reset(struct iwl_priv *priv) | ||
401 | { | ||
402 | int ret = 0; | ||
403 | |||
404 | iwl_apm_stop_master(priv); | ||
405 | |||
406 | |||
407 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
408 | |||
409 | udelay(10); | ||
410 | |||
411 | /* FIXME: put here L1A -L0S w/a */ | ||
412 | |||
413 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
414 | |||
415 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
416 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
417 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
418 | if (ret < 0) | ||
419 | goto out; | ||
420 | |||
421 | udelay(10); | ||
422 | |||
423 | /* Enable DMA and BSM Clock */ | ||
424 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | | ||
425 | APMG_CLK_VAL_BSM_CLK_RQT); | ||
426 | |||
427 | udelay(10); | ||
428 | |||
429 | /* disable L1A */ | ||
430 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
431 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
432 | |||
433 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | ||
434 | wake_up_interruptible(&priv->wait_command_queue); | ||
435 | |||
436 | out: | ||
437 | return ret; | ||
438 | } | ||
439 | |||
440 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. | 347 | /* Reset differential Rx gains in NIC to prepare for chain noise calibration. |
441 | * Called after every association, but this runs only once! | 348 | * Called after every association, but this runs only once! |
442 | * ... once chain noise is calibrated the first time, it's good forever. */ | 349 | * ... once chain noise is calibrated the first time, it's good forever. */ |
@@ -526,18 +433,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
526 | data->beacon_count = 0; | 433 | data->beacon_count = 0; |
527 | } | 434 | } |
528 | 435 | ||
529 | static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
530 | __le32 *tx_flags) | ||
531 | { | ||
532 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
533 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
534 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
535 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
536 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
537 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
538 | } | ||
539 | } | ||
540 | |||
541 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 436 | static void iwl4965_bg_txpower_work(struct work_struct *work) |
542 | { | 437 | { |
543 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 438 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
@@ -718,6 +613,10 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = { | |||
718 | 613 | ||
719 | .nrg_th_cck = 100, | 614 | .nrg_th_cck = 100, |
720 | .nrg_th_ofdm = 100, | 615 | .nrg_th_ofdm = 100, |
616 | |||
617 | .barker_corr_th_min = 190, | ||
618 | .barker_corr_th_min_mrc = 390, | ||
619 | .nrg_th_cca = 62, | ||
721 | }; | 620 | }; |
722 | 621 | ||
723 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | 622 | static void iwl4965_set_ct_threshold(struct iwl_priv *priv) |
@@ -734,19 +633,16 @@ static void iwl4965_set_ct_threshold(struct iwl_priv *priv) | |||
734 | */ | 633 | */ |
735 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | 634 | static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) |
736 | { | 635 | { |
636 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
637 | priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES) | ||
638 | priv->cfg->num_of_queues = | ||
639 | priv->cfg->mod_params->num_of_queues; | ||
737 | 640 | ||
738 | if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || | 641 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
739 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | ||
740 | IWL_ERR(priv, | ||
741 | "invalid queues_num, should be between %d and %d\n", | ||
742 | IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); | ||
743 | return -EINVAL; | ||
744 | } | ||
745 | |||
746 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | ||
747 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; | 642 | priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; |
748 | priv->hw_params.scd_bc_tbls_size = | 643 | priv->hw_params.scd_bc_tbls_size = |
749 | IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); | 644 | priv->cfg->num_of_queues * |
645 | sizeof(struct iwl4965_scd_bc_tbl); | ||
750 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 646 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
751 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; | 647 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
752 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; | 648 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
@@ -757,10 +653,10 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) | |||
757 | 653 | ||
758 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | 654 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; |
759 | 655 | ||
760 | priv->hw_params.tx_chains_num = 2; | 656 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); |
761 | priv->hw_params.rx_chains_num = 2; | 657 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); |
762 | priv->hw_params.valid_tx_ant = ANT_A | ANT_B; | 658 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; |
763 | priv->hw_params.valid_rx_ant = ANT_A | ANT_B; | 659 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; |
764 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | 660 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) |
765 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | 661 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); |
766 | 662 | ||
@@ -1537,14 +1433,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | |||
1537 | return ret; | 1433 | return ret; |
1538 | } | 1434 | } |
1539 | 1435 | ||
1540 | #ifdef IEEE80211_CONF_CHANNEL_SWITCH | ||
1541 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1436 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1542 | { | 1437 | { |
1543 | int rc; | 1438 | int rc; |
1544 | u8 band = 0; | 1439 | u8 band = 0; |
1545 | bool is_ht40 = false; | 1440 | bool is_ht40 = false; |
1546 | u8 ctrl_chan_high = 0; | 1441 | u8 ctrl_chan_high = 0; |
1547 | struct iwl4965_channel_switch_cmd cmd = { 0 }; | 1442 | struct iwl4965_channel_switch_cmd cmd; |
1548 | const struct iwl_channel_info *ch_info; | 1443 | const struct iwl_channel_info *ch_info; |
1549 | 1444 | ||
1550 | band = priv->band == IEEE80211_BAND_2GHZ; | 1445 | band = priv->band == IEEE80211_BAND_2GHZ; |
@@ -1565,8 +1460,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1565 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 1460 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); |
1566 | if (ch_info) | 1461 | if (ch_info) |
1567 | cmd.expect_beacon = is_channel_radar(ch_info); | 1462 | cmd.expect_beacon = is_channel_radar(ch_info); |
1568 | else | 1463 | else { |
1569 | cmd.expect_beacon = 1; | 1464 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", |
1465 | priv->active_rxon.channel, channel); | ||
1466 | return -EFAULT; | ||
1467 | } | ||
1570 | 1468 | ||
1571 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, | 1469 | rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, |
1572 | ctrl_chan_high, &cmd.tx_power); | 1470 | ctrl_chan_high, &cmd.tx_power); |
@@ -1578,7 +1476,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1578 | rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); | 1476 | rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); |
1579 | return rc; | 1477 | return rc; |
1580 | } | 1478 | } |
1581 | #endif | ||
1582 | 1479 | ||
1583 | /** | 1480 | /** |
1584 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 1481 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
@@ -1775,11 +1672,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1775 | u16 ssn_idx, u8 tx_fifo) | 1672 | u16 ssn_idx, u8 tx_fifo) |
1776 | { | 1673 | { |
1777 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1674 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1778 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1675 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1676 | <= txq_id)) { | ||
1779 | IWL_WARN(priv, | 1677 | IWL_WARN(priv, |
1780 | "queue number out of range: %d, must be %d to %d\n", | 1678 | "queue number out of range: %d, must be %d to %d\n", |
1781 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1679 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1782 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1680 | IWL49_FIRST_AMPDU_QUEUE + |
1681 | priv->cfg->num_of_ampdu_queues - 1); | ||
1783 | return -EINVAL; | 1682 | return -EINVAL; |
1784 | } | 1683 | } |
1785 | 1684 | ||
@@ -1840,11 +1739,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1840 | u16 ra_tid; | 1739 | u16 ra_tid; |
1841 | 1740 | ||
1842 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || | 1741 | if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || |
1843 | (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { | 1742 | (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
1743 | <= txq_id)) { | ||
1844 | IWL_WARN(priv, | 1744 | IWL_WARN(priv, |
1845 | "queue number out of range: %d, must be %d to %d\n", | 1745 | "queue number out of range: %d, must be %d to %d\n", |
1846 | txq_id, IWL49_FIRST_AMPDU_QUEUE, | 1746 | txq_id, IWL49_FIRST_AMPDU_QUEUE, |
1847 | IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); | 1747 | IWL49_FIRST_AMPDU_QUEUE + |
1748 | priv->cfg->num_of_ampdu_queues - 1); | ||
1848 | return -EINVAL; | 1749 | return -EINVAL; |
1849 | } | 1750 | } |
1850 | 1751 | ||
@@ -2048,7 +1949,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
2048 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | 1949 | static void iwl4965_rx_reply_tx(struct iwl_priv *priv, |
2049 | struct iwl_rx_mem_buffer *rxb) | 1950 | struct iwl_rx_mem_buffer *rxb) |
2050 | { | 1951 | { |
2051 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1952 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2052 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1953 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
2053 | int txq_id = SEQ_TO_QUEUE(sequence); | 1954 | int txq_id = SEQ_TO_QUEUE(sequence); |
2054 | int index = SEQ_TO_INDEX(sequence); | 1955 | int index = SEQ_TO_INDEX(sequence); |
@@ -2249,7 +2150,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | |||
2249 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, | 2150 | .build_addsta_hcmd = iwl4965_build_addsta_hcmd, |
2250 | .chain_noise_reset = iwl4965_chain_noise_reset, | 2151 | .chain_noise_reset = iwl4965_chain_noise_reset, |
2251 | .gain_computation = iwl4965_gain_computation, | 2152 | .gain_computation = iwl4965_gain_computation, |
2252 | .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, | 2153 | .rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, |
2253 | .calc_rssi = iwl4965_calc_rssi, | 2154 | .calc_rssi = iwl4965_calc_rssi, |
2254 | }; | 2155 | }; |
2255 | 2156 | ||
@@ -2271,9 +2172,9 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2271 | .load_ucode = iwl4965_load_bsm, | 2172 | .load_ucode = iwl4965_load_bsm, |
2272 | .dump_nic_event_log = iwl_dump_nic_event_log, | 2173 | .dump_nic_event_log = iwl_dump_nic_event_log, |
2273 | .dump_nic_error_log = iwl_dump_nic_error_log, | 2174 | .dump_nic_error_log = iwl_dump_nic_error_log, |
2175 | .set_channel_switch = iwl4965_hw_channel_switch, | ||
2274 | .apm_ops = { | 2176 | .apm_ops = { |
2275 | .init = iwl4965_apm_init, | 2177 | .init = iwl_apm_init, |
2276 | .reset = iwl4965_apm_reset, | ||
2277 | .stop = iwl_apm_stop, | 2178 | .stop = iwl_apm_stop, |
2278 | .config = iwl4965_nic_config, | 2179 | .config = iwl4965_nic_config, |
2279 | .set_pwr_src = iwl_set_pwr_src, | 2180 | .set_pwr_src = iwl_set_pwr_src, |
@@ -2323,7 +2224,14 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2323 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | 2224 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, |
2324 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | 2225 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, |
2325 | .ops = &iwl4965_ops, | 2226 | .ops = &iwl4965_ops, |
2227 | .num_of_queues = IWL49_NUM_QUEUES, | ||
2228 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | ||
2326 | .mod_params = &iwl4965_mod_params, | 2229 | .mod_params = &iwl4965_mod_params, |
2230 | .valid_tx_ant = ANT_AB, | ||
2231 | .valid_rx_ant = ANT_AB, | ||
2232 | .pll_cfg_val = 0, | ||
2233 | .set_l0s = true, | ||
2234 | .use_bsm = true, | ||
2327 | .use_isr_legacy = true, | 2235 | .use_isr_legacy = true, |
2328 | .ht_greenfield_support = false, | 2236 | .ht_greenfield_support = false, |
2329 | .broken_powersave = true, | 2237 | .broken_powersave = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 8cc3d50e7f59..d256fecc6cda 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -72,115 +72,14 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = { | |||
72 | IWL_TX_FIFO_HCCA_2 | 72 | IWL_TX_FIFO_HCCA_2 |
73 | }; | 73 | }; |
74 | 74 | ||
75 | int iwl5000_apm_init(struct iwl_priv *priv) | ||
76 | { | ||
77 | int ret = 0; | ||
78 | |||
79 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
80 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
81 | |||
82 | /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ | ||
83 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
84 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
85 | |||
86 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
87 | iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
88 | |||
89 | /* enable HAP INTA to move device L1a -> L0s */ | ||
90 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
91 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
92 | |||
93 | if (priv->cfg->need_pll_cfg) | ||
94 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | ||
95 | |||
96 | /* set "initialization complete" bit to move adapter | ||
97 | * D0U* --> D0A* state */ | ||
98 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
99 | |||
100 | /* wait for clock stabilization */ | ||
101 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
102 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
103 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
104 | if (ret < 0) { | ||
105 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | /* enable DMA */ | ||
110 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
111 | |||
112 | udelay(20); | ||
113 | |||
114 | /* disable L1-Active */ | ||
115 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
116 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | int iwl5000_apm_reset(struct iwl_priv *priv) | ||
122 | { | ||
123 | int ret = 0; | ||
124 | |||
125 | iwl_apm_stop_master(priv); | ||
126 | |||
127 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
128 | |||
129 | udelay(10); | ||
130 | |||
131 | |||
132 | /* FIXME: put here L1A -L0S w/a */ | ||
133 | |||
134 | if (priv->cfg->need_pll_cfg) | ||
135 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | ||
136 | |||
137 | /* set "initialization complete" bit to move adapter | ||
138 | * D0U* --> D0A* state */ | ||
139 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
140 | |||
141 | /* wait for clock stabilization */ | ||
142 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
143 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
144 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
145 | if (ret < 0) { | ||
146 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
147 | goto out; | ||
148 | } | ||
149 | |||
150 | /* enable DMA */ | ||
151 | iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
152 | |||
153 | udelay(20); | ||
154 | |||
155 | /* disable L1-Active */ | ||
156 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
157 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
158 | out: | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | |||
164 | /* NIC configuration for 5000 series */ | 75 | /* NIC configuration for 5000 series */ |
165 | void iwl5000_nic_config(struct iwl_priv *priv) | 76 | void iwl5000_nic_config(struct iwl_priv *priv) |
166 | { | 77 | { |
167 | unsigned long flags; | 78 | unsigned long flags; |
168 | u16 radio_cfg; | 79 | u16 radio_cfg; |
169 | u16 lctl; | ||
170 | 80 | ||
171 | spin_lock_irqsave(&priv->lock, flags); | 81 | spin_lock_irqsave(&priv->lock, flags); |
172 | 82 | ||
173 | lctl = iwl_pcie_link_ctl(priv); | ||
174 | |||
175 | /* HW bug W/A */ | ||
176 | /* L1-ASPM is enabled by BIOS */ | ||
177 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) | ||
178 | /* L1-APSM enabled: disable L0S */ | ||
179 | iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
180 | else | ||
181 | /* L1-ASPM disabled: enable L0S */ | ||
182 | iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); | ||
183 | |||
184 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 83 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
185 | 84 | ||
186 | /* write radio config values to register */ | 85 | /* write radio config values to register */ |
@@ -279,7 +178,7 @@ static void iwl5000_gain_computation(struct iwl_priv *priv, | |||
279 | data->delta_gain_code[i] = 0; | 178 | data->delta_gain_code[i] = 0; |
280 | continue; | 179 | continue; |
281 | } | 180 | } |
282 | delta_g = (1000 * ((s32)average_noise[0] - | 181 | delta_g = (1000 * ((s32)average_noise[default_chain] - |
283 | (s32)average_noise[i])) / 1500; | 182 | (s32)average_noise[i])) / 1500; |
284 | /* bound gain by 2 bits value max, 3rd bit is sign */ | 183 | /* bound gain by 2 bits value max, 3rd bit is sign */ |
285 | data->delta_gain_code[i] = | 184 | data->delta_gain_code[i] = |
@@ -372,6 +271,10 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |||
372 | .auto_corr_max_cck_mrc = 400, | 271 | .auto_corr_max_cck_mrc = 400, |
373 | .nrg_th_cck = 95, | 272 | .nrg_th_cck = 95, |
374 | .nrg_th_ofdm = 95, | 273 | .nrg_th_ofdm = 95, |
274 | |||
275 | .barker_corr_th_min = 190, | ||
276 | .barker_corr_th_min_mrc = 390, | ||
277 | .nrg_th_cca = 62, | ||
375 | }; | 278 | }; |
376 | 279 | ||
377 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | 280 | static struct iwl_sensitivity_ranges iwl5150_sensitivity = { |
@@ -394,6 +297,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
394 | .auto_corr_max_cck_mrc = 400, | 297 | .auto_corr_max_cck_mrc = 400, |
395 | .nrg_th_cck = 95, | 298 | .nrg_th_cck = 95, |
396 | .nrg_th_ofdm = 95, | 299 | .nrg_th_ofdm = 95, |
300 | |||
301 | .barker_corr_th_min = 190, | ||
302 | .barker_corr_th_min_mrc = 390, | ||
303 | .nrg_th_cca = 62, | ||
397 | }; | 304 | }; |
398 | 305 | ||
399 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | 306 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, |
@@ -458,7 +365,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | |||
458 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, | 365 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, |
459 | struct iwl_rx_mem_buffer *rxb) | 366 | struct iwl_rx_mem_buffer *rxb) |
460 | { | 367 | { |
461 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 368 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
462 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | 369 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; |
463 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 370 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
464 | int index; | 371 | int index; |
@@ -784,18 +691,16 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
784 | 691 | ||
785 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | 692 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
786 | { | 693 | { |
787 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | 694 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
788 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | 695 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) |
789 | IWL_ERR(priv, | 696 | priv->cfg->num_of_queues = |
790 | "invalid queues_num, should be between %d and %d\n", | 697 | priv->cfg->mod_params->num_of_queues; |
791 | IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); | ||
792 | return -EINVAL; | ||
793 | } | ||
794 | 698 | ||
795 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 699 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
796 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 700 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
797 | priv->hw_params.scd_bc_tbls_size = | 701 | priv->hw_params.scd_bc_tbls_size = |
798 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | 702 | priv->cfg->num_of_queues * |
703 | sizeof(struct iwl5000_scd_bc_tbl); | ||
799 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 704 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
800 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 705 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
801 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 706 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
@@ -947,11 +852,13 @@ int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
947 | u16 ra_tid; | 852 | u16 ra_tid; |
948 | 853 | ||
949 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | 854 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
950 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { | 855 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
856 | <= txq_id)) { | ||
951 | IWL_WARN(priv, | 857 | IWL_WARN(priv, |
952 | "queue number out of range: %d, must be %d to %d\n", | 858 | "queue number out of range: %d, must be %d to %d\n", |
953 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | 859 | txq_id, IWL50_FIRST_AMPDU_QUEUE, |
954 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | 860 | IWL50_FIRST_AMPDU_QUEUE + |
861 | priv->cfg->num_of_ampdu_queues - 1); | ||
955 | return -EINVAL; | 862 | return -EINVAL; |
956 | } | 863 | } |
957 | 864 | ||
@@ -1005,11 +912,13 @@ int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | |||
1005 | u16 ssn_idx, u8 tx_fifo) | 912 | u16 ssn_idx, u8 tx_fifo) |
1006 | { | 913 | { |
1007 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | 914 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || |
1008 | (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { | 915 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues |
916 | <= txq_id)) { | ||
1009 | IWL_ERR(priv, | 917 | IWL_ERR(priv, |
1010 | "queue number out of range: %d, must be %d to %d\n", | 918 | "queue number out of range: %d, must be %d to %d\n", |
1011 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | 919 | txq_id, IWL50_FIRST_AMPDU_QUEUE, |
1012 | IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); | 920 | IWL50_FIRST_AMPDU_QUEUE + |
921 | priv->cfg->num_of_ampdu_queues - 1); | ||
1013 | return -EINVAL; | 922 | return -EINVAL; |
1014 | } | 923 | } |
1015 | 924 | ||
@@ -1176,7 +1085,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
1176 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | 1085 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, |
1177 | struct iwl_rx_mem_buffer *rxb) | 1086 | struct iwl_rx_mem_buffer *rxb) |
1178 | { | 1087 | { |
1179 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1088 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1180 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1089 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
1181 | int txq_id = SEQ_TO_QUEUE(sequence); | 1090 | int txq_id = SEQ_TO_QUEUE(sequence); |
1182 | int index = SEQ_TO_INDEX(sequence); | 1091 | int index = SEQ_TO_INDEX(sequence); |
@@ -1473,6 +1382,36 @@ IWL5000_UCODE_GET(init_size); | |||
1473 | IWL5000_UCODE_GET(init_data_size); | 1382 | IWL5000_UCODE_GET(init_data_size); |
1474 | IWL5000_UCODE_GET(boot_size); | 1383 | IWL5000_UCODE_GET(boot_size); |
1475 | 1384 | ||
1385 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
1386 | { | ||
1387 | struct iwl5000_channel_switch_cmd cmd; | ||
1388 | const struct iwl_channel_info *ch_info; | ||
1389 | struct iwl_host_cmd hcmd = { | ||
1390 | .id = REPLY_CHANNEL_SWITCH, | ||
1391 | .len = sizeof(cmd), | ||
1392 | .flags = CMD_SIZE_HUGE, | ||
1393 | .data = &cmd, | ||
1394 | }; | ||
1395 | |||
1396 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
1397 | priv->active_rxon.channel, channel); | ||
1398 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
1399 | cmd.channel = cpu_to_le16(channel); | ||
1400 | cmd.rxon_flags = priv->active_rxon.flags; | ||
1401 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | ||
1402 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
1403 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
1404 | if (ch_info) | ||
1405 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
1406 | else { | ||
1407 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
1408 | priv->active_rxon.channel, channel); | ||
1409 | return -EFAULT; | ||
1410 | } | ||
1411 | |||
1412 | return iwl_send_cmd_sync(priv, &hcmd); | ||
1413 | } | ||
1414 | |||
1476 | struct iwl_hcmd_ops iwl5000_hcmd = { | 1415 | struct iwl_hcmd_ops iwl5000_hcmd = { |
1477 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1416 | .rxon_assoc = iwl5000_send_rxon_assoc, |
1478 | .commit_rxon = iwl_commit_rxon, | 1417 | .commit_rxon = iwl_commit_rxon, |
@@ -1520,9 +1459,9 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1520 | .alive_notify = iwl5000_alive_notify, | 1459 | .alive_notify = iwl5000_alive_notify, |
1521 | .send_tx_power = iwl5000_send_tx_power, | 1460 | .send_tx_power = iwl5000_send_tx_power, |
1522 | .update_chain_flags = iwl_update_chain_flags, | 1461 | .update_chain_flags = iwl_update_chain_flags, |
1462 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
1523 | .apm_ops = { | 1463 | .apm_ops = { |
1524 | .init = iwl5000_apm_init, | 1464 | .init = iwl_apm_init, |
1525 | .reset = iwl5000_apm_reset, | ||
1526 | .stop = iwl_apm_stop, | 1465 | .stop = iwl_apm_stop, |
1527 | .config = iwl5000_nic_config, | 1466 | .config = iwl5000_nic_config, |
1528 | .set_pwr_src = iwl_set_pwr_src, | 1467 | .set_pwr_src = iwl_set_pwr_src, |
@@ -1572,9 +1511,9 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1572 | .alive_notify = iwl5000_alive_notify, | 1511 | .alive_notify = iwl5000_alive_notify, |
1573 | .send_tx_power = iwl5000_send_tx_power, | 1512 | .send_tx_power = iwl5000_send_tx_power, |
1574 | .update_chain_flags = iwl_update_chain_flags, | 1513 | .update_chain_flags = iwl_update_chain_flags, |
1514 | .set_channel_switch = iwl5000_hw_channel_switch, | ||
1575 | .apm_ops = { | 1515 | .apm_ops = { |
1576 | .init = iwl5000_apm_init, | 1516 | .init = iwl_apm_init, |
1577 | .reset = iwl5000_apm_reset, | ||
1578 | .stop = iwl_apm_stop, | 1517 | .stop = iwl_apm_stop, |
1579 | .config = iwl5000_nic_config, | 1518 | .config = iwl5000_nic_config, |
1580 | .set_pwr_src = iwl_set_pwr_src, | 1519 | .set_pwr_src = iwl_set_pwr_src, |
@@ -1621,8 +1560,6 @@ static struct iwl_ops iwl5150_ops = { | |||
1621 | }; | 1560 | }; |
1622 | 1561 | ||
1623 | struct iwl_mod_params iwl50_mod_params = { | 1562 | struct iwl_mod_params iwl50_mod_params = { |
1624 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1625 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1626 | .amsdu_size_8K = 1, | 1563 | .amsdu_size_8K = 1, |
1627 | .restart_fw = 1, | 1564 | .restart_fw = 1, |
1628 | /* the rest are 0 by default */ | 1565 | /* the rest are 0 by default */ |
@@ -1639,10 +1576,14 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1639 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1576 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1640 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1577 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1641 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1578 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1579 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1580 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1642 | .mod_params = &iwl50_mod_params, | 1581 | .mod_params = &iwl50_mod_params, |
1643 | .valid_tx_ant = ANT_ABC, | 1582 | .valid_tx_ant = ANT_ABC, |
1644 | .valid_rx_ant = ANT_ABC, | 1583 | .valid_rx_ant = ANT_ABC, |
1645 | .need_pll_cfg = true, | 1584 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1585 | .set_l0s = true, | ||
1586 | .use_bsm = false, | ||
1646 | .ht_greenfield_support = true, | 1587 | .ht_greenfield_support = true, |
1647 | .led_compensation = 51, | 1588 | .led_compensation = 51, |
1648 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1589 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -1658,10 +1599,14 @@ struct iwl_cfg iwl5100_bg_cfg = { | |||
1658 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1599 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1659 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1600 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1660 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1601 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1602 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1603 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1661 | .mod_params = &iwl50_mod_params, | 1604 | .mod_params = &iwl50_mod_params, |
1662 | .valid_tx_ant = ANT_B, | 1605 | .valid_tx_ant = ANT_B, |
1663 | .valid_rx_ant = ANT_AB, | 1606 | .valid_rx_ant = ANT_AB, |
1664 | .need_pll_cfg = true, | 1607 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1608 | .set_l0s = true, | ||
1609 | .use_bsm = false, | ||
1665 | .ht_greenfield_support = true, | 1610 | .ht_greenfield_support = true, |
1666 | .led_compensation = 51, | 1611 | .led_compensation = 51, |
1667 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1612 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -1677,10 +1622,14 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1677 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1622 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1678 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1623 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1679 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1624 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1625 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1626 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1680 | .mod_params = &iwl50_mod_params, | 1627 | .mod_params = &iwl50_mod_params, |
1681 | .valid_tx_ant = ANT_B, | 1628 | .valid_tx_ant = ANT_B, |
1682 | .valid_rx_ant = ANT_AB, | 1629 | .valid_rx_ant = ANT_AB, |
1683 | .need_pll_cfg = true, | 1630 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1631 | .set_l0s = true, | ||
1632 | .use_bsm = false, | ||
1684 | .ht_greenfield_support = true, | 1633 | .ht_greenfield_support = true, |
1685 | .led_compensation = 51, | 1634 | .led_compensation = 51, |
1686 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1635 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -1696,10 +1645,14 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1696 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1645 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1697 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1646 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1698 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 1647 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1648 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1649 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1699 | .mod_params = &iwl50_mod_params, | 1650 | .mod_params = &iwl50_mod_params, |
1700 | .valid_tx_ant = ANT_B, | 1651 | .valid_tx_ant = ANT_B, |
1701 | .valid_rx_ant = ANT_AB, | 1652 | .valid_rx_ant = ANT_AB, |
1702 | .need_pll_cfg = true, | 1653 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1654 | .set_l0s = true, | ||
1655 | .use_bsm = false, | ||
1703 | .ht_greenfield_support = true, | 1656 | .ht_greenfield_support = true, |
1704 | .led_compensation = 51, | 1657 | .led_compensation = 51, |
1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1658 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -1715,10 +1668,14 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1715 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1668 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1716 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 1669 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1717 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 1670 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1671 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1672 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1718 | .mod_params = &iwl50_mod_params, | 1673 | .mod_params = &iwl50_mod_params, |
1719 | .valid_tx_ant = ANT_ABC, | 1674 | .valid_tx_ant = ANT_ABC, |
1720 | .valid_rx_ant = ANT_ABC, | 1675 | .valid_rx_ant = ANT_ABC, |
1721 | .need_pll_cfg = true, | 1676 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1677 | .set_l0s = true, | ||
1678 | .use_bsm = false, | ||
1722 | .ht_greenfield_support = true, | 1679 | .ht_greenfield_support = true, |
1723 | .led_compensation = 51, | 1680 | .led_compensation = 51, |
1724 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1681 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
@@ -1734,10 +1691,14 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1734 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1691 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1735 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 1692 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1736 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 1693 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1694 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1695 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1737 | .mod_params = &iwl50_mod_params, | 1696 | .mod_params = &iwl50_mod_params, |
1738 | .valid_tx_ant = ANT_A, | 1697 | .valid_tx_ant = ANT_A, |
1739 | .valid_rx_ant = ANT_AB, | 1698 | .valid_rx_ant = ANT_AB, |
1740 | .need_pll_cfg = true, | 1699 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1700 | .set_l0s = true, | ||
1701 | .use_bsm = false, | ||
1741 | .ht_greenfield_support = true, | 1702 | .ht_greenfield_support = true, |
1742 | .led_compensation = 51, | 1703 | .led_compensation = 51, |
1743 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1704 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index d1f0b0b4ad0c..32466d38d1ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #define IWL6050_UCODE_API_MAX 4 | 52 | #define IWL6050_UCODE_API_MAX 4 |
53 | 53 | ||
54 | /* Lowest firmware API version supported */ | 54 | /* Lowest firmware API version supported */ |
55 | #define IWL6000_UCODE_API_MIN 1 | 55 | #define IWL6000_UCODE_API_MIN 4 |
56 | #define IWL6050_UCODE_API_MIN 1 | 56 | #define IWL6050_UCODE_API_MIN 4 |
57 | 57 | ||
58 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 58 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
59 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 59 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
@@ -121,22 +121,24 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
121 | .auto_corr_max_cck_mrc = 310, | 121 | .auto_corr_max_cck_mrc = 310, |
122 | .nrg_th_cck = 97, | 122 | .nrg_th_cck = 97, |
123 | .nrg_th_ofdm = 100, | 123 | .nrg_th_ofdm = 100, |
124 | |||
125 | .barker_corr_th_min = 190, | ||
126 | .barker_corr_th_min_mrc = 390, | ||
127 | .nrg_th_cca = 62, | ||
124 | }; | 128 | }; |
125 | 129 | ||
126 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 130 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
127 | { | 131 | { |
128 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | 132 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
129 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | 133 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) |
130 | IWL_ERR(priv, | 134 | priv->cfg->num_of_queues = |
131 | "invalid queues_num, should be between %d and %d\n", | 135 | priv->cfg->mod_params->num_of_queues; |
132 | IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | 136 | ||
136 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | 137 | priv->hw_params.max_txq_num = priv->cfg->num_of_queues; |
137 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 138 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
138 | priv->hw_params.scd_bc_tbls_size = | 139 | priv->hw_params.scd_bc_tbls_size = |
139 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | 140 | priv->cfg->num_of_queues * |
141 | sizeof(struct iwl5000_scd_bc_tbl); | ||
140 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 142 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
141 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 143 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
142 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 144 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
@@ -170,6 +172,37 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
170 | return 0; | 172 | return 0; |
171 | } | 173 | } |
172 | 174 | ||
175 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | ||
176 | { | ||
177 | struct iwl6000_channel_switch_cmd cmd; | ||
178 | const struct iwl_channel_info *ch_info; | ||
179 | struct iwl_host_cmd hcmd = { | ||
180 | .id = REPLY_CHANNEL_SWITCH, | ||
181 | .len = sizeof(cmd), | ||
182 | .flags = CMD_SIZE_HUGE, | ||
183 | .data = &cmd, | ||
184 | }; | ||
185 | |||
186 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | ||
187 | priv->active_rxon.channel, channel); | ||
188 | |||
189 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
190 | cmd.channel = cpu_to_le16(channel); | ||
191 | cmd.rxon_flags = priv->active_rxon.flags; | ||
192 | cmd.rxon_filter_flags = priv->active_rxon.filter_flags; | ||
193 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
194 | ch_info = iwl_get_channel_info(priv, priv->band, channel); | ||
195 | if (ch_info) | ||
196 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
197 | else { | ||
198 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
199 | priv->active_rxon.channel, channel); | ||
200 | return -EFAULT; | ||
201 | } | ||
202 | |||
203 | return iwl_send_cmd_sync(priv, &hcmd); | ||
204 | } | ||
205 | |||
173 | static struct iwl_lib_ops iwl6000_lib = { | 206 | static struct iwl_lib_ops iwl6000_lib = { |
174 | .set_hw_params = iwl6000_hw_set_hw_params, | 207 | .set_hw_params = iwl6000_hw_set_hw_params, |
175 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 208 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
@@ -190,9 +223,9 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
190 | .alive_notify = iwl5000_alive_notify, | 223 | .alive_notify = iwl5000_alive_notify, |
191 | .send_tx_power = iwl5000_send_tx_power, | 224 | .send_tx_power = iwl5000_send_tx_power, |
192 | .update_chain_flags = iwl_update_chain_flags, | 225 | .update_chain_flags = iwl_update_chain_flags, |
226 | .set_channel_switch = iwl6000_hw_channel_switch, | ||
193 | .apm_ops = { | 227 | .apm_ops = { |
194 | .init = iwl5000_apm_init, | 228 | .init = iwl_apm_init, |
195 | .reset = iwl5000_apm_reset, | ||
196 | .stop = iwl_apm_stop, | 229 | .stop = iwl_apm_stop, |
197 | .config = iwl6000_nic_config, | 230 | .config = iwl6000_nic_config, |
198 | .set_pwr_src = iwl_set_pwr_src, | 231 | .set_pwr_src = iwl_set_pwr_src, |
@@ -231,6 +264,21 @@ static struct iwl_ops iwl6000_ops = { | |||
231 | .led = &iwlagn_led_ops, | 264 | .led = &iwlagn_led_ops, |
232 | }; | 265 | }; |
233 | 266 | ||
267 | static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = { | ||
268 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
269 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
270 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
271 | .calc_rssi = iwl5000_calc_rssi, | ||
272 | }; | ||
273 | |||
274 | static struct iwl_ops iwl6050_ops = { | ||
275 | .ucode = &iwl5000_ucode, | ||
276 | .lib = &iwl6000_lib, | ||
277 | .hcmd = &iwl5000_hcmd, | ||
278 | .utils = &iwl6050_hcmd_utils, | ||
279 | .led = &iwlagn_led_ops, | ||
280 | }; | ||
281 | |||
234 | 282 | ||
235 | /* | 283 | /* |
236 | * "h": Hybrid configuration, use both internal and external Power Amplifier | 284 | * "h": Hybrid configuration, use both internal and external Power Amplifier |
@@ -245,10 +293,14 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
245 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 293 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
246 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 294 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
247 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 295 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
296 | .num_of_queues = IWL50_NUM_QUEUES, | ||
297 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
248 | .mod_params = &iwl50_mod_params, | 298 | .mod_params = &iwl50_mod_params, |
249 | .valid_tx_ant = ANT_AB, | 299 | .valid_tx_ant = ANT_AB, |
250 | .valid_rx_ant = ANT_AB, | 300 | .valid_rx_ant = ANT_AB, |
251 | .need_pll_cfg = false, | 301 | .pll_cfg_val = 0, |
302 | .set_l0s = false, | ||
303 | .use_bsm = false, | ||
252 | .pa_type = IWL_PA_HYBRID, | 304 | .pa_type = IWL_PA_HYBRID, |
253 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 305 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
254 | .shadow_ram_support = true, | 306 | .shadow_ram_support = true, |
@@ -257,6 +309,8 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
257 | .use_rts_for_ht = true, /* use rts/cts protection */ | 309 | .use_rts_for_ht = true, /* use rts/cts protection */ |
258 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 310 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
259 | .supports_idle = true, | 311 | .supports_idle = true, |
312 | .adv_thermal_throttle = true, | ||
313 | .support_ct_kill_exit = true, | ||
260 | }; | 314 | }; |
261 | 315 | ||
262 | struct iwl_cfg iwl6000h_2abg_cfg = { | 316 | struct iwl_cfg iwl6000h_2abg_cfg = { |
@@ -269,10 +323,14 @@ struct iwl_cfg iwl6000h_2abg_cfg = { | |||
269 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 323 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
270 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 324 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
271 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 325 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
326 | .num_of_queues = IWL50_NUM_QUEUES, | ||
327 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
272 | .mod_params = &iwl50_mod_params, | 328 | .mod_params = &iwl50_mod_params, |
273 | .valid_tx_ant = ANT_AB, | 329 | .valid_tx_ant = ANT_AB, |
274 | .valid_rx_ant = ANT_AB, | 330 | .valid_rx_ant = ANT_AB, |
275 | .need_pll_cfg = false, | 331 | .pll_cfg_val = 0, |
332 | .set_l0s = false, | ||
333 | .use_bsm = false, | ||
276 | .pa_type = IWL_PA_HYBRID, | 334 | .pa_type = IWL_PA_HYBRID, |
277 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 335 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
278 | .shadow_ram_support = true, | 336 | .shadow_ram_support = true, |
@@ -280,6 +338,8 @@ struct iwl_cfg iwl6000h_2abg_cfg = { | |||
280 | .led_compensation = 51, | 338 | .led_compensation = 51, |
281 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 339 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
282 | .supports_idle = true, | 340 | .supports_idle = true, |
341 | .adv_thermal_throttle = true, | ||
342 | .support_ct_kill_exit = true, | ||
283 | }; | 343 | }; |
284 | 344 | ||
285 | struct iwl_cfg iwl6000h_2bg_cfg = { | 345 | struct iwl_cfg iwl6000h_2bg_cfg = { |
@@ -292,10 +352,14 @@ struct iwl_cfg iwl6000h_2bg_cfg = { | |||
292 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 352 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
293 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 353 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
294 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 354 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
355 | .num_of_queues = IWL50_NUM_QUEUES, | ||
356 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
295 | .mod_params = &iwl50_mod_params, | 357 | .mod_params = &iwl50_mod_params, |
296 | .valid_tx_ant = ANT_AB, | 358 | .valid_tx_ant = ANT_AB, |
297 | .valid_rx_ant = ANT_AB, | 359 | .valid_rx_ant = ANT_AB, |
298 | .need_pll_cfg = false, | 360 | .pll_cfg_val = 0, |
361 | .set_l0s = false, | ||
362 | .use_bsm = false, | ||
299 | .pa_type = IWL_PA_HYBRID, | 363 | .pa_type = IWL_PA_HYBRID, |
300 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 364 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
301 | .shadow_ram_support = true, | 365 | .shadow_ram_support = true, |
@@ -303,6 +367,8 @@ struct iwl_cfg iwl6000h_2bg_cfg = { | |||
303 | .led_compensation = 51, | 367 | .led_compensation = 51, |
304 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 368 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
305 | .supports_idle = true, | 369 | .supports_idle = true, |
370 | .adv_thermal_throttle = true, | ||
371 | .support_ct_kill_exit = true, | ||
306 | }; | 372 | }; |
307 | 373 | ||
308 | /* | 374 | /* |
@@ -318,10 +384,14 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
318 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 384 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
319 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 385 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
320 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 386 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
387 | .num_of_queues = IWL50_NUM_QUEUES, | ||
388 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
321 | .mod_params = &iwl50_mod_params, | 389 | .mod_params = &iwl50_mod_params, |
322 | .valid_tx_ant = ANT_BC, | 390 | .valid_tx_ant = ANT_BC, |
323 | .valid_rx_ant = ANT_BC, | 391 | .valid_rx_ant = ANT_BC, |
324 | .need_pll_cfg = false, | 392 | .pll_cfg_val = 0, |
393 | .set_l0s = false, | ||
394 | .use_bsm = false, | ||
325 | .pa_type = IWL_PA_INTERNAL, | 395 | .pa_type = IWL_PA_INTERNAL, |
326 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 396 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
327 | .shadow_ram_support = true, | 397 | .shadow_ram_support = true, |
@@ -330,6 +400,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
330 | .use_rts_for_ht = true, /* use rts/cts protection */ | 400 | .use_rts_for_ht = true, /* use rts/cts protection */ |
331 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 401 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
332 | .supports_idle = true, | 402 | .supports_idle = true, |
403 | .adv_thermal_throttle = true, | ||
404 | .support_ct_kill_exit = true, | ||
333 | }; | 405 | }; |
334 | 406 | ||
335 | struct iwl_cfg iwl6000i_2abg_cfg = { | 407 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -342,10 +414,14 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
342 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 414 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
343 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 415 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
344 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 416 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
417 | .num_of_queues = IWL50_NUM_QUEUES, | ||
418 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
345 | .mod_params = &iwl50_mod_params, | 419 | .mod_params = &iwl50_mod_params, |
346 | .valid_tx_ant = ANT_BC, | 420 | .valid_tx_ant = ANT_BC, |
347 | .valid_rx_ant = ANT_BC, | 421 | .valid_rx_ant = ANT_BC, |
348 | .need_pll_cfg = false, | 422 | .pll_cfg_val = 0, |
423 | .set_l0s = false, | ||
424 | .use_bsm = false, | ||
349 | .pa_type = IWL_PA_INTERNAL, | 425 | .pa_type = IWL_PA_INTERNAL, |
350 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 426 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
351 | .shadow_ram_support = true, | 427 | .shadow_ram_support = true, |
@@ -353,6 +429,8 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
353 | .led_compensation = 51, | 429 | .led_compensation = 51, |
354 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 430 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
355 | .supports_idle = true, | 431 | .supports_idle = true, |
432 | .adv_thermal_throttle = true, | ||
433 | .support_ct_kill_exit = true, | ||
356 | }; | 434 | }; |
357 | 435 | ||
358 | struct iwl_cfg iwl6000i_2bg_cfg = { | 436 | struct iwl_cfg iwl6000i_2bg_cfg = { |
@@ -365,10 +443,14 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
365 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 443 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
366 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 444 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
367 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 445 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
446 | .num_of_queues = IWL50_NUM_QUEUES, | ||
447 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
368 | .mod_params = &iwl50_mod_params, | 448 | .mod_params = &iwl50_mod_params, |
369 | .valid_tx_ant = ANT_BC, | 449 | .valid_tx_ant = ANT_BC, |
370 | .valid_rx_ant = ANT_BC, | 450 | .valid_rx_ant = ANT_BC, |
371 | .need_pll_cfg = false, | 451 | .pll_cfg_val = 0, |
452 | .set_l0s = false, | ||
453 | .use_bsm = false, | ||
372 | .pa_type = IWL_PA_INTERNAL, | 454 | .pa_type = IWL_PA_INTERNAL, |
373 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 455 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
374 | .shadow_ram_support = true, | 456 | .shadow_ram_support = true, |
@@ -376,6 +458,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
376 | .led_compensation = 51, | 458 | .led_compensation = 51, |
377 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 459 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
378 | .supports_idle = true, | 460 | .supports_idle = true, |
461 | .adv_thermal_throttle = true, | ||
462 | .support_ct_kill_exit = true, | ||
379 | }; | 463 | }; |
380 | 464 | ||
381 | struct iwl_cfg iwl6050_2agn_cfg = { | 465 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -384,22 +468,28 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
384 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 468 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
385 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 469 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
386 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 470 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
387 | .ops = &iwl6000_ops, | 471 | .ops = &iwl6050_ops, |
388 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 472 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
389 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 473 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
390 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 474 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
475 | .num_of_queues = IWL50_NUM_QUEUES, | ||
476 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
391 | .mod_params = &iwl50_mod_params, | 477 | .mod_params = &iwl50_mod_params, |
392 | .valid_tx_ant = ANT_AB, | 478 | .valid_tx_ant = ANT_AB, |
393 | .valid_rx_ant = ANT_AB, | 479 | .valid_rx_ant = ANT_AB, |
394 | .need_pll_cfg = false, | 480 | .pll_cfg_val = 0, |
481 | .set_l0s = false, | ||
482 | .use_bsm = false, | ||
395 | .pa_type = IWL_PA_SYSTEM, | 483 | .pa_type = IWL_PA_SYSTEM, |
396 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 484 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
397 | .shadow_ram_support = true, | 485 | .shadow_ram_support = true, |
398 | .ht_greenfield_support = true, | 486 | .ht_greenfield_support = true, |
399 | .led_compensation = 51, | 487 | .led_compensation = 51, |
400 | .use_rts_for_ht = true, /* use rts/cts protection */ | 488 | .use_rts_for_ht = true, /* use rts/cts protection */ |
401 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 489 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
402 | .supports_idle = true, | 490 | .supports_idle = true, |
491 | .adv_thermal_throttle = true, | ||
492 | .support_ct_kill_exit = true, | ||
403 | }; | 493 | }; |
404 | 494 | ||
405 | struct iwl_cfg iwl6050_2abg_cfg = { | 495 | struct iwl_cfg iwl6050_2abg_cfg = { |
@@ -408,21 +498,27 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
408 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 498 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
409 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 499 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
410 | .sku = IWL_SKU_A|IWL_SKU_G, | 500 | .sku = IWL_SKU_A|IWL_SKU_G, |
411 | .ops = &iwl6000_ops, | 501 | .ops = &iwl6050_ops, |
412 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 502 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
413 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 503 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
414 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 504 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
505 | .num_of_queues = IWL50_NUM_QUEUES, | ||
506 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
415 | .mod_params = &iwl50_mod_params, | 507 | .mod_params = &iwl50_mod_params, |
416 | .valid_tx_ant = ANT_AB, | 508 | .valid_tx_ant = ANT_AB, |
417 | .valid_rx_ant = ANT_AB, | 509 | .valid_rx_ant = ANT_AB, |
418 | .need_pll_cfg = false, | 510 | .pll_cfg_val = 0, |
511 | .set_l0s = false, | ||
512 | .use_bsm = false, | ||
419 | .pa_type = IWL_PA_SYSTEM, | 513 | .pa_type = IWL_PA_SYSTEM, |
420 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 514 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
421 | .shadow_ram_support = true, | 515 | .shadow_ram_support = true, |
422 | .ht_greenfield_support = true, | 516 | .ht_greenfield_support = true, |
423 | .led_compensation = 51, | 517 | .led_compensation = 51, |
424 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 518 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
425 | .supports_idle = true, | 519 | .supports_idle = true, |
520 | .adv_thermal_throttle = true, | ||
521 | .support_ct_kill_exit = true, | ||
426 | }; | 522 | }; |
427 | 523 | ||
428 | struct iwl_cfg iwl6000_3agn_cfg = { | 524 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -435,10 +531,14 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
435 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 531 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
436 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 532 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
437 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 533 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
534 | .num_of_queues = IWL50_NUM_QUEUES, | ||
535 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
438 | .mod_params = &iwl50_mod_params, | 536 | .mod_params = &iwl50_mod_params, |
439 | .valid_tx_ant = ANT_ABC, | 537 | .valid_tx_ant = ANT_ABC, |
440 | .valid_rx_ant = ANT_ABC, | 538 | .valid_rx_ant = ANT_ABC, |
441 | .need_pll_cfg = false, | 539 | .pll_cfg_val = 0, |
540 | .set_l0s = false, | ||
541 | .use_bsm = false, | ||
442 | .pa_type = IWL_PA_SYSTEM, | 542 | .pa_type = IWL_PA_SYSTEM, |
443 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 543 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
444 | .shadow_ram_support = true, | 544 | .shadow_ram_support = true, |
@@ -447,6 +547,8 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
447 | .use_rts_for_ht = true, /* use rts/cts protection */ | 547 | .use_rts_for_ht = true, /* use rts/cts protection */ |
448 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 548 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
449 | .supports_idle = true, | 549 | .supports_idle = true, |
550 | .adv_thermal_throttle = true, | ||
551 | .support_ct_kill_exit = true, | ||
450 | }; | 552 | }; |
451 | 553 | ||
452 | struct iwl_cfg iwl6050_3agn_cfg = { | 554 | struct iwl_cfg iwl6050_3agn_cfg = { |
@@ -455,22 +557,28 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
455 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 557 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
456 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 558 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
457 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 559 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
458 | .ops = &iwl6000_ops, | 560 | .ops = &iwl6050_ops, |
459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 561 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
460 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 562 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 563 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
564 | .num_of_queues = IWL50_NUM_QUEUES, | ||
565 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
462 | .mod_params = &iwl50_mod_params, | 566 | .mod_params = &iwl50_mod_params, |
463 | .valid_tx_ant = ANT_ABC, | 567 | .valid_tx_ant = ANT_ABC, |
464 | .valid_rx_ant = ANT_ABC, | 568 | .valid_rx_ant = ANT_ABC, |
465 | .need_pll_cfg = false, | 569 | .pll_cfg_val = 0, |
570 | .set_l0s = false, | ||
571 | .use_bsm = false, | ||
466 | .pa_type = IWL_PA_SYSTEM, | 572 | .pa_type = IWL_PA_SYSTEM, |
467 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 573 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
468 | .shadow_ram_support = true, | 574 | .shadow_ram_support = true, |
469 | .ht_greenfield_support = true, | 575 | .ht_greenfield_support = true, |
470 | .led_compensation = 51, | 576 | .led_compensation = 51, |
471 | .use_rts_for_ht = true, /* use rts/cts protection */ | 577 | .use_rts_for_ht = true, /* use rts/cts protection */ |
472 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 578 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
473 | .supports_idle = true, | 579 | .supports_idle = true, |
580 | .adv_thermal_throttle = true, | ||
581 | .support_ct_kill_exit = true, | ||
474 | }; | 582 | }; |
475 | 583 | ||
476 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 584 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index a07be29cc5e5..27d4ece4d467 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -75,106 +75,6 @@ static const u8 ant_toggle_lookup[] = { | |||
75 | /*ANT_ABC -> */ ANT_ABC, | 75 | /*ANT_ABC -> */ ANT_ABC, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | /** | ||
79 | * struct iwl_rate_scale_data -- tx success history for one rate | ||
80 | */ | ||
81 | struct iwl_rate_scale_data { | ||
82 | u64 data; /* bitmap of successful frames */ | ||
83 | s32 success_counter; /* number of frames successful */ | ||
84 | s32 success_ratio; /* per-cent * 128 */ | ||
85 | s32 counter; /* number of frames attempted */ | ||
86 | s32 average_tpt; /* success ratio * expected throughput */ | ||
87 | unsigned long stamp; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | ||
92 | * | ||
93 | * There are two of these in struct iwl_lq_sta, | ||
94 | * one for "active", and one for "search". | ||
95 | */ | ||
96 | struct iwl_scale_tbl_info { | ||
97 | enum iwl_table_type lq_type; | ||
98 | u8 ant_type; | ||
99 | u8 is_SGI; /* 1 = short guard interval */ | ||
100 | u8 is_ht40; /* 1 = 40 MHz channel width */ | ||
101 | u8 is_dup; /* 1 = duplicated data streams */ | ||
102 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | ||
103 | u8 max_search; /* maximun number of tables we can search */ | ||
104 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | ||
105 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
106 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | ||
107 | }; | ||
108 | |||
109 | struct iwl_traffic_load { | ||
110 | unsigned long time_stamp; /* age of the oldest statistics */ | ||
111 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | ||
112 | * slice */ | ||
113 | u32 total; /* total num of packets during the | ||
114 | * last TID_MAX_TIME_DIFF */ | ||
115 | u8 queue_count; /* number of queues that has | ||
116 | * been used since the last cleanup */ | ||
117 | u8 head; /* start of the circular buffer */ | ||
118 | }; | ||
119 | |||
120 | /** | ||
121 | * struct iwl_lq_sta -- driver's rate scaling private structure | ||
122 | * | ||
123 | * Pointer to this gets passed back and forth between driver and mac80211. | ||
124 | */ | ||
125 | struct iwl_lq_sta { | ||
126 | u8 active_tbl; /* index of active table, range 0-1 */ | ||
127 | u8 enable_counter; /* indicates HT mode */ | ||
128 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | ||
129 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | ||
130 | s32 last_tpt; | ||
131 | |||
132 | /* The following determine when to search for a new mode */ | ||
133 | u32 table_count_limit; | ||
134 | u32 max_failure_limit; /* # failed frames before new search */ | ||
135 | u32 max_success_limit; /* # successful frames before new search */ | ||
136 | u32 table_count; | ||
137 | u32 total_failed; /* total failed frames, any/all rates */ | ||
138 | u32 total_success; /* total successful frames, any/all rates */ | ||
139 | u64 flush_timer; /* time staying in mode before new search */ | ||
140 | |||
141 | u8 action_counter; /* # mode-switch actions tried */ | ||
142 | u8 is_green; | ||
143 | u8 is_dup; | ||
144 | enum ieee80211_band band; | ||
145 | u8 ibss_sta_added; | ||
146 | |||
147 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | ||
148 | u32 supp_rates; | ||
149 | u16 active_legacy_rate; | ||
150 | u16 active_siso_rate; | ||
151 | u16 active_mimo2_rate; | ||
152 | u16 active_mimo3_rate; | ||
153 | u16 active_rate_basic; | ||
154 | s8 max_rate_idx; /* Max rate set by user */ | ||
155 | u8 missed_rate_counter; | ||
156 | |||
157 | struct iwl_link_quality_cmd lq; | ||
158 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | ||
159 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | ||
160 | u8 tx_agg_tid_en; | ||
161 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
162 | struct dentry *rs_sta_dbgfs_scale_table_file; | ||
163 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
164 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
165 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | ||
166 | u32 dbg_fixed_rate; | ||
167 | #endif | ||
168 | struct iwl_priv *drv; | ||
169 | |||
170 | /* used to be in sta_info */ | ||
171 | int last_txrate_idx; | ||
172 | /* last tx rate_n_flags */ | ||
173 | u32 last_rate_n_flags; | ||
174 | /* packets destined for this STA are aggregated */ | ||
175 | u8 is_agg; | ||
176 | }; | ||
177 | |||
178 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 78 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
179 | struct sk_buff *skb, | 79 | struct sk_buff *skb, |
180 | struct ieee80211_sta *sta, | 80 | struct ieee80211_sta *sta, |
@@ -2575,19 +2475,17 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | |||
2575 | gfp_t gfp) | 2475 | gfp_t gfp) |
2576 | { | 2476 | { |
2577 | struct iwl_lq_sta *lq_sta; | 2477 | struct iwl_lq_sta *lq_sta; |
2478 | struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv; | ||
2578 | struct iwl_priv *priv; | 2479 | struct iwl_priv *priv; |
2579 | int i, j; | 2480 | int i, j; |
2580 | 2481 | ||
2581 | priv = (struct iwl_priv *)priv_rate; | 2482 | priv = (struct iwl_priv *)priv_rate; |
2582 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); | 2483 | IWL_DEBUG_RATE(priv, "create station rate scale window\n"); |
2583 | 2484 | ||
2584 | lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); | 2485 | lq_sta = &sta_priv->lq_sta; |
2585 | 2486 | ||
2586 | if (lq_sta == NULL) | ||
2587 | return NULL; | ||
2588 | lq_sta->lq.sta_id = 0xff; | 2487 | lq_sta->lq.sta_id = 0xff; |
2589 | 2488 | ||
2590 | |||
2591 | for (j = 0; j < LQ_SIZE; j++) | 2489 | for (j = 0; j < LQ_SIZE; j++) |
2592 | for (i = 0; i < IWL_RATE_COUNT; i++) | 2490 | for (i = 0; i < IWL_RATE_COUNT; i++) |
2593 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); | 2491 | rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); |
@@ -2819,11 +2717,9 @@ static void rs_free(void *priv_rate) | |||
2819 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, | 2717 | static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, |
2820 | void *priv_sta) | 2718 | void *priv_sta) |
2821 | { | 2719 | { |
2822 | struct iwl_lq_sta *lq_sta = priv_sta; | ||
2823 | struct iwl_priv *priv __maybe_unused = priv_r; | 2720 | struct iwl_priv *priv __maybe_unused = priv_r; |
2824 | 2721 | ||
2825 | IWL_DEBUG_RATE(priv, "enter\n"); | 2722 | IWL_DEBUG_RATE(priv, "enter\n"); |
2826 | kfree(lq_sta); | ||
2827 | IWL_DEBUG_RATE(priv, "leave\n"); | 2723 | IWL_DEBUG_RATE(priv, "leave\n"); |
2828 | } | 2724 | } |
2829 | 2725 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 9fac530cfb7e..affc0c5a2f2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h | |||
@@ -54,6 +54,7 @@ struct iwl3945_rate_info { | |||
54 | u8 prev_table_rs; /* prev in rate table cmd */ | 54 | u8 prev_table_rs; /* prev in rate table cmd */ |
55 | }; | 55 | }; |
56 | 56 | ||
57 | |||
57 | /* | 58 | /* |
58 | * These serve as indexes into | 59 | * These serve as indexes into |
59 | * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; | 60 | * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; |
@@ -335,6 +336,106 @@ struct iwl_rate_mcs_info { | |||
335 | char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; | 336 | char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; |
336 | }; | 337 | }; |
337 | 338 | ||
339 | /** | ||
340 | * struct iwl_rate_scale_data -- tx success history for one rate | ||
341 | */ | ||
342 | struct iwl_rate_scale_data { | ||
343 | u64 data; /* bitmap of successful frames */ | ||
344 | s32 success_counter; /* number of frames successful */ | ||
345 | s32 success_ratio; /* per-cent * 128 */ | ||
346 | s32 counter; /* number of frames attempted */ | ||
347 | s32 average_tpt; /* success ratio * expected throughput */ | ||
348 | unsigned long stamp; | ||
349 | }; | ||
350 | |||
351 | /** | ||
352 | * struct iwl_scale_tbl_info -- tx params and success history for all rates | ||
353 | * | ||
354 | * There are two of these in struct iwl_lq_sta, | ||
355 | * one for "active", and one for "search". | ||
356 | */ | ||
357 | struct iwl_scale_tbl_info { | ||
358 | enum iwl_table_type lq_type; | ||
359 | u8 ant_type; | ||
360 | u8 is_SGI; /* 1 = short guard interval */ | ||
361 | u8 is_ht40; /* 1 = 40 MHz channel width */ | ||
362 | u8 is_dup; /* 1 = duplicated data streams */ | ||
363 | u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ | ||
364 | u8 max_search; /* maximun number of tables we can search */ | ||
365 | s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ | ||
366 | u32 current_rate; /* rate_n_flags, uCode API format */ | ||
367 | struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ | ||
368 | }; | ||
369 | |||
370 | struct iwl_traffic_load { | ||
371 | unsigned long time_stamp; /* age of the oldest statistics */ | ||
372 | u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time | ||
373 | * slice */ | ||
374 | u32 total; /* total num of packets during the | ||
375 | * last TID_MAX_TIME_DIFF */ | ||
376 | u8 queue_count; /* number of queues that has | ||
377 | * been used since the last cleanup */ | ||
378 | u8 head; /* start of the circular buffer */ | ||
379 | }; | ||
380 | |||
381 | /** | ||
382 | * struct iwl_lq_sta -- driver's rate scaling private structure | ||
383 | * | ||
384 | * Pointer to this gets passed back and forth between driver and mac80211. | ||
385 | */ | ||
386 | struct iwl_lq_sta { | ||
387 | u8 active_tbl; /* index of active table, range 0-1 */ | ||
388 | u8 enable_counter; /* indicates HT mode */ | ||
389 | u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ | ||
390 | u8 search_better_tbl; /* 1: currently trying alternate mode */ | ||
391 | s32 last_tpt; | ||
392 | |||
393 | /* The following determine when to search for a new mode */ | ||
394 | u32 table_count_limit; | ||
395 | u32 max_failure_limit; /* # failed frames before new search */ | ||
396 | u32 max_success_limit; /* # successful frames before new search */ | ||
397 | u32 table_count; | ||
398 | u32 total_failed; /* total failed frames, any/all rates */ | ||
399 | u32 total_success; /* total successful frames, any/all rates */ | ||
400 | u64 flush_timer; /* time staying in mode before new search */ | ||
401 | |||
402 | u8 action_counter; /* # mode-switch actions tried */ | ||
403 | u8 is_green; | ||
404 | u8 is_dup; | ||
405 | enum ieee80211_band band; | ||
406 | u8 ibss_sta_added; | ||
407 | |||
408 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | ||
409 | u32 supp_rates; | ||
410 | u16 active_legacy_rate; | ||
411 | u16 active_siso_rate; | ||
412 | u16 active_mimo2_rate; | ||
413 | u16 active_mimo3_rate; | ||
414 | u16 active_rate_basic; | ||
415 | s8 max_rate_idx; /* Max rate set by user */ | ||
416 | u8 missed_rate_counter; | ||
417 | |||
418 | struct iwl_link_quality_cmd lq; | ||
419 | struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | ||
420 | struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; | ||
421 | u8 tx_agg_tid_en; | ||
422 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
423 | struct dentry *rs_sta_dbgfs_scale_table_file; | ||
424 | struct dentry *rs_sta_dbgfs_stats_table_file; | ||
425 | struct dentry *rs_sta_dbgfs_rate_scale_data_file; | ||
426 | struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; | ||
427 | u32 dbg_fixed_rate; | ||
428 | #endif | ||
429 | struct iwl_priv *drv; | ||
430 | |||
431 | /* used to be in sta_info */ | ||
432 | int last_txrate_idx; | ||
433 | /* last tx rate_n_flags */ | ||
434 | u32 last_rate_n_flags; | ||
435 | /* packets destined for this STA are aggregated */ | ||
436 | u8 is_agg; | ||
437 | }; | ||
438 | |||
338 | static inline u8 num_of_ant(u8 mask) | 439 | static inline u8 num_of_ant(u8 mask) |
339 | { | 440 | { |
340 | return !!((mask) & ANT_A) + | 441 | return !!((mask) & ANT_A) + |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d7bc38fe005..fa1672e99e4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -524,7 +524,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv, | |||
524 | static void iwl_rx_reply_alive(struct iwl_priv *priv, | 524 | static void iwl_rx_reply_alive(struct iwl_priv *priv, |
525 | struct iwl_rx_mem_buffer *rxb) | 525 | struct iwl_rx_mem_buffer *rxb) |
526 | { | 526 | { |
527 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 527 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
528 | struct iwl_alive_resp *palive; | 528 | struct iwl_alive_resp *palive; |
529 | struct delayed_work *pwork; | 529 | struct delayed_work *pwork; |
530 | 530 | ||
@@ -610,7 +610,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
610 | struct iwl_rx_mem_buffer *rxb) | 610 | struct iwl_rx_mem_buffer *rxb) |
611 | { | 611 | { |
612 | #ifdef CONFIG_IWLWIFI_DEBUG | 612 | #ifdef CONFIG_IWLWIFI_DEBUG |
613 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 613 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
614 | struct iwl4965_beacon_notif *beacon = | 614 | struct iwl4965_beacon_notif *beacon = |
615 | (struct iwl4965_beacon_notif *)pkt->u.raw; | 615 | (struct iwl4965_beacon_notif *)pkt->u.raw; |
616 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | 616 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); |
@@ -634,7 +634,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
634 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, | 634 | static void iwl_rx_card_state_notif(struct iwl_priv *priv, |
635 | struct iwl_rx_mem_buffer *rxb) | 635 | struct iwl_rx_mem_buffer *rxb) |
636 | { | 636 | { |
637 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 637 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
638 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 638 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
639 | unsigned long status = priv->status; | 639 | unsigned long status = priv->status; |
640 | 640 | ||
@@ -769,7 +769,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
769 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); | 769 | IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); |
770 | 770 | ||
771 | /* calculate total frames need to be restock after handling RX */ | 771 | /* calculate total frames need to be restock after handling RX */ |
772 | total_empty = r - priv->rxq.write_actual; | 772 | total_empty = r - rxq->write_actual; |
773 | if (total_empty < 0) | 773 | if (total_empty < 0) |
774 | total_empty += RX_QUEUE_SIZE; | 774 | total_empty += RX_QUEUE_SIZE; |
775 | 775 | ||
@@ -786,10 +786,10 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
786 | 786 | ||
787 | rxq->queue[i] = NULL; | 787 | rxq->queue[i] = NULL; |
788 | 788 | ||
789 | pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, | 789 | pci_unmap_page(priv->pci_dev, rxb->page_dma, |
790 | priv->hw_params.rx_buf_size + 256, | 790 | PAGE_SIZE << priv->hw_params.rx_page_order, |
791 | PCI_DMA_FROMDEVICE); | 791 | PCI_DMA_FROMDEVICE); |
792 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 792 | pkt = rxb_addr(rxb); |
793 | 793 | ||
794 | trace_iwlwifi_dev_rx(priv, pkt, | 794 | trace_iwlwifi_dev_rx(priv, pkt, |
795 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 795 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
@@ -814,8 +814,8 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
814 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 814 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
815 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, | 815 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, |
816 | i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 816 | i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
817 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
818 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; | 817 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; |
818 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
819 | } else { | 819 | } else { |
820 | /* No handling needed */ | 820 | /* No handling needed */ |
821 | IWL_DEBUG_RX(priv, | 821 | IWL_DEBUG_RX(priv, |
@@ -824,35 +824,45 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
824 | pkt->hdr.cmd); | 824 | pkt->hdr.cmd); |
825 | } | 825 | } |
826 | 826 | ||
827 | /* | ||
828 | * XXX: After here, we should always check rxb->page | ||
829 | * against NULL before touching it or its virtual | ||
830 | * memory (pkt). Because some rx_handler might have | ||
831 | * already taken or freed the pages. | ||
832 | */ | ||
833 | |||
827 | if (reclaim) { | 834 | if (reclaim) { |
828 | /* Invoke any callbacks, transfer the skb to caller, and | 835 | /* Invoke any callbacks, transfer the buffer to caller, |
829 | * fire off the (possibly) blocking iwl_send_cmd() | 836 | * and fire off the (possibly) blocking iwl_send_cmd() |
830 | * as we reclaim the driver command queue */ | 837 | * as we reclaim the driver command queue */ |
831 | if (rxb && rxb->skb) | 838 | if (rxb->page) |
832 | iwl_tx_cmd_complete(priv, rxb); | 839 | iwl_tx_cmd_complete(priv, rxb); |
833 | else | 840 | else |
834 | IWL_WARN(priv, "Claim null rxb?\n"); | 841 | IWL_WARN(priv, "Claim null rxb?\n"); |
835 | } | 842 | } |
836 | 843 | ||
837 | /* For now we just don't re-use anything. We can tweak this | 844 | /* Reuse the page if possible. For notification packets and |
838 | * later to try and re-use notification packets and SKBs that | 845 | * SKBs that fail to Rx correctly, add them back into the |
839 | * fail to Rx correctly */ | 846 | * rx_free list for reuse later. */ |
840 | if (rxb->skb != NULL) { | ||
841 | priv->alloc_rxb_skb--; | ||
842 | dev_kfree_skb_any(rxb->skb); | ||
843 | rxb->skb = NULL; | ||
844 | } | ||
845 | |||
846 | spin_lock_irqsave(&rxq->lock, flags); | 847 | spin_lock_irqsave(&rxq->lock, flags); |
847 | list_add_tail(&rxb->list, &priv->rxq.rx_used); | 848 | if (rxb->page != NULL) { |
849 | rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, | ||
850 | 0, PAGE_SIZE << priv->hw_params.rx_page_order, | ||
851 | PCI_DMA_FROMDEVICE); | ||
852 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
853 | rxq->free_count++; | ||
854 | } else | ||
855 | list_add_tail(&rxb->list, &rxq->rx_used); | ||
856 | |||
848 | spin_unlock_irqrestore(&rxq->lock, flags); | 857 | spin_unlock_irqrestore(&rxq->lock, flags); |
858 | |||
849 | i = (i + 1) & RX_QUEUE_MASK; | 859 | i = (i + 1) & RX_QUEUE_MASK; |
850 | /* If there are a lot of unused frames, | 860 | /* If there are a lot of unused frames, |
851 | * restock the Rx queue so ucode wont assert. */ | 861 | * restock the Rx queue so ucode wont assert. */ |
852 | if (fill_rx) { | 862 | if (fill_rx) { |
853 | count++; | 863 | count++; |
854 | if (count >= 8) { | 864 | if (count >= 8) { |
855 | priv->rxq.read = i; | 865 | rxq->read = i; |
856 | iwl_rx_replenish_now(priv); | 866 | iwl_rx_replenish_now(priv); |
857 | count = 0; | 867 | count = 0; |
858 | } | 868 | } |
@@ -860,7 +870,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
860 | } | 870 | } |
861 | 871 | ||
862 | /* Backtrack one entry */ | 872 | /* Backtrack one entry */ |
863 | priv->rxq.read = i; | 873 | rxq->read = i; |
864 | if (fill_rx) | 874 | if (fill_rx) |
865 | iwl_rx_replenish_now(priv); | 875 | iwl_rx_replenish_now(priv); |
866 | else | 876 | else |
@@ -907,6 +917,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
907 | } | 917 | } |
908 | #endif | 918 | #endif |
909 | 919 | ||
920 | spin_unlock_irqrestore(&priv->lock, flags); | ||
921 | |||
910 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not | 922 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not |
911 | * atomic, make sure that inta covers all the interrupts that | 923 | * atomic, make sure that inta covers all the interrupts that |
912 | * we've discovered, even if FH interrupt came in just after | 924 | * we've discovered, even if FH interrupt came in just after |
@@ -928,8 +940,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
928 | 940 | ||
929 | handled |= CSR_INT_BIT_HW_ERR; | 941 | handled |= CSR_INT_BIT_HW_ERR; |
930 | 942 | ||
931 | spin_unlock_irqrestore(&priv->lock, flags); | ||
932 | |||
933 | return; | 943 | return; |
934 | } | 944 | } |
935 | 945 | ||
@@ -1019,6 +1029,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1019 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 1029 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
1020 | iwl_rx_handle(priv); | 1030 | iwl_rx_handle(priv); |
1021 | priv->isr_stats.rx++; | 1031 | priv->isr_stats.rx++; |
1032 | iwl_leds_background(priv); | ||
1022 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 1033 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
1023 | } | 1034 | } |
1024 | 1035 | ||
@@ -1056,7 +1067,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1056 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); | 1067 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); |
1057 | } | 1068 | } |
1058 | #endif | 1069 | #endif |
1059 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1060 | } | 1070 | } |
1061 | 1071 | ||
1062 | /* tasklet for iwlagn interrupt */ | 1072 | /* tasklet for iwlagn interrupt */ |
@@ -1086,6 +1096,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1086 | inta, inta_mask); | 1096 | inta, inta_mask); |
1087 | } | 1097 | } |
1088 | #endif | 1098 | #endif |
1099 | |||
1100 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1101 | |||
1089 | /* saved interrupt in inta variable now we can reset priv->inta */ | 1102 | /* saved interrupt in inta variable now we can reset priv->inta */ |
1090 | priv->inta = 0; | 1103 | priv->inta = 0; |
1091 | 1104 | ||
@@ -1101,8 +1114,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1101 | 1114 | ||
1102 | handled |= CSR_INT_BIT_HW_ERR; | 1115 | handled |= CSR_INT_BIT_HW_ERR; |
1103 | 1116 | ||
1104 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1105 | |||
1106 | return; | 1117 | return; |
1107 | } | 1118 | } |
1108 | 1119 | ||
@@ -1220,6 +1231,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1220 | CSR_INT_PERIODIC_ENA); | 1231 | CSR_INT_PERIODIC_ENA); |
1221 | 1232 | ||
1222 | priv->isr_stats.rx++; | 1233 | priv->isr_stats.rx++; |
1234 | iwl_leds_background(priv); | ||
1223 | } | 1235 | } |
1224 | 1236 | ||
1225 | if (inta & CSR_INT_BIT_FH_TX) { | 1237 | if (inta & CSR_INT_BIT_FH_TX) { |
@@ -1242,14 +1254,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1242 | inta & ~priv->inta_mask); | 1254 | inta & ~priv->inta_mask); |
1243 | } | 1255 | } |
1244 | 1256 | ||
1245 | |||
1246 | /* Re-enable all interrupts */ | 1257 | /* Re-enable all interrupts */ |
1247 | /* only Re-enable if diabled by irq */ | 1258 | /* only Re-enable if diabled by irq */ |
1248 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1259 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1249 | iwl_enable_interrupts(priv); | 1260 | iwl_enable_interrupts(priv); |
1250 | |||
1251 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1252 | |||
1253 | } | 1261 | } |
1254 | 1262 | ||
1255 | 1263 | ||
@@ -1899,11 +1907,9 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1899 | 1907 | ||
1900 | udelay(5); | 1908 | udelay(5); |
1901 | 1909 | ||
1902 | /* FIXME: apm_ops.suspend(priv) */ | 1910 | /* Stop the device, and put it in low power state */ |
1903 | if (exit_pending) | 1911 | priv->cfg->ops->lib->apm_ops.stop(priv); |
1904 | priv->cfg->ops->lib->apm_ops.stop(priv); | 1912 | |
1905 | else | ||
1906 | priv->cfg->ops->lib->apm_ops.reset(priv); | ||
1907 | exit: | 1913 | exit: |
1908 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | 1914 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); |
1909 | 1915 | ||
@@ -2290,6 +2296,69 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2290 | 2296 | ||
2291 | #define UCODE_READY_TIMEOUT (4 * HZ) | 2297 | #define UCODE_READY_TIMEOUT (4 * HZ) |
2292 | 2298 | ||
2299 | /* | ||
2300 | * Not a mac80211 entry point function, but it fits in with all the | ||
2301 | * other mac80211 functions grouped here. | ||
2302 | */ | ||
2303 | static int iwl_setup_mac(struct iwl_priv *priv) | ||
2304 | { | ||
2305 | int ret; | ||
2306 | struct ieee80211_hw *hw = priv->hw; | ||
2307 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
2308 | |||
2309 | /* Tell mac80211 our characteristics */ | ||
2310 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
2311 | IEEE80211_HW_NOISE_DBM | | ||
2312 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
2313 | IEEE80211_HW_SPECTRUM_MGMT; | ||
2314 | |||
2315 | if (!priv->cfg->broken_powersave) | ||
2316 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
2317 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
2318 | |||
2319 | hw->sta_data_size = sizeof(struct iwl_station_priv); | ||
2320 | hw->wiphy->interface_modes = | ||
2321 | BIT(NL80211_IFTYPE_STATION) | | ||
2322 | BIT(NL80211_IFTYPE_ADHOC); | ||
2323 | |||
2324 | hw->wiphy->custom_regulatory = true; | ||
2325 | |||
2326 | /* Firmware does not support this */ | ||
2327 | hw->wiphy->disable_beacon_hints = true; | ||
2328 | |||
2329 | /* | ||
2330 | * For now, disable PS by default because it affects | ||
2331 | * RX performance significantly. | ||
2332 | */ | ||
2333 | hw->wiphy->ps_default = false; | ||
2334 | |||
2335 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
2336 | /* we create the 802.11 header and a zero-length SSID element */ | ||
2337 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | ||
2338 | |||
2339 | /* Default value; 4 EDCA QOS priorities */ | ||
2340 | hw->queues = 4; | ||
2341 | |||
2342 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
2343 | |||
2344 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
2345 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
2346 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
2347 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
2348 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
2349 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
2350 | |||
2351 | ret = ieee80211_register_hw(priv->hw); | ||
2352 | if (ret) { | ||
2353 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
2354 | return ret; | ||
2355 | } | ||
2356 | priv->mac80211_registered = 1; | ||
2357 | |||
2358 | return 0; | ||
2359 | } | ||
2360 | |||
2361 | |||
2293 | static int iwl_mac_start(struct ieee80211_hw *hw) | 2362 | static int iwl_mac_start(struct ieee80211_hw *hw) |
2294 | { | 2363 | { |
2295 | struct iwl_priv *priv = hw->priv; | 2364 | struct iwl_priv *priv = hw->priv; |
@@ -3187,6 +3256,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3187 | iwl_down(priv); | 3256 | iwl_down(priv); |
3188 | } | 3257 | } |
3189 | 3258 | ||
3259 | /* | ||
3260 | * Make sure device is reset to low power before unloading driver. | ||
3261 | * This may be redundant with iwl_down(), but there are paths to | ||
3262 | * run iwl_down() without calling apm_ops.stop(), and there are | ||
3263 | * paths to avoid running iwl_down() at all before leaving driver. | ||
3264 | * This (inexpensive) call *makes sure* device is reset. | ||
3265 | */ | ||
3266 | priv->cfg->ops->lib->apm_ops.stop(priv); | ||
3267 | |||
3190 | iwl_tt_exit(priv); | 3268 | iwl_tt_exit(priv); |
3191 | 3269 | ||
3192 | /* make sure we flush any pending irq or | 3270 | /* make sure we flush any pending irq or |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 69a80d7c2e44..1f801eb9fbff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -447,11 +447,11 @@ static int iwl_sensitivity_write(struct iwl_priv *priv) | |||
447 | cpu_to_le16((u16)data->nrg_th_ofdm); | 447 | cpu_to_le16((u16)data->nrg_th_ofdm); |
448 | 448 | ||
449 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = | 449 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = |
450 | cpu_to_le16(190); | 450 | cpu_to_le16(data->barker_corr_th_min); |
451 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = | 451 | cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = |
452 | cpu_to_le16(390); | 452 | cpu_to_le16(data->barker_corr_th_min_mrc); |
453 | cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = | 453 | cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = |
454 | cpu_to_le16(62); | 454 | cpu_to_le16(data->nrg_th_cca); |
455 | 455 | ||
456 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", | 456 | IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", |
457 | data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, | 457 | data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, |
@@ -524,6 +524,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
524 | data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc; | 524 | data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc; |
525 | data->nrg_th_cck = ranges->nrg_th_cck; | 525 | data->nrg_th_cck = ranges->nrg_th_cck; |
526 | data->nrg_th_ofdm = ranges->nrg_th_ofdm; | 526 | data->nrg_th_ofdm = ranges->nrg_th_ofdm; |
527 | data->barker_corr_th_min = ranges->barker_corr_th_min; | ||
528 | data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc; | ||
529 | data->nrg_th_cca = ranges->nrg_th_cca; | ||
527 | 530 | ||
528 | data->last_bad_plcp_cnt_ofdm = 0; | 531 | data->last_bad_plcp_cnt_ofdm = 0; |
529 | data->last_fa_cnt_ofdm = 0; | 532 | data->last_fa_cnt_ofdm = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index ba3e4c837d87..954bad60355d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -109,11 +109,12 @@ enum { | |||
109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ | 109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ |
110 | 110 | ||
111 | /* WiMAX coexistence */ | 111 | /* WiMAX coexistence */ |
112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /*5000 only */ | 112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ |
113 | COEX_MEDIUM_NOTIFICATION = 0x5b, | 113 | COEX_MEDIUM_NOTIFICATION = 0x5b, |
114 | COEX_EVENT_CMD = 0x5c, | 114 | COEX_EVENT_CMD = 0x5c, |
115 | 115 | ||
116 | /* Calibration */ | 116 | /* Calibration */ |
117 | TEMPERATURE_NOTIFICATION = 0x62, | ||
117 | CALIBRATION_CFG_CMD = 0x65, | 118 | CALIBRATION_CFG_CMD = 0x65, |
118 | CALIBRATION_RES_NOTIFICATION = 0x66, | 119 | CALIBRATION_RES_NOTIFICATION = 0x66, |
119 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, | 120 | CALIBRATION_COMPLETE_NOTIFICATION = 0x67, |
@@ -353,6 +354,9 @@ struct iwl3945_power_per_rate { | |||
353 | #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 | 354 | #define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 |
354 | #define POWER_TABLE_CCK_ENTRY 32 | 355 | #define POWER_TABLE_CCK_ENTRY 32 |
355 | 356 | ||
357 | #define IWL_PWR_NUM_HT_OFDM_ENTRIES 24 | ||
358 | #define IWL_PWR_CCK_ENTRIES 2 | ||
359 | |||
356 | /** | 360 | /** |
357 | * union iwl4965_tx_power_dual_stream | 361 | * union iwl4965_tx_power_dual_stream |
358 | * | 362 | * |
@@ -803,7 +807,7 @@ struct iwl3945_channel_switch_cmd { | |||
803 | struct iwl3945_power_per_rate power[IWL_MAX_RATES]; | 807 | struct iwl3945_power_per_rate power[IWL_MAX_RATES]; |
804 | } __attribute__ ((packed)); | 808 | } __attribute__ ((packed)); |
805 | 809 | ||
806 | struct iwl_channel_switch_cmd { | 810 | struct iwl4965_channel_switch_cmd { |
807 | u8 band; | 811 | u8 band; |
808 | u8 expect_beacon; | 812 | u8 expect_beacon; |
809 | __le16 channel; | 813 | __le16 channel; |
@@ -813,6 +817,48 @@ struct iwl_channel_switch_cmd { | |||
813 | struct iwl4965_tx_power_db tx_power; | 817 | struct iwl4965_tx_power_db tx_power; |
814 | } __attribute__ ((packed)); | 818 | } __attribute__ ((packed)); |
815 | 819 | ||
820 | /** | ||
821 | * struct iwl5000_channel_switch_cmd | ||
822 | * @band: 0- 5.2GHz, 1- 2.4GHz | ||
823 | * @expect_beacon: 0- resume transmits after channel switch | ||
824 | * 1- wait for beacon to resume transmits | ||
825 | * @channel: new channel number | ||
826 | * @rxon_flags: Rx on flags | ||
827 | * @rxon_filter_flags: filtering parameters | ||
828 | * @switch_time: switch time in extended beacon format | ||
829 | * @reserved: reserved bytes | ||
830 | */ | ||
831 | struct iwl5000_channel_switch_cmd { | ||
832 | u8 band; | ||
833 | u8 expect_beacon; | ||
834 | __le16 channel; | ||
835 | __le32 rxon_flags; | ||
836 | __le32 rxon_filter_flags; | ||
837 | __le32 switch_time; | ||
838 | __le32 reserved[2][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; | ||
839 | } __attribute__ ((packed)); | ||
840 | |||
841 | /** | ||
842 | * struct iwl6000_channel_switch_cmd | ||
843 | * @band: 0- 5.2GHz, 1- 2.4GHz | ||
844 | * @expect_beacon: 0- resume transmits after channel switch | ||
845 | * 1- wait for beacon to resume transmits | ||
846 | * @channel: new channel number | ||
847 | * @rxon_flags: Rx on flags | ||
848 | * @rxon_filter_flags: filtering parameters | ||
849 | * @switch_time: switch time in extended beacon format | ||
850 | * @reserved: reserved bytes | ||
851 | */ | ||
852 | struct iwl6000_channel_switch_cmd { | ||
853 | u8 band; | ||
854 | u8 expect_beacon; | ||
855 | __le16 channel; | ||
856 | __le32 rxon_flags; | ||
857 | __le32 rxon_filter_flags; | ||
858 | __le32 switch_time; | ||
859 | __le32 reserved[3][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES]; | ||
860 | } __attribute__ ((packed)); | ||
861 | |||
816 | /* | 862 | /* |
817 | * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) | 863 | * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) |
818 | */ | 864 | */ |
@@ -2172,6 +2218,19 @@ struct iwl_link_quality_cmd { | |||
2172 | __le32 reserved2; | 2218 | __le32 reserved2; |
2173 | } __attribute__ ((packed)); | 2219 | } __attribute__ ((packed)); |
2174 | 2220 | ||
2221 | #define BT_COEX_DISABLE (0x0) | ||
2222 | #define BT_COEX_MODE_2W (0x1) | ||
2223 | #define BT_COEX_MODE_3W (0x2) | ||
2224 | #define BT_COEX_MODE_4W (0x3) | ||
2225 | |||
2226 | #define BT_LEAD_TIME_MIN (0x0) | ||
2227 | #define BT_LEAD_TIME_DEF (0x1E) | ||
2228 | #define BT_LEAD_TIME_MAX (0xFF) | ||
2229 | |||
2230 | #define BT_MAX_KILL_MIN (0x1) | ||
2231 | #define BT_MAX_KILL_DEF (0x5) | ||
2232 | #define BT_MAX_KILL_MAX (0xFF) | ||
2233 | |||
2175 | /* | 2234 | /* |
2176 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) | 2235 | * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) |
2177 | * | 2236 | * |
@@ -3247,12 +3306,6 @@ struct iwl_missed_beacon_notif { | |||
3247 | * Lower values mean higher energy; this means making sure that the value | 3306 | * Lower values mean higher energy; this means making sure that the value |
3248 | * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". | 3307 | * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". |
3249 | * | 3308 | * |
3250 | * Driver should set the following entries to fixed values: | ||
3251 | * | ||
3252 | * HD_MIN_ENERGY_OFDM_DET_INDEX 100 | ||
3253 | * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190 | ||
3254 | * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390 | ||
3255 | * HD_OFDM_ENERGY_TH_IN_INDEX 62 | ||
3256 | */ | 3309 | */ |
3257 | 3310 | ||
3258 | /* | 3311 | /* |
@@ -3505,6 +3558,16 @@ struct iwl_wimax_coex_cmd { | |||
3505 | *****************************************************************************/ | 3558 | *****************************************************************************/ |
3506 | 3559 | ||
3507 | struct iwl_rx_packet { | 3560 | struct iwl_rx_packet { |
3561 | /* | ||
3562 | * The first 4 bytes of the RX frame header contain both the RX frame | ||
3563 | * size and some flags. | ||
3564 | * Bit fields: | ||
3565 | * 31: flag flush RB request | ||
3566 | * 30: flag ignore TC (terminal counter) request | ||
3567 | * 29: flag fast IRQ request | ||
3568 | * 28-14: Reserved | ||
3569 | * 13-00: RX frame size | ||
3570 | */ | ||
3508 | __le32 len_n_flags; | 3571 | __le32 len_n_flags; |
3509 | struct iwl_cmd_header hdr; | 3572 | struct iwl_cmd_header hdr; |
3510 | union { | 3573 | union { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index dc7fd87bed98..d2b56baf98fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -604,6 +604,23 @@ void iwlcore_free_geos(struct iwl_priv *priv) | |||
604 | } | 604 | } |
605 | EXPORT_SYMBOL(iwlcore_free_geos); | 605 | EXPORT_SYMBOL(iwlcore_free_geos); |
606 | 606 | ||
607 | /* | ||
608 | * iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this | ||
609 | * function. | ||
610 | */ | ||
611 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
612 | __le32 *tx_flags) | ||
613 | { | ||
614 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
615 | *tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
616 | *tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
617 | } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
618 | *tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
619 | *tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
620 | } | ||
621 | } | ||
622 | EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag); | ||
623 | |||
607 | static bool is_single_rx_stream(struct iwl_priv *priv) | 624 | static bool is_single_rx_stream(struct iwl_priv *priv) |
608 | { | 625 | { |
609 | return !priv->current_ht_config.is_ht || | 626 | return !priv->current_ht_config.is_ht || |
@@ -1264,13 +1281,18 @@ static void iwl_set_rate(struct iwl_priv *priv) | |||
1264 | 1281 | ||
1265 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1282 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1266 | { | 1283 | { |
1267 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1284 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1268 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; | 1285 | struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; |
1269 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); | 1286 | struct iwl_csa_notification *csa = &(pkt->u.csa_notif); |
1270 | IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n", | 1287 | |
1271 | le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); | 1288 | if (!le32_to_cpu(csa->status)) { |
1272 | rxon->channel = csa->channel; | 1289 | rxon->channel = csa->channel; |
1273 | priv->staging_rxon.channel = csa->channel; | 1290 | priv->staging_rxon.channel = csa->channel; |
1291 | IWL_DEBUG_11H(priv, "CSA notif: channel %d\n", | ||
1292 | le16_to_cpu(csa->channel)); | ||
1293 | } else | ||
1294 | IWL_ERR(priv, "CSA notif (fail) : channel %d\n", | ||
1295 | le16_to_cpu(csa->channel)); | ||
1274 | } | 1296 | } |
1275 | EXPORT_SYMBOL(iwl_rx_csa); | 1297 | EXPORT_SYMBOL(iwl_rx_csa); |
1276 | 1298 | ||
@@ -1352,6 +1374,8 @@ void iwl_apm_stop(struct iwl_priv *priv) | |||
1352 | { | 1374 | { |
1353 | unsigned long flags; | 1375 | unsigned long flags; |
1354 | 1376 | ||
1377 | IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n"); | ||
1378 | |||
1355 | iwl_apm_stop_master(priv); | 1379 | iwl_apm_stop_master(priv); |
1356 | 1380 | ||
1357 | spin_lock_irqsave(&priv->lock, flags); | 1381 | spin_lock_irqsave(&priv->lock, flags); |
@@ -1365,6 +1389,118 @@ void iwl_apm_stop(struct iwl_priv *priv) | |||
1365 | } | 1389 | } |
1366 | EXPORT_SYMBOL(iwl_apm_stop); | 1390 | EXPORT_SYMBOL(iwl_apm_stop); |
1367 | 1391 | ||
1392 | |||
1393 | /* | ||
1394 | * Start up NIC's basic functionality after it has been reset | ||
1395 | * (e.g. after platform boot, or shutdown via iwl_apm_stop()) | ||
1396 | * NOTE: This does not load uCode nor start the embedded processor | ||
1397 | */ | ||
1398 | int iwl_apm_init(struct iwl_priv *priv) | ||
1399 | { | ||
1400 | int ret = 0; | ||
1401 | u16 lctl; | ||
1402 | |||
1403 | IWL_DEBUG_INFO(priv, "Init card's basic functions\n"); | ||
1404 | |||
1405 | /* | ||
1406 | * Use "set_bit" below rather than "write", to preserve any hardware | ||
1407 | * bits already set by default after reset. | ||
1408 | */ | ||
1409 | |||
1410 | /* Disable L0S exit timer (platform NMI Work/Around) */ | ||
1411 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
1412 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
1413 | |||
1414 | /* | ||
1415 | * Disable L0s without affecting L1; | ||
1416 | * don't wait for ICH L0s (ICH bug W/A) | ||
1417 | */ | ||
1418 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
1419 | CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); | ||
1420 | |||
1421 | /* Set FH wait threshold to maximum (HW error during stress W/A) */ | ||
1422 | iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); | ||
1423 | |||
1424 | /* | ||
1425 | * Enable HAP INTA (interrupt from management bus) to | ||
1426 | * wake device's PCI Express link L1a -> L0s | ||
1427 | * NOTE: This is no-op for 3945 (non-existant bit) | ||
1428 | */ | ||
1429 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
1430 | CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); | ||
1431 | |||
1432 | /* | ||
1433 | * HW bug W/A - costs negligible power consumption ... | ||
1434 | * Check if BIOS (or OS) enabled L1-ASPM on this device | ||
1435 | */ | ||
1436 | if (priv->cfg->set_l0s) { | ||
1437 | lctl = iwl_pcie_link_ctl(priv); | ||
1438 | if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == | ||
1439 | PCI_CFG_LINK_CTRL_VAL_L1_EN) { | ||
1440 | /* L1-ASPM enabled; disable(!) L0S */ | ||
1441 | iwl_set_bit(priv, CSR_GIO_REG, | ||
1442 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1443 | IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); | ||
1444 | } else { | ||
1445 | /* L1-ASPM disabled; enable(!) L0S */ | ||
1446 | iwl_clear_bit(priv, CSR_GIO_REG, | ||
1447 | CSR_GIO_REG_VAL_L0S_ENABLED); | ||
1448 | IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); | ||
1449 | } | ||
1450 | } | ||
1451 | |||
1452 | /* Configure analog phase-lock-loop before activating to D0A */ | ||
1453 | if (priv->cfg->pll_cfg_val) | ||
1454 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val); | ||
1455 | |||
1456 | /* | ||
1457 | * Set "initialization complete" bit to move adapter from | ||
1458 | * D0U* --> D0A* (powered-up active) state. | ||
1459 | */ | ||
1460 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1461 | |||
1462 | /* | ||
1463 | * Wait for clock stabilization; once stabilized, access to | ||
1464 | * device-internal resources is supported, e.g. iwl_write_prph() | ||
1465 | * and accesses to uCode SRAM. | ||
1466 | */ | ||
1467 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | ||
1468 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
1469 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1470 | if (ret < 0) { | ||
1471 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | ||
1472 | goto out; | ||
1473 | } | ||
1474 | |||
1475 | /* | ||
1476 | * Enable DMA and BSM (if used) clocks, wait for them to stabilize. | ||
1477 | * BSM (Boostrap State Machine) is only in 3945 and 4965; | ||
1478 | * later devices (i.e. 5000 and later) have non-volatile SRAM, | ||
1479 | * and don't need BSM to restore data after power-saving sleep. | ||
1480 | * | ||
1481 | * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits | ||
1482 | * do not disable clocks. This preserves any hardware bits already | ||
1483 | * set by default in "CLK_CTRL_REG" after reset. | ||
1484 | */ | ||
1485 | if (priv->cfg->use_bsm) | ||
1486 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1487 | APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); | ||
1488 | else | ||
1489 | iwl_write_prph(priv, APMG_CLK_EN_REG, | ||
1490 | APMG_CLK_VAL_DMA_CLK_RQT); | ||
1491 | udelay(20); | ||
1492 | |||
1493 | /* Disable L1-Active */ | ||
1494 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | ||
1495 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | ||
1496 | |||
1497 | out: | ||
1498 | return ret; | ||
1499 | } | ||
1500 | EXPORT_SYMBOL(iwl_apm_init); | ||
1501 | |||
1502 | |||
1503 | |||
1368 | void iwl_configure_filter(struct ieee80211_hw *hw, | 1504 | void iwl_configure_filter(struct ieee80211_hw *hw, |
1369 | unsigned int changed_flags, | 1505 | unsigned int changed_flags, |
1370 | unsigned int *total_flags, | 1506 | unsigned int *total_flags, |
@@ -1412,73 +1548,14 @@ void iwl_configure_filter(struct ieee80211_hw *hw, | |||
1412 | } | 1548 | } |
1413 | EXPORT_SYMBOL(iwl_configure_filter); | 1549 | EXPORT_SYMBOL(iwl_configure_filter); |
1414 | 1550 | ||
1415 | int iwl_setup_mac(struct iwl_priv *priv) | ||
1416 | { | ||
1417 | int ret; | ||
1418 | struct ieee80211_hw *hw = priv->hw; | ||
1419 | hw->rate_control_algorithm = "iwl-agn-rs"; | ||
1420 | |||
1421 | /* Tell mac80211 our characteristics */ | ||
1422 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | ||
1423 | IEEE80211_HW_NOISE_DBM | | ||
1424 | IEEE80211_HW_AMPDU_AGGREGATION | | ||
1425 | IEEE80211_HW_SPECTRUM_MGMT; | ||
1426 | |||
1427 | if (!priv->cfg->broken_powersave) | ||
1428 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | ||
1429 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
1430 | |||
1431 | hw->wiphy->interface_modes = | ||
1432 | BIT(NL80211_IFTYPE_STATION) | | ||
1433 | BIT(NL80211_IFTYPE_ADHOC); | ||
1434 | |||
1435 | hw->wiphy->custom_regulatory = true; | ||
1436 | |||
1437 | /* Firmware does not support this */ | ||
1438 | hw->wiphy->disable_beacon_hints = true; | ||
1439 | |||
1440 | /* | ||
1441 | * For now, disable PS by default because it affects | ||
1442 | * RX performance significantly. | ||
1443 | */ | ||
1444 | hw->wiphy->ps_default = false; | ||
1445 | |||
1446 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | ||
1447 | /* we create the 802.11 header and a zero-length SSID element */ | ||
1448 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | ||
1449 | |||
1450 | /* Default value; 4 EDCA QOS priorities */ | ||
1451 | hw->queues = 4; | ||
1452 | |||
1453 | hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||
1454 | |||
1455 | if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | ||
1456 | priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
1457 | &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1458 | if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | ||
1459 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
1460 | &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1461 | |||
1462 | ret = ieee80211_register_hw(priv->hw); | ||
1463 | if (ret) { | ||
1464 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | ||
1465 | return ret; | ||
1466 | } | ||
1467 | priv->mac80211_registered = 1; | ||
1468 | |||
1469 | return 0; | ||
1470 | } | ||
1471 | EXPORT_SYMBOL(iwl_setup_mac); | ||
1472 | |||
1473 | int iwl_set_hw_params(struct iwl_priv *priv) | 1551 | int iwl_set_hw_params(struct iwl_priv *priv) |
1474 | { | 1552 | { |
1475 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | 1553 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
1476 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | 1554 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
1477 | if (priv->cfg->mod_params->amsdu_size_8K) | 1555 | if (priv->cfg->mod_params->amsdu_size_8K) |
1478 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | 1556 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); |
1479 | else | 1557 | else |
1480 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | 1558 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); |
1481 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | ||
1482 | 1559 | ||
1483 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | 1560 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; |
1484 | 1561 | ||
@@ -1507,7 +1584,6 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
1507 | /* Clear the driver's (not device's) station table */ | 1584 | /* Clear the driver's (not device's) station table */ |
1508 | iwl_clear_stations_table(priv); | 1585 | iwl_clear_stations_table(priv); |
1509 | 1586 | ||
1510 | priv->data_retry_limit = -1; | ||
1511 | priv->ieee_channels = NULL; | 1587 | priv->ieee_channels = NULL; |
1512 | priv->ieee_rates = NULL; | 1588 | priv->ieee_rates = NULL; |
1513 | priv->band = IEEE80211_BAND_2GHZ; | 1589 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -1932,9 +2008,9 @@ EXPORT_SYMBOL(iwl_isr_legacy); | |||
1932 | int iwl_send_bt_config(struct iwl_priv *priv) | 2008 | int iwl_send_bt_config(struct iwl_priv *priv) |
1933 | { | 2009 | { |
1934 | struct iwl_bt_cmd bt_cmd = { | 2010 | struct iwl_bt_cmd bt_cmd = { |
1935 | .flags = 3, | 2011 | .flags = BT_COEX_MODE_4W, |
1936 | .lead_time = 0xAA, | 2012 | .lead_time = BT_LEAD_TIME_DEF, |
1937 | .max_kill = 1, | 2013 | .max_kill = BT_MAX_KILL_DEF, |
1938 | .kill_ack_mask = 0, | 2014 | .kill_ack_mask = 0, |
1939 | .kill_cts_mask = 0, | 2015 | .kill_cts_mask = 0, |
1940 | }; | 2016 | }; |
@@ -2094,10 +2170,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2094 | spin_unlock_irqrestore(&priv->lock, flags); | 2170 | spin_unlock_irqrestore(&priv->lock, flags); |
2095 | priv->thermal_throttle.ct_kill_toggle = false; | 2171 | priv->thermal_throttle.ct_kill_toggle = false; |
2096 | 2172 | ||
2097 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 2173 | if (priv->cfg->support_ct_kill_exit) { |
2098 | case CSR_HW_REV_TYPE_1000: | ||
2099 | case CSR_HW_REV_TYPE_6x00: | ||
2100 | case CSR_HW_REV_TYPE_6x50: | ||
2101 | adv_cmd.critical_temperature_enter = | 2174 | adv_cmd.critical_temperature_enter = |
2102 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 2175 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
2103 | adv_cmd.critical_temperature_exit = | 2176 | adv_cmd.critical_temperature_exit = |
@@ -2114,8 +2187,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2114 | "exit is %d\n", | 2187 | "exit is %d\n", |
2115 | priv->hw_params.ct_kill_threshold, | 2188 | priv->hw_params.ct_kill_threshold, |
2116 | priv->hw_params.ct_kill_exit_threshold); | 2189 | priv->hw_params.ct_kill_exit_threshold); |
2117 | break; | 2190 | } else { |
2118 | default: | ||
2119 | cmd.critical_temperature_R = | 2191 | cmd.critical_temperature_R = |
2120 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | 2192 | cpu_to_le32(priv->hw_params.ct_kill_threshold); |
2121 | 2193 | ||
@@ -2128,7 +2200,6 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv) | |||
2128 | "succeeded, " | 2200 | "succeeded, " |
2129 | "critical temperature is %d\n", | 2201 | "critical temperature is %d\n", |
2130 | priv->hw_params.ct_kill_threshold); | 2202 | priv->hw_params.ct_kill_threshold); |
2131 | break; | ||
2132 | } | 2203 | } |
2133 | } | 2204 | } |
2134 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); | 2205 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); |
@@ -2160,7 +2231,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | |||
2160 | struct iwl_rx_mem_buffer *rxb) | 2231 | struct iwl_rx_mem_buffer *rxb) |
2161 | { | 2232 | { |
2162 | #ifdef CONFIG_IWLWIFI_DEBUG | 2233 | #ifdef CONFIG_IWLWIFI_DEBUG |
2163 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2234 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2164 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); | 2235 | struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); |
2165 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", | 2236 | IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", |
2166 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); | 2237 | sleep->pm_sleep_mode, sleep->pm_wakeup_src); |
@@ -2171,7 +2242,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif); | |||
2171 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | 2242 | void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, |
2172 | struct iwl_rx_mem_buffer *rxb) | 2243 | struct iwl_rx_mem_buffer *rxb) |
2173 | { | 2244 | { |
2174 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2245 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2175 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 2246 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
2176 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 2247 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
2177 | "notification for %s:\n", len, | 2248 | "notification for %s:\n", len, |
@@ -2183,7 +2254,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); | |||
2183 | void iwl_rx_reply_error(struct iwl_priv *priv, | 2254 | void iwl_rx_reply_error(struct iwl_priv *priv, |
2184 | struct iwl_rx_mem_buffer *rxb) | 2255 | struct iwl_rx_mem_buffer *rxb) |
2185 | { | 2256 | { |
2186 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2257 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2187 | 2258 | ||
2188 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " | 2259 | IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " |
2189 | "seq 0x%04X ser 0x%08X\n", | 2260 | "seq 0x%04X ser 0x%08X\n", |
@@ -2648,6 +2719,14 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2648 | goto set_ch_out; | 2719 | goto set_ch_out; |
2649 | } | 2720 | } |
2650 | 2721 | ||
2722 | if (iwl_is_associated(priv) && | ||
2723 | (le16_to_cpu(priv->active_rxon.channel) != ch) && | ||
2724 | priv->cfg->ops->lib->set_channel_switch) { | ||
2725 | ret = priv->cfg->ops->lib->set_channel_switch(priv, | ||
2726 | ch); | ||
2727 | goto out; | ||
2728 | } | ||
2729 | |||
2651 | spin_lock_irqsave(&priv->lock, flags); | 2730 | spin_lock_irqsave(&priv->lock, flags); |
2652 | 2731 | ||
2653 | /* Configure HT40 channels */ | 2732 | /* Configure HT40 channels */ |
@@ -2826,6 +2905,27 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2826 | } | 2905 | } |
2827 | EXPORT_SYMBOL(iwl_mac_reset_tsf); | 2906 | EXPORT_SYMBOL(iwl_mac_reset_tsf); |
2828 | 2907 | ||
2908 | int iwl_alloc_txq_mem(struct iwl_priv *priv) | ||
2909 | { | ||
2910 | if (!priv->txq) | ||
2911 | priv->txq = kzalloc( | ||
2912 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | ||
2913 | GFP_KERNEL); | ||
2914 | if (!priv->txq) { | ||
2915 | IWL_ERR(priv, "Not enough memory for txq \n"); | ||
2916 | return -ENOMEM; | ||
2917 | } | ||
2918 | return 0; | ||
2919 | } | ||
2920 | EXPORT_SYMBOL(iwl_alloc_txq_mem); | ||
2921 | |||
2922 | void iwl_free_txq_mem(struct iwl_priv *priv) | ||
2923 | { | ||
2924 | kfree(priv->txq); | ||
2925 | priv->txq = NULL; | ||
2926 | } | ||
2927 | EXPORT_SYMBOL(iwl_free_txq_mem); | ||
2928 | |||
2829 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 2929 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
2830 | 2930 | ||
2831 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) | 2931 | #define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6688b6944200..b875dcfca2d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -109,7 +109,6 @@ struct iwl_hcmd_utils_ops { | |||
109 | 109 | ||
110 | struct iwl_apm_ops { | 110 | struct iwl_apm_ops { |
111 | int (*init)(struct iwl_priv *priv); | 111 | int (*init)(struct iwl_priv *priv); |
112 | int (*reset)(struct iwl_priv *priv); | ||
113 | void (*stop)(struct iwl_priv *priv); | 112 | void (*stop)(struct iwl_priv *priv); |
114 | void (*config)(struct iwl_priv *priv); | 113 | void (*config)(struct iwl_priv *priv); |
115 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); | 114 | int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); |
@@ -170,6 +169,7 @@ struct iwl_lib_ops { | |||
170 | int (*load_ucode)(struct iwl_priv *priv); | 169 | int (*load_ucode)(struct iwl_priv *priv); |
171 | void (*dump_nic_event_log)(struct iwl_priv *priv); | 170 | void (*dump_nic_event_log)(struct iwl_priv *priv); |
172 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 171 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
172 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | ||
173 | /* power management */ | 173 | /* power management */ |
174 | struct iwl_apm_ops apm_ops; | 174 | struct iwl_apm_ops apm_ops; |
175 | 175 | ||
@@ -205,7 +205,6 @@ struct iwl_mod_params { | |||
205 | int sw_crypto; /* def: 0 = using hardware encryption */ | 205 | int sw_crypto; /* def: 0 = using hardware encryption */ |
206 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 206 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
207 | int num_of_queues; /* def: HW dependent */ | 207 | int num_of_queues; /* def: HW dependent */ |
208 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
209 | int disable_11n; /* def: 0 = 11n capabilities enabled */ | 208 | int disable_11n; /* def: 0 = 11n capabilities enabled */ |
210 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ | 209 | int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ |
211 | int antenna; /* def: 0 = both antennas (use diversity) */ | 210 | int antenna; /* def: 0 = both antennas (use diversity) */ |
@@ -227,6 +226,8 @@ struct iwl_mod_params { | |||
227 | * The detail algorithm is described in iwl-led.c | 226 | * The detail algorithm is described in iwl-led.c |
228 | * @use_rts_for_ht: use rts/cts protection for HT traffic | 227 | * @use_rts_for_ht: use rts/cts protection for HT traffic |
229 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 228 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
229 | * @adv_thermal_throttle: support advance thermal throttle | ||
230 | * @support_ct_kill_exit: support ct kill exit condition | ||
230 | * | 231 | * |
231 | * We enable the driver to be backward compatible wrt API version. The | 232 | * We enable the driver to be backward compatible wrt API version. The |
232 | * driver specifies which APIs it supports (with @ucode_api_max being the | 233 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -258,11 +259,18 @@ struct iwl_cfg { | |||
258 | int eeprom_size; | 259 | int eeprom_size; |
259 | u16 eeprom_ver; | 260 | u16 eeprom_ver; |
260 | u16 eeprom_calib_ver; | 261 | u16 eeprom_calib_ver; |
262 | int num_of_queues; /* def: HW dependent */ | ||
263 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
261 | const struct iwl_ops *ops; | 264 | const struct iwl_ops *ops; |
262 | const struct iwl_mod_params *mod_params; | 265 | const struct iwl_mod_params *mod_params; |
263 | u8 valid_tx_ant; | 266 | u8 valid_tx_ant; |
264 | u8 valid_rx_ant; | 267 | u8 valid_rx_ant; |
265 | bool need_pll_cfg; | 268 | |
269 | /* for iwl_apm_init() */ | ||
270 | u32 pll_cfg_val; | ||
271 | bool set_l0s; | ||
272 | bool use_bsm; | ||
273 | |||
266 | bool use_isr_legacy; | 274 | bool use_isr_legacy; |
267 | enum iwl_pa_type pa_type; | 275 | enum iwl_pa_type pa_type; |
268 | const u16 max_ll_items; | 276 | const u16 max_ll_items; |
@@ -273,6 +281,8 @@ struct iwl_cfg { | |||
273 | bool use_rts_for_ht; | 281 | bool use_rts_for_ht; |
274 | int chain_noise_num_beacons; | 282 | int chain_noise_num_beacons; |
275 | const bool supports_idle; | 283 | const bool supports_idle; |
284 | bool adv_thermal_throttle; | ||
285 | bool support_ct_kill_exit; | ||
276 | }; | 286 | }; |
277 | 287 | ||
278 | /*************************** | 288 | /*************************** |
@@ -305,7 +315,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw, | |||
305 | unsigned int changed_flags, | 315 | unsigned int changed_flags, |
306 | unsigned int *total_flags, u64 multicast); | 316 | unsigned int *total_flags, u64 multicast); |
307 | int iwl_hw_nic_init(struct iwl_priv *priv); | 317 | int iwl_hw_nic_init(struct iwl_priv *priv); |
308 | int iwl_setup_mac(struct iwl_priv *priv); | ||
309 | int iwl_set_hw_params(struct iwl_priv *priv); | 318 | int iwl_set_hw_params(struct iwl_priv *priv); |
310 | int iwl_init_drv(struct iwl_priv *priv); | 319 | int iwl_init_drv(struct iwl_priv *priv); |
311 | void iwl_uninit_drv(struct iwl_priv *priv); | 320 | void iwl_uninit_drv(struct iwl_priv *priv); |
@@ -327,6 +336,10 @@ void iwl_config_ap(struct iwl_priv *priv); | |||
327 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | 336 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, |
328 | struct ieee80211_tx_queue_stats *stats); | 337 | struct ieee80211_tx_queue_stats *stats); |
329 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); | 338 | void iwl_mac_reset_tsf(struct ieee80211_hw *hw); |
339 | int iwl_alloc_txq_mem(struct iwl_priv *priv); | ||
340 | void iwl_free_txq_mem(struct iwl_priv *priv); | ||
341 | void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
342 | __le32 *tx_flags); | ||
330 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 343 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
331 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); | 344 | int iwl_alloc_traffic_mem(struct iwl_priv *priv); |
332 | void iwl_free_traffic_mem(struct iwl_priv *priv); | 345 | void iwl_free_traffic_mem(struct iwl_priv *priv); |
@@ -527,7 +540,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, | |||
527 | const void *data, | 540 | const void *data, |
528 | void (*callback)(struct iwl_priv *priv, | 541 | void (*callback)(struct iwl_priv *priv, |
529 | struct iwl_device_cmd *cmd, | 542 | struct iwl_device_cmd *cmd, |
530 | struct sk_buff *skb)); | 543 | struct iwl_rx_packet *pkt)); |
531 | 544 | ||
532 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 545 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
533 | 546 | ||
@@ -660,6 +673,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
660 | struct iwl_rx_mem_buffer *rxb); | 673 | struct iwl_rx_mem_buffer *rxb); |
661 | void iwl_apm_stop(struct iwl_priv *priv); | 674 | void iwl_apm_stop(struct iwl_priv *priv); |
662 | int iwl_apm_stop_master(struct iwl_priv *priv); | 675 | int iwl_apm_stop_master(struct iwl_priv *priv); |
676 | int iwl_apm_init(struct iwl_priv *priv); | ||
663 | 677 | ||
664 | void iwl_setup_rxon_timing(struct iwl_priv *priv); | 678 | void iwl_setup_rxon_timing(struct iwl_priv *priv); |
665 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 679 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 8f183e0fa512..b6ed5a3147a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -109,8 +109,9 @@ | |||
109 | * Bit fields: | 109 | * Bit fields: |
110 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step | 110 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step |
111 | */ | 111 | */ |
112 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) | 112 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) |
113 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) | 113 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) |
114 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) | ||
114 | 115 | ||
115 | /* Bits for CSR_HW_IF_CONFIG_REG */ | 116 | /* Bits for CSR_HW_IF_CONFIG_REG */ |
116 | #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) | 117 | #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) |
@@ -195,6 +196,7 @@ | |||
195 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) | 196 | #define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) |
196 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) | 197 | #define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) |
197 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | 198 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) |
199 | #define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000) | ||
198 | 200 | ||
199 | /* GP (general purpose) CONTROL */ | 201 | /* GP (general purpose) CONTROL */ |
200 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | 202 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) |
@@ -235,6 +237,11 @@ | |||
235 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ | 237 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ |
236 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ | 238 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ |
237 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ | 239 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ |
240 | #define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */ | ||
241 | #define CSR_GP_REG_NO_POWER_SAVE (0x00000000) | ||
242 | #define CSR_GP_REG_MAC_POWER_SAVE (0x01000000) | ||
243 | #define CSR_GP_REG_PHY_POWER_SAVE (0x02000000) | ||
244 | #define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000) | ||
238 | 245 | ||
239 | /* EEPROM signature */ | 246 | /* EEPROM signature */ |
240 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) | 247 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index b9ca475cc61c..96c92eab692a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -106,6 +106,7 @@ struct iwl_debugfs { | |||
106 | struct dentry *file_sensitivity; | 106 | struct dentry *file_sensitivity; |
107 | struct dentry *file_chain_noise; | 107 | struct dentry *file_chain_noise; |
108 | struct dentry *file_tx_power; | 108 | struct dentry *file_tx_power; |
109 | struct dentry *file_power_save_status; | ||
109 | } dbgfs_debug_files; | 110 | } dbgfs_debug_files; |
110 | u32 sram_offset; | 111 | u32 sram_offset; |
111 | u32 sram_len; | 112 | u32 sram_len; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 1794b9c4e6ac..8784911fd56e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -801,15 +801,20 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, | |||
801 | * valid here. However, let's not confuse them and present | 801 | * valid here. However, let's not confuse them and present |
802 | * IWL_POWER_INDEX_1 as "1", not "0". | 802 | * IWL_POWER_INDEX_1 as "1", not "0". |
803 | */ | 803 | */ |
804 | if (value > 0) | 804 | if (value == 0) |
805 | return -EINVAL; | ||
806 | else if (value > 0) | ||
805 | value -= 1; | 807 | value -= 1; |
806 | 808 | ||
807 | if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) | 809 | if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) |
808 | return -EINVAL; | 810 | return -EINVAL; |
809 | 811 | ||
812 | if (!iwl_is_ready_rf(priv)) | ||
813 | return -EAGAIN; | ||
814 | |||
810 | priv->power_data.debug_sleep_level_override = value; | 815 | priv->power_data.debug_sleep_level_override = value; |
811 | 816 | ||
812 | iwl_power_update_mode(priv, false); | 817 | iwl_power_update_mode(priv, true); |
813 | 818 | ||
814 | return count; | 819 | return count; |
815 | } | 820 | } |
@@ -882,10 +887,14 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, | |||
882 | struct iwl_rx_queue *rxq = &priv->rxq; | 887 | struct iwl_rx_queue *rxq = &priv->rxq; |
883 | char *buf; | 888 | char *buf; |
884 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + | 889 | int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + |
885 | (IWL_MAX_NUM_QUEUES * 32 * 8) + 400; | 890 | (priv->cfg->num_of_queues * 32 * 8) + 400; |
886 | const u8 *ptr; | 891 | const u8 *ptr; |
887 | ssize_t ret; | 892 | ssize_t ret; |
888 | 893 | ||
894 | if (!priv->txq) { | ||
895 | IWL_ERR(priv, "txq not ready\n"); | ||
896 | return -EAGAIN; | ||
897 | } | ||
889 | buf = kzalloc(bufsz, GFP_KERNEL); | 898 | buf = kzalloc(bufsz, GFP_KERNEL); |
890 | if (!buf) { | 899 | if (!buf) { |
891 | IWL_ERR(priv, "Can not allocate buffer\n"); | 900 | IWL_ERR(priv, "Can not allocate buffer\n"); |
@@ -977,8 +986,12 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
977 | int pos = 0; | 986 | int pos = 0; |
978 | int cnt; | 987 | int cnt; |
979 | int ret; | 988 | int ret; |
980 | const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES; | 989 | const size_t bufsz = sizeof(char) * 60 * priv->cfg->num_of_queues; |
981 | 990 | ||
991 | if (!priv->txq) { | ||
992 | IWL_ERR(priv, "txq not ready\n"); | ||
993 | return -EAGAIN; | ||
994 | } | ||
982 | buf = kzalloc(bufsz, GFP_KERNEL); | 995 | buf = kzalloc(bufsz, GFP_KERNEL); |
983 | if (!buf) | 996 | if (!buf) |
984 | return -ENOMEM; | 997 | return -ENOMEM; |
@@ -1069,10 +1082,10 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1069 | sizeof(struct statistics_rx_non_phy) * 20 + | 1082 | sizeof(struct statistics_rx_non_phy) * 20 + |
1070 | sizeof(struct statistics_rx_ht_phy) * 20 + 400; | 1083 | sizeof(struct statistics_rx_ht_phy) * 20 + 400; |
1071 | ssize_t ret; | 1084 | ssize_t ret; |
1072 | struct statistics_rx_phy *ofdm; | 1085 | struct statistics_rx_phy *ofdm, *accum_ofdm; |
1073 | struct statistics_rx_phy *cck; | 1086 | struct statistics_rx_phy *cck, *accum_cck; |
1074 | struct statistics_rx_non_phy *general; | 1087 | struct statistics_rx_non_phy *general, *accum_general; |
1075 | struct statistics_rx_ht_phy *ht; | 1088 | struct statistics_rx_ht_phy *ht, *accum_ht; |
1076 | 1089 | ||
1077 | if (!iwl_is_alive(priv)) | 1090 | if (!iwl_is_alive(priv)) |
1078 | return -EAGAIN; | 1091 | return -EAGAIN; |
@@ -1101,155 +1114,268 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1101 | cck = &priv->statistics.rx.cck; | 1114 | cck = &priv->statistics.rx.cck; |
1102 | general = &priv->statistics.rx.general; | 1115 | general = &priv->statistics.rx.general; |
1103 | ht = &priv->statistics.rx.ofdm_ht; | 1116 | ht = &priv->statistics.rx.ofdm_ht; |
1117 | accum_ofdm = &priv->accum_statistics.rx.ofdm; | ||
1118 | accum_cck = &priv->accum_statistics.rx.cck; | ||
1119 | accum_general = &priv->accum_statistics.rx.general; | ||
1120 | accum_ht = &priv->accum_statistics.rx.ofdm_ht; | ||
1104 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1121 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1105 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); | 1122 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); |
1106 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", | 1123 | pos += scnprintf(buf + pos, bufsz - pos, |
1107 | le32_to_cpu(ofdm->ina_cnt)); | 1124 | "\t\t\tcurrent\t\t\taccumulative\n"); |
1108 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", | 1125 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", |
1109 | le32_to_cpu(ofdm->fina_cnt)); | 1126 | le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt); |
1110 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1127 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", |
1111 | le32_to_cpu(ofdm->plcp_err)); | 1128 | le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt); |
1112 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1129 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", |
1113 | le32_to_cpu(ofdm->crc32_err)); | 1130 | le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err); |
1114 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1131 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", |
1115 | le32_to_cpu(ofdm->overrun_err)); | 1132 | le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err); |
1116 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1133 | pos += scnprintf(buf + pos, bufsz - pos, |
1117 | le32_to_cpu(ofdm->early_overrun_err)); | 1134 | "overrun_err:\t\t%u\t\t\t%u\n", |
1118 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1135 | le32_to_cpu(ofdm->overrun_err), |
1119 | le32_to_cpu(ofdm->crc32_good)); | 1136 | accum_ofdm->overrun_err); |
1120 | pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", | 1137 | pos += scnprintf(buf + pos, bufsz - pos, |
1121 | le32_to_cpu(ofdm->false_alarm_cnt)); | 1138 | "early_overrun_err:\t%u\t\t\t%u\n", |
1122 | pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", | 1139 | le32_to_cpu(ofdm->early_overrun_err), |
1123 | le32_to_cpu(ofdm->fina_sync_err_cnt)); | 1140 | accum_ofdm->early_overrun_err); |
1124 | pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", | 1141 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", |
1125 | le32_to_cpu(ofdm->sfd_timeout)); | 1142 | le32_to_cpu(ofdm->crc32_good), |
1126 | pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", | 1143 | accum_ofdm->crc32_good); |
1127 | le32_to_cpu(ofdm->fina_timeout)); | 1144 | pos += scnprintf(buf + pos, bufsz - pos, |
1128 | pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", | 1145 | "false_alarm_cnt:\t%u\t\t\t%u\n", |
1129 | le32_to_cpu(ofdm->unresponded_rts)); | 1146 | le32_to_cpu(ofdm->false_alarm_cnt), |
1130 | pos += scnprintf(buf + pos, bufsz - pos, | 1147 | accum_ofdm->false_alarm_cnt); |
1131 | "rxe_frame_limit_overrun: %u\n", | 1148 | pos += scnprintf(buf + pos, bufsz - pos, |
1132 | le32_to_cpu(ofdm->rxe_frame_limit_overrun)); | 1149 | "fina_sync_err_cnt:\t%u\t\t\t%u\n", |
1133 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", | 1150 | le32_to_cpu(ofdm->fina_sync_err_cnt), |
1134 | le32_to_cpu(ofdm->sent_ack_cnt)); | 1151 | accum_ofdm->fina_sync_err_cnt); |
1135 | pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", | 1152 | pos += scnprintf(buf + pos, bufsz - pos, |
1136 | le32_to_cpu(ofdm->sent_cts_cnt)); | 1153 | "sfd_timeout:\t\t%u\t\t\t%u\n", |
1137 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", | 1154 | le32_to_cpu(ofdm->sfd_timeout), |
1138 | le32_to_cpu(ofdm->sent_ba_rsp_cnt)); | 1155 | accum_ofdm->sfd_timeout); |
1139 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", | 1156 | pos += scnprintf(buf + pos, bufsz - pos, |
1140 | le32_to_cpu(ofdm->dsp_self_kill)); | 1157 | "fina_timeout:\t\t%u\t\t\t%u\n", |
1141 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1158 | le32_to_cpu(ofdm->fina_timeout), |
1142 | le32_to_cpu(ofdm->mh_format_err)); | 1159 | accum_ofdm->fina_timeout); |
1143 | pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", | 1160 | pos += scnprintf(buf + pos, bufsz - pos, |
1144 | le32_to_cpu(ofdm->re_acq_main_rssi_sum)); | 1161 | "unresponded_rts:\t%u\t\t\t%u\n", |
1162 | le32_to_cpu(ofdm->unresponded_rts), | ||
1163 | accum_ofdm->unresponded_rts); | ||
1164 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1165 | "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", | ||
1166 | le32_to_cpu(ofdm->rxe_frame_limit_overrun), | ||
1167 | accum_ofdm->rxe_frame_limit_overrun); | ||
1168 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1169 | "sent_ack_cnt:\t\t%u\t\t\t%u\n", | ||
1170 | le32_to_cpu(ofdm->sent_ack_cnt), | ||
1171 | accum_ofdm->sent_ack_cnt); | ||
1172 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1173 | "sent_cts_cnt:\t\t%u\t\t\t%u\n", | ||
1174 | le32_to_cpu(ofdm->sent_cts_cnt), | ||
1175 | accum_ofdm->sent_cts_cnt); | ||
1176 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1177 | "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", | ||
1178 | le32_to_cpu(ofdm->sent_ba_rsp_cnt), | ||
1179 | accum_ofdm->sent_ba_rsp_cnt); | ||
1180 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1181 | "dsp_self_kill:\t\t%u\t\t\t%u\n", | ||
1182 | le32_to_cpu(ofdm->dsp_self_kill), | ||
1183 | accum_ofdm->dsp_self_kill); | ||
1184 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1185 | "mh_format_err:\t\t%u\t\t\t%u\n", | ||
1186 | le32_to_cpu(ofdm->mh_format_err), | ||
1187 | accum_ofdm->mh_format_err); | ||
1188 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1189 | "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", | ||
1190 | le32_to_cpu(ofdm->re_acq_main_rssi_sum), | ||
1191 | accum_ofdm->re_acq_main_rssi_sum); | ||
1145 | 1192 | ||
1146 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); | 1193 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); |
1147 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", | 1194 | pos += scnprintf(buf + pos, bufsz - pos, |
1148 | le32_to_cpu(cck->ina_cnt)); | 1195 | "\t\t\tcurrent\t\t\taccumulative\n"); |
1149 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", | 1196 | pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n", |
1150 | le32_to_cpu(cck->fina_cnt)); | 1197 | le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt); |
1151 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1198 | pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n", |
1152 | le32_to_cpu(cck->plcp_err)); | 1199 | le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt); |
1153 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1200 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", |
1154 | le32_to_cpu(cck->crc32_err)); | 1201 | le32_to_cpu(cck->plcp_err), accum_cck->plcp_err); |
1155 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1202 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", |
1156 | le32_to_cpu(cck->overrun_err)); | 1203 | le32_to_cpu(cck->crc32_err), accum_cck->crc32_err); |
1157 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1204 | pos += scnprintf(buf + pos, bufsz - pos, |
1158 | le32_to_cpu(cck->early_overrun_err)); | 1205 | "overrun_err:\t\t%u\t\t\t%u\n", |
1159 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1206 | le32_to_cpu(cck->overrun_err), |
1160 | le32_to_cpu(cck->crc32_good)); | 1207 | accum_cck->overrun_err); |
1161 | pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", | 1208 | pos += scnprintf(buf + pos, bufsz - pos, |
1162 | le32_to_cpu(cck->false_alarm_cnt)); | 1209 | "early_overrun_err:\t%u\t\t\t%u\n", |
1163 | pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", | 1210 | le32_to_cpu(cck->early_overrun_err), |
1164 | le32_to_cpu(cck->fina_sync_err_cnt)); | 1211 | accum_cck->early_overrun_err); |
1165 | pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", | 1212 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", |
1166 | le32_to_cpu(cck->sfd_timeout)); | 1213 | le32_to_cpu(cck->crc32_good), accum_cck->crc32_good); |
1167 | pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", | 1214 | pos += scnprintf(buf + pos, bufsz - pos, |
1168 | le32_to_cpu(cck->fina_timeout)); | 1215 | "false_alarm_cnt:\t%u\t\t\t%u\n", |
1169 | pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", | 1216 | le32_to_cpu(cck->false_alarm_cnt), |
1170 | le32_to_cpu(cck->unresponded_rts)); | 1217 | accum_cck->false_alarm_cnt); |
1171 | pos += scnprintf(buf + pos, bufsz - pos, | 1218 | pos += scnprintf(buf + pos, bufsz - pos, |
1172 | "rxe_frame_limit_overrun: %u\n", | 1219 | "fina_sync_err_cnt:\t%u\t\t\t%u\n", |
1173 | le32_to_cpu(cck->rxe_frame_limit_overrun)); | 1220 | le32_to_cpu(cck->fina_sync_err_cnt), |
1174 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", | 1221 | accum_cck->fina_sync_err_cnt); |
1175 | le32_to_cpu(cck->sent_ack_cnt)); | 1222 | pos += scnprintf(buf + pos, bufsz - pos, |
1176 | pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", | 1223 | "sfd_timeout:\t\t%u\t\t\t%u\n", |
1177 | le32_to_cpu(cck->sent_cts_cnt)); | 1224 | le32_to_cpu(cck->sfd_timeout), |
1178 | pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", | 1225 | accum_cck->sfd_timeout); |
1179 | le32_to_cpu(cck->sent_ba_rsp_cnt)); | 1226 | pos += scnprintf(buf + pos, bufsz - pos, |
1180 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", | 1227 | "fina_timeout:\t\t%u\t\t\t%u\n", |
1181 | le32_to_cpu(cck->dsp_self_kill)); | 1228 | le32_to_cpu(cck->fina_timeout), |
1182 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1229 | accum_cck->fina_timeout); |
1183 | le32_to_cpu(cck->mh_format_err)); | 1230 | pos += scnprintf(buf + pos, bufsz - pos, |
1184 | pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", | 1231 | "unresponded_rts:\t%u\t\t\t%u\n", |
1185 | le32_to_cpu(cck->re_acq_main_rssi_sum)); | 1232 | le32_to_cpu(cck->unresponded_rts), |
1233 | accum_cck->unresponded_rts); | ||
1234 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1235 | "rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n", | ||
1236 | le32_to_cpu(cck->rxe_frame_limit_overrun), | ||
1237 | accum_cck->rxe_frame_limit_overrun); | ||
1238 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1239 | "sent_ack_cnt:\t\t%u\t\t\t%u\n", | ||
1240 | le32_to_cpu(cck->sent_ack_cnt), | ||
1241 | accum_cck->sent_ack_cnt); | ||
1242 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1243 | "sent_cts_cnt:\t\t%u\t\t\t%u\n", | ||
1244 | le32_to_cpu(cck->sent_cts_cnt), | ||
1245 | accum_cck->sent_cts_cnt); | ||
1246 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1247 | "sent_ba_rsp_cnt:\t%u\t\t\t%u\n", | ||
1248 | le32_to_cpu(cck->sent_ba_rsp_cnt), | ||
1249 | accum_cck->sent_ba_rsp_cnt); | ||
1250 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1251 | "dsp_self_kill:\t\t%u\t\t\t%u\n", | ||
1252 | le32_to_cpu(cck->dsp_self_kill), | ||
1253 | accum_cck->dsp_self_kill); | ||
1254 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1255 | "mh_format_err:\t\t%u\t\t\t%u\n", | ||
1256 | le32_to_cpu(cck->mh_format_err), | ||
1257 | accum_cck->mh_format_err); | ||
1258 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1259 | "re_acq_main_rssi_sum:\t%u\t\t\t%u\n", | ||
1260 | le32_to_cpu(cck->re_acq_main_rssi_sum), | ||
1261 | accum_cck->re_acq_main_rssi_sum); | ||
1186 | 1262 | ||
1187 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); | 1263 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); |
1188 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n", | 1264 | pos += scnprintf(buf + pos, bufsz - pos, |
1189 | le32_to_cpu(general->bogus_cts)); | 1265 | "\t\t\tcurrent\t\t\taccumulative\n"); |
1190 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n", | 1266 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n", |
1191 | le32_to_cpu(general->bogus_ack)); | 1267 | le32_to_cpu(general->bogus_cts), |
1192 | pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n", | 1268 | accum_general->bogus_cts); |
1193 | le32_to_cpu(general->non_bssid_frames)); | 1269 | pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n", |
1194 | pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n", | 1270 | le32_to_cpu(general->bogus_ack), |
1195 | le32_to_cpu(general->filtered_frames)); | 1271 | accum_general->bogus_ack); |
1196 | pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n", | 1272 | pos += scnprintf(buf + pos, bufsz - pos, |
1197 | le32_to_cpu(general->non_channel_beacons)); | 1273 | "non_bssid_frames:\t%u\t\t\t%u\n", |
1198 | pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n", | 1274 | le32_to_cpu(general->non_bssid_frames), |
1199 | le32_to_cpu(general->channel_beacons)); | 1275 | accum_general->non_bssid_frames); |
1200 | pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n", | 1276 | pos += scnprintf(buf + pos, bufsz - pos, |
1201 | le32_to_cpu(general->num_missed_bcon)); | 1277 | "filtered_frames:\t%u\t\t\t%u\n", |
1202 | pos += scnprintf(buf + pos, bufsz - pos, | 1278 | le32_to_cpu(general->filtered_frames), |
1203 | "adc_rx_saturation_time: %u\n", | 1279 | accum_general->filtered_frames); |
1204 | le32_to_cpu(general->adc_rx_saturation_time)); | 1280 | pos += scnprintf(buf + pos, bufsz - pos, |
1205 | pos += scnprintf(buf + pos, bufsz - pos, | 1281 | "non_channel_beacons:\t%u\t\t\t%u\n", |
1206 | "ina_detection_search_time: %u\n", | 1282 | le32_to_cpu(general->non_channel_beacons), |
1207 | le32_to_cpu(general->ina_detection_search_time)); | 1283 | accum_general->non_channel_beacons); |
1208 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n", | 1284 | pos += scnprintf(buf + pos, bufsz - pos, |
1209 | le32_to_cpu(general->beacon_silence_rssi_a)); | 1285 | "channel_beacons:\t%u\t\t\t%u\n", |
1210 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n", | 1286 | le32_to_cpu(general->channel_beacons), |
1211 | le32_to_cpu(general->beacon_silence_rssi_b)); | 1287 | accum_general->channel_beacons); |
1212 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n", | 1288 | pos += scnprintf(buf + pos, bufsz - pos, |
1213 | le32_to_cpu(general->beacon_silence_rssi_c)); | 1289 | "num_missed_bcon:\t%u\t\t\t%u\n", |
1214 | pos += scnprintf(buf + pos, bufsz - pos, | 1290 | le32_to_cpu(general->num_missed_bcon), |
1215 | "interference_data_flag: %u\n", | 1291 | accum_general->num_missed_bcon); |
1216 | le32_to_cpu(general->interference_data_flag)); | 1292 | pos += scnprintf(buf + pos, bufsz - pos, |
1217 | pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n", | 1293 | "adc_rx_saturation_time:\t%u\t\t\t%u\n", |
1218 | le32_to_cpu(general->channel_load)); | 1294 | le32_to_cpu(general->adc_rx_saturation_time), |
1219 | pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n", | 1295 | accum_general->adc_rx_saturation_time); |
1220 | le32_to_cpu(general->dsp_false_alarms)); | 1296 | pos += scnprintf(buf + pos, bufsz - pos, |
1221 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n", | 1297 | "ina_detect_search_tm:\t%u\t\t\t%u\n", |
1222 | le32_to_cpu(general->beacon_rssi_a)); | 1298 | le32_to_cpu(general->ina_detection_search_time), |
1223 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n", | 1299 | accum_general->ina_detection_search_time); |
1224 | le32_to_cpu(general->beacon_rssi_b)); | 1300 | pos += scnprintf(buf + pos, bufsz - pos, |
1225 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n", | 1301 | "beacon_silence_rssi_a:\t%u\t\t\t%u\n", |
1226 | le32_to_cpu(general->beacon_rssi_c)); | 1302 | le32_to_cpu(general->beacon_silence_rssi_a), |
1227 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n", | 1303 | accum_general->beacon_silence_rssi_a); |
1228 | le32_to_cpu(general->beacon_energy_a)); | 1304 | pos += scnprintf(buf + pos, bufsz - pos, |
1229 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n", | 1305 | "beacon_silence_rssi_b:\t%u\t\t\t%u\n", |
1230 | le32_to_cpu(general->beacon_energy_b)); | 1306 | le32_to_cpu(general->beacon_silence_rssi_b), |
1231 | pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n", | 1307 | accum_general->beacon_silence_rssi_b); |
1232 | le32_to_cpu(general->beacon_energy_c)); | 1308 | pos += scnprintf(buf + pos, bufsz - pos, |
1309 | "beacon_silence_rssi_c:\t%u\t\t\t%u\n", | ||
1310 | le32_to_cpu(general->beacon_silence_rssi_c), | ||
1311 | accum_general->beacon_silence_rssi_c); | ||
1312 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1313 | "interference_data_flag:\t%u\t\t\t%u\n", | ||
1314 | le32_to_cpu(general->interference_data_flag), | ||
1315 | accum_general->interference_data_flag); | ||
1316 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1317 | "channel_load:\t\t%u\t\t\t%u\n", | ||
1318 | le32_to_cpu(general->channel_load), | ||
1319 | accum_general->channel_load); | ||
1320 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1321 | "dsp_false_alarms:\t%u\t\t\t%u\n", | ||
1322 | le32_to_cpu(general->dsp_false_alarms), | ||
1323 | accum_general->dsp_false_alarms); | ||
1324 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1325 | "beacon_rssi_a:\t\t%u\t\t\t%u\n", | ||
1326 | le32_to_cpu(general->beacon_rssi_a), | ||
1327 | accum_general->beacon_rssi_a); | ||
1328 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1329 | "beacon_rssi_b:\t\t%u\t\t\t%u\n", | ||
1330 | le32_to_cpu(general->beacon_rssi_b), | ||
1331 | accum_general->beacon_rssi_b); | ||
1332 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1333 | "beacon_rssi_c:\t\t%u\t\t\t%u\n", | ||
1334 | le32_to_cpu(general->beacon_rssi_c), | ||
1335 | accum_general->beacon_rssi_c); | ||
1336 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1337 | "beacon_energy_a:\t%u\t\t\t%u\n", | ||
1338 | le32_to_cpu(general->beacon_energy_a), | ||
1339 | accum_general->beacon_energy_a); | ||
1340 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1341 | "beacon_energy_b:\t%u\t\t\t%u\n", | ||
1342 | le32_to_cpu(general->beacon_energy_b), | ||
1343 | accum_general->beacon_energy_b); | ||
1344 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1345 | "beacon_energy_c:\t%u\t\t\t%u\n", | ||
1346 | le32_to_cpu(general->beacon_energy_c), | ||
1347 | accum_general->beacon_energy_c); | ||
1233 | 1348 | ||
1234 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); | 1349 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); |
1235 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", | 1350 | pos += scnprintf(buf + pos, bufsz - pos, |
1236 | le32_to_cpu(ht->plcp_err)); | 1351 | "\t\t\tcurrent\t\t\taccumulative\n"); |
1237 | pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", | 1352 | pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n", |
1238 | le32_to_cpu(ht->overrun_err)); | 1353 | le32_to_cpu(ht->plcp_err), accum_ht->plcp_err); |
1239 | pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", | 1354 | pos += scnprintf(buf + pos, bufsz - pos, |
1240 | le32_to_cpu(ht->early_overrun_err)); | 1355 | "overrun_err:\t\t%u\t\t\t%u\n", |
1241 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", | 1356 | le32_to_cpu(ht->overrun_err), accum_ht->overrun_err); |
1242 | le32_to_cpu(ht->crc32_good)); | 1357 | pos += scnprintf(buf + pos, bufsz - pos, |
1243 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", | 1358 | "early_overrun_err:\t%u\t\t\t%u\n", |
1244 | le32_to_cpu(ht->crc32_err)); | 1359 | le32_to_cpu(ht->early_overrun_err), |
1245 | pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", | 1360 | accum_ht->early_overrun_err); |
1246 | le32_to_cpu(ht->mh_format_err)); | 1361 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n", |
1247 | pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n", | 1362 | le32_to_cpu(ht->crc32_good), accum_ht->crc32_good); |
1248 | le32_to_cpu(ht->agg_crc32_good)); | 1363 | pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n", |
1249 | pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n", | 1364 | le32_to_cpu(ht->crc32_err), accum_ht->crc32_err); |
1250 | le32_to_cpu(ht->agg_mpdu_cnt)); | 1365 | pos += scnprintf(buf + pos, bufsz - pos, |
1251 | pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n", | 1366 | "mh_format_err:\t\t%u\t\t\t%u\n", |
1252 | le32_to_cpu(ht->agg_cnt)); | 1367 | le32_to_cpu(ht->mh_format_err), |
1368 | accum_ht->mh_format_err); | ||
1369 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1370 | "agg_crc32_good:\t\t%u\t\t\t%u\n", | ||
1371 | le32_to_cpu(ht->agg_crc32_good), | ||
1372 | accum_ht->agg_crc32_good); | ||
1373 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1374 | "agg_mpdu_cnt:\t\t%u\t\t\t%u\n", | ||
1375 | le32_to_cpu(ht->agg_mpdu_cnt), | ||
1376 | accum_ht->agg_mpdu_cnt); | ||
1377 | pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n", | ||
1378 | le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt); | ||
1253 | 1379 | ||
1254 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1380 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1255 | kfree(buf); | 1381 | kfree(buf); |
@@ -1265,7 +1391,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1265 | char *buf; | 1391 | char *buf; |
1266 | int bufsz = (sizeof(struct statistics_tx) * 24) + 250; | 1392 | int bufsz = (sizeof(struct statistics_tx) * 24) + 250; |
1267 | ssize_t ret; | 1393 | ssize_t ret; |
1268 | struct statistics_tx *tx; | 1394 | struct statistics_tx *tx, *accum_tx; |
1269 | 1395 | ||
1270 | if (!iwl_is_alive(priv)) | 1396 | if (!iwl_is_alive(priv)) |
1271 | return -EAGAIN; | 1397 | return -EAGAIN; |
@@ -1291,62 +1417,107 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1291 | * might not reflect the current uCode activity | 1417 | * might not reflect the current uCode activity |
1292 | */ | 1418 | */ |
1293 | tx = &priv->statistics.tx; | 1419 | tx = &priv->statistics.tx; |
1420 | accum_tx = &priv->accum_statistics.tx; | ||
1294 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1421 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1295 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); | 1422 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); |
1296 | pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n", | 1423 | pos += scnprintf(buf + pos, bufsz - pos, |
1297 | le32_to_cpu(tx->preamble_cnt)); | 1424 | "\t\t\tcurrent\t\t\taccumulative\n"); |
1298 | pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n", | 1425 | pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n", |
1299 | le32_to_cpu(tx->rx_detected_cnt)); | 1426 | le32_to_cpu(tx->preamble_cnt), |
1300 | pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n", | 1427 | accum_tx->preamble_cnt); |
1301 | le32_to_cpu(tx->bt_prio_defer_cnt)); | 1428 | pos += scnprintf(buf + pos, bufsz - pos, |
1302 | pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n", | 1429 | "rx_detected_cnt:\t\t%u\t\t\t%u\n", |
1303 | le32_to_cpu(tx->bt_prio_kill_cnt)); | 1430 | le32_to_cpu(tx->rx_detected_cnt), |
1304 | pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n", | 1431 | accum_tx->rx_detected_cnt); |
1305 | le32_to_cpu(tx->few_bytes_cnt)); | 1432 | pos += scnprintf(buf + pos, bufsz - pos, |
1306 | pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n", | 1433 | "bt_prio_defer_cnt:\t\t%u\t\t\t%u\n", |
1307 | le32_to_cpu(tx->cts_timeout)); | 1434 | le32_to_cpu(tx->bt_prio_defer_cnt), |
1308 | pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n", | 1435 | accum_tx->bt_prio_defer_cnt); |
1309 | le32_to_cpu(tx->ack_timeout)); | 1436 | pos += scnprintf(buf + pos, bufsz - pos, |
1310 | pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n", | 1437 | "bt_prio_kill_cnt:\t\t%u\t\t\t%u\n", |
1311 | le32_to_cpu(tx->expected_ack_cnt)); | 1438 | le32_to_cpu(tx->bt_prio_kill_cnt), |
1312 | pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n", | 1439 | accum_tx->bt_prio_kill_cnt); |
1313 | le32_to_cpu(tx->actual_ack_cnt)); | 1440 | pos += scnprintf(buf + pos, bufsz - pos, |
1314 | pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n", | 1441 | "few_bytes_cnt:\t\t\t%u\t\t\t%u\n", |
1315 | le32_to_cpu(tx->dump_msdu_cnt)); | 1442 | le32_to_cpu(tx->few_bytes_cnt), |
1316 | pos += scnprintf(buf + pos, bufsz - pos, | 1443 | accum_tx->few_bytes_cnt); |
1317 | "burst_abort_next_frame_mismatch_cnt: %u\n", | 1444 | pos += scnprintf(buf + pos, bufsz - pos, |
1318 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt)); | 1445 | "cts_timeout:\t\t\t%u\t\t\t%u\n", |
1319 | pos += scnprintf(buf + pos, bufsz - pos, | 1446 | le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout); |
1320 | "burst_abort_missing_next_frame_cnt: %u\n", | 1447 | pos += scnprintf(buf + pos, bufsz - pos, |
1321 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt)); | 1448 | "ack_timeout:\t\t\t%u\t\t\t%u\n", |
1322 | pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n", | 1449 | le32_to_cpu(tx->ack_timeout), |
1323 | le32_to_cpu(tx->cts_timeout_collision)); | 1450 | accum_tx->ack_timeout); |
1324 | pos += scnprintf(buf + pos, bufsz - pos, | 1451 | pos += scnprintf(buf + pos, bufsz - pos, |
1325 | "ack_or_ba_timeout_collision: %u\n", | 1452 | "expected_ack_cnt:\t\t%u\t\t\t%u\n", |
1326 | le32_to_cpu(tx->ack_or_ba_timeout_collision)); | 1453 | le32_to_cpu(tx->expected_ack_cnt), |
1327 | pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n", | 1454 | accum_tx->expected_ack_cnt); |
1328 | le32_to_cpu(tx->agg.ba_timeout)); | 1455 | pos += scnprintf(buf + pos, bufsz - pos, |
1329 | pos += scnprintf(buf + pos, bufsz - pos, | 1456 | "actual_ack_cnt:\t\t\t%u\t\t\t%u\n", |
1330 | "agg ba_reschedule_frames: %u\n", | 1457 | le32_to_cpu(tx->actual_ack_cnt), |
1331 | le32_to_cpu(tx->agg.ba_reschedule_frames)); | 1458 | accum_tx->actual_ack_cnt); |
1332 | pos += scnprintf(buf + pos, bufsz - pos, | 1459 | pos += scnprintf(buf + pos, bufsz - pos, |
1333 | "agg scd_query_agg_frame_cnt: %u\n", | 1460 | "dump_msdu_cnt:\t\t\t%u\t\t\t%u\n", |
1334 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt)); | 1461 | le32_to_cpu(tx->dump_msdu_cnt), |
1335 | pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n", | 1462 | accum_tx->dump_msdu_cnt); |
1336 | le32_to_cpu(tx->agg.scd_query_no_agg)); | 1463 | pos += scnprintf(buf + pos, bufsz - pos, |
1337 | pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n", | 1464 | "abort_nxt_frame_mismatch:" |
1338 | le32_to_cpu(tx->agg.scd_query_agg)); | 1465 | "\t%u\t\t\t%u\n", |
1339 | pos += scnprintf(buf + pos, bufsz - pos, | 1466 | le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), |
1340 | "agg scd_query_mismatch: %u\n", | 1467 | accum_tx->burst_abort_next_frame_mismatch_cnt); |
1341 | le32_to_cpu(tx->agg.scd_query_mismatch)); | 1468 | pos += scnprintf(buf + pos, bufsz - pos, |
1342 | pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n", | 1469 | "abort_missing_nxt_frame:" |
1343 | le32_to_cpu(tx->agg.frame_not_ready)); | 1470 | "\t%u\t\t\t%u\n", |
1344 | pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n", | 1471 | le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), |
1345 | le32_to_cpu(tx->agg.underrun)); | 1472 | accum_tx->burst_abort_missing_next_frame_cnt); |
1346 | pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n", | 1473 | pos += scnprintf(buf + pos, bufsz - pos, |
1347 | le32_to_cpu(tx->agg.bt_prio_kill)); | 1474 | "cts_timeout_collision:\t\t%u\t\t\t%u\n", |
1348 | pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n", | 1475 | le32_to_cpu(tx->cts_timeout_collision), |
1349 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt)); | 1476 | accum_tx->cts_timeout_collision); |
1477 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1478 | "ack_ba_timeout_collision:\t%u\t\t\t%u\n", | ||
1479 | le32_to_cpu(tx->ack_or_ba_timeout_collision), | ||
1480 | accum_tx->ack_or_ba_timeout_collision); | ||
1481 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1482 | "agg ba_timeout:\t\t\t%u\t\t\t%u\n", | ||
1483 | le32_to_cpu(tx->agg.ba_timeout), | ||
1484 | accum_tx->agg.ba_timeout); | ||
1485 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1486 | "agg ba_resched_frames:\t\t%u\t\t\t%u\n", | ||
1487 | le32_to_cpu(tx->agg.ba_reschedule_frames), | ||
1488 | accum_tx->agg.ba_reschedule_frames); | ||
1489 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1490 | "agg scd_query_agg_frame:\t%u\t\t\t%u\n", | ||
1491 | le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), | ||
1492 | accum_tx->agg.scd_query_agg_frame_cnt); | ||
1493 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1494 | "agg scd_query_no_agg:\t\t%u\t\t\t%u\n", | ||
1495 | le32_to_cpu(tx->agg.scd_query_no_agg), | ||
1496 | accum_tx->agg.scd_query_no_agg); | ||
1497 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1498 | "agg scd_query_agg:\t\t%u\t\t\t%u\n", | ||
1499 | le32_to_cpu(tx->agg.scd_query_agg), | ||
1500 | accum_tx->agg.scd_query_agg); | ||
1501 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1502 | "agg scd_query_mismatch:\t\t%u\t\t\t%u\n", | ||
1503 | le32_to_cpu(tx->agg.scd_query_mismatch), | ||
1504 | accum_tx->agg.scd_query_mismatch); | ||
1505 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1506 | "agg frame_not_ready:\t\t%u\t\t\t%u\n", | ||
1507 | le32_to_cpu(tx->agg.frame_not_ready), | ||
1508 | accum_tx->agg.frame_not_ready); | ||
1509 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1510 | "agg underrun:\t\t\t%u\t\t\t%u\n", | ||
1511 | le32_to_cpu(tx->agg.underrun), | ||
1512 | accum_tx->agg.underrun); | ||
1513 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1514 | "agg bt_prio_kill:\t\t%u\t\t\t%u\n", | ||
1515 | le32_to_cpu(tx->agg.bt_prio_kill), | ||
1516 | accum_tx->agg.bt_prio_kill); | ||
1517 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1518 | "agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n", | ||
1519 | le32_to_cpu(tx->agg.rx_ba_rsp_cnt), | ||
1520 | accum_tx->agg.rx_ba_rsp_cnt); | ||
1350 | 1521 | ||
1351 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1522 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1352 | kfree(buf); | 1523 | kfree(buf); |
@@ -1362,9 +1533,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1362 | char *buf; | 1533 | char *buf; |
1363 | int bufsz = sizeof(struct statistics_general) * 4 + 250; | 1534 | int bufsz = sizeof(struct statistics_general) * 4 + 250; |
1364 | ssize_t ret; | 1535 | ssize_t ret; |
1365 | struct statistics_general *general; | 1536 | struct statistics_general *general, *accum_general; |
1366 | struct statistics_dbg *dbg; | 1537 | struct statistics_dbg *dbg, *accum_dbg; |
1367 | struct statistics_div *div; | 1538 | struct statistics_div *div, *accum_div; |
1368 | 1539 | ||
1369 | if (!iwl_is_alive(priv)) | 1540 | if (!iwl_is_alive(priv)) |
1370 | return -EAGAIN; | 1541 | return -EAGAIN; |
@@ -1392,34 +1563,53 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1392 | general = &priv->statistics.general; | 1563 | general = &priv->statistics.general; |
1393 | dbg = &priv->statistics.general.dbg; | 1564 | dbg = &priv->statistics.general.dbg; |
1394 | div = &priv->statistics.general.div; | 1565 | div = &priv->statistics.general.div; |
1566 | accum_general = &priv->accum_statistics.general; | ||
1567 | accum_dbg = &priv->accum_statistics.general.dbg; | ||
1568 | accum_div = &priv->accum_statistics.general.div; | ||
1395 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); | 1569 | pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); |
1396 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); | 1570 | pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); |
1397 | pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n", | 1571 | pos += scnprintf(buf + pos, bufsz - pos, |
1572 | "\t\t\tcurrent\t\t\taccumulative\n"); | ||
1573 | pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n", | ||
1398 | le32_to_cpu(general->temperature)); | 1574 | le32_to_cpu(general->temperature)); |
1399 | pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n", | 1575 | pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n", |
1400 | le32_to_cpu(general->temperature_m)); | 1576 | le32_to_cpu(general->temperature_m)); |
1401 | pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n", | 1577 | pos += scnprintf(buf + pos, bufsz - pos, |
1402 | le32_to_cpu(dbg->burst_check)); | 1578 | "burst_check:\t\t\t%u\t\t\t%u\n", |
1403 | pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n", | 1579 | le32_to_cpu(dbg->burst_check), |
1404 | le32_to_cpu(dbg->burst_count)); | 1580 | accum_dbg->burst_check); |
1405 | pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n", | 1581 | pos += scnprintf(buf + pos, bufsz - pos, |
1406 | le32_to_cpu(general->sleep_time)); | 1582 | "burst_count:\t\t\t%u\t\t\t%u\n", |
1407 | pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n", | 1583 | le32_to_cpu(dbg->burst_count), |
1408 | le32_to_cpu(general->slots_out)); | 1584 | accum_dbg->burst_count); |
1409 | pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n", | 1585 | pos += scnprintf(buf + pos, bufsz - pos, |
1410 | le32_to_cpu(general->slots_idle)); | 1586 | "sleep_time:\t\t\t%u\t\t\t%u\n", |
1411 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n", | 1587 | le32_to_cpu(general->sleep_time), |
1588 | accum_general->sleep_time); | ||
1589 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1590 | "slots_out:\t\t\t%u\t\t\t%u\n", | ||
1591 | le32_to_cpu(general->slots_out), | ||
1592 | accum_general->slots_out); | ||
1593 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1594 | "slots_idle:\t\t\t%u\t\t\t%u\n", | ||
1595 | le32_to_cpu(general->slots_idle), | ||
1596 | accum_general->slots_idle); | ||
1597 | pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", | ||
1412 | le32_to_cpu(general->ttl_timestamp)); | 1598 | le32_to_cpu(general->ttl_timestamp)); |
1413 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n", | 1599 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n", |
1414 | le32_to_cpu(div->tx_on_a)); | 1600 | le32_to_cpu(div->tx_on_a), accum_div->tx_on_a); |
1415 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n", | 1601 | pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n", |
1416 | le32_to_cpu(div->tx_on_b)); | 1602 | le32_to_cpu(div->tx_on_b), accum_div->tx_on_b); |
1417 | pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n", | 1603 | pos += scnprintf(buf + pos, bufsz - pos, |
1418 | le32_to_cpu(div->exec_time)); | 1604 | "exec_time:\t\t\t%u\t\t\t%u\n", |
1419 | pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n", | 1605 | le32_to_cpu(div->exec_time), accum_div->exec_time); |
1420 | le32_to_cpu(div->probe_time)); | 1606 | pos += scnprintf(buf + pos, bufsz - pos, |
1421 | pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n", | 1607 | "probe_time:\t\t\t%u\t\t\t%u\n", |
1422 | le32_to_cpu(general->rx_enable_counter)); | 1608 | le32_to_cpu(div->probe_time), accum_div->probe_time); |
1609 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1610 | "rx_enable_counter:\t\t%u\t\t\t%u\n", | ||
1611 | le32_to_cpu(general->rx_enable_counter), | ||
1612 | accum_general->rx_enable_counter); | ||
1423 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1613 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1424 | kfree(buf); | 1614 | kfree(buf); |
1425 | return ret; | 1615 | return ret; |
@@ -1615,6 +1805,29 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | |||
1615 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1805 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1616 | } | 1806 | } |
1617 | 1807 | ||
1808 | static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | ||
1809 | char __user *user_buf, | ||
1810 | size_t count, loff_t *ppos) | ||
1811 | { | ||
1812 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | ||
1813 | char buf[60]; | ||
1814 | int pos = 0; | ||
1815 | const size_t bufsz = sizeof(buf); | ||
1816 | u32 pwrsave_status; | ||
1817 | |||
1818 | pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) & | ||
1819 | CSR_GP_REG_POWER_SAVE_STATUS_MSK; | ||
1820 | |||
1821 | pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: "); | ||
1822 | pos += scnprintf(buf + pos, bufsz - pos, "%s\n", | ||
1823 | (pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" : | ||
1824 | (pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" : | ||
1825 | (pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" : | ||
1826 | "error"); | ||
1827 | |||
1828 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1829 | } | ||
1830 | |||
1618 | DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); | 1831 | DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); |
1619 | DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); | 1832 | DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); |
1620 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 1833 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -1626,6 +1839,7 @@ DEBUGFS_READ_FILE_OPS(ucode_general_stats); | |||
1626 | DEBUGFS_READ_FILE_OPS(sensitivity); | 1839 | DEBUGFS_READ_FILE_OPS(sensitivity); |
1627 | DEBUGFS_READ_FILE_OPS(chain_noise); | 1840 | DEBUGFS_READ_FILE_OPS(chain_noise); |
1628 | DEBUGFS_READ_FILE_OPS(tx_power); | 1841 | DEBUGFS_READ_FILE_OPS(tx_power); |
1842 | DEBUGFS_READ_FILE_OPS(power_save_status); | ||
1629 | 1843 | ||
1630 | /* | 1844 | /* |
1631 | * Create the debugfs files and directories | 1845 | * Create the debugfs files and directories |
@@ -1673,6 +1887,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1673 | DEBUGFS_ADD_FILE(rx_queue, debug); | 1887 | DEBUGFS_ADD_FILE(rx_queue, debug); |
1674 | DEBUGFS_ADD_FILE(tx_queue, debug); | 1888 | DEBUGFS_ADD_FILE(tx_queue, debug); |
1675 | DEBUGFS_ADD_FILE(tx_power, debug); | 1889 | DEBUGFS_ADD_FILE(tx_power, debug); |
1890 | DEBUGFS_ADD_FILE(power_save_status, debug); | ||
1676 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 1891 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1677 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug); | 1892 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug); |
1678 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug); | 1893 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug); |
@@ -1725,6 +1940,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1725 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); | 1940 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); |
1726 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); | 1941 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); |
1727 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); | 1942 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); |
1943 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); | ||
1728 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 1944 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1729 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 1945 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
1730 | file_ucode_rx_stats); | 1946 | file_ucode_rx_stats); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 72946c144be7..e7ce67387662 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -85,8 +85,6 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | |||
85 | __le32 *tx_flags); | 85 | __le32 *tx_flags); |
86 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | 86 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, |
87 | struct iwl_rx_phy_res *rx_resp); | 87 | struct iwl_rx_phy_res *rx_resp); |
88 | extern int iwl5000_apm_init(struct iwl_priv *priv); | ||
89 | extern int iwl5000_apm_reset(struct iwl_priv *priv); | ||
90 | extern void iwl5000_nic_config(struct iwl_priv *priv); | 88 | extern void iwl5000_nic_config(struct iwl_priv *priv); |
91 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | 89 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); |
92 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | 90 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, |
@@ -147,12 +145,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv); | |||
147 | #define DEFAULT_LONG_RETRY_LIMIT 4U | 145 | #define DEFAULT_LONG_RETRY_LIMIT 4U |
148 | 146 | ||
149 | struct iwl_rx_mem_buffer { | 147 | struct iwl_rx_mem_buffer { |
150 | dma_addr_t real_dma_addr; | 148 | dma_addr_t page_dma; |
151 | dma_addr_t aligned_dma_addr; | 149 | struct page *page; |
152 | struct sk_buff *skb; | ||
153 | struct list_head list; | 150 | struct list_head list; |
154 | }; | 151 | }; |
155 | 152 | ||
153 | #define rxb_addr(r) page_address(r->page) | ||
154 | |||
156 | /* defined below */ | 155 | /* defined below */ |
157 | struct iwl_device_cmd; | 156 | struct iwl_device_cmd; |
158 | 157 | ||
@@ -168,7 +167,7 @@ struct iwl_cmd_meta { | |||
168 | */ | 167 | */ |
169 | void (*callback)(struct iwl_priv *priv, | 168 | void (*callback)(struct iwl_priv *priv, |
170 | struct iwl_device_cmd *cmd, | 169 | struct iwl_device_cmd *cmd, |
171 | struct sk_buff *skb); | 170 | struct iwl_rx_packet *pkt); |
172 | 171 | ||
173 | /* The CMD_SIZE_HUGE flag bit indicates that the command | 172 | /* The CMD_SIZE_HUGE flag bit indicates that the command |
174 | * structure is stored at the end of the shared queue memory. */ | 173 | * structure is stored at the end of the shared queue memory. */ |
@@ -324,6 +323,12 @@ struct iwl_channel_info { | |||
324 | * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ | 323 | * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ |
325 | #define IWL_MIN_NUM_QUEUES 10 | 324 | #define IWL_MIN_NUM_QUEUES 10 |
326 | 325 | ||
326 | /* | ||
327 | * uCode queue management definitions ... | ||
328 | * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00. | ||
329 | */ | ||
330 | #define IWL_CMD_QUEUE_NUM 4 | ||
331 | |||
327 | /* Power management (not Tx power) structures */ | 332 | /* Power management (not Tx power) structures */ |
328 | 333 | ||
329 | enum iwl_pwr_src { | 334 | enum iwl_pwr_src { |
@@ -359,7 +364,14 @@ enum { | |||
359 | CMD_WANT_SKB = (1 << 2), | 364 | CMD_WANT_SKB = (1 << 2), |
360 | }; | 365 | }; |
361 | 366 | ||
362 | #define IWL_CMD_MAX_PAYLOAD 320 | 367 | #define DEF_CMD_PAYLOAD_SIZE 320 |
368 | |||
369 | /* | ||
370 | * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header, | ||
371 | * SNAP header and alignment. It should also be big enough for 802.11 | ||
372 | * control frames. | ||
373 | */ | ||
374 | #define IWL_LINK_HDR_MAX 64 | ||
363 | 375 | ||
364 | /** | 376 | /** |
365 | * struct iwl_device_cmd | 377 | * struct iwl_device_cmd |
@@ -376,7 +388,8 @@ struct iwl_device_cmd { | |||
376 | u16 val16; | 388 | u16 val16; |
377 | u32 val32; | 389 | u32 val32; |
378 | struct iwl_tx_cmd tx; | 390 | struct iwl_tx_cmd tx; |
379 | u8 payload[IWL_CMD_MAX_PAYLOAD]; | 391 | struct iwl6000_channel_switch_cmd chswitch; |
392 | u8 payload[DEF_CMD_PAYLOAD_SIZE]; | ||
380 | } __attribute__ ((packed)) cmd; | 393 | } __attribute__ ((packed)) cmd; |
381 | } __attribute__ ((packed)); | 394 | } __attribute__ ((packed)); |
382 | 395 | ||
@@ -385,21 +398,15 @@ struct iwl_device_cmd { | |||
385 | 398 | ||
386 | struct iwl_host_cmd { | 399 | struct iwl_host_cmd { |
387 | const void *data; | 400 | const void *data; |
388 | struct sk_buff *reply_skb; | 401 | unsigned long reply_page; |
389 | void (*callback)(struct iwl_priv *priv, | 402 | void (*callback)(struct iwl_priv *priv, |
390 | struct iwl_device_cmd *cmd, | 403 | struct iwl_device_cmd *cmd, |
391 | struct sk_buff *skb); | 404 | struct iwl_rx_packet *pkt); |
392 | u32 flags; | 405 | u32 flags; |
393 | u16 len; | 406 | u16 len; |
394 | u8 id; | 407 | u8 id; |
395 | }; | 408 | }; |
396 | 409 | ||
397 | /* | ||
398 | * RX related structures and functions | ||
399 | */ | ||
400 | #define RX_FREE_BUFFERS 64 | ||
401 | #define RX_LOW_WATERMARK 8 | ||
402 | |||
403 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 | 410 | #define SUP_RATE_11A_MAX_NUM_CHANNELS 8 |
404 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 | 411 | #define SUP_RATE_11B_MAX_NUM_CHANNELS 4 |
405 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 | 412 | #define SUP_RATE_11G_MAX_NUM_CHANNELS 12 |
@@ -563,6 +570,19 @@ struct iwl_station_entry { | |||
563 | struct iwl_hw_key keyinfo; | 570 | struct iwl_hw_key keyinfo; |
564 | }; | 571 | }; |
565 | 572 | ||
573 | /* | ||
574 | * iwl_station_priv: Driver's private station information | ||
575 | * | ||
576 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | ||
577 | * in the structure for use by driver. This structure is places in that | ||
578 | * space. | ||
579 | * | ||
580 | * At the moment use it for the station's rate scaling information. | ||
581 | */ | ||
582 | struct iwl_station_priv { | ||
583 | struct iwl_lq_sta lq_sta; | ||
584 | }; | ||
585 | |||
566 | /* one for each uCode image (inst/data, boot/init/runtime) */ | 586 | /* one for each uCode image (inst/data, boot/init/runtime) */ |
567 | struct fw_desc { | 587 | struct fw_desc { |
568 | void *v_addr; /* access by driver */ | 588 | void *v_addr; /* access by driver */ |
@@ -624,6 +644,10 @@ struct iwl_sensitivity_ranges { | |||
624 | u16 auto_corr_max_cck_mrc; | 644 | u16 auto_corr_max_cck_mrc; |
625 | u16 auto_corr_min_cck; | 645 | u16 auto_corr_min_cck; |
626 | u16 auto_corr_min_cck_mrc; | 646 | u16 auto_corr_min_cck_mrc; |
647 | |||
648 | u16 barker_corr_th_min; | ||
649 | u16 barker_corr_th_min_mrc; | ||
650 | u16 nrg_th_cca; | ||
627 | }; | 651 | }; |
628 | 652 | ||
629 | 653 | ||
@@ -641,7 +665,7 @@ struct iwl_sensitivity_ranges { | |||
641 | * @valid_tx/rx_ant: usable antennas | 665 | * @valid_tx/rx_ant: usable antennas |
642 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) | 666 | * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) |
643 | * @max_rxq_log: Log-base-2 of max_rxq_size | 667 | * @max_rxq_log: Log-base-2 of max_rxq_size |
644 | * @rx_buf_size: Rx buffer size | 668 | * @rx_page_order: Rx buffer page order |
645 | * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR | 669 | * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR |
646 | * @max_stations: | 670 | * @max_stations: |
647 | * @bcast_sta_id: | 671 | * @bcast_sta_id: |
@@ -664,9 +688,8 @@ struct iwl_hw_params { | |||
664 | u8 valid_rx_ant; | 688 | u8 valid_rx_ant; |
665 | u16 max_rxq_size; | 689 | u16 max_rxq_size; |
666 | u16 max_rxq_log; | 690 | u16 max_rxq_log; |
667 | u32 rx_buf_size; | 691 | u32 rx_page_order; |
668 | u32 rx_wrt_ptr_reg; | 692 | u32 rx_wrt_ptr_reg; |
669 | u32 max_pkt_size; | ||
670 | u8 max_stations; | 693 | u8 max_stations; |
671 | u8 bcast_sta_id; | 694 | u8 bcast_sta_id; |
672 | u8 ht40_channel; | 695 | u8 ht40_channel; |
@@ -713,7 +736,11 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i) | |||
713 | 736 | ||
714 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | 737 | static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) |
715 | { | 738 | { |
716 | /* This is for scan command, the big buffer at end of command array */ | 739 | /* |
740 | * This is for init calibration result and scan command which | ||
741 | * required buffer > TFD_MAX_PAYLOAD_SIZE, | ||
742 | * the big buffer at end of command array | ||
743 | */ | ||
717 | if (is_huge) | 744 | if (is_huge) |
718 | return q->n_window; /* must be power of 2 */ | 745 | return q->n_window; /* must be power of 2 */ |
719 | 746 | ||
@@ -845,6 +872,10 @@ struct iwl_sensitivity_data { | |||
845 | s32 nrg_auto_corr_silence_diff; | 872 | s32 nrg_auto_corr_silence_diff; |
846 | u32 num_in_cck_no_fa; | 873 | u32 num_in_cck_no_fa; |
847 | u32 nrg_th_ofdm; | 874 | u32 nrg_th_ofdm; |
875 | |||
876 | u16 barker_corr_th_min; | ||
877 | u16 barker_corr_th_min_mrc; | ||
878 | u16 nrg_th_cca; | ||
848 | }; | 879 | }; |
849 | 880 | ||
850 | /* Chain noise (differential Rx gain) calib data */ | 881 | /* Chain noise (differential Rx gain) calib data */ |
@@ -961,8 +992,6 @@ struct traffic_stats { | |||
961 | }; | 992 | }; |
962 | #endif | 993 | #endif |
963 | 994 | ||
964 | #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ | ||
965 | |||
966 | struct iwl_priv { | 995 | struct iwl_priv { |
967 | 996 | ||
968 | /* ieee device used by generic ieee processing code */ | 997 | /* ieee device used by generic ieee processing code */ |
@@ -976,7 +1005,7 @@ struct iwl_priv { | |||
976 | int frames_count; | 1005 | int frames_count; |
977 | 1006 | ||
978 | enum ieee80211_band band; | 1007 | enum ieee80211_band band; |
979 | int alloc_rxb_skb; | 1008 | int alloc_rxb_page; |
980 | 1009 | ||
981 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, | 1010 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, |
982 | struct iwl_rx_mem_buffer *rxb); | 1011 | struct iwl_rx_mem_buffer *rxb); |
@@ -1081,7 +1110,6 @@ struct iwl_priv { | |||
1081 | u8 last_phy_res[100]; | 1110 | u8 last_phy_res[100]; |
1082 | 1111 | ||
1083 | /* Rate scaling data */ | 1112 | /* Rate scaling data */ |
1084 | s8 data_retry_limit; | ||
1085 | u8 retry_rate; | 1113 | u8 retry_rate; |
1086 | 1114 | ||
1087 | wait_queue_head_t wait_command_queue; | 1115 | wait_queue_head_t wait_command_queue; |
@@ -1090,7 +1118,7 @@ struct iwl_priv { | |||
1090 | 1118 | ||
1091 | /* Rx and Tx DMA processing queues */ | 1119 | /* Rx and Tx DMA processing queues */ |
1092 | struct iwl_rx_queue rxq; | 1120 | struct iwl_rx_queue rxq; |
1093 | struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; | 1121 | struct iwl_tx_queue *txq; |
1094 | unsigned long txq_ctx_active_msk; | 1122 | unsigned long txq_ctx_active_msk; |
1095 | struct iwl_dma_ptr kw; /* keep warm address */ | 1123 | struct iwl_dma_ptr kw; /* keep warm address */ |
1096 | struct iwl_dma_ptr scd_bc_tbls; | 1124 | struct iwl_dma_ptr scd_bc_tbls; |
@@ -1113,7 +1141,9 @@ struct iwl_priv { | |||
1113 | struct iwl_tt_mgmt thermal_throttle; | 1141 | struct iwl_tt_mgmt thermal_throttle; |
1114 | 1142 | ||
1115 | struct iwl_notif_statistics statistics; | 1143 | struct iwl_notif_statistics statistics; |
1116 | unsigned long last_statistics_time; | 1144 | #ifdef CONFIG_IWLWIFI_DEBUG |
1145 | struct iwl_notif_statistics accum_statistics; | ||
1146 | #endif | ||
1117 | 1147 | ||
1118 | /* context information */ | 1148 | /* context information */ |
1119 | u16 rates_mask; | 1149 | u16 rates_mask; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 2e8c40576d22..9429cb1c69bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -358,6 +358,14 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
358 | udelay(5); | 358 | udelay(5); |
359 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, | 359 | iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, |
360 | APMG_PS_CTRL_VAL_RESET_REQ); | 360 | APMG_PS_CTRL_VAL_RESET_REQ); |
361 | |||
362 | /* | ||
363 | * CSR auto clock gate disable bit - | ||
364 | * this is only applicable for HW with OTP shadow RAM | ||
365 | */ | ||
366 | if (priv->cfg->shadow_ram_support) | ||
367 | iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG, | ||
368 | CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||
361 | } | 369 | } |
362 | return ret; | 370 | return ret; |
363 | } | 371 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index b363c96fd6c6..5ba5a4e9e49a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -261,9 +261,12 @@ struct iwl_eeprom_enhanced_txpwr { | |||
261 | /* 1000 Specific */ | 261 | /* 1000 Specific */ |
262 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | 262 | #define EEPROM_1000_EEPROM_VERSION (0x15C) |
263 | 263 | ||
264 | /* 60x0 Specific */ | 264 | /* 6x00 Specific */ |
265 | #define EEPROM_6000_EEPROM_VERSION (0x434) | 265 | #define EEPROM_6000_EEPROM_VERSION (0x434) |
266 | 266 | ||
267 | /* 6x50 Specific */ | ||
268 | #define EEPROM_6050_EEPROM_VERSION (0x532) | ||
269 | |||
267 | /* OTP */ | 270 | /* OTP */ |
268 | /* lower blocks contain EEPROM image and calibration data */ | 271 | /* lower blocks contain EEPROM image and calibration data */ |
269 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | 272 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 532c8d6cd8da..f2a60dc4109f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -92,6 +92,8 @@ const char *get_cmd_string(u8 cmd) | |||
92 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); | 92 | IWL_CMD(CALIBRATION_RES_NOTIFICATION); |
93 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); | 93 | IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); |
94 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); | 94 | IWL_CMD(REPLY_TX_POWER_DBM_CMD); |
95 | IWL_CMD(TEMPERATURE_NOTIFICATION); | ||
96 | IWL_CMD(TX_ANT_CONFIGURATION_CMD); | ||
95 | default: | 97 | default: |
96 | return "UNKNOWN"; | 98 | return "UNKNOWN"; |
97 | 99 | ||
@@ -103,17 +105,8 @@ EXPORT_SYMBOL(get_cmd_string); | |||
103 | 105 | ||
104 | static void iwl_generic_cmd_callback(struct iwl_priv *priv, | 106 | static void iwl_generic_cmd_callback(struct iwl_priv *priv, |
105 | struct iwl_device_cmd *cmd, | 107 | struct iwl_device_cmd *cmd, |
106 | struct sk_buff *skb) | 108 | struct iwl_rx_packet *pkt) |
107 | { | 109 | { |
108 | struct iwl_rx_packet *pkt = NULL; | ||
109 | |||
110 | if (!skb) { | ||
111 | IWL_ERR(priv, "Error: Response NULL in %s.\n", | ||
112 | get_cmd_string(cmd->hdr.cmd)); | ||
113 | return; | ||
114 | } | ||
115 | |||
116 | pkt = (struct iwl_rx_packet *)skb->data; | ||
117 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { | 110 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
118 | IWL_ERR(priv, "Bad return from %s (0x%08X)\n", | 111 | IWL_ERR(priv, "Bad return from %s (0x%08X)\n", |
119 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); | 112 | get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); |
@@ -215,7 +208,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
215 | ret = -EIO; | 208 | ret = -EIO; |
216 | goto fail; | 209 | goto fail; |
217 | } | 210 | } |
218 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) { | 211 | if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) { |
219 | IWL_ERR(priv, "Error: Response NULL in '%s'\n", | 212 | IWL_ERR(priv, "Error: Response NULL in '%s'\n", |
220 | get_cmd_string(cmd->id)); | 213 | get_cmd_string(cmd->id)); |
221 | ret = -EIO; | 214 | ret = -EIO; |
@@ -237,9 +230,9 @@ cancel: | |||
237 | ~CMD_WANT_SKB; | 230 | ~CMD_WANT_SKB; |
238 | } | 231 | } |
239 | fail: | 232 | fail: |
240 | if (cmd->reply_skb) { | 233 | if (cmd->reply_page) { |
241 | dev_kfree_skb_any(cmd->reply_skb); | 234 | free_pages(cmd->reply_page, priv->hw_params.rx_page_order); |
242 | cmd->reply_skb = NULL; | 235 | cmd->reply_page = 0; |
243 | } | 236 | } |
244 | out: | 237 | out: |
245 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); | 238 | clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); |
@@ -272,7 +265,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, | |||
272 | u8 id, u16 len, const void *data, | 265 | u8 id, u16 len, const void *data, |
273 | void (*callback)(struct iwl_priv *priv, | 266 | void (*callback)(struct iwl_priv *priv, |
274 | struct iwl_device_cmd *cmd, | 267 | struct iwl_device_cmd *cmd, |
275 | struct sk_buff *skb)) | 268 | struct iwl_rx_packet *pkt)) |
276 | { | 269 | { |
277 | struct iwl_host_cmd cmd = { | 270 | struct iwl_host_cmd cmd = { |
278 | .id = id, | 271 | .id = id, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 9c6b14952061..9bce2c1625e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -66,7 +66,7 @@ MODULE_PARM_DESC(no_sleep_autoadjust, | |||
66 | 66 | ||
67 | struct iwl_power_vec_entry { | 67 | struct iwl_power_vec_entry { |
68 | struct iwl_powertable_cmd cmd; | 68 | struct iwl_powertable_cmd cmd; |
69 | u8 no_dtim; | 69 | u8 no_dtim; /* number of skip dtim */ |
70 | }; | 70 | }; |
71 | 71 | ||
72 | #define IWL_DTIM_RANGE_0_MAX 2 | 72 | #define IWL_DTIM_RANGE_0_MAX 2 |
@@ -83,8 +83,9 @@ struct iwl_power_vec_entry { | |||
83 | cpu_to_le32(X4)} | 83 | cpu_to_le32(X4)} |
84 | /* default power management (not Tx power) table values */ | 84 | /* default power management (not Tx power) table values */ |
85 | /* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ | 85 | /* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ |
86 | /* DTIM 0 - 2 */ | ||
86 | static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { | 87 | static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { |
87 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 88 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0}, |
88 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, | 89 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, |
89 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, | 90 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, |
90 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, | 91 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, |
@@ -93,15 +94,17 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { | |||
93 | 94 | ||
94 | 95 | ||
95 | /* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ | 96 | /* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ |
97 | /* DTIM 3 - 10 */ | ||
96 | static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { | 98 | static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { |
97 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, | 99 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, |
98 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, | 100 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, |
99 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, | 101 | {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, |
100 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, | 102 | {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, |
101 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} | 103 | {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2} |
102 | }; | 104 | }; |
103 | 105 | ||
104 | /* for DTIM period > IWL_DTIM_RANGE_1_MAX */ | 106 | /* for DTIM period > IWL_DTIM_RANGE_1_MAX */ |
107 | /* DTIM 11 - */ | ||
105 | static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { | 108 | static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { |
106 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, | 109 | {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, |
107 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, | 110 | {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, |
@@ -115,13 +118,15 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
115 | enum iwl_power_level lvl, int period) | 118 | enum iwl_power_level lvl, int period) |
116 | { | 119 | { |
117 | const struct iwl_power_vec_entry *table; | 120 | const struct iwl_power_vec_entry *table; |
118 | int max_sleep, i; | 121 | int max_sleep[IWL_POWER_VEC_SIZE] = { 0 }; |
119 | bool skip; | 122 | int i; |
123 | u8 skip; | ||
124 | u32 slp_itrvl; | ||
120 | 125 | ||
121 | table = range_2; | 126 | table = range_2; |
122 | if (period < IWL_DTIM_RANGE_1_MAX) | 127 | if (period <= IWL_DTIM_RANGE_1_MAX) |
123 | table = range_1; | 128 | table = range_1; |
124 | if (period < IWL_DTIM_RANGE_0_MAX) | 129 | if (period <= IWL_DTIM_RANGE_0_MAX) |
125 | table = range_0; | 130 | table = range_0; |
126 | 131 | ||
127 | BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); | 132 | BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); |
@@ -129,34 +134,60 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
129 | *cmd = table[lvl].cmd; | 134 | *cmd = table[lvl].cmd; |
130 | 135 | ||
131 | if (period == 0) { | 136 | if (period == 0) { |
132 | skip = false; | 137 | skip = 0; |
133 | period = 1; | 138 | period = 1; |
139 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | ||
140 | max_sleep[i] = 1; | ||
141 | |||
134 | } else { | 142 | } else { |
135 | skip = !!table[lvl].no_dtim; | 143 | skip = table[lvl].no_dtim; |
144 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | ||
145 | max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]); | ||
146 | max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1; | ||
136 | } | 147 | } |
137 | 148 | ||
138 | if (skip) { | 149 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
139 | __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; | 150 | /* figure out the listen interval based on dtim period and skip */ |
140 | max_sleep = le32_to_cpu(slp_itrvl); | 151 | if (slp_itrvl == 0xFF) |
141 | if (max_sleep == 0xFF) | 152 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = |
142 | max_sleep = period * (skip + 1); | 153 | cpu_to_le32(period * (skip + 1)); |
143 | else if (max_sleep > period) | 154 | |
144 | max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; | 155 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
156 | if (slp_itrvl > period) | ||
157 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = | ||
158 | cpu_to_le32((slp_itrvl / period) * period); | ||
159 | |||
160 | if (skip) | ||
145 | cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; | 161 | cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; |
146 | } else { | 162 | else |
147 | max_sleep = period; | ||
148 | cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; | 163 | cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; |
149 | } | ||
150 | 164 | ||
151 | for (i = 0; i < IWL_POWER_VEC_SIZE; i++) | 165 | slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]); |
152 | if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) | 166 | if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL) |
153 | cmd->sleep_interval[i] = cpu_to_le32(max_sleep); | 167 | cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] = |
168 | cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL); | ||
169 | |||
170 | /* enforce max sleep interval */ | ||
171 | for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) { | ||
172 | if (le32_to_cpu(cmd->sleep_interval[i]) > | ||
173 | (max_sleep[i] * period)) | ||
174 | cmd->sleep_interval[i] = | ||
175 | cpu_to_le32(max_sleep[i] * period); | ||
176 | if (i != (IWL_POWER_VEC_SIZE - 1)) { | ||
177 | if (le32_to_cpu(cmd->sleep_interval[i]) > | ||
178 | le32_to_cpu(cmd->sleep_interval[i+1])) | ||
179 | cmd->sleep_interval[i] = | ||
180 | cmd->sleep_interval[i+1]; | ||
181 | } | ||
182 | } | ||
154 | 183 | ||
155 | if (priv->power_data.pci_pm) | 184 | if (priv->power_data.pci_pm) |
156 | cmd->flags |= IWL_POWER_PCI_PM_MSK; | 185 | cmd->flags |= IWL_POWER_PCI_PM_MSK; |
157 | else | 186 | else |
158 | cmd->flags &= ~IWL_POWER_PCI_PM_MSK; | 187 | cmd->flags &= ~IWL_POWER_PCI_PM_MSK; |
159 | 188 | ||
189 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", | ||
190 | skip, period); | ||
160 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 191 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
161 | } | 192 | } |
162 | 193 | ||
@@ -862,9 +893,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
862 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | 893 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); |
863 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | 894 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); |
864 | 895 | ||
865 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 896 | if (priv->cfg->adv_thermal_throttle) { |
866 | case CSR_HW_REV_TYPE_6x00: | ||
867 | case CSR_HW_REV_TYPE_6x50: | ||
868 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | 897 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); |
869 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | 898 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * |
870 | IWL_TI_STATE_MAX, GFP_KERNEL); | 899 | IWL_TI_STATE_MAX, GFP_KERNEL); |
@@ -897,11 +926,9 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
897 | &restriction_range[0], size); | 926 | &restriction_range[0], size); |
898 | priv->thermal_throttle.advanced_tt = true; | 927 | priv->thermal_throttle.advanced_tt = true; |
899 | } | 928 | } |
900 | break; | 929 | } else { |
901 | default: | ||
902 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | 930 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); |
903 | priv->thermal_throttle.advanced_tt = false; | 931 | priv->thermal_throttle.advanced_tt = false; |
904 | break; | ||
905 | } | 932 | } |
906 | } | 933 | } |
907 | EXPORT_SYMBOL(iwl_tt_initialize); | 934 | EXPORT_SYMBOL(iwl_tt_initialize); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 493626bcd3ec..e5339c9ad13e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
200 | list_del(element); | 200 | list_del(element); |
201 | 201 | ||
202 | /* Point to Rx buffer via next RBD in circular buffer */ | 202 | /* Point to Rx buffer via next RBD in circular buffer */ |
203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); | 203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); |
204 | rxq->queue[rxq->write] = rxb; | 204 | rxq->queue[rxq->write] = rxb; |
205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
206 | rxq->free_count--; | 206 | rxq->free_count--; |
@@ -239,8 +239,9 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
239 | struct iwl_rx_queue *rxq = &priv->rxq; | 239 | struct iwl_rx_queue *rxq = &priv->rxq; |
240 | struct list_head *element; | 240 | struct list_head *element; |
241 | struct iwl_rx_mem_buffer *rxb; | 241 | struct iwl_rx_mem_buffer *rxb; |
242 | struct sk_buff *skb; | 242 | struct page *page; |
243 | unsigned long flags; | 243 | unsigned long flags; |
244 | gfp_t gfp_mask = priority; | ||
244 | 245 | ||
245 | while (1) { | 246 | while (1) { |
246 | spin_lock_irqsave(&rxq->lock, flags); | 247 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -251,30 +252,35 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
251 | spin_unlock_irqrestore(&rxq->lock, flags); | 252 | spin_unlock_irqrestore(&rxq->lock, flags); |
252 | 253 | ||
253 | if (rxq->free_count > RX_LOW_WATERMARK) | 254 | if (rxq->free_count > RX_LOW_WATERMARK) |
254 | priority |= __GFP_NOWARN; | 255 | gfp_mask |= __GFP_NOWARN; |
255 | /* Alloc a new receive buffer */ | 256 | |
256 | skb = alloc_skb(priv->hw_params.rx_buf_size + 256, | 257 | if (priv->hw_params.rx_page_order > 0) |
257 | priority); | 258 | gfp_mask |= __GFP_COMP; |
258 | 259 | ||
259 | if (!skb) { | 260 | /* Alloc a new receive buffer */ |
261 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
262 | if (!page) { | ||
260 | if (net_ratelimit()) | 263 | if (net_ratelimit()) |
261 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | 264 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " |
265 | "order: %d\n", | ||
266 | priv->hw_params.rx_page_order); | ||
267 | |||
262 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | 268 | if ((rxq->free_count <= RX_LOW_WATERMARK) && |
263 | net_ratelimit()) | 269 | net_ratelimit()) |
264 | IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", | 270 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", |
265 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | 271 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", |
266 | rxq->free_count); | 272 | rxq->free_count); |
267 | /* We don't reschedule replenish work here -- we will | 273 | /* We don't reschedule replenish work here -- we will |
268 | * call the restock method and if it still needs | 274 | * call the restock method and if it still needs |
269 | * more buffers it will schedule replenish */ | 275 | * more buffers it will schedule replenish */ |
270 | break; | 276 | return; |
271 | } | 277 | } |
272 | 278 | ||
273 | spin_lock_irqsave(&rxq->lock, flags); | 279 | spin_lock_irqsave(&rxq->lock, flags); |
274 | 280 | ||
275 | if (list_empty(&rxq->rx_used)) { | 281 | if (list_empty(&rxq->rx_used)) { |
276 | spin_unlock_irqrestore(&rxq->lock, flags); | 282 | spin_unlock_irqrestore(&rxq->lock, flags); |
277 | dev_kfree_skb_any(skb); | 283 | __free_pages(page, priv->hw_params.rx_page_order); |
278 | return; | 284 | return; |
279 | } | 285 | } |
280 | element = rxq->rx_used.next; | 286 | element = rxq->rx_used.next; |
@@ -283,24 +289,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
283 | 289 | ||
284 | spin_unlock_irqrestore(&rxq->lock, flags); | 290 | spin_unlock_irqrestore(&rxq->lock, flags); |
285 | 291 | ||
286 | rxb->skb = skb; | 292 | rxb->page = page; |
287 | /* Get physical address of RB/SKB */ | 293 | /* Get physical address of the RB */ |
288 | rxb->real_dma_addr = pci_map_single( | 294 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, |
289 | priv->pci_dev, | 295 | PAGE_SIZE << priv->hw_params.rx_page_order, |
290 | rxb->skb->data, | 296 | PCI_DMA_FROMDEVICE); |
291 | priv->hw_params.rx_buf_size + 256, | ||
292 | PCI_DMA_FROMDEVICE); | ||
293 | /* dma address must be no more than 36 bits */ | 297 | /* dma address must be no more than 36 bits */ |
294 | BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); | 298 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); |
295 | /* and also 256 byte aligned! */ | 299 | /* and also 256 byte aligned! */ |
296 | rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); | 300 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); |
297 | skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); | ||
298 | 301 | ||
299 | spin_lock_irqsave(&rxq->lock, flags); | 302 | spin_lock_irqsave(&rxq->lock, flags); |
300 | 303 | ||
301 | list_add_tail(&rxb->list, &rxq->rx_free); | 304 | list_add_tail(&rxb->list, &rxq->rx_free); |
302 | rxq->free_count++; | 305 | rxq->free_count++; |
303 | priv->alloc_rxb_skb++; | 306 | priv->alloc_rxb_page++; |
304 | 307 | ||
305 | spin_unlock_irqrestore(&rxq->lock, flags); | 308 | spin_unlock_irqrestore(&rxq->lock, flags); |
306 | } | 309 | } |
@@ -336,12 +339,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
336 | { | 339 | { |
337 | int i; | 340 | int i; |
338 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | 341 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { |
339 | if (rxq->pool[i].skb != NULL) { | 342 | if (rxq->pool[i].page != NULL) { |
340 | pci_unmap_single(priv->pci_dev, | 343 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
341 | rxq->pool[i].real_dma_addr, | 344 | PAGE_SIZE << priv->hw_params.rx_page_order, |
342 | priv->hw_params.rx_buf_size + 256, | 345 | PCI_DMA_FROMDEVICE); |
343 | PCI_DMA_FROMDEVICE); | 346 | __free_pages(rxq->pool[i].page, |
344 | dev_kfree_skb(rxq->pool[i].skb); | 347 | priv->hw_params.rx_page_order); |
348 | rxq->pool[i].page = NULL; | ||
349 | priv->alloc_rxb_page--; | ||
345 | } | 350 | } |
346 | } | 351 | } |
347 | 352 | ||
@@ -405,14 +410,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
405 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | 410 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { |
406 | /* In the reset function, these buffers may have been allocated | 411 | /* In the reset function, these buffers may have been allocated |
407 | * to an SKB, so we need to unmap and free potential storage */ | 412 | * to an SKB, so we need to unmap and free potential storage */ |
408 | if (rxq->pool[i].skb != NULL) { | 413 | if (rxq->pool[i].page != NULL) { |
409 | pci_unmap_single(priv->pci_dev, | 414 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
410 | rxq->pool[i].real_dma_addr, | 415 | PAGE_SIZE << priv->hw_params.rx_page_order, |
411 | priv->hw_params.rx_buf_size + 256, | 416 | PCI_DMA_FROMDEVICE); |
412 | PCI_DMA_FROMDEVICE); | 417 | priv->alloc_rxb_page--; |
413 | priv->alloc_rxb_skb--; | 418 | __free_pages(rxq->pool[i].page, |
414 | dev_kfree_skb(rxq->pool[i].skb); | 419 | priv->hw_params.rx_page_order); |
415 | rxq->pool[i].skb = NULL; | 420 | rxq->pool[i].page = NULL; |
416 | } | 421 | } |
417 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 422 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
418 | } | 423 | } |
@@ -491,7 +496,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
491 | struct iwl_rx_mem_buffer *rxb) | 496 | struct iwl_rx_mem_buffer *rxb) |
492 | 497 | ||
493 | { | 498 | { |
494 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 499 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
495 | struct iwl_missed_beacon_notif *missed_beacon; | 500 | struct iwl_missed_beacon_notif *missed_beacon; |
496 | 501 | ||
497 | missed_beacon = &pkt->u.missed_beacon; | 502 | missed_beacon = &pkt->u.missed_beacon; |
@@ -548,13 +553,51 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
548 | priv->last_rx_noise); | 553 | priv->last_rx_noise); |
549 | } | 554 | } |
550 | 555 | ||
556 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
557 | /* | ||
558 | * based on the assumption of all statistics counter are in DWORD | ||
559 | * FIXME: This function is for debugging, do not deal with | ||
560 | * the case of counters roll-over. | ||
561 | */ | ||
562 | static void iwl_accumulative_statistics(struct iwl_priv *priv, | ||
563 | __le32 *stats) | ||
564 | { | ||
565 | int i; | ||
566 | __le32 *prev_stats; | ||
567 | u32 *accum_stats; | ||
568 | |||
569 | prev_stats = (__le32 *)&priv->statistics; | ||
570 | accum_stats = (u32 *)&priv->accum_statistics; | ||
571 | |||
572 | for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); | ||
573 | i += sizeof(__le32), stats++, prev_stats++, accum_stats++) | ||
574 | if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) | ||
575 | *accum_stats += (le32_to_cpu(*stats) - | ||
576 | le32_to_cpu(*prev_stats)); | ||
577 | |||
578 | /* reset accumulative statistics for "no-counter" type statistics */ | ||
579 | priv->accum_statistics.general.temperature = | ||
580 | priv->statistics.general.temperature; | ||
581 | priv->accum_statistics.general.temperature_m = | ||
582 | priv->statistics.general.temperature_m; | ||
583 | priv->accum_statistics.general.ttl_timestamp = | ||
584 | priv->statistics.general.ttl_timestamp; | ||
585 | priv->accum_statistics.tx.tx_power.ant_a = | ||
586 | priv->statistics.tx.tx_power.ant_a; | ||
587 | priv->accum_statistics.tx.tx_power.ant_b = | ||
588 | priv->statistics.tx.tx_power.ant_b; | ||
589 | priv->accum_statistics.tx.tx_power.ant_c = | ||
590 | priv->statistics.tx.tx_power.ant_c; | ||
591 | } | ||
592 | #endif | ||
593 | |||
551 | #define REG_RECALIB_PERIOD (60) | 594 | #define REG_RECALIB_PERIOD (60) |
552 | 595 | ||
553 | void iwl_rx_statistics(struct iwl_priv *priv, | 596 | void iwl_rx_statistics(struct iwl_priv *priv, |
554 | struct iwl_rx_mem_buffer *rxb) | 597 | struct iwl_rx_mem_buffer *rxb) |
555 | { | 598 | { |
556 | int change; | 599 | int change; |
557 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 600 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
558 | 601 | ||
559 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 602 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
560 | (int)sizeof(priv->statistics), | 603 | (int)sizeof(priv->statistics), |
@@ -566,6 +609,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
566 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != | 609 | STATISTICS_REPLY_FLG_HT40_MODE_MSK) != |
567 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); | 610 | (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); |
568 | 611 | ||
612 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
613 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | ||
614 | #endif | ||
569 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); | 615 | memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); |
570 | 616 | ||
571 | set_bit(STATUS_STATISTICS, &priv->status); | 617 | set_bit(STATUS_STATISTICS, &priv->status); |
@@ -582,9 +628,6 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
582 | iwl_rx_calc_noise(priv); | 628 | iwl_rx_calc_noise(priv); |
583 | queue_work(priv->workqueue, &priv->run_time_calib_work); | 629 | queue_work(priv->workqueue, &priv->run_time_calib_work); |
584 | } | 630 | } |
585 | |||
586 | iwl_leds_background(priv); | ||
587 | |||
588 | if (priv->cfg->ops->lib->temp_ops.temperature && change) | 631 | if (priv->cfg->ops->lib->temp_ops.temperature && change) |
589 | priv->cfg->ops->lib->temp_ops.temperature(priv); | 632 | priv->cfg->ops->lib->temp_ops.temperature(priv); |
590 | } | 633 | } |
@@ -878,6 +921,10 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
878 | struct iwl_rx_mem_buffer *rxb, | 921 | struct iwl_rx_mem_buffer *rxb, |
879 | struct ieee80211_rx_status *stats) | 922 | struct ieee80211_rx_status *stats) |
880 | { | 923 | { |
924 | struct sk_buff *skb; | ||
925 | int ret = 0; | ||
926 | __le16 fc = hdr->frame_control; | ||
927 | |||
881 | /* We only process data packets if the interface is open */ | 928 | /* We only process data packets if the interface is open */ |
882 | if (unlikely(!priv->is_open)) { | 929 | if (unlikely(!priv->is_open)) { |
883 | IWL_DEBUG_DROP_LIMIT(priv, | 930 | IWL_DEBUG_DROP_LIMIT(priv, |
@@ -890,15 +937,43 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
890 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | 937 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) |
891 | return; | 938 | return; |
892 | 939 | ||
893 | /* Resize SKB from mac header to end of packet */ | 940 | skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC); |
894 | skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); | 941 | if (!skb) { |
895 | skb_put(rxb->skb, len); | 942 | IWL_ERR(priv, "alloc_skb failed\n"); |
943 | return; | ||
944 | } | ||
945 | |||
946 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
947 | |||
948 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
949 | * linear SKB for management frame and data frame requires | ||
950 | * software decryption or software defragementation. */ | ||
951 | if (ieee80211_is_mgmt(fc) || | ||
952 | ieee80211_has_protected(fc) || | ||
953 | ieee80211_has_morefrags(fc) || | ||
954 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
955 | ret = skb_linearize(skb); | ||
956 | else | ||
957 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
958 | 0 : -ENOMEM; | ||
959 | |||
960 | if (ret) { | ||
961 | kfree_skb(skb); | ||
962 | goto out; | ||
963 | } | ||
964 | |||
965 | /* | ||
966 | * XXX: We cannot touch the page and its virtual memory (hdr) after | ||
967 | * here. It might have already been freed by the above skb change. | ||
968 | */ | ||
969 | |||
970 | iwl_update_stats(priv, false, fc, len); | ||
971 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
896 | 972 | ||
897 | iwl_update_stats(priv, false, hdr->frame_control, len); | 973 | ieee80211_rx(priv->hw, skb); |
898 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 974 | out: |
899 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 975 | priv->alloc_rxb_page--; |
900 | priv->alloc_rxb_skb--; | 976 | rxb->page = NULL; |
901 | rxb->skb = NULL; | ||
902 | } | 977 | } |
903 | 978 | ||
904 | /* This is necessary only for a number of statistics, see the caller. */ | 979 | /* This is necessary only for a number of statistics, see the caller. */ |
@@ -926,7 +1001,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
926 | { | 1001 | { |
927 | struct ieee80211_hdr *header; | 1002 | struct ieee80211_hdr *header; |
928 | struct ieee80211_rx_status rx_status; | 1003 | struct ieee80211_rx_status rx_status; |
929 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1004 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
930 | struct iwl_rx_phy_res *phy_res; | 1005 | struct iwl_rx_phy_res *phy_res; |
931 | __le32 rx_pkt_status; | 1006 | __le32 rx_pkt_status; |
932 | struct iwl4965_rx_mpdu_res_start *amsdu; | 1007 | struct iwl4965_rx_mpdu_res_start *amsdu; |
@@ -1087,7 +1162,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx); | |||
1087 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | 1162 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, |
1088 | struct iwl_rx_mem_buffer *rxb) | 1163 | struct iwl_rx_mem_buffer *rxb) |
1089 | { | 1164 | { |
1090 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1165 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1091 | priv->last_phy_res[0] = 1; | 1166 | priv->last_phy_res[0] = 1; |
1092 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | 1167 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), |
1093 | sizeof(struct iwl_rx_phy_res)); | 1168 | sizeof(struct iwl_rx_phy_res)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 41f9a0621250..4fca65a2fe9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout); | |||
111 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 111 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
112 | { | 112 | { |
113 | int ret = 0; | 113 | int ret = 0; |
114 | struct iwl_rx_packet *res; | 114 | struct iwl_rx_packet *pkt; |
115 | struct iwl_host_cmd cmd = { | 115 | struct iwl_host_cmd cmd = { |
116 | .id = REPLY_SCAN_ABORT_CMD, | 116 | .id = REPLY_SCAN_ABORT_CMD, |
117 | .flags = CMD_WANT_SKB, | 117 | .flags = CMD_WANT_SKB, |
@@ -131,21 +131,21 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
131 | return ret; | 131 | return ret; |
132 | } | 132 | } |
133 | 133 | ||
134 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 134 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
135 | if (res->u.status != CAN_ABORT_STATUS) { | 135 | if (pkt->u.status != CAN_ABORT_STATUS) { |
136 | /* The scan abort will return 1 for success or | 136 | /* The scan abort will return 1 for success or |
137 | * 2 for "failure". A failure condition can be | 137 | * 2 for "failure". A failure condition can be |
138 | * due to simply not being in an active scan which | 138 | * due to simply not being in an active scan which |
139 | * can occur if we send the scan abort before we | 139 | * can occur if we send the scan abort before we |
140 | * the microcode has notified us that a scan is | 140 | * the microcode has notified us that a scan is |
141 | * completed. */ | 141 | * completed. */ |
142 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status); | 142 | IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status); |
143 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); | 143 | clear_bit(STATUS_SCAN_ABORTING, &priv->status); |
144 | clear_bit(STATUS_SCAN_HW, &priv->status); | 144 | clear_bit(STATUS_SCAN_HW, &priv->status); |
145 | } | 145 | } |
146 | 146 | ||
147 | priv->alloc_rxb_skb--; | 147 | priv->alloc_rxb_page--; |
148 | dev_kfree_skb_any(cmd.reply_skb); | 148 | free_pages(cmd.reply_page, priv->hw_params.rx_page_order); |
149 | 149 | ||
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
@@ -155,7 +155,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
155 | struct iwl_rx_mem_buffer *rxb) | 155 | struct iwl_rx_mem_buffer *rxb) |
156 | { | 156 | { |
157 | #ifdef CONFIG_IWLWIFI_DEBUG | 157 | #ifdef CONFIG_IWLWIFI_DEBUG |
158 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 158 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
159 | struct iwl_scanreq_notification *notif = | 159 | struct iwl_scanreq_notification *notif = |
160 | (struct iwl_scanreq_notification *)pkt->u.raw; | 160 | (struct iwl_scanreq_notification *)pkt->u.raw; |
161 | 161 | ||
@@ -167,7 +167,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv, | |||
167 | static void iwl_rx_scan_start_notif(struct iwl_priv *priv, | 167 | static void iwl_rx_scan_start_notif(struct iwl_priv *priv, |
168 | struct iwl_rx_mem_buffer *rxb) | 168 | struct iwl_rx_mem_buffer *rxb) |
169 | { | 169 | { |
170 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 170 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
171 | struct iwl_scanstart_notification *notif = | 171 | struct iwl_scanstart_notification *notif = |
172 | (struct iwl_scanstart_notification *)pkt->u.raw; | 172 | (struct iwl_scanstart_notification *)pkt->u.raw; |
173 | priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); | 173 | priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); |
@@ -186,7 +186,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv, | |||
186 | struct iwl_rx_mem_buffer *rxb) | 186 | struct iwl_rx_mem_buffer *rxb) |
187 | { | 187 | { |
188 | #ifdef CONFIG_IWLWIFI_DEBUG | 188 | #ifdef CONFIG_IWLWIFI_DEBUG |
189 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 189 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
190 | struct iwl_scanresults_notification *notif = | 190 | struct iwl_scanresults_notification *notif = |
191 | (struct iwl_scanresults_notification *)pkt->u.raw; | 191 | (struct iwl_scanresults_notification *)pkt->u.raw; |
192 | 192 | ||
@@ -213,7 +213,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, | |||
213 | struct iwl_rx_mem_buffer *rxb) | 213 | struct iwl_rx_mem_buffer *rxb) |
214 | { | 214 | { |
215 | #ifdef CONFIG_IWLWIFI_DEBUG | 215 | #ifdef CONFIG_IWLWIFI_DEBUG |
216 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 216 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
217 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; | 217 | struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; |
218 | 218 | ||
219 | IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", | 219 | IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c index 022bcf115731..1ea5cd345fe8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c | |||
@@ -177,7 +177,7 @@ static int iwl_get_measurement(struct iwl_priv *priv, | |||
177 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, | 177 | static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, |
178 | struct iwl_rx_mem_buffer *rxb) | 178 | struct iwl_rx_mem_buffer *rxb) |
179 | { | 179 | { |
180 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 180 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
181 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); | 181 | struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); |
182 | 182 | ||
183 | if (!report->state) { | 183 | if (!report->state) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index c6633fec8216..dc74c16d36a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -99,32 +99,25 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | |||
99 | 99 | ||
100 | static void iwl_add_sta_callback(struct iwl_priv *priv, | 100 | static void iwl_add_sta_callback(struct iwl_priv *priv, |
101 | struct iwl_device_cmd *cmd, | 101 | struct iwl_device_cmd *cmd, |
102 | struct sk_buff *skb) | 102 | struct iwl_rx_packet *pkt) |
103 | { | 103 | { |
104 | struct iwl_rx_packet *res = NULL; | ||
105 | struct iwl_addsta_cmd *addsta = | 104 | struct iwl_addsta_cmd *addsta = |
106 | (struct iwl_addsta_cmd *)cmd->cmd.payload; | 105 | (struct iwl_addsta_cmd *)cmd->cmd.payload; |
107 | u8 sta_id = addsta->sta.sta_id; | 106 | u8 sta_id = addsta->sta.sta_id; |
108 | 107 | ||
109 | if (!skb) { | 108 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
110 | IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | res = (struct iwl_rx_packet *)skb->data; | ||
115 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
116 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 109 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
117 | res->hdr.flags); | 110 | pkt->hdr.flags); |
118 | return; | 111 | return; |
119 | } | 112 | } |
120 | 113 | ||
121 | switch (res->u.add_sta.status) { | 114 | switch (pkt->u.add_sta.status) { |
122 | case ADD_STA_SUCCESS_MSK: | 115 | case ADD_STA_SUCCESS_MSK: |
123 | iwl_sta_ucode_activate(priv, sta_id); | 116 | iwl_sta_ucode_activate(priv, sta_id); |
124 | /* fall through */ | 117 | /* fall through */ |
125 | default: | 118 | default: |
126 | IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", | 119 | IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", |
127 | res->u.add_sta.status); | 120 | pkt->u.add_sta.status); |
128 | break; | 121 | break; |
129 | } | 122 | } |
130 | } | 123 | } |
@@ -132,7 +125,7 @@ static void iwl_add_sta_callback(struct iwl_priv *priv, | |||
132 | int iwl_send_add_sta(struct iwl_priv *priv, | 125 | int iwl_send_add_sta(struct iwl_priv *priv, |
133 | struct iwl_addsta_cmd *sta, u8 flags) | 126 | struct iwl_addsta_cmd *sta, u8 flags) |
134 | { | 127 | { |
135 | struct iwl_rx_packet *res = NULL; | 128 | struct iwl_rx_packet *pkt = NULL; |
136 | int ret = 0; | 129 | int ret = 0; |
137 | u8 data[sizeof(*sta)]; | 130 | u8 data[sizeof(*sta)]; |
138 | struct iwl_host_cmd cmd = { | 131 | struct iwl_host_cmd cmd = { |
@@ -152,15 +145,15 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
152 | if (ret || (flags & CMD_ASYNC)) | 145 | if (ret || (flags & CMD_ASYNC)) |
153 | return ret; | 146 | return ret; |
154 | 147 | ||
155 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 148 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
156 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 149 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
157 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", | 150 | IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", |
158 | res->hdr.flags); | 151 | pkt->hdr.flags); |
159 | ret = -EIO; | 152 | ret = -EIO; |
160 | } | 153 | } |
161 | 154 | ||
162 | if (ret == 0) { | 155 | if (ret == 0) { |
163 | switch (res->u.add_sta.status) { | 156 | switch (pkt->u.add_sta.status) { |
164 | case ADD_STA_SUCCESS_MSK: | 157 | case ADD_STA_SUCCESS_MSK: |
165 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); | 158 | iwl_sta_ucode_activate(priv, sta->sta.sta_id); |
166 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); | 159 | IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); |
@@ -172,8 +165,8 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
172 | } | 165 | } |
173 | } | 166 | } |
174 | 167 | ||
175 | priv->alloc_rxb_skb--; | 168 | priv->alloc_rxb_page--; |
176 | dev_kfree_skb_any(cmd.reply_skb); | 169 | free_pages(cmd.reply_page, priv->hw_params.rx_page_order); |
177 | 170 | ||
178 | return ret; | 171 | return ret; |
179 | } | 172 | } |
@@ -324,26 +317,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) | |||
324 | 317 | ||
325 | static void iwl_remove_sta_callback(struct iwl_priv *priv, | 318 | static void iwl_remove_sta_callback(struct iwl_priv *priv, |
326 | struct iwl_device_cmd *cmd, | 319 | struct iwl_device_cmd *cmd, |
327 | struct sk_buff *skb) | 320 | struct iwl_rx_packet *pkt) |
328 | { | 321 | { |
329 | struct iwl_rx_packet *res = NULL; | ||
330 | struct iwl_rem_sta_cmd *rm_sta = | 322 | struct iwl_rem_sta_cmd *rm_sta = |
331 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; | 323 | (struct iwl_rem_sta_cmd *)cmd->cmd.payload; |
332 | const char *addr = rm_sta->addr; | 324 | const char *addr = rm_sta->addr; |
333 | 325 | ||
334 | if (!skb) { | 326 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
335 | IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n"); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | res = (struct iwl_rx_packet *)skb->data; | ||
340 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
341 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 327 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
342 | res->hdr.flags); | 328 | pkt->hdr.flags); |
343 | return; | 329 | return; |
344 | } | 330 | } |
345 | 331 | ||
346 | switch (res->u.rem_sta.status) { | 332 | switch (pkt->u.rem_sta.status) { |
347 | case REM_STA_SUCCESS_MSK: | 333 | case REM_STA_SUCCESS_MSK: |
348 | iwl_sta_ucode_deactivate(priv, addr); | 334 | iwl_sta_ucode_deactivate(priv, addr); |
349 | break; | 335 | break; |
@@ -356,7 +342,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv, | |||
356 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | 342 | static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, |
357 | u8 flags) | 343 | u8 flags) |
358 | { | 344 | { |
359 | struct iwl_rx_packet *res = NULL; | 345 | struct iwl_rx_packet *pkt; |
360 | int ret; | 346 | int ret; |
361 | 347 | ||
362 | struct iwl_rem_sta_cmd rm_sta_cmd; | 348 | struct iwl_rem_sta_cmd rm_sta_cmd; |
@@ -381,15 +367,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
381 | if (ret || (flags & CMD_ASYNC)) | 367 | if (ret || (flags & CMD_ASYNC)) |
382 | return ret; | 368 | return ret; |
383 | 369 | ||
384 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 370 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
385 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 371 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
386 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", | 372 | IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", |
387 | res->hdr.flags); | 373 | pkt->hdr.flags); |
388 | ret = -EIO; | 374 | ret = -EIO; |
389 | } | 375 | } |
390 | 376 | ||
391 | if (!ret) { | 377 | if (!ret) { |
392 | switch (res->u.rem_sta.status) { | 378 | switch (pkt->u.rem_sta.status) { |
393 | case REM_STA_SUCCESS_MSK: | 379 | case REM_STA_SUCCESS_MSK: |
394 | iwl_sta_ucode_deactivate(priv, addr); | 380 | iwl_sta_ucode_deactivate(priv, addr); |
395 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); | 381 | IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); |
@@ -401,8 +387,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, | |||
401 | } | 387 | } |
402 | } | 388 | } |
403 | 389 | ||
404 | priv->alloc_rxb_skb--; | 390 | priv->alloc_rxb_page--; |
405 | dev_kfree_skb_any(cmd.reply_skb); | 391 | free_pages(cmd.reply_page, priv->hw_params.rx_page_order); |
406 | 392 | ||
407 | return ret; | 393 | return ret; |
408 | } | 394 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index c832ba085dba..8ae4c9b614e7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -131,7 +131,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
131 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 131 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
132 | struct iwl_queue *q = &txq->q; | 132 | struct iwl_queue *q = &txq->q; |
133 | struct pci_dev *dev = priv->pci_dev; | 133 | struct pci_dev *dev = priv->pci_dev; |
134 | int i, len; | 134 | int i; |
135 | 135 | ||
136 | if (q->n_bd == 0) | 136 | if (q->n_bd == 0) |
137 | return; | 137 | return; |
@@ -141,8 +141,6 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
141 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) | 141 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) |
142 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 142 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
143 | 143 | ||
144 | len = sizeof(struct iwl_device_cmd) * q->n_window; | ||
145 | |||
146 | /* De-alloc array of command/tx buffers */ | 144 | /* De-alloc array of command/tx buffers */ |
147 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) | 145 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) |
148 | kfree(txq->cmd[i]); | 146 | kfree(txq->cmd[i]); |
@@ -180,14 +178,11 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
180 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; | 178 | struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; |
181 | struct iwl_queue *q = &txq->q; | 179 | struct iwl_queue *q = &txq->q; |
182 | struct pci_dev *dev = priv->pci_dev; | 180 | struct pci_dev *dev = priv->pci_dev; |
183 | int i, len; | 181 | int i; |
184 | 182 | ||
185 | if (q->n_bd == 0) | 183 | if (q->n_bd == 0) |
186 | return; | 184 | return; |
187 | 185 | ||
188 | len = sizeof(struct iwl_device_cmd) * q->n_window; | ||
189 | len += IWL_MAX_SCAN_SIZE; | ||
190 | |||
191 | /* De-alloc array of command/tx buffers */ | 186 | /* De-alloc array of command/tx buffers */ |
192 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 187 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |
193 | kfree(txq->cmd[i]); | 188 | kfree(txq->cmd[i]); |
@@ -405,15 +400,19 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
405 | int txq_id; | 400 | int txq_id; |
406 | 401 | ||
407 | /* Tx queues */ | 402 | /* Tx queues */ |
408 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | 403 | if (priv->txq) |
409 | if (txq_id == IWL_CMD_QUEUE_NUM) | 404 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; |
410 | iwl_cmd_queue_free(priv); | 405 | txq_id++) |
411 | else | 406 | if (txq_id == IWL_CMD_QUEUE_NUM) |
412 | iwl_tx_queue_free(priv, txq_id); | 407 | iwl_cmd_queue_free(priv); |
413 | 408 | else | |
409 | iwl_tx_queue_free(priv, txq_id); | ||
414 | iwl_free_dma_ptr(priv, &priv->kw); | 410 | iwl_free_dma_ptr(priv, &priv->kw); |
415 | 411 | ||
416 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | 412 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); |
413 | |||
414 | /* free tx queue structure */ | ||
415 | iwl_free_txq_mem(priv); | ||
417 | } | 416 | } |
418 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 417 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
419 | 418 | ||
@@ -445,6 +444,12 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
445 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | 444 | IWL_ERR(priv, "Keep Warm allocation failed\n"); |
446 | goto error_kw; | 445 | goto error_kw; |
447 | } | 446 | } |
447 | |||
448 | /* allocate tx queue structure */ | ||
449 | ret = iwl_alloc_txq_mem(priv); | ||
450 | if (ret) | ||
451 | goto error; | ||
452 | |||
448 | spin_lock_irqsave(&priv->lock, flags); | 453 | spin_lock_irqsave(&priv->lock, flags); |
449 | 454 | ||
450 | /* Turn off all Tx DMA fifos */ | 455 | /* Turn off all Tx DMA fifos */ |
@@ -581,9 +586,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, | |||
581 | u8 rate_plcp; | 586 | u8 rate_plcp; |
582 | 587 | ||
583 | /* Set retry limit on DATA packets and Probe Responses*/ | 588 | /* Set retry limit on DATA packets and Probe Responses*/ |
584 | if (priv->data_retry_limit != -1) | 589 | if (ieee80211_is_probe_resp(fc)) |
585 | data_retry_limit = priv->data_retry_limit; | ||
586 | else if (ieee80211_is_probe_resp(fc)) | ||
587 | data_retry_limit = 3; | 590 | data_retry_limit = 3; |
588 | else | 591 | else |
589 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | 592 | data_retry_limit = IWL_DEFAULT_TX_RETRY; |
@@ -1145,7 +1148,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, | |||
1145 | */ | 1148 | */ |
1146 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 1149 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) |
1147 | { | 1150 | { |
1148 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1151 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1149 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | 1152 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); |
1150 | int txq_id = SEQ_TO_QUEUE(sequence); | 1153 | int txq_id = SEQ_TO_QUEUE(sequence); |
1151 | int index = SEQ_TO_INDEX(sequence); | 1154 | int index = SEQ_TO_INDEX(sequence); |
@@ -1172,10 +1175,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1172 | 1175 | ||
1173 | /* Input error checking is done when commands are added to queue. */ | 1176 | /* Input error checking is done when commands are added to queue. */ |
1174 | if (meta->flags & CMD_WANT_SKB) { | 1177 | if (meta->flags & CMD_WANT_SKB) { |
1175 | meta->source->reply_skb = rxb->skb; | 1178 | meta->source->reply_page = (unsigned long)rxb_addr(rxb); |
1176 | rxb->skb = NULL; | 1179 | rxb->page = NULL; |
1177 | } else if (meta->callback) | 1180 | } else if (meta->callback) |
1178 | meta->callback(priv, cmd, rxb->skb); | 1181 | meta->callback(priv, cmd, pkt); |
1179 | 1182 | ||
1180 | iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); | 1183 | iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); |
1181 | 1184 | ||
@@ -1434,7 +1437,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1434 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | 1437 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, |
1435 | struct iwl_rx_mem_buffer *rxb) | 1438 | struct iwl_rx_mem_buffer *rxb) |
1436 | { | 1439 | { |
1437 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1440 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
1438 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | 1441 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; |
1439 | struct iwl_tx_queue *txq = NULL; | 1442 | struct iwl_tx_queue *txq = NULL; |
1440 | struct iwl_ht_agg *agg; | 1443 | struct iwl_ht_agg *agg; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c347d6631d85..bfd7f497157f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -88,7 +88,6 @@ MODULE_LICENSE("GPL"); | |||
88 | 88 | ||
89 | /* module parameters */ | 89 | /* module parameters */ |
90 | struct iwl_mod_params iwl3945_mod_params = { | 90 | struct iwl_mod_params iwl3945_mod_params = { |
91 | .num_of_queues = IWL39_NUM_QUEUES, /* Not used */ | ||
92 | .sw_crypto = 1, | 91 | .sw_crypto = 1, |
93 | .restart_fw = 1, | 92 | .restart_fw = 1, |
94 | /* the rest are 0 by default */ | 93 | /* the rest are 0 by default */ |
@@ -366,13 +365,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
366 | struct sk_buff *skb_frag, | 365 | struct sk_buff *skb_frag, |
367 | int sta_id) | 366 | int sta_id) |
368 | { | 367 | { |
369 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 368 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
370 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 369 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
371 | 370 | ||
372 | switch (keyinfo->alg) { | 371 | switch (keyinfo->alg) { |
373 | case ALG_CCMP: | 372 | case ALG_CCMP: |
374 | tx->sec_ctl = TX_CMD_SEC_CCM; | 373 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
375 | memcpy(tx->key, keyinfo->key, keyinfo->keylen); | 374 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); |
376 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 375 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
377 | break; | 376 | break; |
378 | 377 | ||
@@ -380,13 +379,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
380 | break; | 379 | break; |
381 | 380 | ||
382 | case ALG_WEP: | 381 | case ALG_WEP: |
383 | tx->sec_ctl = TX_CMD_SEC_WEP | | 382 | tx_cmd->sec_ctl = TX_CMD_SEC_WEP | |
384 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 383 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; |
385 | 384 | ||
386 | if (keyinfo->keylen == 13) | 385 | if (keyinfo->keylen == 13) |
387 | tx->sec_ctl |= TX_CMD_SEC_KEY128; | 386 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; |
388 | 387 | ||
389 | memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen); | 388 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); |
390 | 389 | ||
391 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 390 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
392 | "with key %d\n", info->control.hw_key->hw_key_idx); | 391 | "with key %d\n", info->control.hw_key->hw_key_idx); |
@@ -406,12 +405,11 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
406 | struct ieee80211_tx_info *info, | 405 | struct ieee80211_tx_info *info, |
407 | struct ieee80211_hdr *hdr, u8 std_id) | 406 | struct ieee80211_hdr *hdr, u8 std_id) |
408 | { | 407 | { |
409 | struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 408 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
410 | __le32 tx_flags = tx->tx_flags; | 409 | __le32 tx_flags = tx_cmd->tx_flags; |
411 | __le16 fc = hdr->frame_control; | 410 | __le16 fc = hdr->frame_control; |
412 | u8 rc_flags = info->control.rates[0].flags; | ||
413 | 411 | ||
414 | tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 412 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
415 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 413 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
416 | tx_flags |= TX_CMD_FLG_ACK_MSK; | 414 | tx_flags |= TX_CMD_FLG_ACK_MSK; |
417 | if (ieee80211_is_mgmt(fc)) | 415 | if (ieee80211_is_mgmt(fc)) |
@@ -424,25 +422,19 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
424 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 422 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
425 | } | 423 | } |
426 | 424 | ||
427 | tx->sta_id = std_id; | 425 | tx_cmd->sta_id = std_id; |
428 | if (ieee80211_has_morefrags(fc)) | 426 | if (ieee80211_has_morefrags(fc)) |
429 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | 427 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; |
430 | 428 | ||
431 | if (ieee80211_is_data_qos(fc)) { | 429 | if (ieee80211_is_data_qos(fc)) { |
432 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 430 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
433 | tx->tid_tspec = qc[0] & 0xf; | 431 | tx_cmd->tid_tspec = qc[0] & 0xf; |
434 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | 432 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; |
435 | } else { | 433 | } else { |
436 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | 434 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; |
437 | } | 435 | } |
438 | 436 | ||
439 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | 437 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); |
440 | tx_flags |= TX_CMD_FLG_RTS_MSK; | ||
441 | tx_flags &= ~TX_CMD_FLG_CTS_MSK; | ||
442 | } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
443 | tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
444 | tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
445 | } | ||
446 | 438 | ||
447 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | 439 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) |
448 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | 440 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; |
@@ -450,16 +442,16 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
450 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | 442 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); |
451 | if (ieee80211_is_mgmt(fc)) { | 443 | if (ieee80211_is_mgmt(fc)) { |
452 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | 444 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) |
453 | tx->timeout.pm_frame_timeout = cpu_to_le16(3); | 445 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); |
454 | else | 446 | else |
455 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); | 447 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); |
456 | } else { | 448 | } else { |
457 | tx->timeout.pm_frame_timeout = 0; | 449 | tx_cmd->timeout.pm_frame_timeout = 0; |
458 | } | 450 | } |
459 | 451 | ||
460 | tx->driver_txop = 0; | 452 | tx_cmd->driver_txop = 0; |
461 | tx->tx_flags = tx_flags; | 453 | tx_cmd->tx_flags = tx_flags; |
462 | tx->next_frame_len = 0; | 454 | tx_cmd->next_frame_len = 0; |
463 | } | 455 | } |
464 | 456 | ||
465 | /* | 457 | /* |
@@ -469,7 +461,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
469 | { | 461 | { |
470 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 462 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
471 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 463 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
472 | struct iwl3945_tx_cmd *tx; | 464 | struct iwl3945_tx_cmd *tx_cmd; |
473 | struct iwl_tx_queue *txq = NULL; | 465 | struct iwl_tx_queue *txq = NULL; |
474 | struct iwl_queue *q = NULL; | 466 | struct iwl_queue *q = NULL; |
475 | struct iwl_device_cmd *out_cmd; | 467 | struct iwl_device_cmd *out_cmd; |
@@ -568,9 +560,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
568 | /* Init first empty entry in queue's array of Tx/cmd buffers */ | 560 | /* Init first empty entry in queue's array of Tx/cmd buffers */ |
569 | out_cmd = txq->cmd[idx]; | 561 | out_cmd = txq->cmd[idx]; |
570 | out_meta = &txq->meta[idx]; | 562 | out_meta = &txq->meta[idx]; |
571 | tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; | 563 | tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; |
572 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | 564 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); |
573 | memset(tx, 0, sizeof(*tx)); | 565 | memset(tx_cmd, 0, sizeof(*tx_cmd)); |
574 | 566 | ||
575 | /* | 567 | /* |
576 | * Set up the Tx-command (not MAC!) header. | 568 | * Set up the Tx-command (not MAC!) header. |
@@ -583,7 +575,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
583 | INDEX_TO_SEQ(q->write_ptr))); | 575 | INDEX_TO_SEQ(q->write_ptr))); |
584 | 576 | ||
585 | /* Copy MAC header from skb into command buffer */ | 577 | /* Copy MAC header from skb into command buffer */ |
586 | memcpy(tx->hdr, hdr, hdr_len); | 578 | memcpy(tx_cmd->hdr, hdr, hdr_len); |
587 | 579 | ||
588 | 580 | ||
589 | if (info->control.hw_key) | 581 | if (info->control.hw_key) |
@@ -597,12 +589,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
597 | 589 | ||
598 | /* Total # bytes to be transmitted */ | 590 | /* Total # bytes to be transmitted */ |
599 | len = (u16)skb->len; | 591 | len = (u16)skb->len; |
600 | tx->len = cpu_to_le16(len); | 592 | tx_cmd->len = cpu_to_le16(len); |
601 | 593 | ||
602 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | 594 | iwl_dbg_log_tx_data_frame(priv, len, hdr); |
603 | iwl_update_stats(priv, true, fc, len); | 595 | iwl_update_stats(priv, true, fc, len); |
604 | tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; | 596 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; |
605 | tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; | 597 | tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; |
606 | 598 | ||
607 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 599 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
608 | txq->need_update = 1; | 600 | txq->need_update = 1; |
@@ -615,9 +607,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
615 | 607 | ||
616 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 608 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", |
617 | le16_to_cpu(out_cmd->hdr.sequence)); | 609 | le16_to_cpu(out_cmd->hdr.sequence)); |
618 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); | 610 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); |
619 | iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); | 611 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); |
620 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, | 612 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, |
621 | ieee80211_hdrlen(fc)); | 613 | ieee80211_hdrlen(fc)); |
622 | 614 | ||
623 | /* | 615 | /* |
@@ -753,7 +745,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
753 | u8 type) | 745 | u8 type) |
754 | { | 746 | { |
755 | struct iwl_spectrum_cmd spectrum; | 747 | struct iwl_spectrum_cmd spectrum; |
756 | struct iwl_rx_packet *res; | 748 | struct iwl_rx_packet *pkt; |
757 | struct iwl_host_cmd cmd = { | 749 | struct iwl_host_cmd cmd = { |
758 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, | 750 | .id = REPLY_SPECTRUM_MEASUREMENT_CMD, |
759 | .data = (void *)&spectrum, | 751 | .data = (void *)&spectrum, |
@@ -798,18 +790,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
798 | if (rc) | 790 | if (rc) |
799 | return rc; | 791 | return rc; |
800 | 792 | ||
801 | res = (struct iwl_rx_packet *)cmd.reply_skb->data; | 793 | pkt = (struct iwl_rx_packet *)cmd.reply_page; |
802 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | 794 | if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { |
803 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); | 795 | IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); |
804 | rc = -EIO; | 796 | rc = -EIO; |
805 | } | 797 | } |
806 | 798 | ||
807 | spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); | 799 | spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status); |
808 | switch (spectrum_resp_status) { | 800 | switch (spectrum_resp_status) { |
809 | case 0: /* Command will be handled */ | 801 | case 0: /* Command will be handled */ |
810 | if (res->u.spectrum.id != 0xff) { | 802 | if (pkt->u.spectrum.id != 0xff) { |
811 | IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", | 803 | IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", |
812 | res->u.spectrum.id); | 804 | pkt->u.spectrum.id); |
813 | priv->measurement_status &= ~MEASUREMENT_READY; | 805 | priv->measurement_status &= ~MEASUREMENT_READY; |
814 | } | 806 | } |
815 | priv->measurement_status |= MEASUREMENT_ACTIVE; | 807 | priv->measurement_status |= MEASUREMENT_ACTIVE; |
@@ -821,7 +813,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
821 | break; | 813 | break; |
822 | } | 814 | } |
823 | 815 | ||
824 | dev_kfree_skb_any(cmd.reply_skb); | 816 | free_pages(cmd.reply_page, priv->hw_params.rx_page_order); |
825 | 817 | ||
826 | return rc; | 818 | return rc; |
827 | } | 819 | } |
@@ -830,7 +822,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv, | |||
830 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, | 822 | static void iwl3945_rx_reply_alive(struct iwl_priv *priv, |
831 | struct iwl_rx_mem_buffer *rxb) | 823 | struct iwl_rx_mem_buffer *rxb) |
832 | { | 824 | { |
833 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 825 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
834 | struct iwl_alive_resp *palive; | 826 | struct iwl_alive_resp *palive; |
835 | struct delayed_work *pwork; | 827 | struct delayed_work *pwork; |
836 | 828 | ||
@@ -867,7 +859,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, | |||
867 | struct iwl_rx_mem_buffer *rxb) | 859 | struct iwl_rx_mem_buffer *rxb) |
868 | { | 860 | { |
869 | #ifdef CONFIG_IWLWIFI_DEBUG | 861 | #ifdef CONFIG_IWLWIFI_DEBUG |
870 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 862 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
871 | #endif | 863 | #endif |
872 | 864 | ||
873 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); | 865 | IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); |
@@ -903,7 +895,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
903 | struct iwl_rx_mem_buffer *rxb) | 895 | struct iwl_rx_mem_buffer *rxb) |
904 | { | 896 | { |
905 | #ifdef CONFIG_IWLWIFI_DEBUG | 897 | #ifdef CONFIG_IWLWIFI_DEBUG |
906 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 898 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
907 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); | 899 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); |
908 | u8 rate = beacon->beacon_notify_hdr.rate; | 900 | u8 rate = beacon->beacon_notify_hdr.rate; |
909 | 901 | ||
@@ -926,7 +918,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
926 | static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, | 918 | static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, |
927 | struct iwl_rx_mem_buffer *rxb) | 919 | struct iwl_rx_mem_buffer *rxb) |
928 | { | 920 | { |
929 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 921 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
930 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); | 922 | u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); |
931 | unsigned long status = priv->status; | 923 | unsigned long status = priv->status; |
932 | 924 | ||
@@ -1090,7 +1082,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1090 | list_del(element); | 1082 | list_del(element); |
1091 | 1083 | ||
1092 | /* Point to Rx buffer via next RBD in circular buffer */ | 1084 | /* Point to Rx buffer via next RBD in circular buffer */ |
1093 | rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr); | 1085 | rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma); |
1094 | rxq->queue[rxq->write] = rxb; | 1086 | rxq->queue[rxq->write] = rxb; |
1095 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 1087 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
1096 | rxq->free_count--; | 1088 | rxq->free_count--; |
@@ -1130,8 +1122,9 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1130 | struct iwl_rx_queue *rxq = &priv->rxq; | 1122 | struct iwl_rx_queue *rxq = &priv->rxq; |
1131 | struct list_head *element; | 1123 | struct list_head *element; |
1132 | struct iwl_rx_mem_buffer *rxb; | 1124 | struct iwl_rx_mem_buffer *rxb; |
1133 | struct sk_buff *skb; | 1125 | struct page *page; |
1134 | unsigned long flags; | 1126 | unsigned long flags; |
1127 | gfp_t gfp_mask = priority; | ||
1135 | 1128 | ||
1136 | while (1) { | 1129 | while (1) { |
1137 | spin_lock_irqsave(&rxq->lock, flags); | 1130 | spin_lock_irqsave(&rxq->lock, flags); |
@@ -1143,10 +1136,14 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1143 | spin_unlock_irqrestore(&rxq->lock, flags); | 1136 | spin_unlock_irqrestore(&rxq->lock, flags); |
1144 | 1137 | ||
1145 | if (rxq->free_count > RX_LOW_WATERMARK) | 1138 | if (rxq->free_count > RX_LOW_WATERMARK) |
1146 | priority |= __GFP_NOWARN; | 1139 | gfp_mask |= __GFP_NOWARN; |
1140 | |||
1141 | if (priv->hw_params.rx_page_order > 0) | ||
1142 | gfp_mask |= __GFP_COMP; | ||
1143 | |||
1147 | /* Alloc a new receive buffer */ | 1144 | /* Alloc a new receive buffer */ |
1148 | skb = alloc_skb(priv->hw_params.rx_buf_size, priority); | 1145 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); |
1149 | if (!skb) { | 1146 | if (!page) { |
1150 | if (net_ratelimit()) | 1147 | if (net_ratelimit()) |
1151 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); | 1148 | IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); |
1152 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | 1149 | if ((rxq->free_count <= RX_LOW_WATERMARK) && |
@@ -1163,7 +1160,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1163 | spin_lock_irqsave(&rxq->lock, flags); | 1160 | spin_lock_irqsave(&rxq->lock, flags); |
1164 | if (list_empty(&rxq->rx_used)) { | 1161 | if (list_empty(&rxq->rx_used)) { |
1165 | spin_unlock_irqrestore(&rxq->lock, flags); | 1162 | spin_unlock_irqrestore(&rxq->lock, flags); |
1166 | dev_kfree_skb_any(skb); | 1163 | __free_pages(page, priv->hw_params.rx_page_order); |
1167 | return; | 1164 | return; |
1168 | } | 1165 | } |
1169 | element = rxq->rx_used.next; | 1166 | element = rxq->rx_used.next; |
@@ -1171,26 +1168,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) | |||
1171 | list_del(element); | 1168 | list_del(element); |
1172 | spin_unlock_irqrestore(&rxq->lock, flags); | 1169 | spin_unlock_irqrestore(&rxq->lock, flags); |
1173 | 1170 | ||
1174 | rxb->skb = skb; | 1171 | rxb->page = page; |
1175 | |||
1176 | /* If radiotap head is required, reserve some headroom here. | ||
1177 | * The physical head count is a variable rx_stats->phy_count. | ||
1178 | * We reserve 4 bytes here. Plus these extra bytes, the | ||
1179 | * headroom of the physical head should be enough for the | ||
1180 | * radiotap head that iwl3945 supported. See iwl3945_rt. | ||
1181 | */ | ||
1182 | skb_reserve(rxb->skb, 4); | ||
1183 | |||
1184 | /* Get physical address of RB/SKB */ | 1172 | /* Get physical address of RB/SKB */ |
1185 | rxb->real_dma_addr = pci_map_single(priv->pci_dev, | 1173 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, |
1186 | rxb->skb->data, | 1174 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1187 | priv->hw_params.rx_buf_size, | 1175 | PCI_DMA_FROMDEVICE); |
1188 | PCI_DMA_FROMDEVICE); | ||
1189 | 1176 | ||
1190 | spin_lock_irqsave(&rxq->lock, flags); | 1177 | spin_lock_irqsave(&rxq->lock, flags); |
1178 | |||
1191 | list_add_tail(&rxb->list, &rxq->rx_free); | 1179 | list_add_tail(&rxb->list, &rxq->rx_free); |
1192 | priv->alloc_rxb_skb++; | ||
1193 | rxq->free_count++; | 1180 | rxq->free_count++; |
1181 | priv->alloc_rxb_page++; | ||
1182 | |||
1194 | spin_unlock_irqrestore(&rxq->lock, flags); | 1183 | spin_unlock_irqrestore(&rxq->lock, flags); |
1195 | } | 1184 | } |
1196 | } | 1185 | } |
@@ -1206,14 +1195,14 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
1206 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | 1195 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { |
1207 | /* In the reset function, these buffers may have been allocated | 1196 | /* In the reset function, these buffers may have been allocated |
1208 | * to an SKB, so we need to unmap and free potential storage */ | 1197 | * to an SKB, so we need to unmap and free potential storage */ |
1209 | if (rxq->pool[i].skb != NULL) { | 1198 | if (rxq->pool[i].page != NULL) { |
1210 | pci_unmap_single(priv->pci_dev, | 1199 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
1211 | rxq->pool[i].real_dma_addr, | 1200 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1212 | priv->hw_params.rx_buf_size, | 1201 | PCI_DMA_FROMDEVICE); |
1213 | PCI_DMA_FROMDEVICE); | 1202 | priv->alloc_rxb_page--; |
1214 | priv->alloc_rxb_skb--; | 1203 | __free_pages(rxq->pool[i].page, |
1215 | dev_kfree_skb(rxq->pool[i].skb); | 1204 | priv->hw_params.rx_page_order); |
1216 | rxq->pool[i].skb = NULL; | 1205 | rxq->pool[i].page = NULL; |
1217 | } | 1206 | } |
1218 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | 1207 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); |
1219 | } | 1208 | } |
@@ -1221,8 +1210,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
1221 | /* Set us so that we have processed and used all buffers, but have | 1210 | /* Set us so that we have processed and used all buffers, but have |
1222 | * not restocked the Rx queue with fresh buffers */ | 1211 | * not restocked the Rx queue with fresh buffers */ |
1223 | rxq->read = rxq->write = 0; | 1212 | rxq->read = rxq->write = 0; |
1224 | rxq->free_count = 0; | ||
1225 | rxq->write_actual = 0; | 1213 | rxq->write_actual = 0; |
1214 | rxq->free_count = 0; | ||
1226 | spin_unlock_irqrestore(&rxq->lock, flags); | 1215 | spin_unlock_irqrestore(&rxq->lock, flags); |
1227 | } | 1216 | } |
1228 | 1217 | ||
@@ -1255,12 +1244,14 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx | |||
1255 | { | 1244 | { |
1256 | int i; | 1245 | int i; |
1257 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | 1246 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { |
1258 | if (rxq->pool[i].skb != NULL) { | 1247 | if (rxq->pool[i].page != NULL) { |
1259 | pci_unmap_single(priv->pci_dev, | 1248 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, |
1260 | rxq->pool[i].real_dma_addr, | 1249 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1261 | priv->hw_params.rx_buf_size, | 1250 | PCI_DMA_FROMDEVICE); |
1262 | PCI_DMA_FROMDEVICE); | 1251 | __free_pages(rxq->pool[i].page, |
1263 | dev_kfree_skb(rxq->pool[i].skb); | 1252 | priv->hw_params.rx_page_order); |
1253 | rxq->pool[i].page = NULL; | ||
1254 | priv->alloc_rxb_page--; | ||
1264 | } | 1255 | } |
1265 | } | 1256 | } |
1266 | 1257 | ||
@@ -1376,7 +1367,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1376 | i = rxq->read; | 1367 | i = rxq->read; |
1377 | 1368 | ||
1378 | /* calculate total frames need to be restock after handling RX */ | 1369 | /* calculate total frames need to be restock after handling RX */ |
1379 | total_empty = r - priv->rxq.write_actual; | 1370 | total_empty = r - rxq->write_actual; |
1380 | if (total_empty < 0) | 1371 | if (total_empty < 0) |
1381 | total_empty += RX_QUEUE_SIZE; | 1372 | total_empty += RX_QUEUE_SIZE; |
1382 | 1373 | ||
@@ -1396,10 +1387,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1396 | 1387 | ||
1397 | rxq->queue[i] = NULL; | 1388 | rxq->queue[i] = NULL; |
1398 | 1389 | ||
1399 | pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, | 1390 | pci_unmap_page(priv->pci_dev, rxb->page_dma, |
1400 | priv->hw_params.rx_buf_size, | 1391 | PAGE_SIZE << priv->hw_params.rx_page_order, |
1401 | PCI_DMA_FROMDEVICE); | 1392 | PCI_DMA_FROMDEVICE); |
1402 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1393 | pkt = rxb_addr(rxb); |
1403 | 1394 | ||
1404 | trace_iwlwifi_dev_rx(priv, pkt, | 1395 | trace_iwlwifi_dev_rx(priv, pkt, |
1405 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | 1396 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
@@ -1420,44 +1411,55 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1420 | if (priv->rx_handlers[pkt->hdr.cmd]) { | 1411 | if (priv->rx_handlers[pkt->hdr.cmd]) { |
1421 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, | 1412 | IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, |
1422 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 1413 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); |
1423 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
1424 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; | 1414 | priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; |
1415 | priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); | ||
1425 | } else { | 1416 | } else { |
1426 | /* No handling needed */ | 1417 | /* No handling needed */ |
1427 | IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n", | 1418 | IWL_DEBUG_RX(priv, |
1419 | "r %d i %d No handler needed for %s, 0x%02x\n", | ||
1428 | r, i, get_cmd_string(pkt->hdr.cmd), | 1420 | r, i, get_cmd_string(pkt->hdr.cmd), |
1429 | pkt->hdr.cmd); | 1421 | pkt->hdr.cmd); |
1430 | } | 1422 | } |
1431 | 1423 | ||
1424 | /* | ||
1425 | * XXX: After here, we should always check rxb->page | ||
1426 | * against NULL before touching it or its virtual | ||
1427 | * memory (pkt). Because some rx_handler might have | ||
1428 | * already taken or freed the pages. | ||
1429 | */ | ||
1430 | |||
1432 | if (reclaim) { | 1431 | if (reclaim) { |
1433 | /* Invoke any callbacks, transfer the skb to caller, and | 1432 | /* Invoke any callbacks, transfer the buffer to caller, |
1434 | * fire off the (possibly) blocking iwl_send_cmd() | 1433 | * and fire off the (possibly) blocking iwl_send_cmd() |
1435 | * as we reclaim the driver command queue */ | 1434 | * as we reclaim the driver command queue */ |
1436 | if (rxb && rxb->skb) | 1435 | if (rxb->page) |
1437 | iwl_tx_cmd_complete(priv, rxb); | 1436 | iwl_tx_cmd_complete(priv, rxb); |
1438 | else | 1437 | else |
1439 | IWL_WARN(priv, "Claim null rxb?\n"); | 1438 | IWL_WARN(priv, "Claim null rxb?\n"); |
1440 | } | 1439 | } |
1441 | 1440 | ||
1442 | /* For now we just don't re-use anything. We can tweak this | 1441 | /* Reuse the page if possible. For notification packets and |
1443 | * later to try and re-use notification packets and SKBs that | 1442 | * SKBs that fail to Rx correctly, add them back into the |
1444 | * fail to Rx correctly */ | 1443 | * rx_free list for reuse later. */ |
1445 | if (rxb->skb != NULL) { | ||
1446 | priv->alloc_rxb_skb--; | ||
1447 | dev_kfree_skb_any(rxb->skb); | ||
1448 | rxb->skb = NULL; | ||
1449 | } | ||
1450 | |||
1451 | spin_lock_irqsave(&rxq->lock, flags); | 1444 | spin_lock_irqsave(&rxq->lock, flags); |
1452 | list_add_tail(&rxb->list, &priv->rxq.rx_used); | 1445 | if (rxb->page != NULL) { |
1446 | rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, | ||
1447 | 0, PAGE_SIZE << priv->hw_params.rx_page_order, | ||
1448 | PCI_DMA_FROMDEVICE); | ||
1449 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
1450 | rxq->free_count++; | ||
1451 | } else | ||
1452 | list_add_tail(&rxb->list, &rxq->rx_used); | ||
1453 | |||
1453 | spin_unlock_irqrestore(&rxq->lock, flags); | 1454 | spin_unlock_irqrestore(&rxq->lock, flags); |
1455 | |||
1454 | i = (i + 1) & RX_QUEUE_MASK; | 1456 | i = (i + 1) & RX_QUEUE_MASK; |
1455 | /* If there are a lot of unused frames, | 1457 | /* If there are a lot of unused frames, |
1456 | * restock the Rx queue so ucode won't assert. */ | 1458 | * restock the Rx queue so ucode won't assert. */ |
1457 | if (fill_rx) { | 1459 | if (fill_rx) { |
1458 | count++; | 1460 | count++; |
1459 | if (count >= 8) { | 1461 | if (count >= 8) { |
1460 | priv->rxq.read = i; | 1462 | rxq->read = i; |
1461 | iwl3945_rx_replenish_now(priv); | 1463 | iwl3945_rx_replenish_now(priv); |
1462 | count = 0; | 1464 | count = 0; |
1463 | } | 1465 | } |
@@ -1465,7 +1467,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1465 | } | 1467 | } |
1466 | 1468 | ||
1467 | /* Backtrack one entry */ | 1469 | /* Backtrack one entry */ |
1468 | priv->rxq.read = i; | 1470 | rxq->read = i; |
1469 | if (fill_rx) | 1471 | if (fill_rx) |
1470 | iwl3945_rx_replenish_now(priv); | 1472 | iwl3945_rx_replenish_now(priv); |
1471 | else | 1473 | else |
@@ -1686,6 +1688,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1686 | } | 1688 | } |
1687 | #endif | 1689 | #endif |
1688 | 1690 | ||
1691 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1692 | |||
1689 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not | 1693 | /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not |
1690 | * atomic, make sure that inta covers all the interrupts that | 1694 | * atomic, make sure that inta covers all the interrupts that |
1691 | * we've discovered, even if FH interrupt came in just after | 1695 | * we've discovered, even if FH interrupt came in just after |
@@ -1707,8 +1711,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1707 | 1711 | ||
1708 | handled |= CSR_INT_BIT_HW_ERR; | 1712 | handled |= CSR_INT_BIT_HW_ERR; |
1709 | 1713 | ||
1710 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1711 | |||
1712 | return; | 1714 | return; |
1713 | } | 1715 | } |
1714 | 1716 | ||
@@ -1800,7 +1802,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv) | |||
1800 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); | 1802 | "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); |
1801 | } | 1803 | } |
1802 | #endif | 1804 | #endif |
1803 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1804 | } | 1805 | } |
1805 | 1806 | ||
1806 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | 1807 | static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, |
@@ -2563,11 +2564,6 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2563 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 2564 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
2564 | STATUS_EXIT_PENDING; | 2565 | STATUS_EXIT_PENDING; |
2565 | 2566 | ||
2566 | priv->cfg->ops->lib->apm_ops.reset(priv); | ||
2567 | spin_lock_irqsave(&priv->lock, flags); | ||
2568 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
2569 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2570 | |||
2571 | iwl3945_hw_txq_ctx_stop(priv); | 2567 | iwl3945_hw_txq_ctx_stop(priv); |
2572 | iwl3945_hw_rxq_stop(priv); | 2568 | iwl3945_hw_rxq_stop(priv); |
2573 | 2569 | ||
@@ -2576,10 +2572,8 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2576 | 2572 | ||
2577 | udelay(5); | 2573 | udelay(5); |
2578 | 2574 | ||
2579 | if (exit_pending) | 2575 | /* Stop the device, and put it in low power state */ |
2580 | priv->cfg->ops->lib->apm_ops.stop(priv); | 2576 | priv->cfg->ops->lib->apm_ops.stop(priv); |
2581 | else | ||
2582 | priv->cfg->ops->lib->apm_ops.reset(priv); | ||
2583 | 2577 | ||
2584 | exit: | 2578 | exit: |
2585 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); | 2579 | memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); |
@@ -2724,19 +2718,34 @@ static void iwl3945_bg_alive_start(struct work_struct *data) | |||
2724 | mutex_unlock(&priv->mutex); | 2718 | mutex_unlock(&priv->mutex); |
2725 | } | 2719 | } |
2726 | 2720 | ||
2721 | /* | ||
2722 | * 3945 cannot interrupt driver when hardware rf kill switch toggles; | ||
2723 | * driver must poll CSR_GP_CNTRL_REG register for change. This register | ||
2724 | * *is* readable even when device has been SW_RESET into low power mode | ||
2725 | * (e.g. during RF KILL). | ||
2726 | */ | ||
2727 | static void iwl3945_rfkill_poll(struct work_struct *data) | 2727 | static void iwl3945_rfkill_poll(struct work_struct *data) |
2728 | { | 2728 | { |
2729 | struct iwl_priv *priv = | 2729 | struct iwl_priv *priv = |
2730 | container_of(data, struct iwl_priv, rfkill_poll.work); | 2730 | container_of(data, struct iwl_priv, rfkill_poll.work); |
2731 | bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2732 | bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL) | ||
2733 | & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); | ||
2731 | 2734 | ||
2732 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | 2735 | if (new_rfkill != old_rfkill) { |
2733 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | 2736 | if (new_rfkill) |
2734 | else | 2737 | set_bit(STATUS_RF_KILL_HW, &priv->status); |
2735 | set_bit(STATUS_RF_KILL_HW, &priv->status); | 2738 | else |
2739 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
2736 | 2740 | ||
2737 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, | 2741 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill); |
2738 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | ||
2739 | 2742 | ||
2743 | IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n", | ||
2744 | new_rfkill ? "disable radio" : "enable radio"); | ||
2745 | } | ||
2746 | |||
2747 | /* Keep this running, even if radio now enabled. This will be | ||
2748 | * cancelled in mac_start() if system decides to start again */ | ||
2740 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, | 2749 | queue_delayed_work(priv->workqueue, &priv->rfkill_poll, |
2741 | round_jiffies_relative(2 * HZ)); | 2750 | round_jiffies_relative(2 * HZ)); |
2742 | 2751 | ||
@@ -3797,7 +3806,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3797 | /* Clear the driver's (not device's) station table */ | 3806 | /* Clear the driver's (not device's) station table */ |
3798 | iwl_clear_stations_table(priv); | 3807 | iwl_clear_stations_table(priv); |
3799 | 3808 | ||
3800 | priv->data_retry_limit = -1; | ||
3801 | priv->ieee_channels = NULL; | 3809 | priv->ieee_channels = NULL; |
3802 | priv->ieee_rates = NULL; | 3810 | priv->ieee_rates = NULL; |
3803 | priv->band = IEEE80211_BAND_2GHZ; | 3811 | priv->band = IEEE80211_BAND_2GHZ; |
@@ -4056,6 +4064,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4056 | &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); | 4064 | &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); |
4057 | iwl3945_setup_deferred_work(priv); | 4065 | iwl3945_setup_deferred_work(priv); |
4058 | iwl3945_setup_rx_handlers(priv); | 4066 | iwl3945_setup_rx_handlers(priv); |
4067 | iwl_power_initialize(priv); | ||
4059 | 4068 | ||
4060 | /********************************* | 4069 | /********************************* |
4061 | * 8. Setup and Register mac80211 | 4070 | * 8. Setup and Register mac80211 |
@@ -4126,6 +4135,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4126 | iwl3945_down(priv); | 4135 | iwl3945_down(priv); |
4127 | } | 4136 | } |
4128 | 4137 | ||
4138 | /* | ||
4139 | * Make sure device is reset to low power before unloading driver. | ||
4140 | * This may be redundant with iwl_down(), but there are paths to | ||
4141 | * run iwl_down() without calling apm_ops.stop(), and there are | ||
4142 | * paths to avoid running iwl_down() at all before leaving driver. | ||
4143 | * This (inexpensive) call *makes sure* device is reset. | ||
4144 | */ | ||
4145 | priv->cfg->ops->lib->apm_ops.stop(priv); | ||
4146 | |||
4129 | /* make sure we flush any pending irq or | 4147 | /* make sure we flush any pending irq or |
4130 | * tasklet for the driver | 4148 | * tasklet for the driver |
4131 | */ | 4149 | */ |
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index a56a2b0ac99a..af72cc746f15 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -404,39 +404,21 @@ static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
404 | { | 404 | { |
405 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 405 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
406 | struct ieee80211_channel *chan = params->channel; | 406 | struct ieee80211_channel *chan = params->channel; |
407 | struct cfg80211_bss *bss; | ||
408 | 407 | ||
409 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) | 408 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) |
410 | return -EIO; | 409 | return -EIO; |
411 | 410 | ||
412 | /* UMAC doesn't support creating IBSS network with specified bssid. | 411 | /* UMAC doesn't support creating or joining an IBSS network |
413 | * This should be removed after we have join only mode supported. */ | 412 | * with specified bssid. */ |
414 | if (params->bssid) | 413 | if (params->bssid) |
415 | return -EOPNOTSUPP; | 414 | return -EOPNOTSUPP; |
416 | 415 | ||
417 | bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, | ||
418 | params->ssid, params->ssid_len); | ||
419 | if (!bss) { | ||
420 | iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len); | ||
421 | schedule_timeout_interruptible(2 * HZ); | ||
422 | bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, | ||
423 | params->ssid, params->ssid_len); | ||
424 | } | ||
425 | /* IBSS join only mode is not supported by UMAC ATM */ | ||
426 | if (bss) { | ||
427 | cfg80211_put_bss(bss); | ||
428 | return -EOPNOTSUPP; | ||
429 | } | ||
430 | |||
431 | iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); | 416 | iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); |
432 | iwm->umac_profile->ibss.band = chan->band; | 417 | iwm->umac_profile->ibss.band = chan->band; |
433 | iwm->umac_profile->ibss.channel = iwm->channel; | 418 | iwm->umac_profile->ibss.channel = iwm->channel; |
434 | iwm->umac_profile->ssid.ssid_len = params->ssid_len; | 419 | iwm->umac_profile->ssid.ssid_len = params->ssid_len; |
435 | memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); | 420 | memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); |
436 | 421 | ||
437 | if (params->bssid) | ||
438 | memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN); | ||
439 | |||
440 | return iwm_send_mlme_profile(iwm); | 422 | return iwm_send_mlme_profile(iwm); |
441 | } | 423 | } |
442 | 424 | ||
@@ -489,12 +471,12 @@ static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) | |||
489 | return 0; | 471 | return 0; |
490 | } | 472 | } |
491 | 473 | ||
474 | if (wpa_version & NL80211_WPA_VERSION_1) | ||
475 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; | ||
476 | |||
492 | if (wpa_version & NL80211_WPA_VERSION_2) | 477 | if (wpa_version & NL80211_WPA_VERSION_2) |
493 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; | 478 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; |
494 | 479 | ||
495 | if (wpa_version & NL80211_WPA_VERSION_1) | ||
496 | iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; | ||
497 | |||
498 | return 0; | 480 | return 0; |
499 | } | 481 | } |
500 | 482 | ||
@@ -645,6 +627,13 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
645 | iwm->default_key = sme->key_idx; | 627 | iwm->default_key = sme->key_idx; |
646 | } | 628 | } |
647 | 629 | ||
630 | /* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */ | ||
631 | if ((iwm->umac_profile->sec.flags & | ||
632 | (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) && | ||
633 | iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) { | ||
634 | iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK; | ||
635 | } | ||
636 | |||
648 | ret = iwm_send_mlme_profile(iwm); | 637 | ret = iwm_send_mlme_profile(iwm); |
649 | 638 | ||
650 | if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || | 639 | if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || |
@@ -681,9 +670,19 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, | |||
681 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, | 670 | static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, |
682 | enum tx_power_setting type, int dbm) | 671 | enum tx_power_setting type, int dbm) |
683 | { | 672 | { |
673 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | ||
674 | int ret; | ||
675 | |||
684 | switch (type) { | 676 | switch (type) { |
685 | case TX_POWER_AUTOMATIC: | 677 | case TX_POWER_AUTOMATIC: |
686 | return 0; | 678 | return 0; |
679 | case TX_POWER_FIXED: | ||
680 | ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, | ||
681 | CFG_TX_PWR_LIMIT_USR, dbm * 2); | ||
682 | if (ret < 0) | ||
683 | return ret; | ||
684 | |||
685 | return iwm_tx_power_trigger(iwm); | ||
687 | default: | 686 | default: |
688 | return -EOPNOTSUPP; | 687 | return -EOPNOTSUPP; |
689 | } | 688 | } |
@@ -695,7 +694,7 @@ static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) | |||
695 | { | 694 | { |
696 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); | 695 | struct iwm_priv *iwm = wiphy_to_iwm(wiphy); |
697 | 696 | ||
698 | *dbm = iwm->txpower; | 697 | *dbm = iwm->txpower >> 1; |
699 | 698 | ||
700 | return 0; | 699 | return 0; |
701 | } | 700 | } |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 23b52fa2605f..cad511afd907 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c | |||
@@ -76,6 +76,11 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, | |||
76 | int ret; | 76 | int ret; |
77 | u8 oid = hdr->oid; | 77 | u8 oid = hdr->oid; |
78 | 78 | ||
79 | if (!test_bit(IWM_STATUS_READY, &iwm->status)) { | ||
80 | IWM_ERR(iwm, "Interface is not ready yet"); | ||
81 | return -EAGAIN; | ||
82 | } | ||
83 | |||
79 | umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; | 84 | umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; |
80 | umac_cmd.resp = resp; | 85 | umac_cmd.resp = resp; |
81 | 86 | ||
@@ -274,6 +279,17 @@ int iwm_send_calib_results(struct iwm_priv *iwm) | |||
274 | return ret; | 279 | return ret; |
275 | } | 280 | } |
276 | 281 | ||
282 | int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit) | ||
283 | { | ||
284 | struct iwm_ct_kill_cfg_cmd cmd; | ||
285 | |||
286 | cmd.entry_threshold = entry; | ||
287 | cmd.exit_threshold = exit; | ||
288 | |||
289 | return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd, | ||
290 | sizeof(struct iwm_ct_kill_cfg_cmd), 0); | ||
291 | } | ||
292 | |||
277 | int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) | 293 | int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) |
278 | { | 294 | { |
279 | struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; | 295 | struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; |
@@ -777,11 +793,24 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) | |||
777 | return ret; | 793 | return ret; |
778 | 794 | ||
779 | ret = wait_event_interruptible_timeout(iwm->mlme_queue, | 795 | ret = wait_event_interruptible_timeout(iwm->mlme_queue, |
780 | (iwm->umac_profile_active == 0), 2 * HZ); | 796 | (iwm->umac_profile_active == 0), 5 * HZ); |
781 | 797 | ||
782 | return ret ? 0 : -EBUSY; | 798 | return ret ? 0 : -EBUSY; |
783 | } | 799 | } |
784 | 800 | ||
801 | int iwm_tx_power_trigger(struct iwm_priv *iwm) | ||
802 | { | ||
803 | struct iwm_umac_pwr_trigger pwr_trigger; | ||
804 | |||
805 | pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER; | ||
806 | pwr_trigger.hdr.buf_size = | ||
807 | cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) - | ||
808 | sizeof(struct iwm_umac_wifi_if)); | ||
809 | |||
810 | |||
811 | return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1); | ||
812 | } | ||
813 | |||
785 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) | 814 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) |
786 | { | 815 | { |
787 | struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; | 816 | struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; |
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index e24d5b633997..b36be2b23a3c 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h | |||
@@ -102,7 +102,6 @@ enum { | |||
102 | CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN, | 102 | CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN, |
103 | CFG_TLC_SUPPORTED_TX_HT_RATES, | 103 | CFG_TLC_SUPPORTED_TX_HT_RATES, |
104 | CFG_TLC_SUPPORTED_TX_RATES, | 104 | CFG_TLC_SUPPORTED_TX_RATES, |
105 | CFG_TLC_VALID_ANTENNA, | ||
106 | CFG_TLC_SPATIAL_STREAM_SUPPORTED, | 105 | CFG_TLC_SPATIAL_STREAM_SUPPORTED, |
107 | CFG_TLC_RETRY_PER_RATE, | 106 | CFG_TLC_RETRY_PER_RATE, |
108 | CFG_TLC_RETRY_PER_HT_RATE, | 107 | CFG_TLC_RETRY_PER_HT_RATE, |
@@ -136,6 +135,10 @@ enum { | |||
136 | CFG_TLC_RENEW_ADDBA_DELAY, | 135 | CFG_TLC_RENEW_ADDBA_DELAY, |
137 | CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD, | 136 | CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD, |
138 | CFG_TLC_IS_STABLE_IN_HT, | 137 | CFG_TLC_IS_STABLE_IN_HT, |
138 | CFG_TLC_SR_SIC_1ST_FAIL, | ||
139 | CFG_TLC_SR_SIC_1ST_PASS, | ||
140 | CFG_TLC_SR_SIC_TOTAL_FAIL, | ||
141 | CFG_TLC_SR_SIC_TOTAL_PASS, | ||
139 | CFG_RLC_CHAIN_CTRL, | 142 | CFG_RLC_CHAIN_CTRL, |
140 | CFG_TRK_TABLE_OP_MODE, | 143 | CFG_TRK_TABLE_OP_MODE, |
141 | CFG_TRK_TABLE_RSSI_THRESHOLD, | 144 | CFG_TRK_TABLE_RSSI_THRESHOLD, |
@@ -147,6 +150,58 @@ enum { | |||
147 | CFG_MLME_DBG_NOTIF_BLOCK, | 150 | CFG_MLME_DBG_NOTIF_BLOCK, |
148 | CFG_BT_OFF_BECONS_INTERVALS, | 151 | CFG_BT_OFF_BECONS_INTERVALS, |
149 | CFG_BT_FRAG_DURATION, | 152 | CFG_BT_FRAG_DURATION, |
153 | CFG_ACTIVE_CHAINS, | ||
154 | CFG_CALIB_CTRL, | ||
155 | CFG_CAPABILITY_SUPPORTED_HT_RATES, | ||
156 | CFG_HT_MAC_PARAM_INFO, | ||
157 | CFG_MIMO_PS_MODE, | ||
158 | CFG_HT_DEFAULT_CAPABILIES_INFO, | ||
159 | CFG_LED_SC_RESOLUTION_FACTOR, | ||
160 | CFG_PTAM_ENERGY_CCK_DET_DEFAULT, | ||
161 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_DEFAULT, | ||
162 | CFG_PTAM_CORR40_4_TH_ADD_MIN_DEFAULT, | ||
163 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_DEFAULT, | ||
164 | CFG_PTAM_CORR32_4_TH_ADD_MIN_DEFAULT, | ||
165 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_DEFAULT, | ||
166 | CFG_PTAM_CORR32_1_TH_ADD_MIN_DEFAULT, | ||
167 | CFG_PTAM_ENERGY_CCK_DET_MIN_VAL, | ||
168 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MIN_VAL, | ||
169 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MIN_VAL, | ||
170 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MIN_VAL, | ||
171 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MIN_VAL, | ||
172 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MIN_VAL, | ||
173 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MIN_VAL, | ||
174 | CFG_PTAM_ENERGY_CCK_DET_MAX_VAL, | ||
175 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MAX_VAL, | ||
176 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MAX_VAL, | ||
177 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MAX_VAL, | ||
178 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MAX_VAL, | ||
179 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MAX_VAL, | ||
180 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MAX_VAL, | ||
181 | CFG_PTAM_ENERGY_CCK_DET_STEP_VAL, | ||
182 | CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_STEP_VAL, | ||
183 | CFG_PTAM_CORR40_4_TH_ADD_MIN_STEP_VAL, | ||
184 | CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_STEP_VAL, | ||
185 | CFG_PTAM_CORR32_4_TH_ADD_MIN_STEP_VAL, | ||
186 | CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_STEP_VAL, | ||
187 | CFG_PTAM_CORR32_1_TH_ADD_MIN_STEP_VAL, | ||
188 | CFG_PTAM_LINK_SENS_FA_OFDM_MAX, | ||
189 | CFG_PTAM_LINK_SENS_FA_OFDM_MIN, | ||
190 | CFG_PTAM_LINK_SENS_FA_CCK_MAX, | ||
191 | CFG_PTAM_LINK_SENS_FA_CCK_MIN, | ||
192 | CFG_PTAM_LINK_SENS_NRG_DIFF, | ||
193 | CFG_PTAM_LINK_SENS_NRG_MARGIN, | ||
194 | CFG_PTAM_LINK_SENS_MAX_NUMBER_OF_TIMES_IN_CCK_NO_FA, | ||
195 | CFG_PTAM_LINK_SENS_AUTO_CORR_MAX_TH_CCK, | ||
196 | CFG_AGG_MGG_TID_LOAD_ADDBA_THRESHOLD, | ||
197 | CFG_AGG_MGG_TID_LOAD_DELBA_THRESHOLD, | ||
198 | CFG_AGG_MGG_ADDBA_BUF_SIZE, | ||
199 | CFG_AGG_MGG_ADDBA_INACTIVE_TIMEOUT, | ||
200 | CFG_AGG_MGG_ADDBA_DEBUG_FLAGS, | ||
201 | CFG_SCAN_PERIODIC_RSSI_HIGH_THRESHOLD, | ||
202 | CFG_SCAN_PERIODIC_COEF_RSSI_HIGH, | ||
203 | CFG_11D_ENABLED, | ||
204 | CFG_11H_FEATURE_FLAGS, | ||
150 | 205 | ||
151 | /* <-- LAST --> */ | 206 | /* <-- LAST --> */ |
152 | CFG_TBL_FIX_LAST | 207 | CFG_TBL_FIX_LAST |
@@ -155,7 +210,8 @@ enum { | |||
155 | /* variable size table */ | 210 | /* variable size table */ |
156 | enum { | 211 | enum { |
157 | CFG_NET_ADDR = 0, | 212 | CFG_NET_ADDR = 0, |
158 | CFG_PROFILE, | 213 | CFG_LED_PATTERN_TABLE, |
214 | |||
159 | /* <-- LAST --> */ | 215 | /* <-- LAST --> */ |
160 | CFG_TBL_VAR_LAST | 216 | CFG_TBL_VAR_LAST |
161 | }; | 217 | }; |
@@ -288,6 +344,9 @@ struct iwm_umac_cmd_scan_request { | |||
288 | /* iwm_umac_security.flag is WSC mode on -- bits [2:2] */ | 344 | /* iwm_umac_security.flag is WSC mode on -- bits [2:2] */ |
289 | #define UMAC_SEC_FLG_WSC_ON_POS 2 | 345 | #define UMAC_SEC_FLG_WSC_ON_POS 2 |
290 | #define UMAC_SEC_FLG_WSC_ON_SEED 1 | 346 | #define UMAC_SEC_FLG_WSC_ON_SEED 1 |
347 | #define UMAC_SEC_FLG_WSC_ON_MSK (UMAC_SEC_FLG_WSC_ON_SEED << \ | ||
348 | UMAC_SEC_FLG_WSC_ON_POS) | ||
349 | |||
291 | 350 | ||
292 | /* Legacy profile can use only WEP40 and WEP104 for encryption and | 351 | /* Legacy profile can use only WEP40 and WEP104 for encryption and |
293 | * OPEN or PSK for authentication */ | 352 | * OPEN or PSK for authentication */ |
@@ -382,6 +441,11 @@ struct iwm_umac_tx_key_id { | |||
382 | u8 reserved[3]; | 441 | u8 reserved[3]; |
383 | } __attribute__ ((packed)); | 442 | } __attribute__ ((packed)); |
384 | 443 | ||
444 | struct iwm_umac_pwr_trigger { | ||
445 | struct iwm_umac_wifi_if hdr; | ||
446 | __le32 reseved; | ||
447 | } __attribute__ ((packed)); | ||
448 | |||
385 | struct iwm_umac_cmd_stats_req { | 449 | struct iwm_umac_cmd_stats_req { |
386 | __le32 flags; | 450 | __le32 flags; |
387 | } __attribute__ ((packed)); | 451 | } __attribute__ ((packed)); |
@@ -393,6 +457,7 @@ int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); | |||
393 | int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); | 457 | int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); |
394 | int iwm_send_calib_results(struct iwm_priv *iwm); | 458 | int iwm_send_calib_results(struct iwm_priv *iwm); |
395 | int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); | 459 | int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); |
460 | int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit); | ||
396 | 461 | ||
397 | /* UMAC commands */ | 462 | /* UMAC commands */ |
398 | int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, | 463 | int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, |
@@ -407,6 +472,7 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); | |||
407 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); | 472 | int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); |
408 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); | 473 | int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); |
409 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); | 474 | int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); |
475 | int iwm_tx_power_trigger(struct iwm_priv *iwm); | ||
410 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); | 476 | int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); |
411 | int iwm_send_umac_channel_list(struct iwm_priv *iwm); | 477 | int iwm_send_umac_channel_list(struct iwm_priv *iwm); |
412 | int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, | 478 | int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, |
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index 6b0bcad758ca..49067092d336 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c | |||
@@ -217,6 +217,13 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name) | |||
217 | IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date), | 217 | IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date), |
218 | IWM_BUILD_DAY(build_date)); | 218 | IWM_BUILD_DAY(build_date)); |
219 | 219 | ||
220 | if (!strcmp(img_name, iwm->bus_ops->umac_name)) | ||
221 | sprintf(iwm->umac_version, "%02X.%02X", | ||
222 | ver->major, ver->minor); | ||
223 | |||
224 | if (!strcmp(img_name, iwm->bus_ops->lmac_name)) | ||
225 | sprintf(iwm->lmac_version, "%02X.%02X", | ||
226 | ver->major, ver->minor); | ||
220 | 227 | ||
221 | err_release_fw: | 228 | err_release_fw: |
222 | release_firmware(fw); | 229 | release_firmware(fw); |
@@ -398,6 +405,8 @@ int iwm_load_fw(struct iwm_priv *iwm) | |||
398 | iwm_send_prio_table(iwm); | 405 | iwm_send_prio_table(iwm); |
399 | iwm_send_calib_results(iwm); | 406 | iwm_send_calib_results(iwm); |
400 | iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); | 407 | iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); |
408 | iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry, | ||
409 | iwm->conf.ct_kill_exit); | ||
401 | 410 | ||
402 | return 0; | 411 | return 0; |
403 | 412 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 1b02a4e2a1ac..a9bf6bc97bea 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -65,6 +65,8 @@ struct iwm_conf { | |||
65 | u32 sdio_ior_timeout; | 65 | u32 sdio_ior_timeout; |
66 | unsigned long calib_map; | 66 | unsigned long calib_map; |
67 | unsigned long expected_calib_map; | 67 | unsigned long expected_calib_map; |
68 | u8 ct_kill_entry; | ||
69 | u8 ct_kill_exit; | ||
68 | bool reset_on_fatal_err; | 70 | bool reset_on_fatal_err; |
69 | bool auto_connect; | 71 | bool auto_connect; |
70 | bool wimax_not_present; | 72 | bool wimax_not_present; |
@@ -276,12 +278,14 @@ struct iwm_priv { | |||
276 | struct iw_statistics wstats; | 278 | struct iw_statistics wstats; |
277 | struct delayed_work stats_request; | 279 | struct delayed_work stats_request; |
278 | struct delayed_work disconnect; | 280 | struct delayed_work disconnect; |
281 | struct delayed_work ct_kill_delay; | ||
279 | 282 | ||
280 | struct iwm_debugfs dbg; | 283 | struct iwm_debugfs dbg; |
281 | 284 | ||
282 | u8 *eeprom; | 285 | u8 *eeprom; |
283 | struct timer_list watchdog; | 286 | struct timer_list watchdog; |
284 | struct work_struct reset_worker; | 287 | struct work_struct reset_worker; |
288 | struct work_struct auth_retry_worker; | ||
285 | struct mutex mutex; | 289 | struct mutex mutex; |
286 | 290 | ||
287 | u8 *req_ie; | 291 | u8 *req_ie; |
@@ -290,6 +294,8 @@ struct iwm_priv { | |||
290 | int resp_ie_len; | 294 | int resp_ie_len; |
291 | 295 | ||
292 | struct iwm_fw_error_hdr *last_fw_err; | 296 | struct iwm_fw_error_hdr *last_fw_err; |
297 | char umac_version[8]; | ||
298 | char lmac_version[8]; | ||
293 | 299 | ||
294 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 300 | char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); |
295 | }; | 301 | }; |
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h index 6c1a14c4480f..a3a79b5e2898 100644 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h | |||
@@ -187,6 +187,14 @@ struct iwm_coex_prio_table_cmd { | |||
187 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ | 187 | COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ |
188 | COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) | 188 | COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) |
189 | 189 | ||
190 | /* CT kill config command */ | ||
191 | struct iwm_ct_kill_cfg_cmd { | ||
192 | u32 exit_threshold; | ||
193 | u32 reserved; | ||
194 | u32 entry_threshold; | ||
195 | } __attribute__ ((packed)); | ||
196 | |||
197 | |||
190 | /* LMAC OP CODES */ | 198 | /* LMAC OP CODES */ |
191 | #define REPLY_PAD 0x0 | 199 | #define REPLY_PAD 0x0 |
192 | #define REPLY_ALIVE 0x1 | 200 | #define REPLY_ALIVE 0x1 |
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 170f33706490..f93e9139b0f2 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -63,6 +63,8 @@ static struct iwm_conf def_iwm_conf = { | |||
63 | BIT(PHY_CALIBRATE_TX_IQ_CMD) | | 63 | BIT(PHY_CALIBRATE_TX_IQ_CMD) | |
64 | BIT(PHY_CALIBRATE_RX_IQ_CMD) | | 64 | BIT(PHY_CALIBRATE_RX_IQ_CMD) | |
65 | BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), | 65 | BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), |
66 | .ct_kill_entry = 110, | ||
67 | .ct_kill_exit = 110, | ||
66 | .reset_on_fatal_err = 1, | 68 | .reset_on_fatal_err = 1, |
67 | .auto_connect = 1, | 69 | .auto_connect = 1, |
68 | .wimax_not_present = 0, | 70 | .wimax_not_present = 0, |
@@ -133,6 +135,17 @@ static void iwm_disconnect_work(struct work_struct *work) | |||
133 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); | 135 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); |
134 | } | 136 | } |
135 | 137 | ||
138 | static void iwm_ct_kill_work(struct work_struct *work) | ||
139 | { | ||
140 | struct iwm_priv *iwm = | ||
141 | container_of(work, struct iwm_priv, ct_kill_delay.work); | ||
142 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | ||
143 | |||
144 | IWM_INFO(iwm, "CT kill delay timeout\n"); | ||
145 | |||
146 | wiphy_rfkill_set_hw_state(wiphy, false); | ||
147 | } | ||
148 | |||
136 | static int __iwm_up(struct iwm_priv *iwm); | 149 | static int __iwm_up(struct iwm_priv *iwm); |
137 | static int __iwm_down(struct iwm_priv *iwm); | 150 | static int __iwm_down(struct iwm_priv *iwm); |
138 | 151 | ||
@@ -194,6 +207,33 @@ static void iwm_reset_worker(struct work_struct *work) | |||
194 | mutex_unlock(&iwm->mutex); | 207 | mutex_unlock(&iwm->mutex); |
195 | } | 208 | } |
196 | 209 | ||
210 | static void iwm_auth_retry_worker(struct work_struct *work) | ||
211 | { | ||
212 | struct iwm_priv *iwm; | ||
213 | int i, ret; | ||
214 | |||
215 | iwm = container_of(work, struct iwm_priv, auth_retry_worker); | ||
216 | if (iwm->umac_profile_active) { | ||
217 | ret = iwm_invalidate_mlme_profile(iwm); | ||
218 | if (ret < 0) | ||
219 | return; | ||
220 | } | ||
221 | |||
222 | iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; | ||
223 | |||
224 | ret = iwm_send_mlme_profile(iwm); | ||
225 | if (ret < 0) | ||
226 | return; | ||
227 | |||
228 | for (i = 0; i < IWM_NUM_KEYS; i++) | ||
229 | if (iwm->keys[i].key_len) | ||
230 | iwm_set_key(iwm, 0, &iwm->keys[i]); | ||
231 | |||
232 | iwm_set_tx_key(iwm, iwm->default_key); | ||
233 | } | ||
234 | |||
235 | |||
236 | |||
197 | static void iwm_watchdog(unsigned long data) | 237 | static void iwm_watchdog(unsigned long data) |
198 | { | 238 | { |
199 | struct iwm_priv *iwm = (struct iwm_priv *)data; | 239 | struct iwm_priv *iwm = (struct iwm_priv *)data; |
@@ -225,7 +265,9 @@ int iwm_priv_init(struct iwm_priv *iwm) | |||
225 | iwm->scan_id = 1; | 265 | iwm->scan_id = 1; |
226 | INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); | 266 | INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); |
227 | INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); | 267 | INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); |
268 | INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work); | ||
228 | INIT_WORK(&iwm->reset_worker, iwm_reset_worker); | 269 | INIT_WORK(&iwm->reset_worker, iwm_reset_worker); |
270 | INIT_WORK(&iwm->auth_retry_worker, iwm_auth_retry_worker); | ||
229 | INIT_LIST_HEAD(&iwm->bss_list); | 271 | INIT_LIST_HEAD(&iwm->bss_list); |
230 | 272 | ||
231 | skb_queue_head_init(&iwm->rx_list); | 273 | skb_queue_head_init(&iwm->rx_list); |
@@ -586,6 +628,7 @@ static int __iwm_up(struct iwm_priv *iwm) | |||
586 | { | 628 | { |
587 | int ret; | 629 | int ret; |
588 | struct iwm_notif *notif_reboot, *notif_ack = NULL; | 630 | struct iwm_notif *notif_reboot, *notif_ack = NULL; |
631 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | ||
589 | 632 | ||
590 | ret = iwm_bus_enable(iwm); | 633 | ret = iwm_bus_enable(iwm); |
591 | if (ret) { | 634 | if (ret) { |
@@ -647,6 +690,9 @@ static int __iwm_up(struct iwm_priv *iwm) | |||
647 | goto err_disable; | 690 | goto err_disable; |
648 | } | 691 | } |
649 | 692 | ||
693 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s", | ||
694 | iwm->lmac_version, iwm->umac_version); | ||
695 | |||
650 | /* We configure the UMAC and enable the wifi module */ | 696 | /* We configure the UMAC and enable the wifi module */ |
651 | ret = iwm_send_umac_config(iwm, | 697 | ret = iwm_send_umac_config(iwm, |
652 | cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) | | 698 | cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) | |
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 35ec006c2d2c..4f8dbdd7b917 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c | |||
@@ -152,6 +152,7 @@ void iwm_if_free(struct iwm_priv *iwm) | |||
152 | if (!iwm_to_ndev(iwm)) | 152 | if (!iwm_to_ndev(iwm)) |
153 | return; | 153 | return; |
154 | 154 | ||
155 | cancel_delayed_work_sync(&iwm->ct_kill_delay); | ||
155 | free_netdev(iwm_to_ndev(iwm)); | 156 | free_netdev(iwm_to_ndev(iwm)); |
156 | iwm_priv_deinit(iwm); | 157 | iwm_priv_deinit(iwm); |
157 | kfree(iwm->umac_profile); | 158 | kfree(iwm->umac_profile); |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 40dbcbc16593..3ad95dc0dd8d 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -422,7 +422,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, | |||
422 | if (IS_ERR(ticket_node)) | 422 | if (IS_ERR(ticket_node)) |
423 | return PTR_ERR(ticket_node); | 423 | return PTR_ERR(ticket_node); |
424 | 424 | ||
425 | IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", | 425 | IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", |
426 | ticket->action == IWM_RX_TICKET_RELEASE ? | ||
427 | "RELEASE" : "DROP", | ||
426 | ticket->id); | 428 | ticket->id); |
427 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); | 429 | list_add_tail(&ticket_node->node, &iwm->rx_tickets); |
428 | 430 | ||
@@ -499,6 +501,18 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, | |||
499 | return 0; | 501 | return 0; |
500 | } | 502 | } |
501 | 503 | ||
504 | static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm) | ||
505 | { | ||
506 | if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 || | ||
507 | iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) && | ||
508 | (iwm->umac_profile->sec.ucast_cipher == | ||
509 | iwm->umac_profile->sec.mcast_cipher) && | ||
510 | (iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN)) | ||
511 | return 1; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
502 | static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | 516 | static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, |
503 | unsigned long buf_size, | 517 | unsigned long buf_size, |
504 | struct iwm_wifi_cmd *cmd) | 518 | struct iwm_wifi_cmd *cmd) |
@@ -564,11 +578,17 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
564 | goto ibss; | 578 | goto ibss; |
565 | 579 | ||
566 | if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) | 580 | if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) |
567 | cfg80211_connect_result(iwm_to_ndev(iwm), | 581 | if (!iwm_is_open_wep_profile(iwm)) { |
568 | complete->bssid, | 582 | cfg80211_connect_result(iwm_to_ndev(iwm), |
569 | NULL, 0, NULL, 0, | 583 | complete->bssid, |
570 | WLAN_STATUS_UNSPECIFIED_FAILURE, | 584 | NULL, 0, NULL, 0, |
571 | GFP_KERNEL); | 585 | WLAN_STATUS_UNSPECIFIED_FAILURE, |
586 | GFP_KERNEL); | ||
587 | } else { | ||
588 | /* Let's try shared WEP auth */ | ||
589 | IWM_ERR(iwm, "Trying WEP shared auth\n"); | ||
590 | schedule_work(&iwm->auth_retry_worker); | ||
591 | } | ||
572 | else | 592 | else |
573 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, | 593 | cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, |
574 | GFP_KERNEL); | 594 | GFP_KERNEL); |
@@ -712,6 +732,19 @@ static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf, | |||
712 | return 0; | 732 | return 0; |
713 | } | 733 | } |
714 | 734 | ||
735 | static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf, | ||
736 | unsigned long buf_size, | ||
737 | struct iwm_wifi_cmd *cmd) | ||
738 | { | ||
739 | struct wiphy *wiphy = iwm_to_wiphy(iwm); | ||
740 | |||
741 | IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n"); | ||
742 | |||
743 | wiphy_rfkill_set_hw_state(wiphy, true); | ||
744 | |||
745 | return 0; | ||
746 | } | ||
747 | |||
715 | static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | 748 | static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, |
716 | unsigned long buf_size, | 749 | unsigned long buf_size, |
717 | struct iwm_wifi_cmd *cmd) | 750 | struct iwm_wifi_cmd *cmd) |
@@ -898,6 +931,8 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, | |||
898 | case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: | 931 | case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: |
899 | IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); | 932 | IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); |
900 | break; | 933 | break; |
934 | case WIFI_IF_NTFY_RADIO_PREEMPTION: | ||
935 | return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd); | ||
901 | case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: | 936 | case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: |
902 | return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); | 937 | return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); |
903 | case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: | 938 | case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: |
@@ -1055,8 +1090,14 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | |||
1055 | unsigned long buf_size, | 1090 | unsigned long buf_size, |
1056 | struct iwm_wifi_cmd *cmd) | 1091 | struct iwm_wifi_cmd *cmd) |
1057 | { | 1092 | { |
1058 | struct iwm_umac_wifi_if *hdr = | 1093 | struct iwm_umac_wifi_if *hdr; |
1059 | (struct iwm_umac_wifi_if *)cmd->buf.payload; | 1094 | |
1095 | if (cmd == NULL) { | ||
1096 | IWM_ERR(iwm, "Couldn't find expected wifi command\n"); | ||
1097 | return -EINVAL; | ||
1098 | } | ||
1099 | |||
1100 | hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload; | ||
1060 | 1101 | ||
1061 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " | 1102 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " |
1062 | "oid is 0x%x\n", hdr->oid); | 1103 | "oid is 0x%x\n", hdr->oid); |
@@ -1078,6 +1119,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | |||
1078 | return 0; | 1119 | return 0; |
1079 | } | 1120 | } |
1080 | 1121 | ||
1122 | #define CT_KILL_DELAY (30 * HZ) | ||
1081 | static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, | 1123 | static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, |
1082 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) | 1124 | unsigned long buf_size, struct iwm_wifi_cmd *cmd) |
1083 | { | 1125 | { |
@@ -1090,7 +1132,20 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, | |||
1090 | flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", | 1132 | flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", |
1091 | flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); | 1133 | flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); |
1092 | 1134 | ||
1093 | wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED); | 1135 | if (flags & IWM_CARD_STATE_CTKILL_DISABLED) { |
1136 | /* | ||
1137 | * We got a CTKILL event: We bring the interface down in | ||
1138 | * oder to cool the device down, and try to bring it up | ||
1139 | * 30 seconds later. If it's still too hot, we'll go through | ||
1140 | * this code path again. | ||
1141 | */ | ||
1142 | cancel_delayed_work_sync(&iwm->ct_kill_delay); | ||
1143 | schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY); | ||
1144 | } | ||
1145 | |||
1146 | wiphy_rfkill_set_hw_state(wiphy, flags & | ||
1147 | (IWM_CARD_STATE_HW_DISABLED | | ||
1148 | IWM_CARD_STATE_CTKILL_DISABLED)); | ||
1094 | 1149 | ||
1095 | return 0; | 1150 | return 0; |
1096 | } | 1151 | } |
@@ -1281,6 +1336,14 @@ int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size) | |||
1281 | 1336 | ||
1282 | switch (le32_to_cpu(hdr->cmd)) { | 1337 | switch (le32_to_cpu(hdr->cmd)) { |
1283 | case UMAC_REBOOT_BARKER: | 1338 | case UMAC_REBOOT_BARKER: |
1339 | if (test_bit(IWM_STATUS_READY, &iwm->status)) { | ||
1340 | IWM_ERR(iwm, "Unexpected BARKER\n"); | ||
1341 | |||
1342 | schedule_work(&iwm->reset_worker); | ||
1343 | |||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1284 | return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, | 1347 | return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, |
1285 | IWM_SRC_UDMA, buf, buf_size); | 1348 | IWM_SRC_UDMA, buf, buf_size); |
1286 | case UMAC_ACK_BARKER: | 1349 | case UMAC_ACK_BARKER: |
@@ -1443,7 +1506,8 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, | |||
1443 | } | 1506 | } |
1444 | break; | 1507 | break; |
1445 | case IWM_RX_TICKET_DROP: | 1508 | case IWM_RX_TICKET_DROP: |
1446 | IWM_DBG_RX(iwm, DBG, "DROP packet\n"); | 1509 | IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n", |
1510 | le16_to_cpu(ticket_node->ticket->flags)); | ||
1447 | kfree_skb(packet->skb); | 1511 | kfree_skb(packet->skb); |
1448 | break; | 1512 | break; |
1449 | default: | 1513 | default: |
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index 8b1de84003ca..cf86294f719b 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c | |||
@@ -224,8 +224,6 @@ static int if_sdio_disable(struct iwm_priv *iwm) | |||
224 | struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); | 224 | struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); |
225 | int ret; | 225 | int ret; |
226 | 226 | ||
227 | iwm_reset(iwm); | ||
228 | |||
229 | sdio_claim_host(hw->func); | 227 | sdio_claim_host(hw->func); |
230 | sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret); | 228 | sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret); |
231 | if (ret < 0) | 229 | if (ret < 0) |
@@ -237,6 +235,8 @@ static int if_sdio_disable(struct iwm_priv *iwm) | |||
237 | 235 | ||
238 | iwm_sdio_rx_free(hw); | 236 | iwm_sdio_rx_free(hw); |
239 | 237 | ||
238 | iwm_reset(iwm); | ||
239 | |||
240 | IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n"); | 240 | IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n"); |
241 | 241 | ||
242 | return 0; | 242 | return 0; |
@@ -493,8 +493,10 @@ static void iwm_sdio_remove(struct sdio_func *func) | |||
493 | } | 493 | } |
494 | 494 | ||
495 | static const struct sdio_device_id iwm_sdio_ids[] = { | 495 | static const struct sdio_device_id iwm_sdio_ids[] = { |
496 | { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, | 496 | /* Global/AGN SKU */ |
497 | SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) }, | 497 | { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1403) }, |
498 | /* BGN SKU */ | ||
499 | { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1408) }, | ||
498 | { /* end: all zeroes */ }, | 500 | { /* end: all zeroes */ }, |
499 | }; | 501 | }; |
500 | MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); | 502 | MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); |
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index c5a14ae3160a..be903543bb47 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h | |||
@@ -687,6 +687,9 @@ struct iwm_umac_notif_rx_ticket { | |||
687 | /* Tx/Rx rates window (number of max of last update window per second) */ | 687 | /* Tx/Rx rates window (number of max of last update window per second) */ |
688 | #define UMAC_NTF_RATE_SAMPLE_NR 4 | 688 | #define UMAC_NTF_RATE_SAMPLE_NR 4 |
689 | 689 | ||
690 | /* Max numbers of bits required to go through all antennae in bitmasks */ | ||
691 | #define UMAC_PHY_NUM_CHAINS 3 | ||
692 | |||
690 | #define IWM_UMAC_MGMT_TID 8 | 693 | #define IWM_UMAC_MGMT_TID 8 |
691 | #define IWM_UMAC_TID_NR 8 | 694 | #define IWM_UMAC_TID_NR 8 |
692 | 695 | ||
@@ -697,9 +700,11 @@ struct iwm_umac_notif_stats { | |||
697 | __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */ | 700 | __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */ |
698 | __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; | 701 | __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; |
699 | __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; | 702 | __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; |
703 | __le32 chain_energy[UMAC_PHY_NUM_CHAINS]; | ||
700 | s32 rssi_dbm; | 704 | s32 rssi_dbm; |
701 | s32 noise_dbm; | 705 | s32 noise_dbm; |
702 | __le32 supp_rates; | 706 | __le32 supp_rates; |
707 | __le32 supp_ht_rates; | ||
703 | __le32 missed_beacons; | 708 | __le32 missed_beacons; |
704 | __le32 rx_beacons; | 709 | __le32 rx_beacons; |
705 | __le32 rx_dir_pkts; | 710 | __le32 rx_dir_pkts; |
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c deleted file mode 100644 index 5c6968101f0d..000000000000 --- a/drivers/net/wireless/libertas/11d.c +++ /dev/null | |||
@@ -1,696 +0,0 @@ | |||
1 | /** | ||
2 | * This file contains functions for 802.11D. | ||
3 | */ | ||
4 | #include <linux/ctype.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/wireless.h> | ||
7 | |||
8 | #include "host.h" | ||
9 | #include "decl.h" | ||
10 | #include "11d.h" | ||
11 | #include "dev.h" | ||
12 | #include "wext.h" | ||
13 | |||
14 | #define TX_PWR_DEFAULT 10 | ||
15 | |||
16 | static struct region_code_mapping region_code_mapping[] = { | ||
17 | {"US ", 0x10}, /* US FCC */ | ||
18 | {"CA ", 0x10}, /* IC Canada */ | ||
19 | {"SG ", 0x10}, /* Singapore */ | ||
20 | {"EU ", 0x30}, /* ETSI */ | ||
21 | {"AU ", 0x30}, /* Australia */ | ||
22 | {"KR ", 0x30}, /* Republic Of Korea */ | ||
23 | {"ES ", 0x31}, /* Spain */ | ||
24 | {"FR ", 0x32}, /* France */ | ||
25 | {"JP ", 0x40}, /* Japan */ | ||
26 | }; | ||
27 | |||
28 | /* Following 2 structure defines the supported channels */ | ||
29 | static struct chan_freq_power channel_freq_power_UN_BG[] = { | ||
30 | {1, 2412, TX_PWR_DEFAULT}, | ||
31 | {2, 2417, TX_PWR_DEFAULT}, | ||
32 | {3, 2422, TX_PWR_DEFAULT}, | ||
33 | {4, 2427, TX_PWR_DEFAULT}, | ||
34 | {5, 2432, TX_PWR_DEFAULT}, | ||
35 | {6, 2437, TX_PWR_DEFAULT}, | ||
36 | {7, 2442, TX_PWR_DEFAULT}, | ||
37 | {8, 2447, TX_PWR_DEFAULT}, | ||
38 | {9, 2452, TX_PWR_DEFAULT}, | ||
39 | {10, 2457, TX_PWR_DEFAULT}, | ||
40 | {11, 2462, TX_PWR_DEFAULT}, | ||
41 | {12, 2467, TX_PWR_DEFAULT}, | ||
42 | {13, 2472, TX_PWR_DEFAULT}, | ||
43 | {14, 2484, TX_PWR_DEFAULT} | ||
44 | }; | ||
45 | |||
46 | static u8 lbs_region_2_code(u8 *region) | ||
47 | { | ||
48 | u8 i; | ||
49 | |||
50 | for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++) | ||
51 | region[i] = toupper(region[i]); | ||
52 | |||
53 | for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { | ||
54 | if (!memcmp(region, region_code_mapping[i].region, | ||
55 | COUNTRY_CODE_LEN)) | ||
56 | return (region_code_mapping[i].code); | ||
57 | } | ||
58 | |||
59 | /* default is US */ | ||
60 | return (region_code_mapping[0].code); | ||
61 | } | ||
62 | |||
63 | static u8 *lbs_code_2_region(u8 code) | ||
64 | { | ||
65 | u8 i; | ||
66 | |||
67 | for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { | ||
68 | if (region_code_mapping[i].code == code) | ||
69 | return (region_code_mapping[i].region); | ||
70 | } | ||
71 | /* default is US */ | ||
72 | return (region_code_mapping[0].region); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * @brief This function finds the nrchan-th chan after the firstchan | ||
77 | * @param band band | ||
78 | * @param firstchan first channel number | ||
79 | * @param nrchan number of channels | ||
80 | * @return the nrchan-th chan number | ||
81 | */ | ||
82 | static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan) | ||
83 | /*find the nrchan-th chan after the firstchan*/ | ||
84 | { | ||
85 | u8 i; | ||
86 | struct chan_freq_power *cfp; | ||
87 | u8 cfp_no; | ||
88 | |||
89 | cfp = channel_freq_power_UN_BG; | ||
90 | cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG); | ||
91 | |||
92 | for (i = 0; i < cfp_no; i++) { | ||
93 | if ((cfp + i)->channel == firstchan) { | ||
94 | lbs_deb_11d("firstchan found\n"); | ||
95 | break; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | if (i < cfp_no) { | ||
100 | /*if beyond the boundary */ | ||
101 | if (i + nrchan < cfp_no) { | ||
102 | *chan = (cfp + i + nrchan)->channel; | ||
103 | return 1; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * @brief This function Checks if chan txpwr is learned from AP/IBSS | ||
112 | * @param chan chan number | ||
113 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
114 | * @return TRUE; FALSE | ||
115 | */ | ||
116 | static u8 lbs_channel_known_11d(u8 chan, | ||
117 | struct parsed_region_chan_11d * parsed_region_chan) | ||
118 | { | ||
119 | struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr; | ||
120 | u8 nr_chan = parsed_region_chan->nr_chan; | ||
121 | u8 i = 0; | ||
122 | |||
123 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr, | ||
124 | sizeof(struct chan_power_11d) * nr_chan); | ||
125 | |||
126 | for (i = 0; i < nr_chan; i++) { | ||
127 | if (chan == chanpwr[i].chan) { | ||
128 | lbs_deb_11d("found chan %d\n", chan); | ||
129 | return 1; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | lbs_deb_11d("chan %d not found\n", chan); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | u32 lbs_chan_2_freq(u8 chan) | ||
138 | { | ||
139 | struct chan_freq_power *cf; | ||
140 | u16 i; | ||
141 | u32 freq = 0; | ||
142 | |||
143 | cf = channel_freq_power_UN_BG; | ||
144 | |||
145 | for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) { | ||
146 | if (chan == cf[i].channel) | ||
147 | freq = cf[i].freq; | ||
148 | } | ||
149 | |||
150 | return freq; | ||
151 | } | ||
152 | |||
153 | static int generate_domain_info_11d(struct parsed_region_chan_11d | ||
154 | *parsed_region_chan, | ||
155 | struct lbs_802_11d_domain_reg *domaininfo) | ||
156 | { | ||
157 | u8 nr_subband = 0; | ||
158 | |||
159 | u8 nr_chan = parsed_region_chan->nr_chan; | ||
160 | u8 nr_parsedchan = 0; | ||
161 | |||
162 | u8 firstchan = 0, nextchan = 0, maxpwr = 0; | ||
163 | |||
164 | u8 i, flag = 0; | ||
165 | |||
166 | memcpy(domaininfo->countrycode, parsed_region_chan->countrycode, | ||
167 | COUNTRY_CODE_LEN); | ||
168 | |||
169 | lbs_deb_11d("nrchan %d\n", nr_chan); | ||
170 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan, | ||
171 | sizeof(struct parsed_region_chan_11d)); | ||
172 | |||
173 | for (i = 0; i < nr_chan; i++) { | ||
174 | if (!flag) { | ||
175 | flag = 1; | ||
176 | nextchan = firstchan = | ||
177 | parsed_region_chan->chanpwr[i].chan; | ||
178 | maxpwr = parsed_region_chan->chanpwr[i].pwr; | ||
179 | nr_parsedchan = 1; | ||
180 | continue; | ||
181 | } | ||
182 | |||
183 | if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 && | ||
184 | parsed_region_chan->chanpwr[i].pwr == maxpwr) { | ||
185 | nextchan++; | ||
186 | nr_parsedchan++; | ||
187 | } else { | ||
188 | domaininfo->subband[nr_subband].firstchan = firstchan; | ||
189 | domaininfo->subband[nr_subband].nrchan = | ||
190 | nr_parsedchan; | ||
191 | domaininfo->subband[nr_subband].maxtxpwr = maxpwr; | ||
192 | nr_subband++; | ||
193 | nextchan = firstchan = | ||
194 | parsed_region_chan->chanpwr[i].chan; | ||
195 | maxpwr = parsed_region_chan->chanpwr[i].pwr; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | if (flag) { | ||
200 | domaininfo->subband[nr_subband].firstchan = firstchan; | ||
201 | domaininfo->subband[nr_subband].nrchan = nr_parsedchan; | ||
202 | domaininfo->subband[nr_subband].maxtxpwr = maxpwr; | ||
203 | nr_subband++; | ||
204 | } | ||
205 | domaininfo->nr_subband = nr_subband; | ||
206 | |||
207 | lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); | ||
208 | lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo, | ||
209 | COUNTRY_CODE_LEN + 1 + | ||
210 | sizeof(struct ieee_subbandset) * nr_subband); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS | ||
216 | * @param region_chan pointer to struct region_channel | ||
217 | * @param *parsed_region_chan pointer to parsed_region_chan_11d | ||
218 | * @return N/A | ||
219 | */ | ||
220 | static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan, | ||
221 | struct parsed_region_chan_11d * | ||
222 | parsed_region_chan) | ||
223 | { | ||
224 | u8 i; | ||
225 | struct chan_freq_power *cfp; | ||
226 | |||
227 | if (region_chan == NULL) { | ||
228 | lbs_deb_11d("region_chan is NULL\n"); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | cfp = region_chan->CFP; | ||
233 | if (cfp == NULL) { | ||
234 | lbs_deb_11d("cfp is NULL \n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | parsed_region_chan->band = region_chan->band; | ||
239 | parsed_region_chan->region = region_chan->region; | ||
240 | memcpy(parsed_region_chan->countrycode, | ||
241 | lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN); | ||
242 | |||
243 | lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region, | ||
244 | parsed_region_chan->band); | ||
245 | |||
246 | for (i = 0; i < region_chan->nrcfp; i++, cfp++) { | ||
247 | parsed_region_chan->chanpwr[i].chan = cfp->channel; | ||
248 | parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower; | ||
249 | lbs_deb_11d("chan %d, pwr %d\n", | ||
250 | parsed_region_chan->chanpwr[i].chan, | ||
251 | parsed_region_chan->chanpwr[i].pwr); | ||
252 | } | ||
253 | parsed_region_chan->nr_chan = region_chan->nrcfp; | ||
254 | |||
255 | lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan); | ||
256 | |||
257 | return; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS | ||
262 | * @param region region ID | ||
263 | * @param band band | ||
264 | * @param chan chan | ||
265 | * @return TRUE;FALSE | ||
266 | */ | ||
267 | static u8 lbs_region_chan_supported_11d(u8 region, u8 chan) | ||
268 | { | ||
269 | struct chan_freq_power *cfp; | ||
270 | int cfp_no; | ||
271 | u8 idx; | ||
272 | int ret = 0; | ||
273 | |||
274 | lbs_deb_enter(LBS_DEB_11D); | ||
275 | |||
276 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
277 | if (cfp == NULL) | ||
278 | return 0; | ||
279 | |||
280 | for (idx = 0; idx < cfp_no; idx++) { | ||
281 | if (chan == (cfp + idx)->channel) { | ||
282 | /* If Mrvl Chip Supported? */ | ||
283 | if ((cfp + idx)->unsupported) { | ||
284 | ret = 0; | ||
285 | } else { | ||
286 | ret = 1; | ||
287 | } | ||
288 | goto done; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | /*chan is not in the region table */ | ||
293 | |||
294 | done: | ||
295 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
296 | return ret; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * @brief This function checks if chan txpwr is learned from AP/IBSS | ||
301 | * @param chan chan number | ||
302 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
303 | * @return 0 | ||
304 | */ | ||
305 | static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo, | ||
306 | u8 band, | ||
307 | struct parsed_region_chan_11d *parsed_region_chan) | ||
308 | { | ||
309 | u8 nr_subband, nrchan; | ||
310 | u8 lastchan, firstchan; | ||
311 | u8 region; | ||
312 | u8 curchan = 0; | ||
313 | |||
314 | u8 idx = 0; /*chan index in parsed_region_chan */ | ||
315 | |||
316 | u8 j, i; | ||
317 | |||
318 | lbs_deb_enter(LBS_DEB_11D); | ||
319 | |||
320 | /*validation Rules: | ||
321 | 1. valid region Code | ||
322 | 2. First Chan increment | ||
323 | 3. channel range no overlap | ||
324 | 4. channel is valid? | ||
325 | 5. channel is supported by region? | ||
326 | 6. Others | ||
327 | */ | ||
328 | |||
329 | lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30); | ||
330 | |||
331 | if ((*(countryinfo->countrycode)) == 0 | ||
332 | || (countryinfo->header.len <= COUNTRY_CODE_LEN)) { | ||
333 | /* No region Info or Wrong region info: treat as No 11D info */ | ||
334 | goto done; | ||
335 | } | ||
336 | |||
337 | /*Step1: check region_code */ | ||
338 | parsed_region_chan->region = region = | ||
339 | lbs_region_2_code(countryinfo->countrycode); | ||
340 | |||
341 | lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region); | ||
342 | lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode, | ||
343 | COUNTRY_CODE_LEN); | ||
344 | |||
345 | parsed_region_chan->band = band; | ||
346 | |||
347 | memcpy(parsed_region_chan->countrycode, countryinfo->countrycode, | ||
348 | COUNTRY_CODE_LEN); | ||
349 | |||
350 | nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) / | ||
351 | sizeof(struct ieee_subbandset); | ||
352 | |||
353 | for (j = 0, lastchan = 0; j < nr_subband; j++) { | ||
354 | |||
355 | if (countryinfo->subband[j].firstchan <= lastchan) { | ||
356 | /*Step2&3. Check First Chan Num increment and no overlap */ | ||
357 | lbs_deb_11d("chan %d>%d, overlap\n", | ||
358 | countryinfo->subband[j].firstchan, lastchan); | ||
359 | continue; | ||
360 | } | ||
361 | |||
362 | firstchan = countryinfo->subband[j].firstchan; | ||
363 | nrchan = countryinfo->subband[j].nrchan; | ||
364 | |||
365 | for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) { | ||
366 | /*step4: channel is supported? */ | ||
367 | |||
368 | if (!lbs_get_chan_11d(firstchan, i, &curchan)) { | ||
369 | /* Chan is not found in UN table */ | ||
370 | lbs_deb_11d("chan is not supported: %d \n", i); | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | lastchan = curchan; | ||
375 | |||
376 | if (lbs_region_chan_supported_11d(region, curchan)) { | ||
377 | /*step5: Check if curchan is supported by mrvl in region */ | ||
378 | parsed_region_chan->chanpwr[idx].chan = curchan; | ||
379 | parsed_region_chan->chanpwr[idx].pwr = | ||
380 | countryinfo->subband[j].maxtxpwr; | ||
381 | idx++; | ||
382 | } else { | ||
383 | /*not supported and ignore the chan */ | ||
384 | lbs_deb_11d( | ||
385 | "i %d, chan %d unsupported in region %x, band %d\n", | ||
386 | i, curchan, region, band); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | /*Step6: Add other checking if any */ | ||
391 | |||
392 | } | ||
393 | |||
394 | parsed_region_chan->nr_chan = idx; | ||
395 | |||
396 | lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan); | ||
397 | lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan, | ||
398 | 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx); | ||
399 | |||
400 | done: | ||
401 | lbs_deb_enter(LBS_DEB_11D); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * @brief This function calculates the scan type for channels | ||
407 | * @param chan chan number | ||
408 | * @param parsed_region_chan pointer to parsed_region_chan_11d | ||
409 | * @return PASSIVE if chan is unknown; ACTIVE if chan is known | ||
410 | */ | ||
411 | u8 lbs_get_scan_type_11d(u8 chan, | ||
412 | struct parsed_region_chan_11d * parsed_region_chan) | ||
413 | { | ||
414 | u8 scan_type = CMD_SCAN_TYPE_PASSIVE; | ||
415 | |||
416 | lbs_deb_enter(LBS_DEB_11D); | ||
417 | |||
418 | if (lbs_channel_known_11d(chan, parsed_region_chan)) { | ||
419 | lbs_deb_11d("found, do active scan\n"); | ||
420 | scan_type = CMD_SCAN_TYPE_ACTIVE; | ||
421 | } else { | ||
422 | lbs_deb_11d("not found, do passive scan\n"); | ||
423 | } | ||
424 | |||
425 | lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type); | ||
426 | return scan_type; | ||
427 | |||
428 | } | ||
429 | |||
430 | void lbs_init_11d(struct lbs_private *priv) | ||
431 | { | ||
432 | priv->enable11d = 0; | ||
433 | memset(&(priv->parsed_region_chan), 0, | ||
434 | sizeof(struct parsed_region_chan_11d)); | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * @brief This function sets DOMAIN INFO to FW | ||
440 | * @param priv pointer to struct lbs_private | ||
441 | * @return 0; -1 | ||
442 | */ | ||
443 | static int set_domain_info_11d(struct lbs_private *priv) | ||
444 | { | ||
445 | int ret; | ||
446 | |||
447 | if (!priv->enable11d) { | ||
448 | lbs_deb_11d("dnld domain Info with 11d disabled\n"); | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO, | ||
453 | CMD_ACT_SET, | ||
454 | CMD_OPTION_WAITFORRSP, 0, NULL); | ||
455 | if (ret) | ||
456 | lbs_deb_11d("fail to dnld domain info\n"); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | /** | ||
462 | * @brief This function setups scan channels | ||
463 | * @param priv pointer to struct lbs_private | ||
464 | * @param band band | ||
465 | * @return 0 | ||
466 | */ | ||
467 | int lbs_set_universaltable(struct lbs_private *priv, u8 band) | ||
468 | { | ||
469 | u16 size = sizeof(struct chan_freq_power); | ||
470 | u16 i = 0; | ||
471 | |||
472 | memset(priv->universal_channel, 0, | ||
473 | sizeof(priv->universal_channel)); | ||
474 | |||
475 | priv->universal_channel[i].nrcfp = | ||
476 | sizeof(channel_freq_power_UN_BG) / size; | ||
477 | lbs_deb_11d("BG-band nrcfp %d\n", | ||
478 | priv->universal_channel[i].nrcfp); | ||
479 | |||
480 | priv->universal_channel[i].CFP = channel_freq_power_UN_BG; | ||
481 | priv->universal_channel[i].valid = 1; | ||
482 | priv->universal_channel[i].region = UNIVERSAL_REGION_CODE; | ||
483 | priv->universal_channel[i].band = band; | ||
484 | i++; | ||
485 | |||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /** | ||
490 | * @brief This function implements command CMD_802_11D_DOMAIN_INFO | ||
491 | * @param priv pointer to struct lbs_private | ||
492 | * @param cmd pointer to cmd buffer | ||
493 | * @param cmdno cmd ID | ||
494 | * @param cmdOption cmd action | ||
495 | * @return 0 | ||
496 | */ | ||
497 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
498 | struct cmd_ds_command *cmd, u16 cmdno, | ||
499 | u16 cmdoption) | ||
500 | { | ||
501 | struct cmd_ds_802_11d_domain_info *pdomaininfo = | ||
502 | &cmd->params.domaininfo; | ||
503 | struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; | ||
504 | u8 nr_subband = priv->domainreg.nr_subband; | ||
505 | |||
506 | lbs_deb_enter(LBS_DEB_11D); | ||
507 | |||
508 | lbs_deb_11d("nr_subband=%x\n", nr_subband); | ||
509 | |||
510 | cmd->command = cpu_to_le16(cmdno); | ||
511 | pdomaininfo->action = cpu_to_le16(cmdoption); | ||
512 | if (cmdoption == CMD_ACT_GET) { | ||
513 | cmd->size = | ||
514 | cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); | ||
515 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, | ||
516 | le16_to_cpu(cmd->size)); | ||
517 | goto done; | ||
518 | } | ||
519 | |||
520 | domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); | ||
521 | memcpy(domain->countrycode, priv->domainreg.countrycode, | ||
522 | sizeof(domain->countrycode)); | ||
523 | |||
524 | domain->header.len = | ||
525 | cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) + | ||
526 | sizeof(domain->countrycode)); | ||
527 | |||
528 | if (nr_subband) { | ||
529 | memcpy(domain->subband, priv->domainreg.subband, | ||
530 | nr_subband * sizeof(struct ieee_subbandset)); | ||
531 | |||
532 | cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + | ||
533 | le16_to_cpu(domain->header.len) + | ||
534 | sizeof(struct mrvl_ie_header) + | ||
535 | S_DS_GEN); | ||
536 | } else { | ||
537 | cmd->size = | ||
538 | cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); | ||
539 | } | ||
540 | |||
541 | lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size)); | ||
542 | |||
543 | done: | ||
544 | lbs_deb_enter(LBS_DEB_11D); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /** | ||
549 | * @brief This function parses countryinfo from AP and download country info to FW | ||
550 | * @param priv pointer to struct lbs_private | ||
551 | * @param resp pointer to command response buffer | ||
552 | * @return 0; -1 | ||
553 | */ | ||
554 | int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) | ||
555 | { | ||
556 | struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; | ||
557 | struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; | ||
558 | u16 action = le16_to_cpu(domaininfo->action); | ||
559 | s16 ret = 0; | ||
560 | u8 nr_subband = 0; | ||
561 | |||
562 | lbs_deb_enter(LBS_DEB_11D); | ||
563 | |||
564 | lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp, | ||
565 | (int)le16_to_cpu(resp->size)); | ||
566 | |||
567 | nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / | ||
568 | sizeof(struct ieee_subbandset); | ||
569 | |||
570 | lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband); | ||
571 | |||
572 | if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) { | ||
573 | lbs_deb_11d("Invalid Numrer of Subband returned!!\n"); | ||
574 | return -1; | ||
575 | } | ||
576 | |||
577 | switch (action) { | ||
578 | case CMD_ACT_SET: /*Proc Set action */ | ||
579 | break; | ||
580 | |||
581 | case CMD_ACT_GET: | ||
582 | break; | ||
583 | default: | ||
584 | lbs_deb_11d("Invalid action:%d\n", domaininfo->action); | ||
585 | ret = -1; | ||
586 | break; | ||
587 | } | ||
588 | |||
589 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
590 | return ret; | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * @brief This function parses countryinfo from AP and download country info to FW | ||
595 | * @param priv pointer to struct lbs_private | ||
596 | * @return 0; -1 | ||
597 | */ | ||
598 | int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, | ||
599 | struct bss_descriptor * bss) | ||
600 | { | ||
601 | int ret; | ||
602 | |||
603 | lbs_deb_enter(LBS_DEB_11D); | ||
604 | if (priv->enable11d) { | ||
605 | memset(&priv->parsed_region_chan, 0, | ||
606 | sizeof(struct parsed_region_chan_11d)); | ||
607 | ret = parse_domain_info_11d(&bss->countryinfo, 0, | ||
608 | &priv->parsed_region_chan); | ||
609 | |||
610 | if (ret == -1) { | ||
611 | lbs_deb_11d("error parsing domain_info from AP\n"); | ||
612 | goto done; | ||
613 | } | ||
614 | |||
615 | memset(&priv->domainreg, 0, | ||
616 | sizeof(struct lbs_802_11d_domain_reg)); | ||
617 | generate_domain_info_11d(&priv->parsed_region_chan, | ||
618 | &priv->domainreg); | ||
619 | |||
620 | ret = set_domain_info_11d(priv); | ||
621 | |||
622 | if (ret) { | ||
623 | lbs_deb_11d("error setting domain info\n"); | ||
624 | goto done; | ||
625 | } | ||
626 | } | ||
627 | ret = 0; | ||
628 | |||
629 | done: | ||
630 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
631 | return ret; | ||
632 | } | ||
633 | |||
634 | /** | ||
635 | * @brief This function generates 11D info from user specified regioncode and download to FW | ||
636 | * @param priv pointer to struct lbs_private | ||
637 | * @return 0; -1 | ||
638 | */ | ||
639 | int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv) | ||
640 | { | ||
641 | int ret; | ||
642 | struct region_channel *region_chan; | ||
643 | u8 j; | ||
644 | |||
645 | lbs_deb_enter(LBS_DEB_11D); | ||
646 | lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band); | ||
647 | |||
648 | if (priv->enable11d) { | ||
649 | /* update parsed_region_chan_11; dnld domaininf to FW */ | ||
650 | |||
651 | for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) { | ||
652 | region_chan = &priv->region_channel[j]; | ||
653 | |||
654 | lbs_deb_11d("%d region_chan->band %d\n", j, | ||
655 | region_chan->band); | ||
656 | |||
657 | if (!region_chan || !region_chan->valid | ||
658 | || !region_chan->CFP) | ||
659 | continue; | ||
660 | if (region_chan->band != priv->curbssparams.band) | ||
661 | continue; | ||
662 | break; | ||
663 | } | ||
664 | |||
665 | if (j >= ARRAY_SIZE(priv->region_channel)) { | ||
666 | lbs_deb_11d("region_chan not found, band %d\n", | ||
667 | priv->curbssparams.band); | ||
668 | ret = -1; | ||
669 | goto done; | ||
670 | } | ||
671 | |||
672 | memset(&priv->parsed_region_chan, 0, | ||
673 | sizeof(struct parsed_region_chan_11d)); | ||
674 | lbs_generate_parsed_region_chan_11d(region_chan, | ||
675 | &priv-> | ||
676 | parsed_region_chan); | ||
677 | |||
678 | memset(&priv->domainreg, 0, | ||
679 | sizeof(struct lbs_802_11d_domain_reg)); | ||
680 | generate_domain_info_11d(&priv->parsed_region_chan, | ||
681 | &priv->domainreg); | ||
682 | |||
683 | ret = set_domain_info_11d(priv); | ||
684 | |||
685 | if (ret) { | ||
686 | lbs_deb_11d("error setting domain info\n"); | ||
687 | goto done; | ||
688 | } | ||
689 | |||
690 | } | ||
691 | ret = 0; | ||
692 | |||
693 | done: | ||
694 | lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); | ||
695 | return ret; | ||
696 | } | ||
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h deleted file mode 100644 index fb75d3e321a0..000000000000 --- a/drivers/net/wireless/libertas/11d.h +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | /** | ||
2 | * This header file contains data structures and | ||
3 | * function declarations of 802.11d | ||
4 | */ | ||
5 | #ifndef _LBS_11D_ | ||
6 | #define _LBS_11D_ | ||
7 | |||
8 | #include "types.h" | ||
9 | #include "defs.h" | ||
10 | |||
11 | #define UNIVERSAL_REGION_CODE 0xff | ||
12 | |||
13 | /** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) | ||
14 | */ | ||
15 | #define MRVDRV_MAX_SUBBAND_802_11D 83 | ||
16 | |||
17 | #define COUNTRY_CODE_LEN 3 | ||
18 | #define MAX_NO_OF_CHAN 40 | ||
19 | |||
20 | struct cmd_ds_command; | ||
21 | |||
22 | /** Data structure for Country IE*/ | ||
23 | struct ieee_subbandset { | ||
24 | u8 firstchan; | ||
25 | u8 nrchan; | ||
26 | u8 maxtxpwr; | ||
27 | } __attribute__ ((packed)); | ||
28 | |||
29 | struct ieee_ie_country_info_set { | ||
30 | struct ieee_ie_header header; | ||
31 | |||
32 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
33 | struct ieee_subbandset subband[1]; | ||
34 | }; | ||
35 | |||
36 | struct ieee_ie_country_info_full_set { | ||
37 | struct ieee_ie_header header; | ||
38 | |||
39 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
40 | struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; | ||
41 | } __attribute__ ((packed)); | ||
42 | |||
43 | struct mrvl_ie_domain_param_set { | ||
44 | struct mrvl_ie_header header; | ||
45 | |||
46 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
47 | struct ieee_subbandset subband[1]; | ||
48 | } __attribute__ ((packed)); | ||
49 | |||
50 | struct cmd_ds_802_11d_domain_info { | ||
51 | __le16 action; | ||
52 | struct mrvl_ie_domain_param_set domain; | ||
53 | } __attribute__ ((packed)); | ||
54 | |||
55 | /** domain regulatory information */ | ||
56 | struct lbs_802_11d_domain_reg { | ||
57 | /** country Code*/ | ||
58 | u8 countrycode[COUNTRY_CODE_LEN]; | ||
59 | /** No. of subband*/ | ||
60 | u8 nr_subband; | ||
61 | struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; | ||
62 | }; | ||
63 | |||
64 | struct chan_power_11d { | ||
65 | u8 chan; | ||
66 | u8 pwr; | ||
67 | } __attribute__ ((packed)); | ||
68 | |||
69 | struct parsed_region_chan_11d { | ||
70 | u8 band; | ||
71 | u8 region; | ||
72 | s8 countrycode[COUNTRY_CODE_LEN]; | ||
73 | struct chan_power_11d chanpwr[MAX_NO_OF_CHAN]; | ||
74 | u8 nr_chan; | ||
75 | } __attribute__ ((packed)); | ||
76 | |||
77 | struct region_code_mapping { | ||
78 | u8 region[COUNTRY_CODE_LEN]; | ||
79 | u8 code; | ||
80 | }; | ||
81 | |||
82 | struct lbs_private; | ||
83 | |||
84 | u8 lbs_get_scan_type_11d(u8 chan, | ||
85 | struct parsed_region_chan_11d *parsed_region_chan); | ||
86 | |||
87 | u32 lbs_chan_2_freq(u8 chan); | ||
88 | |||
89 | void lbs_init_11d(struct lbs_private *priv); | ||
90 | |||
91 | int lbs_set_universaltable(struct lbs_private *priv, u8 band); | ||
92 | |||
93 | int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, | ||
94 | struct cmd_ds_command *cmd, u16 cmdno, | ||
95 | u16 cmdOption); | ||
96 | |||
97 | int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); | ||
98 | |||
99 | struct bss_descriptor; | ||
100 | int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, | ||
101 | struct bss_descriptor * bss); | ||
102 | |||
103 | int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv); | ||
104 | |||
105 | #endif | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index e5584dd1c79a..fa37039e0eae 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -1,4 +1,3 @@ | |||
1 | libertas-y += 11d.o | ||
2 | libertas-y += assoc.o | 1 | libertas-y += assoc.o |
3 | libertas-y += cfg.o | 2 | libertas-y += cfg.o |
4 | libertas-y += cmd.o | 3 | libertas-y += cmd.o |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index dd8732611ba9..751067369ba8 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -23,6 +23,13 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = | |||
23 | */ | 23 | */ |
24 | #define CAPINFO_MASK (~(0xda00)) | 24 | #define CAPINFO_MASK (~(0xda00)) |
25 | 25 | ||
26 | /** | ||
27 | * 802.11b/g supported bitrates (in 500Kb/s units) | ||
28 | */ | ||
29 | u8 lbs_bg_rates[MAX_RATES] = | ||
30 | { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, | ||
31 | 0x00, 0x00 }; | ||
32 | |||
26 | 33 | ||
27 | /** | 34 | /** |
28 | * @brief This function finds common rates between rates and card rates. | 35 | * @brief This function finds common rates between rates and card rates. |
@@ -147,6 +154,397 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth | |||
147 | } | 154 | } |
148 | 155 | ||
149 | 156 | ||
157 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
158 | struct assoc_request *assoc) | ||
159 | { | ||
160 | struct cmd_ds_802_11_set_wep cmd; | ||
161 | int ret = 0; | ||
162 | |||
163 | lbs_deb_enter(LBS_DEB_CMD); | ||
164 | |||
165 | memset(&cmd, 0, sizeof(cmd)); | ||
166 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | ||
167 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
168 | |||
169 | cmd.action = cpu_to_le16(cmd_action); | ||
170 | |||
171 | if (cmd_action == CMD_ACT_ADD) { | ||
172 | int i; | ||
173 | |||
174 | /* default tx key index */ | ||
175 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
176 | CMD_WEP_KEY_INDEX_MASK); | ||
177 | |||
178 | /* Copy key types and material to host command structure */ | ||
179 | for (i = 0; i < 4; i++) { | ||
180 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
181 | |||
182 | switch (pkey->len) { | ||
183 | case KEY_LEN_WEP_40: | ||
184 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
185 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
186 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
187 | break; | ||
188 | case KEY_LEN_WEP_104: | ||
189 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
190 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
191 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
192 | break; | ||
193 | case 0: | ||
194 | break; | ||
195 | default: | ||
196 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
197 | i, pkey->len); | ||
198 | ret = -1; | ||
199 | goto done; | ||
200 | break; | ||
201 | } | ||
202 | } | ||
203 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
204 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
205 | |||
206 | /* default tx key index */ | ||
207 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
208 | CMD_WEP_KEY_INDEX_MASK); | ||
209 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
210 | } | ||
211 | |||
212 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
213 | done: | ||
214 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
219 | uint16_t *enable) | ||
220 | { | ||
221 | struct cmd_ds_802_11_enable_rsn cmd; | ||
222 | int ret; | ||
223 | |||
224 | lbs_deb_enter(LBS_DEB_CMD); | ||
225 | |||
226 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
227 | cmd.action = cpu_to_le16(cmd_action); | ||
228 | |||
229 | if (cmd_action == CMD_ACT_GET) | ||
230 | cmd.enable = 0; | ||
231 | else { | ||
232 | if (*enable) | ||
233 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
234 | else | ||
235 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
236 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
237 | } | ||
238 | |||
239 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
240 | if (!ret && cmd_action == CMD_ACT_GET) | ||
241 | *enable = le16_to_cpu(cmd.enable); | ||
242 | |||
243 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | ||
248 | struct enc_key *key) | ||
249 | { | ||
250 | lbs_deb_enter(LBS_DEB_CMD); | ||
251 | |||
252 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
253 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
254 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
255 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
256 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
257 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
258 | |||
259 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
260 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
261 | keyparam->keylen = cpu_to_le16(key->len); | ||
262 | memcpy(keyparam->key, key->key, key->len); | ||
263 | |||
264 | /* Length field doesn't include the {type,length} header */ | ||
265 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
266 | lbs_deb_leave(LBS_DEB_CMD); | ||
267 | } | ||
268 | |||
269 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
270 | struct assoc_request *assoc) | ||
271 | { | ||
272 | struct cmd_ds_802_11_key_material cmd; | ||
273 | int ret = 0; | ||
274 | int index = 0; | ||
275 | |||
276 | lbs_deb_enter(LBS_DEB_CMD); | ||
277 | |||
278 | cmd.action = cpu_to_le16(cmd_action); | ||
279 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
280 | |||
281 | if (cmd_action == CMD_ACT_GET) { | ||
282 | cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2); | ||
283 | } else { | ||
284 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | ||
285 | |||
286 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | ||
287 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
288 | &assoc->wpa_unicast_key); | ||
289 | index++; | ||
290 | } | ||
291 | |||
292 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
293 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
294 | &assoc->wpa_mcast_key); | ||
295 | index++; | ||
296 | } | ||
297 | |||
298 | /* The common header and as many keys as we included */ | ||
299 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | ||
300 | keyParamSet[index])); | ||
301 | } | ||
302 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
303 | /* Copy the returned key to driver private data */ | ||
304 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
305 | void *buf_ptr = cmd.keyParamSet; | ||
306 | void *resp_end = &(&cmd)[1]; | ||
307 | |||
308 | while (buf_ptr < resp_end) { | ||
309 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
310 | struct enc_key *key; | ||
311 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
312 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
313 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
314 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
315 | void *end; | ||
316 | |||
317 | end = (void *)keyparam + sizeof(keyparam->type) | ||
318 | + sizeof(keyparam->length) + param_set_len; | ||
319 | |||
320 | /* Make sure we don't access past the end of the IEs */ | ||
321 | if (end > resp_end) | ||
322 | break; | ||
323 | |||
324 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
325 | key = &priv->wpa_unicast_key; | ||
326 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
327 | key = &priv->wpa_mcast_key; | ||
328 | else | ||
329 | break; | ||
330 | |||
331 | /* Copy returned key into driver */ | ||
332 | memset(key, 0, sizeof(struct enc_key)); | ||
333 | if (key_len > sizeof(key->key)) | ||
334 | break; | ||
335 | key->type = key_type; | ||
336 | key->flags = key_flags; | ||
337 | key->len = key_len; | ||
338 | memcpy(key->key, keyparam->key, key->len); | ||
339 | |||
340 | buf_ptr = end + 1; | ||
341 | } | ||
342 | } | ||
343 | |||
344 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
349 | { | ||
350 | /* Bit Rate | ||
351 | * 15:13 Reserved | ||
352 | * 12 54 Mbps | ||
353 | * 11 48 Mbps | ||
354 | * 10 36 Mbps | ||
355 | * 9 24 Mbps | ||
356 | * 8 18 Mbps | ||
357 | * 7 12 Mbps | ||
358 | * 6 9 Mbps | ||
359 | * 5 6 Mbps | ||
360 | * 4 Reserved | ||
361 | * 3 11 Mbps | ||
362 | * 2 5.5 Mbps | ||
363 | * 1 2 Mbps | ||
364 | * 0 1 Mbps | ||
365 | **/ | ||
366 | |||
367 | uint16_t ratemask; | ||
368 | int i = lbs_data_rate_to_fw_index(rate); | ||
369 | if (lower_rates_ok) | ||
370 | ratemask = (0x1fef >> (12 - i)); | ||
371 | else | ||
372 | ratemask = (1 << i); | ||
373 | return cpu_to_le16(ratemask); | ||
374 | } | ||
375 | |||
376 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
377 | uint16_t cmd_action) | ||
378 | { | ||
379 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
380 | int ret; | ||
381 | |||
382 | lbs_deb_enter(LBS_DEB_CMD); | ||
383 | |||
384 | if (!priv->cur_rate && !priv->enablehwauto) | ||
385 | return -EINVAL; | ||
386 | |||
387 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
388 | |||
389 | cmd.action = cpu_to_le16(cmd_action); | ||
390 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
391 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
392 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
393 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
394 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
395 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
396 | } | ||
397 | |||
398 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * @brief Set the data rate | ||
404 | * | ||
405 | * @param priv A pointer to struct lbs_private structure | ||
406 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
407 | * | ||
408 | * @return 0 on success, error on failure | ||
409 | */ | ||
410 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
411 | { | ||
412 | struct cmd_ds_802_11_data_rate cmd; | ||
413 | int ret = 0; | ||
414 | |||
415 | lbs_deb_enter(LBS_DEB_CMD); | ||
416 | |||
417 | memset(&cmd, 0, sizeof(cmd)); | ||
418 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
419 | |||
420 | if (rate > 0) { | ||
421 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
422 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
423 | if (cmd.rates[0] == 0) { | ||
424 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
425 | " 0x%02X\n", rate); | ||
426 | ret = 0; | ||
427 | goto out; | ||
428 | } | ||
429 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
430 | } else { | ||
431 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
432 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
433 | } | ||
434 | |||
435 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
436 | if (ret) | ||
437 | goto out; | ||
438 | |||
439 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd)); | ||
440 | |||
441 | /* FIXME: get actual rates FW can do if this command actually returns | ||
442 | * all data rates supported. | ||
443 | */ | ||
444 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
445 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
446 | |||
447 | out: | ||
448 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | |||
453 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
454 | struct cmd_ds_command *cmd) | ||
455 | { | ||
456 | |||
457 | lbs_deb_enter(LBS_DEB_CMD); | ||
458 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
459 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + | ||
460 | sizeof(struct cmd_header)); | ||
461 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
462 | |||
463 | /* reset Beacon SNR/NF/RSSI values */ | ||
464 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
465 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
466 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
467 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
468 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
469 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
470 | |||
471 | lbs_deb_leave(LBS_DEB_CMD); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
476 | struct cmd_ds_command *resp) | ||
477 | { | ||
478 | struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; | ||
479 | |||
480 | lbs_deb_enter(LBS_DEB_CMD); | ||
481 | |||
482 | /* store the non average value */ | ||
483 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); | ||
484 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = | ||
485 | get_unaligned_le16(&rssirsp->noisefloor); | ||
486 | |||
487 | priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); | ||
488 | priv->NF[TYPE_BEACON][TYPE_AVG] = | ||
489 | get_unaligned_le16(&rssirsp->avgnoisefloor); | ||
490 | |||
491 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = | ||
492 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
493 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
494 | |||
495 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = | ||
496 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, | ||
497 | priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); | ||
498 | |||
499 | lbs_deb_cmd("RSSI: beacon %d, avg %d\n", | ||
500 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG], | ||
501 | priv->RSSI[TYPE_BEACON][TYPE_AVG]); | ||
502 | |||
503 | lbs_deb_leave(LBS_DEB_CMD); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | |||
508 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
509 | struct cmd_ds_command *cmd, | ||
510 | u16 cmd_action) | ||
511 | { | ||
512 | struct cmd_ds_802_11_beacon_control | ||
513 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
514 | |||
515 | lbs_deb_enter(LBS_DEB_CMD); | ||
516 | cmd->size = | ||
517 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
518 | + sizeof(struct cmd_header)); | ||
519 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
520 | |||
521 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
522 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
523 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
524 | |||
525 | lbs_deb_leave(LBS_DEB_CMD); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
530 | struct cmd_ds_command *resp) | ||
531 | { | ||
532 | struct cmd_ds_802_11_beacon_control *bcn_ctrl = | ||
533 | &resp->params.bcn_ctrl; | ||
534 | |||
535 | lbs_deb_enter(LBS_DEB_CMD); | ||
536 | |||
537 | if (bcn_ctrl->action == CMD_ACT_GET) { | ||
538 | priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); | ||
539 | priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); | ||
540 | } | ||
541 | |||
542 | lbs_deb_enter(LBS_DEB_CMD); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | |||
547 | |||
150 | static int lbs_assoc_post(struct lbs_private *priv, | 548 | static int lbs_assoc_post(struct lbs_private *priv, |
151 | struct cmd_ds_802_11_associate_response *resp) | 549 | struct cmd_ds_802_11_associate_response *resp) |
152 | { | 550 | { |
@@ -226,7 +624,7 @@ static int lbs_assoc_post(struct lbs_private *priv, | |||
226 | priv->connect_status = LBS_CONNECTED; | 624 | priv->connect_status = LBS_CONNECTED; |
227 | 625 | ||
228 | /* Update current SSID and BSSID */ | 626 | /* Update current SSID and BSSID */ |
229 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | 627 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); |
230 | priv->curbssparams.ssid_len = bss->ssid_len; | 628 | priv->curbssparams.ssid_len = bss->ssid_len; |
231 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | 629 | memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); |
232 | 630 | ||
@@ -369,12 +767,7 @@ static int lbs_associate(struct lbs_private *priv, | |||
369 | (u16)(pos - (u8 *) &cmd.iebuf)); | 767 | (u16)(pos - (u8 *) &cmd.iebuf)); |
370 | 768 | ||
371 | /* update curbssparams */ | 769 | /* update curbssparams */ |
372 | priv->curbssparams.channel = bss->phy.ds.channel; | 770 | priv->channel = bss->phy.ds.channel; |
373 | |||
374 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
375 | ret = -1; | ||
376 | goto done; | ||
377 | } | ||
378 | 771 | ||
379 | ret = lbs_cmd_with_response(priv, command, &cmd); | 772 | ret = lbs_cmd_with_response(priv, command, &cmd); |
380 | if (ret == 0) { | 773 | if (ret == 0) { |
@@ -472,7 +865,7 @@ static int lbs_adhoc_post(struct lbs_private *priv, | |||
472 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); | 865 | memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); |
473 | 866 | ||
474 | /* Set the new SSID to current SSID */ | 867 | /* Set the new SSID to current SSID */ |
475 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); | 868 | memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN); |
476 | priv->curbssparams.ssid_len = bss->ssid_len; | 869 | priv->curbssparams.ssid_len = bss->ssid_len; |
477 | 870 | ||
478 | netif_carrier_on(priv->dev); | 871 | netif_carrier_on(priv->dev); |
@@ -487,7 +880,7 @@ static int lbs_adhoc_post(struct lbs_private *priv, | |||
487 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", | 880 | lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", |
488 | print_ssid(ssid, bss->ssid, bss->ssid_len), | 881 | print_ssid(ssid, bss->ssid, bss->ssid_len), |
489 | priv->curbssparams.bssid, | 882 | priv->curbssparams.bssid, |
490 | priv->curbssparams.channel); | 883 | priv->channel); |
491 | 884 | ||
492 | done: | 885 | done: |
493 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); | 886 | lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); |
@@ -560,7 +953,7 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
560 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); | 953 | lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); |
561 | 954 | ||
562 | priv->adhoccreate = 0; | 955 | priv->adhoccreate = 0; |
563 | priv->curbssparams.channel = bss->channel; | 956 | priv->channel = bss->channel; |
564 | 957 | ||
565 | /* Build the join command */ | 958 | /* Build the join command */ |
566 | memset(&cmd, 0, sizeof(cmd)); | 959 | memset(&cmd, 0, sizeof(cmd)); |
@@ -633,11 +1026,6 @@ static int lbs_adhoc_join(struct lbs_private *priv, | |||
633 | } | 1026 | } |
634 | } | 1027 | } |
635 | 1028 | ||
636 | if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { | ||
637 | ret = -1; | ||
638 | goto out; | ||
639 | } | ||
640 | |||
641 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); | 1029 | ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); |
642 | if (ret == 0) { | 1030 | if (ret == 0) { |
643 | ret = lbs_adhoc_post(priv, | 1031 | ret = lbs_adhoc_post(priv, |
@@ -737,12 +1125,6 @@ static int lbs_adhoc_start(struct lbs_private *priv, | |||
737 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", | 1125 | lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", |
738 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); | 1126 | cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); |
739 | 1127 | ||
740 | if (lbs_create_dnld_countryinfo_11d(priv)) { | ||
741 | lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n"); | ||
742 | ret = -1; | ||
743 | goto out; | ||
744 | } | ||
745 | |||
746 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", | 1128 | lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", |
747 | assoc_req->channel, assoc_req->band); | 1129 | assoc_req->channel, assoc_req->band); |
748 | 1130 | ||
@@ -1099,7 +1481,7 @@ static int assoc_helper_essid(struct lbs_private *priv, | |||
1099 | /* else send START command */ | 1481 | /* else send START command */ |
1100 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); | 1482 | lbs_deb_assoc("SSID not found, creating adhoc network\n"); |
1101 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, | 1483 | memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, |
1102 | IW_ESSID_MAX_SIZE); | 1484 | IEEE80211_MAX_SSID_LEN); |
1103 | assoc_req->bss.ssid_len = assoc_req->ssid_len; | 1485 | assoc_req->bss.ssid_len = assoc_req->ssid_len; |
1104 | lbs_adhoc_start(priv, assoc_req); | 1486 | lbs_adhoc_start(priv, assoc_req); |
1105 | } | 1487 | } |
@@ -1185,7 +1567,8 @@ static int assoc_helper_mode(struct lbs_private *priv, | |||
1185 | } | 1567 | } |
1186 | 1568 | ||
1187 | priv->mode = assoc_req->mode; | 1569 | priv->mode = assoc_req->mode; |
1188 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode); | 1570 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, |
1571 | assoc_req->mode == IW_MODE_ADHOC ? 2 : 1); | ||
1189 | 1572 | ||
1190 | done: | 1573 | done: |
1191 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 1574 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -1205,7 +1588,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1205 | goto done; | 1588 | goto done; |
1206 | } | 1589 | } |
1207 | 1590 | ||
1208 | if (assoc_req->channel == priv->curbssparams.channel) | 1591 | if (assoc_req->channel == priv->channel) |
1209 | goto done; | 1592 | goto done; |
1210 | 1593 | ||
1211 | if (priv->mesh_dev) { | 1594 | if (priv->mesh_dev) { |
@@ -1217,7 +1600,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1217 | } | 1600 | } |
1218 | 1601 | ||
1219 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", | 1602 | lbs_deb_assoc("ASSOC: channel: %d -> %d\n", |
1220 | priv->curbssparams.channel, assoc_req->channel); | 1603 | priv->channel, assoc_req->channel); |
1221 | 1604 | ||
1222 | ret = lbs_set_channel(priv, assoc_req->channel); | 1605 | ret = lbs_set_channel(priv, assoc_req->channel); |
1223 | if (ret < 0) | 1606 | if (ret < 0) |
@@ -1232,7 +1615,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1232 | goto done; | 1615 | goto done; |
1233 | } | 1616 | } |
1234 | 1617 | ||
1235 | if (assoc_req->channel != priv->curbssparams.channel) { | 1618 | if (assoc_req->channel != priv->channel) { |
1236 | lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", | 1619 | lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", |
1237 | assoc_req->channel); | 1620 | assoc_req->channel); |
1238 | goto restore_mesh; | 1621 | goto restore_mesh; |
@@ -1253,7 +1636,7 @@ static int assoc_helper_channel(struct lbs_private *priv, | |||
1253 | restore_mesh: | 1636 | restore_mesh: |
1254 | if (priv->mesh_dev) | 1637 | if (priv->mesh_dev) |
1255 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 1638 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1256 | priv->curbssparams.channel); | 1639 | priv->channel); |
1257 | 1640 | ||
1258 | done: | 1641 | done: |
1259 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 1642 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -1475,7 +1858,7 @@ static int should_stop_adhoc(struct lbs_private *priv, | |||
1475 | } | 1858 | } |
1476 | 1859 | ||
1477 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { | 1860 | if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { |
1478 | if (assoc_req->channel != priv->curbssparams.channel) | 1861 | if (assoc_req->channel != priv->channel) |
1479 | return 1; | 1862 | return 1; |
1480 | } | 1863 | } |
1481 | 1864 | ||
@@ -1557,7 +1940,7 @@ static int lbs_find_best_network_ssid(struct lbs_private *priv, | |||
1557 | 1940 | ||
1558 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); | 1941 | found = lbs_find_best_ssid_in_list(priv, preferred_mode); |
1559 | if (found && (found->ssid_len > 0)) { | 1942 | if (found && (found->ssid_len > 0)) { |
1560 | memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); | 1943 | memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN); |
1561 | *out_ssid_len = found->ssid_len; | 1944 | *out_ssid_len = found->ssid_len; |
1562 | *out_mode = found->mode; | 1945 | *out_mode = found->mode; |
1563 | ret = 0; | 1946 | ret = 0; |
@@ -1775,12 +2158,12 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) | |||
1775 | assoc_req = priv->pending_assoc_req; | 2158 | assoc_req = priv->pending_assoc_req; |
1776 | if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { | 2159 | if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { |
1777 | memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, | 2160 | memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, |
1778 | IW_ESSID_MAX_SIZE); | 2161 | IEEE80211_MAX_SSID_LEN); |
1779 | assoc_req->ssid_len = priv->curbssparams.ssid_len; | 2162 | assoc_req->ssid_len = priv->curbssparams.ssid_len; |
1780 | } | 2163 | } |
1781 | 2164 | ||
1782 | if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) | 2165 | if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) |
1783 | assoc_req->channel = priv->curbssparams.channel; | 2166 | assoc_req->channel = priv->channel; |
1784 | 2167 | ||
1785 | if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) | 2168 | if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) |
1786 | assoc_req->band = priv->curbssparams.band; | 2169 | assoc_req->band = priv->curbssparams.band; |
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 6e765e9f91a3..40621b789fc5 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h | |||
@@ -3,7 +3,126 @@ | |||
3 | #ifndef _LBS_ASSOC_H_ | 3 | #ifndef _LBS_ASSOC_H_ |
4 | #define _LBS_ASSOC_H_ | 4 | #define _LBS_ASSOC_H_ |
5 | 5 | ||
6 | #include "dev.h" | 6 | |
7 | #include "defs.h" | ||
8 | #include "host.h" | ||
9 | |||
10 | |||
11 | struct lbs_private; | ||
12 | |||
13 | /* | ||
14 | * In theory, the IE is limited to the IE length, 255, | ||
15 | * but in practice 64 bytes are enough. | ||
16 | */ | ||
17 | #define MAX_WPA_IE_LEN 64 | ||
18 | |||
19 | |||
20 | |||
21 | struct lbs_802_11_security { | ||
22 | u8 WPAenabled; | ||
23 | u8 WPA2enabled; | ||
24 | u8 wep_enabled; | ||
25 | u8 auth_mode; | ||
26 | u32 key_mgmt; | ||
27 | }; | ||
28 | |||
29 | /** Current Basic Service Set State Structure */ | ||
30 | struct current_bss_params { | ||
31 | /** bssid */ | ||
32 | u8 bssid[ETH_ALEN]; | ||
33 | /** ssid */ | ||
34 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
35 | u8 ssid_len; | ||
36 | |||
37 | /** band */ | ||
38 | u8 band; | ||
39 | /** channel is directly in priv->channel */ | ||
40 | /** zero-terminated array of supported data rates */ | ||
41 | u8 rates[MAX_RATES + 1]; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * @brief Structure used to store information for each beacon/probe response | ||
46 | */ | ||
47 | struct bss_descriptor { | ||
48 | u8 bssid[ETH_ALEN]; | ||
49 | |||
50 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
51 | u8 ssid_len; | ||
52 | |||
53 | u16 capability; | ||
54 | u32 rssi; | ||
55 | u32 channel; | ||
56 | u16 beaconperiod; | ||
57 | __le16 atimwindow; | ||
58 | |||
59 | /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ | ||
60 | u8 mode; | ||
61 | |||
62 | /* zero-terminated array of supported data rates */ | ||
63 | u8 rates[MAX_RATES + 1]; | ||
64 | |||
65 | unsigned long last_scanned; | ||
66 | |||
67 | union ieee_phy_param_set phy; | ||
68 | union ieee_ss_param_set ss; | ||
69 | |||
70 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
71 | size_t wpa_ie_len; | ||
72 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
73 | size_t rsn_ie_len; | ||
74 | |||
75 | u8 mesh; | ||
76 | |||
77 | struct list_head list; | ||
78 | }; | ||
79 | |||
80 | /** Association request | ||
81 | * | ||
82 | * Encapsulates all the options that describe a specific assocation request | ||
83 | * or configuration of the wireless card's radio, mode, and security settings. | ||
84 | */ | ||
85 | struct assoc_request { | ||
86 | #define ASSOC_FLAG_SSID 1 | ||
87 | #define ASSOC_FLAG_CHANNEL 2 | ||
88 | #define ASSOC_FLAG_BAND 3 | ||
89 | #define ASSOC_FLAG_MODE 4 | ||
90 | #define ASSOC_FLAG_BSSID 5 | ||
91 | #define ASSOC_FLAG_WEP_KEYS 6 | ||
92 | #define ASSOC_FLAG_WEP_TX_KEYIDX 7 | ||
93 | #define ASSOC_FLAG_WPA_MCAST_KEY 8 | ||
94 | #define ASSOC_FLAG_WPA_UCAST_KEY 9 | ||
95 | #define ASSOC_FLAG_SECINFO 10 | ||
96 | #define ASSOC_FLAG_WPA_IE 11 | ||
97 | unsigned long flags; | ||
98 | |||
99 | u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
100 | u8 ssid_len; | ||
101 | u8 channel; | ||
102 | u8 band; | ||
103 | u8 mode; | ||
104 | u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); | ||
105 | |||
106 | /** WEP keys */ | ||
107 | struct enc_key wep_keys[4]; | ||
108 | u16 wep_tx_keyidx; | ||
109 | |||
110 | /** WPA keys */ | ||
111 | struct enc_key wpa_mcast_key; | ||
112 | struct enc_key wpa_unicast_key; | ||
113 | |||
114 | struct lbs_802_11_security secinfo; | ||
115 | |||
116 | /** WPA Information Elements*/ | ||
117 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
118 | u8 wpa_ie_len; | ||
119 | |||
120 | /* BSS to associate with for infrastructure of Ad-Hoc join */ | ||
121 | struct bss_descriptor bss; | ||
122 | }; | ||
123 | |||
124 | |||
125 | extern u8 lbs_bg_rates[MAX_RATES]; | ||
7 | 126 | ||
8 | void lbs_association_worker(struct work_struct *work); | 127 | void lbs_association_worker(struct work_struct *work); |
9 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv); | 128 | struct assoc_request *lbs_get_association_request(struct lbs_private *priv); |
@@ -13,4 +132,24 @@ int lbs_adhoc_stop(struct lbs_private *priv); | |||
13 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, | 132 | int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, |
14 | u8 bssid[ETH_ALEN], u16 reason); | 133 | u8 bssid[ETH_ALEN], u16 reason); |
15 | 134 | ||
135 | int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
136 | struct cmd_ds_command *cmd); | ||
137 | int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
138 | struct cmd_ds_command *resp); | ||
139 | |||
140 | int lbs_cmd_bcn_ctrl(struct lbs_private *priv, | ||
141 | struct cmd_ds_command *cmd, | ||
142 | u16 cmd_action); | ||
143 | int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv, | ||
144 | struct cmd_ds_command *resp); | ||
145 | |||
146 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
147 | struct assoc_request *assoc); | ||
148 | |||
149 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
150 | uint16_t *enable); | ||
151 | |||
152 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
153 | struct assoc_request *assoc); | ||
154 | |||
16 | #endif /* _LBS_ASSOC_H */ | 155 | #endif /* _LBS_ASSOC_H */ |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 0fb312576b8d..1065ce29cd08 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -3,18 +3,20 @@ | |||
3 | * It prepares command and sends it to firmware when it is ready. | 3 | * It prepares command and sends it to firmware when it is ready. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <net/iw_handler.h> | ||
7 | #include <net/lib80211.h> | 6 | #include <net/lib80211.h> |
8 | #include <linux/kfifo.h> | 7 | #include <linux/kfifo.h> |
8 | #include <linux/sched.h> | ||
9 | |||
9 | #include "host.h" | 10 | #include "host.h" |
10 | #include "hostcmd.h" | ||
11 | #include "decl.h" | 11 | #include "decl.h" |
12 | #include "defs.h" | 12 | #include "defs.h" |
13 | #include "dev.h" | 13 | #include "dev.h" |
14 | #include "assoc.h" | 14 | #include "assoc.h" |
15 | #include "wext.h" | 15 | #include "wext.h" |
16 | #include "scan.h" | ||
16 | #include "cmd.h" | 17 | #include "cmd.h" |
17 | 18 | ||
19 | |||
18 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | 20 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); |
19 | 21 | ||
20 | /** | 22 | /** |
@@ -191,11 +193,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
191 | goto out; | 193 | goto out; |
192 | } | 194 | } |
193 | 195 | ||
194 | if (lbs_set_universaltable(priv, 0)) { | ||
195 | ret = -1; | ||
196 | goto out; | ||
197 | } | ||
198 | |||
199 | out: | 196 | out: |
200 | lbs_deb_leave(LBS_DEB_CMD); | 197 | lbs_deb_leave(LBS_DEB_CMD); |
201 | return ret; | 198 | return ret; |
@@ -244,7 +241,7 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
244 | 241 | ||
245 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); | 242 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); |
246 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + | 243 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + |
247 | S_DS_GEN); | 244 | sizeof(struct cmd_header)); |
248 | psm->action = cpu_to_le16(cmd_action); | 245 | psm->action = cpu_to_le16(cmd_action); |
249 | psm->multipledtim = 0; | 246 | psm->multipledtim = 0; |
250 | switch (cmd_action) { | 247 | switch (cmd_action) { |
@@ -273,33 +270,6 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
273 | return 0; | 270 | return 0; |
274 | } | 271 | } |
275 | 272 | ||
276 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | ||
277 | uint16_t cmd_action, uint16_t *timeout) | ||
278 | { | ||
279 | struct cmd_ds_802_11_inactivity_timeout cmd; | ||
280 | int ret; | ||
281 | |||
282 | lbs_deb_enter(LBS_DEB_CMD); | ||
283 | |||
284 | cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT); | ||
285 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
286 | |||
287 | cmd.action = cpu_to_le16(cmd_action); | ||
288 | |||
289 | if (cmd_action == CMD_ACT_SET) | ||
290 | cmd.timeout = cpu_to_le16(*timeout); | ||
291 | else | ||
292 | cmd.timeout = 0; | ||
293 | |||
294 | ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd); | ||
295 | |||
296 | if (!ret) | ||
297 | *timeout = le16_to_cpu(cmd.timeout); | ||
298 | |||
299 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 273 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
304 | struct sleep_params *sp) | 274 | struct sleep_params *sp) |
305 | { | 275 | { |
@@ -396,197 +366,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) | |||
396 | return ret; | 366 | return ret; |
397 | } | 367 | } |
398 | 368 | ||
399 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
400 | struct assoc_request *assoc) | ||
401 | { | ||
402 | struct cmd_ds_802_11_set_wep cmd; | ||
403 | int ret = 0; | ||
404 | |||
405 | lbs_deb_enter(LBS_DEB_CMD); | ||
406 | |||
407 | memset(&cmd, 0, sizeof(cmd)); | ||
408 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | ||
409 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
410 | |||
411 | cmd.action = cpu_to_le16(cmd_action); | ||
412 | |||
413 | if (cmd_action == CMD_ACT_ADD) { | ||
414 | int i; | ||
415 | |||
416 | /* default tx key index */ | ||
417 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
418 | CMD_WEP_KEY_INDEX_MASK); | ||
419 | |||
420 | /* Copy key types and material to host command structure */ | ||
421 | for (i = 0; i < 4; i++) { | ||
422 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
423 | |||
424 | switch (pkey->len) { | ||
425 | case KEY_LEN_WEP_40: | ||
426 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
427 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
428 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
429 | break; | ||
430 | case KEY_LEN_WEP_104: | ||
431 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
432 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
433 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
434 | break; | ||
435 | case 0: | ||
436 | break; | ||
437 | default: | ||
438 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
439 | i, pkey->len); | ||
440 | ret = -1; | ||
441 | goto done; | ||
442 | break; | ||
443 | } | ||
444 | } | ||
445 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
446 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
447 | |||
448 | /* default tx key index */ | ||
449 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
450 | CMD_WEP_KEY_INDEX_MASK); | ||
451 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
452 | } | ||
453 | |||
454 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
455 | done: | ||
456 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
461 | uint16_t *enable) | ||
462 | { | ||
463 | struct cmd_ds_802_11_enable_rsn cmd; | ||
464 | int ret; | ||
465 | |||
466 | lbs_deb_enter(LBS_DEB_CMD); | ||
467 | |||
468 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
469 | cmd.action = cpu_to_le16(cmd_action); | ||
470 | |||
471 | if (cmd_action == CMD_ACT_GET) | ||
472 | cmd.enable = 0; | ||
473 | else { | ||
474 | if (*enable) | ||
475 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
476 | else | ||
477 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
478 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
479 | } | ||
480 | |||
481 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
482 | if (!ret && cmd_action == CMD_ACT_GET) | ||
483 | *enable = le16_to_cpu(cmd.enable); | ||
484 | |||
485 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
486 | return ret; | ||
487 | } | ||
488 | |||
489 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | ||
490 | struct enc_key *key) | ||
491 | { | ||
492 | lbs_deb_enter(LBS_DEB_CMD); | ||
493 | |||
494 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
495 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
496 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
497 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
498 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
499 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
500 | |||
501 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
502 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
503 | keyparam->keylen = cpu_to_le16(key->len); | ||
504 | memcpy(keyparam->key, key->key, key->len); | ||
505 | |||
506 | /* Length field doesn't include the {type,length} header */ | ||
507 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
508 | lbs_deb_leave(LBS_DEB_CMD); | ||
509 | } | ||
510 | |||
511 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
512 | struct assoc_request *assoc) | ||
513 | { | ||
514 | struct cmd_ds_802_11_key_material cmd; | ||
515 | int ret = 0; | ||
516 | int index = 0; | ||
517 | |||
518 | lbs_deb_enter(LBS_DEB_CMD); | ||
519 | |||
520 | cmd.action = cpu_to_le16(cmd_action); | ||
521 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
522 | |||
523 | if (cmd_action == CMD_ACT_GET) { | ||
524 | cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); | ||
525 | } else { | ||
526 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | ||
527 | |||
528 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | ||
529 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
530 | &assoc->wpa_unicast_key); | ||
531 | index++; | ||
532 | } | ||
533 | |||
534 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
535 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
536 | &assoc->wpa_mcast_key); | ||
537 | index++; | ||
538 | } | ||
539 | |||
540 | /* The common header and as many keys as we included */ | ||
541 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | ||
542 | keyParamSet[index])); | ||
543 | } | ||
544 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | ||
545 | /* Copy the returned key to driver private data */ | ||
546 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
547 | void *buf_ptr = cmd.keyParamSet; | ||
548 | void *resp_end = &(&cmd)[1]; | ||
549 | |||
550 | while (buf_ptr < resp_end) { | ||
551 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
552 | struct enc_key *key; | ||
553 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
554 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
555 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
556 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
557 | void *end; | ||
558 | |||
559 | end = (void *)keyparam + sizeof(keyparam->type) | ||
560 | + sizeof(keyparam->length) + param_set_len; | ||
561 | |||
562 | /* Make sure we don't access past the end of the IEs */ | ||
563 | if (end > resp_end) | ||
564 | break; | ||
565 | |||
566 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
567 | key = &priv->wpa_unicast_key; | ||
568 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
569 | key = &priv->wpa_mcast_key; | ||
570 | else | ||
571 | break; | ||
572 | |||
573 | /* Copy returned key into driver */ | ||
574 | memset(key, 0, sizeof(struct enc_key)); | ||
575 | if (key_len > sizeof(key->key)) | ||
576 | break; | ||
577 | key->type = key_type; | ||
578 | key->flags = key_flags; | ||
579 | key->len = key_len; | ||
580 | memcpy(key->key, keyparam->key, key->len); | ||
581 | |||
582 | buf_ptr = end + 1; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
587 | return ret; | ||
588 | } | ||
589 | |||
590 | /** | 369 | /** |
591 | * @brief Set an SNMP MIB value | 370 | * @brief Set an SNMP MIB value |
592 | * | 371 | * |
@@ -611,7 +390,7 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) | |||
611 | switch (oid) { | 390 | switch (oid) { |
612 | case SNMP_MIB_OID_BSS_TYPE: | 391 | case SNMP_MIB_OID_BSS_TYPE: |
613 | cmd.bufsize = cpu_to_le16(sizeof(u8)); | 392 | cmd.bufsize = cpu_to_le16(sizeof(u8)); |
614 | cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1; | 393 | cmd.value[0] = val; |
615 | break; | 394 | break; |
616 | case SNMP_MIB_OID_11D_ENABLE: | 395 | case SNMP_MIB_OID_11D_ENABLE: |
617 | case SNMP_MIB_OID_FRAG_THRESHOLD: | 396 | case SNMP_MIB_OID_FRAG_THRESHOLD: |
@@ -664,13 +443,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) | |||
664 | 443 | ||
665 | switch (le16_to_cpu(cmd.bufsize)) { | 444 | switch (le16_to_cpu(cmd.bufsize)) { |
666 | case sizeof(u8): | 445 | case sizeof(u8): |
667 | if (oid == SNMP_MIB_OID_BSS_TYPE) { | 446 | *out_val = cmd.value[0]; |
668 | if (cmd.value[0] == 2) | ||
669 | *out_val = IW_MODE_ADHOC; | ||
670 | else | ||
671 | *out_val = IW_MODE_INFRA; | ||
672 | } else | ||
673 | *out_val = cmd.value[0]; | ||
674 | break; | 447 | break; |
675 | case sizeof(u16): | 448 | case sizeof(u16): |
676 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); | 449 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); |
@@ -757,7 +530,7 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
757 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); | 530 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); |
758 | cmd->size = | 531 | cmd->size = |
759 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + | 532 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + |
760 | S_DS_GEN); | 533 | sizeof(struct cmd_header)); |
761 | 534 | ||
762 | monitor->action = cpu_to_le16(cmd_action); | 535 | monitor->action = cpu_to_le16(cmd_action); |
763 | if (cmd_action == CMD_ACT_SET) { | 536 | if (cmd_action == CMD_ACT_SET) { |
@@ -768,111 +541,6 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
768 | return 0; | 541 | return 0; |
769 | } | 542 | } |
770 | 543 | ||
771 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
772 | { | ||
773 | /* Bit Rate | ||
774 | * 15:13 Reserved | ||
775 | * 12 54 Mbps | ||
776 | * 11 48 Mbps | ||
777 | * 10 36 Mbps | ||
778 | * 9 24 Mbps | ||
779 | * 8 18 Mbps | ||
780 | * 7 12 Mbps | ||
781 | * 6 9 Mbps | ||
782 | * 5 6 Mbps | ||
783 | * 4 Reserved | ||
784 | * 3 11 Mbps | ||
785 | * 2 5.5 Mbps | ||
786 | * 1 2 Mbps | ||
787 | * 0 1 Mbps | ||
788 | **/ | ||
789 | |||
790 | uint16_t ratemask; | ||
791 | int i = lbs_data_rate_to_fw_index(rate); | ||
792 | if (lower_rates_ok) | ||
793 | ratemask = (0x1fef >> (12 - i)); | ||
794 | else | ||
795 | ratemask = (1 << i); | ||
796 | return cpu_to_le16(ratemask); | ||
797 | } | ||
798 | |||
799 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
800 | uint16_t cmd_action) | ||
801 | { | ||
802 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
803 | int ret; | ||
804 | |||
805 | lbs_deb_enter(LBS_DEB_CMD); | ||
806 | |||
807 | if (!priv->cur_rate && !priv->enablehwauto) | ||
808 | return -EINVAL; | ||
809 | |||
810 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
811 | |||
812 | cmd.action = cpu_to_le16(cmd_action); | ||
813 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
814 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
815 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
816 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
817 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
818 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
819 | } | ||
820 | |||
821 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
822 | return ret; | ||
823 | } | ||
824 | EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset); | ||
825 | |||
826 | /** | ||
827 | * @brief Set the data rate | ||
828 | * | ||
829 | * @param priv A pointer to struct lbs_private structure | ||
830 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
831 | * | ||
832 | * @return 0 on success, error on failure | ||
833 | */ | ||
834 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
835 | { | ||
836 | struct cmd_ds_802_11_data_rate cmd; | ||
837 | int ret = 0; | ||
838 | |||
839 | lbs_deb_enter(LBS_DEB_CMD); | ||
840 | |||
841 | memset(&cmd, 0, sizeof(cmd)); | ||
842 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
843 | |||
844 | if (rate > 0) { | ||
845 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
846 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
847 | if (cmd.rates[0] == 0) { | ||
848 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
849 | " 0x%02X\n", rate); | ||
850 | ret = 0; | ||
851 | goto out; | ||
852 | } | ||
853 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
854 | } else { | ||
855 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
856 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
857 | } | ||
858 | |||
859 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
860 | if (ret) | ||
861 | goto out; | ||
862 | |||
863 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); | ||
864 | |||
865 | /* FIXME: get actual rates FW can do if this command actually returns | ||
866 | * all data rates supported. | ||
867 | */ | ||
868 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
869 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
870 | |||
871 | out: | ||
872 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
873 | return ret; | ||
874 | } | ||
875 | |||
876 | /** | 544 | /** |
877 | * @brief Get the radio channel | 545 | * @brief Get the radio channel |
878 | * | 546 | * |
@@ -880,7 +548,7 @@ out: | |||
880 | * | 548 | * |
881 | * @return The channel on success, error on failure | 549 | * @return The channel on success, error on failure |
882 | */ | 550 | */ |
883 | int lbs_get_channel(struct lbs_private *priv) | 551 | static int lbs_get_channel(struct lbs_private *priv) |
884 | { | 552 | { |
885 | struct cmd_ds_802_11_rf_channel cmd; | 553 | struct cmd_ds_802_11_rf_channel cmd; |
886 | int ret = 0; | 554 | int ret = 0; |
@@ -912,7 +580,7 @@ int lbs_update_channel(struct lbs_private *priv) | |||
912 | 580 | ||
913 | ret = lbs_get_channel(priv); | 581 | ret = lbs_get_channel(priv); |
914 | if (ret > 0) { | 582 | if (ret > 0) { |
915 | priv->curbssparams.channel = ret; | 583 | priv->channel = ret; |
916 | ret = 0; | 584 | ret = 0; |
917 | } | 585 | } |
918 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 586 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -931,7 +599,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
931 | { | 599 | { |
932 | struct cmd_ds_802_11_rf_channel cmd; | 600 | struct cmd_ds_802_11_rf_channel cmd; |
933 | #ifdef DEBUG | 601 | #ifdef DEBUG |
934 | u8 old_channel = priv->curbssparams.channel; | 602 | u8 old_channel = priv->channel; |
935 | #endif | 603 | #endif |
936 | int ret = 0; | 604 | int ret = 0; |
937 | 605 | ||
@@ -946,36 +614,15 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
946 | if (ret) | 614 | if (ret) |
947 | goto out; | 615 | goto out; |
948 | 616 | ||
949 | priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel); | 617 | priv->channel = (uint8_t) le16_to_cpu(cmd.channel); |
950 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, | 618 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, |
951 | priv->curbssparams.channel); | 619 | priv->channel); |
952 | 620 | ||
953 | out: | 621 | out: |
954 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 622 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
955 | return ret; | 623 | return ret; |
956 | } | 624 | } |
957 | 625 | ||
958 | static int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
959 | struct cmd_ds_command *cmd) | ||
960 | { | ||
961 | |||
962 | lbs_deb_enter(LBS_DEB_CMD); | ||
963 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
964 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); | ||
965 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
966 | |||
967 | /* reset Beacon SNR/NF/RSSI values */ | ||
968 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
969 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
970 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
971 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
972 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
973 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
974 | |||
975 | lbs_deb_leave(LBS_DEB_CMD); | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | 626 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, |
980 | u8 cmd_action, void *pdata_buf) | 627 | u8 cmd_action, void *pdata_buf) |
981 | { | 628 | { |
@@ -992,7 +639,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
992 | 639 | ||
993 | cmdptr->size = | 640 | cmdptr->size = |
994 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) | 641 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) |
995 | + S_DS_GEN); | 642 | + sizeof(struct cmd_header)); |
996 | macreg = | 643 | macreg = |
997 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. | 644 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. |
998 | macreg; | 645 | macreg; |
@@ -1011,7 +658,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
1011 | cmdptr->size = | 658 | cmdptr->size = |
1012 | cpu_to_le16(sizeof | 659 | cpu_to_le16(sizeof |
1013 | (struct cmd_ds_bbp_reg_access) | 660 | (struct cmd_ds_bbp_reg_access) |
1014 | + S_DS_GEN); | 661 | + sizeof(struct cmd_header)); |
1015 | bbpreg = | 662 | bbpreg = |
1016 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. | 663 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. |
1017 | bbpreg; | 664 | bbpreg; |
@@ -1030,7 +677,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
1030 | cmdptr->size = | 677 | cmdptr->size = |
1031 | cpu_to_le16(sizeof | 678 | cpu_to_le16(sizeof |
1032 | (struct cmd_ds_rf_reg_access) + | 679 | (struct cmd_ds_rf_reg_access) + |
1033 | S_DS_GEN); | 680 | sizeof(struct cmd_header)); |
1034 | rfreg = | 681 | rfreg = |
1035 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. | 682 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. |
1036 | rfreg; | 683 | rfreg; |
@@ -1057,7 +704,8 @@ static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | |||
1057 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | 704 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); |
1058 | 705 | ||
1059 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | 706 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); |
1060 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); | 707 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + |
708 | sizeof(struct cmd_header)); | ||
1061 | cmd->result = 0; | 709 | cmd->result = 0; |
1062 | bt_access->action = cpu_to_le16(cmd_action); | 710 | bt_access->action = cpu_to_le16(cmd_action); |
1063 | 711 | ||
@@ -1094,7 +742,8 @@ static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | |||
1094 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | 742 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); |
1095 | 743 | ||
1096 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | 744 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); |
1097 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); | 745 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + |
746 | sizeof(struct cmd_header)); | ||
1098 | cmd->result = 0; | 747 | cmd->result = 0; |
1099 | 748 | ||
1100 | if (pdata_buf) | 749 | if (pdata_buf) |
@@ -1200,7 +849,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | |||
1200 | ie->val.mesh_id_len = priv->mesh_ssid_len; | 849 | ie->val.mesh_id_len = priv->mesh_ssid_len; |
1201 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); | 850 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); |
1202 | ie->len = sizeof(struct mrvl_meshie_val) - | 851 | ie->len = sizeof(struct mrvl_meshie_val) - |
1203 | IW_ESSID_MAX_SIZE + priv->mesh_ssid_len; | 852 | IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len; |
1204 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); | 853 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); |
1205 | break; | 854 | break; |
1206 | case CMD_ACT_MESH_CONFIG_STOP: | 855 | case CMD_ACT_MESH_CONFIG_STOP: |
@@ -1215,27 +864,6 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | |||
1215 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | 864 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); |
1216 | } | 865 | } |
1217 | 866 | ||
1218 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, | ||
1219 | struct cmd_ds_command *cmd, | ||
1220 | u16 cmd_action) | ||
1221 | { | ||
1222 | struct cmd_ds_802_11_beacon_control | ||
1223 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
1224 | |||
1225 | lbs_deb_enter(LBS_DEB_CMD); | ||
1226 | cmd->size = | ||
1227 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
1228 | + S_DS_GEN); | ||
1229 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
1230 | |||
1231 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
1232 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
1233 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
1234 | |||
1235 | lbs_deb_leave(LBS_DEB_CMD); | ||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | static void lbs_queue_cmd(struct lbs_private *priv, | 867 | static void lbs_queue_cmd(struct lbs_private *priv, |
1240 | struct cmd_ctrl_node *cmdnode) | 868 | struct cmd_ctrl_node *cmdnode) |
1241 | { | 869 | { |
@@ -1531,7 +1159,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1531 | 1159 | ||
1532 | cmdptr->command = cpu_to_le16(cmd_no); | 1160 | cmdptr->command = cpu_to_le16(cmd_no); |
1533 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + | 1161 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + |
1534 | S_DS_GEN); | 1162 | sizeof(struct cmd_header)); |
1535 | 1163 | ||
1536 | memmove(&cmdptr->params.afc, | 1164 | memmove(&cmdptr->params.afc, |
1537 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); | 1165 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); |
@@ -1539,45 +1167,17 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1539 | ret = 0; | 1167 | ret = 0; |
1540 | goto done; | 1168 | goto done; |
1541 | 1169 | ||
1542 | case CMD_802_11D_DOMAIN_INFO: | ||
1543 | ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, | ||
1544 | cmd_no, cmd_action); | ||
1545 | break; | ||
1546 | |||
1547 | case CMD_802_11_TPC_CFG: | 1170 | case CMD_802_11_TPC_CFG: |
1548 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); | 1171 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); |
1549 | cmdptr->size = | 1172 | cmdptr->size = |
1550 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + | 1173 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + |
1551 | S_DS_GEN); | 1174 | sizeof(struct cmd_header)); |
1552 | 1175 | ||
1553 | memmove(&cmdptr->params.tpccfg, | 1176 | memmove(&cmdptr->params.tpccfg, |
1554 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); | 1177 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); |
1555 | 1178 | ||
1556 | ret = 0; | 1179 | ret = 0; |
1557 | break; | 1180 | break; |
1558 | case CMD_802_11_LED_GPIO_CTRL: | ||
1559 | { | ||
1560 | struct mrvl_ie_ledgpio *gpio = | ||
1561 | (struct mrvl_ie_ledgpio*) | ||
1562 | cmdptr->params.ledgpio.data; | ||
1563 | |||
1564 | memmove(&cmdptr->params.ledgpio, | ||
1565 | pdata_buf, | ||
1566 | sizeof(struct cmd_ds_802_11_led_ctrl)); | ||
1567 | |||
1568 | cmdptr->command = | ||
1569 | cpu_to_le16(CMD_802_11_LED_GPIO_CTRL); | ||
1570 | |||
1571 | #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 | ||
1572 | cmdptr->size = | ||
1573 | cpu_to_le16(le16_to_cpu(gpio->header.len) | ||
1574 | + S_DS_GEN | ||
1575 | + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); | ||
1576 | gpio->header.len = gpio->header.len; | ||
1577 | |||
1578 | ret = 0; | ||
1579 | break; | ||
1580 | } | ||
1581 | 1181 | ||
1582 | case CMD_BT_ACCESS: | 1182 | case CMD_BT_ACCESS: |
1583 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); | 1183 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); |
@@ -1587,18 +1187,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1587 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); | 1187 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); |
1588 | break; | 1188 | break; |
1589 | 1189 | ||
1590 | case CMD_GET_TSF: | ||
1591 | cmdptr->command = cpu_to_le16(CMD_GET_TSF); | ||
1592 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + | ||
1593 | S_DS_GEN); | ||
1594 | ret = 0; | ||
1595 | break; | ||
1596 | case CMD_802_11_BEACON_CTRL: | 1190 | case CMD_802_11_BEACON_CTRL: |
1597 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1191 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1598 | break; | 1192 | break; |
1599 | case CMD_802_11_DEEP_SLEEP: | 1193 | case CMD_802_11_DEEP_SLEEP: |
1600 | cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); | 1194 | cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); |
1601 | cmdptr->size = cpu_to_le16(S_DS_GEN); | 1195 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_header)); |
1602 | break; | 1196 | break; |
1603 | default: | 1197 | default: |
1604 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); | 1198 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); |
@@ -1917,30 +1511,6 @@ done: | |||
1917 | return ret; | 1511 | return ret; |
1918 | } | 1512 | } |
1919 | 1513 | ||
1920 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
1921 | { | ||
1922 | union iwreq_data iwrq; | ||
1923 | u8 buf[50]; | ||
1924 | |||
1925 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1926 | |||
1927 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
1928 | memset(buf, 0, sizeof(buf)); | ||
1929 | |||
1930 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
1931 | |||
1932 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
1933 | |||
1934 | /* Send Event to upper layer */ | ||
1935 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
1936 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
1937 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
1938 | |||
1939 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
1940 | |||
1941 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1942 | } | ||
1943 | |||
1944 | static void lbs_send_confirmsleep(struct lbs_private *priv) | 1514 | static void lbs_send_confirmsleep(struct lbs_private *priv) |
1945 | { | 1515 | { |
1946 | unsigned long flags; | 1516 | unsigned long flags; |
@@ -2118,7 +1688,7 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | |||
2118 | } | 1688 | } |
2119 | 1689 | ||
2120 | 1690 | ||
2121 | static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | 1691 | struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, |
2122 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, | 1692 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, |
2123 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | 1693 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), |
2124 | unsigned long callback_arg) | 1694 | unsigned long callback_arg) |
@@ -2216,5 +1786,3 @@ done: | |||
2216 | return ret; | 1786 | return ret; |
2217 | } | 1787 | } |
2218 | EXPORT_SYMBOL_GPL(__lbs_cmd); | 1788 | EXPORT_SYMBOL_GPL(__lbs_cmd); |
2219 | |||
2220 | |||
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 392e578ca095..2862748aef70 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -3,11 +3,30 @@ | |||
3 | #ifndef _LBS_CMD_H_ | 3 | #ifndef _LBS_CMD_H_ |
4 | #define _LBS_CMD_H_ | 4 | #define _LBS_CMD_H_ |
5 | 5 | ||
6 | #include "hostcmd.h" | 6 | #include "host.h" |
7 | #include "dev.h" | 7 | #include "dev.h" |
8 | 8 | ||
9 | |||
10 | /* Command & response transfer between host and card */ | ||
11 | |||
12 | struct cmd_ctrl_node { | ||
13 | struct list_head list; | ||
14 | int result; | ||
15 | /* command response */ | ||
16 | int (*callback)(struct lbs_private *, | ||
17 | unsigned long, | ||
18 | struct cmd_header *); | ||
19 | unsigned long callback_arg; | ||
20 | /* command data */ | ||
21 | struct cmd_header *cmdbuf; | ||
22 | /* wait queue */ | ||
23 | u16 cmdwaitqwoken; | ||
24 | wait_queue_head_t cmdwait_q; | ||
25 | }; | ||
26 | |||
27 | |||
9 | /* lbs_cmd() infers the size of the buffer to copy data back into, from | 28 | /* lbs_cmd() infers the size of the buffer to copy data back into, from |
10 | the size of the target of the pointer. Since the command to be sent | 29 | the size of the target of the pointer. Since the command to be sent |
11 | may often be smaller, that size is set in cmd->size by the caller.*/ | 30 | may often be smaller, that size is set in cmd->size by the caller.*/ |
12 | #define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ | 31 | #define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ |
13 | uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ | 32 | uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ |
@@ -18,6 +37,11 @@ | |||
18 | #define lbs_cmd_with_response(priv, cmdnr, cmd) \ | 37 | #define lbs_cmd_with_response(priv, cmdnr, cmd) \ |
19 | lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) | 38 | lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) |
20 | 39 | ||
40 | int lbs_prepare_and_send_command(struct lbs_private *priv, | ||
41 | u16 cmd_no, | ||
42 | u16 cmd_action, | ||
43 | u16 wait_option, u32 cmd_oid, void *pdata_buf); | ||
44 | |||
21 | void lbs_cmd_async(struct lbs_private *priv, uint16_t command, | 45 | void lbs_cmd_async(struct lbs_private *priv, uint16_t command, |
22 | struct cmd_header *in_cmd, int in_cmd_size); | 46 | struct cmd_header *in_cmd, int in_cmd_size); |
23 | 47 | ||
@@ -26,62 +50,93 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command, | |||
26 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | 50 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), |
27 | unsigned long callback_arg); | 51 | unsigned long callback_arg); |
28 | 52 | ||
29 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 53 | struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, |
30 | int8_t p1, int8_t p2); | 54 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, |
55 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | ||
56 | unsigned long callback_arg); | ||
31 | 57 | ||
32 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | 58 | int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, |
33 | int8_t p2, int usesnr); | 59 | struct cmd_header *resp); |
34 | 60 | ||
35 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | 61 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); |
36 | int8_t p1, int8_t p2); | 62 | int lbs_free_cmd_buffer(struct lbs_private *priv); |
37 | 63 | ||
38 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | 64 | int lbs_execute_next_command(struct lbs_private *priv); |
39 | int8_t p2, int usesnr); | 65 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, |
66 | int result); | ||
67 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); | ||
40 | 68 | ||
41 | int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, | ||
42 | struct cmd_header *resp); | ||
43 | 69 | ||
44 | int lbs_update_hw_spec(struct lbs_private *priv); | 70 | /* From cmdresp.c */ |
45 | 71 | ||
46 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | 72 | void lbs_mac_event_disconnected(struct lbs_private *priv); |
47 | struct cmd_ds_mesh_access *cmd); | ||
48 | 73 | ||
49 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate); | ||
50 | 74 | ||
51 | int lbs_get_channel(struct lbs_private *priv); | 75 | |
76 | /* Events */ | ||
77 | |||
78 | int lbs_process_event(struct lbs_private *priv, u32 event); | ||
79 | |||
80 | |||
81 | /* Actual commands */ | ||
82 | |||
83 | int lbs_update_hw_spec(struct lbs_private *priv); | ||
84 | |||
52 | int lbs_set_channel(struct lbs_private *priv, u8 channel); | 85 | int lbs_set_channel(struct lbs_private *priv, u8 channel); |
53 | 86 | ||
54 | int lbs_mesh_config_send(struct lbs_private *priv, | 87 | int lbs_update_channel(struct lbs_private *priv); |
55 | struct cmd_ds_mesh_config *cmd, | ||
56 | uint16_t action, uint16_t type); | ||
57 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
58 | 88 | ||
59 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | 89 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, |
60 | struct wol_config *p_wol_config); | 90 | struct wol_config *p_wol_config); |
61 | int lbs_suspend(struct lbs_private *priv); | ||
62 | void lbs_resume(struct lbs_private *priv); | ||
63 | 91 | ||
64 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
65 | uint16_t cmd_action); | ||
66 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | ||
67 | uint16_t cmd_action, uint16_t *timeout); | ||
68 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 92 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
69 | struct sleep_params *sp); | 93 | struct sleep_params *sp); |
70 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | ||
71 | struct assoc_request *assoc); | ||
72 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
73 | uint16_t *enable); | ||
74 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
75 | struct assoc_request *assoc); | ||
76 | 94 | ||
77 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | 95 | void lbs_ps_sleep(struct lbs_private *priv, int wait_option); |
78 | s16 *maxlevel); | 96 | |
79 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); | 97 | void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); |
98 | |||
99 | void lbs_ps_confirm_sleep(struct lbs_private *priv); | ||
80 | 100 | ||
81 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); | 101 | int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); |
82 | 102 | ||
103 | void lbs_set_mac_control(struct lbs_private *priv); | ||
104 | |||
105 | int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, | ||
106 | s16 *maxlevel); | ||
107 | |||
83 | int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); | 108 | int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); |
84 | 109 | ||
85 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); | 110 | int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); |
86 | 111 | ||
112 | |||
113 | /* Mesh related */ | ||
114 | |||
115 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
116 | struct cmd_ds_mesh_access *cmd); | ||
117 | |||
118 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
119 | struct cmd_ds_mesh_config *cmd, | ||
120 | uint16_t action, uint16_t type); | ||
121 | |||
122 | int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); | ||
123 | |||
124 | |||
125 | /* Commands only used in wext.c, assoc. and scan.c */ | ||
126 | |||
127 | int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | ||
128 | int8_t p1, int8_t p2); | ||
129 | |||
130 | int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, | ||
131 | int8_t p2, int usesnr); | ||
132 | |||
133 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate); | ||
134 | |||
135 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
136 | uint16_t cmd_action); | ||
137 | |||
138 | int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); | ||
139 | |||
140 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); | ||
141 | |||
87 | #endif /* _LBS_CMD_H */ | 142 | #endif /* _LBS_CMD_H */ |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 9ee8bd11bda9..21d57690c20a 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include "host.h" | 12 | #include "host.h" |
13 | #include "decl.h" | 13 | #include "decl.h" |
14 | #include "cmd.h" | ||
14 | #include "defs.h" | 15 | #include "defs.h" |
15 | #include "dev.h" | 16 | #include "dev.h" |
16 | #include "assoc.h" | 17 | #include "assoc.h" |
@@ -26,23 +27,17 @@ | |||
26 | */ | 27 | */ |
27 | void lbs_mac_event_disconnected(struct lbs_private *priv) | 28 | void lbs_mac_event_disconnected(struct lbs_private *priv) |
28 | { | 29 | { |
29 | union iwreq_data wrqu; | ||
30 | |||
31 | if (priv->connect_status != LBS_CONNECTED) | 30 | if (priv->connect_status != LBS_CONNECTED) |
32 | return; | 31 | return; |
33 | 32 | ||
34 | lbs_deb_enter(LBS_DEB_ASSOC); | 33 | lbs_deb_enter(LBS_DEB_ASSOC); |
35 | 34 | ||
36 | memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); | ||
37 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
38 | |||
39 | /* | 35 | /* |
40 | * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. | 36 | * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. |
41 | * It causes problem in the Supplicant | 37 | * It causes problem in the Supplicant |
42 | */ | 38 | */ |
43 | |||
44 | msleep_interruptible(1000); | 39 | msleep_interruptible(1000); |
45 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | 40 | lbs_send_disconnect_notification(priv); |
46 | 41 | ||
47 | /* report disconnect to upper layer */ | 42 | /* report disconnect to upper layer */ |
48 | netif_stop_queue(priv->dev); | 43 | netif_stop_queue(priv->dev); |
@@ -67,7 +62,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
67 | * no longer valid. | 62 | * no longer valid. |
68 | */ | 63 | */ |
69 | memset(&priv->curbssparams.bssid, 0, ETH_ALEN); | 64 | memset(&priv->curbssparams.bssid, 0, ETH_ALEN); |
70 | memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE); | 65 | memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN); |
71 | priv->curbssparams.ssid_len = 0; | 66 | priv->curbssparams.ssid_len = 0; |
72 | 67 | ||
73 | if (priv->psstate != PS_STATE_FULL_POWER) { | 68 | if (priv->psstate != PS_STATE_FULL_POWER) { |
@@ -78,32 +73,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) | |||
78 | lbs_deb_leave(LBS_DEB_ASSOC); | 73 | lbs_deb_leave(LBS_DEB_ASSOC); |
79 | } | 74 | } |
80 | 75 | ||
81 | /** | ||
82 | * @brief This function handles MIC failure event. | ||
83 | * | ||
84 | * @param priv A pointer to struct lbs_private structure | ||
85 | * @para event the event id | ||
86 | * @return n/a | ||
87 | */ | ||
88 | static void handle_mic_failureevent(struct lbs_private *priv, u32 event) | ||
89 | { | ||
90 | char buf[50]; | ||
91 | |||
92 | lbs_deb_enter(LBS_DEB_CMD); | ||
93 | memset(buf, 0, sizeof(buf)); | ||
94 | |||
95 | sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); | ||
96 | |||
97 | if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { | ||
98 | strcat(buf, "unicast "); | ||
99 | } else { | ||
100 | strcat(buf, "multicast "); | ||
101 | } | ||
102 | |||
103 | lbs_send_iwevcustom_event(priv, buf); | ||
104 | lbs_deb_leave(LBS_DEB_CMD); | ||
105 | } | ||
106 | |||
107 | static int lbs_ret_reg_access(struct lbs_private *priv, | 76 | static int lbs_ret_reg_access(struct lbs_private *priv, |
108 | u16 type, struct cmd_ds_command *resp) | 77 | u16 type, struct cmd_ds_command *resp) |
109 | { | 78 | { |
@@ -147,53 +116,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv, | |||
147 | return ret; | 116 | return ret; |
148 | } | 117 | } |
149 | 118 | ||
150 | static int lbs_ret_802_11_rssi(struct lbs_private *priv, | ||
151 | struct cmd_ds_command *resp) | ||
152 | { | ||
153 | struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; | ||
154 | |||
155 | lbs_deb_enter(LBS_DEB_CMD); | ||
156 | |||
157 | /* store the non average value */ | ||
158 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); | ||
159 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor); | ||
160 | |||
161 | priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); | ||
162 | priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor); | ||
163 | |||
164 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = | ||
165 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], | ||
166 | priv->NF[TYPE_BEACON][TYPE_NOAVG]); | ||
167 | |||
168 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = | ||
169 | CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, | ||
170 | priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); | ||
171 | |||
172 | lbs_deb_cmd("RSSI: beacon %d, avg %d\n", | ||
173 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG], | ||
174 | priv->RSSI[TYPE_BEACON][TYPE_AVG]); | ||
175 | |||
176 | lbs_deb_leave(LBS_DEB_CMD); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, | ||
181 | struct cmd_ds_command *resp) | ||
182 | { | ||
183 | struct cmd_ds_802_11_beacon_control *bcn_ctrl = | ||
184 | &resp->params.bcn_ctrl; | ||
185 | |||
186 | lbs_deb_enter(LBS_DEB_CMD); | ||
187 | |||
188 | if (bcn_ctrl->action == CMD_ACT_GET) { | ||
189 | priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); | ||
190 | priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); | ||
191 | } | ||
192 | |||
193 | lbs_deb_enter(LBS_DEB_CMD); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static inline int handle_cmd_response(struct lbs_private *priv, | 119 | static inline int handle_cmd_response(struct lbs_private *priv, |
198 | struct cmd_header *cmd_response) | 120 | struct cmd_header *cmd_response) |
199 | { | 121 | { |
@@ -227,29 +149,13 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
227 | ret = lbs_ret_802_11_rssi(priv, resp); | 149 | ret = lbs_ret_802_11_rssi(priv, resp); |
228 | break; | 150 | break; |
229 | 151 | ||
230 | case CMD_RET(CMD_802_11D_DOMAIN_INFO): | ||
231 | ret = lbs_ret_802_11d_domain_info(resp); | ||
232 | break; | ||
233 | |||
234 | case CMD_RET(CMD_802_11_TPC_CFG): | 152 | case CMD_RET(CMD_802_11_TPC_CFG): |
235 | spin_lock_irqsave(&priv->driver_lock, flags); | 153 | spin_lock_irqsave(&priv->driver_lock, flags); |
236 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, | 154 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, |
237 | sizeof(struct cmd_ds_802_11_tpc_cfg)); | 155 | sizeof(struct cmd_ds_802_11_tpc_cfg)); |
238 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 156 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
239 | break; | 157 | break; |
240 | case CMD_RET(CMD_802_11_LED_GPIO_CTRL): | ||
241 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
242 | memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio, | ||
243 | sizeof(struct cmd_ds_802_11_led_ctrl)); | ||
244 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
245 | break; | ||
246 | 158 | ||
247 | case CMD_RET(CMD_GET_TSF): | ||
248 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
249 | memcpy((void *)priv->cur_cmd->callback_arg, | ||
250 | &resp->params.gettsf.tsfvalue, sizeof(u64)); | ||
251 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
252 | break; | ||
253 | case CMD_RET(CMD_BT_ACCESS): | 159 | case CMD_RET(CMD_BT_ACCESS): |
254 | spin_lock_irqsave(&priv->driver_lock, flags); | 160 | spin_lock_irqsave(&priv->driver_lock, flags); |
255 | if (priv->cur_cmd->callback_arg) | 161 | if (priv->cur_cmd->callback_arg) |
@@ -545,12 +451,12 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
545 | 451 | ||
546 | case MACREG_INT_CODE_MIC_ERR_UNICAST: | 452 | case MACREG_INT_CODE_MIC_ERR_UNICAST: |
547 | lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); | 453 | lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); |
548 | handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST); | 454 | lbs_send_mic_failureevent(priv, event); |
549 | break; | 455 | break; |
550 | 456 | ||
551 | case MACREG_INT_CODE_MIC_ERR_MULTICAST: | 457 | case MACREG_INT_CODE_MIC_ERR_MULTICAST: |
552 | lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); | 458 | lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); |
553 | handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); | 459 | lbs_send_mic_failureevent(priv, event); |
554 | break; | 460 | break; |
555 | 461 | ||
556 | case MACREG_INT_CODE_MIB_CHANGED: | 462 | case MACREG_INT_CODE_MIB_CHANGED: |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 893a55ca344a..587b0cb0088d 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -451,10 +451,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, | |||
451 | CMD_MAC_REG_ACCESS, 0, | 451 | CMD_MAC_REG_ACCESS, 0, |
452 | CMD_OPTION_WAITFORRSP, 0, &offval); | 452 | CMD_OPTION_WAITFORRSP, 0, &offval); |
453 | mdelay(10); | 453 | mdelay(10); |
454 | pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", | 454 | if (!ret) { |
455 | pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", | ||
455 | priv->mac_offset, priv->offsetvalue.value); | 456 | priv->mac_offset, priv->offsetvalue.value); |
456 | 457 | ||
457 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 458 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
459 | } | ||
458 | free_page(addr); | 460 | free_page(addr); |
459 | return ret; | 461 | return ret; |
460 | } | 462 | } |
@@ -514,7 +516,8 @@ static ssize_t lbs_wrmac_write(struct file *file, | |||
514 | CMD_OPTION_WAITFORRSP, 0, &offval); | 516 | CMD_OPTION_WAITFORRSP, 0, &offval); |
515 | mdelay(10); | 517 | mdelay(10); |
516 | 518 | ||
517 | res = count; | 519 | if (!res) |
520 | res = count; | ||
518 | out_unlock: | 521 | out_unlock: |
519 | free_page(addr); | 522 | free_page(addr); |
520 | return res; | 523 | return res; |
@@ -539,10 +542,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, | |||
539 | CMD_BBP_REG_ACCESS, 0, | 542 | CMD_BBP_REG_ACCESS, 0, |
540 | CMD_OPTION_WAITFORRSP, 0, &offval); | 543 | CMD_OPTION_WAITFORRSP, 0, &offval); |
541 | mdelay(10); | 544 | mdelay(10); |
542 | pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", | 545 | if (!ret) { |
546 | pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", | ||
543 | priv->bbp_offset, priv->offsetvalue.value); | 547 | priv->bbp_offset, priv->offsetvalue.value); |
544 | 548 | ||
545 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 549 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
550 | } | ||
546 | free_page(addr); | 551 | free_page(addr); |
547 | 552 | ||
548 | return ret; | 553 | return ret; |
@@ -603,7 +608,8 @@ static ssize_t lbs_wrbbp_write(struct file *file, | |||
603 | CMD_OPTION_WAITFORRSP, 0, &offval); | 608 | CMD_OPTION_WAITFORRSP, 0, &offval); |
604 | mdelay(10); | 609 | mdelay(10); |
605 | 610 | ||
606 | res = count; | 611 | if (!res) |
612 | res = count; | ||
607 | out_unlock: | 613 | out_unlock: |
608 | free_page(addr); | 614 | free_page(addr); |
609 | return res; | 615 | return res; |
@@ -628,10 +634,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, | |||
628 | CMD_RF_REG_ACCESS, 0, | 634 | CMD_RF_REG_ACCESS, 0, |
629 | CMD_OPTION_WAITFORRSP, 0, &offval); | 635 | CMD_OPTION_WAITFORRSP, 0, &offval); |
630 | mdelay(10); | 636 | mdelay(10); |
631 | pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", | 637 | if (!ret) { |
638 | pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", | ||
632 | priv->rf_offset, priv->offsetvalue.value); | 639 | priv->rf_offset, priv->offsetvalue.value); |
633 | 640 | ||
634 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); | 641 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); |
642 | } | ||
635 | free_page(addr); | 643 | free_page(addr); |
636 | 644 | ||
637 | return ret; | 645 | return ret; |
@@ -692,7 +700,8 @@ static ssize_t lbs_wrrf_write(struct file *file, | |||
692 | CMD_OPTION_WAITFORRSP, 0, &offval); | 700 | CMD_OPTION_WAITFORRSP, 0, &offval); |
693 | mdelay(10); | 701 | mdelay(10); |
694 | 702 | ||
695 | res = count; | 703 | if (!res) |
704 | res = count; | ||
696 | out_unlock: | 705 | out_unlock: |
697 | free_page(addr); | 706 | free_page(addr); |
698 | return res; | 707 | return res; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index fb91c3639fc1..678f7c9f7503 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -8,74 +8,48 @@ | |||
8 | 8 | ||
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | 10 | ||
11 | #include "defs.h" | ||
12 | 11 | ||
13 | /** Function Prototype Declaration */ | ||
14 | struct lbs_private; | 12 | struct lbs_private; |
15 | struct sk_buff; | 13 | struct sk_buff; |
16 | struct net_device; | 14 | struct net_device; |
17 | struct cmd_ctrl_node; | ||
18 | struct cmd_ds_command; | ||
19 | 15 | ||
20 | void lbs_set_mac_control(struct lbs_private *priv); | ||
21 | 16 | ||
22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); | 17 | /* ethtool.c */ |
23 | 18 | extern const struct ethtool_ops lbs_ethtool_ops; | |
24 | int lbs_free_cmd_buffer(struct lbs_private *priv); | ||
25 | 19 | ||
26 | int lbs_prepare_and_send_command(struct lbs_private *priv, | ||
27 | u16 cmd_no, | ||
28 | u16 cmd_action, | ||
29 | u16 wait_option, u32 cmd_oid, void *pdata_buf); | ||
30 | |||
31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); | ||
32 | int lbs_execute_next_command(struct lbs_private *priv); | ||
33 | int lbs_process_event(struct lbs_private *priv, u32 event); | ||
34 | void lbs_queue_event(struct lbs_private *priv, u32 event); | ||
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
36 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); | ||
37 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv); | ||
38 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | ||
39 | 20 | ||
40 | u32 lbs_fw_index_to_data_rate(u8 index); | 21 | /* tx.c */ |
41 | u8 lbs_data_rate_to_fw_index(u32 rate); | 22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); |
42 | |||
43 | /** The proc fs interface */ | ||
44 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); | ||
45 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, | ||
46 | int result); | ||
47 | netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, | 23 | netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, |
48 | struct net_device *dev); | 24 | struct net_device *dev); |
49 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); | ||
50 | 25 | ||
26 | /* rx.c */ | ||
51 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); | 27 | int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); |
52 | 28 | ||
53 | void lbs_ps_sleep(struct lbs_private *priv, int wait_option); | ||
54 | void lbs_ps_confirm_sleep(struct lbs_private *priv); | ||
55 | void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); | ||
56 | |||
57 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
58 | struct lbs_private *priv, | ||
59 | u8 band, | ||
60 | u16 channel); | ||
61 | |||
62 | void lbs_mac_event_disconnected(struct lbs_private *priv); | ||
63 | |||
64 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); | ||
65 | 29 | ||
66 | /* persistcfg.c */ | 30 | /* persistcfg.c */ |
67 | void lbs_persist_config_init(struct net_device *net); | 31 | void lbs_persist_config_init(struct net_device *net); |
68 | void lbs_persist_config_remove(struct net_device *net); | 32 | void lbs_persist_config_remove(struct net_device *net); |
69 | 33 | ||
34 | |||
70 | /* main.c */ | 35 | /* main.c */ |
71 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, | ||
72 | int *cfp_no); | ||
73 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev); | 36 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev); |
74 | void lbs_remove_card(struct lbs_private *priv); | 37 | void lbs_remove_card(struct lbs_private *priv); |
75 | int lbs_start_card(struct lbs_private *priv); | 38 | int lbs_start_card(struct lbs_private *priv); |
76 | void lbs_stop_card(struct lbs_private *priv); | 39 | void lbs_stop_card(struct lbs_private *priv); |
77 | void lbs_host_to_card_done(struct lbs_private *priv); | 40 | void lbs_host_to_card_done(struct lbs_private *priv); |
78 | 41 | ||
79 | int lbs_update_channel(struct lbs_private *priv); | 42 | int lbs_suspend(struct lbs_private *priv); |
43 | void lbs_resume(struct lbs_private *priv); | ||
44 | |||
45 | void lbs_queue_event(struct lbs_private *priv, u32 event); | ||
46 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
47 | |||
48 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv); | ||
49 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | ||
50 | |||
51 | u32 lbs_fw_index_to_data_rate(u8 index); | ||
52 | u8 lbs_data_rate_to_fw_index(u32 rate); | ||
53 | |||
80 | 54 | ||
81 | #endif | 55 | #endif |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 1cf5d5985dac..6b6ea9f7bf5b 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -322,7 +322,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
322 | extern const char lbs_driver_version[]; | 322 | extern const char lbs_driver_version[]; |
323 | extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; | 323 | extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; |
324 | 324 | ||
325 | extern u8 lbs_bg_rates[MAX_RATES]; | ||
326 | 325 | ||
327 | /** ENUM definition*/ | 326 | /** ENUM definition*/ |
328 | /** SNRNF_TYPE */ | 327 | /** SNRNF_TYPE */ |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 8abb28af5afa..1a675111300d 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -6,75 +6,10 @@ | |||
6 | #ifndef _LBS_DEV_H_ | 6 | #ifndef _LBS_DEV_H_ |
7 | #define _LBS_DEV_H_ | 7 | #define _LBS_DEV_H_ |
8 | 8 | ||
9 | #include <linux/netdevice.h> | 9 | #include "scan.h" |
10 | #include <linux/wireless.h> | 10 | #include "assoc.h" |
11 | #include <linux/ethtool.h> | ||
12 | #include <linux/debugfs.h> | ||
13 | 11 | ||
14 | #include "defs.h" | ||
15 | #include "hostcmd.h" | ||
16 | 12 | ||
17 | extern const struct ethtool_ops lbs_ethtool_ops; | ||
18 | |||
19 | #define MAX_BSSID_PER_CHANNEL 16 | ||
20 | |||
21 | #define NR_TX_QUEUE 3 | ||
22 | |||
23 | /* For the extended Scan */ | ||
24 | #define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \ | ||
25 | MRVDRV_MAX_CHANNEL_SIZE + 1 | ||
26 | |||
27 | #define MAX_REGION_CHANNEL_NUM 2 | ||
28 | |||
29 | /** Chan-freq-TxPower mapping table*/ | ||
30 | struct chan_freq_power { | ||
31 | /** channel Number */ | ||
32 | u16 channel; | ||
33 | /** frequency of this channel */ | ||
34 | u32 freq; | ||
35 | /** Max allowed Tx power level */ | ||
36 | u16 maxtxpower; | ||
37 | /** TRUE:channel unsupported; FLASE:supported*/ | ||
38 | u8 unsupported; | ||
39 | }; | ||
40 | |||
41 | /** region-band mapping table*/ | ||
42 | struct region_channel { | ||
43 | /** TRUE if this entry is valid */ | ||
44 | u8 valid; | ||
45 | /** region code for US, Japan ... */ | ||
46 | u8 region; | ||
47 | /** band B/G/A, used for BAND_CONFIG cmd */ | ||
48 | u8 band; | ||
49 | /** Actual No. of elements in the array below */ | ||
50 | u8 nrcfp; | ||
51 | /** chan-freq-txpower mapping table*/ | ||
52 | struct chan_freq_power *CFP; | ||
53 | }; | ||
54 | |||
55 | struct lbs_802_11_security { | ||
56 | u8 WPAenabled; | ||
57 | u8 WPA2enabled; | ||
58 | u8 wep_enabled; | ||
59 | u8 auth_mode; | ||
60 | u32 key_mgmt; | ||
61 | }; | ||
62 | |||
63 | /** Current Basic Service Set State Structure */ | ||
64 | struct current_bss_params { | ||
65 | /** bssid */ | ||
66 | u8 bssid[ETH_ALEN]; | ||
67 | /** ssid */ | ||
68 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
69 | u8 ssid_len; | ||
70 | |||
71 | /** band */ | ||
72 | u8 band; | ||
73 | /** channel */ | ||
74 | u8 channel; | ||
75 | /** zero-terminated array of supported data rates */ | ||
76 | u8 rates[MAX_RATES + 1]; | ||
77 | }; | ||
78 | 13 | ||
79 | /** sleep_params */ | 14 | /** sleep_params */ |
80 | struct sleep_params { | 15 | struct sleep_params { |
@@ -100,113 +35,96 @@ struct lbs_mesh_stats { | |||
100 | 35 | ||
101 | /** Private structure for the MV device */ | 36 | /** Private structure for the MV device */ |
102 | struct lbs_private { | 37 | struct lbs_private { |
38 | |||
39 | /* Basic networking */ | ||
40 | struct net_device *dev; | ||
41 | u32 connect_status; | ||
42 | int infra_open; | ||
43 | struct work_struct mcast_work; | ||
44 | u32 nr_of_multicastmacaddr; | ||
45 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | ||
46 | |||
47 | /* CFG80211 */ | ||
103 | struct wireless_dev *wdev; | 48 | struct wireless_dev *wdev; |
49 | |||
50 | /* Mesh */ | ||
51 | struct net_device *mesh_dev; /* Virtual device */ | ||
52 | u32 mesh_connect_status; | ||
53 | struct lbs_mesh_stats mstats; | ||
104 | int mesh_open; | 54 | int mesh_open; |
105 | int mesh_fw_ver; | 55 | int mesh_fw_ver; |
106 | int infra_open; | ||
107 | int mesh_autostart_enabled; | 56 | int mesh_autostart_enabled; |
57 | uint16_t mesh_tlv; | ||
58 | u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1]; | ||
59 | u8 mesh_ssid_len; | ||
60 | struct work_struct sync_channel; | ||
108 | 61 | ||
109 | char name[DEV_NAME_LEN]; | 62 | /* Monitor mode */ |
110 | |||
111 | void *card; | ||
112 | struct net_device *dev; | ||
113 | |||
114 | struct net_device *mesh_dev; /* Virtual device */ | ||
115 | struct net_device *rtap_net_dev; | 63 | struct net_device *rtap_net_dev; |
64 | u32 monitormode; | ||
116 | 65 | ||
117 | struct iw_statistics wstats; | 66 | /* Debugfs */ |
118 | struct lbs_mesh_stats mstats; | ||
119 | struct dentry *debugfs_dir; | 67 | struct dentry *debugfs_dir; |
120 | struct dentry *debugfs_debug; | 68 | struct dentry *debugfs_debug; |
121 | struct dentry *debugfs_files[6]; | 69 | struct dentry *debugfs_files[6]; |
122 | |||
123 | struct dentry *events_dir; | 70 | struct dentry *events_dir; |
124 | struct dentry *debugfs_events_files[6]; | 71 | struct dentry *debugfs_events_files[6]; |
125 | |||
126 | struct dentry *regs_dir; | 72 | struct dentry *regs_dir; |
127 | struct dentry *debugfs_regs_files[6]; | 73 | struct dentry *debugfs_regs_files[6]; |
128 | 74 | ||
75 | /* Hardware debugging */ | ||
129 | u32 mac_offset; | 76 | u32 mac_offset; |
130 | u32 bbp_offset; | 77 | u32 bbp_offset; |
131 | u32 rf_offset; | 78 | u32 rf_offset; |
79 | struct lbs_offset_value offsetvalue; | ||
80 | |||
81 | /* Power management */ | ||
82 | u16 psmode; | ||
83 | u32 psstate; | ||
84 | u8 needtowakeup; | ||
132 | 85 | ||
133 | /** Deep sleep flag */ | 86 | /* Deep sleep */ |
134 | int is_deep_sleep; | 87 | int is_deep_sleep; |
135 | /** Auto deep sleep enabled flag */ | ||
136 | int is_auto_deep_sleep_enabled; | 88 | int is_auto_deep_sleep_enabled; |
137 | /** Device wakeup required flag */ | ||
138 | int wakeup_dev_required; | 89 | int wakeup_dev_required; |
139 | /** Auto deep sleep flag*/ | ||
140 | int is_activity_detected; | 90 | int is_activity_detected; |
141 | /** Auto deep sleep timeout (in miliseconds) */ | 91 | int auto_deep_sleep_timeout; /* in ms */ |
142 | int auto_deep_sleep_timeout; | 92 | wait_queue_head_t ds_awake_q; |
143 | 93 | struct timer_list auto_deepsleep_timer; | |
144 | /** Deep sleep wait queue */ | ||
145 | wait_queue_head_t ds_awake_q; | ||
146 | |||
147 | /* Download sent: | ||
148 | bit0 1/0=data_sent/data_tx_done, | ||
149 | bit1 1/0=cmd_sent/cmd_tx_done, | ||
150 | all other bits reserved 0 */ | ||
151 | u8 dnld_sent; | ||
152 | |||
153 | /** thread to service interrupts */ | ||
154 | struct task_struct *main_thread; | ||
155 | wait_queue_head_t waitq; | ||
156 | struct workqueue_struct *work_thread; | ||
157 | |||
158 | struct work_struct mcast_work; | ||
159 | |||
160 | /** Scanning */ | ||
161 | struct delayed_work scan_work; | ||
162 | struct delayed_work assoc_work; | ||
163 | struct work_struct sync_channel; | ||
164 | /* remember which channel was scanned last, != 0 if currently scanning */ | ||
165 | int scan_channel; | ||
166 | u8 scan_ssid[IW_ESSID_MAX_SIZE + 1]; | ||
167 | u8 scan_ssid_len; | ||
168 | 94 | ||
169 | /** Hardware access */ | 95 | /* Hardware access */ |
96 | void *card; | ||
97 | u8 fw_ready; | ||
98 | u8 surpriseremoved; | ||
170 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 99 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
171 | void (*reset_card) (struct lbs_private *priv); | 100 | void (*reset_card) (struct lbs_private *priv); |
172 | int (*enter_deep_sleep) (struct lbs_private *priv); | 101 | int (*enter_deep_sleep) (struct lbs_private *priv); |
173 | int (*exit_deep_sleep) (struct lbs_private *priv); | 102 | int (*exit_deep_sleep) (struct lbs_private *priv); |
174 | int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); | 103 | int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); |
175 | 104 | ||
176 | /* Wake On LAN */ | 105 | /* Adapter info (from EEPROM) */ |
177 | uint32_t wol_criteria; | ||
178 | uint8_t wol_gpio; | ||
179 | uint8_t wol_gap; | ||
180 | |||
181 | /** Wlan adapter data structure*/ | ||
182 | /** STATUS variables */ | ||
183 | u32 fwrelease; | 106 | u32 fwrelease; |
184 | u32 fwcapinfo; | 107 | u32 fwcapinfo; |
108 | u16 regioncode; | ||
109 | u8 current_addr[ETH_ALEN]; | ||
185 | 110 | ||
186 | struct mutex lock; | 111 | /* Command download */ |
187 | 112 | u8 dnld_sent; | |
188 | /* TX packet ready to be sent... */ | 113 | /* bit0 1/0=data_sent/data_tx_done, |
189 | int tx_pending_len; /* -1 while building packet */ | 114 | bit1 1/0=cmd_sent/cmd_tx_done, |
190 | 115 | all other bits reserved 0 */ | |
191 | u8 tx_pending_buf[LBS_UPLD_SIZE]; | ||
192 | /* protected by hard_start_xmit serialization */ | ||
193 | |||
194 | /** command-related variables */ | ||
195 | u16 seqnum; | 116 | u16 seqnum; |
196 | |||
197 | struct cmd_ctrl_node *cmd_array; | 117 | struct cmd_ctrl_node *cmd_array; |
198 | /** Current command */ | ||
199 | struct cmd_ctrl_node *cur_cmd; | 118 | struct cmd_ctrl_node *cur_cmd; |
200 | int cur_cmd_retcode; | 119 | struct list_head cmdfreeq; /* free command buffers */ |
201 | /** command Queues */ | 120 | struct list_head cmdpendingq; /* pending command buffers */ |
202 | /** Free command buffers */ | ||
203 | struct list_head cmdfreeq; | ||
204 | /** Pending command buffers */ | ||
205 | struct list_head cmdpendingq; | ||
206 | |||
207 | wait_queue_head_t cmd_pending; | 121 | wait_queue_head_t cmd_pending; |
122 | struct timer_list command_timer; | ||
123 | int nr_retries; | ||
124 | int cmd_timed_out; | ||
208 | 125 | ||
209 | /* Command responses sent from the hardware to the driver */ | 126 | /* Command responses sent from the hardware to the driver */ |
127 | int cur_cmd_retcode; | ||
210 | u8 resp_idx; | 128 | u8 resp_idx; |
211 | u8 resp_buf[2][LBS_UPLD_SIZE]; | 129 | u8 resp_buf[2][LBS_UPLD_SIZE]; |
212 | u32 resp_len[2]; | 130 | u32 resp_len[2]; |
@@ -214,96 +132,76 @@ struct lbs_private { | |||
214 | /* Events sent from hardware to driver */ | 132 | /* Events sent from hardware to driver */ |
215 | struct kfifo *event_fifo; | 133 | struct kfifo *event_fifo; |
216 | 134 | ||
217 | /* nickname */ | 135 | /** thread to service interrupts */ |
218 | u8 nodename[16]; | 136 | struct task_struct *main_thread; |
219 | 137 | wait_queue_head_t waitq; | |
220 | /** spin locks */ | 138 | struct workqueue_struct *work_thread; |
221 | spinlock_t driver_lock; | ||
222 | |||
223 | /** Timers */ | ||
224 | struct timer_list command_timer; | ||
225 | struct timer_list auto_deepsleep_timer; | ||
226 | int nr_retries; | ||
227 | int cmd_timed_out; | ||
228 | |||
229 | /** current ssid/bssid related parameters*/ | ||
230 | struct current_bss_params curbssparams; | ||
231 | |||
232 | uint16_t mesh_tlv; | ||
233 | u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1]; | ||
234 | u8 mesh_ssid_len; | ||
235 | |||
236 | /* IW_MODE_* */ | ||
237 | u8 mode; | ||
238 | |||
239 | /* Scan results list */ | ||
240 | struct list_head network_list; | ||
241 | struct list_head network_free_list; | ||
242 | struct bss_descriptor *networks; | ||
243 | |||
244 | u16 beacon_period; | ||
245 | u8 beacon_enable; | ||
246 | u8 adhoccreate; | ||
247 | |||
248 | /** capability Info used in Association, start, join */ | ||
249 | u16 capability; | ||
250 | |||
251 | /** MAC address information */ | ||
252 | u8 current_addr[ETH_ALEN]; | ||
253 | u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | ||
254 | u32 nr_of_multicastmacaddr; | ||
255 | 139 | ||
256 | /** 802.11 statistics */ | 140 | /** Encryption stuff */ |
257 | // struct cmd_DS_802_11_GET_STAT wlan802_11Stat; | 141 | struct lbs_802_11_security secinfo; |
142 | struct enc_key wpa_mcast_key; | ||
143 | struct enc_key wpa_unicast_key; | ||
144 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
145 | u8 wpa_ie_len; | ||
146 | u16 wep_tx_keyidx; | ||
147 | struct enc_key wep_keys[4]; | ||
258 | 148 | ||
259 | uint16_t enablehwauto; | 149 | /* Wake On LAN */ |
260 | uint16_t ratebitmap; | 150 | uint32_t wol_criteria; |
151 | uint8_t wol_gpio; | ||
152 | uint8_t wol_gap; | ||
261 | 153 | ||
154 | /* Transmitting */ | ||
155 | int tx_pending_len; /* -1 while building packet */ | ||
156 | u8 tx_pending_buf[LBS_UPLD_SIZE]; | ||
157 | /* protected by hard_start_xmit serialization */ | ||
262 | u8 txretrycount; | 158 | u8 txretrycount; |
263 | |||
264 | /** Tx-related variables (for single packet tx) */ | ||
265 | struct sk_buff *currenttxskb; | 159 | struct sk_buff *currenttxskb; |
266 | 160 | ||
267 | /** NIC Operation characteristics */ | 161 | /* Locks */ |
162 | struct mutex lock; | ||
163 | spinlock_t driver_lock; | ||
164 | |||
165 | /* NIC/link operation characteristics */ | ||
268 | u16 mac_control; | 166 | u16 mac_control; |
269 | u32 connect_status; | 167 | u8 radio_on; |
270 | u32 mesh_connect_status; | 168 | u8 channel; |
271 | u16 regioncode; | ||
272 | s16 txpower_cur; | 169 | s16 txpower_cur; |
273 | s16 txpower_min; | 170 | s16 txpower_min; |
274 | s16 txpower_max; | 171 | s16 txpower_max; |
275 | 172 | ||
276 | /** POWER MANAGEMENT AND PnP SUPPORT */ | 173 | /** Scanning */ |
277 | u8 surpriseremoved; | 174 | struct delayed_work scan_work; |
278 | 175 | int scan_channel; | |
279 | u16 psmode; /* Wlan802_11PowermodeCAM=disable | 176 | /* remember which channel was scanned last, != 0 if currently scanning */ |
280 | Wlan802_11PowermodeMAX_PSP=enable */ | 177 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1]; |
281 | u32 psstate; | 178 | u8 scan_ssid_len; |
282 | u8 needtowakeup; | ||
283 | 179 | ||
180 | /* Associating */ | ||
181 | struct delayed_work assoc_work; | ||
182 | struct current_bss_params curbssparams; | ||
183 | u8 mode; | ||
184 | struct list_head network_list; | ||
185 | struct list_head network_free_list; | ||
186 | struct bss_descriptor *networks; | ||
284 | struct assoc_request * pending_assoc_req; | 187 | struct assoc_request * pending_assoc_req; |
285 | struct assoc_request * in_progress_assoc_req; | 188 | struct assoc_request * in_progress_assoc_req; |
189 | u16 capability; | ||
190 | uint16_t enablehwauto; | ||
191 | uint16_t ratebitmap; | ||
286 | 192 | ||
287 | /** Encryption parameter */ | 193 | /* ADHOC */ |
288 | struct lbs_802_11_security secinfo; | 194 | u16 beacon_period; |
289 | 195 | u8 beacon_enable; | |
290 | /** WEP keys */ | 196 | u8 adhoccreate; |
291 | struct enc_key wep_keys[4]; | ||
292 | u16 wep_tx_keyidx; | ||
293 | |||
294 | /** WPA keys */ | ||
295 | struct enc_key wpa_mcast_key; | ||
296 | struct enc_key wpa_unicast_key; | ||
297 | |||
298 | /* | ||
299 | * In theory, the IE is limited to the IE length, 255, | ||
300 | * but in practice 64 bytes are enough. | ||
301 | */ | ||
302 | #define MAX_WPA_IE_LEN 64 | ||
303 | 197 | ||
304 | /** WPA Information Elements*/ | 198 | /* WEXT */ |
305 | u8 wpa_ie[MAX_WPA_IE_LEN]; | 199 | char name[DEV_NAME_LEN]; |
306 | u8 wpa_ie_len; | 200 | u8 nodename[16]; |
201 | struct iw_statistics wstats; | ||
202 | u8 cur_rate; | ||
203 | #define MAX_REGION_CHANNEL_NUM 2 | ||
204 | struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; | ||
307 | 205 | ||
308 | /** Requested Signal Strength*/ | 206 | /** Requested Signal Strength*/ |
309 | u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; | 207 | u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; |
@@ -313,116 +211,8 @@ struct lbs_private { | |||
313 | u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; | 211 | u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; |
314 | u16 nextSNRNF; | 212 | u16 nextSNRNF; |
315 | u16 numSNRNF; | 213 | u16 numSNRNF; |
316 | |||
317 | u8 radio_on; | ||
318 | |||
319 | /** data rate stuff */ | ||
320 | u8 cur_rate; | ||
321 | |||
322 | /** RF calibration data */ | ||
323 | |||
324 | #define MAX_REGION_CHANNEL_NUM 2 | ||
325 | /** region channel data */ | ||
326 | struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; | ||
327 | |||
328 | struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM]; | ||
329 | |||
330 | /** 11D and Domain Regulatory Data */ | ||
331 | struct lbs_802_11d_domain_reg domainreg; | ||
332 | struct parsed_region_chan_11d parsed_region_chan; | ||
333 | |||
334 | /** FSM variable for 11d support */ | ||
335 | u32 enable11d; | ||
336 | |||
337 | /** MISCELLANEOUS */ | ||
338 | struct lbs_offset_value offsetvalue; | ||
339 | |||
340 | u32 monitormode; | ||
341 | u8 fw_ready; | ||
342 | }; | 214 | }; |
343 | 215 | ||
344 | extern struct cmd_confirm_sleep confirm_sleep; | 216 | extern struct cmd_confirm_sleep confirm_sleep; |
345 | 217 | ||
346 | /** | ||
347 | * @brief Structure used to store information for each beacon/probe response | ||
348 | */ | ||
349 | struct bss_descriptor { | ||
350 | u8 bssid[ETH_ALEN]; | ||
351 | |||
352 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
353 | u8 ssid_len; | ||
354 | |||
355 | u16 capability; | ||
356 | u32 rssi; | ||
357 | u32 channel; | ||
358 | u16 beaconperiod; | ||
359 | __le16 atimwindow; | ||
360 | |||
361 | /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ | ||
362 | u8 mode; | ||
363 | |||
364 | /* zero-terminated array of supported data rates */ | ||
365 | u8 rates[MAX_RATES + 1]; | ||
366 | |||
367 | unsigned long last_scanned; | ||
368 | |||
369 | union ieee_phy_param_set phy; | ||
370 | union ieee_ss_param_set ss; | ||
371 | |||
372 | struct ieee_ie_country_info_full_set countryinfo; | ||
373 | |||
374 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
375 | size_t wpa_ie_len; | ||
376 | u8 rsn_ie[MAX_WPA_IE_LEN]; | ||
377 | size_t rsn_ie_len; | ||
378 | |||
379 | u8 mesh; | ||
380 | |||
381 | struct list_head list; | ||
382 | }; | ||
383 | |||
384 | /** Association request | ||
385 | * | ||
386 | * Encapsulates all the options that describe a specific assocation request | ||
387 | * or configuration of the wireless card's radio, mode, and security settings. | ||
388 | */ | ||
389 | struct assoc_request { | ||
390 | #define ASSOC_FLAG_SSID 1 | ||
391 | #define ASSOC_FLAG_CHANNEL 2 | ||
392 | #define ASSOC_FLAG_BAND 3 | ||
393 | #define ASSOC_FLAG_MODE 4 | ||
394 | #define ASSOC_FLAG_BSSID 5 | ||
395 | #define ASSOC_FLAG_WEP_KEYS 6 | ||
396 | #define ASSOC_FLAG_WEP_TX_KEYIDX 7 | ||
397 | #define ASSOC_FLAG_WPA_MCAST_KEY 8 | ||
398 | #define ASSOC_FLAG_WPA_UCAST_KEY 9 | ||
399 | #define ASSOC_FLAG_SECINFO 10 | ||
400 | #define ASSOC_FLAG_WPA_IE 11 | ||
401 | unsigned long flags; | ||
402 | |||
403 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | ||
404 | u8 ssid_len; | ||
405 | u8 channel; | ||
406 | u8 band; | ||
407 | u8 mode; | ||
408 | u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); | ||
409 | |||
410 | /** WEP keys */ | ||
411 | struct enc_key wep_keys[4]; | ||
412 | u16 wep_tx_keyidx; | ||
413 | |||
414 | /** WPA keys */ | ||
415 | struct enc_key wpa_mcast_key; | ||
416 | struct enc_key wpa_unicast_key; | ||
417 | |||
418 | struct lbs_802_11_security secinfo; | ||
419 | |||
420 | /** WPA Information Elements*/ | ||
421 | u8 wpa_ie[MAX_WPA_IE_LEN]; | ||
422 | u8 wpa_ie_len; | ||
423 | |||
424 | /* BSS to associate with for infrastructure of Ad-Hoc join */ | ||
425 | struct bss_descriptor bss; | ||
426 | }; | ||
427 | |||
428 | #endif | 218 | #endif |
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index c055daabea13..3809c0b49464 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -1,202 +1,190 @@ | |||
1 | /** | 1 | /** |
2 | * This file contains definitions of WLAN commands. | 2 | * This file function prototypes, data structure |
3 | * and definitions for all the host/station commands | ||
3 | */ | 4 | */ |
4 | 5 | ||
5 | #ifndef _LBS_HOST_H_ | 6 | #ifndef _LBS_HOST_H_ |
6 | #define _LBS_HOST_H_ | 7 | #define _LBS_HOST_H_ |
7 | 8 | ||
8 | /** PUBLIC DEFINITIONS */ | 9 | #include "types.h" |
9 | #define DEFAULT_AD_HOC_CHANNEL 6 | 10 | #include "defs.h" |
10 | #define DEFAULT_AD_HOC_CHANNEL_A 36 | ||
11 | 11 | ||
12 | #define CMD_OPTION_WAITFORRSP 0x0002 | 12 | #define DEFAULT_AD_HOC_CHANNEL 6 |
13 | |||
14 | #define CMD_OPTION_WAITFORRSP 0x0002 | ||
13 | 15 | ||
14 | /** Host command IDs */ | 16 | /** Host command IDs */ |
15 | 17 | ||
16 | /* Return command are almost always the same as the host command, but with | 18 | /* Return command are almost always the same as the host command, but with |
17 | * bit 15 set high. There are a few exceptions, though... | 19 | * bit 15 set high. There are a few exceptions, though... |
18 | */ | 20 | */ |
19 | #define CMD_RET(cmd) (0x8000 | cmd) | 21 | #define CMD_RET(cmd) (0x8000 | cmd) |
20 | 22 | ||
21 | /* Return command convention exceptions: */ | 23 | /* Return command convention exceptions: */ |
22 | #define CMD_RET_802_11_ASSOCIATE 0x8012 | 24 | #define CMD_RET_802_11_ASSOCIATE 0x8012 |
23 | 25 | ||
24 | /* Command codes */ | 26 | /* Command codes */ |
25 | #define CMD_GET_HW_SPEC 0x0003 | 27 | #define CMD_GET_HW_SPEC 0x0003 |
26 | #define CMD_EEPROM_UPDATE 0x0004 | 28 | #define CMD_EEPROM_UPDATE 0x0004 |
27 | #define CMD_802_11_RESET 0x0005 | 29 | #define CMD_802_11_RESET 0x0005 |
28 | #define CMD_802_11_SCAN 0x0006 | 30 | #define CMD_802_11_SCAN 0x0006 |
29 | #define CMD_802_11_GET_LOG 0x000b | 31 | #define CMD_802_11_GET_LOG 0x000b |
30 | #define CMD_MAC_MULTICAST_ADR 0x0010 | 32 | #define CMD_MAC_MULTICAST_ADR 0x0010 |
31 | #define CMD_802_11_AUTHENTICATE 0x0011 | 33 | #define CMD_802_11_AUTHENTICATE 0x0011 |
32 | #define CMD_802_11_EEPROM_ACCESS 0x0059 | 34 | #define CMD_802_11_EEPROM_ACCESS 0x0059 |
33 | #define CMD_802_11_ASSOCIATE 0x0050 | 35 | #define CMD_802_11_ASSOCIATE 0x0050 |
34 | #define CMD_802_11_SET_WEP 0x0013 | 36 | #define CMD_802_11_SET_WEP 0x0013 |
35 | #define CMD_802_11_GET_STAT 0x0014 | 37 | #define CMD_802_11_GET_STAT 0x0014 |
36 | #define CMD_802_3_GET_STAT 0x0015 | 38 | #define CMD_802_3_GET_STAT 0x0015 |
37 | #define CMD_802_11_SNMP_MIB 0x0016 | 39 | #define CMD_802_11_SNMP_MIB 0x0016 |
38 | #define CMD_MAC_REG_MAP 0x0017 | 40 | #define CMD_MAC_REG_MAP 0x0017 |
39 | #define CMD_BBP_REG_MAP 0x0018 | 41 | #define CMD_BBP_REG_MAP 0x0018 |
40 | #define CMD_MAC_REG_ACCESS 0x0019 | 42 | #define CMD_MAC_REG_ACCESS 0x0019 |
41 | #define CMD_BBP_REG_ACCESS 0x001a | 43 | #define CMD_BBP_REG_ACCESS 0x001a |
42 | #define CMD_RF_REG_ACCESS 0x001b | 44 | #define CMD_RF_REG_ACCESS 0x001b |
43 | #define CMD_802_11_RADIO_CONTROL 0x001c | 45 | #define CMD_802_11_RADIO_CONTROL 0x001c |
44 | #define CMD_802_11_RF_CHANNEL 0x001d | 46 | #define CMD_802_11_RF_CHANNEL 0x001d |
45 | #define CMD_802_11_RF_TX_POWER 0x001e | 47 | #define CMD_802_11_RF_TX_POWER 0x001e |
46 | #define CMD_802_11_RSSI 0x001f | 48 | #define CMD_802_11_RSSI 0x001f |
47 | #define CMD_802_11_RF_ANTENNA 0x0020 | 49 | #define CMD_802_11_RF_ANTENNA 0x0020 |
48 | #define CMD_802_11_PS_MODE 0x0021 | 50 | #define CMD_802_11_PS_MODE 0x0021 |
49 | #define CMD_802_11_DATA_RATE 0x0022 | 51 | #define CMD_802_11_DATA_RATE 0x0022 |
50 | #define CMD_RF_REG_MAP 0x0023 | 52 | #define CMD_RF_REG_MAP 0x0023 |
51 | #define CMD_802_11_DEAUTHENTICATE 0x0024 | 53 | #define CMD_802_11_DEAUTHENTICATE 0x0024 |
52 | #define CMD_802_11_REASSOCIATE 0x0025 | 54 | #define CMD_802_11_REASSOCIATE 0x0025 |
53 | #define CMD_MAC_CONTROL 0x0028 | 55 | #define CMD_MAC_CONTROL 0x0028 |
54 | #define CMD_802_11_AD_HOC_START 0x002b | 56 | #define CMD_802_11_AD_HOC_START 0x002b |
55 | #define CMD_802_11_AD_HOC_JOIN 0x002c | 57 | #define CMD_802_11_AD_HOC_JOIN 0x002c |
56 | #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e | 58 | #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e |
57 | #define CMD_802_11_ENABLE_RSN 0x002f | 59 | #define CMD_802_11_ENABLE_RSN 0x002f |
58 | #define CMD_802_11_SET_AFC 0x003c | 60 | #define CMD_802_11_SET_AFC 0x003c |
59 | #define CMD_802_11_GET_AFC 0x003d | 61 | #define CMD_802_11_GET_AFC 0x003d |
60 | #define CMD_802_11_DEEP_SLEEP 0x003e | 62 | #define CMD_802_11_DEEP_SLEEP 0x003e |
61 | #define CMD_802_11_AD_HOC_STOP 0x0040 | 63 | #define CMD_802_11_AD_HOC_STOP 0x0040 |
62 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 | 64 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 |
63 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 | 65 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 |
64 | #define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 | 66 | #define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 |
65 | #define CMD_802_11_BEACON_STOP 0x0049 | 67 | #define CMD_802_11_BEACON_STOP 0x0049 |
66 | #define CMD_802_11_MAC_ADDRESS 0x004d | 68 | #define CMD_802_11_MAC_ADDRESS 0x004d |
67 | #define CMD_802_11_LED_GPIO_CTRL 0x004e | 69 | #define CMD_802_11_LED_GPIO_CTRL 0x004e |
68 | #define CMD_802_11_EEPROM_ACCESS 0x0059 | 70 | #define CMD_802_11_EEPROM_ACCESS 0x0059 |
69 | #define CMD_802_11_BAND_CONFIG 0x0058 | 71 | #define CMD_802_11_BAND_CONFIG 0x0058 |
70 | #define CMD_GSPI_BUS_CONFIG 0x005a | 72 | #define CMD_GSPI_BUS_CONFIG 0x005a |
71 | #define CMD_802_11D_DOMAIN_INFO 0x005b | 73 | #define CMD_802_11D_DOMAIN_INFO 0x005b |
72 | #define CMD_802_11_KEY_MATERIAL 0x005e | 74 | #define CMD_802_11_KEY_MATERIAL 0x005e |
73 | #define CMD_802_11_SLEEP_PARAMS 0x0066 | 75 | #define CMD_802_11_SLEEP_PARAMS 0x0066 |
74 | #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 | 76 | #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 |
75 | #define CMD_802_11_SLEEP_PERIOD 0x0068 | 77 | #define CMD_802_11_SLEEP_PERIOD 0x0068 |
76 | #define CMD_802_11_TPC_CFG 0x0072 | 78 | #define CMD_802_11_TPC_CFG 0x0072 |
77 | #define CMD_802_11_PA_CFG 0x0073 | 79 | #define CMD_802_11_PA_CFG 0x0073 |
78 | #define CMD_802_11_FW_WAKE_METHOD 0x0074 | 80 | #define CMD_802_11_FW_WAKE_METHOD 0x0074 |
79 | #define CMD_802_11_SUBSCRIBE_EVENT 0x0075 | 81 | #define CMD_802_11_SUBSCRIBE_EVENT 0x0075 |
80 | #define CMD_802_11_RATE_ADAPT_RATESET 0x0076 | 82 | #define CMD_802_11_RATE_ADAPT_RATESET 0x0076 |
81 | #define CMD_802_11_TX_RATE_QUERY 0x007f | 83 | #define CMD_802_11_TX_RATE_QUERY 0x007f |
82 | #define CMD_GET_TSF 0x0080 | 84 | #define CMD_GET_TSF 0x0080 |
83 | #define CMD_BT_ACCESS 0x0087 | 85 | #define CMD_BT_ACCESS 0x0087 |
84 | #define CMD_FWT_ACCESS 0x0095 | 86 | #define CMD_FWT_ACCESS 0x0095 |
85 | #define CMD_802_11_MONITOR_MODE 0x0098 | 87 | #define CMD_802_11_MONITOR_MODE 0x0098 |
86 | #define CMD_MESH_ACCESS 0x009b | 88 | #define CMD_MESH_ACCESS 0x009b |
87 | #define CMD_MESH_CONFIG_OLD 0x00a3 | 89 | #define CMD_MESH_CONFIG_OLD 0x00a3 |
88 | #define CMD_MESH_CONFIG 0x00ac | 90 | #define CMD_MESH_CONFIG 0x00ac |
89 | #define CMD_SET_BOOT2_VER 0x00a5 | 91 | #define CMD_SET_BOOT2_VER 0x00a5 |
90 | #define CMD_FUNC_INIT 0x00a9 | 92 | #define CMD_FUNC_INIT 0x00a9 |
91 | #define CMD_FUNC_SHUTDOWN 0x00aa | 93 | #define CMD_FUNC_SHUTDOWN 0x00aa |
92 | #define CMD_802_11_BEACON_CTRL 0x00b0 | 94 | #define CMD_802_11_BEACON_CTRL 0x00b0 |
93 | 95 | ||
94 | /* For the IEEE Power Save */ | 96 | /* For the IEEE Power Save */ |
95 | #define CMD_SUBCMD_ENTER_PS 0x0030 | 97 | #define CMD_SUBCMD_ENTER_PS 0x0030 |
96 | #define CMD_SUBCMD_EXIT_PS 0x0031 | 98 | #define CMD_SUBCMD_EXIT_PS 0x0031 |
97 | #define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 | 99 | #define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 |
98 | #define CMD_SUBCMD_FULL_POWERDOWN 0x0035 | 100 | #define CMD_SUBCMD_FULL_POWERDOWN 0x0035 |
99 | #define CMD_SUBCMD_FULL_POWERUP 0x0036 | 101 | #define CMD_SUBCMD_FULL_POWERUP 0x0036 |
100 | 102 | ||
101 | #define CMD_ENABLE_RSN 0x0001 | 103 | #define CMD_ENABLE_RSN 0x0001 |
102 | #define CMD_DISABLE_RSN 0x0000 | 104 | #define CMD_DISABLE_RSN 0x0000 |
103 | 105 | ||
104 | #define CMD_ACT_GET 0x0000 | 106 | #define CMD_ACT_GET 0x0000 |
105 | #define CMD_ACT_SET 0x0001 | 107 | #define CMD_ACT_SET 0x0001 |
106 | #define CMD_ACT_GET_AES 0x0002 | ||
107 | #define CMD_ACT_SET_AES 0x0003 | ||
108 | #define CMD_ACT_REMOVE_AES 0x0004 | ||
109 | 108 | ||
110 | /* Define action or option for CMD_802_11_SET_WEP */ | 109 | /* Define action or option for CMD_802_11_SET_WEP */ |
111 | #define CMD_ACT_ADD 0x0002 | 110 | #define CMD_ACT_ADD 0x0002 |
112 | #define CMD_ACT_REMOVE 0x0004 | 111 | #define CMD_ACT_REMOVE 0x0004 |
113 | #define CMD_ACT_USE_DEFAULT 0x0008 | ||
114 | |||
115 | #define CMD_TYPE_WEP_40_BIT 0x01 | ||
116 | #define CMD_TYPE_WEP_104_BIT 0x02 | ||
117 | 112 | ||
118 | #define CMD_NUM_OF_WEP_KEYS 4 | 113 | #define CMD_TYPE_WEP_40_BIT 0x01 |
114 | #define CMD_TYPE_WEP_104_BIT 0x02 | ||
119 | 115 | ||
120 | #define CMD_WEP_KEY_INDEX_MASK 0x3fff | 116 | #define CMD_NUM_OF_WEP_KEYS 4 |
121 | 117 | ||
122 | /* Define action or option for CMD_802_11_RESET */ | 118 | #define CMD_WEP_KEY_INDEX_MASK 0x3fff |
123 | #define CMD_ACT_HALT 0x0003 | ||
124 | 119 | ||
125 | /* Define action or option for CMD_802_11_SCAN */ | 120 | /* Define action or option for CMD_802_11_SCAN */ |
126 | #define CMD_BSS_TYPE_BSS 0x0001 | 121 | #define CMD_BSS_TYPE_BSS 0x0001 |
127 | #define CMD_BSS_TYPE_IBSS 0x0002 | 122 | #define CMD_BSS_TYPE_IBSS 0x0002 |
128 | #define CMD_BSS_TYPE_ANY 0x0003 | 123 | #define CMD_BSS_TYPE_ANY 0x0003 |
129 | 124 | ||
130 | /* Define action or option for CMD_802_11_SCAN */ | 125 | /* Define action or option for CMD_802_11_SCAN */ |
131 | #define CMD_SCAN_TYPE_ACTIVE 0x0000 | 126 | #define CMD_SCAN_TYPE_ACTIVE 0x0000 |
132 | #define CMD_SCAN_TYPE_PASSIVE 0x0001 | 127 | #define CMD_SCAN_TYPE_PASSIVE 0x0001 |
133 | 128 | ||
134 | #define CMD_SCAN_RADIO_TYPE_BG 0 | 129 | #define CMD_SCAN_RADIO_TYPE_BG 0 |
135 | 130 | ||
136 | #define CMD_SCAN_PROBE_DELAY_TIME 0 | 131 | #define CMD_SCAN_PROBE_DELAY_TIME 0 |
137 | 132 | ||
138 | /* Define action or option for CMD_MAC_CONTROL */ | 133 | /* Define action or option for CMD_MAC_CONTROL */ |
139 | #define CMD_ACT_MAC_RX_ON 0x0001 | 134 | #define CMD_ACT_MAC_RX_ON 0x0001 |
140 | #define CMD_ACT_MAC_TX_ON 0x0002 | 135 | #define CMD_ACT_MAC_TX_ON 0x0002 |
141 | #define CMD_ACT_MAC_LOOPBACK_ON 0x0004 | 136 | #define CMD_ACT_MAC_LOOPBACK_ON 0x0004 |
142 | #define CMD_ACT_MAC_WEP_ENABLE 0x0008 | 137 | #define CMD_ACT_MAC_WEP_ENABLE 0x0008 |
143 | #define CMD_ACT_MAC_INT_ENABLE 0x0010 | 138 | #define CMD_ACT_MAC_INT_ENABLE 0x0010 |
144 | #define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 | 139 | #define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 |
145 | #define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 | 140 | #define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 |
146 | #define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 | 141 | #define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 |
147 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 | 142 | #define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 |
148 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 | 143 | #define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 |
149 | 144 | ||
150 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ | 145 | /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ |
151 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 | 146 | #define CMD_SUBSCRIBE_RSSI_LOW 0x0001 |
152 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 | 147 | #define CMD_SUBSCRIBE_SNR_LOW 0x0002 |
153 | #define CMD_SUBSCRIBE_FAILCOUNT 0x0004 | 148 | #define CMD_SUBSCRIBE_FAILCOUNT 0x0004 |
154 | #define CMD_SUBSCRIBE_BCNMISS 0x0008 | 149 | #define CMD_SUBSCRIBE_BCNMISS 0x0008 |
155 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 | 150 | #define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 |
156 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 | 151 | #define CMD_SUBSCRIBE_SNR_HIGH 0x0020 |
157 | 152 | ||
158 | #define RADIO_PREAMBLE_LONG 0x00 | 153 | #define RADIO_PREAMBLE_LONG 0x00 |
159 | #define RADIO_PREAMBLE_SHORT 0x02 | 154 | #define RADIO_PREAMBLE_SHORT 0x02 |
160 | #define RADIO_PREAMBLE_AUTO 0x04 | 155 | #define RADIO_PREAMBLE_AUTO 0x04 |
161 | 156 | ||
162 | /* Define action or option for CMD_802_11_RF_CHANNEL */ | 157 | /* Define action or option for CMD_802_11_RF_CHANNEL */ |
163 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 | 158 | #define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 |
164 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 | 159 | #define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 |
165 | 160 | ||
166 | /* Define action or option for CMD_802_11_DATA_RATE */ | 161 | /* Define action or option for CMD_802_11_DATA_RATE */ |
167 | #define CMD_ACT_SET_TX_AUTO 0x0000 | 162 | #define CMD_ACT_SET_TX_AUTO 0x0000 |
168 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 | 163 | #define CMD_ACT_SET_TX_FIX_RATE 0x0001 |
169 | #define CMD_ACT_GET_TX_RATE 0x0002 | 164 | #define CMD_ACT_GET_TX_RATE 0x0002 |
170 | |||
171 | #define CMD_ACT_SET_RX 0x0001 | ||
172 | #define CMD_ACT_SET_TX 0x0002 | ||
173 | #define CMD_ACT_SET_BOTH 0x0003 | ||
174 | #define CMD_ACT_GET_RX 0x0004 | ||
175 | #define CMD_ACT_GET_TX 0x0008 | ||
176 | #define CMD_ACT_GET_BOTH 0x000c | ||
177 | 165 | ||
178 | /* Define action or option for CMD_802_11_PS_MODE */ | 166 | /* Define action or option for CMD_802_11_PS_MODE */ |
179 | #define CMD_TYPE_CAM 0x0000 | 167 | #define CMD_TYPE_CAM 0x0000 |
180 | #define CMD_TYPE_MAX_PSP 0x0001 | 168 | #define CMD_TYPE_MAX_PSP 0x0001 |
181 | #define CMD_TYPE_FAST_PSP 0x0002 | 169 | #define CMD_TYPE_FAST_PSP 0x0002 |
182 | 170 | ||
183 | /* Options for CMD_802_11_FW_WAKE_METHOD */ | 171 | /* Options for CMD_802_11_FW_WAKE_METHOD */ |
184 | #define CMD_WAKE_METHOD_UNCHANGED 0x0000 | 172 | #define CMD_WAKE_METHOD_UNCHANGED 0x0000 |
185 | #define CMD_WAKE_METHOD_COMMAND_INT 0x0001 | 173 | #define CMD_WAKE_METHOD_COMMAND_INT 0x0001 |
186 | #define CMD_WAKE_METHOD_GPIO 0x0002 | 174 | #define CMD_WAKE_METHOD_GPIO 0x0002 |
187 | 175 | ||
188 | /* Object IDs for CMD_802_11_SNMP_MIB */ | 176 | /* Object IDs for CMD_802_11_SNMP_MIB */ |
189 | #define SNMP_MIB_OID_BSS_TYPE 0x0000 | 177 | #define SNMP_MIB_OID_BSS_TYPE 0x0000 |
190 | #define SNMP_MIB_OID_OP_RATE_SET 0x0001 | 178 | #define SNMP_MIB_OID_OP_RATE_SET 0x0001 |
191 | #define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */ | 179 | #define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */ |
192 | #define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */ | 180 | #define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */ |
193 | #define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */ | 181 | #define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */ |
194 | #define SNMP_MIB_OID_RTS_THRESHOLD 0x0005 | 182 | #define SNMP_MIB_OID_RTS_THRESHOLD 0x0005 |
195 | #define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006 | 183 | #define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006 |
196 | #define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007 | 184 | #define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007 |
197 | #define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008 | 185 | #define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008 |
198 | #define SNMP_MIB_OID_11D_ENABLE 0x0009 | 186 | #define SNMP_MIB_OID_11D_ENABLE 0x0009 |
199 | #define SNMP_MIB_OID_11H_ENABLE 0x000A | 187 | #define SNMP_MIB_OID_11H_ENABLE 0x000A |
200 | 188 | ||
201 | /* Define action or option for CMD_BT_ACCESS */ | 189 | /* Define action or option for CMD_BT_ACCESS */ |
202 | enum cmd_bt_access_opts { | 190 | enum cmd_bt_access_opts { |
@@ -303,4 +291,672 @@ enum cmd_mesh_config_types { | |||
303 | #define MACREG_INT_CODE_MESH_AUTO_STARTED 35 | 291 | #define MACREG_INT_CODE_MESH_AUTO_STARTED 35 |
304 | #define MACREG_INT_CODE_FIRMWARE_READY 48 | 292 | #define MACREG_INT_CODE_FIRMWARE_READY 48 |
305 | 293 | ||
294 | |||
295 | /* 802.11-related definitions */ | ||
296 | |||
297 | /* TxPD descriptor */ | ||
298 | struct txpd { | ||
299 | /* union to cope up with later FW revisions */ | ||
300 | union { | ||
301 | /* Current Tx packet status */ | ||
302 | __le32 tx_status; | ||
303 | struct { | ||
304 | /* BSS type: client, AP, etc. */ | ||
305 | u8 bss_type; | ||
306 | /* BSS number */ | ||
307 | u8 bss_num; | ||
308 | /* Reserved */ | ||
309 | __le16 reserved; | ||
310 | } bss; | ||
311 | } u; | ||
312 | /* Tx control */ | ||
313 | __le32 tx_control; | ||
314 | __le32 tx_packet_location; | ||
315 | /* Tx packet length */ | ||
316 | __le16 tx_packet_length; | ||
317 | /* First 2 byte of destination MAC address */ | ||
318 | u8 tx_dest_addr_high[2]; | ||
319 | /* Last 4 byte of destination MAC address */ | ||
320 | u8 tx_dest_addr_low[4]; | ||
321 | /* Pkt Priority */ | ||
322 | u8 priority; | ||
323 | /* Pkt Trasnit Power control */ | ||
324 | u8 powermgmt; | ||
325 | /* Amount of time the packet has been queued (units = 2ms) */ | ||
326 | u8 pktdelay_2ms; | ||
327 | /* reserved */ | ||
328 | u8 reserved1; | ||
329 | } __attribute__ ((packed)); | ||
330 | |||
331 | /* RxPD Descriptor */ | ||
332 | struct rxpd { | ||
333 | /* union to cope up with later FW revisions */ | ||
334 | union { | ||
335 | /* Current Rx packet status */ | ||
336 | __le16 status; | ||
337 | struct { | ||
338 | /* BSS type: client, AP, etc. */ | ||
339 | u8 bss_type; | ||
340 | /* BSS number */ | ||
341 | u8 bss_num; | ||
342 | } __attribute__ ((packed)) bss; | ||
343 | } __attribute__ ((packed)) u; | ||
344 | |||
345 | /* SNR */ | ||
346 | u8 snr; | ||
347 | |||
348 | /* Tx control */ | ||
349 | u8 rx_control; | ||
350 | |||
351 | /* Pkt length */ | ||
352 | __le16 pkt_len; | ||
353 | |||
354 | /* Noise Floor */ | ||
355 | u8 nf; | ||
356 | |||
357 | /* Rx Packet Rate */ | ||
358 | u8 rx_rate; | ||
359 | |||
360 | /* Pkt addr */ | ||
361 | __le32 pkt_ptr; | ||
362 | |||
363 | /* Next Rx RxPD addr */ | ||
364 | __le32 next_rxpd_ptr; | ||
365 | |||
366 | /* Pkt Priority */ | ||
367 | u8 priority; | ||
368 | u8 reserved[3]; | ||
369 | } __attribute__ ((packed)); | ||
370 | |||
371 | struct cmd_header { | ||
372 | __le16 command; | ||
373 | __le16 size; | ||
374 | __le16 seqnum; | ||
375 | __le16 result; | ||
376 | } __attribute__ ((packed)); | ||
377 | |||
378 | /* Generic structure to hold all key types. */ | ||
379 | struct enc_key { | ||
380 | u16 len; | ||
381 | u16 flags; /* KEY_INFO_* from defs.h */ | ||
382 | u16 type; /* KEY_TYPE_* from defs.h */ | ||
383 | u8 key[32]; | ||
384 | }; | ||
385 | |||
386 | /* lbs_offset_value */ | ||
387 | struct lbs_offset_value { | ||
388 | u32 offset; | ||
389 | u32 value; | ||
390 | } __attribute__ ((packed)); | ||
391 | |||
392 | /* | ||
393 | * Define data structure for CMD_GET_HW_SPEC | ||
394 | * This structure defines the response for the GET_HW_SPEC command | ||
395 | */ | ||
396 | struct cmd_ds_get_hw_spec { | ||
397 | struct cmd_header hdr; | ||
398 | |||
399 | /* HW Interface version number */ | ||
400 | __le16 hwifversion; | ||
401 | /* HW version number */ | ||
402 | __le16 version; | ||
403 | /* Max number of TxPD FW can handle */ | ||
404 | __le16 nr_txpd; | ||
405 | /* Max no of Multicast address */ | ||
406 | __le16 nr_mcast_adr; | ||
407 | /* MAC address */ | ||
408 | u8 permanentaddr[6]; | ||
409 | |||
410 | /* region Code */ | ||
411 | __le16 regioncode; | ||
412 | |||
413 | /* Number of antenna used */ | ||
414 | __le16 nr_antenna; | ||
415 | |||
416 | /* FW release number, example 0x01030304 = 2.3.4p1 */ | ||
417 | __le32 fwrelease; | ||
418 | |||
419 | /* Base Address of TxPD queue */ | ||
420 | __le32 wcb_base; | ||
421 | /* Read Pointer of RxPd queue */ | ||
422 | __le32 rxpd_rdptr; | ||
423 | |||
424 | /* Write Pointer of RxPd queue */ | ||
425 | __le32 rxpd_wrptr; | ||
426 | |||
427 | /*FW/HW capability */ | ||
428 | __le32 fwcapinfo; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct cmd_ds_802_11_subscribe_event { | ||
432 | struct cmd_header hdr; | ||
433 | |||
434 | __le16 action; | ||
435 | __le16 events; | ||
436 | |||
437 | /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a | ||
438 | * number of TLVs. From the v5.1 manual, those TLVs would add up to | ||
439 | * 40 bytes. However, future firmware might add additional TLVs, so I | ||
440 | * bump this up a bit. | ||
441 | */ | ||
442 | uint8_t tlv[128]; | ||
443 | } __attribute__ ((packed)); | ||
444 | |||
445 | /* | ||
446 | * This scan handle Country Information IE(802.11d compliant) | ||
447 | * Define data structure for CMD_802_11_SCAN | ||
448 | */ | ||
449 | struct cmd_ds_802_11_scan { | ||
450 | struct cmd_header hdr; | ||
451 | |||
452 | uint8_t bsstype; | ||
453 | uint8_t bssid[ETH_ALEN]; | ||
454 | uint8_t tlvbuffer[0]; | ||
455 | } __attribute__ ((packed)); | ||
456 | |||
457 | struct cmd_ds_802_11_scan_rsp { | ||
458 | struct cmd_header hdr; | ||
459 | |||
460 | __le16 bssdescriptsize; | ||
461 | uint8_t nr_sets; | ||
462 | uint8_t bssdesc_and_tlvbuffer[0]; | ||
463 | } __attribute__ ((packed)); | ||
464 | |||
465 | struct cmd_ds_802_11_get_log { | ||
466 | struct cmd_header hdr; | ||
467 | |||
468 | __le32 mcasttxframe; | ||
469 | __le32 failed; | ||
470 | __le32 retry; | ||
471 | __le32 multiretry; | ||
472 | __le32 framedup; | ||
473 | __le32 rtssuccess; | ||
474 | __le32 rtsfailure; | ||
475 | __le32 ackfailure; | ||
476 | __le32 rxfrag; | ||
477 | __le32 mcastrxframe; | ||
478 | __le32 fcserror; | ||
479 | __le32 txframe; | ||
480 | __le32 wepundecryptable; | ||
481 | } __attribute__ ((packed)); | ||
482 | |||
483 | struct cmd_ds_mac_control { | ||
484 | struct cmd_header hdr; | ||
485 | __le16 action; | ||
486 | u16 reserved; | ||
487 | } __attribute__ ((packed)); | ||
488 | |||
489 | struct cmd_ds_mac_multicast_adr { | ||
490 | struct cmd_header hdr; | ||
491 | __le16 action; | ||
492 | __le16 nr_of_adrs; | ||
493 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | ||
494 | } __attribute__ ((packed)); | ||
495 | |||
496 | struct cmd_ds_802_11_authenticate { | ||
497 | struct cmd_header hdr; | ||
498 | |||
499 | u8 bssid[ETH_ALEN]; | ||
500 | u8 authtype; | ||
501 | u8 reserved[10]; | ||
502 | } __attribute__ ((packed)); | ||
503 | |||
504 | struct cmd_ds_802_11_deauthenticate { | ||
505 | struct cmd_header hdr; | ||
506 | |||
507 | u8 macaddr[ETH_ALEN]; | ||
508 | __le16 reasoncode; | ||
509 | } __attribute__ ((packed)); | ||
510 | |||
511 | struct cmd_ds_802_11_associate { | ||
512 | struct cmd_header hdr; | ||
513 | |||
514 | u8 bssid[6]; | ||
515 | __le16 capability; | ||
516 | __le16 listeninterval; | ||
517 | __le16 bcnperiod; | ||
518 | u8 dtimperiod; | ||
519 | u8 iebuf[512]; /* Enough for required and most optional IEs */ | ||
520 | } __attribute__ ((packed)); | ||
521 | |||
522 | struct cmd_ds_802_11_associate_response { | ||
523 | struct cmd_header hdr; | ||
524 | |||
525 | __le16 capability; | ||
526 | __le16 statuscode; | ||
527 | __le16 aid; | ||
528 | u8 iebuf[512]; | ||
529 | } __attribute__ ((packed)); | ||
530 | |||
531 | struct cmd_ds_802_11_set_wep { | ||
532 | struct cmd_header hdr; | ||
533 | |||
534 | /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ | ||
535 | __le16 action; | ||
536 | |||
537 | /* key Index selected for Tx */ | ||
538 | __le16 keyindex; | ||
539 | |||
540 | /* 40, 128bit or TXWEP */ | ||
541 | uint8_t keytype[4]; | ||
542 | uint8_t keymaterial[4][16]; | ||
543 | } __attribute__ ((packed)); | ||
544 | |||
545 | struct cmd_ds_802_11_snmp_mib { | ||
546 | struct cmd_header hdr; | ||
547 | |||
548 | __le16 action; | ||
549 | __le16 oid; | ||
550 | __le16 bufsize; | ||
551 | u8 value[128]; | ||
552 | } __attribute__ ((packed)); | ||
553 | |||
554 | struct cmd_ds_mac_reg_access { | ||
555 | __le16 action; | ||
556 | __le16 offset; | ||
557 | __le32 value; | ||
558 | } __attribute__ ((packed)); | ||
559 | |||
560 | struct cmd_ds_bbp_reg_access { | ||
561 | __le16 action; | ||
562 | __le16 offset; | ||
563 | u8 value; | ||
564 | u8 reserved[3]; | ||
565 | } __attribute__ ((packed)); | ||
566 | |||
567 | struct cmd_ds_rf_reg_access { | ||
568 | __le16 action; | ||
569 | __le16 offset; | ||
570 | u8 value; | ||
571 | u8 reserved[3]; | ||
572 | } __attribute__ ((packed)); | ||
573 | |||
574 | struct cmd_ds_802_11_radio_control { | ||
575 | struct cmd_header hdr; | ||
576 | |||
577 | __le16 action; | ||
578 | __le16 control; | ||
579 | } __attribute__ ((packed)); | ||
580 | |||
581 | struct cmd_ds_802_11_beacon_control { | ||
582 | __le16 action; | ||
583 | __le16 beacon_enable; | ||
584 | __le16 beacon_period; | ||
585 | } __attribute__ ((packed)); | ||
586 | |||
587 | struct cmd_ds_802_11_sleep_params { | ||
588 | struct cmd_header hdr; | ||
589 | |||
590 | /* ACT_GET/ACT_SET */ | ||
591 | __le16 action; | ||
592 | |||
593 | /* Sleep clock error in ppm */ | ||
594 | __le16 error; | ||
595 | |||
596 | /* Wakeup offset in usec */ | ||
597 | __le16 offset; | ||
598 | |||
599 | /* Clock stabilization time in usec */ | ||
600 | __le16 stabletime; | ||
601 | |||
602 | /* control periodic calibration */ | ||
603 | uint8_t calcontrol; | ||
604 | |||
605 | /* control the use of external sleep clock */ | ||
606 | uint8_t externalsleepclk; | ||
607 | |||
608 | /* reserved field, should be set to zero */ | ||
609 | __le16 reserved; | ||
610 | } __attribute__ ((packed)); | ||
611 | |||
612 | struct cmd_ds_802_11_rf_channel { | ||
613 | struct cmd_header hdr; | ||
614 | |||
615 | __le16 action; | ||
616 | __le16 channel; | ||
617 | __le16 rftype; /* unused */ | ||
618 | __le16 reserved; /* unused */ | ||
619 | u8 channellist[32]; /* unused */ | ||
620 | } __attribute__ ((packed)); | ||
621 | |||
622 | struct cmd_ds_802_11_rssi { | ||
623 | /* weighting factor */ | ||
624 | __le16 N; | ||
625 | |||
626 | __le16 reserved_0; | ||
627 | __le16 reserved_1; | ||
628 | __le16 reserved_2; | ||
629 | } __attribute__ ((packed)); | ||
630 | |||
631 | struct cmd_ds_802_11_rssi_rsp { | ||
632 | __le16 SNR; | ||
633 | __le16 noisefloor; | ||
634 | __le16 avgSNR; | ||
635 | __le16 avgnoisefloor; | ||
636 | } __attribute__ ((packed)); | ||
637 | |||
638 | struct cmd_ds_802_11_mac_address { | ||
639 | struct cmd_header hdr; | ||
640 | |||
641 | __le16 action; | ||
642 | u8 macadd[ETH_ALEN]; | ||
643 | } __attribute__ ((packed)); | ||
644 | |||
645 | struct cmd_ds_802_11_rf_tx_power { | ||
646 | struct cmd_header hdr; | ||
647 | |||
648 | __le16 action; | ||
649 | __le16 curlevel; | ||
650 | s8 maxlevel; | ||
651 | s8 minlevel; | ||
652 | } __attribute__ ((packed)); | ||
653 | |||
654 | struct cmd_ds_802_11_monitor_mode { | ||
655 | __le16 action; | ||
656 | __le16 mode; | ||
657 | } __attribute__ ((packed)); | ||
658 | |||
659 | struct cmd_ds_set_boot2_ver { | ||
660 | struct cmd_header hdr; | ||
661 | |||
662 | __le16 action; | ||
663 | __le16 version; | ||
664 | } __attribute__ ((packed)); | ||
665 | |||
666 | struct cmd_ds_802_11_fw_wake_method { | ||
667 | struct cmd_header hdr; | ||
668 | |||
669 | __le16 action; | ||
670 | __le16 method; | ||
671 | } __attribute__ ((packed)); | ||
672 | |||
673 | struct cmd_ds_802_11_ps_mode { | ||
674 | __le16 action; | ||
675 | __le16 nullpktinterval; | ||
676 | __le16 multipledtim; | ||
677 | __le16 reserved; | ||
678 | __le16 locallisteninterval; | ||
679 | } __attribute__ ((packed)); | ||
680 | |||
681 | struct cmd_confirm_sleep { | ||
682 | struct cmd_header hdr; | ||
683 | |||
684 | __le16 action; | ||
685 | __le16 nullpktinterval; | ||
686 | __le16 multipledtim; | ||
687 | __le16 reserved; | ||
688 | __le16 locallisteninterval; | ||
689 | } __attribute__ ((packed)); | ||
690 | |||
691 | struct cmd_ds_802_11_data_rate { | ||
692 | struct cmd_header hdr; | ||
693 | |||
694 | __le16 action; | ||
695 | __le16 reserved; | ||
696 | u8 rates[MAX_RATES]; | ||
697 | } __attribute__ ((packed)); | ||
698 | |||
699 | struct cmd_ds_802_11_rate_adapt_rateset { | ||
700 | struct cmd_header hdr; | ||
701 | __le16 action; | ||
702 | __le16 enablehwauto; | ||
703 | __le16 bitmap; | ||
704 | } __attribute__ ((packed)); | ||
705 | |||
706 | struct cmd_ds_802_11_ad_hoc_start { | ||
707 | struct cmd_header hdr; | ||
708 | |||
709 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
710 | u8 bsstype; | ||
711 | __le16 beaconperiod; | ||
712 | u8 dtimperiod; /* Reserved on v9 and later */ | ||
713 | struct ieee_ie_ibss_param_set ibss; | ||
714 | u8 reserved1[4]; | ||
715 | struct ieee_ie_ds_param_set ds; | ||
716 | u8 reserved2[4]; | ||
717 | __le16 probedelay; /* Reserved on v9 and later */ | ||
718 | __le16 capability; | ||
719 | u8 rates[MAX_RATES]; | ||
720 | u8 tlv_memory_size_pad[100]; | ||
721 | } __attribute__ ((packed)); | ||
722 | |||
723 | struct cmd_ds_802_11_ad_hoc_result { | ||
724 | struct cmd_header hdr; | ||
725 | |||
726 | u8 pad[3]; | ||
727 | u8 bssid[ETH_ALEN]; | ||
728 | } __attribute__ ((packed)); | ||
729 | |||
730 | struct adhoc_bssdesc { | ||
731 | u8 bssid[ETH_ALEN]; | ||
732 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
733 | u8 type; | ||
734 | __le16 beaconperiod; | ||
735 | u8 dtimperiod; | ||
736 | __le64 timestamp; | ||
737 | __le64 localtime; | ||
738 | struct ieee_ie_ds_param_set ds; | ||
739 | u8 reserved1[4]; | ||
740 | struct ieee_ie_ibss_param_set ibss; | ||
741 | u8 reserved2[4]; | ||
742 | __le16 capability; | ||
743 | u8 rates[MAX_RATES]; | ||
744 | |||
745 | /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the | ||
746 | * Adhoc join command and will cause a binary layout mismatch with | ||
747 | * the firmware | ||
748 | */ | ||
749 | } __attribute__ ((packed)); | ||
750 | |||
751 | struct cmd_ds_802_11_ad_hoc_join { | ||
752 | struct cmd_header hdr; | ||
753 | |||
754 | struct adhoc_bssdesc bss; | ||
755 | __le16 failtimeout; /* Reserved on v9 and later */ | ||
756 | __le16 probedelay; /* Reserved on v9 and later */ | ||
757 | } __attribute__ ((packed)); | ||
758 | |||
759 | struct cmd_ds_802_11_ad_hoc_stop { | ||
760 | struct cmd_header hdr; | ||
761 | } __attribute__ ((packed)); | ||
762 | |||
763 | struct cmd_ds_802_11_enable_rsn { | ||
764 | struct cmd_header hdr; | ||
765 | |||
766 | __le16 action; | ||
767 | __le16 enable; | ||
768 | } __attribute__ ((packed)); | ||
769 | |||
770 | struct MrvlIEtype_keyParamSet { | ||
771 | /* type ID */ | ||
772 | __le16 type; | ||
773 | |||
774 | /* length of Payload */ | ||
775 | __le16 length; | ||
776 | |||
777 | /* type of key: WEP=0, TKIP=1, AES=2 */ | ||
778 | __le16 keytypeid; | ||
779 | |||
780 | /* key control Info specific to a keytypeid */ | ||
781 | __le16 keyinfo; | ||
782 | |||
783 | /* length of key */ | ||
784 | __le16 keylen; | ||
785 | |||
786 | /* key material of size keylen */ | ||
787 | u8 key[32]; | ||
788 | } __attribute__ ((packed)); | ||
789 | |||
790 | #define MAX_WOL_RULES 16 | ||
791 | |||
792 | struct host_wol_rule { | ||
793 | uint8_t rule_no; | ||
794 | uint8_t rule_ops; | ||
795 | __le16 sig_offset; | ||
796 | __le16 sig_length; | ||
797 | __le16 reserve; | ||
798 | __be32 sig_mask; | ||
799 | __be32 signature; | ||
800 | } __attribute__ ((packed)); | ||
801 | |||
802 | struct wol_config { | ||
803 | uint8_t action; | ||
804 | uint8_t pattern; | ||
805 | uint8_t no_rules_in_cmd; | ||
806 | uint8_t result; | ||
807 | struct host_wol_rule rule[MAX_WOL_RULES]; | ||
808 | } __attribute__ ((packed)); | ||
809 | |||
810 | struct cmd_ds_host_sleep { | ||
811 | struct cmd_header hdr; | ||
812 | __le32 criteria; | ||
813 | uint8_t gpio; | ||
814 | uint16_t gap; | ||
815 | struct wol_config wol_conf; | ||
816 | } __attribute__ ((packed)); | ||
817 | |||
818 | |||
819 | |||
820 | struct cmd_ds_802_11_key_material { | ||
821 | struct cmd_header hdr; | ||
822 | |||
823 | __le16 action; | ||
824 | struct MrvlIEtype_keyParamSet keyParamSet[2]; | ||
825 | } __attribute__ ((packed)); | ||
826 | |||
827 | struct cmd_ds_802_11_eeprom_access { | ||
828 | struct cmd_header hdr; | ||
829 | __le16 action; | ||
830 | __le16 offset; | ||
831 | __le16 len; | ||
832 | /* firmware says it returns a maximum of 20 bytes */ | ||
833 | #define LBS_EEPROM_READ_LEN 20 | ||
834 | u8 value[LBS_EEPROM_READ_LEN]; | ||
835 | } __attribute__ ((packed)); | ||
836 | |||
837 | struct cmd_ds_802_11_tpc_cfg { | ||
838 | struct cmd_header hdr; | ||
839 | |||
840 | __le16 action; | ||
841 | uint8_t enable; | ||
842 | int8_t P0; | ||
843 | int8_t P1; | ||
844 | int8_t P2; | ||
845 | uint8_t usesnr; | ||
846 | } __attribute__ ((packed)); | ||
847 | |||
848 | |||
849 | struct cmd_ds_802_11_pa_cfg { | ||
850 | struct cmd_header hdr; | ||
851 | |||
852 | __le16 action; | ||
853 | uint8_t enable; | ||
854 | int8_t P0; | ||
855 | int8_t P1; | ||
856 | int8_t P2; | ||
857 | } __attribute__ ((packed)); | ||
858 | |||
859 | |||
860 | struct cmd_ds_802_11_led_ctrl { | ||
861 | __le16 action; | ||
862 | __le16 numled; | ||
863 | u8 data[256]; | ||
864 | } __attribute__ ((packed)); | ||
865 | |||
866 | struct cmd_ds_802_11_afc { | ||
867 | __le16 afc_auto; | ||
868 | union { | ||
869 | struct { | ||
870 | __le16 threshold; | ||
871 | __le16 period; | ||
872 | }; | ||
873 | struct { | ||
874 | __le16 timing_offset; /* signed */ | ||
875 | __le16 carrier_offset; /* signed */ | ||
876 | }; | ||
877 | }; | ||
878 | } __attribute__ ((packed)); | ||
879 | |||
880 | struct cmd_tx_rate_query { | ||
881 | __le16 txrate; | ||
882 | } __attribute__ ((packed)); | ||
883 | |||
884 | struct cmd_ds_get_tsf { | ||
885 | __le64 tsfvalue; | ||
886 | } __attribute__ ((packed)); | ||
887 | |||
888 | struct cmd_ds_bt_access { | ||
889 | __le16 action; | ||
890 | __le32 id; | ||
891 | u8 addr1[ETH_ALEN]; | ||
892 | u8 addr2[ETH_ALEN]; | ||
893 | } __attribute__ ((packed)); | ||
894 | |||
895 | struct cmd_ds_fwt_access { | ||
896 | __le16 action; | ||
897 | __le32 id; | ||
898 | u8 valid; | ||
899 | u8 da[ETH_ALEN]; | ||
900 | u8 dir; | ||
901 | u8 ra[ETH_ALEN]; | ||
902 | __le32 ssn; | ||
903 | __le32 dsn; | ||
904 | __le32 metric; | ||
905 | u8 rate; | ||
906 | u8 hopcount; | ||
907 | u8 ttl; | ||
908 | __le32 expiration; | ||
909 | u8 sleepmode; | ||
910 | __le32 snr; | ||
911 | __le32 references; | ||
912 | u8 prec[ETH_ALEN]; | ||
913 | } __attribute__ ((packed)); | ||
914 | |||
915 | struct cmd_ds_mesh_config { | ||
916 | struct cmd_header hdr; | ||
917 | |||
918 | __le16 action; | ||
919 | __le16 channel; | ||
920 | __le16 type; | ||
921 | __le16 length; | ||
922 | u8 data[128]; /* last position reserved */ | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | struct cmd_ds_mesh_access { | ||
926 | struct cmd_header hdr; | ||
927 | |||
928 | __le16 action; | ||
929 | __le32 data[32]; /* last position reserved */ | ||
930 | } __attribute__ ((packed)); | ||
931 | |||
932 | /* Number of stats counters returned by the firmware */ | ||
933 | #define MESH_STATS_NUM 8 | ||
934 | |||
935 | struct cmd_ds_command { | ||
936 | /* command header */ | ||
937 | __le16 command; | ||
938 | __le16 size; | ||
939 | __le16 seqnum; | ||
940 | __le16 result; | ||
941 | |||
942 | /* command Body */ | ||
943 | union { | ||
944 | struct cmd_ds_802_11_ps_mode psmode; | ||
945 | struct cmd_ds_802_11_monitor_mode monitor; | ||
946 | struct cmd_ds_802_11_rssi rssi; | ||
947 | struct cmd_ds_802_11_rssi_rsp rssirsp; | ||
948 | struct cmd_ds_mac_reg_access macreg; | ||
949 | struct cmd_ds_bbp_reg_access bbpreg; | ||
950 | struct cmd_ds_rf_reg_access rfreg; | ||
951 | |||
952 | struct cmd_ds_802_11_tpc_cfg tpccfg; | ||
953 | struct cmd_ds_802_11_afc afc; | ||
954 | struct cmd_ds_802_11_led_ctrl ledgpio; | ||
955 | |||
956 | struct cmd_ds_bt_access bt; | ||
957 | struct cmd_ds_fwt_access fwt; | ||
958 | struct cmd_ds_802_11_beacon_control bcn_ctrl; | ||
959 | } params; | ||
960 | } __attribute__ ((packed)); | ||
961 | |||
306 | #endif | 962 | #endif |
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h deleted file mode 100644 index c8a1998d4744..000000000000 --- a/drivers/net/wireless/libertas/hostcmd.h +++ /dev/null | |||
@@ -1,800 +0,0 @@ | |||
1 | /* | ||
2 | * This file contains the function prototypes, data structure | ||
3 | * and defines for all the host/station commands | ||
4 | */ | ||
5 | #ifndef _LBS_HOSTCMD_H | ||
6 | #define _LBS_HOSTCMD_H | ||
7 | |||
8 | #include <linux/wireless.h> | ||
9 | #include "11d.h" | ||
10 | #include "types.h" | ||
11 | |||
12 | /* 802.11-related definitions */ | ||
13 | |||
14 | /* TxPD descriptor */ | ||
15 | struct txpd { | ||
16 | /* union to cope up with later FW revisions */ | ||
17 | union { | ||
18 | /* Current Tx packet status */ | ||
19 | __le32 tx_status; | ||
20 | struct { | ||
21 | /* BSS type: client, AP, etc. */ | ||
22 | u8 bss_type; | ||
23 | /* BSS number */ | ||
24 | u8 bss_num; | ||
25 | /* Reserved */ | ||
26 | __le16 reserved; | ||
27 | } bss; | ||
28 | } u; | ||
29 | /* Tx control */ | ||
30 | __le32 tx_control; | ||
31 | __le32 tx_packet_location; | ||
32 | /* Tx packet length */ | ||
33 | __le16 tx_packet_length; | ||
34 | /* First 2 byte of destination MAC address */ | ||
35 | u8 tx_dest_addr_high[2]; | ||
36 | /* Last 4 byte of destination MAC address */ | ||
37 | u8 tx_dest_addr_low[4]; | ||
38 | /* Pkt Priority */ | ||
39 | u8 priority; | ||
40 | /* Pkt Trasnit Power control */ | ||
41 | u8 powermgmt; | ||
42 | /* Amount of time the packet has been queued in the driver (units = 2ms) */ | ||
43 | u8 pktdelay_2ms; | ||
44 | /* reserved */ | ||
45 | u8 reserved1; | ||
46 | } __attribute__ ((packed)); | ||
47 | |||
48 | /* RxPD Descriptor */ | ||
49 | struct rxpd { | ||
50 | /* union to cope up with later FW revisions */ | ||
51 | union { | ||
52 | /* Current Rx packet status */ | ||
53 | __le16 status; | ||
54 | struct { | ||
55 | /* BSS type: client, AP, etc. */ | ||
56 | u8 bss_type; | ||
57 | /* BSS number */ | ||
58 | u8 bss_num; | ||
59 | } __attribute__ ((packed)) bss; | ||
60 | } __attribute__ ((packed)) u; | ||
61 | |||
62 | /* SNR */ | ||
63 | u8 snr; | ||
64 | |||
65 | /* Tx control */ | ||
66 | u8 rx_control; | ||
67 | |||
68 | /* Pkt length */ | ||
69 | __le16 pkt_len; | ||
70 | |||
71 | /* Noise Floor */ | ||
72 | u8 nf; | ||
73 | |||
74 | /* Rx Packet Rate */ | ||
75 | u8 rx_rate; | ||
76 | |||
77 | /* Pkt addr */ | ||
78 | __le32 pkt_ptr; | ||
79 | |||
80 | /* Next Rx RxPD addr */ | ||
81 | __le32 next_rxpd_ptr; | ||
82 | |||
83 | /* Pkt Priority */ | ||
84 | u8 priority; | ||
85 | u8 reserved[3]; | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | struct cmd_header { | ||
89 | __le16 command; | ||
90 | __le16 size; | ||
91 | __le16 seqnum; | ||
92 | __le16 result; | ||
93 | } __attribute__ ((packed)); | ||
94 | |||
95 | struct cmd_ctrl_node { | ||
96 | struct list_head list; | ||
97 | int result; | ||
98 | /* command response */ | ||
99 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *); | ||
100 | unsigned long callback_arg; | ||
101 | /* command data */ | ||
102 | struct cmd_header *cmdbuf; | ||
103 | /* wait queue */ | ||
104 | u16 cmdwaitqwoken; | ||
105 | wait_queue_head_t cmdwait_q; | ||
106 | }; | ||
107 | |||
108 | /* Generic structure to hold all key types. */ | ||
109 | struct enc_key { | ||
110 | u16 len; | ||
111 | u16 flags; /* KEY_INFO_* from defs.h */ | ||
112 | u16 type; /* KEY_TYPE_* from defs.h */ | ||
113 | u8 key[32]; | ||
114 | }; | ||
115 | |||
116 | /* lbs_offset_value */ | ||
117 | struct lbs_offset_value { | ||
118 | u32 offset; | ||
119 | u32 value; | ||
120 | } __attribute__ ((packed)); | ||
121 | |||
122 | /* Define general data structure */ | ||
123 | /* cmd_DS_GEN */ | ||
124 | struct cmd_ds_gen { | ||
125 | __le16 command; | ||
126 | __le16 size; | ||
127 | __le16 seqnum; | ||
128 | __le16 result; | ||
129 | void *cmdresp[0]; | ||
130 | } __attribute__ ((packed)); | ||
131 | |||
132 | #define S_DS_GEN sizeof(struct cmd_ds_gen) | ||
133 | |||
134 | |||
135 | /* | ||
136 | * Define data structure for CMD_GET_HW_SPEC | ||
137 | * This structure defines the response for the GET_HW_SPEC command | ||
138 | */ | ||
139 | struct cmd_ds_get_hw_spec { | ||
140 | struct cmd_header hdr; | ||
141 | |||
142 | /* HW Interface version number */ | ||
143 | __le16 hwifversion; | ||
144 | /* HW version number */ | ||
145 | __le16 version; | ||
146 | /* Max number of TxPD FW can handle */ | ||
147 | __le16 nr_txpd; | ||
148 | /* Max no of Multicast address */ | ||
149 | __le16 nr_mcast_adr; | ||
150 | /* MAC address */ | ||
151 | u8 permanentaddr[6]; | ||
152 | |||
153 | /* region Code */ | ||
154 | __le16 regioncode; | ||
155 | |||
156 | /* Number of antenna used */ | ||
157 | __le16 nr_antenna; | ||
158 | |||
159 | /* FW release number, example 0x01030304 = 2.3.4p1 */ | ||
160 | __le32 fwrelease; | ||
161 | |||
162 | /* Base Address of TxPD queue */ | ||
163 | __le32 wcb_base; | ||
164 | /* Read Pointer of RxPd queue */ | ||
165 | __le32 rxpd_rdptr; | ||
166 | |||
167 | /* Write Pointer of RxPd queue */ | ||
168 | __le32 rxpd_wrptr; | ||
169 | |||
170 | /*FW/HW capability */ | ||
171 | __le32 fwcapinfo; | ||
172 | } __attribute__ ((packed)); | ||
173 | |||
174 | struct cmd_ds_802_11_subscribe_event { | ||
175 | struct cmd_header hdr; | ||
176 | |||
177 | __le16 action; | ||
178 | __le16 events; | ||
179 | |||
180 | /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a | ||
181 | * number of TLVs. From the v5.1 manual, those TLVs would add up to | ||
182 | * 40 bytes. However, future firmware might add additional TLVs, so I | ||
183 | * bump this up a bit. | ||
184 | */ | ||
185 | uint8_t tlv[128]; | ||
186 | } __attribute__ ((packed)); | ||
187 | |||
188 | /* | ||
189 | * This scan handle Country Information IE(802.11d compliant) | ||
190 | * Define data structure for CMD_802_11_SCAN | ||
191 | */ | ||
192 | struct cmd_ds_802_11_scan { | ||
193 | struct cmd_header hdr; | ||
194 | |||
195 | uint8_t bsstype; | ||
196 | uint8_t bssid[ETH_ALEN]; | ||
197 | uint8_t tlvbuffer[0]; | ||
198 | #if 0 | ||
199 | mrvlietypes_ssidparamset_t ssidParamSet; | ||
200 | mrvlietypes_chanlistparamset_t ChanListParamSet; | ||
201 | mrvlietypes_ratesparamset_t OpRateSet; | ||
202 | #endif | ||
203 | } __attribute__ ((packed)); | ||
204 | |||
205 | struct cmd_ds_802_11_scan_rsp { | ||
206 | struct cmd_header hdr; | ||
207 | |||
208 | __le16 bssdescriptsize; | ||
209 | uint8_t nr_sets; | ||
210 | uint8_t bssdesc_and_tlvbuffer[0]; | ||
211 | } __attribute__ ((packed)); | ||
212 | |||
213 | struct cmd_ds_802_11_get_log { | ||
214 | struct cmd_header hdr; | ||
215 | |||
216 | __le32 mcasttxframe; | ||
217 | __le32 failed; | ||
218 | __le32 retry; | ||
219 | __le32 multiretry; | ||
220 | __le32 framedup; | ||
221 | __le32 rtssuccess; | ||
222 | __le32 rtsfailure; | ||
223 | __le32 ackfailure; | ||
224 | __le32 rxfrag; | ||
225 | __le32 mcastrxframe; | ||
226 | __le32 fcserror; | ||
227 | __le32 txframe; | ||
228 | __le32 wepundecryptable; | ||
229 | } __attribute__ ((packed)); | ||
230 | |||
231 | struct cmd_ds_mac_control { | ||
232 | struct cmd_header hdr; | ||
233 | __le16 action; | ||
234 | u16 reserved; | ||
235 | } __attribute__ ((packed)); | ||
236 | |||
237 | struct cmd_ds_mac_multicast_adr { | ||
238 | struct cmd_header hdr; | ||
239 | __le16 action; | ||
240 | __le16 nr_of_adrs; | ||
241 | u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; | ||
242 | } __attribute__ ((packed)); | ||
243 | |||
244 | struct cmd_ds_gspi_bus_config { | ||
245 | struct cmd_header hdr; | ||
246 | __le16 action; | ||
247 | __le16 bus_delay_mode; | ||
248 | __le16 host_time_delay_to_read_port; | ||
249 | __le16 host_time_delay_to_read_register; | ||
250 | } __attribute__ ((packed)); | ||
251 | |||
252 | struct cmd_ds_802_11_authenticate { | ||
253 | struct cmd_header hdr; | ||
254 | |||
255 | u8 bssid[ETH_ALEN]; | ||
256 | u8 authtype; | ||
257 | u8 reserved[10]; | ||
258 | } __attribute__ ((packed)); | ||
259 | |||
260 | struct cmd_ds_802_11_deauthenticate { | ||
261 | struct cmd_header hdr; | ||
262 | |||
263 | u8 macaddr[ETH_ALEN]; | ||
264 | __le16 reasoncode; | ||
265 | } __attribute__ ((packed)); | ||
266 | |||
267 | struct cmd_ds_802_11_associate { | ||
268 | struct cmd_header hdr; | ||
269 | |||
270 | u8 bssid[6]; | ||
271 | __le16 capability; | ||
272 | __le16 listeninterval; | ||
273 | __le16 bcnperiod; | ||
274 | u8 dtimperiod; | ||
275 | u8 iebuf[512]; /* Enough for required and most optional IEs */ | ||
276 | } __attribute__ ((packed)); | ||
277 | |||
278 | struct cmd_ds_802_11_associate_response { | ||
279 | struct cmd_header hdr; | ||
280 | |||
281 | __le16 capability; | ||
282 | __le16 statuscode; | ||
283 | __le16 aid; | ||
284 | u8 iebuf[512]; | ||
285 | } __attribute__ ((packed)); | ||
286 | |||
287 | struct cmd_ds_802_11_set_wep { | ||
288 | struct cmd_header hdr; | ||
289 | |||
290 | /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ | ||
291 | __le16 action; | ||
292 | |||
293 | /* key Index selected for Tx */ | ||
294 | __le16 keyindex; | ||
295 | |||
296 | /* 40, 128bit or TXWEP */ | ||
297 | uint8_t keytype[4]; | ||
298 | uint8_t keymaterial[4][16]; | ||
299 | } __attribute__ ((packed)); | ||
300 | |||
301 | struct cmd_ds_802_3_get_stat { | ||
302 | __le32 xmitok; | ||
303 | __le32 rcvok; | ||
304 | __le32 xmiterror; | ||
305 | __le32 rcverror; | ||
306 | __le32 rcvnobuffer; | ||
307 | __le32 rcvcrcerror; | ||
308 | } __attribute__ ((packed)); | ||
309 | |||
310 | struct cmd_ds_802_11_get_stat { | ||
311 | __le32 txfragmentcnt; | ||
312 | __le32 mcasttxframecnt; | ||
313 | __le32 failedcnt; | ||
314 | __le32 retrycnt; | ||
315 | __le32 Multipleretrycnt; | ||
316 | __le32 rtssuccesscnt; | ||
317 | __le32 rtsfailurecnt; | ||
318 | __le32 ackfailurecnt; | ||
319 | __le32 frameduplicatecnt; | ||
320 | __le32 rxfragmentcnt; | ||
321 | __le32 mcastrxframecnt; | ||
322 | __le32 fcserrorcnt; | ||
323 | __le32 bcasttxframecnt; | ||
324 | __le32 bcastrxframecnt; | ||
325 | __le32 txbeacon; | ||
326 | __le32 rxbeacon; | ||
327 | __le32 wepundecryptable; | ||
328 | } __attribute__ ((packed)); | ||
329 | |||
330 | struct cmd_ds_802_11_snmp_mib { | ||
331 | struct cmd_header hdr; | ||
332 | |||
333 | __le16 action; | ||
334 | __le16 oid; | ||
335 | __le16 bufsize; | ||
336 | u8 value[128]; | ||
337 | } __attribute__ ((packed)); | ||
338 | |||
339 | struct cmd_ds_mac_reg_map { | ||
340 | __le16 buffersize; | ||
341 | u8 regmap[128]; | ||
342 | __le16 reserved; | ||
343 | } __attribute__ ((packed)); | ||
344 | |||
345 | struct cmd_ds_bbp_reg_map { | ||
346 | __le16 buffersize; | ||
347 | u8 regmap[128]; | ||
348 | __le16 reserved; | ||
349 | } __attribute__ ((packed)); | ||
350 | |||
351 | struct cmd_ds_rf_reg_map { | ||
352 | __le16 buffersize; | ||
353 | u8 regmap[64]; | ||
354 | __le16 reserved; | ||
355 | } __attribute__ ((packed)); | ||
356 | |||
357 | struct cmd_ds_mac_reg_access { | ||
358 | __le16 action; | ||
359 | __le16 offset; | ||
360 | __le32 value; | ||
361 | } __attribute__ ((packed)); | ||
362 | |||
363 | struct cmd_ds_bbp_reg_access { | ||
364 | __le16 action; | ||
365 | __le16 offset; | ||
366 | u8 value; | ||
367 | u8 reserved[3]; | ||
368 | } __attribute__ ((packed)); | ||
369 | |||
370 | struct cmd_ds_rf_reg_access { | ||
371 | __le16 action; | ||
372 | __le16 offset; | ||
373 | u8 value; | ||
374 | u8 reserved[3]; | ||
375 | } __attribute__ ((packed)); | ||
376 | |||
377 | struct cmd_ds_802_11_radio_control { | ||
378 | struct cmd_header hdr; | ||
379 | |||
380 | __le16 action; | ||
381 | __le16 control; | ||
382 | } __attribute__ ((packed)); | ||
383 | |||
384 | struct cmd_ds_802_11_beacon_control { | ||
385 | __le16 action; | ||
386 | __le16 beacon_enable; | ||
387 | __le16 beacon_period; | ||
388 | } __attribute__ ((packed)); | ||
389 | |||
390 | struct cmd_ds_802_11_sleep_params { | ||
391 | struct cmd_header hdr; | ||
392 | |||
393 | /* ACT_GET/ACT_SET */ | ||
394 | __le16 action; | ||
395 | |||
396 | /* Sleep clock error in ppm */ | ||
397 | __le16 error; | ||
398 | |||
399 | /* Wakeup offset in usec */ | ||
400 | __le16 offset; | ||
401 | |||
402 | /* Clock stabilization time in usec */ | ||
403 | __le16 stabletime; | ||
404 | |||
405 | /* control periodic calibration */ | ||
406 | uint8_t calcontrol; | ||
407 | |||
408 | /* control the use of external sleep clock */ | ||
409 | uint8_t externalsleepclk; | ||
410 | |||
411 | /* reserved field, should be set to zero */ | ||
412 | __le16 reserved; | ||
413 | } __attribute__ ((packed)); | ||
414 | |||
415 | struct cmd_ds_802_11_inactivity_timeout { | ||
416 | struct cmd_header hdr; | ||
417 | |||
418 | /* ACT_GET/ACT_SET */ | ||
419 | __le16 action; | ||
420 | |||
421 | /* Inactivity timeout in msec */ | ||
422 | __le16 timeout; | ||
423 | } __attribute__ ((packed)); | ||
424 | |||
425 | struct cmd_ds_802_11_rf_channel { | ||
426 | struct cmd_header hdr; | ||
427 | |||
428 | __le16 action; | ||
429 | __le16 channel; | ||
430 | __le16 rftype; /* unused */ | ||
431 | __le16 reserved; /* unused */ | ||
432 | u8 channellist[32]; /* unused */ | ||
433 | } __attribute__ ((packed)); | ||
434 | |||
435 | struct cmd_ds_802_11_rssi { | ||
436 | /* weighting factor */ | ||
437 | __le16 N; | ||
438 | |||
439 | __le16 reserved_0; | ||
440 | __le16 reserved_1; | ||
441 | __le16 reserved_2; | ||
442 | } __attribute__ ((packed)); | ||
443 | |||
444 | struct cmd_ds_802_11_rssi_rsp { | ||
445 | __le16 SNR; | ||
446 | __le16 noisefloor; | ||
447 | __le16 avgSNR; | ||
448 | __le16 avgnoisefloor; | ||
449 | } __attribute__ ((packed)); | ||
450 | |||
451 | struct cmd_ds_802_11_mac_address { | ||
452 | struct cmd_header hdr; | ||
453 | |||
454 | __le16 action; | ||
455 | u8 macadd[ETH_ALEN]; | ||
456 | } __attribute__ ((packed)); | ||
457 | |||
458 | struct cmd_ds_802_11_rf_tx_power { | ||
459 | struct cmd_header hdr; | ||
460 | |||
461 | __le16 action; | ||
462 | __le16 curlevel; | ||
463 | s8 maxlevel; | ||
464 | s8 minlevel; | ||
465 | } __attribute__ ((packed)); | ||
466 | |||
467 | struct cmd_ds_802_11_rf_antenna { | ||
468 | __le16 action; | ||
469 | |||
470 | /* Number of antennas or 0xffff(diversity) */ | ||
471 | __le16 antennamode; | ||
472 | |||
473 | } __attribute__ ((packed)); | ||
474 | |||
475 | struct cmd_ds_802_11_monitor_mode { | ||
476 | __le16 action; | ||
477 | __le16 mode; | ||
478 | } __attribute__ ((packed)); | ||
479 | |||
480 | struct cmd_ds_set_boot2_ver { | ||
481 | struct cmd_header hdr; | ||
482 | |||
483 | __le16 action; | ||
484 | __le16 version; | ||
485 | } __attribute__ ((packed)); | ||
486 | |||
487 | struct cmd_ds_802_11_fw_wake_method { | ||
488 | struct cmd_header hdr; | ||
489 | |||
490 | __le16 action; | ||
491 | __le16 method; | ||
492 | } __attribute__ ((packed)); | ||
493 | |||
494 | struct cmd_ds_802_11_sleep_period { | ||
495 | struct cmd_header hdr; | ||
496 | |||
497 | __le16 action; | ||
498 | __le16 period; | ||
499 | } __attribute__ ((packed)); | ||
500 | |||
501 | struct cmd_ds_802_11_ps_mode { | ||
502 | __le16 action; | ||
503 | __le16 nullpktinterval; | ||
504 | __le16 multipledtim; | ||
505 | __le16 reserved; | ||
506 | __le16 locallisteninterval; | ||
507 | } __attribute__ ((packed)); | ||
508 | |||
509 | struct cmd_confirm_sleep { | ||
510 | struct cmd_header hdr; | ||
511 | |||
512 | __le16 action; | ||
513 | __le16 nullpktinterval; | ||
514 | __le16 multipledtim; | ||
515 | __le16 reserved; | ||
516 | __le16 locallisteninterval; | ||
517 | } __attribute__ ((packed)); | ||
518 | |||
519 | struct cmd_ds_802_11_data_rate { | ||
520 | struct cmd_header hdr; | ||
521 | |||
522 | __le16 action; | ||
523 | __le16 reserved; | ||
524 | u8 rates[MAX_RATES]; | ||
525 | } __attribute__ ((packed)); | ||
526 | |||
527 | struct cmd_ds_802_11_rate_adapt_rateset { | ||
528 | struct cmd_header hdr; | ||
529 | __le16 action; | ||
530 | __le16 enablehwauto; | ||
531 | __le16 bitmap; | ||
532 | } __attribute__ ((packed)); | ||
533 | |||
534 | struct cmd_ds_802_11_ad_hoc_start { | ||
535 | struct cmd_header hdr; | ||
536 | |||
537 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
538 | u8 bsstype; | ||
539 | __le16 beaconperiod; | ||
540 | u8 dtimperiod; /* Reserved on v9 and later */ | ||
541 | struct ieee_ie_ibss_param_set ibss; | ||
542 | u8 reserved1[4]; | ||
543 | struct ieee_ie_ds_param_set ds; | ||
544 | u8 reserved2[4]; | ||
545 | __le16 probedelay; /* Reserved on v9 and later */ | ||
546 | __le16 capability; | ||
547 | u8 rates[MAX_RATES]; | ||
548 | u8 tlv_memory_size_pad[100]; | ||
549 | } __attribute__ ((packed)); | ||
550 | |||
551 | struct cmd_ds_802_11_ad_hoc_result { | ||
552 | struct cmd_header hdr; | ||
553 | |||
554 | u8 pad[3]; | ||
555 | u8 bssid[ETH_ALEN]; | ||
556 | } __attribute__ ((packed)); | ||
557 | |||
558 | struct adhoc_bssdesc { | ||
559 | u8 bssid[ETH_ALEN]; | ||
560 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
561 | u8 type; | ||
562 | __le16 beaconperiod; | ||
563 | u8 dtimperiod; | ||
564 | __le64 timestamp; | ||
565 | __le64 localtime; | ||
566 | struct ieee_ie_ds_param_set ds; | ||
567 | u8 reserved1[4]; | ||
568 | struct ieee_ie_ibss_param_set ibss; | ||
569 | u8 reserved2[4]; | ||
570 | __le16 capability; | ||
571 | u8 rates[MAX_RATES]; | ||
572 | |||
573 | /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the | ||
574 | * Adhoc join command and will cause a binary layout mismatch with | ||
575 | * the firmware | ||
576 | */ | ||
577 | } __attribute__ ((packed)); | ||
578 | |||
579 | struct cmd_ds_802_11_ad_hoc_join { | ||
580 | struct cmd_header hdr; | ||
581 | |||
582 | struct adhoc_bssdesc bss; | ||
583 | __le16 failtimeout; /* Reserved on v9 and later */ | ||
584 | __le16 probedelay; /* Reserved on v9 and later */ | ||
585 | } __attribute__ ((packed)); | ||
586 | |||
587 | struct cmd_ds_802_11_ad_hoc_stop { | ||
588 | struct cmd_header hdr; | ||
589 | } __attribute__ ((packed)); | ||
590 | |||
591 | struct cmd_ds_802_11_enable_rsn { | ||
592 | struct cmd_header hdr; | ||
593 | |||
594 | __le16 action; | ||
595 | __le16 enable; | ||
596 | } __attribute__ ((packed)); | ||
597 | |||
598 | struct MrvlIEtype_keyParamSet { | ||
599 | /* type ID */ | ||
600 | __le16 type; | ||
601 | |||
602 | /* length of Payload */ | ||
603 | __le16 length; | ||
604 | |||
605 | /* type of key: WEP=0, TKIP=1, AES=2 */ | ||
606 | __le16 keytypeid; | ||
607 | |||
608 | /* key control Info specific to a keytypeid */ | ||
609 | __le16 keyinfo; | ||
610 | |||
611 | /* length of key */ | ||
612 | __le16 keylen; | ||
613 | |||
614 | /* key material of size keylen */ | ||
615 | u8 key[32]; | ||
616 | } __attribute__ ((packed)); | ||
617 | |||
618 | #define MAX_WOL_RULES 16 | ||
619 | |||
620 | struct host_wol_rule { | ||
621 | uint8_t rule_no; | ||
622 | uint8_t rule_ops; | ||
623 | __le16 sig_offset; | ||
624 | __le16 sig_length; | ||
625 | __le16 reserve; | ||
626 | __be32 sig_mask; | ||
627 | __be32 signature; | ||
628 | } __attribute__ ((packed)); | ||
629 | |||
630 | struct wol_config { | ||
631 | uint8_t action; | ||
632 | uint8_t pattern; | ||
633 | uint8_t no_rules_in_cmd; | ||
634 | uint8_t result; | ||
635 | struct host_wol_rule rule[MAX_WOL_RULES]; | ||
636 | } __attribute__ ((packed)); | ||
637 | |||
638 | struct cmd_ds_host_sleep { | ||
639 | struct cmd_header hdr; | ||
640 | __le32 criteria; | ||
641 | uint8_t gpio; | ||
642 | uint16_t gap; | ||
643 | struct wol_config wol_conf; | ||
644 | } __attribute__ ((packed)); | ||
645 | |||
646 | |||
647 | |||
648 | struct cmd_ds_802_11_key_material { | ||
649 | struct cmd_header hdr; | ||
650 | |||
651 | __le16 action; | ||
652 | struct MrvlIEtype_keyParamSet keyParamSet[2]; | ||
653 | } __attribute__ ((packed)); | ||
654 | |||
655 | struct cmd_ds_802_11_eeprom_access { | ||
656 | struct cmd_header hdr; | ||
657 | __le16 action; | ||
658 | __le16 offset; | ||
659 | __le16 len; | ||
660 | /* firmware says it returns a maximum of 20 bytes */ | ||
661 | #define LBS_EEPROM_READ_LEN 20 | ||
662 | u8 value[LBS_EEPROM_READ_LEN]; | ||
663 | } __attribute__ ((packed)); | ||
664 | |||
665 | struct cmd_ds_802_11_tpc_cfg { | ||
666 | struct cmd_header hdr; | ||
667 | |||
668 | __le16 action; | ||
669 | uint8_t enable; | ||
670 | int8_t P0; | ||
671 | int8_t P1; | ||
672 | int8_t P2; | ||
673 | uint8_t usesnr; | ||
674 | } __attribute__ ((packed)); | ||
675 | |||
676 | |||
677 | struct cmd_ds_802_11_pa_cfg { | ||
678 | struct cmd_header hdr; | ||
679 | |||
680 | __le16 action; | ||
681 | uint8_t enable; | ||
682 | int8_t P0; | ||
683 | int8_t P1; | ||
684 | int8_t P2; | ||
685 | } __attribute__ ((packed)); | ||
686 | |||
687 | |||
688 | struct cmd_ds_802_11_led_ctrl { | ||
689 | __le16 action; | ||
690 | __le16 numled; | ||
691 | u8 data[256]; | ||
692 | } __attribute__ ((packed)); | ||
693 | |||
694 | struct cmd_ds_802_11_afc { | ||
695 | __le16 afc_auto; | ||
696 | union { | ||
697 | struct { | ||
698 | __le16 threshold; | ||
699 | __le16 period; | ||
700 | }; | ||
701 | struct { | ||
702 | __le16 timing_offset; /* signed */ | ||
703 | __le16 carrier_offset; /* signed */ | ||
704 | }; | ||
705 | }; | ||
706 | } __attribute__ ((packed)); | ||
707 | |||
708 | struct cmd_tx_rate_query { | ||
709 | __le16 txrate; | ||
710 | } __attribute__ ((packed)); | ||
711 | |||
712 | struct cmd_ds_get_tsf { | ||
713 | __le64 tsfvalue; | ||
714 | } __attribute__ ((packed)); | ||
715 | |||
716 | struct cmd_ds_bt_access { | ||
717 | __le16 action; | ||
718 | __le32 id; | ||
719 | u8 addr1[ETH_ALEN]; | ||
720 | u8 addr2[ETH_ALEN]; | ||
721 | } __attribute__ ((packed)); | ||
722 | |||
723 | struct cmd_ds_fwt_access { | ||
724 | __le16 action; | ||
725 | __le32 id; | ||
726 | u8 valid; | ||
727 | u8 da[ETH_ALEN]; | ||
728 | u8 dir; | ||
729 | u8 ra[ETH_ALEN]; | ||
730 | __le32 ssn; | ||
731 | __le32 dsn; | ||
732 | __le32 metric; | ||
733 | u8 rate; | ||
734 | u8 hopcount; | ||
735 | u8 ttl; | ||
736 | __le32 expiration; | ||
737 | u8 sleepmode; | ||
738 | __le32 snr; | ||
739 | __le32 references; | ||
740 | u8 prec[ETH_ALEN]; | ||
741 | } __attribute__ ((packed)); | ||
742 | |||
743 | |||
744 | struct cmd_ds_mesh_config { | ||
745 | struct cmd_header hdr; | ||
746 | |||
747 | __le16 action; | ||
748 | __le16 channel; | ||
749 | __le16 type; | ||
750 | __le16 length; | ||
751 | u8 data[128]; /* last position reserved */ | ||
752 | } __attribute__ ((packed)); | ||
753 | |||
754 | |||
755 | struct cmd_ds_mesh_access { | ||
756 | struct cmd_header hdr; | ||
757 | |||
758 | __le16 action; | ||
759 | __le32 data[32]; /* last position reserved */ | ||
760 | } __attribute__ ((packed)); | ||
761 | |||
762 | /* Number of stats counters returned by the firmware */ | ||
763 | #define MESH_STATS_NUM 8 | ||
764 | |||
765 | struct cmd_ds_command { | ||
766 | /* command header */ | ||
767 | __le16 command; | ||
768 | __le16 size; | ||
769 | __le16 seqnum; | ||
770 | __le16 result; | ||
771 | |||
772 | /* command Body */ | ||
773 | union { | ||
774 | struct cmd_ds_802_11_ps_mode psmode; | ||
775 | struct cmd_ds_802_11_get_stat gstat; | ||
776 | struct cmd_ds_802_3_get_stat gstat_8023; | ||
777 | struct cmd_ds_802_11_rf_antenna rant; | ||
778 | struct cmd_ds_802_11_monitor_mode monitor; | ||
779 | struct cmd_ds_802_11_rssi rssi; | ||
780 | struct cmd_ds_802_11_rssi_rsp rssirsp; | ||
781 | struct cmd_ds_mac_reg_access macreg; | ||
782 | struct cmd_ds_bbp_reg_access bbpreg; | ||
783 | struct cmd_ds_rf_reg_access rfreg; | ||
784 | |||
785 | struct cmd_ds_802_11d_domain_info domaininfo; | ||
786 | struct cmd_ds_802_11d_domain_info domaininforesp; | ||
787 | |||
788 | struct cmd_ds_802_11_tpc_cfg tpccfg; | ||
789 | struct cmd_ds_802_11_afc afc; | ||
790 | struct cmd_ds_802_11_led_ctrl ledgpio; | ||
791 | |||
792 | struct cmd_tx_rate_query txrate; | ||
793 | struct cmd_ds_bt_access bt; | ||
794 | struct cmd_ds_fwt_access fwt; | ||
795 | struct cmd_ds_get_tsf gettsf; | ||
796 | struct cmd_ds_802_11_beacon_control bcn_ctrl; | ||
797 | } params; | ||
798 | } __attribute__ ((packed)); | ||
799 | |||
800 | #endif | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 87bfd17b9c8c..01f46cf288d7 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -45,119 +45,6 @@ module_param_named(libertas_debug, lbs_debug, int, 0644); | |||
45 | struct cmd_confirm_sleep confirm_sleep; | 45 | struct cmd_confirm_sleep confirm_sleep; |
46 | 46 | ||
47 | 47 | ||
48 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | ||
49 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | ||
50 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | ||
51 | #define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ | ||
52 | #define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ | ||
53 | |||
54 | /* Format { channel, frequency (MHz), maxtxpower } */ | ||
55 | /* band: 'B/G', region: USA FCC/Canada IC */ | ||
56 | static struct chan_freq_power channel_freq_power_US_BG[] = { | ||
57 | {1, 2412, LBS_TX_PWR_US_DEFAULT}, | ||
58 | {2, 2417, LBS_TX_PWR_US_DEFAULT}, | ||
59 | {3, 2422, LBS_TX_PWR_US_DEFAULT}, | ||
60 | {4, 2427, LBS_TX_PWR_US_DEFAULT}, | ||
61 | {5, 2432, LBS_TX_PWR_US_DEFAULT}, | ||
62 | {6, 2437, LBS_TX_PWR_US_DEFAULT}, | ||
63 | {7, 2442, LBS_TX_PWR_US_DEFAULT}, | ||
64 | {8, 2447, LBS_TX_PWR_US_DEFAULT}, | ||
65 | {9, 2452, LBS_TX_PWR_US_DEFAULT}, | ||
66 | {10, 2457, LBS_TX_PWR_US_DEFAULT}, | ||
67 | {11, 2462, LBS_TX_PWR_US_DEFAULT} | ||
68 | }; | ||
69 | |||
70 | /* band: 'B/G', region: Europe ETSI */ | ||
71 | static struct chan_freq_power channel_freq_power_EU_BG[] = { | ||
72 | {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, | ||
73 | {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, | ||
74 | {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, | ||
75 | {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, | ||
76 | {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, | ||
77 | {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, | ||
78 | {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, | ||
79 | {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, | ||
80 | {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, | ||
81 | {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, | ||
82 | {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, | ||
83 | {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, | ||
84 | {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} | ||
85 | }; | ||
86 | |||
87 | /* band: 'B/G', region: Spain */ | ||
88 | static struct chan_freq_power channel_freq_power_SPN_BG[] = { | ||
89 | {10, 2457, LBS_TX_PWR_DEFAULT}, | ||
90 | {11, 2462, LBS_TX_PWR_DEFAULT} | ||
91 | }; | ||
92 | |||
93 | /* band: 'B/G', region: France */ | ||
94 | static struct chan_freq_power channel_freq_power_FR_BG[] = { | ||
95 | {10, 2457, LBS_TX_PWR_FR_DEFAULT}, | ||
96 | {11, 2462, LBS_TX_PWR_FR_DEFAULT}, | ||
97 | {12, 2467, LBS_TX_PWR_FR_DEFAULT}, | ||
98 | {13, 2472, LBS_TX_PWR_FR_DEFAULT} | ||
99 | }; | ||
100 | |||
101 | /* band: 'B/G', region: Japan */ | ||
102 | static struct chan_freq_power channel_freq_power_JPN_BG[] = { | ||
103 | {1, 2412, LBS_TX_PWR_JP_DEFAULT}, | ||
104 | {2, 2417, LBS_TX_PWR_JP_DEFAULT}, | ||
105 | {3, 2422, LBS_TX_PWR_JP_DEFAULT}, | ||
106 | {4, 2427, LBS_TX_PWR_JP_DEFAULT}, | ||
107 | {5, 2432, LBS_TX_PWR_JP_DEFAULT}, | ||
108 | {6, 2437, LBS_TX_PWR_JP_DEFAULT}, | ||
109 | {7, 2442, LBS_TX_PWR_JP_DEFAULT}, | ||
110 | {8, 2447, LBS_TX_PWR_JP_DEFAULT}, | ||
111 | {9, 2452, LBS_TX_PWR_JP_DEFAULT}, | ||
112 | {10, 2457, LBS_TX_PWR_JP_DEFAULT}, | ||
113 | {11, 2462, LBS_TX_PWR_JP_DEFAULT}, | ||
114 | {12, 2467, LBS_TX_PWR_JP_DEFAULT}, | ||
115 | {13, 2472, LBS_TX_PWR_JP_DEFAULT}, | ||
116 | {14, 2484, LBS_TX_PWR_JP_DEFAULT} | ||
117 | }; | ||
118 | |||
119 | /** | ||
120 | * the structure for channel, frequency and power | ||
121 | */ | ||
122 | struct region_cfp_table { | ||
123 | u8 region; | ||
124 | struct chan_freq_power *cfp_BG; | ||
125 | int cfp_no_BG; | ||
126 | }; | ||
127 | |||
128 | /** | ||
129 | * the structure for the mapping between region and CFP | ||
130 | */ | ||
131 | static struct region_cfp_table region_cfp_table[] = { | ||
132 | {0x10, /*US FCC */ | ||
133 | channel_freq_power_US_BG, | ||
134 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
135 | } | ||
136 | , | ||
137 | {0x20, /*CANADA IC */ | ||
138 | channel_freq_power_US_BG, | ||
139 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
140 | } | ||
141 | , | ||
142 | {0x30, /*EU*/ channel_freq_power_EU_BG, | ||
143 | ARRAY_SIZE(channel_freq_power_EU_BG), | ||
144 | } | ||
145 | , | ||
146 | {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, | ||
147 | ARRAY_SIZE(channel_freq_power_SPN_BG), | ||
148 | } | ||
149 | , | ||
150 | {0x32, /*FRANCE*/ channel_freq_power_FR_BG, | ||
151 | ARRAY_SIZE(channel_freq_power_FR_BG), | ||
152 | } | ||
153 | , | ||
154 | {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, | ||
155 | ARRAY_SIZE(channel_freq_power_JPN_BG), | ||
156 | } | ||
157 | , | ||
158 | /*Add new region here */ | ||
159 | }; | ||
160 | |||
161 | /** | 48 | /** |
162 | * the table to keep region code | 49 | * the table to keep region code |
163 | */ | 50 | */ |
@@ -165,13 +52,6 @@ u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = | |||
165 | { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; | 52 | { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; |
166 | 53 | ||
167 | /** | 54 | /** |
168 | * 802.11b/g supported bitrates (in 500Kb/s units) | ||
169 | */ | ||
170 | u8 lbs_bg_rates[MAX_RATES] = | ||
171 | { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, | ||
172 | 0x00, 0x00 }; | ||
173 | |||
174 | /** | ||
175 | * FW rate table. FW refers to rates by their index in this table, not by the | 55 | * FW rate table. FW refers to rates by their index in this table, not by the |
176 | * rate value itself. Values of 0x00 are | 56 | * rate value itself. Values of 0x00 are |
177 | * reserved positions. | 57 | * reserved positions. |
@@ -405,7 +285,7 @@ static ssize_t lbs_mesh_set(struct device *dev, | |||
405 | return count; | 285 | return count; |
406 | if (enable) | 286 | if (enable) |
407 | action = CMD_ACT_MESH_CONFIG_START; | 287 | action = CMD_ACT_MESH_CONFIG_START; |
408 | ret = lbs_mesh_config(priv, action, priv->curbssparams.channel); | 288 | ret = lbs_mesh_config(priv, action, priv->channel); |
409 | if (ret) | 289 | if (ret) |
410 | return ret; | 290 | return ret; |
411 | 291 | ||
@@ -1089,6 +969,8 @@ static void auto_deepsleep_timer_fn(unsigned long data) | |||
1089 | ret = lbs_prepare_and_send_command(priv, | 969 | ret = lbs_prepare_and_send_command(priv, |
1090 | CMD_802_11_DEEP_SLEEP, 0, | 970 | CMD_802_11_DEEP_SLEEP, 0, |
1091 | 0, 0, NULL); | 971 | 0, 0, NULL); |
972 | if (ret) | ||
973 | lbs_pr_err("Enter Deep Sleep command failed\n"); | ||
1092 | } | 974 | } |
1093 | } | 975 | } |
1094 | mod_timer(&priv->auto_deepsleep_timer , jiffies + | 976 | mod_timer(&priv->auto_deepsleep_timer , jiffies + |
@@ -1164,7 +1046,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1164 | priv->mesh_connect_status = LBS_DISCONNECTED; | 1046 | priv->mesh_connect_status = LBS_DISCONNECTED; |
1165 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; | 1047 | priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; |
1166 | priv->mode = IW_MODE_INFRA; | 1048 | priv->mode = IW_MODE_INFRA; |
1167 | priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; | 1049 | priv->channel = DEFAULT_AD_HOC_CHANNEL; |
1168 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; | 1050 | priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; |
1169 | priv->radio_on = 1; | 1051 | priv->radio_on = 1; |
1170 | priv->enablehwauto = 1; | 1052 | priv->enablehwauto = 1; |
@@ -1345,7 +1227,6 @@ EXPORT_SYMBOL_GPL(lbs_add_card); | |||
1345 | void lbs_remove_card(struct lbs_private *priv) | 1227 | void lbs_remove_card(struct lbs_private *priv) |
1346 | { | 1228 | { |
1347 | struct net_device *dev = priv->dev; | 1229 | struct net_device *dev = priv->dev; |
1348 | union iwreq_data wrqu; | ||
1349 | 1230 | ||
1350 | lbs_deb_enter(LBS_DEB_MAIN); | 1231 | lbs_deb_enter(LBS_DEB_MAIN); |
1351 | 1232 | ||
@@ -1370,9 +1251,7 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1370 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); | 1251 | lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); |
1371 | } | 1252 | } |
1372 | 1253 | ||
1373 | memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); | 1254 | lbs_send_disconnect_notification(priv); |
1374 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1375 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1376 | 1255 | ||
1377 | if (priv->is_deep_sleep) { | 1256 | if (priv->is_deep_sleep) { |
1378 | priv->is_deep_sleep = 0; | 1257 | priv->is_deep_sleep = 0; |
@@ -1406,9 +1285,6 @@ int lbs_start_card(struct lbs_private *priv) | |||
1406 | if (ret) | 1285 | if (ret) |
1407 | goto done; | 1286 | goto done; |
1408 | 1287 | ||
1409 | /* init 802.11d */ | ||
1410 | lbs_init_11d(priv); | ||
1411 | |||
1412 | if (lbs_cfg_register(priv)) { | 1288 | if (lbs_cfg_register(priv)) { |
1413 | lbs_pr_err("cannot register device\n"); | 1289 | lbs_pr_err("cannot register device\n"); |
1414 | goto done; | 1290 | goto done; |
@@ -1435,10 +1311,10 @@ int lbs_start_card(struct lbs_private *priv) | |||
1435 | 1311 | ||
1436 | priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; | 1312 | priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; |
1437 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 1313 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1438 | priv->curbssparams.channel)) { | 1314 | priv->channel)) { |
1439 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | 1315 | priv->mesh_tlv = TLV_TYPE_MESH_ID; |
1440 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 1316 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1441 | priv->curbssparams.channel)) | 1317 | priv->channel)) |
1442 | priv->mesh_tlv = 0; | 1318 | priv->mesh_tlv = 0; |
1443 | } | 1319 | } |
1444 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { | 1320 | } else if (priv->mesh_fw_ver == MESH_FW_NEW) { |
@@ -1447,7 +1323,7 @@ int lbs_start_card(struct lbs_private *priv) | |||
1447 | */ | 1323 | */ |
1448 | priv->mesh_tlv = TLV_TYPE_MESH_ID; | 1324 | priv->mesh_tlv = TLV_TYPE_MESH_ID; |
1449 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 1325 | if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
1450 | priv->curbssparams.channel)) | 1326 | priv->channel)) |
1451 | priv->mesh_tlv = 0; | 1327 | priv->mesh_tlv = 0; |
1452 | } | 1328 | } |
1453 | if (priv->mesh_tlv) { | 1329 | if (priv->mesh_tlv) { |
@@ -1618,68 +1494,6 @@ static void lbs_remove_mesh(struct lbs_private *priv) | |||
1618 | lbs_deb_leave(LBS_DEB_MESH); | 1494 | lbs_deb_leave(LBS_DEB_MESH); |
1619 | } | 1495 | } |
1620 | 1496 | ||
1621 | /** | ||
1622 | * @brief This function finds the CFP in | ||
1623 | * region_cfp_table based on region and band parameter. | ||
1624 | * | ||
1625 | * @param region The region code | ||
1626 | * @param band The band | ||
1627 | * @param cfp_no A pointer to CFP number | ||
1628 | * @return A pointer to CFP | ||
1629 | */ | ||
1630 | struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) | ||
1631 | { | ||
1632 | int i, end; | ||
1633 | |||
1634 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1635 | |||
1636 | end = ARRAY_SIZE(region_cfp_table); | ||
1637 | |||
1638 | for (i = 0; i < end ; i++) { | ||
1639 | lbs_deb_main("region_cfp_table[i].region=%d\n", | ||
1640 | region_cfp_table[i].region); | ||
1641 | if (region_cfp_table[i].region == region) { | ||
1642 | *cfp_no = region_cfp_table[i].cfp_no_BG; | ||
1643 | lbs_deb_leave(LBS_DEB_MAIN); | ||
1644 | return region_cfp_table[i].cfp_BG; | ||
1645 | } | ||
1646 | } | ||
1647 | |||
1648 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); | ||
1649 | return NULL; | ||
1650 | } | ||
1651 | |||
1652 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | ||
1653 | { | ||
1654 | int ret = 0; | ||
1655 | int i = 0; | ||
1656 | |||
1657 | struct chan_freq_power *cfp; | ||
1658 | int cfp_no; | ||
1659 | |||
1660 | lbs_deb_enter(LBS_DEB_MAIN); | ||
1661 | |||
1662 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | ||
1663 | |||
1664 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
1665 | if (cfp != NULL) { | ||
1666 | priv->region_channel[i].nrcfp = cfp_no; | ||
1667 | priv->region_channel[i].CFP = cfp; | ||
1668 | } else { | ||
1669 | lbs_deb_main("wrong region code %#x in band B/G\n", | ||
1670 | region); | ||
1671 | ret = -1; | ||
1672 | goto out; | ||
1673 | } | ||
1674 | priv->region_channel[i].valid = 1; | ||
1675 | priv->region_channel[i].region = region; | ||
1676 | priv->region_channel[i].band = band; | ||
1677 | i++; | ||
1678 | out: | ||
1679 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
1680 | return ret; | ||
1681 | } | ||
1682 | |||
1683 | void lbs_queue_event(struct lbs_private *priv, u32 event) | 1497 | void lbs_queue_event(struct lbs_private *priv, u32 event) |
1684 | { | 1498 | { |
1685 | unsigned long flags; | 1499 | unsigned long flags; |
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c index 18fe29faf99b..871f914a75fc 100644 --- a/drivers/net/wireless/libertas/persistcfg.c +++ b/drivers/net/wireless/libertas/persistcfg.c | |||
@@ -187,9 +187,9 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, | |||
187 | if (ret) | 187 | if (ret) |
188 | return ret; | 188 | return ret; |
189 | 189 | ||
190 | if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) { | 190 | if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { |
191 | lbs_pr_err("inconsistent mesh ID length"); | 191 | lbs_pr_err("inconsistent mesh ID length"); |
192 | defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE; | 192 | defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; |
193 | } | 193 | } |
194 | 194 | ||
195 | /* SSID not null terminated: reserve room for \0 + \n */ | 195 | /* SSID not null terminated: reserve room for \0 + \n */ |
@@ -214,7 +214,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | |||
214 | int len; | 214 | int len; |
215 | int ret; | 215 | int ret; |
216 | 216 | ||
217 | if (count < 2 || count > IW_ESSID_MAX_SIZE + 1) | 217 | if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1) |
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | 219 | ||
220 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); | 220 | memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); |
@@ -233,7 +233,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, | |||
233 | /* SSID len */ | 233 | /* SSID len */ |
234 | ie->val.mesh_id_len = len; | 234 | ie->val.mesh_id_len = len; |
235 | /* IE len */ | 235 | /* IE len */ |
236 | ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len; | 236 | ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len; |
237 | 237 | ||
238 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, | 238 | ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, |
239 | CMD_TYPE_MESH_SET_MESH_IE); | 239 | CMD_TYPE_MESH_SET_MESH_IE); |
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 65f02cc6752f..9f18a19cc49d 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <linux/etherdevice.h> | 4 | #include <linux/etherdevice.h> |
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | 6 | ||
7 | #include "hostcmd.h" | 7 | #include "host.h" |
8 | #include "radiotap.h" | 8 | #include "radiotap.h" |
9 | #include "decl.h" | 9 | #include "decl.h" |
10 | #include "dev.h" | 10 | #include "dev.h" |
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 6c95af3023cc..c6a6c042b82f 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -12,18 +12,19 @@ | |||
12 | #include <net/lib80211.h> | 12 | #include <net/lib80211.h> |
13 | 13 | ||
14 | #include "host.h" | 14 | #include "host.h" |
15 | #include "decl.h" | ||
16 | #include "dev.h" | 15 | #include "dev.h" |
17 | #include "scan.h" | 16 | #include "scan.h" |
17 | #include "assoc.h" | ||
18 | #include "wext.h" | ||
18 | #include "cmd.h" | 19 | #include "cmd.h" |
19 | 20 | ||
20 | //! Approximate amount of data needed to pass a scan result back to iwlist | 21 | //! Approximate amount of data needed to pass a scan result back to iwlist |
21 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ | 22 | #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ |
22 | + IW_ESSID_MAX_SIZE \ | 23 | + IEEE80211_MAX_SSID_LEN \ |
23 | + IW_EV_UINT_LEN \ | 24 | + IW_EV_UINT_LEN \ |
24 | + IW_EV_FREQ_LEN \ | 25 | + IW_EV_FREQ_LEN \ |
25 | + IW_EV_QUAL_LEN \ | 26 | + IW_EV_QUAL_LEN \ |
26 | + IW_ESSID_MAX_SIZE \ | 27 | + IEEE80211_MAX_SSID_LEN \ |
27 | + IW_EV_PARAM_LEN \ | 28 | + IW_EV_PARAM_LEN \ |
28 | + 40) /* 40 for WPAIE */ | 29 | + 40) /* 40 for WPAIE */ |
29 | 30 | ||
@@ -121,6 +122,189 @@ static inline int is_same_network(struct bss_descriptor *src, | |||
121 | 122 | ||
122 | 123 | ||
123 | 124 | ||
125 | /*********************************************************************/ | ||
126 | /* */ | ||
127 | /* Region channel support */ | ||
128 | /* */ | ||
129 | /*********************************************************************/ | ||
130 | |||
131 | #define LBS_TX_PWR_DEFAULT 20 /*100mW */ | ||
132 | #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ | ||
133 | #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ | ||
134 | #define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ | ||
135 | #define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ | ||
136 | |||
137 | /* Format { channel, frequency (MHz), maxtxpower } */ | ||
138 | /* band: 'B/G', region: USA FCC/Canada IC */ | ||
139 | static struct chan_freq_power channel_freq_power_US_BG[] = { | ||
140 | {1, 2412, LBS_TX_PWR_US_DEFAULT}, | ||
141 | {2, 2417, LBS_TX_PWR_US_DEFAULT}, | ||
142 | {3, 2422, LBS_TX_PWR_US_DEFAULT}, | ||
143 | {4, 2427, LBS_TX_PWR_US_DEFAULT}, | ||
144 | {5, 2432, LBS_TX_PWR_US_DEFAULT}, | ||
145 | {6, 2437, LBS_TX_PWR_US_DEFAULT}, | ||
146 | {7, 2442, LBS_TX_PWR_US_DEFAULT}, | ||
147 | {8, 2447, LBS_TX_PWR_US_DEFAULT}, | ||
148 | {9, 2452, LBS_TX_PWR_US_DEFAULT}, | ||
149 | {10, 2457, LBS_TX_PWR_US_DEFAULT}, | ||
150 | {11, 2462, LBS_TX_PWR_US_DEFAULT} | ||
151 | }; | ||
152 | |||
153 | /* band: 'B/G', region: Europe ETSI */ | ||
154 | static struct chan_freq_power channel_freq_power_EU_BG[] = { | ||
155 | {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, | ||
156 | {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, | ||
157 | {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, | ||
158 | {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, | ||
159 | {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, | ||
160 | {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, | ||
161 | {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, | ||
162 | {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, | ||
163 | {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, | ||
164 | {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, | ||
165 | {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, | ||
166 | {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, | ||
167 | {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} | ||
168 | }; | ||
169 | |||
170 | /* band: 'B/G', region: Spain */ | ||
171 | static struct chan_freq_power channel_freq_power_SPN_BG[] = { | ||
172 | {10, 2457, LBS_TX_PWR_DEFAULT}, | ||
173 | {11, 2462, LBS_TX_PWR_DEFAULT} | ||
174 | }; | ||
175 | |||
176 | /* band: 'B/G', region: France */ | ||
177 | static struct chan_freq_power channel_freq_power_FR_BG[] = { | ||
178 | {10, 2457, LBS_TX_PWR_FR_DEFAULT}, | ||
179 | {11, 2462, LBS_TX_PWR_FR_DEFAULT}, | ||
180 | {12, 2467, LBS_TX_PWR_FR_DEFAULT}, | ||
181 | {13, 2472, LBS_TX_PWR_FR_DEFAULT} | ||
182 | }; | ||
183 | |||
184 | /* band: 'B/G', region: Japan */ | ||
185 | static struct chan_freq_power channel_freq_power_JPN_BG[] = { | ||
186 | {1, 2412, LBS_TX_PWR_JP_DEFAULT}, | ||
187 | {2, 2417, LBS_TX_PWR_JP_DEFAULT}, | ||
188 | {3, 2422, LBS_TX_PWR_JP_DEFAULT}, | ||
189 | {4, 2427, LBS_TX_PWR_JP_DEFAULT}, | ||
190 | {5, 2432, LBS_TX_PWR_JP_DEFAULT}, | ||
191 | {6, 2437, LBS_TX_PWR_JP_DEFAULT}, | ||
192 | {7, 2442, LBS_TX_PWR_JP_DEFAULT}, | ||
193 | {8, 2447, LBS_TX_PWR_JP_DEFAULT}, | ||
194 | {9, 2452, LBS_TX_PWR_JP_DEFAULT}, | ||
195 | {10, 2457, LBS_TX_PWR_JP_DEFAULT}, | ||
196 | {11, 2462, LBS_TX_PWR_JP_DEFAULT}, | ||
197 | {12, 2467, LBS_TX_PWR_JP_DEFAULT}, | ||
198 | {13, 2472, LBS_TX_PWR_JP_DEFAULT}, | ||
199 | {14, 2484, LBS_TX_PWR_JP_DEFAULT} | ||
200 | }; | ||
201 | |||
202 | /** | ||
203 | * the structure for channel, frequency and power | ||
204 | */ | ||
205 | struct region_cfp_table { | ||
206 | u8 region; | ||
207 | struct chan_freq_power *cfp_BG; | ||
208 | int cfp_no_BG; | ||
209 | }; | ||
210 | |||
211 | /** | ||
212 | * the structure for the mapping between region and CFP | ||
213 | */ | ||
214 | static struct region_cfp_table region_cfp_table[] = { | ||
215 | {0x10, /*US FCC */ | ||
216 | channel_freq_power_US_BG, | ||
217 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
218 | } | ||
219 | , | ||
220 | {0x20, /*CANADA IC */ | ||
221 | channel_freq_power_US_BG, | ||
222 | ARRAY_SIZE(channel_freq_power_US_BG), | ||
223 | } | ||
224 | , | ||
225 | {0x30, /*EU*/ channel_freq_power_EU_BG, | ||
226 | ARRAY_SIZE(channel_freq_power_EU_BG), | ||
227 | } | ||
228 | , | ||
229 | {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, | ||
230 | ARRAY_SIZE(channel_freq_power_SPN_BG), | ||
231 | } | ||
232 | , | ||
233 | {0x32, /*FRANCE*/ channel_freq_power_FR_BG, | ||
234 | ARRAY_SIZE(channel_freq_power_FR_BG), | ||
235 | } | ||
236 | , | ||
237 | {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, | ||
238 | ARRAY_SIZE(channel_freq_power_JPN_BG), | ||
239 | } | ||
240 | , | ||
241 | /*Add new region here */ | ||
242 | }; | ||
243 | |||
244 | /** | ||
245 | * @brief This function finds the CFP in | ||
246 | * region_cfp_table based on region and band parameter. | ||
247 | * | ||
248 | * @param region The region code | ||
249 | * @param band The band | ||
250 | * @param cfp_no A pointer to CFP number | ||
251 | * @return A pointer to CFP | ||
252 | */ | ||
253 | static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) | ||
254 | { | ||
255 | int i, end; | ||
256 | |||
257 | lbs_deb_enter(LBS_DEB_MAIN); | ||
258 | |||
259 | end = ARRAY_SIZE(region_cfp_table); | ||
260 | |||
261 | for (i = 0; i < end ; i++) { | ||
262 | lbs_deb_main("region_cfp_table[i].region=%d\n", | ||
263 | region_cfp_table[i].region); | ||
264 | if (region_cfp_table[i].region == region) { | ||
265 | *cfp_no = region_cfp_table[i].cfp_no_BG; | ||
266 | lbs_deb_leave(LBS_DEB_MAIN); | ||
267 | return region_cfp_table[i].cfp_BG; | ||
268 | } | ||
269 | } | ||
270 | |||
271 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); | ||
272 | return NULL; | ||
273 | } | ||
274 | |||
275 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) | ||
276 | { | ||
277 | int ret = 0; | ||
278 | int i = 0; | ||
279 | |||
280 | struct chan_freq_power *cfp; | ||
281 | int cfp_no; | ||
282 | |||
283 | lbs_deb_enter(LBS_DEB_MAIN); | ||
284 | |||
285 | memset(priv->region_channel, 0, sizeof(priv->region_channel)); | ||
286 | |||
287 | cfp = lbs_get_region_cfp_table(region, &cfp_no); | ||
288 | if (cfp != NULL) { | ||
289 | priv->region_channel[i].nrcfp = cfp_no; | ||
290 | priv->region_channel[i].CFP = cfp; | ||
291 | } else { | ||
292 | lbs_deb_main("wrong region code %#x in band B/G\n", | ||
293 | region); | ||
294 | ret = -1; | ||
295 | goto out; | ||
296 | } | ||
297 | priv->region_channel[i].valid = 1; | ||
298 | priv->region_channel[i].region = region; | ||
299 | priv->region_channel[i].band = band; | ||
300 | i++; | ||
301 | out: | ||
302 | lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | |||
307 | |||
124 | 308 | ||
125 | /*********************************************************************/ | 309 | /*********************************************************************/ |
126 | /* */ | 310 | /* */ |
@@ -161,31 +345,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, | |||
161 | scantype = CMD_SCAN_TYPE_ACTIVE; | 345 | scantype = CMD_SCAN_TYPE_ACTIVE; |
162 | 346 | ||
163 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { | 347 | for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { |
164 | if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) | 348 | if (!priv->region_channel[rgnidx].valid) |
165 | && (priv->mesh_connect_status != LBS_CONNECTED)) { | 349 | continue; |
166 | /* Scan all the supported chan for the first scan */ | 350 | scanregion = &priv->region_channel[rgnidx]; |
167 | if (!priv->universal_channel[rgnidx].valid) | ||
168 | continue; | ||
169 | scanregion = &priv->universal_channel[rgnidx]; | ||
170 | |||
171 | /* clear the parsed_region_chan for the first scan */ | ||
172 | memset(&priv->parsed_region_chan, 0x00, | ||
173 | sizeof(priv->parsed_region_chan)); | ||
174 | } else { | ||
175 | if (!priv->region_channel[rgnidx].valid) | ||
176 | continue; | ||
177 | scanregion = &priv->region_channel[rgnidx]; | ||
178 | } | ||
179 | 351 | ||
180 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { | 352 | for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { |
181 | struct chanscanparamset *chan = &scanchanlist[chanidx]; | 353 | struct chanscanparamset *chan = &scanchanlist[chanidx]; |
182 | 354 | ||
183 | cfp = scanregion->CFP + nextchan; | 355 | cfp = scanregion->CFP + nextchan; |
184 | 356 | ||
185 | if (priv->enable11d) | ||
186 | scantype = lbs_get_scan_type_11d(cfp->channel, | ||
187 | &priv->parsed_region_chan); | ||
188 | |||
189 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) | 357 | if (scanregion->band == BAND_B || scanregion->band == BAND_G) |
190 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; | 358 | chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; |
191 | 359 | ||
@@ -519,7 +687,6 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
519 | struct ieee_ie_cf_param_set *cf; | 687 | struct ieee_ie_cf_param_set *cf; |
520 | struct ieee_ie_ibss_param_set *ibss; | 688 | struct ieee_ie_ibss_param_set *ibss; |
521 | DECLARE_SSID_BUF(ssid); | 689 | DECLARE_SSID_BUF(ssid); |
522 | struct ieee_ie_country_info_set *pcountryinfo; | ||
523 | uint8_t *pos, *end, *p; | 690 | uint8_t *pos, *end, *p; |
524 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; | 691 | uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; |
525 | uint16_t beaconsize = 0; | 692 | uint16_t beaconsize = 0; |
@@ -642,26 +809,6 @@ static int lbs_process_bss(struct bss_descriptor *bss, | |||
642 | lbs_deb_scan("got IBSS IE\n"); | 809 | lbs_deb_scan("got IBSS IE\n"); |
643 | break; | 810 | break; |
644 | 811 | ||
645 | case WLAN_EID_COUNTRY: | ||
646 | pcountryinfo = (struct ieee_ie_country_info_set *) pos; | ||
647 | lbs_deb_scan("got COUNTRY IE\n"); | ||
648 | if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode) | ||
649 | || pcountryinfo->header.len > 254) { | ||
650 | lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n", | ||
651 | __func__, | ||
652 | pcountryinfo->header.len, | ||
653 | sizeof(pcountryinfo->countrycode)); | ||
654 | ret = -1; | ||
655 | goto done; | ||
656 | } | ||
657 | |||
658 | memcpy(&bss->countryinfo, pcountryinfo, | ||
659 | pcountryinfo->header.len + 2); | ||
660 | lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", | ||
661 | (uint8_t *) pcountryinfo, | ||
662 | (int) (pcountryinfo->header.len + 2)); | ||
663 | break; | ||
664 | |||
665 | case WLAN_EID_EXT_SUPP_RATES: | 812 | case WLAN_EID_EXT_SUPP_RATES: |
666 | /* only process extended supported rate if data rate is | 813 | /* only process extended supported rate if data rate is |
667 | * already found. Data rate IE should come before | 814 | * already found. Data rate IE should come before |
@@ -812,7 +959,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, | |||
812 | /* SSID */ | 959 | /* SSID */ |
813 | iwe.cmd = SIOCGIWESSID; | 960 | iwe.cmd = SIOCGIWESSID; |
814 | iwe.u.data.flags = 1; | 961 | iwe.u.data.flags = 1; |
815 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); | 962 | iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN); |
816 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); | 963 | start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); |
817 | 964 | ||
818 | /* Mode */ | 965 | /* Mode */ |
@@ -1022,9 +1169,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1022 | return -EAGAIN; | 1169 | return -EAGAIN; |
1023 | 1170 | ||
1024 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ | 1171 | /* Update RSSI if current BSS is a locally created ad-hoc BSS */ |
1025 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) | 1172 | if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { |
1026 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 1173 | err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
1027 | CMD_OPTION_WAITFORRSP, 0, NULL); | 1174 | CMD_OPTION_WAITFORRSP, 0, NULL); |
1175 | if (err) | ||
1176 | goto out; | ||
1177 | } | ||
1028 | 1178 | ||
1029 | mutex_lock(&priv->lock); | 1179 | mutex_lock(&priv->lock); |
1030 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { | 1180 | list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { |
@@ -1058,7 +1208,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, | |||
1058 | 1208 | ||
1059 | dwrq->length = (ev - extra); | 1209 | dwrq->length = (ev - extra); |
1060 | dwrq->flags = 0; | 1210 | dwrq->flags = 0; |
1061 | 1211 | out: | |
1062 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); | 1212 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); |
1063 | return err; | 1213 | return err; |
1064 | } | 1214 | } |
@@ -1141,11 +1291,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, | |||
1141 | /* The size of the TLV buffer is equal to the entire command response | 1291 | /* The size of the TLV buffer is equal to the entire command response |
1142 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the | 1292 | * size (scanrespsize) minus the fixed fields (sizeof()'s), the |
1143 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command | 1293 | * BSS Descriptions (bssdescriptsize as bytesLef) and the command |
1144 | * response header (S_DS_GEN) | 1294 | * response header (sizeof(struct cmd_header)) |
1145 | */ | 1295 | */ |
1146 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) | 1296 | tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) |
1147 | + sizeof(scanresp->nr_sets) | 1297 | + sizeof(scanresp->nr_sets) |
1148 | + S_DS_GEN); | 1298 | + sizeof(struct cmd_header)); |
1149 | 1299 | ||
1150 | /* | 1300 | /* |
1151 | * Process each scan response returned (scanresp->nr_sets). Save | 1301 | * Process each scan response returned (scanresp->nr_sets). Save |
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index fab7d5d097fc..8fb1706d7526 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h | |||
@@ -9,8 +9,36 @@ | |||
9 | 9 | ||
10 | #include <net/iw_handler.h> | 10 | #include <net/iw_handler.h> |
11 | 11 | ||
12 | struct lbs_private; | ||
13 | |||
12 | #define MAX_NETWORK_COUNT 128 | 14 | #define MAX_NETWORK_COUNT 128 |
13 | 15 | ||
16 | /** Chan-freq-TxPower mapping table*/ | ||
17 | struct chan_freq_power { | ||
18 | /** channel Number */ | ||
19 | u16 channel; | ||
20 | /** frequency of this channel */ | ||
21 | u32 freq; | ||
22 | /** Max allowed Tx power level */ | ||
23 | u16 maxtxpower; | ||
24 | /** TRUE:channel unsupported; FLASE:supported*/ | ||
25 | u8 unsupported; | ||
26 | }; | ||
27 | |||
28 | /** region-band mapping table*/ | ||
29 | struct region_channel { | ||
30 | /** TRUE if this entry is valid */ | ||
31 | u8 valid; | ||
32 | /** region code for US, Japan ... */ | ||
33 | u8 region; | ||
34 | /** band B/G/A, used for BAND_CONFIG cmd */ | ||
35 | u8 band; | ||
36 | /** Actual No. of elements in the array below */ | ||
37 | u8 nrcfp; | ||
38 | /** chan-freq-txpower mapping table*/ | ||
39 | struct chan_freq_power *CFP; | ||
40 | }; | ||
41 | |||
14 | /** | 42 | /** |
15 | * @brief Maximum number of channels that can be sent in a setuserscan ioctl | 43 | * @brief Maximum number of channels that can be sent in a setuserscan ioctl |
16 | */ | 44 | */ |
@@ -18,6 +46,8 @@ | |||
18 | 46 | ||
19 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); | 47 | int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); |
20 | 48 | ||
49 | int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); | ||
50 | |||
21 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | 51 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, |
22 | u8 ssid_len); | 52 | u8 ssid_len); |
23 | 53 | ||
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 4c018f7a0a8d..5d7c011fe296 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <linux/netdevice.h> | 4 | #include <linux/netdevice.h> |
5 | #include <linux/etherdevice.h> | 5 | #include <linux/etherdevice.h> |
6 | 6 | ||
7 | #include "hostcmd.h" | 7 | #include "host.h" |
8 | #include "radiotap.h" | 8 | #include "radiotap.h" |
9 | #include "decl.h" | 9 | #include "decl.h" |
10 | #include "defs.h" | 10 | #include "defs.h" |
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index 99905df65b25..3e72c86ceca8 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h | |||
@@ -5,8 +5,8 @@ | |||
5 | #define _LBS_TYPES_H_ | 5 | #define _LBS_TYPES_H_ |
6 | 6 | ||
7 | #include <linux/if_ether.h> | 7 | #include <linux/if_ether.h> |
8 | #include <linux/ieee80211.h> | ||
8 | #include <asm/byteorder.h> | 9 | #include <asm/byteorder.h> |
9 | #include <linux/wireless.h> | ||
10 | 10 | ||
11 | struct ieee_ie_header { | 11 | struct ieee_ie_header { |
12 | u8 id; | 12 | u8 id; |
@@ -247,7 +247,7 @@ struct mrvl_meshie_val { | |||
247 | uint8_t active_metric_id; | 247 | uint8_t active_metric_id; |
248 | uint8_t mesh_capability; | 248 | uint8_t mesh_capability; |
249 | uint8_t mesh_id_len; | 249 | uint8_t mesh_id_len; |
250 | uint8_t mesh_id[IW_ESSID_MAX_SIZE]; | 250 | uint8_t mesh_id[IEEE80211_MAX_SSID_LEN]; |
251 | } __attribute__ ((packed)); | 251 | } __attribute__ ((packed)); |
252 | 252 | ||
253 | struct mrvl_meshie { | 253 | struct mrvl_meshie { |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 69dd19bf9558..a8eb9e1fcf36 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -45,6 +45,64 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) | |||
45 | priv->pending_assoc_req = NULL; | 45 | priv->pending_assoc_req = NULL; |
46 | } | 46 | } |
47 | 47 | ||
48 | void lbs_send_disconnect_notification(struct lbs_private *priv) | ||
49 | { | ||
50 | union iwreq_data wrqu; | ||
51 | |||
52 | memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); | ||
53 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
54 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
55 | } | ||
56 | |||
57 | static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
58 | { | ||
59 | union iwreq_data iwrq; | ||
60 | u8 buf[50]; | ||
61 | |||
62 | lbs_deb_enter(LBS_DEB_WEXT); | ||
63 | |||
64 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
65 | memset(buf, 0, sizeof(buf)); | ||
66 | |||
67 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
68 | |||
69 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
70 | |||
71 | /* Send Event to upper layer */ | ||
72 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
73 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
74 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
75 | |||
76 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
77 | |||
78 | lbs_deb_leave(LBS_DEB_WEXT); | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * @brief This function handles MIC failure event. | ||
83 | * | ||
84 | * @param priv A pointer to struct lbs_private structure | ||
85 | * @para event the event id | ||
86 | * @return n/a | ||
87 | */ | ||
88 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event) | ||
89 | { | ||
90 | char buf[50]; | ||
91 | |||
92 | lbs_deb_enter(LBS_DEB_CMD); | ||
93 | memset(buf, 0, sizeof(buf)); | ||
94 | |||
95 | sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); | ||
96 | |||
97 | if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) | ||
98 | strcat(buf, "unicast "); | ||
99 | else | ||
100 | strcat(buf, "multicast "); | ||
101 | |||
102 | lbs_send_iwevcustom_event(priv, buf); | ||
103 | lbs_deb_leave(LBS_DEB_CMD); | ||
104 | } | ||
105 | |||
48 | /** | 106 | /** |
49 | * @brief Find the channel frequency power info with specific channel | 107 | * @brief Find the channel frequency power info with specific channel |
50 | * | 108 | * |
@@ -65,8 +123,6 @@ struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | |||
65 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | 123 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
66 | rc = &priv->region_channel[j]; | 124 | rc = &priv->region_channel[j]; |
67 | 125 | ||
68 | if (priv->enable11d) | ||
69 | rc = &priv->universal_channel[j]; | ||
70 | if (!rc->valid || !rc->CFP) | 126 | if (!rc->valid || !rc->CFP) |
71 | continue; | 127 | continue; |
72 | if (rc->band != band) | 128 | if (rc->band != band) |
@@ -106,8 +162,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq( | |||
106 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { | 162 | for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
107 | rc = &priv->region_channel[j]; | 163 | rc = &priv->region_channel[j]; |
108 | 164 | ||
109 | if (priv->enable11d) | ||
110 | rc = &priv->universal_channel[j]; | ||
111 | if (!rc->valid || !rc->CFP) | 165 | if (!rc->valid || !rc->CFP) |
112 | continue; | 166 | continue; |
113 | if (rc->band != band) | 167 | if (rc->band != band) |
@@ -168,12 +222,12 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, | |||
168 | lbs_deb_enter(LBS_DEB_WEXT); | 222 | lbs_deb_enter(LBS_DEB_WEXT); |
169 | 223 | ||
170 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, | 224 | cfp = lbs_find_cfp_by_band_and_channel(priv, 0, |
171 | priv->curbssparams.channel); | 225 | priv->channel); |
172 | 226 | ||
173 | if (!cfp) { | 227 | if (!cfp) { |
174 | if (priv->curbssparams.channel) | 228 | if (priv->channel) |
175 | lbs_deb_wext("invalid channel %d\n", | 229 | lbs_deb_wext("invalid channel %d\n", |
176 | priv->curbssparams.channel); | 230 | priv->channel); |
177 | return -EINVAL; | 231 | return -EINVAL; |
178 | } | 232 | } |
179 | 233 | ||
@@ -546,8 +600,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
546 | struct chan_freq_power *cfp; | 600 | struct chan_freq_power *cfp; |
547 | u8 rates[MAX_RATES + 1]; | 601 | u8 rates[MAX_RATES + 1]; |
548 | 602 | ||
549 | u8 flag = 0; | ||
550 | |||
551 | lbs_deb_enter(LBS_DEB_WEXT); | 603 | lbs_deb_enter(LBS_DEB_WEXT); |
552 | 604 | ||
553 | dwrq->length = sizeof(struct iw_range); | 605 | dwrq->length = sizeof(struct iw_range); |
@@ -569,52 +621,21 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
569 | 621 | ||
570 | range->scan_capa = IW_SCAN_CAPA_ESSID; | 622 | range->scan_capa = IW_SCAN_CAPA_ESSID; |
571 | 623 | ||
572 | if (priv->enable11d && | 624 | for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) |
573 | (priv->connect_status == LBS_CONNECTED || | 625 | && (j < ARRAY_SIZE(priv->region_channel)); j++) { |
574 | priv->mesh_connect_status == LBS_CONNECTED)) { | 626 | cfp = priv->region_channel[j].CFP; |
575 | u8 chan_no; | ||
576 | u8 band; | ||
577 | |||
578 | struct parsed_region_chan_11d *parsed_region_chan = | ||
579 | &priv->parsed_region_chan; | ||
580 | |||
581 | if (parsed_region_chan == NULL) { | ||
582 | lbs_deb_wext("11d: parsed_region_chan is NULL\n"); | ||
583 | goto out; | ||
584 | } | ||
585 | band = parsed_region_chan->band; | ||
586 | lbs_deb_wext("band %d, nr_char %d\n", band, | ||
587 | parsed_region_chan->nr_chan); | ||
588 | |||
589 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | 627 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) |
590 | && (i < parsed_region_chan->nr_chan); i++) { | 628 | && priv->region_channel[j].valid |
591 | chan_no = parsed_region_chan->chanpwr[i].chan; | 629 | && cfp |
592 | lbs_deb_wext("chan_no %d\n", chan_no); | 630 | && (i < priv->region_channel[j].nrcfp); i++) { |
593 | range->freq[range->num_frequency].i = (long)chan_no; | 631 | range->freq[range->num_frequency].i = |
632 | (long)cfp->channel; | ||
594 | range->freq[range->num_frequency].m = | 633 | range->freq[range->num_frequency].m = |
595 | (long)lbs_chan_2_freq(chan_no) * 100000; | 634 | (long)cfp->freq * 100000; |
596 | range->freq[range->num_frequency].e = 1; | 635 | range->freq[range->num_frequency].e = 1; |
636 | cfp++; | ||
597 | range->num_frequency++; | 637 | range->num_frequency++; |
598 | } | 638 | } |
599 | flag = 1; | ||
600 | } | ||
601 | if (!flag) { | ||
602 | for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
603 | && (j < ARRAY_SIZE(priv->region_channel)); j++) { | ||
604 | cfp = priv->region_channel[j].CFP; | ||
605 | for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) | ||
606 | && priv->region_channel[j].valid | ||
607 | && cfp | ||
608 | && (i < priv->region_channel[j].nrcfp); i++) { | ||
609 | range->freq[range->num_frequency].i = | ||
610 | (long)cfp->channel; | ||
611 | range->freq[range->num_frequency].m = | ||
612 | (long)cfp->freq * 100000; | ||
613 | range->freq[range->num_frequency].e = 1; | ||
614 | cfp++; | ||
615 | range->num_frequency++; | ||
616 | } | ||
617 | } | ||
618 | } | 639 | } |
619 | 640 | ||
620 | lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", | 641 | lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", |
@@ -699,7 +720,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, | |||
699 | | IW_ENC_CAPA_CIPHER_CCMP; | 720 | | IW_ENC_CAPA_CIPHER_CCMP; |
700 | } | 721 | } |
701 | 722 | ||
702 | out: | ||
703 | lbs_deb_leave(LBS_DEB_WEXT); | 723 | lbs_deb_leave(LBS_DEB_WEXT); |
704 | return 0; | 724 | return 0; |
705 | } | 725 | } |
@@ -832,7 +852,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
832 | u32 rssi_qual; | 852 | u32 rssi_qual; |
833 | u32 tx_qual; | 853 | u32 tx_qual; |
834 | u32 quality = 0; | 854 | u32 quality = 0; |
835 | int stats_valid = 0; | 855 | int ret, stats_valid = 0; |
836 | u8 rssi; | 856 | u8 rssi; |
837 | u32 tx_retries; | 857 | u32 tx_retries; |
838 | struct cmd_ds_802_11_get_log log; | 858 | struct cmd_ds_802_11_get_log log; |
@@ -881,7 +901,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
881 | 901 | ||
882 | memset(&log, 0, sizeof(log)); | 902 | memset(&log, 0, sizeof(log)); |
883 | log.hdr.size = cpu_to_le16(sizeof(log)); | 903 | log.hdr.size = cpu_to_le16(sizeof(log)); |
884 | lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); | 904 | ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); |
905 | if (ret) | ||
906 | goto out; | ||
885 | 907 | ||
886 | tx_retries = le32_to_cpu(log.retry); | 908 | tx_retries = le32_to_cpu(log.retry); |
887 | 909 | ||
@@ -909,8 +931,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) | |||
909 | stats_valid = 1; | 931 | stats_valid = 1; |
910 | 932 | ||
911 | /* update stats asynchronously for future calls */ | 933 | /* update stats asynchronously for future calls */ |
912 | lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, | 934 | ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, |
913 | 0, 0, NULL); | 935 | 0, 0, NULL); |
936 | if (ret) | ||
937 | lbs_pr_err("RSSI command failed\n"); | ||
914 | out: | 938 | out: |
915 | if (!stats_valid) { | 939 | if (!stats_valid) { |
916 | priv->wstats.miss.beacon = 0; | 940 | priv->wstats.miss.beacon = 0; |
@@ -1020,7 +1044,7 @@ static int lbs_mesh_set_freq(struct net_device *dev, | |||
1020 | goto out; | 1044 | goto out; |
1021 | } | 1045 | } |
1022 | 1046 | ||
1023 | if (fwrq->m != priv->curbssparams.channel) { | 1047 | if (fwrq->m != priv->channel) { |
1024 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); | 1048 | lbs_deb_wext("mesh channel change forces eth disconnect\n"); |
1025 | if (priv->mode == IW_MODE_INFRA) | 1049 | if (priv->mode == IW_MODE_INFRA) |
1026 | lbs_cmd_80211_deauthenticate(priv, | 1050 | lbs_cmd_80211_deauthenticate(priv, |
@@ -2023,7 +2047,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | |||
2023 | { | 2047 | { |
2024 | struct lbs_private *priv = dev->ml_priv; | 2048 | struct lbs_private *priv = dev->ml_priv; |
2025 | int ret = 0; | 2049 | int ret = 0; |
2026 | u8 ssid[IW_ESSID_MAX_SIZE]; | 2050 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
2027 | u8 ssid_len = 0; | 2051 | u8 ssid_len = 0; |
2028 | struct assoc_request * assoc_req; | 2052 | struct assoc_request * assoc_req; |
2029 | int in_ssid_len = dwrq->length; | 2053 | int in_ssid_len = dwrq->length; |
@@ -2037,7 +2061,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, | |||
2037 | } | 2061 | } |
2038 | 2062 | ||
2039 | /* Check the size of the string */ | 2063 | /* Check the size of the string */ |
2040 | if (in_ssid_len > IW_ESSID_MAX_SIZE) { | 2064 | if (in_ssid_len > IEEE80211_MAX_SSID_LEN) { |
2041 | ret = -E2BIG; | 2065 | ret = -E2BIG; |
2042 | goto out; | 2066 | goto out; |
2043 | } | 2067 | } |
@@ -2068,7 +2092,7 @@ out: | |||
2068 | ret = -ENOMEM; | 2092 | ret = -ENOMEM; |
2069 | } else { | 2093 | } else { |
2070 | /* Copy the SSID to the association request */ | 2094 | /* Copy the SSID to the association request */ |
2071 | memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE); | 2095 | memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN); |
2072 | assoc_req->ssid_len = ssid_len; | 2096 | assoc_req->ssid_len = ssid_len; |
2073 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); | 2097 | set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); |
2074 | lbs_postpone_association_work(priv); | 2098 | lbs_postpone_association_work(priv); |
@@ -2119,7 +2143,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2119 | } | 2143 | } |
2120 | 2144 | ||
2121 | /* Check the size of the string */ | 2145 | /* Check the size of the string */ |
2122 | if (dwrq->length > IW_ESSID_MAX_SIZE) { | 2146 | if (dwrq->length > IEEE80211_MAX_SSID_LEN) { |
2123 | ret = -E2BIG; | 2147 | ret = -E2BIG; |
2124 | goto out; | 2148 | goto out; |
2125 | } | 2149 | } |
@@ -2134,7 +2158,7 @@ static int lbs_mesh_set_essid(struct net_device *dev, | |||
2134 | } | 2158 | } |
2135 | 2159 | ||
2136 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, | 2160 | lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, |
2137 | priv->curbssparams.channel); | 2161 | priv->channel); |
2138 | out: | 2162 | out: |
2139 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); | 2163 | lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); |
2140 | return ret; | 2164 | return ret; |
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index 4c08db497606..7863baf7d234 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h | |||
@@ -4,7 +4,15 @@ | |||
4 | #ifndef _LBS_WEXT_H_ | 4 | #ifndef _LBS_WEXT_H_ |
5 | #define _LBS_WEXT_H_ | 5 | #define _LBS_WEXT_H_ |
6 | 6 | ||
7 | void lbs_send_disconnect_notification(struct lbs_private *priv); | ||
8 | void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); | ||
9 | |||
7 | extern struct iw_handler_def lbs_handler_def; | 10 | extern struct iw_handler_def lbs_handler_def; |
8 | extern struct iw_handler_def mesh_handler_def; | 11 | extern struct iw_handler_def mesh_handler_def; |
9 | 12 | ||
13 | struct chan_freq_power *lbs_find_cfp_by_band_and_channel( | ||
14 | struct lbs_private *priv, | ||
15 | u8 band, | ||
16 | u16 channel); | ||
17 | |||
10 | #endif | 18 | #endif |
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 359652d35e63..404830f47ab2 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c | |||
@@ -60,8 +60,15 @@ static inline fwtype_t determine_firmware_type(struct comp_id *nic_id) | |||
60 | /* Set priv->firmware type, determine firmware properties | 60 | /* Set priv->firmware type, determine firmware properties |
61 | * This function can be called before we have registerred with netdev, | 61 | * This function can be called before we have registerred with netdev, |
62 | * so all errors go out with dev_* rather than printk | 62 | * so all errors go out with dev_* rather than printk |
63 | * | ||
64 | * If non-NULL stores a firmware description in fw_name. | ||
65 | * If non-NULL stores a HW version in hw_ver | ||
66 | * | ||
67 | * These are output via generic cfg80211 ethtool support. | ||
63 | */ | 68 | */ |
64 | int determine_fw_capabilities(struct orinoco_private *priv) | 69 | int determine_fw_capabilities(struct orinoco_private *priv, |
70 | char *fw_name, size_t fw_name_len, | ||
71 | u32 *hw_ver) | ||
65 | { | 72 | { |
66 | struct device *dev = priv->dev; | 73 | struct device *dev = priv->dev; |
67 | hermes_t *hw = &priv->hw; | 74 | hermes_t *hw = &priv->hw; |
@@ -85,6 +92,12 @@ int determine_fw_capabilities(struct orinoco_private *priv) | |||
85 | dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n", | 92 | dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n", |
86 | nic_id.id, nic_id.variant, nic_id.major, nic_id.minor); | 93 | nic_id.id, nic_id.variant, nic_id.major, nic_id.minor); |
87 | 94 | ||
95 | if (hw_ver) | ||
96 | *hw_ver = (((nic_id.id & 0xff) << 24) | | ||
97 | ((nic_id.variant & 0xff) << 16) | | ||
98 | ((nic_id.major & 0xff) << 8) | | ||
99 | (nic_id.minor & 0xff)); | ||
100 | |||
88 | priv->firmware_type = determine_firmware_type(&nic_id); | 101 | priv->firmware_type = determine_firmware_type(&nic_id); |
89 | 102 | ||
90 | /* Get the firmware version */ | 103 | /* Get the firmware version */ |
@@ -135,8 +148,9 @@ int determine_fw_capabilities(struct orinoco_private *priv) | |||
135 | case FIRMWARE_TYPE_AGERE: | 148 | case FIRMWARE_TYPE_AGERE: |
136 | /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, | 149 | /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, |
137 | ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */ | 150 | ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */ |
138 | snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, | 151 | if (fw_name) |
139 | "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor); | 152 | snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d", |
153 | sta_id.major, sta_id.minor); | ||
140 | 154 | ||
141 | firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor; | 155 | firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor; |
142 | 156 | ||
@@ -185,8 +199,8 @@ int determine_fw_capabilities(struct orinoco_private *priv) | |||
185 | tmp[SYMBOL_MAX_VER_LEN] = '\0'; | 199 | tmp[SYMBOL_MAX_VER_LEN] = '\0'; |
186 | } | 200 | } |
187 | 201 | ||
188 | snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, | 202 | if (fw_name) |
189 | "Symbol %s", tmp); | 203 | snprintf(fw_name, fw_name_len, "Symbol %s", tmp); |
190 | 204 | ||
191 | priv->has_ibss = (firmver >= 0x20000); | 205 | priv->has_ibss = (firmver >= 0x20000); |
192 | priv->has_wep = (firmver >= 0x15012); | 206 | priv->has_wep = (firmver >= 0x15012); |
@@ -224,9 +238,9 @@ int determine_fw_capabilities(struct orinoco_private *priv) | |||
224 | * different and less well tested */ | 238 | * different and less well tested */ |
225 | /* D-Link MAC : 00:40:05:* */ | 239 | /* D-Link MAC : 00:40:05:* */ |
226 | /* Addtron MAC : 00:90:D1:* */ | 240 | /* Addtron MAC : 00:90:D1:* */ |
227 | snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, | 241 | if (fw_name) |
228 | "Intersil %d.%d.%d", sta_id.major, sta_id.minor, | 242 | snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d", |
229 | sta_id.variant); | 243 | sta_id.major, sta_id.minor, sta_id.variant); |
230 | 244 | ||
231 | firmver = ((unsigned long)sta_id.major << 16) | | 245 | firmver = ((unsigned long)sta_id.major << 16) | |
232 | ((unsigned long)sta_id.minor << 8) | sta_id.variant; | 246 | ((unsigned long)sta_id.minor << 8) | sta_id.variant; |
@@ -245,7 +259,8 @@ int determine_fw_capabilities(struct orinoco_private *priv) | |||
245 | } | 259 | } |
246 | break; | 260 | break; |
247 | } | 261 | } |
248 | dev_info(dev, "Firmware determined as %s\n", priv->fw_name); | 262 | if (fw_name) |
263 | dev_info(dev, "Firmware determined as %s\n", fw_name); | ||
249 | 264 | ||
250 | return 0; | 265 | return 0; |
251 | } | 266 | } |
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h index 8df6e8752be6..e2f7fdc4d45a 100644 --- a/drivers/net/wireless/orinoco/hw.h +++ b/drivers/net/wireless/orinoco/hw.h | |||
@@ -24,7 +24,8 @@ | |||
24 | struct orinoco_private; | 24 | struct orinoco_private; |
25 | struct dev_addr_list; | 25 | struct dev_addr_list; |
26 | 26 | ||
27 | int determine_fw_capabilities(struct orinoco_private *priv); | 27 | int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name, |
28 | size_t fw_name_len, u32 *hw_ver); | ||
28 | int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr); | 29 | int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr); |
29 | int orinoco_hw_allocate_fid(struct orinoco_private *priv); | 30 | int orinoco_hw_allocate_fid(struct orinoco_private *priv); |
30 | int orinoco_get_bitratemode(int bitrate, int automatic); | 31 | int orinoco_get_bitratemode(int bitrate, int automatic); |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 5fdc59c594f2..753a1804eee7 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
@@ -83,7 +83,6 @@ | |||
83 | #include <linux/device.h> | 83 | #include <linux/device.h> |
84 | #include <linux/netdevice.h> | 84 | #include <linux/netdevice.h> |
85 | #include <linux/etherdevice.h> | 85 | #include <linux/etherdevice.h> |
86 | #include <linux/ethtool.h> | ||
87 | #include <linux/suspend.h> | 86 | #include <linux/suspend.h> |
88 | #include <linux/if_arp.h> | 87 | #include <linux/if_arp.h> |
89 | #include <linux/wireless.h> | 88 | #include <linux/wireless.h> |
@@ -162,8 +161,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | |||
162 | | HERMES_EV_WTERR | HERMES_EV_INFO \ | 161 | | HERMES_EV_WTERR | HERMES_EV_INFO \ |
163 | | HERMES_EV_INFDROP) | 162 | | HERMES_EV_INFDROP) |
164 | 163 | ||
165 | static const struct ethtool_ops orinoco_ethtool_ops; | ||
166 | |||
167 | /********************************************************************/ | 164 | /********************************************************************/ |
168 | /* Data types */ | 165 | /* Data types */ |
169 | /********************************************************************/ | 166 | /********************************************************************/ |
@@ -1994,7 +1991,9 @@ int orinoco_init(struct orinoco_private *priv) | |||
1994 | goto out; | 1991 | goto out; |
1995 | } | 1992 | } |
1996 | 1993 | ||
1997 | err = determine_fw_capabilities(priv); | 1994 | err = determine_fw_capabilities(priv, wiphy->fw_version, |
1995 | sizeof(wiphy->fw_version), | ||
1996 | &wiphy->hw_version); | ||
1998 | if (err != 0) { | 1997 | if (err != 0) { |
1999 | dev_err(dev, "Incompatible firmware, aborting\n"); | 1998 | dev_err(dev, "Incompatible firmware, aborting\n"); |
2000 | goto out; | 1999 | goto out; |
@@ -2010,7 +2009,9 @@ int orinoco_init(struct orinoco_private *priv) | |||
2010 | priv->do_fw_download = 0; | 2009 | priv->do_fw_download = 0; |
2011 | 2010 | ||
2012 | /* Check firmware version again */ | 2011 | /* Check firmware version again */ |
2013 | err = determine_fw_capabilities(priv); | 2012 | err = determine_fw_capabilities(priv, wiphy->fw_version, |
2013 | sizeof(wiphy->fw_version), | ||
2014 | &wiphy->hw_version); | ||
2014 | if (err != 0) { | 2015 | if (err != 0) { |
2015 | dev_err(dev, "Incompatible firmware, aborting\n"); | 2016 | dev_err(dev, "Incompatible firmware, aborting\n"); |
2016 | goto out; | 2017 | goto out; |
@@ -2212,7 +2213,6 @@ int orinoco_if_add(struct orinoco_private *priv, | |||
2212 | dev->ieee80211_ptr = wdev; | 2213 | dev->ieee80211_ptr = wdev; |
2213 | dev->netdev_ops = &orinoco_netdev_ops; | 2214 | dev->netdev_ops = &orinoco_netdev_ops; |
2214 | dev->watchdog_timeo = HZ; /* 1 second timeout */ | 2215 | dev->watchdog_timeo = HZ; /* 1 second timeout */ |
2215 | dev->ethtool_ops = &orinoco_ethtool_ops; | ||
2216 | dev->wireless_handlers = &orinoco_handler_def; | 2216 | dev->wireless_handlers = &orinoco_handler_def; |
2217 | #ifdef WIRELESS_SPY | 2217 | #ifdef WIRELESS_SPY |
2218 | dev->wireless_data = &priv->wireless_data; | 2218 | dev->wireless_data = &priv->wireless_data; |
@@ -2349,27 +2349,6 @@ void orinoco_down(struct orinoco_private *priv) | |||
2349 | } | 2349 | } |
2350 | EXPORT_SYMBOL(orinoco_down); | 2350 | EXPORT_SYMBOL(orinoco_down); |
2351 | 2351 | ||
2352 | static void orinoco_get_drvinfo(struct net_device *dev, | ||
2353 | struct ethtool_drvinfo *info) | ||
2354 | { | ||
2355 | struct orinoco_private *priv = ndev_priv(dev); | ||
2356 | |||
2357 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); | ||
2358 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); | ||
2359 | strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); | ||
2360 | if (dev->dev.parent) | ||
2361 | strncpy(info->bus_info, dev_name(dev->dev.parent), | ||
2362 | sizeof(info->bus_info) - 1); | ||
2363 | else | ||
2364 | snprintf(info->bus_info, sizeof(info->bus_info) - 1, | ||
2365 | "PCMCIA %p", priv->hw.iobase); | ||
2366 | } | ||
2367 | |||
2368 | static const struct ethtool_ops orinoco_ethtool_ops = { | ||
2369 | .get_drvinfo = orinoco_get_drvinfo, | ||
2370 | .get_link = ethtool_op_get_link, | ||
2371 | }; | ||
2372 | |||
2373 | /********************************************************************/ | 2352 | /********************************************************************/ |
2374 | /* Module initialization */ | 2353 | /* Module initialization */ |
2375 | /********************************************************************/ | 2354 | /********************************************************************/ |
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 9ac6f1dda4b0..665ef56f8382 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h | |||
@@ -93,7 +93,6 @@ struct orinoco_private { | |||
93 | 93 | ||
94 | /* Capabilities of the hardware/firmware */ | 94 | /* Capabilities of the hardware/firmware */ |
95 | fwtype_t firmware_type; | 95 | fwtype_t firmware_type; |
96 | char fw_name[32]; | ||
97 | int ibss_port; | 96 | int ibss_port; |
98 | int nicbuf_size; | 97 | int nicbuf_size; |
99 | u16 channel_mask; | 98 | u16 channel_mask; |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index ed1f997e3521..390c0c7b3ac2 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -53,6 +53,32 @@ config RT61PCI | |||
53 | 53 | ||
54 | When compiled as a module, this driver will be called rt61pci. | 54 | When compiled as a module, this driver will be called rt61pci. |
55 | 55 | ||
56 | config RT2800PCI_PCI | ||
57 | tristate | ||
58 | depends on PCI | ||
59 | default y | ||
60 | |||
61 | config RT2800PCI_SOC | ||
62 | tristate | ||
63 | depends on RALINK_RT288X || RALINK_RT305X | ||
64 | default y | ||
65 | |||
66 | config RT2800PCI | ||
67 | tristate "Ralink rt2800 (PCI/PCMCIA) support" | ||
68 | depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL | ||
69 | select RT2X00_LIB_PCI if RT2800PCI_PCI | ||
70 | select RT2X00_LIB_SOC if RT2800PCI_SOC | ||
71 | select RT2X00_LIB_HT | ||
72 | select RT2X00_LIB_FIRMWARE | ||
73 | select RT2X00_LIB_CRYPTO | ||
74 | select CRC_CCITT | ||
75 | select EEPROM_93CX6 | ||
76 | ---help--- | ||
77 | This adds support for rt2800 wireless chipset family. | ||
78 | Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052 | ||
79 | |||
80 | When compiled as a module, this driver will be called "rt2800pci.ko". | ||
81 | |||
56 | config RT2500USB | 82 | config RT2500USB |
57 | tristate "Ralink rt2500 (USB) support" | 83 | tristate "Ralink rt2500 (USB) support" |
58 | depends on USB | 84 | depends on USB |
@@ -95,6 +121,10 @@ config RT2X00_LIB_PCI | |||
95 | tristate | 121 | tristate |
96 | select RT2X00_LIB | 122 | select RT2X00_LIB |
97 | 123 | ||
124 | config RT2X00_LIB_SOC | ||
125 | tristate | ||
126 | select RT2X00_LIB | ||
127 | |||
98 | config RT2X00_LIB_USB | 128 | config RT2X00_LIB_USB |
99 | tristate | 129 | tristate |
100 | select RT2X00_LIB | 130 | select RT2X00_LIB |
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 13043ea97667..912f5f67e159 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile | |||
@@ -11,10 +11,12 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o | |||
11 | 11 | ||
12 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o | 12 | obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o |
13 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o | 13 | obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o |
14 | obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o | ||
14 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o | 15 | obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o |
15 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o | 16 | obj-$(CONFIG_RT2400PCI) += rt2400pci.o |
16 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o | 17 | obj-$(CONFIG_RT2500PCI) += rt2500pci.o |
17 | obj-$(CONFIG_RT61PCI) += rt61pci.o | 18 | obj-$(CONFIG_RT61PCI) += rt61pci.o |
19 | obj-$(CONFIG_RT2800PCI) += rt2800pci.o | ||
18 | obj-$(CONFIG_RT2500USB) += rt2500usb.o | 20 | obj-$(CONFIG_RT2500USB) += rt2500usb.o |
19 | obj-$(CONFIG_RT73USB) += rt73usb.o | 21 | obj-$(CONFIG_RT73USB) += rt73usb.o |
20 | obj-$(CONFIG_RT2800USB) += rt2800usb.o | 22 | obj-$(CONFIG_RT2800USB) += rt2800usb.o |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c new file mode 100644 index 000000000000..be81788b80c7 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -0,0 +1,3323 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2800pci | ||
23 | Abstract: rt2800pci device specific routines. | ||
24 | Supported chipsets: RT2800E & RT2800ED. | ||
25 | */ | ||
26 | |||
27 | #include <linux/crc-ccitt.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/etherdevice.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/kernel.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/eeprom_93cx6.h> | ||
36 | |||
37 | #include "rt2x00.h" | ||
38 | #include "rt2x00pci.h" | ||
39 | #include "rt2x00soc.h" | ||
40 | #include "rt2800pci.h" | ||
41 | |||
42 | #ifdef CONFIG_RT2800PCI_PCI_MODULE | ||
43 | #define CONFIG_RT2800PCI_PCI | ||
44 | #endif | ||
45 | |||
46 | #ifdef CONFIG_RT2800PCI_WISOC_MODULE | ||
47 | #define CONFIG_RT2800PCI_WISOC | ||
48 | #endif | ||
49 | |||
50 | /* | ||
51 | * Allow hardware encryption to be disabled. | ||
52 | */ | ||
53 | static int modparam_nohwcrypt = 1; | ||
54 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | ||
55 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | ||
56 | |||
57 | /* | ||
58 | * Register access. | ||
59 | * BBP and RF register require indirect register access, | ||
60 | * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this. | ||
61 | * These indirect registers work with busy bits, | ||
62 | * and we will try maximal REGISTER_BUSY_COUNT times to access | ||
63 | * the register while taking a REGISTER_BUSY_DELAY us delay | ||
64 | * between each attampt. When the busy bit is still set at that time, | ||
65 | * the access attempt is considered to have failed, | ||
66 | * and we will print an error. | ||
67 | */ | ||
68 | #define WAIT_FOR_BBP(__dev, __reg) \ | ||
69 | rt2x00pci_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) | ||
70 | #define WAIT_FOR_RFCSR(__dev, __reg) \ | ||
71 | rt2x00pci_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) | ||
72 | #define WAIT_FOR_RF(__dev, __reg) \ | ||
73 | rt2x00pci_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) | ||
74 | #define WAIT_FOR_MCU(__dev, __reg) \ | ||
75 | rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ | ||
76 | H2M_MAILBOX_CSR_OWNER, (__reg)) | ||
77 | |||
78 | static void rt2800pci_bbp_write(struct rt2x00_dev *rt2x00dev, | ||
79 | const unsigned int word, const u8 value) | ||
80 | { | ||
81 | u32 reg; | ||
82 | |||
83 | mutex_lock(&rt2x00dev->csr_mutex); | ||
84 | |||
85 | /* | ||
86 | * Wait until the BBP becomes available, afterwards we | ||
87 | * can safely write the new data into the register. | ||
88 | */ | ||
89 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { | ||
90 | reg = 0; | ||
91 | rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); | ||
92 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | ||
93 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | ||
94 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); | ||
95 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | ||
96 | |||
97 | rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); | ||
98 | } | ||
99 | |||
100 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
101 | } | ||
102 | |||
103 | static void rt2800pci_bbp_read(struct rt2x00_dev *rt2x00dev, | ||
104 | const unsigned int word, u8 *value) | ||
105 | { | ||
106 | u32 reg; | ||
107 | |||
108 | mutex_lock(&rt2x00dev->csr_mutex); | ||
109 | |||
110 | /* | ||
111 | * Wait until the BBP becomes available, afterwards we | ||
112 | * can safely write the read request into the register. | ||
113 | * After the data has been written, we wait until hardware | ||
114 | * returns the correct value, if at any time the register | ||
115 | * doesn't become available in time, reg will be 0xffffffff | ||
116 | * which means we return 0xff to the caller. | ||
117 | */ | ||
118 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { | ||
119 | reg = 0; | ||
120 | rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); | ||
121 | rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); | ||
122 | rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); | ||
123 | rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); | ||
124 | |||
125 | rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); | ||
126 | |||
127 | WAIT_FOR_BBP(rt2x00dev, ®); | ||
128 | } | ||
129 | |||
130 | *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); | ||
131 | |||
132 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
133 | } | ||
134 | |||
135 | static void rt2800pci_rfcsr_write(struct rt2x00_dev *rt2x00dev, | ||
136 | const unsigned int word, const u8 value) | ||
137 | { | ||
138 | u32 reg; | ||
139 | |||
140 | mutex_lock(&rt2x00dev->csr_mutex); | ||
141 | |||
142 | /* | ||
143 | * Wait until the RFCSR becomes available, afterwards we | ||
144 | * can safely write the new data into the register. | ||
145 | */ | ||
146 | if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { | ||
147 | reg = 0; | ||
148 | rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); | ||
149 | rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); | ||
150 | rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); | ||
151 | rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); | ||
152 | |||
153 | rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg); | ||
154 | } | ||
155 | |||
156 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
157 | } | ||
158 | |||
159 | static void rt2800pci_rfcsr_read(struct rt2x00_dev *rt2x00dev, | ||
160 | const unsigned int word, u8 *value) | ||
161 | { | ||
162 | u32 reg; | ||
163 | |||
164 | mutex_lock(&rt2x00dev->csr_mutex); | ||
165 | |||
166 | /* | ||
167 | * Wait until the RFCSR becomes available, afterwards we | ||
168 | * can safely write the read request into the register. | ||
169 | * After the data has been written, we wait until hardware | ||
170 | * returns the correct value, if at any time the register | ||
171 | * doesn't become available in time, reg will be 0xffffffff | ||
172 | * which means we return 0xff to the caller. | ||
173 | */ | ||
174 | if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { | ||
175 | reg = 0; | ||
176 | rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); | ||
177 | rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); | ||
178 | rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); | ||
179 | |||
180 | rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg); | ||
181 | |||
182 | WAIT_FOR_RFCSR(rt2x00dev, ®); | ||
183 | } | ||
184 | |||
185 | *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); | ||
186 | |||
187 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
188 | } | ||
189 | |||
190 | static void rt2800pci_rf_write(struct rt2x00_dev *rt2x00dev, | ||
191 | const unsigned int word, const u32 value) | ||
192 | { | ||
193 | u32 reg; | ||
194 | |||
195 | mutex_lock(&rt2x00dev->csr_mutex); | ||
196 | |||
197 | /* | ||
198 | * Wait until the RF becomes available, afterwards we | ||
199 | * can safely write the new data into the register. | ||
200 | */ | ||
201 | if (WAIT_FOR_RF(rt2x00dev, ®)) { | ||
202 | reg = 0; | ||
203 | rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); | ||
204 | rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); | ||
205 | rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); | ||
206 | rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); | ||
207 | |||
208 | rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG0, reg); | ||
209 | rt2x00_rf_write(rt2x00dev, word, value); | ||
210 | } | ||
211 | |||
212 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
213 | } | ||
214 | |||
215 | static void rt2800pci_mcu_request(struct rt2x00_dev *rt2x00dev, | ||
216 | const u8 command, const u8 token, | ||
217 | const u8 arg0, const u8 arg1) | ||
218 | { | ||
219 | u32 reg; | ||
220 | |||
221 | /* | ||
222 | * RT2880 and RT3052 don't support MCU requests. | ||
223 | */ | ||
224 | if (rt2x00_rt(&rt2x00dev->chip, RT2880) || | ||
225 | rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
226 | return; | ||
227 | |||
228 | mutex_lock(&rt2x00dev->csr_mutex); | ||
229 | |||
230 | /* | ||
231 | * Wait until the MCU becomes available, afterwards we | ||
232 | * can safely write the new data into the register. | ||
233 | */ | ||
234 | if (WAIT_FOR_MCU(rt2x00dev, ®)) { | ||
235 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); | ||
236 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); | ||
237 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); | ||
238 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); | ||
239 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); | ||
240 | |||
241 | reg = 0; | ||
242 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | ||
243 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); | ||
244 | } | ||
245 | |||
246 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
247 | } | ||
248 | |||
249 | static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | ||
250 | { | ||
251 | unsigned int i; | ||
252 | u32 reg; | ||
253 | |||
254 | for (i = 0; i < 200; i++) { | ||
255 | rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); | ||
256 | |||
257 | if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || | ||
258 | (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || | ||
259 | (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) || | ||
260 | (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token)) | ||
261 | break; | ||
262 | |||
263 | udelay(REGISTER_BUSY_DELAY); | ||
264 | } | ||
265 | |||
266 | if (i == 200) | ||
267 | ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); | ||
268 | |||
269 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); | ||
270 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | ||
271 | } | ||
272 | |||
273 | #ifdef CONFIG_RT2800PCI_WISOC | ||
274 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
275 | { | ||
276 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ | ||
277 | |||
278 | memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); | ||
279 | } | ||
280 | #else | ||
281 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | ||
282 | { | ||
283 | } | ||
284 | #endif /* CONFIG_RT2800PCI_WISOC */ | ||
285 | |||
286 | #ifdef CONFIG_RT2800PCI_PCI | ||
287 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | ||
288 | { | ||
289 | struct rt2x00_dev *rt2x00dev = eeprom->data; | ||
290 | u32 reg; | ||
291 | |||
292 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | ||
293 | |||
294 | eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); | ||
295 | eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); | ||
296 | eeprom->reg_data_clock = | ||
297 | !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK); | ||
298 | eeprom->reg_chip_select = | ||
299 | !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT); | ||
300 | } | ||
301 | |||
302 | static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) | ||
303 | { | ||
304 | struct rt2x00_dev *rt2x00dev = eeprom->data; | ||
305 | u32 reg = 0; | ||
306 | |||
307 | rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in); | ||
308 | rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out); | ||
309 | rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, | ||
310 | !!eeprom->reg_data_clock); | ||
311 | rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, | ||
312 | !!eeprom->reg_chip_select); | ||
313 | |||
314 | rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); | ||
315 | } | ||
316 | |||
317 | static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | ||
318 | { | ||
319 | struct eeprom_93cx6 eeprom; | ||
320 | u32 reg; | ||
321 | |||
322 | rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); | ||
323 | |||
324 | eeprom.data = rt2x00dev; | ||
325 | eeprom.register_read = rt2800pci_eepromregister_read; | ||
326 | eeprom.register_write = rt2800pci_eepromregister_write; | ||
327 | eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ? | ||
328 | PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; | ||
329 | eeprom.reg_data_in = 0; | ||
330 | eeprom.reg_data_out = 0; | ||
331 | eeprom.reg_data_clock = 0; | ||
332 | eeprom.reg_chip_select = 0; | ||
333 | |||
334 | eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, | ||
335 | EEPROM_SIZE / sizeof(u16)); | ||
336 | } | ||
337 | |||
338 | static void rt2800pci_efuse_read(struct rt2x00_dev *rt2x00dev, | ||
339 | unsigned int i) | ||
340 | { | ||
341 | u32 reg; | ||
342 | |||
343 | rt2x00pci_register_read(rt2x00dev, EFUSE_CTRL, ®); | ||
344 | rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i); | ||
345 | rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0); | ||
346 | rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); | ||
347 | rt2x00pci_register_write(rt2x00dev, EFUSE_CTRL, reg); | ||
348 | |||
349 | /* Wait until the EEPROM has been loaded */ | ||
350 | rt2x00pci_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); | ||
351 | |||
352 | /* Apparently the data is read from end to start */ | ||
353 | rt2x00pci_register_read(rt2x00dev, EFUSE_DATA3, | ||
354 | (u32 *)&rt2x00dev->eeprom[i]); | ||
355 | rt2x00pci_register_read(rt2x00dev, EFUSE_DATA2, | ||
356 | (u32 *)&rt2x00dev->eeprom[i + 2]); | ||
357 | rt2x00pci_register_read(rt2x00dev, EFUSE_DATA1, | ||
358 | (u32 *)&rt2x00dev->eeprom[i + 4]); | ||
359 | rt2x00pci_register_read(rt2x00dev, EFUSE_DATA0, | ||
360 | (u32 *)&rt2x00dev->eeprom[i + 6]); | ||
361 | } | ||
362 | |||
363 | static void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | ||
364 | { | ||
365 | unsigned int i; | ||
366 | |||
367 | for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8) | ||
368 | rt2800pci_efuse_read(rt2x00dev, i); | ||
369 | } | ||
370 | #else | ||
371 | static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) | ||
372 | { | ||
373 | } | ||
374 | |||
375 | static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) | ||
376 | { | ||
377 | } | ||
378 | #endif /* CONFIG_RT2800PCI_PCI */ | ||
379 | |||
380 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
381 | static const struct rt2x00debug rt2800pci_rt2x00debug = { | ||
382 | .owner = THIS_MODULE, | ||
383 | .csr = { | ||
384 | .read = rt2x00pci_register_read, | ||
385 | .write = rt2x00pci_register_write, | ||
386 | .flags = RT2X00DEBUGFS_OFFSET, | ||
387 | .word_base = CSR_REG_BASE, | ||
388 | .word_size = sizeof(u32), | ||
389 | .word_count = CSR_REG_SIZE / sizeof(u32), | ||
390 | }, | ||
391 | .eeprom = { | ||
392 | .read = rt2x00_eeprom_read, | ||
393 | .write = rt2x00_eeprom_write, | ||
394 | .word_base = EEPROM_BASE, | ||
395 | .word_size = sizeof(u16), | ||
396 | .word_count = EEPROM_SIZE / sizeof(u16), | ||
397 | }, | ||
398 | .bbp = { | ||
399 | .read = rt2800pci_bbp_read, | ||
400 | .write = rt2800pci_bbp_write, | ||
401 | .word_base = BBP_BASE, | ||
402 | .word_size = sizeof(u8), | ||
403 | .word_count = BBP_SIZE / sizeof(u8), | ||
404 | }, | ||
405 | .rf = { | ||
406 | .read = rt2x00_rf_read, | ||
407 | .write = rt2800pci_rf_write, | ||
408 | .word_base = RF_BASE, | ||
409 | .word_size = sizeof(u32), | ||
410 | .word_count = RF_SIZE / sizeof(u32), | ||
411 | }, | ||
412 | }; | ||
413 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
414 | |||
415 | static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) | ||
416 | { | ||
417 | u32 reg; | ||
418 | |||
419 | rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); | ||
420 | return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); | ||
421 | } | ||
422 | |||
423 | #ifdef CONFIG_RT2X00_LIB_LEDS | ||
424 | static void rt2800pci_brightness_set(struct led_classdev *led_cdev, | ||
425 | enum led_brightness brightness) | ||
426 | { | ||
427 | struct rt2x00_led *led = | ||
428 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
429 | unsigned int enabled = brightness != LED_OFF; | ||
430 | unsigned int bg_mode = | ||
431 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | ||
432 | unsigned int polarity = | ||
433 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
434 | EEPROM_FREQ_LED_POLARITY); | ||
435 | unsigned int ledmode = | ||
436 | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, | ||
437 | EEPROM_FREQ_LED_MODE); | ||
438 | |||
439 | if (led->type == LED_TYPE_RADIO) { | ||
440 | rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
441 | enabled ? 0x20 : 0); | ||
442 | } else if (led->type == LED_TYPE_ASSOC) { | ||
443 | rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, | ||
444 | enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); | ||
445 | } else if (led->type == LED_TYPE_QUALITY) { | ||
446 | /* | ||
447 | * The brightness is divided into 6 levels (0 - 5), | ||
448 | * The specs tell us the following levels: | ||
449 | * 0, 1 ,3, 7, 15, 31 | ||
450 | * to determine the level in a simple way we can simply | ||
451 | * work with bitshifting: | ||
452 | * (1 << level) - 1 | ||
453 | */ | ||
454 | rt2800pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, | ||
455 | (1 << brightness / (LED_FULL / 6)) - 1, | ||
456 | polarity); | ||
457 | } | ||
458 | } | ||
459 | |||
460 | static int rt2800pci_blink_set(struct led_classdev *led_cdev, | ||
461 | unsigned long *delay_on, | ||
462 | unsigned long *delay_off) | ||
463 | { | ||
464 | struct rt2x00_led *led = | ||
465 | container_of(led_cdev, struct rt2x00_led, led_dev); | ||
466 | u32 reg; | ||
467 | |||
468 | rt2x00pci_register_read(led->rt2x00dev, LED_CFG, ®); | ||
469 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); | ||
470 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); | ||
471 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | ||
472 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | ||
473 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); | ||
474 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | ||
475 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | ||
476 | rt2x00pci_register_write(led->rt2x00dev, LED_CFG, reg); | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static void rt2800pci_init_led(struct rt2x00_dev *rt2x00dev, | ||
482 | struct rt2x00_led *led, | ||
483 | enum led_type type) | ||
484 | { | ||
485 | led->rt2x00dev = rt2x00dev; | ||
486 | led->type = type; | ||
487 | led->led_dev.brightness_set = rt2800pci_brightness_set; | ||
488 | led->led_dev.blink_set = rt2800pci_blink_set; | ||
489 | led->flags = LED_INITIALIZED; | ||
490 | } | ||
491 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | ||
492 | |||
493 | /* | ||
494 | * Configuration handlers. | ||
495 | */ | ||
496 | static void rt2800pci_config_wcid_attr(struct rt2x00_dev *rt2x00dev, | ||
497 | struct rt2x00lib_crypto *crypto, | ||
498 | struct ieee80211_key_conf *key) | ||
499 | { | ||
500 | struct mac_wcid_entry wcid_entry; | ||
501 | struct mac_iveiv_entry iveiv_entry; | ||
502 | u32 offset; | ||
503 | u32 reg; | ||
504 | |||
505 | offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); | ||
506 | |||
507 | rt2x00pci_register_read(rt2x00dev, offset, ®); | ||
508 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, | ||
509 | !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); | ||
510 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, | ||
511 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
512 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, | ||
513 | (crypto->cmd == SET_KEY) * crypto->bssidx); | ||
514 | rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); | ||
515 | rt2x00pci_register_write(rt2x00dev, offset, reg); | ||
516 | |||
517 | offset = MAC_IVEIV_ENTRY(key->hw_key_idx); | ||
518 | |||
519 | memset(&iveiv_entry, 0, sizeof(iveiv_entry)); | ||
520 | if ((crypto->cipher == CIPHER_TKIP) || | ||
521 | (crypto->cipher == CIPHER_TKIP_NO_MIC) || | ||
522 | (crypto->cipher == CIPHER_AES)) | ||
523 | iveiv_entry.iv[3] |= 0x20; | ||
524 | iveiv_entry.iv[3] |= key->keyidx << 6; | ||
525 | rt2x00pci_register_multiwrite(rt2x00dev, offset, | ||
526 | &iveiv_entry, sizeof(iveiv_entry)); | ||
527 | |||
528 | offset = MAC_WCID_ENTRY(key->hw_key_idx); | ||
529 | |||
530 | memset(&wcid_entry, 0, sizeof(wcid_entry)); | ||
531 | if (crypto->cmd == SET_KEY) | ||
532 | memcpy(&wcid_entry, crypto->address, ETH_ALEN); | ||
533 | rt2x00pci_register_multiwrite(rt2x00dev, offset, | ||
534 | &wcid_entry, sizeof(wcid_entry)); | ||
535 | } | ||
536 | |||
537 | static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev, | ||
538 | struct rt2x00lib_crypto *crypto, | ||
539 | struct ieee80211_key_conf *key) | ||
540 | { | ||
541 | struct hw_key_entry key_entry; | ||
542 | struct rt2x00_field32 field; | ||
543 | u32 offset; | ||
544 | u32 reg; | ||
545 | |||
546 | if (crypto->cmd == SET_KEY) { | ||
547 | key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; | ||
548 | |||
549 | memcpy(key_entry.key, crypto->key, | ||
550 | sizeof(key_entry.key)); | ||
551 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
552 | sizeof(key_entry.tx_mic)); | ||
553 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
554 | sizeof(key_entry.rx_mic)); | ||
555 | |||
556 | offset = SHARED_KEY_ENTRY(key->hw_key_idx); | ||
557 | rt2x00pci_register_multiwrite(rt2x00dev, offset, | ||
558 | &key_entry, sizeof(key_entry)); | ||
559 | } | ||
560 | |||
561 | /* | ||
562 | * The cipher types are stored over multiple registers | ||
563 | * starting with SHARED_KEY_MODE_BASE each word will have | ||
564 | * 32 bits and contains the cipher types for 2 bssidx each. | ||
565 | * Using the correct defines correctly will cause overhead, | ||
566 | * so just calculate the correct offset. | ||
567 | */ | ||
568 | field.bit_offset = 4 * (key->hw_key_idx % 8); | ||
569 | field.bit_mask = 0x7 << field.bit_offset; | ||
570 | |||
571 | offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); | ||
572 | |||
573 | rt2x00pci_register_read(rt2x00dev, offset, ®); | ||
574 | rt2x00_set_field32(®, field, | ||
575 | (crypto->cmd == SET_KEY) * crypto->cipher); | ||
576 | rt2x00pci_register_write(rt2x00dev, offset, reg); | ||
577 | |||
578 | /* | ||
579 | * Update WCID information | ||
580 | */ | ||
581 | rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int rt2800pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | ||
587 | struct rt2x00lib_crypto *crypto, | ||
588 | struct ieee80211_key_conf *key) | ||
589 | { | ||
590 | struct hw_key_entry key_entry; | ||
591 | u32 offset; | ||
592 | |||
593 | if (crypto->cmd == SET_KEY) { | ||
594 | /* | ||
595 | * 1 pairwise key is possible per AID, this means that the AID | ||
596 | * equals our hw_key_idx. Make sure the WCID starts _after_ the | ||
597 | * last possible shared key entry. | ||
598 | */ | ||
599 | if (crypto->aid > (256 - 32)) | ||
600 | return -ENOSPC; | ||
601 | |||
602 | key->hw_key_idx = 32 + crypto->aid; | ||
603 | |||
604 | |||
605 | memcpy(key_entry.key, crypto->key, | ||
606 | sizeof(key_entry.key)); | ||
607 | memcpy(key_entry.tx_mic, crypto->tx_mic, | ||
608 | sizeof(key_entry.tx_mic)); | ||
609 | memcpy(key_entry.rx_mic, crypto->rx_mic, | ||
610 | sizeof(key_entry.rx_mic)); | ||
611 | |||
612 | offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); | ||
613 | rt2x00pci_register_multiwrite(rt2x00dev, offset, | ||
614 | &key_entry, sizeof(key_entry)); | ||
615 | } | ||
616 | |||
617 | /* | ||
618 | * Update WCID information | ||
619 | */ | ||
620 | rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void rt2800pci_config_filter(struct rt2x00_dev *rt2x00dev, | ||
626 | const unsigned int filter_flags) | ||
627 | { | ||
628 | u32 reg; | ||
629 | |||
630 | /* | ||
631 | * Start configuration steps. | ||
632 | * Note that the version error will always be dropped | ||
633 | * and broadcast frames will always be accepted since | ||
634 | * there is no filter for it at this time. | ||
635 | */ | ||
636 | rt2x00pci_register_read(rt2x00dev, RX_FILTER_CFG, ®); | ||
637 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, | ||
638 | !(filter_flags & FIF_FCSFAIL)); | ||
639 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, | ||
640 | !(filter_flags & FIF_PLCPFAIL)); | ||
641 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, | ||
642 | !(filter_flags & FIF_PROMISC_IN_BSS)); | ||
643 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); | ||
644 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); | ||
645 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, | ||
646 | !(filter_flags & FIF_ALLMULTI)); | ||
647 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); | ||
648 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); | ||
649 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, | ||
650 | !(filter_flags & FIF_CONTROL)); | ||
651 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, | ||
652 | !(filter_flags & FIF_CONTROL)); | ||
653 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, | ||
654 | !(filter_flags & FIF_CONTROL)); | ||
655 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, | ||
656 | !(filter_flags & FIF_CONTROL)); | ||
657 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, | ||
658 | !(filter_flags & FIF_CONTROL)); | ||
659 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, | ||
660 | !(filter_flags & FIF_PSPOLL)); | ||
661 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); | ||
662 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); | ||
663 | rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, | ||
664 | !(filter_flags & FIF_CONTROL)); | ||
665 | rt2x00pci_register_write(rt2x00dev, RX_FILTER_CFG, reg); | ||
666 | } | ||
667 | |||
668 | static void rt2800pci_config_intf(struct rt2x00_dev *rt2x00dev, | ||
669 | struct rt2x00_intf *intf, | ||
670 | struct rt2x00intf_conf *conf, | ||
671 | const unsigned int flags) | ||
672 | { | ||
673 | unsigned int beacon_base; | ||
674 | u32 reg; | ||
675 | |||
676 | if (flags & CONFIG_UPDATE_TYPE) { | ||
677 | /* | ||
678 | * Clear current synchronisation setup. | ||
679 | * For the Beacon base registers we only need to clear | ||
680 | * the first byte since that byte contains the VALID and OWNER | ||
681 | * bits which (when set to 0) will invalidate the entire beacon. | ||
682 | */ | ||
683 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | ||
684 | rt2x00pci_register_write(rt2x00dev, beacon_base, 0); | ||
685 | |||
686 | /* | ||
687 | * Enable synchronisation. | ||
688 | */ | ||
689 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
690 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
691 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); | ||
692 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
693 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
694 | } | ||
695 | |||
696 | if (flags & CONFIG_UPDATE_MAC) { | ||
697 | reg = le32_to_cpu(conf->mac[1]); | ||
698 | rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); | ||
699 | conf->mac[1] = cpu_to_le32(reg); | ||
700 | |||
701 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, | ||
702 | conf->mac, sizeof(conf->mac)); | ||
703 | } | ||
704 | |||
705 | if (flags & CONFIG_UPDATE_BSSID) { | ||
706 | reg = le32_to_cpu(conf->bssid[1]); | ||
707 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); | ||
708 | rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); | ||
709 | conf->bssid[1] = cpu_to_le32(reg); | ||
710 | |||
711 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, | ||
712 | conf->bssid, sizeof(conf->bssid)); | ||
713 | } | ||
714 | } | ||
715 | |||
716 | static void rt2800pci_config_erp(struct rt2x00_dev *rt2x00dev, | ||
717 | struct rt2x00lib_erp *erp) | ||
718 | { | ||
719 | u32 reg; | ||
720 | |||
721 | rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | ||
722 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); | ||
723 | rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | ||
724 | |||
725 | rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | ||
726 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | ||
727 | !!erp->short_preamble); | ||
728 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, | ||
729 | !!erp->short_preamble); | ||
730 | rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | ||
731 | |||
732 | rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
733 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, | ||
734 | erp->cts_protection ? 2 : 0); | ||
735 | rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
736 | |||
737 | rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, | ||
738 | erp->basic_rates); | ||
739 | rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | ||
740 | |||
741 | rt2x00pci_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | ||
742 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | ||
743 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | ||
744 | rt2x00pci_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | ||
745 | |||
746 | rt2x00pci_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | ||
747 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); | ||
748 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); | ||
749 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | ||
750 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | ||
751 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | ||
752 | rt2x00pci_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | ||
753 | |||
754 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
755 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, | ||
756 | erp->beacon_int * 16); | ||
757 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
758 | } | ||
759 | |||
760 | static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev, | ||
761 | struct antenna_setup *ant) | ||
762 | { | ||
763 | u8 r1; | ||
764 | u8 r3; | ||
765 | |||
766 | rt2800pci_bbp_read(rt2x00dev, 1, &r1); | ||
767 | rt2800pci_bbp_read(rt2x00dev, 3, &r3); | ||
768 | |||
769 | /* | ||
770 | * Configure the TX antenna. | ||
771 | */ | ||
772 | switch ((int)ant->tx) { | ||
773 | case 1: | ||
774 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); | ||
775 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | ||
776 | break; | ||
777 | case 2: | ||
778 | rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); | ||
779 | break; | ||
780 | case 3: | ||
781 | /* Do nothing */ | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Configure the RX antenna. | ||
787 | */ | ||
788 | switch ((int)ant->rx) { | ||
789 | case 1: | ||
790 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); | ||
791 | break; | ||
792 | case 2: | ||
793 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); | ||
794 | break; | ||
795 | case 3: | ||
796 | rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); | ||
797 | break; | ||
798 | } | ||
799 | |||
800 | rt2800pci_bbp_write(rt2x00dev, 3, r3); | ||
801 | rt2800pci_bbp_write(rt2x00dev, 1, r1); | ||
802 | } | ||
803 | |||
804 | static void rt2800pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, | ||
805 | struct rt2x00lib_conf *libconf) | ||
806 | { | ||
807 | u16 eeprom; | ||
808 | short lna_gain; | ||
809 | |||
810 | if (libconf->rf.channel <= 14) { | ||
811 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
812 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); | ||
813 | } else if (libconf->rf.channel <= 64) { | ||
814 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); | ||
815 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); | ||
816 | } else if (libconf->rf.channel <= 128) { | ||
817 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); | ||
818 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); | ||
819 | } else { | ||
820 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); | ||
821 | lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); | ||
822 | } | ||
823 | |||
824 | rt2x00dev->lna_gain = lna_gain; | ||
825 | } | ||
826 | |||
827 | static void rt2800pci_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | ||
828 | struct ieee80211_conf *conf, | ||
829 | struct rf_channel *rf, | ||
830 | struct channel_info *info) | ||
831 | { | ||
832 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
833 | |||
834 | if (rt2x00dev->default_ant.tx == 1) | ||
835 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); | ||
836 | |||
837 | if (rt2x00dev->default_ant.rx == 1) { | ||
838 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); | ||
839 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
840 | } else if (rt2x00dev->default_ant.rx == 2) | ||
841 | rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); | ||
842 | |||
843 | if (rf->channel > 14) { | ||
844 | /* | ||
845 | * When TX power is below 0, we should increase it by 7 to | ||
846 | * make it a positive value (Minumum value is -7). | ||
847 | * However this means that values between 0 and 7 have | ||
848 | * double meaning, and we should set a 7DBm boost flag. | ||
849 | */ | ||
850 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, | ||
851 | (info->tx_power1 >= 0)); | ||
852 | |||
853 | if (info->tx_power1 < 0) | ||
854 | info->tx_power1 += 7; | ||
855 | |||
856 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, | ||
857 | TXPOWER_A_TO_DEV(info->tx_power1)); | ||
858 | |||
859 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, | ||
860 | (info->tx_power2 >= 0)); | ||
861 | |||
862 | if (info->tx_power2 < 0) | ||
863 | info->tx_power2 += 7; | ||
864 | |||
865 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, | ||
866 | TXPOWER_A_TO_DEV(info->tx_power2)); | ||
867 | } else { | ||
868 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, | ||
869 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
870 | rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, | ||
871 | TXPOWER_G_TO_DEV(info->tx_power2)); | ||
872 | } | ||
873 | |||
874 | rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); | ||
875 | |||
876 | rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); | ||
877 | rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); | ||
878 | rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
879 | rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); | ||
880 | |||
881 | udelay(200); | ||
882 | |||
883 | rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); | ||
884 | rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); | ||
885 | rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); | ||
886 | rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); | ||
887 | |||
888 | udelay(200); | ||
889 | |||
890 | rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); | ||
891 | rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); | ||
892 | rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); | ||
893 | rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); | ||
894 | } | ||
895 | |||
896 | static void rt2800pci_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | ||
897 | struct ieee80211_conf *conf, | ||
898 | struct rf_channel *rf, | ||
899 | struct channel_info *info) | ||
900 | { | ||
901 | u8 rfcsr; | ||
902 | |||
903 | rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf1); | ||
904 | rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf3); | ||
905 | |||
906 | rt2800pci_rfcsr_read(rt2x00dev, 6, &rfcsr); | ||
907 | rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); | ||
908 | rt2800pci_rfcsr_write(rt2x00dev, 6, rfcsr); | ||
909 | |||
910 | rt2800pci_rfcsr_read(rt2x00dev, 12, &rfcsr); | ||
911 | rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, | ||
912 | TXPOWER_G_TO_DEV(info->tx_power1)); | ||
913 | rt2800pci_rfcsr_write(rt2x00dev, 12, rfcsr); | ||
914 | |||
915 | rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
916 | rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); | ||
917 | rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
918 | |||
919 | rt2800pci_rfcsr_write(rt2x00dev, 24, | ||
920 | rt2x00dev->calibration[conf_is_ht40(conf)]); | ||
921 | |||
922 | rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr); | ||
923 | rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); | ||
924 | rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr); | ||
925 | } | ||
926 | |||
927 | static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, | ||
928 | struct ieee80211_conf *conf, | ||
929 | struct rf_channel *rf, | ||
930 | struct channel_info *info) | ||
931 | { | ||
932 | u32 reg; | ||
933 | unsigned int tx_pin; | ||
934 | u8 bbp; | ||
935 | |||
936 | if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | ||
937 | rt2800pci_config_channel_rt2x(rt2x00dev, conf, rf, info); | ||
938 | else | ||
939 | rt2800pci_config_channel_rt3x(rt2x00dev, conf, rf, info); | ||
940 | |||
941 | /* | ||
942 | * Change BBP settings | ||
943 | */ | ||
944 | rt2800pci_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); | ||
945 | rt2800pci_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); | ||
946 | rt2800pci_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); | ||
947 | rt2800pci_bbp_write(rt2x00dev, 86, 0); | ||
948 | |||
949 | if (rf->channel <= 14) { | ||
950 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { | ||
951 | rt2800pci_bbp_write(rt2x00dev, 82, 0x62); | ||
952 | rt2800pci_bbp_write(rt2x00dev, 75, 0x46); | ||
953 | } else { | ||
954 | rt2800pci_bbp_write(rt2x00dev, 82, 0x84); | ||
955 | rt2800pci_bbp_write(rt2x00dev, 75, 0x50); | ||
956 | } | ||
957 | } else { | ||
958 | rt2800pci_bbp_write(rt2x00dev, 82, 0xf2); | ||
959 | |||
960 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) | ||
961 | rt2800pci_bbp_write(rt2x00dev, 75, 0x46); | ||
962 | else | ||
963 | rt2800pci_bbp_write(rt2x00dev, 75, 0x50); | ||
964 | } | ||
965 | |||
966 | rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); | ||
967 | rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
968 | rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); | ||
969 | rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); | ||
970 | rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); | ||
971 | |||
972 | tx_pin = 0; | ||
973 | |||
974 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
975 | if (rt2x00dev->default_ant.tx != 1) { | ||
976 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); | ||
977 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); | ||
978 | } | ||
979 | |||
980 | /* Turn on unused PA or LNA when not using 1T or 1R */ | ||
981 | if (rt2x00dev->default_ant.rx != 1) { | ||
982 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); | ||
983 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); | ||
984 | } | ||
985 | |||
986 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); | ||
987 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); | ||
988 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); | ||
989 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); | ||
990 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); | ||
991 | rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); | ||
992 | |||
993 | rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); | ||
994 | |||
995 | rt2800pci_bbp_read(rt2x00dev, 4, &bbp); | ||
996 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); | ||
997 | rt2800pci_bbp_write(rt2x00dev, 4, bbp); | ||
998 | |||
999 | rt2800pci_bbp_read(rt2x00dev, 3, &bbp); | ||
1000 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | ||
1001 | rt2800pci_bbp_write(rt2x00dev, 3, bbp); | ||
1002 | |||
1003 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | ||
1004 | if (conf_is_ht40(conf)) { | ||
1005 | rt2800pci_bbp_write(rt2x00dev, 69, 0x1a); | ||
1006 | rt2800pci_bbp_write(rt2x00dev, 70, 0x0a); | ||
1007 | rt2800pci_bbp_write(rt2x00dev, 73, 0x16); | ||
1008 | } else { | ||
1009 | rt2800pci_bbp_write(rt2x00dev, 69, 0x16); | ||
1010 | rt2800pci_bbp_write(rt2x00dev, 70, 0x08); | ||
1011 | rt2800pci_bbp_write(rt2x00dev, 73, 0x11); | ||
1012 | } | ||
1013 | } | ||
1014 | |||
1015 | msleep(1); | ||
1016 | } | ||
1017 | |||
1018 | static void rt2800pci_config_txpower(struct rt2x00_dev *rt2x00dev, | ||
1019 | const int txpower) | ||
1020 | { | ||
1021 | u32 reg; | ||
1022 | u32 value = TXPOWER_G_TO_DEV(txpower); | ||
1023 | u8 r1; | ||
1024 | |||
1025 | rt2800pci_bbp_read(rt2x00dev, 1, &r1); | ||
1026 | rt2x00_set_field8(®, BBP1_TX_POWER, 0); | ||
1027 | rt2800pci_bbp_write(rt2x00dev, 1, r1); | ||
1028 | |||
1029 | rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | ||
1030 | rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); | ||
1031 | rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); | ||
1032 | rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); | ||
1033 | rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); | ||
1034 | rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); | ||
1035 | rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); | ||
1036 | rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); | ||
1037 | rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); | ||
1038 | rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_0, reg); | ||
1039 | |||
1040 | rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_1, ®); | ||
1041 | rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); | ||
1042 | rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); | ||
1043 | rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); | ||
1044 | rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); | ||
1045 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); | ||
1046 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); | ||
1047 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); | ||
1048 | rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); | ||
1049 | rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_1, reg); | ||
1050 | |||
1051 | rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_2, ®); | ||
1052 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); | ||
1053 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); | ||
1054 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); | ||
1055 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); | ||
1056 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); | ||
1057 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); | ||
1058 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); | ||
1059 | rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); | ||
1060 | rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_2, reg); | ||
1061 | |||
1062 | rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_3, ®); | ||
1063 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); | ||
1064 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); | ||
1065 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); | ||
1066 | rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); | ||
1067 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); | ||
1068 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); | ||
1069 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); | ||
1070 | rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); | ||
1071 | rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_3, reg); | ||
1072 | |||
1073 | rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_4, ®); | ||
1074 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); | ||
1075 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); | ||
1076 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); | ||
1077 | rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); | ||
1078 | rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_4, reg); | ||
1079 | } | ||
1080 | |||
1081 | static void rt2800pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, | ||
1082 | struct rt2x00lib_conf *libconf) | ||
1083 | { | ||
1084 | u32 reg; | ||
1085 | |||
1086 | rt2x00pci_register_read(rt2x00dev, TX_RTY_CFG, ®); | ||
1087 | rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, | ||
1088 | libconf->conf->short_frame_max_tx_count); | ||
1089 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, | ||
1090 | libconf->conf->long_frame_max_tx_count); | ||
1091 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | ||
1092 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | ||
1093 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | ||
1094 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | ||
1095 | rt2x00pci_register_write(rt2x00dev, TX_RTY_CFG, reg); | ||
1096 | } | ||
1097 | |||
1098 | static void rt2800pci_config_ps(struct rt2x00_dev *rt2x00dev, | ||
1099 | struct rt2x00lib_conf *libconf) | ||
1100 | { | ||
1101 | enum dev_state state = | ||
1102 | (libconf->conf->flags & IEEE80211_CONF_PS) ? | ||
1103 | STATE_SLEEP : STATE_AWAKE; | ||
1104 | u32 reg; | ||
1105 | |||
1106 | if (state == STATE_SLEEP) { | ||
1107 | rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); | ||
1108 | |||
1109 | rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
1110 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); | ||
1111 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, | ||
1112 | libconf->conf->listen_interval - 1); | ||
1113 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); | ||
1114 | rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
1115 | |||
1116 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1117 | } else { | ||
1118 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1119 | |||
1120 | rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | ||
1121 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | ||
1122 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | ||
1123 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | ||
1124 | rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | static void rt2800pci_config(struct rt2x00_dev *rt2x00dev, | ||
1129 | struct rt2x00lib_conf *libconf, | ||
1130 | const unsigned int flags) | ||
1131 | { | ||
1132 | /* Always recalculate LNA gain before changing configuration */ | ||
1133 | rt2800pci_config_lna_gain(rt2x00dev, libconf); | ||
1134 | |||
1135 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) | ||
1136 | rt2800pci_config_channel(rt2x00dev, libconf->conf, | ||
1137 | &libconf->rf, &libconf->channel); | ||
1138 | if (flags & IEEE80211_CONF_CHANGE_POWER) | ||
1139 | rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level); | ||
1140 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | ||
1141 | rt2800pci_config_retry_limit(rt2x00dev, libconf); | ||
1142 | if (flags & IEEE80211_CONF_CHANGE_PS) | ||
1143 | rt2800pci_config_ps(rt2x00dev, libconf); | ||
1144 | } | ||
1145 | |||
1146 | /* | ||
1147 | * Link tuning | ||
1148 | */ | ||
1149 | static void rt2800pci_link_stats(struct rt2x00_dev *rt2x00dev, | ||
1150 | struct link_qual *qual) | ||
1151 | { | ||
1152 | u32 reg; | ||
1153 | |||
1154 | /* | ||
1155 | * Update FCS error count from register. | ||
1156 | */ | ||
1157 | rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, ®); | ||
1158 | qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); | ||
1159 | } | ||
1160 | |||
1161 | static u8 rt2800pci_get_default_vgc(struct rt2x00_dev *rt2x00dev) | ||
1162 | { | ||
1163 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) | ||
1164 | return 0x2e + rt2x00dev->lna_gain; | ||
1165 | |||
1166 | if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) | ||
1167 | return 0x32 + (rt2x00dev->lna_gain * 5) / 3; | ||
1168 | else | ||
1169 | return 0x3a + (rt2x00dev->lna_gain * 5) / 3; | ||
1170 | } | ||
1171 | |||
1172 | static inline void rt2800pci_set_vgc(struct rt2x00_dev *rt2x00dev, | ||
1173 | struct link_qual *qual, u8 vgc_level) | ||
1174 | { | ||
1175 | if (qual->vgc_level != vgc_level) { | ||
1176 | rt2800pci_bbp_write(rt2x00dev, 66, vgc_level); | ||
1177 | qual->vgc_level = vgc_level; | ||
1178 | qual->vgc_level_reg = vgc_level; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | static void rt2800pci_reset_tuner(struct rt2x00_dev *rt2x00dev, | ||
1183 | struct link_qual *qual) | ||
1184 | { | ||
1185 | rt2800pci_set_vgc(rt2x00dev, qual, | ||
1186 | rt2800pci_get_default_vgc(rt2x00dev)); | ||
1187 | } | ||
1188 | |||
1189 | static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev, | ||
1190 | struct link_qual *qual, const u32 count) | ||
1191 | { | ||
1192 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | ||
1193 | return; | ||
1194 | |||
1195 | /* | ||
1196 | * When RSSI is better then -80 increase VGC level with 0x10 | ||
1197 | */ | ||
1198 | rt2800pci_set_vgc(rt2x00dev, qual, | ||
1199 | rt2800pci_get_default_vgc(rt2x00dev) + | ||
1200 | ((qual->rssi > -80) * 0x10)); | ||
1201 | } | ||
1202 | |||
1203 | /* | ||
1204 | * Firmware functions | ||
1205 | */ | ||
1206 | static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) | ||
1207 | { | ||
1208 | return FIRMWARE_RT2860; | ||
1209 | } | ||
1210 | |||
1211 | static int rt2800pci_check_firmware(struct rt2x00_dev *rt2x00dev, | ||
1212 | const u8 *data, const size_t len) | ||
1213 | { | ||
1214 | u16 fw_crc; | ||
1215 | u16 crc; | ||
1216 | |||
1217 | /* | ||
1218 | * Only support 8kb firmware files. | ||
1219 | */ | ||
1220 | if (len != 8192) | ||
1221 | return FW_BAD_LENGTH; | ||
1222 | |||
1223 | /* | ||
1224 | * The last 2 bytes in the firmware array are the crc checksum itself, | ||
1225 | * this means that we should never pass those 2 bytes to the crc | ||
1226 | * algorithm. | ||
1227 | */ | ||
1228 | fw_crc = (data[len - 2] << 8 | data[len - 1]); | ||
1229 | |||
1230 | /* | ||
1231 | * Use the crc ccitt algorithm. | ||
1232 | * This will return the same value as the legacy driver which | ||
1233 | * used bit ordering reversion on the both the firmware bytes | ||
1234 | * before input input as well as on the final output. | ||
1235 | * Obviously using crc ccitt directly is much more efficient. | ||
1236 | */ | ||
1237 | crc = crc_ccitt(~0, data, len - 2); | ||
1238 | |||
1239 | /* | ||
1240 | * There is a small difference between the crc-itu-t + bitrev and | ||
1241 | * the crc-ccitt crc calculation. In the latter method the 2 bytes | ||
1242 | * will be swapped, use swab16 to convert the crc to the correct | ||
1243 | * value. | ||
1244 | */ | ||
1245 | crc = swab16(crc); | ||
1246 | |||
1247 | return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; | ||
1248 | } | ||
1249 | |||
1250 | static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, | ||
1251 | const u8 *data, const size_t len) | ||
1252 | { | ||
1253 | unsigned int i; | ||
1254 | u32 reg; | ||
1255 | |||
1256 | /* | ||
1257 | * Wait for stable hardware. | ||
1258 | */ | ||
1259 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1260 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | ||
1261 | if (reg && reg != ~0) | ||
1262 | break; | ||
1263 | msleep(1); | ||
1264 | } | ||
1265 | |||
1266 | if (i == REGISTER_BUSY_COUNT) { | ||
1267 | ERROR(rt2x00dev, "Unstable hardware.\n"); | ||
1268 | return -EBUSY; | ||
1269 | } | ||
1270 | |||
1271 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); | ||
1272 | rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000); | ||
1273 | |||
1274 | /* | ||
1275 | * Disable DMA, will be reenabled later when enabling | ||
1276 | * the radio. | ||
1277 | */ | ||
1278 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
1279 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
1280 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
1281 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
1282 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
1283 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
1284 | rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
1285 | |||
1286 | /* | ||
1287 | * enable Host program ram write selection | ||
1288 | */ | ||
1289 | reg = 0; | ||
1290 | rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); | ||
1291 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); | ||
1292 | |||
1293 | /* | ||
1294 | * Write firmware to device. | ||
1295 | */ | ||
1296 | rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, | ||
1297 | data, len); | ||
1298 | |||
1299 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); | ||
1300 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); | ||
1301 | |||
1302 | /* | ||
1303 | * Wait for device to stabilize. | ||
1304 | */ | ||
1305 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1306 | rt2x00pci_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | ||
1307 | if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) | ||
1308 | break; | ||
1309 | msleep(1); | ||
1310 | } | ||
1311 | |||
1312 | if (i == REGISTER_BUSY_COUNT) { | ||
1313 | ERROR(rt2x00dev, "PBF system register not ready.\n"); | ||
1314 | return -EBUSY; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * Disable interrupts | ||
1319 | */ | ||
1320 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); | ||
1321 | |||
1322 | /* | ||
1323 | * Initialize BBP R/W access agent | ||
1324 | */ | ||
1325 | rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
1326 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
1327 | |||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | /* | ||
1332 | * Initialization functions. | ||
1333 | */ | ||
1334 | static bool rt2800pci_get_entry_state(struct queue_entry *entry) | ||
1335 | { | ||
1336 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1337 | u32 word; | ||
1338 | |||
1339 | if (entry->queue->qid == QID_RX) { | ||
1340 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1341 | |||
1342 | return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); | ||
1343 | } else { | ||
1344 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1345 | |||
1346 | return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); | ||
1347 | } | ||
1348 | } | ||
1349 | |||
1350 | static void rt2800pci_clear_entry(struct queue_entry *entry) | ||
1351 | { | ||
1352 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
1353 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
1354 | u32 word; | ||
1355 | |||
1356 | if (entry->queue->qid == QID_RX) { | ||
1357 | rt2x00_desc_read(entry_priv->desc, 0, &word); | ||
1358 | rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); | ||
1359 | rt2x00_desc_write(entry_priv->desc, 0, word); | ||
1360 | |||
1361 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1362 | rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); | ||
1363 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
1364 | } else { | ||
1365 | rt2x00_desc_read(entry_priv->desc, 1, &word); | ||
1366 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); | ||
1367 | rt2x00_desc_write(entry_priv->desc, 1, word); | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1371 | static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | ||
1372 | { | ||
1373 | struct queue_entry_priv_pci *entry_priv; | ||
1374 | u32 reg; | ||
1375 | |||
1376 | rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
1377 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
1378 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
1379 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
1380 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
1381 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
1382 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
1383 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
1384 | rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
1385 | |||
1386 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
1387 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
1388 | |||
1389 | /* | ||
1390 | * Initialize registers. | ||
1391 | */ | ||
1392 | entry_priv = rt2x00dev->tx[0].entries[0].priv_data; | ||
1393 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); | ||
1394 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); | ||
1395 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); | ||
1396 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0); | ||
1397 | |||
1398 | entry_priv = rt2x00dev->tx[1].entries[0].priv_data; | ||
1399 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); | ||
1400 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); | ||
1401 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); | ||
1402 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0); | ||
1403 | |||
1404 | entry_priv = rt2x00dev->tx[2].entries[0].priv_data; | ||
1405 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); | ||
1406 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); | ||
1407 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); | ||
1408 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0); | ||
1409 | |||
1410 | entry_priv = rt2x00dev->tx[3].entries[0].priv_data; | ||
1411 | rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); | ||
1412 | rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); | ||
1413 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); | ||
1414 | rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0); | ||
1415 | |||
1416 | entry_priv = rt2x00dev->rx->entries[0].priv_data; | ||
1417 | rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); | ||
1418 | rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); | ||
1419 | rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); | ||
1420 | rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); | ||
1421 | |||
1422 | /* | ||
1423 | * Enable global DMA configuration | ||
1424 | */ | ||
1425 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
1426 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
1427 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
1428 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
1429 | rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
1430 | |||
1431 | rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); | ||
1432 | |||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) | ||
1437 | { | ||
1438 | u32 reg; | ||
1439 | unsigned int i; | ||
1440 | |||
1441 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
1442 | |||
1443 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
1444 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | ||
1445 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); | ||
1446 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
1447 | |||
1448 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
1449 | |||
1450 | rt2x00pci_register_read(rt2x00dev, BCN_OFFSET0, ®); | ||
1451 | rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ | ||
1452 | rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ | ||
1453 | rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ | ||
1454 | rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ | ||
1455 | rt2x00pci_register_write(rt2x00dev, BCN_OFFSET0, reg); | ||
1456 | |||
1457 | rt2x00pci_register_read(rt2x00dev, BCN_OFFSET1, ®); | ||
1458 | rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ | ||
1459 | rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ | ||
1460 | rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ | ||
1461 | rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ | ||
1462 | rt2x00pci_register_write(rt2x00dev, BCN_OFFSET1, reg); | ||
1463 | |||
1464 | rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); | ||
1465 | rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); | ||
1466 | |||
1467 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); | ||
1468 | |||
1469 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
1470 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); | ||
1471 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); | ||
1472 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); | ||
1473 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); | ||
1474 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
1475 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); | ||
1476 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
1477 | |||
1478 | rt2x00pci_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); | ||
1479 | rt2x00pci_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | ||
1480 | |||
1481 | rt2x00pci_register_read(rt2x00dev, TX_LINK_CFG, ®); | ||
1482 | rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); | ||
1483 | rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); | ||
1484 | rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); | ||
1485 | rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); | ||
1486 | rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); | ||
1487 | rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); | ||
1488 | rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); | ||
1489 | rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); | ||
1490 | rt2x00pci_register_write(rt2x00dev, TX_LINK_CFG, reg); | ||
1491 | |||
1492 | rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | ||
1493 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); | ||
1494 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); | ||
1495 | rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | ||
1496 | |||
1497 | rt2x00pci_register_read(rt2x00dev, MAX_LEN_CFG, ®); | ||
1498 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | ||
1499 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && | ||
1500 | rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) | ||
1501 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | ||
1502 | else | ||
1503 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | ||
1504 | rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); | ||
1505 | rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); | ||
1506 | rt2x00pci_register_write(rt2x00dev, MAX_LEN_CFG, reg); | ||
1507 | |||
1508 | rt2x00pci_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); | ||
1509 | |||
1510 | rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | ||
1511 | rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); | ||
1512 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); | ||
1513 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); | ||
1514 | rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); | ||
1515 | rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); | ||
1516 | rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | ||
1517 | |||
1518 | rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, ®); | ||
1519 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); | ||
1520 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); | ||
1521 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); | ||
1522 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1523 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1524 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1525 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); | ||
1526 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1527 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); | ||
1528 | rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); | ||
1529 | |||
1530 | rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
1531 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); | ||
1532 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); | ||
1533 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); | ||
1534 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1535 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1536 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1537 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); | ||
1538 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1539 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); | ||
1540 | rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
1541 | |||
1542 | rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, ®); | ||
1543 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); | ||
1544 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); | ||
1545 | rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); | ||
1546 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1547 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1548 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1549 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); | ||
1550 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1551 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); | ||
1552 | rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); | ||
1553 | |||
1554 | rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, ®); | ||
1555 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); | ||
1556 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); | ||
1557 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); | ||
1558 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1559 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1560 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1561 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); | ||
1562 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1563 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | ||
1564 | rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); | ||
1565 | |||
1566 | rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, ®); | ||
1567 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); | ||
1568 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); | ||
1569 | rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); | ||
1570 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1571 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1572 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1573 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); | ||
1574 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1575 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); | ||
1576 | rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); | ||
1577 | |||
1578 | rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, ®); | ||
1579 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); | ||
1580 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); | ||
1581 | rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); | ||
1582 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); | ||
1583 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | ||
1584 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); | ||
1585 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); | ||
1586 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); | ||
1587 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | ||
1588 | rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); | ||
1589 | |||
1590 | rt2x00pci_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); | ||
1591 | rt2x00pci_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); | ||
1592 | |||
1593 | rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); | ||
1594 | rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); | ||
1595 | rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, | ||
1596 | IEEE80211_MAX_RTS_THRESHOLD); | ||
1597 | rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); | ||
1598 | rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); | ||
1599 | |||
1600 | rt2x00pci_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); | ||
1601 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | ||
1602 | |||
1603 | /* | ||
1604 | * ASIC will keep garbage value after boot, clear encryption keys. | ||
1605 | */ | ||
1606 | for (i = 0; i < 4; i++) | ||
1607 | rt2x00pci_register_write(rt2x00dev, | ||
1608 | SHARED_KEY_MODE_ENTRY(i), 0); | ||
1609 | |||
1610 | for (i = 0; i < 256; i++) { | ||
1611 | u32 wcid[2] = { 0xffffffff, 0x00ffffff }; | ||
1612 | rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), | ||
1613 | wcid, sizeof(wcid)); | ||
1614 | |||
1615 | rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); | ||
1616 | rt2x00pci_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); | ||
1617 | } | ||
1618 | |||
1619 | /* | ||
1620 | * Clear all beacons | ||
1621 | * For the Beacon base registers we only need to clear | ||
1622 | * the first byte since that byte contains the VALID and OWNER | ||
1623 | * bits which (when set to 0) will invalidate the entire beacon. | ||
1624 | */ | ||
1625 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); | ||
1626 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); | ||
1627 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); | ||
1628 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); | ||
1629 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE4, 0); | ||
1630 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE5, 0); | ||
1631 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE6, 0); | ||
1632 | rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE7, 0); | ||
1633 | |||
1634 | rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG0, ®); | ||
1635 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); | ||
1636 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); | ||
1637 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); | ||
1638 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); | ||
1639 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); | ||
1640 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); | ||
1641 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); | ||
1642 | rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); | ||
1643 | rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG0, reg); | ||
1644 | |||
1645 | rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG1, ®); | ||
1646 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); | ||
1647 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); | ||
1648 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); | ||
1649 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); | ||
1650 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); | ||
1651 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); | ||
1652 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); | ||
1653 | rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); | ||
1654 | rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG1, reg); | ||
1655 | |||
1656 | rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG0, ®); | ||
1657 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); | ||
1658 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); | ||
1659 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); | ||
1660 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); | ||
1661 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); | ||
1662 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); | ||
1663 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); | ||
1664 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); | ||
1665 | rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG0, reg); | ||
1666 | |||
1667 | rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG1, ®); | ||
1668 | rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); | ||
1669 | rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); | ||
1670 | rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); | ||
1671 | rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); | ||
1672 | rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG1, reg); | ||
1673 | |||
1674 | /* | ||
1675 | * We must clear the error counters. | ||
1676 | * These registers are cleared on read, | ||
1677 | * so we may pass a useless variable to store the value. | ||
1678 | */ | ||
1679 | rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, ®); | ||
1680 | rt2x00pci_register_read(rt2x00dev, RX_STA_CNT1, ®); | ||
1681 | rt2x00pci_register_read(rt2x00dev, RX_STA_CNT2, ®); | ||
1682 | rt2x00pci_register_read(rt2x00dev, TX_STA_CNT0, ®); | ||
1683 | rt2x00pci_register_read(rt2x00dev, TX_STA_CNT1, ®); | ||
1684 | rt2x00pci_register_read(rt2x00dev, TX_STA_CNT2, ®); | ||
1685 | |||
1686 | return 0; | ||
1687 | } | ||
1688 | |||
1689 | static int rt2800pci_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) | ||
1690 | { | ||
1691 | unsigned int i; | ||
1692 | u32 reg; | ||
1693 | |||
1694 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1695 | rt2x00pci_register_read(rt2x00dev, MAC_STATUS_CFG, ®); | ||
1696 | if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) | ||
1697 | return 0; | ||
1698 | |||
1699 | udelay(REGISTER_BUSY_DELAY); | ||
1700 | } | ||
1701 | |||
1702 | ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); | ||
1703 | return -EACCES; | ||
1704 | } | ||
1705 | |||
1706 | static int rt2800pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) | ||
1707 | { | ||
1708 | unsigned int i; | ||
1709 | u8 value; | ||
1710 | |||
1711 | /* | ||
1712 | * BBP was enabled after firmware was loaded, | ||
1713 | * but we need to reactivate it now. | ||
1714 | */ | ||
1715 | rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); | ||
1716 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); | ||
1717 | msleep(1); | ||
1718 | |||
1719 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1720 | rt2800pci_bbp_read(rt2x00dev, 0, &value); | ||
1721 | if ((value != 0xff) && (value != 0x00)) | ||
1722 | return 0; | ||
1723 | udelay(REGISTER_BUSY_DELAY); | ||
1724 | } | ||
1725 | |||
1726 | ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); | ||
1727 | return -EACCES; | ||
1728 | } | ||
1729 | |||
1730 | static int rt2800pci_init_bbp(struct rt2x00_dev *rt2x00dev) | ||
1731 | { | ||
1732 | unsigned int i; | ||
1733 | u16 eeprom; | ||
1734 | u8 reg_id; | ||
1735 | u8 value; | ||
1736 | |||
1737 | if (unlikely(rt2800pci_wait_bbp_rf_ready(rt2x00dev) || | ||
1738 | rt2800pci_wait_bbp_ready(rt2x00dev))) | ||
1739 | return -EACCES; | ||
1740 | |||
1741 | rt2800pci_bbp_write(rt2x00dev, 65, 0x2c); | ||
1742 | rt2800pci_bbp_write(rt2x00dev, 66, 0x38); | ||
1743 | rt2800pci_bbp_write(rt2x00dev, 69, 0x12); | ||
1744 | rt2800pci_bbp_write(rt2x00dev, 70, 0x0a); | ||
1745 | rt2800pci_bbp_write(rt2x00dev, 73, 0x10); | ||
1746 | rt2800pci_bbp_write(rt2x00dev, 81, 0x37); | ||
1747 | rt2800pci_bbp_write(rt2x00dev, 82, 0x62); | ||
1748 | rt2800pci_bbp_write(rt2x00dev, 83, 0x6a); | ||
1749 | rt2800pci_bbp_write(rt2x00dev, 84, 0x99); | ||
1750 | rt2800pci_bbp_write(rt2x00dev, 86, 0x00); | ||
1751 | rt2800pci_bbp_write(rt2x00dev, 91, 0x04); | ||
1752 | rt2800pci_bbp_write(rt2x00dev, 92, 0x00); | ||
1753 | rt2800pci_bbp_write(rt2x00dev, 103, 0x00); | ||
1754 | rt2800pci_bbp_write(rt2x00dev, 105, 0x05); | ||
1755 | |||
1756 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | ||
1757 | rt2800pci_bbp_write(rt2x00dev, 69, 0x16); | ||
1758 | rt2800pci_bbp_write(rt2x00dev, 73, 0x12); | ||
1759 | } | ||
1760 | |||
1761 | if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) | ||
1762 | rt2800pci_bbp_write(rt2x00dev, 84, 0x19); | ||
1763 | |||
1764 | if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { | ||
1765 | rt2800pci_bbp_write(rt2x00dev, 31, 0x08); | ||
1766 | rt2800pci_bbp_write(rt2x00dev, 78, 0x0e); | ||
1767 | rt2800pci_bbp_write(rt2x00dev, 80, 0x08); | ||
1768 | } | ||
1769 | |||
1770 | for (i = 0; i < EEPROM_BBP_SIZE; i++) { | ||
1771 | rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); | ||
1772 | |||
1773 | if (eeprom != 0xffff && eeprom != 0x0000) { | ||
1774 | reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); | ||
1775 | value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); | ||
1776 | rt2800pci_bbp_write(rt2x00dev, reg_id, value); | ||
1777 | } | ||
1778 | } | ||
1779 | |||
1780 | return 0; | ||
1781 | } | ||
1782 | |||
1783 | static u8 rt2800pci_init_rx_filter(struct rt2x00_dev *rt2x00dev, | ||
1784 | bool bw40, u8 rfcsr24, u8 filter_target) | ||
1785 | { | ||
1786 | unsigned int i; | ||
1787 | u8 bbp; | ||
1788 | u8 rfcsr; | ||
1789 | u8 passband; | ||
1790 | u8 stopband; | ||
1791 | u8 overtuned = 0; | ||
1792 | |||
1793 | rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); | ||
1794 | |||
1795 | rt2800pci_bbp_read(rt2x00dev, 4, &bbp); | ||
1796 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); | ||
1797 | rt2800pci_bbp_write(rt2x00dev, 4, bbp); | ||
1798 | |||
1799 | rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr); | ||
1800 | rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); | ||
1801 | rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr); | ||
1802 | |||
1803 | /* | ||
1804 | * Set power & frequency of passband test tone | ||
1805 | */ | ||
1806 | rt2800pci_bbp_write(rt2x00dev, 24, 0); | ||
1807 | |||
1808 | for (i = 0; i < 100; i++) { | ||
1809 | rt2800pci_bbp_write(rt2x00dev, 25, 0x90); | ||
1810 | msleep(1); | ||
1811 | |||
1812 | rt2800pci_bbp_read(rt2x00dev, 55, &passband); | ||
1813 | if (passband) | ||
1814 | break; | ||
1815 | } | ||
1816 | |||
1817 | /* | ||
1818 | * Set power & frequency of stopband test tone | ||
1819 | */ | ||
1820 | rt2800pci_bbp_write(rt2x00dev, 24, 0x06); | ||
1821 | |||
1822 | for (i = 0; i < 100; i++) { | ||
1823 | rt2800pci_bbp_write(rt2x00dev, 25, 0x90); | ||
1824 | msleep(1); | ||
1825 | |||
1826 | rt2800pci_bbp_read(rt2x00dev, 55, &stopband); | ||
1827 | |||
1828 | if ((passband - stopband) <= filter_target) { | ||
1829 | rfcsr24++; | ||
1830 | overtuned += ((passband - stopband) == filter_target); | ||
1831 | } else | ||
1832 | break; | ||
1833 | |||
1834 | rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); | ||
1835 | } | ||
1836 | |||
1837 | rfcsr24 -= !!overtuned; | ||
1838 | |||
1839 | rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24); | ||
1840 | return rfcsr24; | ||
1841 | } | ||
1842 | |||
1843 | static int rt2800pci_init_rfcsr(struct rt2x00_dev *rt2x00dev) | ||
1844 | { | ||
1845 | u8 rfcsr; | ||
1846 | u8 bbp; | ||
1847 | |||
1848 | if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && | ||
1849 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | ||
1850 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) | ||
1851 | return 0; | ||
1852 | |||
1853 | /* | ||
1854 | * Init RF calibration. | ||
1855 | */ | ||
1856 | rt2800pci_rfcsr_read(rt2x00dev, 30, &rfcsr); | ||
1857 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); | ||
1858 | rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1859 | msleep(1); | ||
1860 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | ||
1861 | rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr); | ||
1862 | |||
1863 | rt2800pci_rfcsr_write(rt2x00dev, 0, 0x50); | ||
1864 | rt2800pci_rfcsr_write(rt2x00dev, 1, 0x01); | ||
1865 | rt2800pci_rfcsr_write(rt2x00dev, 2, 0xf7); | ||
1866 | rt2800pci_rfcsr_write(rt2x00dev, 3, 0x75); | ||
1867 | rt2800pci_rfcsr_write(rt2x00dev, 4, 0x40); | ||
1868 | rt2800pci_rfcsr_write(rt2x00dev, 5, 0x03); | ||
1869 | rt2800pci_rfcsr_write(rt2x00dev, 6, 0x02); | ||
1870 | rt2800pci_rfcsr_write(rt2x00dev, 7, 0x50); | ||
1871 | rt2800pci_rfcsr_write(rt2x00dev, 8, 0x39); | ||
1872 | rt2800pci_rfcsr_write(rt2x00dev, 9, 0x0f); | ||
1873 | rt2800pci_rfcsr_write(rt2x00dev, 10, 0x60); | ||
1874 | rt2800pci_rfcsr_write(rt2x00dev, 11, 0x21); | ||
1875 | rt2800pci_rfcsr_write(rt2x00dev, 12, 0x75); | ||
1876 | rt2800pci_rfcsr_write(rt2x00dev, 13, 0x75); | ||
1877 | rt2800pci_rfcsr_write(rt2x00dev, 14, 0x90); | ||
1878 | rt2800pci_rfcsr_write(rt2x00dev, 15, 0x58); | ||
1879 | rt2800pci_rfcsr_write(rt2x00dev, 16, 0xb3); | ||
1880 | rt2800pci_rfcsr_write(rt2x00dev, 17, 0x92); | ||
1881 | rt2800pci_rfcsr_write(rt2x00dev, 18, 0x2c); | ||
1882 | rt2800pci_rfcsr_write(rt2x00dev, 19, 0x02); | ||
1883 | rt2800pci_rfcsr_write(rt2x00dev, 20, 0xba); | ||
1884 | rt2800pci_rfcsr_write(rt2x00dev, 21, 0xdb); | ||
1885 | rt2800pci_rfcsr_write(rt2x00dev, 22, 0x00); | ||
1886 | rt2800pci_rfcsr_write(rt2x00dev, 23, 0x31); | ||
1887 | rt2800pci_rfcsr_write(rt2x00dev, 24, 0x08); | ||
1888 | rt2800pci_rfcsr_write(rt2x00dev, 25, 0x01); | ||
1889 | rt2800pci_rfcsr_write(rt2x00dev, 26, 0x25); | ||
1890 | rt2800pci_rfcsr_write(rt2x00dev, 27, 0x23); | ||
1891 | rt2800pci_rfcsr_write(rt2x00dev, 28, 0x13); | ||
1892 | rt2800pci_rfcsr_write(rt2x00dev, 29, 0x83); | ||
1893 | |||
1894 | /* | ||
1895 | * Set RX Filter calibration for 20MHz and 40MHz | ||
1896 | */ | ||
1897 | rt2x00dev->calibration[0] = | ||
1898 | rt2800pci_init_rx_filter(rt2x00dev, false, 0x07, 0x16); | ||
1899 | rt2x00dev->calibration[1] = | ||
1900 | rt2800pci_init_rx_filter(rt2x00dev, true, 0x27, 0x19); | ||
1901 | |||
1902 | /* | ||
1903 | * Set back to initial state | ||
1904 | */ | ||
1905 | rt2800pci_bbp_write(rt2x00dev, 24, 0); | ||
1906 | |||
1907 | rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr); | ||
1908 | rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); | ||
1909 | rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr); | ||
1910 | |||
1911 | /* | ||
1912 | * set BBP back to BW20 | ||
1913 | */ | ||
1914 | rt2800pci_bbp_read(rt2x00dev, 4, &bbp); | ||
1915 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); | ||
1916 | rt2800pci_bbp_write(rt2x00dev, 4, bbp); | ||
1917 | |||
1918 | return 0; | ||
1919 | } | ||
1920 | |||
1921 | /* | ||
1922 | * Device state switch handlers. | ||
1923 | */ | ||
1924 | static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, | ||
1925 | enum dev_state state) | ||
1926 | { | ||
1927 | u32 reg; | ||
1928 | |||
1929 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
1930 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, | ||
1931 | (state == STATE_RADIO_RX_ON) || | ||
1932 | (state == STATE_RADIO_RX_ON_LINK)); | ||
1933 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
1934 | } | ||
1935 | |||
1936 | static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, | ||
1937 | enum dev_state state) | ||
1938 | { | ||
1939 | int mask = (state == STATE_RADIO_IRQ_ON); | ||
1940 | u32 reg; | ||
1941 | |||
1942 | /* | ||
1943 | * When interrupts are being enabled, the interrupt registers | ||
1944 | * should clear the register to assure a clean state. | ||
1945 | */ | ||
1946 | if (state == STATE_RADIO_IRQ_ON) { | ||
1947 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
1948 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
1949 | } | ||
1950 | |||
1951 | rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); | ||
1952 | rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, mask); | ||
1953 | rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, mask); | ||
1954 | rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); | ||
1955 | rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, mask); | ||
1956 | rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, mask); | ||
1957 | rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, mask); | ||
1958 | rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, mask); | ||
1959 | rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, mask); | ||
1960 | rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, mask); | ||
1961 | rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, mask); | ||
1962 | rt2x00_set_field32(®, INT_MASK_CSR_RXTX_COHERENT, mask); | ||
1963 | rt2x00_set_field32(®, INT_MASK_CSR_TBTT, mask); | ||
1964 | rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, mask); | ||
1965 | rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, mask); | ||
1966 | rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, mask); | ||
1967 | rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, mask); | ||
1968 | rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, mask); | ||
1969 | rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, mask); | ||
1970 | rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); | ||
1971 | } | ||
1972 | |||
1973 | static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) | ||
1974 | { | ||
1975 | unsigned int i; | ||
1976 | u32 reg; | ||
1977 | |||
1978 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
1979 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
1980 | if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && | ||
1981 | !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) | ||
1982 | return 0; | ||
1983 | |||
1984 | msleep(1); | ||
1985 | } | ||
1986 | |||
1987 | ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); | ||
1988 | return -EACCES; | ||
1989 | } | ||
1990 | |||
1991 | static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | ||
1992 | { | ||
1993 | u32 reg; | ||
1994 | u16 word; | ||
1995 | |||
1996 | /* | ||
1997 | * Initialize all registers. | ||
1998 | */ | ||
1999 | if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || | ||
2000 | rt2800pci_init_queues(rt2x00dev) || | ||
2001 | rt2800pci_init_registers(rt2x00dev) || | ||
2002 | rt2800pci_wait_wpdma_ready(rt2x00dev) || | ||
2003 | rt2800pci_init_bbp(rt2x00dev) || | ||
2004 | rt2800pci_init_rfcsr(rt2x00dev))) | ||
2005 | return -EIO; | ||
2006 | |||
2007 | /* | ||
2008 | * Send signal to firmware during boot time. | ||
2009 | */ | ||
2010 | rt2800pci_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); | ||
2011 | |||
2012 | /* | ||
2013 | * Enable RX. | ||
2014 | */ | ||
2015 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
2016 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); | ||
2017 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | ||
2018 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
2019 | |||
2020 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
2021 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); | ||
2022 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); | ||
2023 | rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2); | ||
2024 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
2025 | rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
2026 | |||
2027 | rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | ||
2028 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); | ||
2029 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); | ||
2030 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | ||
2031 | |||
2032 | /* | ||
2033 | * Initialize LED control | ||
2034 | */ | ||
2035 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); | ||
2036 | rt2800pci_mcu_request(rt2x00dev, MCU_LED_1, 0xff, | ||
2037 | word & 0xff, (word >> 8) & 0xff); | ||
2038 | |||
2039 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); | ||
2040 | rt2800pci_mcu_request(rt2x00dev, MCU_LED_2, 0xff, | ||
2041 | word & 0xff, (word >> 8) & 0xff); | ||
2042 | |||
2043 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); | ||
2044 | rt2800pci_mcu_request(rt2x00dev, MCU_LED_3, 0xff, | ||
2045 | word & 0xff, (word >> 8) & 0xff); | ||
2046 | |||
2047 | return 0; | ||
2048 | } | ||
2049 | |||
2050 | static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | ||
2051 | { | ||
2052 | u32 reg; | ||
2053 | |||
2054 | rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
2055 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
2056 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
2057 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
2058 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
2059 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
2060 | rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
2061 | |||
2062 | rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0); | ||
2063 | rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
2064 | rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
2065 | |||
2066 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); | ||
2067 | |||
2068 | rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
2069 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
2070 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
2071 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
2072 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
2073 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
2074 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
2075 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
2076 | rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
2077 | |||
2078 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
2079 | rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
2080 | |||
2081 | /* Wait for DMA, ignore error */ | ||
2082 | rt2800pci_wait_wpdma_ready(rt2x00dev); | ||
2083 | } | ||
2084 | |||
2085 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | ||
2086 | enum dev_state state) | ||
2087 | { | ||
2088 | /* | ||
2089 | * Always put the device to sleep (even when we intend to wakeup!) | ||
2090 | * if the device is booting and wasn't asleep it will return | ||
2091 | * failure when attempting to wakeup. | ||
2092 | */ | ||
2093 | rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); | ||
2094 | |||
2095 | if (state == STATE_AWAKE) { | ||
2096 | rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); | ||
2097 | rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); | ||
2098 | } | ||
2099 | |||
2100 | return 0; | ||
2101 | } | ||
2102 | |||
2103 | static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | ||
2104 | enum dev_state state) | ||
2105 | { | ||
2106 | int retval = 0; | ||
2107 | |||
2108 | switch (state) { | ||
2109 | case STATE_RADIO_ON: | ||
2110 | /* | ||
2111 | * Before the radio can be enabled, the device first has | ||
2112 | * to be woken up. After that it needs a bit of time | ||
2113 | * to be fully awake and then the radio can be enabled. | ||
2114 | */ | ||
2115 | rt2800pci_set_state(rt2x00dev, STATE_AWAKE); | ||
2116 | msleep(1); | ||
2117 | retval = rt2800pci_enable_radio(rt2x00dev); | ||
2118 | break; | ||
2119 | case STATE_RADIO_OFF: | ||
2120 | /* | ||
2121 | * After the radio has been disabled, the device should | ||
2122 | * be put to sleep for powersaving. | ||
2123 | */ | ||
2124 | rt2800pci_disable_radio(rt2x00dev); | ||
2125 | rt2800pci_set_state(rt2x00dev, STATE_SLEEP); | ||
2126 | break; | ||
2127 | case STATE_RADIO_RX_ON: | ||
2128 | case STATE_RADIO_RX_ON_LINK: | ||
2129 | case STATE_RADIO_RX_OFF: | ||
2130 | case STATE_RADIO_RX_OFF_LINK: | ||
2131 | rt2800pci_toggle_rx(rt2x00dev, state); | ||
2132 | break; | ||
2133 | case STATE_RADIO_IRQ_ON: | ||
2134 | case STATE_RADIO_IRQ_OFF: | ||
2135 | rt2800pci_toggle_irq(rt2x00dev, state); | ||
2136 | break; | ||
2137 | case STATE_DEEP_SLEEP: | ||
2138 | case STATE_SLEEP: | ||
2139 | case STATE_STANDBY: | ||
2140 | case STATE_AWAKE: | ||
2141 | retval = rt2800pci_set_state(rt2x00dev, state); | ||
2142 | break; | ||
2143 | default: | ||
2144 | retval = -ENOTSUPP; | ||
2145 | break; | ||
2146 | } | ||
2147 | |||
2148 | if (unlikely(retval)) | ||
2149 | ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", | ||
2150 | state, retval); | ||
2151 | |||
2152 | return retval; | ||
2153 | } | ||
2154 | |||
2155 | /* | ||
2156 | * TX descriptor initialization | ||
2157 | */ | ||
2158 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | ||
2159 | struct sk_buff *skb, | ||
2160 | struct txentry_desc *txdesc) | ||
2161 | { | ||
2162 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | ||
2163 | __le32 *txd = skbdesc->desc; | ||
2164 | __le32 *txwi = (__le32 *)(skb->data - rt2x00dev->hw->extra_tx_headroom); | ||
2165 | u32 word; | ||
2166 | |||
2167 | /* | ||
2168 | * Initialize TX Info descriptor | ||
2169 | */ | ||
2170 | rt2x00_desc_read(txwi, 0, &word); | ||
2171 | rt2x00_set_field32(&word, TXWI_W0_FRAG, | ||
2172 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
2173 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); | ||
2174 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); | ||
2175 | rt2x00_set_field32(&word, TXWI_W0_TS, | ||
2176 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); | ||
2177 | rt2x00_set_field32(&word, TXWI_W0_AMPDU, | ||
2178 | test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); | ||
2179 | rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); | ||
2180 | rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); | ||
2181 | rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); | ||
2182 | rt2x00_set_field32(&word, TXWI_W0_BW, | ||
2183 | test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); | ||
2184 | rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, | ||
2185 | test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); | ||
2186 | rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); | ||
2187 | rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); | ||
2188 | rt2x00_desc_write(txwi, 0, word); | ||
2189 | |||
2190 | rt2x00_desc_read(txwi, 1, &word); | ||
2191 | rt2x00_set_field32(&word, TXWI_W1_ACK, | ||
2192 | test_bit(ENTRY_TXD_ACK, &txdesc->flags)); | ||
2193 | rt2x00_set_field32(&word, TXWI_W1_NSEQ, | ||
2194 | test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); | ||
2195 | rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); | ||
2196 | rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, | ||
2197 | test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? | ||
2198 | (skbdesc->entry->entry_idx + 1) : 0xff); | ||
2199 | rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, | ||
2200 | skb->len - txdesc->l2pad); | ||
2201 | rt2x00_set_field32(&word, TXWI_W1_PACKETID, | ||
2202 | skbdesc->entry->queue->qid + 1); | ||
2203 | rt2x00_desc_write(txwi, 1, word); | ||
2204 | |||
2205 | /* | ||
2206 | * Always write 0 to IV/EIV fields, hardware will insert the IV | ||
2207 | * from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0. | ||
2208 | * When ENTRY_TXD_ENCRYPT_IV is set to 1 it will use the IV data | ||
2209 | * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which | ||
2210 | * crypto entry in the registers should be used to encrypt the frame. | ||
2211 | */ | ||
2212 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); | ||
2213 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); | ||
2214 | |||
2215 | /* | ||
2216 | * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 | ||
2217 | * must contains a TXWI structure + 802.11 header + padding + 802.11 | ||
2218 | * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and | ||
2219 | * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 | ||
2220 | * data. It means that LAST_SEC0 is always 0. | ||
2221 | */ | ||
2222 | |||
2223 | /* | ||
2224 | * Initialize TX descriptor | ||
2225 | */ | ||
2226 | rt2x00_desc_read(txd, 0, &word); | ||
2227 | rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); | ||
2228 | rt2x00_desc_write(txd, 0, word); | ||
2229 | |||
2230 | rt2x00_desc_read(txd, 1, &word); | ||
2231 | rt2x00_set_field32(&word, TXD_W1_SD_LEN1, skb->len); | ||
2232 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, | ||
2233 | !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | ||
2234 | rt2x00_set_field32(&word, TXD_W1_BURST, | ||
2235 | test_bit(ENTRY_TXD_BURST, &txdesc->flags)); | ||
2236 | rt2x00_set_field32(&word, TXD_W1_SD_LEN0, | ||
2237 | rt2x00dev->hw->extra_tx_headroom); | ||
2238 | rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); | ||
2239 | rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); | ||
2240 | rt2x00_desc_write(txd, 1, word); | ||
2241 | |||
2242 | rt2x00_desc_read(txd, 2, &word); | ||
2243 | rt2x00_set_field32(&word, TXD_W2_SD_PTR1, | ||
2244 | skbdesc->skb_dma + rt2x00dev->hw->extra_tx_headroom); | ||
2245 | rt2x00_desc_write(txd, 2, word); | ||
2246 | |||
2247 | rt2x00_desc_read(txd, 3, &word); | ||
2248 | rt2x00_set_field32(&word, TXD_W3_WIV, | ||
2249 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | ||
2250 | rt2x00_set_field32(&word, TXD_W3_QSEL, 2); | ||
2251 | rt2x00_desc_write(txd, 3, word); | ||
2252 | } | ||
2253 | |||
2254 | /* | ||
2255 | * TX data initialization | ||
2256 | */ | ||
2257 | static void rt2800pci_write_beacon(struct queue_entry *entry) | ||
2258 | { | ||
2259 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
2260 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
2261 | unsigned int beacon_base; | ||
2262 | u32 reg; | ||
2263 | |||
2264 | /* | ||
2265 | * Disable beaconing while we are reloading the beacon data, | ||
2266 | * otherwise we might be sending out invalid data. | ||
2267 | */ | ||
2268 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
2269 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); | ||
2270 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
2271 | |||
2272 | /* | ||
2273 | * Write entire beacon with descriptor to register. | ||
2274 | */ | ||
2275 | beacon_base = HW_BEACON_OFFSET(entry->entry_idx); | ||
2276 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
2277 | beacon_base, | ||
2278 | skbdesc->desc, skbdesc->desc_len); | ||
2279 | rt2x00pci_register_multiwrite(rt2x00dev, | ||
2280 | beacon_base + skbdesc->desc_len, | ||
2281 | entry->skb->data, entry->skb->len); | ||
2282 | |||
2283 | /* | ||
2284 | * Clean up beacon skb. | ||
2285 | */ | ||
2286 | dev_kfree_skb_any(entry->skb); | ||
2287 | entry->skb = NULL; | ||
2288 | } | ||
2289 | |||
2290 | static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | ||
2291 | const enum data_queue_qid queue_idx) | ||
2292 | { | ||
2293 | struct data_queue *queue; | ||
2294 | unsigned int idx, qidx = 0; | ||
2295 | u32 reg; | ||
2296 | |||
2297 | if (queue_idx == QID_BEACON) { | ||
2298 | rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); | ||
2299 | if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { | ||
2300 | rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); | ||
2301 | rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); | ||
2302 | rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); | ||
2303 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); | ||
2304 | } | ||
2305 | return; | ||
2306 | } | ||
2307 | |||
2308 | if (queue_idx > QID_HCCA && queue_idx != QID_MGMT) | ||
2309 | return; | ||
2310 | |||
2311 | queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); | ||
2312 | idx = queue->index[Q_INDEX]; | ||
2313 | |||
2314 | if (queue_idx == QID_MGMT) | ||
2315 | qidx = 5; | ||
2316 | else | ||
2317 | qidx = queue_idx; | ||
2318 | |||
2319 | rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); | ||
2320 | } | ||
2321 | |||
2322 | static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, | ||
2323 | const enum data_queue_qid qid) | ||
2324 | { | ||
2325 | u32 reg; | ||
2326 | |||
2327 | if (qid == QID_BEACON) { | ||
2328 | rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, 0); | ||
2329 | return; | ||
2330 | } | ||
2331 | |||
2332 | rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
2333 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE)); | ||
2334 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK)); | ||
2335 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI)); | ||
2336 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO)); | ||
2337 | rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
2338 | } | ||
2339 | |||
2340 | /* | ||
2341 | * RX control handlers | ||
2342 | */ | ||
2343 | static void rt2800pci_fill_rxdone(struct queue_entry *entry, | ||
2344 | struct rxdone_entry_desc *rxdesc) | ||
2345 | { | ||
2346 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
2347 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
2348 | struct queue_entry_priv_pci *entry_priv = entry->priv_data; | ||
2349 | __le32 *rxd = entry_priv->desc; | ||
2350 | __le32 *rxwi = (__le32 *)entry->skb->data; | ||
2351 | u32 rxd3; | ||
2352 | u32 rxwi0; | ||
2353 | u32 rxwi1; | ||
2354 | u32 rxwi2; | ||
2355 | u32 rxwi3; | ||
2356 | |||
2357 | rt2x00_desc_read(rxd, 3, &rxd3); | ||
2358 | rt2x00_desc_read(rxwi, 0, &rxwi0); | ||
2359 | rt2x00_desc_read(rxwi, 1, &rxwi1); | ||
2360 | rt2x00_desc_read(rxwi, 2, &rxwi2); | ||
2361 | rt2x00_desc_read(rxwi, 3, &rxwi3); | ||
2362 | |||
2363 | if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR)) | ||
2364 | rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; | ||
2365 | |||
2366 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { | ||
2367 | /* | ||
2368 | * Unfortunately we don't know the cipher type used during | ||
2369 | * decryption. This prevents us from correct providing | ||
2370 | * correct statistics through debugfs. | ||
2371 | */ | ||
2372 | rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); | ||
2373 | rxdesc->cipher_status = | ||
2374 | rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); | ||
2375 | } | ||
2376 | |||
2377 | if (rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED)) { | ||
2378 | /* | ||
2379 | * Hardware has stripped IV/EIV data from 802.11 frame during | ||
2380 | * decryption. Unfortunately the descriptor doesn't contain | ||
2381 | * any fields with the EIV/IV data either, so they can't | ||
2382 | * be restored by rt2x00lib. | ||
2383 | */ | ||
2384 | rxdesc->flags |= RX_FLAG_IV_STRIPPED; | ||
2385 | |||
2386 | if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) | ||
2387 | rxdesc->flags |= RX_FLAG_DECRYPTED; | ||
2388 | else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) | ||
2389 | rxdesc->flags |= RX_FLAG_MMIC_ERROR; | ||
2390 | } | ||
2391 | |||
2392 | if (rt2x00_get_field32(rxd3, RXD_W3_MY_BSS)) | ||
2393 | rxdesc->dev_flags |= RXDONE_MY_BSS; | ||
2394 | |||
2395 | if (rt2x00_get_field32(rxd3, RXD_W3_L2PAD)) { | ||
2396 | rxdesc->dev_flags |= RXDONE_L2PAD; | ||
2397 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
2398 | } | ||
2399 | |||
2400 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | ||
2401 | rxdesc->flags |= RX_FLAG_SHORT_GI; | ||
2402 | |||
2403 | if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) | ||
2404 | rxdesc->flags |= RX_FLAG_40MHZ; | ||
2405 | |||
2406 | /* | ||
2407 | * Detect RX rate, always use MCS as signal type. | ||
2408 | */ | ||
2409 | rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; | ||
2410 | rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); | ||
2411 | rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); | ||
2412 | |||
2413 | /* | ||
2414 | * Mask of 0x8 bit to remove the short preamble flag. | ||
2415 | */ | ||
2416 | if (rxdesc->rate_mode == RATE_MODE_CCK) | ||
2417 | rxdesc->signal &= ~0x8; | ||
2418 | |||
2419 | rxdesc->rssi = | ||
2420 | (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + | ||
2421 | rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; | ||
2422 | |||
2423 | rxdesc->noise = | ||
2424 | (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + | ||
2425 | rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; | ||
2426 | |||
2427 | rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); | ||
2428 | |||
2429 | /* | ||
2430 | * Set RX IDX in register to inform hardware that we have handled | ||
2431 | * this entry and it is available for reuse again. | ||
2432 | */ | ||
2433 | rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx); | ||
2434 | |||
2435 | /* | ||
2436 | * Remove TXWI descriptor from start of buffer. | ||
2437 | */ | ||
2438 | skb_pull(entry->skb, RXWI_DESC_SIZE); | ||
2439 | skb_trim(entry->skb, rxdesc->size); | ||
2440 | } | ||
2441 | |||
2442 | /* | ||
2443 | * Interrupt functions. | ||
2444 | */ | ||
2445 | static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
2446 | { | ||
2447 | struct data_queue *queue; | ||
2448 | struct queue_entry *entry; | ||
2449 | struct queue_entry *entry_done; | ||
2450 | struct queue_entry_priv_pci *entry_priv; | ||
2451 | struct txdone_entry_desc txdesc; | ||
2452 | u32 word; | ||
2453 | u32 reg; | ||
2454 | u32 old_reg; | ||
2455 | unsigned int type; | ||
2456 | unsigned int index; | ||
2457 | u16 mcs, real_mcs; | ||
2458 | |||
2459 | /* | ||
2460 | * During each loop we will compare the freshly read | ||
2461 | * TX_STA_FIFO register value with the value read from | ||
2462 | * the previous loop. If the 2 values are equal then | ||
2463 | * we should stop processing because the chance it | ||
2464 | * quite big that the device has been unplugged and | ||
2465 | * we risk going into an endless loop. | ||
2466 | */ | ||
2467 | old_reg = 0; | ||
2468 | |||
2469 | while (1) { | ||
2470 | rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
2471 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
2472 | break; | ||
2473 | |||
2474 | if (old_reg == reg) | ||
2475 | break; | ||
2476 | old_reg = reg; | ||
2477 | |||
2478 | /* | ||
2479 | * Skip this entry when it contains an invalid | ||
2480 | * queue identication number. | ||
2481 | */ | ||
2482 | type = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE) - 1; | ||
2483 | if (type >= QID_RX) | ||
2484 | continue; | ||
2485 | |||
2486 | queue = rt2x00queue_get_queue(rt2x00dev, type); | ||
2487 | if (unlikely(!queue)) | ||
2488 | continue; | ||
2489 | |||
2490 | /* | ||
2491 | * Skip this entry when it contains an invalid | ||
2492 | * index number. | ||
2493 | */ | ||
2494 | index = rt2x00_get_field32(reg, TX_STA_FIFO_WCID) - 1; | ||
2495 | if (unlikely(index >= queue->limit)) | ||
2496 | continue; | ||
2497 | |||
2498 | entry = &queue->entries[index]; | ||
2499 | entry_priv = entry->priv_data; | ||
2500 | rt2x00_desc_read((__le32 *)entry->skb->data, 0, &word); | ||
2501 | |||
2502 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
2503 | while (entry != entry_done) { | ||
2504 | /* | ||
2505 | * Catch up. | ||
2506 | * Just report any entries we missed as failed. | ||
2507 | */ | ||
2508 | WARNING(rt2x00dev, | ||
2509 | "TX status report missed for entry %d\n", | ||
2510 | entry_done->entry_idx); | ||
2511 | |||
2512 | txdesc.flags = 0; | ||
2513 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
2514 | txdesc.retry = 0; | ||
2515 | |||
2516 | rt2x00lib_txdone(entry_done, &txdesc); | ||
2517 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
2518 | } | ||
2519 | |||
2520 | /* | ||
2521 | * Obtain the status about this packet. | ||
2522 | */ | ||
2523 | txdesc.flags = 0; | ||
2524 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) | ||
2525 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
2526 | else | ||
2527 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
2528 | |||
2529 | /* | ||
2530 | * Ralink has a retry mechanism using a global fallback | ||
2531 | * table. We setup this fallback table to try immediate | ||
2532 | * lower rate for all rates. In the TX_STA_FIFO, | ||
2533 | * the MCS field contains the MCS used for the successfull | ||
2534 | * transmission. If the first transmission succeed, | ||
2535 | * we have mcs == tx_mcs. On the second transmission, | ||
2536 | * we have mcs = tx_mcs - 1. So the number of | ||
2537 | * retry is (tx_mcs - mcs). | ||
2538 | */ | ||
2539 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
2540 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
2541 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
2542 | txdesc.retry = mcs - min(mcs, real_mcs); | ||
2543 | |||
2544 | rt2x00lib_txdone(entry, &txdesc); | ||
2545 | } | ||
2546 | } | ||
2547 | |||
2548 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | ||
2549 | { | ||
2550 | struct rt2x00_dev *rt2x00dev = dev_instance; | ||
2551 | u32 reg; | ||
2552 | |||
2553 | /* Read status and ACK all interrupts */ | ||
2554 | rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); | ||
2555 | rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); | ||
2556 | |||
2557 | if (!reg) | ||
2558 | return IRQ_NONE; | ||
2559 | |||
2560 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) | ||
2561 | return IRQ_HANDLED; | ||
2562 | |||
2563 | /* | ||
2564 | * 1 - Rx ring done interrupt. | ||
2565 | */ | ||
2566 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) | ||
2567 | rt2x00pci_rxdone(rt2x00dev); | ||
2568 | |||
2569 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | ||
2570 | rt2800pci_txdone(rt2x00dev); | ||
2571 | |||
2572 | return IRQ_HANDLED; | ||
2573 | } | ||
2574 | |||
2575 | /* | ||
2576 | * Device probe functions. | ||
2577 | */ | ||
2578 | static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) | ||
2579 | { | ||
2580 | u16 word; | ||
2581 | u8 *mac; | ||
2582 | u8 default_lna_gain; | ||
2583 | |||
2584 | /* | ||
2585 | * Read EEPROM into buffer | ||
2586 | */ | ||
2587 | switch(rt2x00dev->chip.rt) { | ||
2588 | case RT2880: | ||
2589 | case RT3052: | ||
2590 | rt2800pci_read_eeprom_soc(rt2x00dev); | ||
2591 | break; | ||
2592 | case RT3090: | ||
2593 | rt2800pci_read_eeprom_efuse(rt2x00dev); | ||
2594 | break; | ||
2595 | default: | ||
2596 | rt2800pci_read_eeprom_pci(rt2x00dev); | ||
2597 | break; | ||
2598 | } | ||
2599 | |||
2600 | /* | ||
2601 | * Start validation of the data that has been read. | ||
2602 | */ | ||
2603 | mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); | ||
2604 | if (!is_valid_ether_addr(mac)) { | ||
2605 | random_ether_addr(mac); | ||
2606 | EEPROM(rt2x00dev, "MAC: %pM\n", mac); | ||
2607 | } | ||
2608 | |||
2609 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); | ||
2610 | if (word == 0xffff) { | ||
2611 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); | ||
2612 | rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); | ||
2613 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); | ||
2614 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | ||
2615 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | ||
2616 | } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { | ||
2617 | /* | ||
2618 | * There is a max of 2 RX streams for RT2860 series | ||
2619 | */ | ||
2620 | if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) | ||
2621 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); | ||
2622 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | ||
2623 | } | ||
2624 | |||
2625 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); | ||
2626 | if (word == 0xffff) { | ||
2627 | rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); | ||
2628 | rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); | ||
2629 | rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); | ||
2630 | rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); | ||
2631 | rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); | ||
2632 | rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); | ||
2633 | rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); | ||
2634 | rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); | ||
2635 | rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); | ||
2636 | rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); | ||
2637 | rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); | ||
2638 | EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); | ||
2639 | } | ||
2640 | |||
2641 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); | ||
2642 | if ((word & 0x00ff) == 0x00ff) { | ||
2643 | rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); | ||
2644 | rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, | ||
2645 | LED_MODE_TXRX_ACTIVITY); | ||
2646 | rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); | ||
2647 | rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); | ||
2648 | rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); | ||
2649 | rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); | ||
2650 | rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); | ||
2651 | EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); | ||
2652 | } | ||
2653 | |||
2654 | /* | ||
2655 | * During the LNA validation we are going to use | ||
2656 | * lna0 as correct value. Note that EEPROM_LNA | ||
2657 | * is never validated. | ||
2658 | */ | ||
2659 | rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); | ||
2660 | default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); | ||
2661 | |||
2662 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); | ||
2663 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) | ||
2664 | rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); | ||
2665 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) | ||
2666 | rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); | ||
2667 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); | ||
2668 | |||
2669 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); | ||
2670 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) | ||
2671 | rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); | ||
2672 | if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || | ||
2673 | rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) | ||
2674 | rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, | ||
2675 | default_lna_gain); | ||
2676 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); | ||
2677 | |||
2678 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); | ||
2679 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) | ||
2680 | rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); | ||
2681 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) | ||
2682 | rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); | ||
2683 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); | ||
2684 | |||
2685 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); | ||
2686 | if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) | ||
2687 | rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); | ||
2688 | if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || | ||
2689 | rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) | ||
2690 | rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, | ||
2691 | default_lna_gain); | ||
2692 | rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); | ||
2693 | |||
2694 | return 0; | ||
2695 | } | ||
2696 | |||
2697 | static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | ||
2698 | { | ||
2699 | u32 reg; | ||
2700 | u16 value; | ||
2701 | u16 eeprom; | ||
2702 | |||
2703 | /* | ||
2704 | * Read EEPROM word for configuration. | ||
2705 | */ | ||
2706 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | ||
2707 | |||
2708 | /* | ||
2709 | * Identify RF chipset. | ||
2710 | */ | ||
2711 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | ||
2712 | rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); | ||
2713 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | ||
2714 | |||
2715 | if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && | ||
2716 | !rt2x00_rf(&rt2x00dev->chip, RF2850) && | ||
2717 | !rt2x00_rf(&rt2x00dev->chip, RF2720) && | ||
2718 | !rt2x00_rf(&rt2x00dev->chip, RF2750) && | ||
2719 | !rt2x00_rf(&rt2x00dev->chip, RF3020) && | ||
2720 | !rt2x00_rf(&rt2x00dev->chip, RF2020) && | ||
2721 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | ||
2722 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) { | ||
2723 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | ||
2724 | return -ENODEV; | ||
2725 | } | ||
2726 | |||
2727 | /* | ||
2728 | * Identify default antenna configuration. | ||
2729 | */ | ||
2730 | rt2x00dev->default_ant.tx = | ||
2731 | rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); | ||
2732 | rt2x00dev->default_ant.rx = | ||
2733 | rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); | ||
2734 | |||
2735 | /* | ||
2736 | * Read frequency offset and RF programming sequence. | ||
2737 | */ | ||
2738 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); | ||
2739 | rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); | ||
2740 | |||
2741 | /* | ||
2742 | * Read external LNA informations. | ||
2743 | */ | ||
2744 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | ||
2745 | |||
2746 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) | ||
2747 | __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); | ||
2748 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) | ||
2749 | __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); | ||
2750 | |||
2751 | /* | ||
2752 | * Detect if this device has an hardware controlled radio. | ||
2753 | */ | ||
2754 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) | ||
2755 | __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); | ||
2756 | |||
2757 | /* | ||
2758 | * Store led settings, for correct led behaviour. | ||
2759 | */ | ||
2760 | #ifdef CONFIG_RT2X00_LIB_LEDS | ||
2761 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); | ||
2762 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); | ||
2763 | rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); | ||
2764 | |||
2765 | rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); | ||
2766 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | ||
2767 | |||
2768 | return 0; | ||
2769 | } | ||
2770 | |||
2771 | /* | ||
2772 | * RF value list for rt2860 | ||
2773 | * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) | ||
2774 | */ | ||
2775 | static const struct rf_channel rf_vals[] = { | ||
2776 | { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, | ||
2777 | { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, | ||
2778 | { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, | ||
2779 | { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, | ||
2780 | { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, | ||
2781 | { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, | ||
2782 | { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, | ||
2783 | { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, | ||
2784 | { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, | ||
2785 | { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, | ||
2786 | { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, | ||
2787 | { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, | ||
2788 | { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, | ||
2789 | { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, | ||
2790 | |||
2791 | /* 802.11 UNI / HyperLan 2 */ | ||
2792 | { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, | ||
2793 | { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, | ||
2794 | { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, | ||
2795 | { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, | ||
2796 | { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, | ||
2797 | { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, | ||
2798 | { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, | ||
2799 | { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, | ||
2800 | { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, | ||
2801 | { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, | ||
2802 | { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, | ||
2803 | { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, | ||
2804 | |||
2805 | /* 802.11 HyperLan 2 */ | ||
2806 | { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, | ||
2807 | { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 }, | ||
2808 | { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 }, | ||
2809 | { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 }, | ||
2810 | { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, | ||
2811 | { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, | ||
2812 | { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, | ||
2813 | { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, | ||
2814 | { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, | ||
2815 | { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, | ||
2816 | { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, | ||
2817 | { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, | ||
2818 | { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, | ||
2819 | { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, | ||
2820 | { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, | ||
2821 | { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, | ||
2822 | |||
2823 | /* 802.11 UNII */ | ||
2824 | { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, | ||
2825 | { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, | ||
2826 | { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, | ||
2827 | { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, | ||
2828 | { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, | ||
2829 | { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, | ||
2830 | { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, | ||
2831 | |||
2832 | /* 802.11 Japan */ | ||
2833 | { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, | ||
2834 | { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, | ||
2835 | { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, | ||
2836 | { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, | ||
2837 | { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, | ||
2838 | { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, | ||
2839 | { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, | ||
2840 | }; | ||
2841 | |||
2842 | static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | ||
2843 | { | ||
2844 | struct hw_mode_spec *spec = &rt2x00dev->spec; | ||
2845 | struct channel_info *info; | ||
2846 | char *tx_power1; | ||
2847 | char *tx_power2; | ||
2848 | unsigned int i; | ||
2849 | u16 eeprom; | ||
2850 | |||
2851 | /* | ||
2852 | * Initialize all hw fields. | ||
2853 | */ | ||
2854 | rt2x00dev->hw->flags = | ||
2855 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
2856 | IEEE80211_HW_SIGNAL_DBM | | ||
2857 | IEEE80211_HW_SUPPORTS_PS | | ||
2858 | IEEE80211_HW_PS_NULLFUNC_STACK; | ||
2859 | rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE; | ||
2860 | |||
2861 | SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); | ||
2862 | SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, | ||
2863 | rt2x00_eeprom_addr(rt2x00dev, | ||
2864 | EEPROM_MAC_ADDR_0)); | ||
2865 | |||
2866 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | ||
2867 | |||
2868 | /* | ||
2869 | * Initialize hw_mode information. | ||
2870 | */ | ||
2871 | spec->supported_bands = SUPPORT_BAND_2GHZ; | ||
2872 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | ||
2873 | |||
2874 | if (rt2x00_rf(&rt2x00dev->chip, RF2820) || | ||
2875 | rt2x00_rf(&rt2x00dev->chip, RF2720) || | ||
2876 | rt2x00_rf(&rt2x00dev->chip, RF3020) || | ||
2877 | rt2x00_rf(&rt2x00dev->chip, RF3021) || | ||
2878 | rt2x00_rf(&rt2x00dev->chip, RF3022) || | ||
2879 | rt2x00_rf(&rt2x00dev->chip, RF2020) || | ||
2880 | rt2x00_rf(&rt2x00dev->chip, RF3052)) { | ||
2881 | spec->num_channels = 14; | ||
2882 | spec->channels = rf_vals; | ||
2883 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || | ||
2884 | rt2x00_rf(&rt2x00dev->chip, RF2750)) { | ||
2885 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | ||
2886 | spec->num_channels = ARRAY_SIZE(rf_vals); | ||
2887 | spec->channels = rf_vals; | ||
2888 | } | ||
2889 | |||
2890 | /* | ||
2891 | * Initialize HT information. | ||
2892 | */ | ||
2893 | spec->ht.ht_supported = true; | ||
2894 | spec->ht.cap = | ||
2895 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | ||
2896 | IEEE80211_HT_CAP_GRN_FLD | | ||
2897 | IEEE80211_HT_CAP_SGI_20 | | ||
2898 | IEEE80211_HT_CAP_SGI_40 | | ||
2899 | IEEE80211_HT_CAP_TX_STBC | | ||
2900 | IEEE80211_HT_CAP_RX_STBC | | ||
2901 | IEEE80211_HT_CAP_PSMP_SUPPORT; | ||
2902 | spec->ht.ampdu_factor = 3; | ||
2903 | spec->ht.ampdu_density = 4; | ||
2904 | spec->ht.mcs.tx_params = | ||
2905 | IEEE80211_HT_MCS_TX_DEFINED | | ||
2906 | IEEE80211_HT_MCS_TX_RX_DIFF | | ||
2907 | ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << | ||
2908 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
2909 | |||
2910 | switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { | ||
2911 | case 3: | ||
2912 | spec->ht.mcs.rx_mask[2] = 0xff; | ||
2913 | case 2: | ||
2914 | spec->ht.mcs.rx_mask[1] = 0xff; | ||
2915 | case 1: | ||
2916 | spec->ht.mcs.rx_mask[0] = 0xff; | ||
2917 | spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ | ||
2918 | break; | ||
2919 | } | ||
2920 | |||
2921 | /* | ||
2922 | * Create channel information array | ||
2923 | */ | ||
2924 | info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); | ||
2925 | if (!info) | ||
2926 | return -ENOMEM; | ||
2927 | |||
2928 | spec->channels_info = info; | ||
2929 | |||
2930 | tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); | ||
2931 | tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); | ||
2932 | |||
2933 | for (i = 0; i < 14; i++) { | ||
2934 | info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); | ||
2935 | info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); | ||
2936 | } | ||
2937 | |||
2938 | if (spec->num_channels > 14) { | ||
2939 | tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); | ||
2940 | tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); | ||
2941 | |||
2942 | for (i = 14; i < spec->num_channels; i++) { | ||
2943 | info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); | ||
2944 | info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); | ||
2945 | } | ||
2946 | } | ||
2947 | |||
2948 | return 0; | ||
2949 | } | ||
2950 | |||
2951 | static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | ||
2952 | { | ||
2953 | int retval; | ||
2954 | |||
2955 | /* | ||
2956 | * Allocate eeprom data. | ||
2957 | */ | ||
2958 | retval = rt2800pci_validate_eeprom(rt2x00dev); | ||
2959 | if (retval) | ||
2960 | return retval; | ||
2961 | |||
2962 | retval = rt2800pci_init_eeprom(rt2x00dev); | ||
2963 | if (retval) | ||
2964 | return retval; | ||
2965 | |||
2966 | /* | ||
2967 | * Initialize hw specifications. | ||
2968 | */ | ||
2969 | retval = rt2800pci_probe_hw_mode(rt2x00dev); | ||
2970 | if (retval) | ||
2971 | return retval; | ||
2972 | |||
2973 | /* | ||
2974 | * This device has multiple filters for control frames | ||
2975 | * and has a separate filter for PS Poll frames. | ||
2976 | */ | ||
2977 | __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); | ||
2978 | __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); | ||
2979 | |||
2980 | /* | ||
2981 | * This device requires firmware. | ||
2982 | */ | ||
2983 | if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && | ||
2984 | !rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
2985 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | ||
2986 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | ||
2987 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | ||
2988 | if (!modparam_nohwcrypt) | ||
2989 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | ||
2990 | |||
2991 | /* | ||
2992 | * Set the rssi offset. | ||
2993 | */ | ||
2994 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; | ||
2995 | |||
2996 | return 0; | ||
2997 | } | ||
2998 | |||
2999 | /* | ||
3000 | * IEEE80211 stack callback functions. | ||
3001 | */ | ||
3002 | static void rt2800pci_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, | ||
3003 | u32 *iv32, u16 *iv16) | ||
3004 | { | ||
3005 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
3006 | struct mac_iveiv_entry iveiv_entry; | ||
3007 | u32 offset; | ||
3008 | |||
3009 | offset = MAC_IVEIV_ENTRY(hw_key_idx); | ||
3010 | rt2x00pci_register_multiread(rt2x00dev, offset, | ||
3011 | &iveiv_entry, sizeof(iveiv_entry)); | ||
3012 | |||
3013 | memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); | ||
3014 | memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); | ||
3015 | } | ||
3016 | |||
3017 | static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
3018 | { | ||
3019 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
3020 | u32 reg; | ||
3021 | bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); | ||
3022 | |||
3023 | rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); | ||
3024 | rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); | ||
3025 | rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); | ||
3026 | |||
3027 | rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, ®); | ||
3028 | rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); | ||
3029 | rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); | ||
3030 | |||
3031 | rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | ||
3032 | rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); | ||
3033 | rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | ||
3034 | |||
3035 | rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, ®); | ||
3036 | rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); | ||
3037 | rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); | ||
3038 | |||
3039 | rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, ®); | ||
3040 | rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); | ||
3041 | rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); | ||
3042 | |||
3043 | rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, ®); | ||
3044 | rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); | ||
3045 | rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); | ||
3046 | |||
3047 | rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, ®); | ||
3048 | rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); | ||
3049 | rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); | ||
3050 | |||
3051 | return 0; | ||
3052 | } | ||
3053 | |||
3054 | static int rt2800pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | ||
3055 | const struct ieee80211_tx_queue_params *params) | ||
3056 | { | ||
3057 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
3058 | struct data_queue *queue; | ||
3059 | struct rt2x00_field32 field; | ||
3060 | int retval; | ||
3061 | u32 reg; | ||
3062 | u32 offset; | ||
3063 | |||
3064 | /* | ||
3065 | * First pass the configuration through rt2x00lib, that will | ||
3066 | * update the queue settings and validate the input. After that | ||
3067 | * we are free to update the registers based on the value | ||
3068 | * in the queue parameter. | ||
3069 | */ | ||
3070 | retval = rt2x00mac_conf_tx(hw, queue_idx, params); | ||
3071 | if (retval) | ||
3072 | return retval; | ||
3073 | |||
3074 | /* | ||
3075 | * We only need to perform additional register initialization | ||
3076 | * for WMM queues/ | ||
3077 | */ | ||
3078 | if (queue_idx >= 4) | ||
3079 | return 0; | ||
3080 | |||
3081 | queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); | ||
3082 | |||
3083 | /* Update WMM TXOP register */ | ||
3084 | offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); | ||
3085 | field.bit_offset = (queue_idx & 1) * 16; | ||
3086 | field.bit_mask = 0xffff << field.bit_offset; | ||
3087 | |||
3088 | rt2x00pci_register_read(rt2x00dev, offset, ®); | ||
3089 | rt2x00_set_field32(®, field, queue->txop); | ||
3090 | rt2x00pci_register_write(rt2x00dev, offset, reg); | ||
3091 | |||
3092 | /* Update WMM registers */ | ||
3093 | field.bit_offset = queue_idx * 4; | ||
3094 | field.bit_mask = 0xf << field.bit_offset; | ||
3095 | |||
3096 | rt2x00pci_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); | ||
3097 | rt2x00_set_field32(®, field, queue->aifs); | ||
3098 | rt2x00pci_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); | ||
3099 | |||
3100 | rt2x00pci_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); | ||
3101 | rt2x00_set_field32(®, field, queue->cw_min); | ||
3102 | rt2x00pci_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); | ||
3103 | |||
3104 | rt2x00pci_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); | ||
3105 | rt2x00_set_field32(®, field, queue->cw_max); | ||
3106 | rt2x00pci_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); | ||
3107 | |||
3108 | /* Update EDCA registers */ | ||
3109 | offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); | ||
3110 | |||
3111 | rt2x00pci_register_read(rt2x00dev, offset, ®); | ||
3112 | rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); | ||
3113 | rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); | ||
3114 | rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); | ||
3115 | rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); | ||
3116 | rt2x00pci_register_write(rt2x00dev, offset, reg); | ||
3117 | |||
3118 | return 0; | ||
3119 | } | ||
3120 | |||
3121 | static u64 rt2800pci_get_tsf(struct ieee80211_hw *hw) | ||
3122 | { | ||
3123 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
3124 | u64 tsf; | ||
3125 | u32 reg; | ||
3126 | |||
3127 | rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW1, ®); | ||
3128 | tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; | ||
3129 | rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW0, ®); | ||
3130 | tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); | ||
3131 | |||
3132 | return tsf; | ||
3133 | } | ||
3134 | |||
3135 | static const struct ieee80211_ops rt2800pci_mac80211_ops = { | ||
3136 | .tx = rt2x00mac_tx, | ||
3137 | .start = rt2x00mac_start, | ||
3138 | .stop = rt2x00mac_stop, | ||
3139 | .add_interface = rt2x00mac_add_interface, | ||
3140 | .remove_interface = rt2x00mac_remove_interface, | ||
3141 | .config = rt2x00mac_config, | ||
3142 | .configure_filter = rt2x00mac_configure_filter, | ||
3143 | .set_key = rt2x00mac_set_key, | ||
3144 | .get_stats = rt2x00mac_get_stats, | ||
3145 | .get_tkip_seq = rt2800pci_get_tkip_seq, | ||
3146 | .set_rts_threshold = rt2800pci_set_rts_threshold, | ||
3147 | .bss_info_changed = rt2x00mac_bss_info_changed, | ||
3148 | .conf_tx = rt2800pci_conf_tx, | ||
3149 | .get_tx_stats = rt2x00mac_get_tx_stats, | ||
3150 | .get_tsf = rt2800pci_get_tsf, | ||
3151 | .rfkill_poll = rt2x00mac_rfkill_poll, | ||
3152 | }; | ||
3153 | |||
3154 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | ||
3155 | .irq_handler = rt2800pci_interrupt, | ||
3156 | .probe_hw = rt2800pci_probe_hw, | ||
3157 | .get_firmware_name = rt2800pci_get_firmware_name, | ||
3158 | .check_firmware = rt2800pci_check_firmware, | ||
3159 | .load_firmware = rt2800pci_load_firmware, | ||
3160 | .initialize = rt2x00pci_initialize, | ||
3161 | .uninitialize = rt2x00pci_uninitialize, | ||
3162 | .get_entry_state = rt2800pci_get_entry_state, | ||
3163 | .clear_entry = rt2800pci_clear_entry, | ||
3164 | .set_device_state = rt2800pci_set_device_state, | ||
3165 | .rfkill_poll = rt2800pci_rfkill_poll, | ||
3166 | .link_stats = rt2800pci_link_stats, | ||
3167 | .reset_tuner = rt2800pci_reset_tuner, | ||
3168 | .link_tuner = rt2800pci_link_tuner, | ||
3169 | .write_tx_desc = rt2800pci_write_tx_desc, | ||
3170 | .write_tx_data = rt2x00pci_write_tx_data, | ||
3171 | .write_beacon = rt2800pci_write_beacon, | ||
3172 | .kick_tx_queue = rt2800pci_kick_tx_queue, | ||
3173 | .kill_tx_queue = rt2800pci_kill_tx_queue, | ||
3174 | .fill_rxdone = rt2800pci_fill_rxdone, | ||
3175 | .config_shared_key = rt2800pci_config_shared_key, | ||
3176 | .config_pairwise_key = rt2800pci_config_pairwise_key, | ||
3177 | .config_filter = rt2800pci_config_filter, | ||
3178 | .config_intf = rt2800pci_config_intf, | ||
3179 | .config_erp = rt2800pci_config_erp, | ||
3180 | .config_ant = rt2800pci_config_ant, | ||
3181 | .config = rt2800pci_config, | ||
3182 | }; | ||
3183 | |||
3184 | static const struct data_queue_desc rt2800pci_queue_rx = { | ||
3185 | .entry_num = RX_ENTRIES, | ||
3186 | .data_size = AGGREGATION_SIZE, | ||
3187 | .desc_size = RXD_DESC_SIZE, | ||
3188 | .priv_size = sizeof(struct queue_entry_priv_pci), | ||
3189 | }; | ||
3190 | |||
3191 | static const struct data_queue_desc rt2800pci_queue_tx = { | ||
3192 | .entry_num = TX_ENTRIES, | ||
3193 | .data_size = AGGREGATION_SIZE, | ||
3194 | .desc_size = TXD_DESC_SIZE, | ||
3195 | .priv_size = sizeof(struct queue_entry_priv_pci), | ||
3196 | }; | ||
3197 | |||
3198 | static const struct data_queue_desc rt2800pci_queue_bcn = { | ||
3199 | .entry_num = 8 * BEACON_ENTRIES, | ||
3200 | .data_size = 0, /* No DMA required for beacons */ | ||
3201 | .desc_size = TXWI_DESC_SIZE, | ||
3202 | .priv_size = sizeof(struct queue_entry_priv_pci), | ||
3203 | }; | ||
3204 | |||
3205 | static const struct rt2x00_ops rt2800pci_ops = { | ||
3206 | .name = KBUILD_MODNAME, | ||
3207 | .max_sta_intf = 1, | ||
3208 | .max_ap_intf = 8, | ||
3209 | .eeprom_size = EEPROM_SIZE, | ||
3210 | .rf_size = RF_SIZE, | ||
3211 | .tx_queues = NUM_TX_QUEUES, | ||
3212 | .rx = &rt2800pci_queue_rx, | ||
3213 | .tx = &rt2800pci_queue_tx, | ||
3214 | .bcn = &rt2800pci_queue_bcn, | ||
3215 | .lib = &rt2800pci_rt2x00_ops, | ||
3216 | .hw = &rt2800pci_mac80211_ops, | ||
3217 | #ifdef CONFIG_RT2X00_LIB_DEBUGFS | ||
3218 | .debugfs = &rt2800pci_rt2x00debug, | ||
3219 | #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ | ||
3220 | }; | ||
3221 | |||
3222 | /* | ||
3223 | * RT2800pci module information. | ||
3224 | */ | ||
3225 | static struct pci_device_id rt2800pci_device_table[] = { | ||
3226 | { PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3227 | { PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3228 | { PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3229 | { PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3230 | { PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3231 | { PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3232 | { PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3233 | { PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3234 | { PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3235 | { PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3236 | { PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3237 | { PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3238 | { PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3239 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3240 | { PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3241 | { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3242 | { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3243 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3244 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3245 | { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
3246 | { 0, } | ||
3247 | }; | ||
3248 | |||
3249 | MODULE_AUTHOR(DRV_PROJECT); | ||
3250 | MODULE_VERSION(DRV_VERSION); | ||
3251 | MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); | ||
3252 | MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); | ||
3253 | #ifdef CONFIG_RT2800PCI_PCI | ||
3254 | MODULE_FIRMWARE(FIRMWARE_RT2860); | ||
3255 | MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | ||
3256 | #endif /* CONFIG_RT2800PCI_PCI */ | ||
3257 | MODULE_LICENSE("GPL"); | ||
3258 | |||
3259 | #ifdef CONFIG_RT2800PCI_WISOC | ||
3260 | #if defined(CONFIG_RALINK_RT288X) | ||
3261 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); | ||
3262 | #elif defined(CONFIG_RALINK_RT305X) | ||
3263 | __rt2x00soc_probe(RT3052, &rt2800pci_ops); | ||
3264 | #endif | ||
3265 | |||
3266 | static struct platform_driver rt2800soc_driver = { | ||
3267 | .driver = { | ||
3268 | .name = "rt2800_wmac", | ||
3269 | .owner = THIS_MODULE, | ||
3270 | .mod_name = KBUILD_MODNAME, | ||
3271 | }, | ||
3272 | .probe = __rt2x00soc_probe, | ||
3273 | .remove = __devexit_p(rt2x00soc_remove), | ||
3274 | .suspend = rt2x00soc_suspend, | ||
3275 | .resume = rt2x00soc_resume, | ||
3276 | }; | ||
3277 | #endif /* CONFIG_RT2800PCI_WISOC */ | ||
3278 | |||
3279 | #ifdef CONFIG_RT2800PCI_PCI | ||
3280 | static struct pci_driver rt2800pci_driver = { | ||
3281 | .name = KBUILD_MODNAME, | ||
3282 | .id_table = rt2800pci_device_table, | ||
3283 | .probe = rt2x00pci_probe, | ||
3284 | .remove = __devexit_p(rt2x00pci_remove), | ||
3285 | .suspend = rt2x00pci_suspend, | ||
3286 | .resume = rt2x00pci_resume, | ||
3287 | }; | ||
3288 | #endif /* CONFIG_RT2800PCI_PCI */ | ||
3289 | |||
3290 | static int __init rt2800pci_init(void) | ||
3291 | { | ||
3292 | int ret = 0; | ||
3293 | |||
3294 | #ifdef CONFIG_RT2800PCI_WISOC | ||
3295 | ret = platform_driver_register(&rt2800soc_driver); | ||
3296 | if (ret) | ||
3297 | return ret; | ||
3298 | #endif | ||
3299 | #ifdef CONFIG_RT2800PCI_PCI | ||
3300 | ret = pci_register_driver(&rt2800pci_driver); | ||
3301 | if (ret) { | ||
3302 | #ifdef CONFIG_RT2800PCI_WISOC | ||
3303 | platform_driver_unregister(&rt2800soc_driver); | ||
3304 | #endif | ||
3305 | return ret; | ||
3306 | } | ||
3307 | #endif | ||
3308 | |||
3309 | return ret; | ||
3310 | } | ||
3311 | |||
3312 | static void __exit rt2800pci_exit(void) | ||
3313 | { | ||
3314 | #ifdef CONFIG_RT2800PCI_PCI | ||
3315 | pci_unregister_driver(&rt2800pci_driver); | ||
3316 | #endif | ||
3317 | #ifdef CONFIG_RT2800PCI_WISOC | ||
3318 | platform_driver_unregister(&rt2800soc_driver); | ||
3319 | #endif | ||
3320 | } | ||
3321 | |||
3322 | module_init(rt2800pci_init); | ||
3323 | module_exit(rt2800pci_exit); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h new file mode 100644 index 000000000000..856908815221 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.h | |||
@@ -0,0 +1,1960 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2800pci | ||
23 | Abstract: Data structures and registers for the rt2800pci module. | ||
24 | Supported chipsets: RT2800E & RT2800ED. | ||
25 | */ | ||
26 | |||
27 | #ifndef RT2800PCI_H | ||
28 | #define RT2800PCI_H | ||
29 | |||
30 | /* | ||
31 | * RF chip defines. | ||
32 | * | ||
33 | * RF2820 2.4G 2T3R | ||
34 | * RF2850 2.4G/5G 2T3R | ||
35 | * RF2720 2.4G 1T2R | ||
36 | * RF2750 2.4G/5G 1T2R | ||
37 | * RF3020 2.4G 1T1R | ||
38 | * RF2020 2.4G B/G | ||
39 | * RF3021 2.4G 1T2R | ||
40 | * RF3022 2.4G 2T2R | ||
41 | * RF3052 2.4G 2T2R | ||
42 | */ | ||
43 | #define RF2820 0x0001 | ||
44 | #define RF2850 0x0002 | ||
45 | #define RF2720 0x0003 | ||
46 | #define RF2750 0x0004 | ||
47 | #define RF3020 0x0005 | ||
48 | #define RF2020 0x0006 | ||
49 | #define RF3021 0x0007 | ||
50 | #define RF3022 0x0008 | ||
51 | #define RF3052 0x0009 | ||
52 | |||
53 | /* | ||
54 | * RT2860 version | ||
55 | */ | ||
56 | #define RT2860C_VERSION 0x28600100 | ||
57 | #define RT2860D_VERSION 0x28600101 | ||
58 | #define RT2880E_VERSION 0x28720200 | ||
59 | #define RT2883_VERSION 0x28830300 | ||
60 | #define RT3070_VERSION 0x30700200 | ||
61 | |||
62 | /* | ||
63 | * Signal information. | ||
64 | * Default offset is required for RSSI <-> dBm conversion. | ||
65 | */ | ||
66 | #define DEFAULT_RSSI_OFFSET 120 /* FIXME */ | ||
67 | |||
68 | /* | ||
69 | * Register layout information. | ||
70 | */ | ||
71 | #define CSR_REG_BASE 0x1000 | ||
72 | #define CSR_REG_SIZE 0x0800 | ||
73 | #define EEPROM_BASE 0x0000 | ||
74 | #define EEPROM_SIZE 0x0110 | ||
75 | #define BBP_BASE 0x0000 | ||
76 | #define BBP_SIZE 0x0080 | ||
77 | #define RF_BASE 0x0004 | ||
78 | #define RF_SIZE 0x0010 | ||
79 | |||
80 | /* | ||
81 | * Number of TX queues. | ||
82 | */ | ||
83 | #define NUM_TX_QUEUES 4 | ||
84 | |||
85 | /* | ||
86 | * PCI registers. | ||
87 | */ | ||
88 | |||
89 | /* | ||
90 | * E2PROM_CSR: EEPROM control register. | ||
91 | * RELOAD: Write 1 to reload eeprom content. | ||
92 | * TYPE: 0: 93c46, 1:93c66. | ||
93 | * LOAD_STATUS: 1:loading, 0:done. | ||
94 | */ | ||
95 | #define E2PROM_CSR 0x0004 | ||
96 | #define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000001) | ||
97 | #define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) | ||
98 | #define E2PROM_CSR_DATA_IN FIELD32(0x00000004) | ||
99 | #define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) | ||
100 | #define E2PROM_CSR_TYPE FIELD32(0x00000030) | ||
101 | #define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) | ||
102 | #define E2PROM_CSR_RELOAD FIELD32(0x00000080) | ||
103 | |||
104 | /* | ||
105 | * INT_SOURCE_CSR: Interrupt source register. | ||
106 | * Write one to clear corresponding bit. | ||
107 | * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c | ||
108 | */ | ||
109 | #define INT_SOURCE_CSR 0x0200 | ||
110 | #define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) | ||
111 | #define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) | ||
112 | #define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) | ||
113 | #define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) | ||
114 | #define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) | ||
115 | #define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) | ||
116 | #define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) | ||
117 | #define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) | ||
118 | #define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) | ||
119 | #define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) | ||
120 | #define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) | ||
121 | #define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) | ||
122 | #define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) | ||
123 | #define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) | ||
124 | #define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) | ||
125 | #define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) | ||
126 | #define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) | ||
127 | #define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) | ||
128 | |||
129 | /* | ||
130 | * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. | ||
131 | */ | ||
132 | #define INT_MASK_CSR 0x0204 | ||
133 | #define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) | ||
134 | #define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) | ||
135 | #define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) | ||
136 | #define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) | ||
137 | #define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) | ||
138 | #define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) | ||
139 | #define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) | ||
140 | #define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) | ||
141 | #define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) | ||
142 | #define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) | ||
143 | #define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) | ||
144 | #define INT_MASK_CSR_TBTT FIELD32(0x00000800) | ||
145 | #define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) | ||
146 | #define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) | ||
147 | #define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) | ||
148 | #define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) | ||
149 | #define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) | ||
150 | #define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) | ||
151 | |||
152 | /* | ||
153 | * WPDMA_GLO_CFG | ||
154 | */ | ||
155 | #define WPDMA_GLO_CFG 0x0208 | ||
156 | #define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) | ||
157 | #define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) | ||
158 | #define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) | ||
159 | #define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) | ||
160 | #define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) | ||
161 | #define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) | ||
162 | #define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) | ||
163 | #define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) | ||
164 | #define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) | ||
165 | |||
166 | /* | ||
167 | * WPDMA_RST_IDX | ||
168 | */ | ||
169 | #define WPDMA_RST_IDX 0x020c | ||
170 | #define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) | ||
171 | #define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) | ||
172 | #define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) | ||
173 | #define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) | ||
174 | #define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) | ||
175 | #define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) | ||
176 | #define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) | ||
177 | |||
178 | /* | ||
179 | * DELAY_INT_CFG | ||
180 | */ | ||
181 | #define DELAY_INT_CFG 0x0210 | ||
182 | #define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) | ||
183 | #define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) | ||
184 | #define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) | ||
185 | #define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) | ||
186 | #define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) | ||
187 | #define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) | ||
188 | |||
189 | /* | ||
190 | * WMM_AIFSN_CFG: Aifsn for each EDCA AC | ||
191 | * AIFSN0: AC_BE | ||
192 | * AIFSN1: AC_BK | ||
193 | * AIFSN1: AC_VI | ||
194 | * AIFSN1: AC_VO | ||
195 | */ | ||
196 | #define WMM_AIFSN_CFG 0x0214 | ||
197 | #define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) | ||
198 | #define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) | ||
199 | #define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) | ||
200 | #define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) | ||
201 | |||
202 | /* | ||
203 | * WMM_CWMIN_CSR: CWmin for each EDCA AC | ||
204 | * CWMIN0: AC_BE | ||
205 | * CWMIN1: AC_BK | ||
206 | * CWMIN1: AC_VI | ||
207 | * CWMIN1: AC_VO | ||
208 | */ | ||
209 | #define WMM_CWMIN_CFG 0x0218 | ||
210 | #define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) | ||
211 | #define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) | ||
212 | #define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) | ||
213 | #define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) | ||
214 | |||
215 | /* | ||
216 | * WMM_CWMAX_CSR: CWmax for each EDCA AC | ||
217 | * CWMAX0: AC_BE | ||
218 | * CWMAX1: AC_BK | ||
219 | * CWMAX1: AC_VI | ||
220 | * CWMAX1: AC_VO | ||
221 | */ | ||
222 | #define WMM_CWMAX_CFG 0x021c | ||
223 | #define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) | ||
224 | #define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) | ||
225 | #define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) | ||
226 | #define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) | ||
227 | |||
228 | /* | ||
229 | * AC_TXOP0: AC_BK/AC_BE TXOP register | ||
230 | * AC0TXOP: AC_BK in unit of 32us | ||
231 | * AC1TXOP: AC_BE in unit of 32us | ||
232 | */ | ||
233 | #define WMM_TXOP0_CFG 0x0220 | ||
234 | #define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) | ||
235 | #define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) | ||
236 | |||
237 | /* | ||
238 | * AC_TXOP1: AC_VO/AC_VI TXOP register | ||
239 | * AC2TXOP: AC_VI in unit of 32us | ||
240 | * AC3TXOP: AC_VO in unit of 32us | ||
241 | */ | ||
242 | #define WMM_TXOP1_CFG 0x0224 | ||
243 | #define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) | ||
244 | #define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) | ||
245 | |||
246 | /* | ||
247 | * GPIO_CTRL_CFG: | ||
248 | */ | ||
249 | #define GPIO_CTRL_CFG 0x0228 | ||
250 | #define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) | ||
251 | #define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) | ||
252 | #define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) | ||
253 | #define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) | ||
254 | #define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) | ||
255 | #define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) | ||
256 | #define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) | ||
257 | #define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) | ||
258 | #define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) | ||
259 | |||
260 | /* | ||
261 | * MCU_CMD_CFG | ||
262 | */ | ||
263 | #define MCU_CMD_CFG 0x022c | ||
264 | |||
265 | /* | ||
266 | * AC_BK register offsets | ||
267 | */ | ||
268 | #define TX_BASE_PTR0 0x0230 | ||
269 | #define TX_MAX_CNT0 0x0234 | ||
270 | #define TX_CTX_IDX0 0x0238 | ||
271 | #define TX_DTX_IDX0 0x023c | ||
272 | |||
273 | /* | ||
274 | * AC_BE register offsets | ||
275 | */ | ||
276 | #define TX_BASE_PTR1 0x0240 | ||
277 | #define TX_MAX_CNT1 0x0244 | ||
278 | #define TX_CTX_IDX1 0x0248 | ||
279 | #define TX_DTX_IDX1 0x024c | ||
280 | |||
281 | /* | ||
282 | * AC_VI register offsets | ||
283 | */ | ||
284 | #define TX_BASE_PTR2 0x0250 | ||
285 | #define TX_MAX_CNT2 0x0254 | ||
286 | #define TX_CTX_IDX2 0x0258 | ||
287 | #define TX_DTX_IDX2 0x025c | ||
288 | |||
289 | /* | ||
290 | * AC_VO register offsets | ||
291 | */ | ||
292 | #define TX_BASE_PTR3 0x0260 | ||
293 | #define TX_MAX_CNT3 0x0264 | ||
294 | #define TX_CTX_IDX3 0x0268 | ||
295 | #define TX_DTX_IDX3 0x026c | ||
296 | |||
297 | /* | ||
298 | * HCCA register offsets | ||
299 | */ | ||
300 | #define TX_BASE_PTR4 0x0270 | ||
301 | #define TX_MAX_CNT4 0x0274 | ||
302 | #define TX_CTX_IDX4 0x0278 | ||
303 | #define TX_DTX_IDX4 0x027c | ||
304 | |||
305 | /* | ||
306 | * MGMT register offsets | ||
307 | */ | ||
308 | #define TX_BASE_PTR5 0x0280 | ||
309 | #define TX_MAX_CNT5 0x0284 | ||
310 | #define TX_CTX_IDX5 0x0288 | ||
311 | #define TX_DTX_IDX5 0x028c | ||
312 | |||
313 | /* | ||
314 | * Queue register offset macros | ||
315 | */ | ||
316 | #define TX_QUEUE_REG_OFFSET 0x10 | ||
317 | #define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET) | ||
318 | #define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET) | ||
319 | #define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) | ||
320 | #define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET) | ||
321 | |||
322 | /* | ||
323 | * RX register offsets | ||
324 | */ | ||
325 | #define RX_BASE_PTR 0x0290 | ||
326 | #define RX_MAX_CNT 0x0294 | ||
327 | #define RX_CRX_IDX 0x0298 | ||
328 | #define RX_DRX_IDX 0x029c | ||
329 | |||
330 | /* | ||
331 | * PBF_SYS_CTRL | ||
332 | * HOST_RAM_WRITE: enable Host program ram write selection | ||
333 | */ | ||
334 | #define PBF_SYS_CTRL 0x0400 | ||
335 | #define PBF_SYS_CTRL_READY FIELD32(0x00000080) | ||
336 | #define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) | ||
337 | |||
338 | /* | ||
339 | * HOST-MCU shared memory | ||
340 | */ | ||
341 | #define HOST_CMD_CSR 0x0404 | ||
342 | #define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) | ||
343 | |||
344 | /* | ||
345 | * PBF registers | ||
346 | * Most are for debug. Driver doesn't touch PBF register. | ||
347 | */ | ||
348 | #define PBF_CFG 0x0408 | ||
349 | #define PBF_MAX_PCNT 0x040c | ||
350 | #define PBF_CTRL 0x0410 | ||
351 | #define PBF_INT_STA 0x0414 | ||
352 | #define PBF_INT_ENA 0x0418 | ||
353 | |||
354 | /* | ||
355 | * BCN_OFFSET0: | ||
356 | */ | ||
357 | #define BCN_OFFSET0 0x042c | ||
358 | #define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) | ||
359 | #define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) | ||
360 | #define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) | ||
361 | #define BCN_OFFSET0_BCN3 FIELD32(0xff000000) | ||
362 | |||
363 | /* | ||
364 | * BCN_OFFSET1: | ||
365 | */ | ||
366 | #define BCN_OFFSET1 0x0430 | ||
367 | #define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) | ||
368 | #define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) | ||
369 | #define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) | ||
370 | #define BCN_OFFSET1_BCN7 FIELD32(0xff000000) | ||
371 | |||
372 | /* | ||
373 | * PBF registers | ||
374 | * Most are for debug. Driver doesn't touch PBF register. | ||
375 | */ | ||
376 | #define TXRXQ_PCNT 0x0438 | ||
377 | #define PBF_DBG 0x043c | ||
378 | |||
379 | /* | ||
380 | * RF registers | ||
381 | */ | ||
382 | #define RF_CSR_CFG 0x0500 | ||
383 | #define RF_CSR_CFG_DATA FIELD32(0x000000ff) | ||
384 | #define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) | ||
385 | #define RF_CSR_CFG_WRITE FIELD32(0x00010000) | ||
386 | #define RF_CSR_CFG_BUSY FIELD32(0x00020000) | ||
387 | |||
388 | /* | ||
389 | * EFUSE_CSR: RT3090 EEPROM | ||
390 | */ | ||
391 | #define EFUSE_CTRL 0x0580 | ||
392 | #define EFUSE_CTRL_ADDRESS_IN FIELD32(0x03fe0000) | ||
393 | #define EFUSE_CTRL_MODE FIELD32(0x000000c0) | ||
394 | #define EFUSE_CTRL_KICK FIELD32(0x40000000) | ||
395 | |||
396 | /* | ||
397 | * EFUSE_DATA0 | ||
398 | */ | ||
399 | #define EFUSE_DATA0 0x0590 | ||
400 | |||
401 | /* | ||
402 | * EFUSE_DATA1 | ||
403 | */ | ||
404 | #define EFUSE_DATA1 0x0594 | ||
405 | |||
406 | /* | ||
407 | * EFUSE_DATA2 | ||
408 | */ | ||
409 | #define EFUSE_DATA2 0x0598 | ||
410 | |||
411 | /* | ||
412 | * EFUSE_DATA3 | ||
413 | */ | ||
414 | #define EFUSE_DATA3 0x059c | ||
415 | |||
416 | /* | ||
417 | * MAC Control/Status Registers(CSR). | ||
418 | * Some values are set in TU, whereas 1 TU == 1024 us. | ||
419 | */ | ||
420 | |||
421 | /* | ||
422 | * MAC_CSR0: ASIC revision number. | ||
423 | * ASIC_REV: 0 | ||
424 | * ASIC_VER: 2860 | ||
425 | */ | ||
426 | #define MAC_CSR0 0x1000 | ||
427 | #define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) | ||
428 | #define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) | ||
429 | |||
430 | /* | ||
431 | * MAC_SYS_CTRL: | ||
432 | */ | ||
433 | #define MAC_SYS_CTRL 0x1004 | ||
434 | #define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) | ||
435 | #define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) | ||
436 | #define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) | ||
437 | #define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) | ||
438 | #define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) | ||
439 | #define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) | ||
440 | #define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) | ||
441 | #define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) | ||
442 | |||
443 | /* | ||
444 | * MAC_ADDR_DW0: STA MAC register 0 | ||
445 | */ | ||
446 | #define MAC_ADDR_DW0 0x1008 | ||
447 | #define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) | ||
448 | #define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) | ||
449 | #define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) | ||
450 | #define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) | ||
451 | |||
452 | /* | ||
453 | * MAC_ADDR_DW1: STA MAC register 1 | ||
454 | * UNICAST_TO_ME_MASK: | ||
455 | * Used to mask off bits from byte 5 of the MAC address | ||
456 | * to determine the UNICAST_TO_ME bit for RX frames. | ||
457 | * The full mask is complemented by BSS_ID_MASK: | ||
458 | * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK | ||
459 | */ | ||
460 | #define MAC_ADDR_DW1 0x100c | ||
461 | #define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) | ||
462 | #define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) | ||
463 | #define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) | ||
464 | |||
465 | /* | ||
466 | * MAC_BSSID_DW0: BSSID register 0 | ||
467 | */ | ||
468 | #define MAC_BSSID_DW0 0x1010 | ||
469 | #define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) | ||
470 | #define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) | ||
471 | #define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) | ||
472 | #define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) | ||
473 | |||
474 | /* | ||
475 | * MAC_BSSID_DW1: BSSID register 1 | ||
476 | * BSS_ID_MASK: | ||
477 | * 0: 1-BSSID mode (BSS index = 0) | ||
478 | * 1: 2-BSSID mode (BSS index: Byte5, bit 0) | ||
479 | * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) | ||
480 | * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) | ||
481 | * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the | ||
482 | * BSSID. This will make sure that those bits will be ignored | ||
483 | * when determining the MY_BSS of RX frames. | ||
484 | */ | ||
485 | #define MAC_BSSID_DW1 0x1014 | ||
486 | #define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) | ||
487 | #define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) | ||
488 | #define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) | ||
489 | #define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) | ||
490 | |||
491 | /* | ||
492 | * MAX_LEN_CFG: Maximum frame length register. | ||
493 | * MAX_MPDU: rt2860b max 16k bytes | ||
494 | * MAX_PSDU: Maximum PSDU length | ||
495 | * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 | ||
496 | */ | ||
497 | #define MAX_LEN_CFG 0x1018 | ||
498 | #define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) | ||
499 | #define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) | ||
500 | #define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) | ||
501 | #define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) | ||
502 | |||
503 | /* | ||
504 | * BBP_CSR_CFG: BBP serial control register | ||
505 | * VALUE: Register value to program into BBP | ||
506 | * REG_NUM: Selected BBP register | ||
507 | * READ_CONTROL: 0 write BBP, 1 read BBP | ||
508 | * BUSY: ASIC is busy executing BBP commands | ||
509 | * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks | ||
510 | * BBP_RW_MODE: 0 serial, 1 paralell | ||
511 | */ | ||
512 | #define BBP_CSR_CFG 0x101c | ||
513 | #define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) | ||
514 | #define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) | ||
515 | #define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) | ||
516 | #define BBP_CSR_CFG_BUSY FIELD32(0x00020000) | ||
517 | #define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) | ||
518 | #define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) | ||
519 | |||
520 | /* | ||
521 | * RF_CSR_CFG0: RF control register | ||
522 | * REGID_AND_VALUE: Register value to program into RF | ||
523 | * BITWIDTH: Selected RF register | ||
524 | * STANDBYMODE: 0 high when standby, 1 low when standby | ||
525 | * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate | ||
526 | * BUSY: ASIC is busy executing RF commands | ||
527 | */ | ||
528 | #define RF_CSR_CFG0 0x1020 | ||
529 | #define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) | ||
530 | #define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) | ||
531 | #define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) | ||
532 | #define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) | ||
533 | #define RF_CSR_CFG0_SEL FIELD32(0x40000000) | ||
534 | #define RF_CSR_CFG0_BUSY FIELD32(0x80000000) | ||
535 | |||
536 | /* | ||
537 | * RF_CSR_CFG1: RF control register | ||
538 | * REGID_AND_VALUE: Register value to program into RF | ||
539 | * RFGAP: Gap between BB_CONTROL_RF and RF_LE | ||
540 | * 0: 3 system clock cycle (37.5usec) | ||
541 | * 1: 5 system clock cycle (62.5usec) | ||
542 | */ | ||
543 | #define RF_CSR_CFG1 0x1024 | ||
544 | #define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) | ||
545 | #define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) | ||
546 | |||
547 | /* | ||
548 | * RF_CSR_CFG2: RF control register | ||
549 | * VALUE: Register value to program into RF | ||
550 | * RFGAP: Gap between BB_CONTROL_RF and RF_LE | ||
551 | * 0: 3 system clock cycle (37.5usec) | ||
552 | * 1: 5 system clock cycle (62.5usec) | ||
553 | */ | ||
554 | #define RF_CSR_CFG2 0x1028 | ||
555 | #define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) | ||
556 | |||
557 | /* | ||
558 | * LED_CFG: LED control | ||
559 | * color LED's: | ||
560 | * 0: off | ||
561 | * 1: blinking upon TX2 | ||
562 | * 2: periodic slow blinking | ||
563 | * 3: always on | ||
564 | * LED polarity: | ||
565 | * 0: active low | ||
566 | * 1: active high | ||
567 | */ | ||
568 | #define LED_CFG 0x102c | ||
569 | #define LED_CFG_ON_PERIOD FIELD32(0x000000ff) | ||
570 | #define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) | ||
571 | #define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) | ||
572 | #define LED_CFG_R_LED_MODE FIELD32(0x03000000) | ||
573 | #define LED_CFG_G_LED_MODE FIELD32(0x0c000000) | ||
574 | #define LED_CFG_Y_LED_MODE FIELD32(0x30000000) | ||
575 | #define LED_CFG_LED_POLAR FIELD32(0x40000000) | ||
576 | |||
577 | /* | ||
578 | * XIFS_TIME_CFG: MAC timing | ||
579 | * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX | ||
580 | * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX | ||
581 | * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX | ||
582 | * when MAC doesn't reference BBP signal BBRXEND | ||
583 | * EIFS: unit 1us | ||
584 | * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer | ||
585 | * | ||
586 | */ | ||
587 | #define XIFS_TIME_CFG 0x1100 | ||
588 | #define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) | ||
589 | #define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) | ||
590 | #define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) | ||
591 | #define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) | ||
592 | #define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) | ||
593 | |||
594 | /* | ||
595 | * BKOFF_SLOT_CFG: | ||
596 | */ | ||
597 | #define BKOFF_SLOT_CFG 0x1104 | ||
598 | #define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) | ||
599 | #define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) | ||
600 | |||
601 | /* | ||
602 | * NAV_TIME_CFG: | ||
603 | */ | ||
604 | #define NAV_TIME_CFG 0x1108 | ||
605 | #define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) | ||
606 | #define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) | ||
607 | #define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) | ||
608 | #define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) | ||
609 | |||
610 | /* | ||
611 | * CH_TIME_CFG: count as channel busy | ||
612 | */ | ||
613 | #define CH_TIME_CFG 0x110c | ||
614 | |||
615 | /* | ||
616 | * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us | ||
617 | */ | ||
618 | #define PBF_LIFE_TIMER 0x1110 | ||
619 | |||
620 | /* | ||
621 | * BCN_TIME_CFG: | ||
622 | * BEACON_INTERVAL: in unit of 1/16 TU | ||
623 | * TSF_TICKING: Enable TSF auto counting | ||
624 | * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode | ||
625 | * BEACON_GEN: Enable beacon generator | ||
626 | */ | ||
627 | #define BCN_TIME_CFG 0x1114 | ||
628 | #define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) | ||
629 | #define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) | ||
630 | #define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) | ||
631 | #define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) | ||
632 | #define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) | ||
633 | #define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) | ||
634 | |||
635 | /* | ||
636 | * TBTT_SYNC_CFG: | ||
637 | */ | ||
638 | #define TBTT_SYNC_CFG 0x1118 | ||
639 | |||
640 | /* | ||
641 | * TSF_TIMER_DW0: Local lsb TSF timer, read-only | ||
642 | */ | ||
643 | #define TSF_TIMER_DW0 0x111c | ||
644 | #define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) | ||
645 | |||
646 | /* | ||
647 | * TSF_TIMER_DW1: Local msb TSF timer, read-only | ||
648 | */ | ||
649 | #define TSF_TIMER_DW1 0x1120 | ||
650 | #define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) | ||
651 | |||
652 | /* | ||
653 | * TBTT_TIMER: TImer remains till next TBTT, read-only | ||
654 | */ | ||
655 | #define TBTT_TIMER 0x1124 | ||
656 | |||
657 | /* | ||
658 | * INT_TIMER_CFG: | ||
659 | */ | ||
660 | #define INT_TIMER_CFG 0x1128 | ||
661 | |||
662 | /* | ||
663 | * INT_TIMER_EN: GP-timer and pre-tbtt Int enable | ||
664 | */ | ||
665 | #define INT_TIMER_EN 0x112c | ||
666 | |||
667 | /* | ||
668 | * CH_IDLE_STA: channel idle time | ||
669 | */ | ||
670 | #define CH_IDLE_STA 0x1130 | ||
671 | |||
672 | /* | ||
673 | * CH_BUSY_STA: channel busy time | ||
674 | */ | ||
675 | #define CH_BUSY_STA 0x1134 | ||
676 | |||
677 | /* | ||
678 | * MAC_STATUS_CFG: | ||
679 | * BBP_RF_BUSY: When set to 0, BBP and RF are stable. | ||
680 | * if 1 or higher one of the 2 registers is busy. | ||
681 | */ | ||
682 | #define MAC_STATUS_CFG 0x1200 | ||
683 | #define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) | ||
684 | |||
685 | /* | ||
686 | * PWR_PIN_CFG: | ||
687 | */ | ||
688 | #define PWR_PIN_CFG 0x1204 | ||
689 | |||
690 | /* | ||
691 | * AUTOWAKEUP_CFG: Manual power control / status register | ||
692 | * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set | ||
693 | * AUTOWAKE: 0:sleep, 1:awake | ||
694 | */ | ||
695 | #define AUTOWAKEUP_CFG 0x1208 | ||
696 | #define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) | ||
697 | #define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) | ||
698 | #define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) | ||
699 | |||
700 | /* | ||
701 | * EDCA_AC0_CFG: | ||
702 | */ | ||
703 | #define EDCA_AC0_CFG 0x1300 | ||
704 | #define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) | ||
705 | #define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) | ||
706 | #define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) | ||
707 | #define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) | ||
708 | |||
709 | /* | ||
710 | * EDCA_AC1_CFG: | ||
711 | */ | ||
712 | #define EDCA_AC1_CFG 0x1304 | ||
713 | #define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) | ||
714 | #define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) | ||
715 | #define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) | ||
716 | #define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) | ||
717 | |||
718 | /* | ||
719 | * EDCA_AC2_CFG: | ||
720 | */ | ||
721 | #define EDCA_AC2_CFG 0x1308 | ||
722 | #define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) | ||
723 | #define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) | ||
724 | #define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) | ||
725 | #define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) | ||
726 | |||
727 | /* | ||
728 | * EDCA_AC3_CFG: | ||
729 | */ | ||
730 | #define EDCA_AC3_CFG 0x130c | ||
731 | #define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) | ||
732 | #define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) | ||
733 | #define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) | ||
734 | #define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) | ||
735 | |||
736 | /* | ||
737 | * EDCA_TID_AC_MAP: | ||
738 | */ | ||
739 | #define EDCA_TID_AC_MAP 0x1310 | ||
740 | |||
741 | /* | ||
742 | * TX_PWR_CFG_0: | ||
743 | */ | ||
744 | #define TX_PWR_CFG_0 0x1314 | ||
745 | #define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) | ||
746 | #define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) | ||
747 | #define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) | ||
748 | #define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) | ||
749 | #define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) | ||
750 | #define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) | ||
751 | #define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) | ||
752 | #define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) | ||
753 | |||
754 | /* | ||
755 | * TX_PWR_CFG_1: | ||
756 | */ | ||
757 | #define TX_PWR_CFG_1 0x1318 | ||
758 | #define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) | ||
759 | #define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) | ||
760 | #define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) | ||
761 | #define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) | ||
762 | #define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) | ||
763 | #define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) | ||
764 | #define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) | ||
765 | #define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) | ||
766 | |||
767 | /* | ||
768 | * TX_PWR_CFG_2: | ||
769 | */ | ||
770 | #define TX_PWR_CFG_2 0x131c | ||
771 | #define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) | ||
772 | #define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) | ||
773 | #define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) | ||
774 | #define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) | ||
775 | #define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) | ||
776 | #define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) | ||
777 | #define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) | ||
778 | #define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) | ||
779 | |||
780 | /* | ||
781 | * TX_PWR_CFG_3: | ||
782 | */ | ||
783 | #define TX_PWR_CFG_3 0x1320 | ||
784 | #define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) | ||
785 | #define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) | ||
786 | #define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) | ||
787 | #define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) | ||
788 | #define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) | ||
789 | #define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) | ||
790 | #define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) | ||
791 | #define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) | ||
792 | |||
793 | /* | ||
794 | * TX_PWR_CFG_4: | ||
795 | */ | ||
796 | #define TX_PWR_CFG_4 0x1324 | ||
797 | #define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) | ||
798 | #define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) | ||
799 | #define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) | ||
800 | #define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) | ||
801 | |||
802 | /* | ||
803 | * TX_PIN_CFG: | ||
804 | */ | ||
805 | #define TX_PIN_CFG 0x1328 | ||
806 | #define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) | ||
807 | #define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) | ||
808 | #define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) | ||
809 | #define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) | ||
810 | #define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) | ||
811 | #define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) | ||
812 | #define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) | ||
813 | #define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) | ||
814 | #define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) | ||
815 | #define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) | ||
816 | #define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) | ||
817 | #define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) | ||
818 | #define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) | ||
819 | #define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) | ||
820 | #define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) | ||
821 | #define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) | ||
822 | #define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) | ||
823 | #define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) | ||
824 | #define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) | ||
825 | #define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) | ||
826 | |||
827 | /* | ||
828 | * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz | ||
829 | */ | ||
830 | #define TX_BAND_CFG 0x132c | ||
831 | #define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) | ||
832 | #define TX_BAND_CFG_A FIELD32(0x00000002) | ||
833 | #define TX_BAND_CFG_BG FIELD32(0x00000004) | ||
834 | |||
835 | /* | ||
836 | * TX_SW_CFG0: | ||
837 | */ | ||
838 | #define TX_SW_CFG0 0x1330 | ||
839 | |||
840 | /* | ||
841 | * TX_SW_CFG1: | ||
842 | */ | ||
843 | #define TX_SW_CFG1 0x1334 | ||
844 | |||
845 | /* | ||
846 | * TX_SW_CFG2: | ||
847 | */ | ||
848 | #define TX_SW_CFG2 0x1338 | ||
849 | |||
850 | /* | ||
851 | * TXOP_THRES_CFG: | ||
852 | */ | ||
853 | #define TXOP_THRES_CFG 0x133c | ||
854 | |||
855 | /* | ||
856 | * TXOP_CTRL_CFG: | ||
857 | */ | ||
858 | #define TXOP_CTRL_CFG 0x1340 | ||
859 | |||
860 | /* | ||
861 | * TX_RTS_CFG: | ||
862 | * RTS_THRES: unit:byte | ||
863 | * RTS_FBK_EN: enable rts rate fallback | ||
864 | */ | ||
865 | #define TX_RTS_CFG 0x1344 | ||
866 | #define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) | ||
867 | #define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) | ||
868 | #define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) | ||
869 | |||
870 | /* | ||
871 | * TX_TIMEOUT_CFG: | ||
872 | * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us | ||
873 | * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure | ||
874 | * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. | ||
875 | * it is recommended that: | ||
876 | * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) | ||
877 | */ | ||
878 | #define TX_TIMEOUT_CFG 0x1348 | ||
879 | #define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) | ||
880 | #define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) | ||
881 | #define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) | ||
882 | |||
883 | /* | ||
884 | * TX_RTY_CFG: | ||
885 | * SHORT_RTY_LIMIT: short retry limit | ||
886 | * LONG_RTY_LIMIT: long retry limit | ||
887 | * LONG_RTY_THRE: Long retry threshoold | ||
888 | * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode | ||
889 | * 0:expired by retry limit, 1: expired by mpdu life timer | ||
890 | * AGG_RTY_MODE: Aggregate MPDU retry mode | ||
891 | * 0:expired by retry limit, 1: expired by mpdu life timer | ||
892 | * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable | ||
893 | */ | ||
894 | #define TX_RTY_CFG 0x134c | ||
895 | #define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) | ||
896 | #define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) | ||
897 | #define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) | ||
898 | #define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) | ||
899 | #define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) | ||
900 | #define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) | ||
901 | |||
902 | /* | ||
903 | * TX_LINK_CFG: | ||
904 | * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us | ||
905 | * MFB_ENABLE: TX apply remote MFB 1:enable | ||
906 | * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable | ||
907 | * 0: not apply remote remote unsolicit (MFS=7) | ||
908 | * TX_MRQ_EN: MCS request TX enable | ||
909 | * TX_RDG_EN: RDG TX enable | ||
910 | * TX_CF_ACK_EN: Piggyback CF-ACK enable | ||
911 | * REMOTE_MFB: remote MCS feedback | ||
912 | * REMOTE_MFS: remote MCS feedback sequence number | ||
913 | */ | ||
914 | #define TX_LINK_CFG 0x1350 | ||
915 | #define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) | ||
916 | #define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) | ||
917 | #define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) | ||
918 | #define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) | ||
919 | #define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) | ||
920 | #define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) | ||
921 | #define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) | ||
922 | #define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) | ||
923 | |||
924 | /* | ||
925 | * HT_FBK_CFG0: | ||
926 | */ | ||
927 | #define HT_FBK_CFG0 0x1354 | ||
928 | #define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) | ||
929 | #define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) | ||
930 | #define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) | ||
931 | #define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) | ||
932 | #define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) | ||
933 | #define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) | ||
934 | #define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) | ||
935 | #define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) | ||
936 | |||
937 | /* | ||
938 | * HT_FBK_CFG1: | ||
939 | */ | ||
940 | #define HT_FBK_CFG1 0x1358 | ||
941 | #define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) | ||
942 | #define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) | ||
943 | #define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) | ||
944 | #define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) | ||
945 | #define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) | ||
946 | #define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) | ||
947 | #define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) | ||
948 | #define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) | ||
949 | |||
950 | /* | ||
951 | * LG_FBK_CFG0: | ||
952 | */ | ||
953 | #define LG_FBK_CFG0 0x135c | ||
954 | #define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) | ||
955 | #define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) | ||
956 | #define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) | ||
957 | #define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) | ||
958 | #define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) | ||
959 | #define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) | ||
960 | #define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) | ||
961 | #define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) | ||
962 | |||
963 | /* | ||
964 | * LG_FBK_CFG1: | ||
965 | */ | ||
966 | #define LG_FBK_CFG1 0x1360 | ||
967 | #define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) | ||
968 | #define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) | ||
969 | #define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) | ||
970 | #define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) | ||
971 | |||
972 | /* | ||
973 | * CCK_PROT_CFG: CCK Protection | ||
974 | * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) | ||
975 | * PROTECT_CTRL: Protection control frame type for CCK TX | ||
976 | * 0:none, 1:RTS/CTS, 2:CTS-to-self | ||
977 | * PROTECT_NAV: TXOP protection type for CCK TX | ||
978 | * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect | ||
979 | * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow | ||
980 | * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow | ||
981 | * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow | ||
982 | * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow | ||
983 | * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow | ||
984 | * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow | ||
985 | * RTS_TH_EN: RTS threshold enable on CCK TX | ||
986 | */ | ||
987 | #define CCK_PROT_CFG 0x1364 | ||
988 | #define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
989 | #define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
990 | #define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
991 | #define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
992 | #define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
993 | #define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
994 | #define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
995 | #define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
996 | #define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
997 | #define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
998 | |||
999 | /* | ||
1000 | * OFDM_PROT_CFG: OFDM Protection | ||
1001 | */ | ||
1002 | #define OFDM_PROT_CFG 0x1368 | ||
1003 | #define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
1004 | #define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
1005 | #define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
1006 | #define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
1007 | #define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
1008 | #define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
1009 | #define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
1010 | #define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
1011 | #define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
1012 | #define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
1013 | |||
1014 | /* | ||
1015 | * MM20_PROT_CFG: MM20 Protection | ||
1016 | */ | ||
1017 | #define MM20_PROT_CFG 0x136c | ||
1018 | #define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
1019 | #define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
1020 | #define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
1021 | #define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
1022 | #define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
1023 | #define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
1024 | #define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
1025 | #define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
1026 | #define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
1027 | #define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
1028 | |||
1029 | /* | ||
1030 | * MM40_PROT_CFG: MM40 Protection | ||
1031 | */ | ||
1032 | #define MM40_PROT_CFG 0x1370 | ||
1033 | #define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
1034 | #define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
1035 | #define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
1036 | #define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
1037 | #define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
1038 | #define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
1039 | #define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
1040 | #define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
1041 | #define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
1042 | #define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
1043 | |||
1044 | /* | ||
1045 | * GF20_PROT_CFG: GF20 Protection | ||
1046 | */ | ||
1047 | #define GF20_PROT_CFG 0x1374 | ||
1048 | #define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
1049 | #define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
1050 | #define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
1051 | #define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
1052 | #define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
1053 | #define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
1054 | #define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
1055 | #define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
1056 | #define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
1057 | #define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
1058 | |||
1059 | /* | ||
1060 | * GF40_PROT_CFG: GF40 Protection | ||
1061 | */ | ||
1062 | #define GF40_PROT_CFG 0x1378 | ||
1063 | #define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) | ||
1064 | #define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) | ||
1065 | #define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) | ||
1066 | #define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) | ||
1067 | #define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) | ||
1068 | #define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) | ||
1069 | #define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) | ||
1070 | #define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) | ||
1071 | #define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) | ||
1072 | #define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) | ||
1073 | |||
1074 | /* | ||
1075 | * EXP_CTS_TIME: | ||
1076 | */ | ||
1077 | #define EXP_CTS_TIME 0x137c | ||
1078 | |||
1079 | /* | ||
1080 | * EXP_ACK_TIME: | ||
1081 | */ | ||
1082 | #define EXP_ACK_TIME 0x1380 | ||
1083 | |||
1084 | /* | ||
1085 | * RX_FILTER_CFG: RX configuration register. | ||
1086 | */ | ||
1087 | #define RX_FILTER_CFG 0x1400 | ||
1088 | #define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) | ||
1089 | #define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) | ||
1090 | #define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) | ||
1091 | #define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) | ||
1092 | #define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) | ||
1093 | #define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) | ||
1094 | #define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) | ||
1095 | #define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) | ||
1096 | #define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) | ||
1097 | #define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) | ||
1098 | #define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) | ||
1099 | #define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) | ||
1100 | #define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) | ||
1101 | #define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) | ||
1102 | #define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) | ||
1103 | #define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) | ||
1104 | #define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) | ||
1105 | |||
1106 | /* | ||
1107 | * AUTO_RSP_CFG: | ||
1108 | * AUTORESPONDER: 0: disable, 1: enable | ||
1109 | * BAC_ACK_POLICY: 0:long, 1:short preamble | ||
1110 | * CTS_40_MMODE: Response CTS 40MHz duplicate mode | ||
1111 | * CTS_40_MREF: Response CTS 40MHz duplicate mode | ||
1112 | * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble | ||
1113 | * DUAL_CTS_EN: Power bit value in control frame | ||
1114 | * ACK_CTS_PSM_BIT:Power bit value in control frame | ||
1115 | */ | ||
1116 | #define AUTO_RSP_CFG 0x1404 | ||
1117 | #define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) | ||
1118 | #define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) | ||
1119 | #define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) | ||
1120 | #define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) | ||
1121 | #define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) | ||
1122 | #define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) | ||
1123 | #define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) | ||
1124 | |||
1125 | /* | ||
1126 | * LEGACY_BASIC_RATE: | ||
1127 | */ | ||
1128 | #define LEGACY_BASIC_RATE 0x1408 | ||
1129 | |||
1130 | /* | ||
1131 | * HT_BASIC_RATE: | ||
1132 | */ | ||
1133 | #define HT_BASIC_RATE 0x140c | ||
1134 | |||
1135 | /* | ||
1136 | * HT_CTRL_CFG: | ||
1137 | */ | ||
1138 | #define HT_CTRL_CFG 0x1410 | ||
1139 | |||
1140 | /* | ||
1141 | * SIFS_COST_CFG: | ||
1142 | */ | ||
1143 | #define SIFS_COST_CFG 0x1414 | ||
1144 | |||
1145 | /* | ||
1146 | * RX_PARSER_CFG: | ||
1147 | * Set NAV for all received frames | ||
1148 | */ | ||
1149 | #define RX_PARSER_CFG 0x1418 | ||
1150 | |||
1151 | /* | ||
1152 | * TX_SEC_CNT0: | ||
1153 | */ | ||
1154 | #define TX_SEC_CNT0 0x1500 | ||
1155 | |||
1156 | /* | ||
1157 | * RX_SEC_CNT0: | ||
1158 | */ | ||
1159 | #define RX_SEC_CNT0 0x1504 | ||
1160 | |||
1161 | /* | ||
1162 | * CCMP_FC_MUTE: | ||
1163 | */ | ||
1164 | #define CCMP_FC_MUTE 0x1508 | ||
1165 | |||
1166 | /* | ||
1167 | * TXOP_HLDR_ADDR0: | ||
1168 | */ | ||
1169 | #define TXOP_HLDR_ADDR0 0x1600 | ||
1170 | |||
1171 | /* | ||
1172 | * TXOP_HLDR_ADDR1: | ||
1173 | */ | ||
1174 | #define TXOP_HLDR_ADDR1 0x1604 | ||
1175 | |||
1176 | /* | ||
1177 | * TXOP_HLDR_ET: | ||
1178 | */ | ||
1179 | #define TXOP_HLDR_ET 0x1608 | ||
1180 | |||
1181 | /* | ||
1182 | * QOS_CFPOLL_RA_DW0: | ||
1183 | */ | ||
1184 | #define QOS_CFPOLL_RA_DW0 0x160c | ||
1185 | |||
1186 | /* | ||
1187 | * QOS_CFPOLL_RA_DW1: | ||
1188 | */ | ||
1189 | #define QOS_CFPOLL_RA_DW1 0x1610 | ||
1190 | |||
1191 | /* | ||
1192 | * QOS_CFPOLL_QC: | ||
1193 | */ | ||
1194 | #define QOS_CFPOLL_QC 0x1614 | ||
1195 | |||
1196 | /* | ||
1197 | * RX_STA_CNT0: RX PLCP error count & RX CRC error count | ||
1198 | */ | ||
1199 | #define RX_STA_CNT0 0x1700 | ||
1200 | #define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) | ||
1201 | #define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) | ||
1202 | |||
1203 | /* | ||
1204 | * RX_STA_CNT1: RX False CCA count & RX LONG frame count | ||
1205 | */ | ||
1206 | #define RX_STA_CNT1 0x1704 | ||
1207 | #define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) | ||
1208 | #define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) | ||
1209 | |||
1210 | /* | ||
1211 | * RX_STA_CNT2: | ||
1212 | */ | ||
1213 | #define RX_STA_CNT2 0x1708 | ||
1214 | #define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) | ||
1215 | #define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) | ||
1216 | |||
1217 | /* | ||
1218 | * TX_STA_CNT0: TX Beacon count | ||
1219 | */ | ||
1220 | #define TX_STA_CNT0 0x170c | ||
1221 | #define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) | ||
1222 | #define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) | ||
1223 | |||
1224 | /* | ||
1225 | * TX_STA_CNT1: TX tx count | ||
1226 | */ | ||
1227 | #define TX_STA_CNT1 0x1710 | ||
1228 | #define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) | ||
1229 | #define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) | ||
1230 | |||
1231 | /* | ||
1232 | * TX_STA_CNT2: TX tx count | ||
1233 | */ | ||
1234 | #define TX_STA_CNT2 0x1714 | ||
1235 | #define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) | ||
1236 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) | ||
1237 | |||
1238 | /* | ||
1239 | * TX_STA_FIFO: TX Result for specific PID status fifo register | ||
1240 | */ | ||
1241 | #define TX_STA_FIFO 0x1718 | ||
1242 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) | ||
1243 | #define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) | ||
1244 | #define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) | ||
1245 | #define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) | ||
1246 | #define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) | ||
1247 | #define TX_STA_FIFO_WCID FIELD32(0x0000ff00) | ||
1248 | #define TX_STA_FIFO_MCS FIELD32(0x007f0000) | ||
1249 | #define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000) | ||
1250 | |||
1251 | /* | ||
1252 | * TX_AGG_CNT: Debug counter | ||
1253 | */ | ||
1254 | #define TX_AGG_CNT 0x171c | ||
1255 | #define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) | ||
1256 | #define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) | ||
1257 | |||
1258 | /* | ||
1259 | * TX_AGG_CNT0: | ||
1260 | */ | ||
1261 | #define TX_AGG_CNT0 0x1720 | ||
1262 | #define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) | ||
1263 | #define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) | ||
1264 | |||
1265 | /* | ||
1266 | * TX_AGG_CNT1: | ||
1267 | */ | ||
1268 | #define TX_AGG_CNT1 0x1724 | ||
1269 | #define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) | ||
1270 | #define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) | ||
1271 | |||
1272 | /* | ||
1273 | * TX_AGG_CNT2: | ||
1274 | */ | ||
1275 | #define TX_AGG_CNT2 0x1728 | ||
1276 | #define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) | ||
1277 | #define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) | ||
1278 | |||
1279 | /* | ||
1280 | * TX_AGG_CNT3: | ||
1281 | */ | ||
1282 | #define TX_AGG_CNT3 0x172c | ||
1283 | #define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) | ||
1284 | #define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) | ||
1285 | |||
1286 | /* | ||
1287 | * TX_AGG_CNT4: | ||
1288 | */ | ||
1289 | #define TX_AGG_CNT4 0x1730 | ||
1290 | #define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) | ||
1291 | #define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) | ||
1292 | |||
1293 | /* | ||
1294 | * TX_AGG_CNT5: | ||
1295 | */ | ||
1296 | #define TX_AGG_CNT5 0x1734 | ||
1297 | #define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) | ||
1298 | #define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) | ||
1299 | |||
1300 | /* | ||
1301 | * TX_AGG_CNT6: | ||
1302 | */ | ||
1303 | #define TX_AGG_CNT6 0x1738 | ||
1304 | #define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) | ||
1305 | #define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) | ||
1306 | |||
1307 | /* | ||
1308 | * TX_AGG_CNT7: | ||
1309 | */ | ||
1310 | #define TX_AGG_CNT7 0x173c | ||
1311 | #define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) | ||
1312 | #define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) | ||
1313 | |||
1314 | /* | ||
1315 | * MPDU_DENSITY_CNT: | ||
1316 | * TX_ZERO_DEL: TX zero length delimiter count | ||
1317 | * RX_ZERO_DEL: RX zero length delimiter count | ||
1318 | */ | ||
1319 | #define MPDU_DENSITY_CNT 0x1740 | ||
1320 | #define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) | ||
1321 | #define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) | ||
1322 | |||
1323 | /* | ||
1324 | * Security key table memory. | ||
1325 | * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry | ||
1326 | * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry | ||
1327 | * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry | ||
1328 | * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry | ||
1329 | * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry | ||
1330 | * SHARED_KEY_MODE_BASE: 4 bits * 32-entry | ||
1331 | */ | ||
1332 | #define MAC_WCID_BASE 0x1800 | ||
1333 | #define PAIRWISE_KEY_TABLE_BASE 0x4000 | ||
1334 | #define MAC_IVEIV_TABLE_BASE 0x6000 | ||
1335 | #define MAC_WCID_ATTRIBUTE_BASE 0x6800 | ||
1336 | #define SHARED_KEY_TABLE_BASE 0x6c00 | ||
1337 | #define SHARED_KEY_MODE_BASE 0x7000 | ||
1338 | |||
1339 | #define MAC_WCID_ENTRY(__idx) \ | ||
1340 | ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) | ||
1341 | #define PAIRWISE_KEY_ENTRY(__idx) \ | ||
1342 | ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) | ||
1343 | #define MAC_IVEIV_ENTRY(__idx) \ | ||
1344 | ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) | ||
1345 | #define MAC_WCID_ATTR_ENTRY(__idx) \ | ||
1346 | ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) | ||
1347 | #define SHARED_KEY_ENTRY(__idx) \ | ||
1348 | ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) | ||
1349 | #define SHARED_KEY_MODE_ENTRY(__idx) \ | ||
1350 | ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) | ||
1351 | |||
1352 | struct mac_wcid_entry { | ||
1353 | u8 mac[6]; | ||
1354 | u8 reserved[2]; | ||
1355 | } __attribute__ ((packed)); | ||
1356 | |||
1357 | struct hw_key_entry { | ||
1358 | u8 key[16]; | ||
1359 | u8 tx_mic[8]; | ||
1360 | u8 rx_mic[8]; | ||
1361 | } __attribute__ ((packed)); | ||
1362 | |||
1363 | struct mac_iveiv_entry { | ||
1364 | u8 iv[8]; | ||
1365 | } __attribute__ ((packed)); | ||
1366 | |||
1367 | /* | ||
1368 | * MAC_WCID_ATTRIBUTE: | ||
1369 | */ | ||
1370 | #define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) | ||
1371 | #define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) | ||
1372 | #define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) | ||
1373 | #define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) | ||
1374 | |||
1375 | /* | ||
1376 | * SHARED_KEY_MODE: | ||
1377 | */ | ||
1378 | #define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) | ||
1379 | #define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) | ||
1380 | #define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) | ||
1381 | #define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) | ||
1382 | #define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) | ||
1383 | #define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) | ||
1384 | #define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) | ||
1385 | #define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) | ||
1386 | |||
1387 | /* | ||
1388 | * HOST-MCU communication | ||
1389 | */ | ||
1390 | |||
1391 | /* | ||
1392 | * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. | ||
1393 | */ | ||
1394 | #define H2M_MAILBOX_CSR 0x7010 | ||
1395 | #define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) | ||
1396 | #define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) | ||
1397 | #define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) | ||
1398 | #define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) | ||
1399 | |||
1400 | /* | ||
1401 | * H2M_MAILBOX_CID: | ||
1402 | */ | ||
1403 | #define H2M_MAILBOX_CID 0x7014 | ||
1404 | #define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) | ||
1405 | #define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) | ||
1406 | #define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) | ||
1407 | #define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) | ||
1408 | |||
1409 | /* | ||
1410 | * H2M_MAILBOX_STATUS: | ||
1411 | */ | ||
1412 | #define H2M_MAILBOX_STATUS 0x701c | ||
1413 | |||
1414 | /* | ||
1415 | * H2M_INT_SRC: | ||
1416 | */ | ||
1417 | #define H2M_INT_SRC 0x7024 | ||
1418 | |||
1419 | /* | ||
1420 | * H2M_BBP_AGENT: | ||
1421 | */ | ||
1422 | #define H2M_BBP_AGENT 0x7028 | ||
1423 | |||
1424 | /* | ||
1425 | * MCU_LEDCS: LED control for MCU Mailbox. | ||
1426 | */ | ||
1427 | #define MCU_LEDCS_LED_MODE FIELD8(0x1f) | ||
1428 | #define MCU_LEDCS_POLARITY FIELD8(0x01) | ||
1429 | |||
1430 | /* | ||
1431 | * HW_CS_CTS_BASE: | ||
1432 | * Carrier-sense CTS frame base address. | ||
1433 | * It's where mac stores carrier-sense frame for carrier-sense function. | ||
1434 | */ | ||
1435 | #define HW_CS_CTS_BASE 0x7700 | ||
1436 | |||
1437 | /* | ||
1438 | * HW_DFS_CTS_BASE: | ||
1439 | * FS CTS frame base address. It's where mac stores CTS frame for DFS. | ||
1440 | */ | ||
1441 | #define HW_DFS_CTS_BASE 0x7780 | ||
1442 | |||
1443 | /* | ||
1444 | * TXRX control registers - base address 0x3000 | ||
1445 | */ | ||
1446 | |||
1447 | /* | ||
1448 | * TXRX_CSR1: | ||
1449 | * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. | ||
1450 | */ | ||
1451 | #define TXRX_CSR1 0x77d0 | ||
1452 | |||
1453 | /* | ||
1454 | * HW_DEBUG_SETTING_BASE: | ||
1455 | * since NULL frame won't be that long (256 byte) | ||
1456 | * We steal 16 tail bytes to save debugging settings | ||
1457 | */ | ||
1458 | #define HW_DEBUG_SETTING_BASE 0x77f0 | ||
1459 | #define HW_DEBUG_SETTING_BASE2 0x7770 | ||
1460 | |||
1461 | /* | ||
1462 | * HW_BEACON_BASE | ||
1463 | * In order to support maximum 8 MBSS and its maximum length | ||
1464 | * is 512 bytes for each beacon | ||
1465 | * Three section discontinue memory segments will be used. | ||
1466 | * 1. The original region for BCN 0~3 | ||
1467 | * 2. Extract memory from FCE table for BCN 4~5 | ||
1468 | * 3. Extract memory from Pair-wise key table for BCN 6~7 | ||
1469 | * It occupied those memory of wcid 238~253 for BCN 6 | ||
1470 | * and wcid 222~237 for BCN 7 | ||
1471 | * | ||
1472 | * IMPORTANT NOTE: Not sure why legacy driver does this, | ||
1473 | * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. | ||
1474 | */ | ||
1475 | #define HW_BEACON_BASE0 0x7800 | ||
1476 | #define HW_BEACON_BASE1 0x7a00 | ||
1477 | #define HW_BEACON_BASE2 0x7c00 | ||
1478 | #define HW_BEACON_BASE3 0x7e00 | ||
1479 | #define HW_BEACON_BASE4 0x7200 | ||
1480 | #define HW_BEACON_BASE5 0x7400 | ||
1481 | #define HW_BEACON_BASE6 0x5dc0 | ||
1482 | #define HW_BEACON_BASE7 0x5bc0 | ||
1483 | |||
1484 | #define HW_BEACON_OFFSET(__index) \ | ||
1485 | ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ | ||
1486 | (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ | ||
1487 | (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) | ||
1488 | |||
1489 | /* | ||
1490 | * 8051 firmware image. | ||
1491 | */ | ||
1492 | #define FIRMWARE_RT2860 "rt2860.bin" | ||
1493 | #define FIRMWARE_IMAGE_BASE 0x2000 | ||
1494 | |||
1495 | /* | ||
1496 | * BBP registers. | ||
1497 | * The wordsize of the BBP is 8 bits. | ||
1498 | */ | ||
1499 | |||
1500 | /* | ||
1501 | * BBP 1: TX Antenna | ||
1502 | */ | ||
1503 | #define BBP1_TX_POWER FIELD8(0x07) | ||
1504 | #define BBP1_TX_ANTENNA FIELD8(0x18) | ||
1505 | |||
1506 | /* | ||
1507 | * BBP 3: RX Antenna | ||
1508 | */ | ||
1509 | #define BBP3_RX_ANTENNA FIELD8(0x18) | ||
1510 | #define BBP3_HT40_PLUS FIELD8(0x20) | ||
1511 | |||
1512 | /* | ||
1513 | * BBP 4: Bandwidth | ||
1514 | */ | ||
1515 | #define BBP4_TX_BF FIELD8(0x01) | ||
1516 | #define BBP4_BANDWIDTH FIELD8(0x18) | ||
1517 | |||
1518 | /* | ||
1519 | * RFCSR registers | ||
1520 | * The wordsize of the RFCSR is 8 bits. | ||
1521 | */ | ||
1522 | |||
1523 | /* | ||
1524 | * RFCSR 6: | ||
1525 | */ | ||
1526 | #define RFCSR6_R FIELD8(0x03) | ||
1527 | |||
1528 | /* | ||
1529 | * RFCSR 7: | ||
1530 | */ | ||
1531 | #define RFCSR7_RF_TUNING FIELD8(0x01) | ||
1532 | |||
1533 | /* | ||
1534 | * RFCSR 12: | ||
1535 | */ | ||
1536 | #define RFCSR12_TX_POWER FIELD8(0x1f) | ||
1537 | |||
1538 | /* | ||
1539 | * RFCSR 22: | ||
1540 | */ | ||
1541 | #define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) | ||
1542 | |||
1543 | /* | ||
1544 | * RFCSR 23: | ||
1545 | */ | ||
1546 | #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) | ||
1547 | |||
1548 | /* | ||
1549 | * RFCSR 30: | ||
1550 | */ | ||
1551 | #define RFCSR30_RF_CALIBRATION FIELD8(0x80) | ||
1552 | |||
1553 | /* | ||
1554 | * RF registers | ||
1555 | */ | ||
1556 | |||
1557 | /* | ||
1558 | * RF 2 | ||
1559 | */ | ||
1560 | #define RF2_ANTENNA_RX2 FIELD32(0x00000040) | ||
1561 | #define RF2_ANTENNA_TX1 FIELD32(0x00004000) | ||
1562 | #define RF2_ANTENNA_RX1 FIELD32(0x00020000) | ||
1563 | |||
1564 | /* | ||
1565 | * RF 3 | ||
1566 | */ | ||
1567 | #define RF3_TXPOWER_G FIELD32(0x00003e00) | ||
1568 | #define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) | ||
1569 | #define RF3_TXPOWER_A FIELD32(0x00003c00) | ||
1570 | |||
1571 | /* | ||
1572 | * RF 4 | ||
1573 | */ | ||
1574 | #define RF4_TXPOWER_G FIELD32(0x000007c0) | ||
1575 | #define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) | ||
1576 | #define RF4_TXPOWER_A FIELD32(0x00000780) | ||
1577 | #define RF4_FREQ_OFFSET FIELD32(0x001f8000) | ||
1578 | #define RF4_HT40 FIELD32(0x00200000) | ||
1579 | |||
1580 | /* | ||
1581 | * EEPROM content. | ||
1582 | * The wordsize of the EEPROM is 16 bits. | ||
1583 | */ | ||
1584 | |||
1585 | /* | ||
1586 | * EEPROM Version | ||
1587 | */ | ||
1588 | #define EEPROM_VERSION 0x0001 | ||
1589 | #define EEPROM_VERSION_FAE FIELD16(0x00ff) | ||
1590 | #define EEPROM_VERSION_VERSION FIELD16(0xff00) | ||
1591 | |||
1592 | /* | ||
1593 | * HW MAC address. | ||
1594 | */ | ||
1595 | #define EEPROM_MAC_ADDR_0 0x0002 | ||
1596 | #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) | ||
1597 | #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) | ||
1598 | #define EEPROM_MAC_ADDR_1 0x0003 | ||
1599 | #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) | ||
1600 | #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) | ||
1601 | #define EEPROM_MAC_ADDR_2 0x0004 | ||
1602 | #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) | ||
1603 | #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) | ||
1604 | |||
1605 | /* | ||
1606 | * EEPROM ANTENNA config | ||
1607 | * RXPATH: 1: 1R, 2: 2R, 3: 3R | ||
1608 | * TXPATH: 1: 1T, 2: 2T | ||
1609 | */ | ||
1610 | #define EEPROM_ANTENNA 0x001a | ||
1611 | #define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) | ||
1612 | #define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) | ||
1613 | #define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) | ||
1614 | |||
1615 | /* | ||
1616 | * EEPROM NIC config | ||
1617 | * CARDBUS_ACCEL: 0 - enable, 1 - disable | ||
1618 | */ | ||
1619 | #define EEPROM_NIC 0x001b | ||
1620 | #define EEPROM_NIC_HW_RADIO FIELD16(0x0001) | ||
1621 | #define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) | ||
1622 | #define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) | ||
1623 | #define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) | ||
1624 | #define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) | ||
1625 | #define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) | ||
1626 | #define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) | ||
1627 | #define EEPROM_NIC_WPS_PBC FIELD16(0x0080) | ||
1628 | #define EEPROM_NIC_BW40M_BG FIELD16(0x0100) | ||
1629 | #define EEPROM_NIC_BW40M_A FIELD16(0x0200) | ||
1630 | |||
1631 | /* | ||
1632 | * EEPROM frequency | ||
1633 | */ | ||
1634 | #define EEPROM_FREQ 0x001d | ||
1635 | #define EEPROM_FREQ_OFFSET FIELD16(0x00ff) | ||
1636 | #define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) | ||
1637 | #define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) | ||
1638 | |||
1639 | /* | ||
1640 | * EEPROM LED | ||
1641 | * POLARITY_RDY_G: Polarity RDY_G setting. | ||
1642 | * POLARITY_RDY_A: Polarity RDY_A setting. | ||
1643 | * POLARITY_ACT: Polarity ACT setting. | ||
1644 | * POLARITY_GPIO_0: Polarity GPIO0 setting. | ||
1645 | * POLARITY_GPIO_1: Polarity GPIO1 setting. | ||
1646 | * POLARITY_GPIO_2: Polarity GPIO2 setting. | ||
1647 | * POLARITY_GPIO_3: Polarity GPIO3 setting. | ||
1648 | * POLARITY_GPIO_4: Polarity GPIO4 setting. | ||
1649 | * LED_MODE: Led mode. | ||
1650 | */ | ||
1651 | #define EEPROM_LED1 0x001e | ||
1652 | #define EEPROM_LED2 0x001f | ||
1653 | #define EEPROM_LED3 0x0020 | ||
1654 | #define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) | ||
1655 | #define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) | ||
1656 | #define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) | ||
1657 | #define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) | ||
1658 | #define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) | ||
1659 | #define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) | ||
1660 | #define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) | ||
1661 | #define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) | ||
1662 | #define EEPROM_LED_LED_MODE FIELD16(0x1f00) | ||
1663 | |||
1664 | /* | ||
1665 | * EEPROM LNA | ||
1666 | */ | ||
1667 | #define EEPROM_LNA 0x0022 | ||
1668 | #define EEPROM_LNA_BG FIELD16(0x00ff) | ||
1669 | #define EEPROM_LNA_A0 FIELD16(0xff00) | ||
1670 | |||
1671 | /* | ||
1672 | * EEPROM RSSI BG offset | ||
1673 | */ | ||
1674 | #define EEPROM_RSSI_BG 0x0023 | ||
1675 | #define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) | ||
1676 | #define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) | ||
1677 | |||
1678 | /* | ||
1679 | * EEPROM RSSI BG2 offset | ||
1680 | */ | ||
1681 | #define EEPROM_RSSI_BG2 0x0024 | ||
1682 | #define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) | ||
1683 | #define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) | ||
1684 | |||
1685 | /* | ||
1686 | * EEPROM RSSI A offset | ||
1687 | */ | ||
1688 | #define EEPROM_RSSI_A 0x0025 | ||
1689 | #define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) | ||
1690 | #define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) | ||
1691 | |||
1692 | /* | ||
1693 | * EEPROM RSSI A2 offset | ||
1694 | */ | ||
1695 | #define EEPROM_RSSI_A2 0x0026 | ||
1696 | #define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) | ||
1697 | #define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) | ||
1698 | |||
1699 | /* | ||
1700 | * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. | ||
1701 | * This is delta in 40MHZ. | ||
1702 | * VALUE: Tx Power dalta value (MAX=4) | ||
1703 | * TYPE: 1: Plus the delta value, 0: minus the delta value | ||
1704 | * TXPOWER: Enable: | ||
1705 | */ | ||
1706 | #define EEPROM_TXPOWER_DELTA 0x0028 | ||
1707 | #define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) | ||
1708 | #define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) | ||
1709 | #define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) | ||
1710 | |||
1711 | /* | ||
1712 | * EEPROM TXPOWER 802.11BG | ||
1713 | */ | ||
1714 | #define EEPROM_TXPOWER_BG1 0x0029 | ||
1715 | #define EEPROM_TXPOWER_BG2 0x0030 | ||
1716 | #define EEPROM_TXPOWER_BG_SIZE 7 | ||
1717 | #define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) | ||
1718 | #define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) | ||
1719 | |||
1720 | /* | ||
1721 | * EEPROM TXPOWER 802.11A | ||
1722 | */ | ||
1723 | #define EEPROM_TXPOWER_A1 0x003c | ||
1724 | #define EEPROM_TXPOWER_A2 0x0053 | ||
1725 | #define EEPROM_TXPOWER_A_SIZE 6 | ||
1726 | #define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) | ||
1727 | #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) | ||
1728 | |||
1729 | /* | ||
1730 | * EEPROM TXpower byrate: 20MHZ power | ||
1731 | */ | ||
1732 | #define EEPROM_TXPOWER_BYRATE 0x006f | ||
1733 | |||
1734 | /* | ||
1735 | * EEPROM BBP. | ||
1736 | */ | ||
1737 | #define EEPROM_BBP_START 0x0078 | ||
1738 | #define EEPROM_BBP_SIZE 16 | ||
1739 | #define EEPROM_BBP_VALUE FIELD16(0x00ff) | ||
1740 | #define EEPROM_BBP_REG_ID FIELD16(0xff00) | ||
1741 | |||
1742 | /* | ||
1743 | * MCU mailbox commands. | ||
1744 | */ | ||
1745 | #define MCU_SLEEP 0x30 | ||
1746 | #define MCU_WAKEUP 0x31 | ||
1747 | #define MCU_RADIO_OFF 0x35 | ||
1748 | #define MCU_CURRENT 0x36 | ||
1749 | #define MCU_LED 0x50 | ||
1750 | #define MCU_LED_STRENGTH 0x51 | ||
1751 | #define MCU_LED_1 0x52 | ||
1752 | #define MCU_LED_2 0x53 | ||
1753 | #define MCU_LED_3 0x54 | ||
1754 | #define MCU_RADAR 0x60 | ||
1755 | #define MCU_BOOT_SIGNAL 0x72 | ||
1756 | #define MCU_BBP_SIGNAL 0x80 | ||
1757 | #define MCU_POWER_SAVE 0x83 | ||
1758 | |||
1759 | /* | ||
1760 | * MCU mailbox tokens | ||
1761 | */ | ||
1762 | #define TOKEN_WAKUP 3 | ||
1763 | |||
1764 | /* | ||
1765 | * DMA descriptor defines. | ||
1766 | */ | ||
1767 | #define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
1768 | #define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
1769 | #define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
1770 | #define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) | ||
1771 | |||
1772 | /* | ||
1773 | * TX descriptor format for TX, PRIO and Beacon Ring. | ||
1774 | */ | ||
1775 | |||
1776 | /* | ||
1777 | * Word0 | ||
1778 | */ | ||
1779 | #define TXD_W0_SD_PTR0 FIELD32(0xffffffff) | ||
1780 | |||
1781 | /* | ||
1782 | * Word1 | ||
1783 | */ | ||
1784 | #define TXD_W1_SD_LEN1 FIELD32(0x00003fff) | ||
1785 | #define TXD_W1_LAST_SEC1 FIELD32(0x00004000) | ||
1786 | #define TXD_W1_BURST FIELD32(0x00008000) | ||
1787 | #define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) | ||
1788 | #define TXD_W1_LAST_SEC0 FIELD32(0x40000000) | ||
1789 | #define TXD_W1_DMA_DONE FIELD32(0x80000000) | ||
1790 | |||
1791 | /* | ||
1792 | * Word2 | ||
1793 | */ | ||
1794 | #define TXD_W2_SD_PTR1 FIELD32(0xffffffff) | ||
1795 | |||
1796 | /* | ||
1797 | * Word3 | ||
1798 | * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI | ||
1799 | * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. | ||
1800 | * 0:MGMT, 1:HCCA 2:EDCA | ||
1801 | */ | ||
1802 | #define TXD_W3_WIV FIELD32(0x01000000) | ||
1803 | #define TXD_W3_QSEL FIELD32(0x06000000) | ||
1804 | #define TXD_W3_TCO FIELD32(0x20000000) | ||
1805 | #define TXD_W3_UCO FIELD32(0x40000000) | ||
1806 | #define TXD_W3_ICO FIELD32(0x80000000) | ||
1807 | |||
1808 | /* | ||
1809 | * TX WI structure | ||
1810 | */ | ||
1811 | |||
1812 | /* | ||
1813 | * Word0 | ||
1814 | * FRAG: 1 To inform TKIP engine this is a fragment. | ||
1815 | * MIMO_PS: The remote peer is in dynamic MIMO-PS mode | ||
1816 | * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs | ||
1817 | * BW: Channel bandwidth 20MHz or 40 MHz | ||
1818 | * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED | ||
1819 | */ | ||
1820 | #define TXWI_W0_FRAG FIELD32(0x00000001) | ||
1821 | #define TXWI_W0_MIMO_PS FIELD32(0x00000002) | ||
1822 | #define TXWI_W0_CF_ACK FIELD32(0x00000004) | ||
1823 | #define TXWI_W0_TS FIELD32(0x00000008) | ||
1824 | #define TXWI_W0_AMPDU FIELD32(0x00000010) | ||
1825 | #define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) | ||
1826 | #define TXWI_W0_TX_OP FIELD32(0x00000300) | ||
1827 | #define TXWI_W0_MCS FIELD32(0x007f0000) | ||
1828 | #define TXWI_W0_BW FIELD32(0x00800000) | ||
1829 | #define TXWI_W0_SHORT_GI FIELD32(0x01000000) | ||
1830 | #define TXWI_W0_STBC FIELD32(0x06000000) | ||
1831 | #define TXWI_W0_IFS FIELD32(0x08000000) | ||
1832 | #define TXWI_W0_PHYMODE FIELD32(0xc0000000) | ||
1833 | |||
1834 | /* | ||
1835 | * Word1 | ||
1836 | */ | ||
1837 | #define TXWI_W1_ACK FIELD32(0x00000001) | ||
1838 | #define TXWI_W1_NSEQ FIELD32(0x00000002) | ||
1839 | #define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) | ||
1840 | #define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) | ||
1841 | #define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) | ||
1842 | #define TXWI_W1_PACKETID FIELD32(0xf0000000) | ||
1843 | |||
1844 | /* | ||
1845 | * Word2 | ||
1846 | */ | ||
1847 | #define TXWI_W2_IV FIELD32(0xffffffff) | ||
1848 | |||
1849 | /* | ||
1850 | * Word3 | ||
1851 | */ | ||
1852 | #define TXWI_W3_EIV FIELD32(0xffffffff) | ||
1853 | |||
1854 | /* | ||
1855 | * RX descriptor format for RX Ring. | ||
1856 | */ | ||
1857 | |||
1858 | /* | ||
1859 | * Word0 | ||
1860 | */ | ||
1861 | #define RXD_W0_SDP0 FIELD32(0xffffffff) | ||
1862 | |||
1863 | /* | ||
1864 | * Word1 | ||
1865 | */ | ||
1866 | #define RXD_W1_SDL1 FIELD32(0x00003fff) | ||
1867 | #define RXD_W1_SDL0 FIELD32(0x3fff0000) | ||
1868 | #define RXD_W1_LS0 FIELD32(0x40000000) | ||
1869 | #define RXD_W1_DMA_DONE FIELD32(0x80000000) | ||
1870 | |||
1871 | /* | ||
1872 | * Word2 | ||
1873 | */ | ||
1874 | #define RXD_W2_SDP1 FIELD32(0xffffffff) | ||
1875 | |||
1876 | /* | ||
1877 | * Word3 | ||
1878 | * AMSDU: RX with 802.3 header, not 802.11 header. | ||
1879 | * DECRYPTED: This frame is being decrypted. | ||
1880 | */ | ||
1881 | #define RXD_W3_BA FIELD32(0x00000001) | ||
1882 | #define RXD_W3_DATA FIELD32(0x00000002) | ||
1883 | #define RXD_W3_NULLDATA FIELD32(0x00000004) | ||
1884 | #define RXD_W3_FRAG FIELD32(0x00000008) | ||
1885 | #define RXD_W3_UNICAST_TO_ME FIELD32(0x00000010) | ||
1886 | #define RXD_W3_MULTICAST FIELD32(0x00000020) | ||
1887 | #define RXD_W3_BROADCAST FIELD32(0x00000040) | ||
1888 | #define RXD_W3_MY_BSS FIELD32(0x00000080) | ||
1889 | #define RXD_W3_CRC_ERROR FIELD32(0x00000100) | ||
1890 | #define RXD_W3_CIPHER_ERROR FIELD32(0x00000600) | ||
1891 | #define RXD_W3_AMSDU FIELD32(0x00000800) | ||
1892 | #define RXD_W3_HTC FIELD32(0x00001000) | ||
1893 | #define RXD_W3_RSSI FIELD32(0x00002000) | ||
1894 | #define RXD_W3_L2PAD FIELD32(0x00004000) | ||
1895 | #define RXD_W3_AMPDU FIELD32(0x00008000) | ||
1896 | #define RXD_W3_DECRYPTED FIELD32(0x00010000) | ||
1897 | #define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000) | ||
1898 | #define RXD_W3_PLCP_RSSI FIELD32(0x00040000) | ||
1899 | |||
1900 | /* | ||
1901 | * RX WI structure | ||
1902 | */ | ||
1903 | |||
1904 | /* | ||
1905 | * Word0 | ||
1906 | */ | ||
1907 | #define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) | ||
1908 | #define RXWI_W0_KEY_INDEX FIELD32(0x00000300) | ||
1909 | #define RXWI_W0_BSSID FIELD32(0x00001c00) | ||
1910 | #define RXWI_W0_UDF FIELD32(0x0000e000) | ||
1911 | #define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) | ||
1912 | #define RXWI_W0_TID FIELD32(0xf0000000) | ||
1913 | |||
1914 | /* | ||
1915 | * Word1 | ||
1916 | */ | ||
1917 | #define RXWI_W1_FRAG FIELD32(0x0000000f) | ||
1918 | #define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) | ||
1919 | #define RXWI_W1_MCS FIELD32(0x007f0000) | ||
1920 | #define RXWI_W1_BW FIELD32(0x00800000) | ||
1921 | #define RXWI_W1_SHORT_GI FIELD32(0x01000000) | ||
1922 | #define RXWI_W1_STBC FIELD32(0x06000000) | ||
1923 | #define RXWI_W1_PHYMODE FIELD32(0xc0000000) | ||
1924 | |||
1925 | /* | ||
1926 | * Word2 | ||
1927 | */ | ||
1928 | #define RXWI_W2_RSSI0 FIELD32(0x000000ff) | ||
1929 | #define RXWI_W2_RSSI1 FIELD32(0x0000ff00) | ||
1930 | #define RXWI_W2_RSSI2 FIELD32(0x00ff0000) | ||
1931 | |||
1932 | /* | ||
1933 | * Word3 | ||
1934 | */ | ||
1935 | #define RXWI_W3_SNR0 FIELD32(0x000000ff) | ||
1936 | #define RXWI_W3_SNR1 FIELD32(0x0000ff00) | ||
1937 | |||
1938 | /* | ||
1939 | * Macros for converting txpower from EEPROM to mac80211 value | ||
1940 | * and from mac80211 value to register value. | ||
1941 | */ | ||
1942 | #define MIN_G_TXPOWER 0 | ||
1943 | #define MIN_A_TXPOWER -7 | ||
1944 | #define MAX_G_TXPOWER 31 | ||
1945 | #define MAX_A_TXPOWER 15 | ||
1946 | #define DEFAULT_TXPOWER 5 | ||
1947 | |||
1948 | #define TXPOWER_G_FROM_DEV(__txpower) \ | ||
1949 | ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) | ||
1950 | |||
1951 | #define TXPOWER_G_TO_DEV(__txpower) \ | ||
1952 | clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) | ||
1953 | |||
1954 | #define TXPOWER_A_FROM_DEV(__txpower) \ | ||
1955 | ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) | ||
1956 | |||
1957 | #define TXPOWER_A_TO_DEV(__txpower) \ | ||
1958 | clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) | ||
1959 | |||
1960 | #endif /* RT2800PCI_H */ | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 27bc6b7fbfde..196de8ab8153 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -158,6 +158,13 @@ struct rt2x00_chip { | |||
158 | #define RT2561 0x0302 | 158 | #define RT2561 0x0302 |
159 | #define RT2661 0x0401 | 159 | #define RT2661 0x0401 |
160 | #define RT2571 0x1300 | 160 | #define RT2571 0x1300 |
161 | #define RT2860 0x0601 /* 2.4GHz PCI/CB */ | ||
162 | #define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ | ||
163 | #define RT2890 0x0701 /* 2.4GHz PCIe */ | ||
164 | #define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ | ||
165 | #define RT2880 0x2880 /* WSOC */ | ||
166 | #define RT3052 0x3052 /* WSOC */ | ||
167 | #define RT3090 0x3090 /* 2.4GHz PCIe */ | ||
161 | #define RT2870 0x1600 | 168 | #define RT2870 0x1600 |
162 | 169 | ||
163 | u16 rf; | 170 | u16 rf; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c new file mode 100644 index 000000000000..539568c48953 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00soc | ||
23 | Abstract: rt2x00 generic soc device routines. | ||
24 | */ | ||
25 | |||
26 | #include <linux/bug.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/platform_device.h> | ||
30 | |||
31 | #include "rt2x00.h" | ||
32 | #include "rt2x00soc.h" | ||
33 | |||
34 | static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev) | ||
35 | { | ||
36 | kfree(rt2x00dev->rf); | ||
37 | rt2x00dev->rf = NULL; | ||
38 | |||
39 | kfree(rt2x00dev->eeprom); | ||
40 | rt2x00dev->eeprom = NULL; | ||
41 | } | ||
42 | |||
43 | static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev) | ||
44 | { | ||
45 | struct platform_device *pdev = to_platform_device(rt2x00dev->dev); | ||
46 | struct resource *res; | ||
47 | |||
48 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
49 | if (!res) | ||
50 | return -ENODEV; | ||
51 | |||
52 | rt2x00dev->csr.base = (void __iomem *)KSEG1ADDR(res->start); | ||
53 | if (!rt2x00dev->csr.base) | ||
54 | goto exit; | ||
55 | |||
56 | rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); | ||
57 | if (!rt2x00dev->eeprom) | ||
58 | goto exit; | ||
59 | |||
60 | rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL); | ||
61 | if (!rt2x00dev->rf) | ||
62 | goto exit; | ||
63 | |||
64 | return 0; | ||
65 | |||
66 | exit: | ||
67 | ERROR_PROBE("Failed to allocate registers.\n"); | ||
68 | rt2x00soc_free_reg(rt2x00dev); | ||
69 | |||
70 | return -ENOMEM; | ||
71 | } | ||
72 | |||
73 | int rt2x00soc_probe(struct platform_device *pdev, | ||
74 | const unsigned short chipset, | ||
75 | const struct rt2x00_ops *ops) | ||
76 | { | ||
77 | struct ieee80211_hw *hw; | ||
78 | struct rt2x00_dev *rt2x00dev; | ||
79 | int retval; | ||
80 | |||
81 | hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); | ||
82 | if (!hw) { | ||
83 | ERROR_PROBE("Failed to allocate hardware.\n"); | ||
84 | return -ENOMEM; | ||
85 | } | ||
86 | |||
87 | platform_set_drvdata(pdev, hw); | ||
88 | |||
89 | rt2x00dev = hw->priv; | ||
90 | rt2x00dev->dev = &pdev->dev; | ||
91 | rt2x00dev->ops = ops; | ||
92 | rt2x00dev->hw = hw; | ||
93 | rt2x00dev->irq = platform_get_irq(pdev, 0); | ||
94 | rt2x00dev->name = pdev->dev.driver->name; | ||
95 | |||
96 | rt2x00_set_chip_rt(rt2x00dev, chipset); | ||
97 | |||
98 | retval = rt2x00soc_alloc_reg(rt2x00dev); | ||
99 | if (retval) | ||
100 | goto exit_free_device; | ||
101 | |||
102 | retval = rt2x00lib_probe_dev(rt2x00dev); | ||
103 | if (retval) | ||
104 | goto exit_free_reg; | ||
105 | |||
106 | return 0; | ||
107 | |||
108 | exit_free_reg: | ||
109 | rt2x00soc_free_reg(rt2x00dev); | ||
110 | |||
111 | exit_free_device: | ||
112 | ieee80211_free_hw(hw); | ||
113 | |||
114 | return retval; | ||
115 | } | ||
116 | |||
117 | int rt2x00soc_remove(struct platform_device *pdev) | ||
118 | { | ||
119 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
120 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
121 | |||
122 | /* | ||
123 | * Free all allocated data. | ||
124 | */ | ||
125 | rt2x00lib_remove_dev(rt2x00dev); | ||
126 | rt2x00soc_free_reg(rt2x00dev); | ||
127 | ieee80211_free_hw(hw); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(rt2x00soc_remove); | ||
132 | |||
133 | #ifdef CONFIG_PM | ||
134 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state) | ||
135 | { | ||
136 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
137 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
138 | |||
139 | return rt2x00lib_suspend(rt2x00dev, state); | ||
140 | } | ||
141 | EXPORT_SYMBOL_GPL(rt2x00soc_suspend); | ||
142 | |||
143 | int rt2x00soc_resume(struct platform_device *pdev) | ||
144 | { | ||
145 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
146 | struct rt2x00_dev *rt2x00dev = hw->priv; | ||
147 | |||
148 | return rt2x00lib_resume(rt2x00dev); | ||
149 | } | ||
150 | EXPORT_SYMBOL_GPL(rt2x00soc_resume); | ||
151 | #endif /* CONFIG_PM */ | ||
152 | |||
153 | /* | ||
154 | * rt2x00soc module information. | ||
155 | */ | ||
156 | MODULE_AUTHOR(DRV_PROJECT); | ||
157 | MODULE_VERSION(DRV_VERSION); | ||
158 | MODULE_DESCRIPTION("rt2x00 soc library"); | ||
159 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h new file mode 100644 index 000000000000..5cf114ac2b9c --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | Copyright (C) 2004 - 2009 rt2x00 SourceForge Project | ||
3 | <http://rt2x00.serialmonkey.com> | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the | ||
17 | Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | Module: rt2x00soc | ||
23 | Abstract: Data structures for the rt2x00soc module. | ||
24 | */ | ||
25 | |||
26 | #ifndef RT2X00SOC_H | ||
27 | #define RT2X00SOC_H | ||
28 | |||
29 | #define KSEG1ADDR(__ptr) __ptr | ||
30 | |||
31 | #define __rt2x00soc_probe(__chipset, __ops) \ | ||
32 | static int __rt2x00soc_probe(struct platform_device *pdev) \ | ||
33 | { \ | ||
34 | return rt2x00soc_probe(pdev, (__chipset), (__ops)); \ | ||
35 | } | ||
36 | |||
37 | /* | ||
38 | * SoC driver handlers. | ||
39 | */ | ||
40 | int rt2x00soc_probe(struct platform_device *pdev, | ||
41 | const unsigned short chipset, | ||
42 | const struct rt2x00_ops *ops); | ||
43 | int rt2x00soc_remove(struct platform_device *pdev); | ||
44 | #ifdef CONFIG_PM | ||
45 | int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state); | ||
46 | int rt2x00soc_resume(struct platform_device *pdev); | ||
47 | #else | ||
48 | #define rt2x00soc_suspend NULL | ||
49 | #define rt2x00soc_resume NULL | ||
50 | #endif /* CONFIG_PM */ | ||
51 | |||
52 | #endif /* RT2X00SOC_H */ | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 1103256ad989..48b0bfd6c55a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -183,8 +183,11 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
183 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", | 183 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", |
184 | wl->chip_id); | 184 | wl->chip_id); |
185 | break; | 185 | break; |
186 | case CHIP_ID_1251_PG10: | ||
187 | case CHIP_ID_1251_PG11: | 186 | case CHIP_ID_1251_PG11: |
187 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)", | ||
188 | wl->chip_id); | ||
189 | break; | ||
190 | case CHIP_ID_1251_PG10: | ||
188 | default: | 191 | default: |
189 | wl1251_error("unsupported chip id: 0x%x", wl->chip_id); | 192 | wl1251_error("unsupported chip id: 0x%x", wl->chip_id); |
190 | ret = -ENODEV; | 193 | ret = -ENODEV; |
@@ -1426,4 +1429,4 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw); | |||
1426 | MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); | 1429 | MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); |
1427 | MODULE_LICENSE("GPL"); | 1430 | MODULE_LICENSE("GPL"); |
1428 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); | 1431 | MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>"); |
1429 | MODULE_ALIAS("spi:wl12xx"); | 1432 | MODULE_ALIAS("spi:wl1251"); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 17c54b59ef86..601fe0d67827 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -153,7 +153,7 @@ static void wl1251_rx_body(struct wl1251 *wl, | |||
153 | beacon ? "beacon" : ""); | 153 | beacon ? "beacon" : ""); |
154 | 154 | ||
155 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 155 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
156 | ieee80211_rx(wl->hw, skb); | 156 | ieee80211_rx_ni(wl->hw, skb); |
157 | } | 157 | } |
158 | 158 | ||
159 | static void wl1251_rx_ack(struct wl1251 *wl) | 159 | static void wl1251_rx_ack(struct wl1251 *wl) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 14eff2b3d4c6..2cf8a2169d43 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -307,7 +307,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) | |||
307 | 307 | ||
308 | static struct spi_driver wl1251_spi_driver = { | 308 | static struct spi_driver wl1251_spi_driver = { |
309 | .driver = { | 309 | .driver = { |
310 | .name = "wl12xx", | 310 | .name = "wl1251", |
311 | .bus = &spi_bus_type, | 311 | .bus = &spi_bus_type, |
312 | .owner = THIS_MODULE, | 312 | .owner = THIS_MODULE, |
313 | }, | 313 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 55818f94017b..566f1521ec22 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | 34 | ||
35 | #include "wl1271_conf.h" | ||
36 | |||
35 | #define DRIVER_NAME "wl1271" | 37 | #define DRIVER_NAME "wl1271" |
36 | #define DRIVER_PREFIX DRIVER_NAME ": " | 38 | #define DRIVER_PREFIX DRIVER_NAME ": " |
37 | 39 | ||
@@ -97,21 +99,42 @@ enum { | |||
97 | } while (0) | 99 | } while (0) |
98 | 100 | ||
99 | #define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ | 101 | #define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ |
100 | CFG_BSSID_FILTER_EN) | 102 | CFG_BSSID_FILTER_EN | \ |
103 | CFG_MC_FILTER_EN) | ||
101 | 104 | ||
102 | #define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ | 105 | #define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ |
103 | CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ | 106 | CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ |
104 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
105 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
106 | 109 | ||
110 | #define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) | ||
111 | |||
107 | #define WL1271_FW_NAME "wl1271-fw.bin" | 112 | #define WL1271_FW_NAME "wl1271-fw.bin" |
108 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
109 | 114 | ||
110 | #define WL1271_BUSY_WORD_LEN 8 | 115 | /* |
116 | * Enable/disable 802.11a support for WL1273 | ||
117 | */ | ||
118 | #undef WL1271_80211A_ENABLED | ||
119 | |||
120 | /* | ||
121 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
122 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
123 | * with this mode occasionally on boot, so lets have three for now. A value of | ||
124 | * three should make sure, that the chipset will always be ready, though this | ||
125 | * will impact throughput and latencies slightly. | ||
126 | */ | ||
127 | #define WL1271_BUSY_WORD_CNT 3 | ||
128 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | ||
111 | 129 | ||
112 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 130 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
113 | #define WL1271_ELP_HW_STATE_IRQ 1 | 131 | #define WL1271_ELP_HW_STATE_IRQ 1 |
114 | 132 | ||
133 | #define WL1271_DEFAULT_BEACON_INT 100 | ||
134 | #define WL1271_DEFAULT_DTIM_PERIOD 1 | ||
135 | |||
136 | #define ACX_TX_DESCRIPTORS 32 | ||
137 | |||
115 | enum wl1271_state { | 138 | enum wl1271_state { |
116 | WL1271_STATE_OFF, | 139 | WL1271_STATE_OFF, |
117 | WL1271_STATE_ON, | 140 | WL1271_STATE_ON, |
@@ -134,6 +157,8 @@ struct wl1271_partition { | |||
134 | struct wl1271_partition_set { | 157 | struct wl1271_partition_set { |
135 | struct wl1271_partition mem; | 158 | struct wl1271_partition mem; |
136 | struct wl1271_partition reg; | 159 | struct wl1271_partition reg; |
160 | struct wl1271_partition mem2; | ||
161 | struct wl1271_partition mem3; | ||
137 | }; | 162 | }; |
138 | 163 | ||
139 | struct wl1271; | 164 | struct wl1271; |
@@ -258,15 +283,15 @@ struct wl1271_debugfs { | |||
258 | 283 | ||
259 | /* FW status registers */ | 284 | /* FW status registers */ |
260 | struct wl1271_fw_status { | 285 | struct wl1271_fw_status { |
261 | u32 intr; | 286 | __le32 intr; |
262 | u8 fw_rx_counter; | 287 | u8 fw_rx_counter; |
263 | u8 drv_rx_counter; | 288 | u8 drv_rx_counter; |
264 | u8 reserved; | 289 | u8 reserved; |
265 | u8 tx_results_counter; | 290 | u8 tx_results_counter; |
266 | u32 rx_pkt_descs[NUM_RX_PKT_DESC]; | 291 | __le32 rx_pkt_descs[NUM_RX_PKT_DESC]; |
267 | u32 tx_released_blks[NUM_TX_QUEUES]; | 292 | __le32 tx_released_blks[NUM_TX_QUEUES]; |
268 | u32 fw_localtime; | 293 | __le32 fw_localtime; |
269 | u32 padding[2]; | 294 | __le32 padding[2]; |
270 | } __attribute__ ((packed)); | 295 | } __attribute__ ((packed)); |
271 | 296 | ||
272 | struct wl1271_rx_mem_pool_addr { | 297 | struct wl1271_rx_mem_pool_addr { |
@@ -274,6 +299,15 @@ struct wl1271_rx_mem_pool_addr { | |||
274 | u32 addr_extra; | 299 | u32 addr_extra; |
275 | }; | 300 | }; |
276 | 301 | ||
302 | struct wl1271_scan { | ||
303 | u8 state; | ||
304 | u8 ssid[IW_ESSID_MAX_SIZE+1]; | ||
305 | size_t ssid_len; | ||
306 | u8 active; | ||
307 | u8 high_prio; | ||
308 | u8 probe_requests; | ||
309 | }; | ||
310 | |||
277 | struct wl1271 { | 311 | struct wl1271 { |
278 | struct ieee80211_hw *hw; | 312 | struct ieee80211_hw *hw; |
279 | bool mac80211_registered; | 313 | bool mac80211_registered; |
@@ -288,10 +322,7 @@ struct wl1271 { | |||
288 | enum wl1271_state state; | 322 | enum wl1271_state state; |
289 | struct mutex mutex; | 323 | struct mutex mutex; |
290 | 324 | ||
291 | int physical_mem_addr; | 325 | struct wl1271_partition_set part; |
292 | int physical_reg_addr; | ||
293 | int virtual_mem_addr; | ||
294 | int virtual_reg_addr; | ||
295 | 326 | ||
296 | struct wl1271_chip chip; | 327 | struct wl1271_chip chip; |
297 | 328 | ||
@@ -308,7 +339,6 @@ struct wl1271 { | |||
308 | u8 bss_type; | 339 | u8 bss_type; |
309 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | 340 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; |
310 | u8 ssid_len; | 341 | u8 ssid_len; |
311 | u8 listen_int; | ||
312 | int channel; | 342 | int channel; |
313 | 343 | ||
314 | struct wl1271_acx_mem_map *target_mem_map; | 344 | struct wl1271_acx_mem_map *target_mem_map; |
@@ -332,10 +362,14 @@ struct wl1271 { | |||
332 | bool tx_queue_stopped; | 362 | bool tx_queue_stopped; |
333 | 363 | ||
334 | struct work_struct tx_work; | 364 | struct work_struct tx_work; |
335 | struct work_struct filter_work; | ||
336 | 365 | ||
337 | /* Pending TX frames */ | 366 | /* Pending TX frames */ |
338 | struct sk_buff *tx_frames[16]; | 367 | struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; |
368 | |||
369 | /* Security sequence number counters */ | ||
370 | u8 tx_security_last_seq; | ||
371 | u16 tx_security_seq_16; | ||
372 | u32 tx_security_seq_32; | ||
339 | 373 | ||
340 | /* FW Rx counter */ | 374 | /* FW Rx counter */ |
341 | u32 rx_counter; | 375 | u32 rx_counter; |
@@ -354,10 +388,17 @@ struct wl1271 { | |||
354 | 388 | ||
355 | /* Are we currently scanning */ | 389 | /* Are we currently scanning */ |
356 | bool scanning; | 390 | bool scanning; |
391 | struct wl1271_scan scan; | ||
357 | 392 | ||
358 | /* Our association ID */ | 393 | /* Our association ID */ |
359 | u16 aid; | 394 | u16 aid; |
360 | 395 | ||
396 | /* currently configured rate set */ | ||
397 | u32 basic_rate_set; | ||
398 | |||
399 | /* The current band */ | ||
400 | enum ieee80211_band band; | ||
401 | |||
361 | /* Default key (for WEP) */ | 402 | /* Default key (for WEP) */ |
362 | u32 default_key; | 403 | u32 default_key; |
363 | 404 | ||
@@ -368,6 +409,7 @@ struct wl1271 { | |||
368 | bool elp; | 409 | bool elp; |
369 | 410 | ||
370 | struct completion *elp_compl; | 411 | struct completion *elp_compl; |
412 | struct delayed_work elp_work; | ||
371 | 413 | ||
372 | /* we can be in psm, but not in elp, we have to differentiate */ | 414 | /* we can be in psm, but not in elp, we have to differentiate */ |
373 | bool psm; | 415 | bool psm; |
@@ -383,11 +425,20 @@ struct wl1271 { | |||
383 | 425 | ||
384 | u32 buffer_32; | 426 | u32 buffer_32; |
385 | u32 buffer_cmd; | 427 | u32 buffer_cmd; |
386 | u8 buffer_busyword[WL1271_BUSY_WORD_LEN]; | 428 | u32 buffer_busyword[WL1271_BUSY_WORD_CNT]; |
387 | struct wl1271_rx_descriptor *rx_descriptor; | ||
388 | 429 | ||
389 | struct wl1271_fw_status *fw_status; | 430 | struct wl1271_fw_status *fw_status; |
390 | struct wl1271_tx_hw_res_if *tx_res_if; | 431 | struct wl1271_tx_hw_res_if *tx_res_if; |
432 | |||
433 | struct ieee80211_vif *vif; | ||
434 | |||
435 | /* Used for a workaround to send disconnect before rejoining */ | ||
436 | bool joined; | ||
437 | |||
438 | /* Current chipset configuration */ | ||
439 | struct conf_drv_settings conf; | ||
440 | |||
441 | struct list_head list; | ||
391 | }; | 442 | }; |
392 | 443 | ||
393 | int wl1271_plt_start(struct wl1271 *wl); | 444 | int wl1271_plt_start(struct wl1271 *wl); |
@@ -404,4 +455,13 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
404 | /* WL1271 needs a 200ms sleep after power on */ | 455 | /* WL1271 needs a 200ms sleep after power on */ |
405 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 456 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
406 | 457 | ||
458 | static inline bool wl1271_11a_enabled(void) | ||
459 | { | ||
460 | #ifdef WL1271_80211A_ENABLED | ||
461 | return true; | ||
462 | #else | ||
463 | return false; | ||
464 | #endif | ||
465 | } | ||
466 | |||
407 | #endif | 467 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index f622a4092615..bf5a8680a462 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -34,8 +34,7 @@ | |||
34 | #include "wl1271_spi.h" | 34 | #include "wl1271_spi.h" |
35 | #include "wl1271_ps.h" | 35 | #include "wl1271_ps.h" |
36 | 36 | ||
37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, | 37 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl) |
38 | u8 listen_interval) | ||
39 | { | 38 | { |
40 | struct acx_wake_up_condition *wake_up; | 39 | struct acx_wake_up_condition *wake_up; |
41 | int ret; | 40 | int ret; |
@@ -48,8 +47,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, | |||
48 | goto out; | 47 | goto out; |
49 | } | 48 | } |
50 | 49 | ||
51 | wake_up->wake_up_event = wake_up_event; | 50 | wake_up->wake_up_event = wl->conf.conn.wake_up_event; |
52 | wake_up->listen_interval = listen_interval; | 51 | wake_up->listen_interval = wl->conf.conn.listen_interval; |
53 | 52 | ||
54 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, | 53 | ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, |
55 | wake_up, sizeof(*wake_up)); | 54 | wake_up, sizeof(*wake_up)); |
@@ -137,7 +136,12 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power) | |||
137 | goto out; | 136 | goto out; |
138 | } | 137 | } |
139 | 138 | ||
140 | acx->current_tx_power = power * 10; | 139 | /* |
140 | * FIXME: This is a workaround needed while we don't the correct | ||
141 | * calibration, to avoid distortions | ||
142 | */ | ||
143 | /* acx->current_tx_power = power * 10; */ | ||
144 | acx->current_tx_power = 70; | ||
141 | 145 | ||
142 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); | 146 | ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); |
143 | if (ret < 0) { | 147 | if (ret < 0) { |
@@ -193,7 +197,7 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, | |||
193 | return 0; | 197 | return 0; |
194 | } | 198 | } |
195 | 199 | ||
196 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time) | 200 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl) |
197 | { | 201 | { |
198 | struct acx_rx_msdu_lifetime *acx; | 202 | struct acx_rx_msdu_lifetime *acx; |
199 | int ret; | 203 | int ret; |
@@ -206,7 +210,7 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time) | |||
206 | goto out; | 210 | goto out; |
207 | } | 211 | } |
208 | 212 | ||
209 | acx->lifetime = life_time; | 213 | acx->lifetime = cpu_to_le32(wl->conf.rx.rx_msdu_life_time); |
210 | ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, | 214 | ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, |
211 | acx, sizeof(*acx)); | 215 | acx, sizeof(*acx)); |
212 | if (ret < 0) { | 216 | if (ret < 0) { |
@@ -232,8 +236,8 @@ int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter) | |||
232 | goto out; | 236 | goto out; |
233 | } | 237 | } |
234 | 238 | ||
235 | rx_config->config_options = config; | 239 | rx_config->config_options = cpu_to_le32(config); |
236 | rx_config->filter_options = filter; | 240 | rx_config->filter_options = cpu_to_le32(filter); |
237 | 241 | ||
238 | ret = wl1271_cmd_configure(wl, ACX_RX_CFG, | 242 | ret = wl1271_cmd_configure(wl, ACX_RX_CFG, |
239 | rx_config, sizeof(*rx_config)); | 243 | rx_config, sizeof(*rx_config)); |
@@ -260,7 +264,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) | |||
260 | goto out; | 264 | goto out; |
261 | } | 265 | } |
262 | 266 | ||
263 | /* FIXME: threshold value not set */ | 267 | pd->threshold = cpu_to_le32(wl->conf.rx.packet_detection_threshold); |
264 | 268 | ||
265 | ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); | 269 | ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); |
266 | if (ret < 0) { | 270 | if (ret < 0) { |
@@ -300,7 +304,8 @@ out: | |||
300 | return ret; | 304 | return ret; |
301 | } | 305 | } |
302 | 306 | ||
303 | int wl1271_acx_group_address_tbl(struct wl1271 *wl) | 307 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, |
308 | void *mc_list, u32 mc_list_len) | ||
304 | { | 309 | { |
305 | struct acx_dot11_grp_addr_tbl *acx; | 310 | struct acx_dot11_grp_addr_tbl *acx; |
306 | int ret; | 311 | int ret; |
@@ -314,9 +319,9 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl) | |||
314 | } | 319 | } |
315 | 320 | ||
316 | /* MAC filtering */ | 321 | /* MAC filtering */ |
317 | acx->enabled = 0; | 322 | acx->enabled = enable; |
318 | acx->num_groups = 0; | 323 | acx->num_groups = mc_list_len; |
319 | memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); | 324 | memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); |
320 | 325 | ||
321 | ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, | 326 | ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, |
322 | acx, sizeof(*acx)); | 327 | acx, sizeof(*acx)); |
@@ -343,8 +348,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl) | |||
343 | 348 | ||
344 | wl1271_debug(DEBUG_ACX, "acx service period timeout"); | 349 | wl1271_debug(DEBUG_ACX, "acx service period timeout"); |
345 | 350 | ||
346 | rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; | 351 | rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); |
347 | rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; | 352 | rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); |
348 | 353 | ||
349 | ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, | 354 | ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, |
350 | rx_timeout, sizeof(*rx_timeout)); | 355 | rx_timeout, sizeof(*rx_timeout)); |
@@ -372,7 +377,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | |||
372 | goto out; | 377 | goto out; |
373 | } | 378 | } |
374 | 379 | ||
375 | rts->threshold = rts_threshold; | 380 | rts->threshold = cpu_to_le16(rts_threshold); |
376 | 381 | ||
377 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); | 382 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); |
378 | if (ret < 0) { | 383 | if (ret < 0) { |
@@ -385,20 +390,29 @@ out: | |||
385 | return ret; | 390 | return ret; |
386 | } | 391 | } |
387 | 392 | ||
388 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl) | 393 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) |
389 | { | 394 | { |
390 | struct acx_beacon_filter_option *beacon_filter; | 395 | struct acx_beacon_filter_option *beacon_filter = NULL; |
391 | int ret; | 396 | int ret = 0; |
392 | 397 | ||
393 | wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); | 398 | wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); |
394 | 399 | ||
400 | if (enable_filter && | ||
401 | wl->conf.conn.bcn_filt_mode == CONF_BCN_FILT_MODE_DISABLED) | ||
402 | goto out; | ||
403 | |||
395 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); | 404 | beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); |
396 | if (!beacon_filter) { | 405 | if (!beacon_filter) { |
397 | ret = -ENOMEM; | 406 | ret = -ENOMEM; |
398 | goto out; | 407 | goto out; |
399 | } | 408 | } |
400 | 409 | ||
401 | beacon_filter->enable = 0; | 410 | beacon_filter->enable = enable_filter; |
411 | |||
412 | /* | ||
413 | * When set to zero, and the filter is enabled, beacons | ||
414 | * without the unicast TIM bit set are dropped. | ||
415 | */ | ||
402 | beacon_filter->max_num_beacons = 0; | 416 | beacon_filter->max_num_beacons = 0; |
403 | 417 | ||
404 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT, | 418 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT, |
@@ -416,7 +430,9 @@ out: | |||
416 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl) | 430 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl) |
417 | { | 431 | { |
418 | struct acx_beacon_filter_ie_table *ie_table; | 432 | struct acx_beacon_filter_ie_table *ie_table; |
433 | int i, idx = 0; | ||
419 | int ret; | 434 | int ret; |
435 | bool vendor_spec = false; | ||
420 | 436 | ||
421 | wl1271_debug(DEBUG_ACX, "acx beacon filter table"); | 437 | wl1271_debug(DEBUG_ACX, "acx beacon filter table"); |
422 | 438 | ||
@@ -426,8 +442,32 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl) | |||
426 | goto out; | 442 | goto out; |
427 | } | 443 | } |
428 | 444 | ||
445 | /* configure default beacon pass-through rules */ | ||
429 | ie_table->num_ie = 0; | 446 | ie_table->num_ie = 0; |
430 | memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); | 447 | for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { |
448 | struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); | ||
449 | ie_table->table[idx++] = r->ie; | ||
450 | ie_table->table[idx++] = r->rule; | ||
451 | |||
452 | if (r->ie == WLAN_EID_VENDOR_SPECIFIC) { | ||
453 | /* only one vendor specific ie allowed */ | ||
454 | if (vendor_spec) | ||
455 | continue; | ||
456 | |||
457 | /* for vendor specific rules configure the | ||
458 | additional fields */ | ||
459 | memcpy(&(ie_table->table[idx]), r->oui, | ||
460 | CONF_BCN_IE_OUI_LEN); | ||
461 | idx += CONF_BCN_IE_OUI_LEN; | ||
462 | ie_table->table[idx++] = r->type; | ||
463 | memcpy(&(ie_table->table[idx]), r->version, | ||
464 | CONF_BCN_IE_VER_LEN); | ||
465 | idx += CONF_BCN_IE_VER_LEN; | ||
466 | vendor_spec = true; | ||
467 | } | ||
468 | |||
469 | ie_table->num_ie++; | ||
470 | } | ||
431 | 471 | ||
432 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, | 472 | ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, |
433 | ie_table, sizeof(*ie_table)); | 473 | ie_table, sizeof(*ie_table)); |
@@ -441,6 +481,36 @@ out: | |||
441 | return ret; | 481 | return ret; |
442 | } | 482 | } |
443 | 483 | ||
484 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | ||
485 | { | ||
486 | struct acx_conn_monit_params *acx; | ||
487 | int ret; | ||
488 | |||
489 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | ||
490 | |||
491 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
492 | if (!acx) { | ||
493 | ret = -ENOMEM; | ||
494 | goto out; | ||
495 | } | ||
496 | |||
497 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | ||
498 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | ||
499 | |||
500 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | ||
501 | acx, sizeof(*acx)); | ||
502 | if (ret < 0) { | ||
503 | wl1271_warning("failed to set connection monitor " | ||
504 | "parameters: %d", ret); | ||
505 | goto out; | ||
506 | } | ||
507 | |||
508 | out: | ||
509 | kfree(acx); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | |||
444 | int wl1271_acx_sg_enable(struct wl1271 *wl) | 514 | int wl1271_acx_sg_enable(struct wl1271 *wl) |
445 | { | 515 | { |
446 | struct acx_bt_wlan_coex *pta; | 516 | struct acx_bt_wlan_coex *pta; |
@@ -470,6 +540,7 @@ out: | |||
470 | int wl1271_acx_sg_cfg(struct wl1271 *wl) | 540 | int wl1271_acx_sg_cfg(struct wl1271 *wl) |
471 | { | 541 | { |
472 | struct acx_bt_wlan_coex_param *param; | 542 | struct acx_bt_wlan_coex_param *param; |
543 | struct conf_sg_settings *c = &wl->conf.sg; | ||
473 | int ret; | 544 | int ret; |
474 | 545 | ||
475 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 546 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); |
@@ -481,34 +552,19 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
481 | } | 552 | } |
482 | 553 | ||
483 | /* BT-WLAN coext parameters */ | 554 | /* BT-WLAN coext parameters */ |
484 | param->min_rate = RATE_INDEX_24MBPS; | 555 | param->per_threshold = cpu_to_le32(c->per_threshold); |
485 | param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; | 556 | param->max_scan_compensation_time = |
486 | param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; | 557 | cpu_to_le32(c->max_scan_compensation_time); |
487 | param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; | 558 | param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval); |
488 | param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; | 559 | param->load_ratio = c->load_ratio; |
489 | param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; | 560 | param->auto_ps_mode = c->auto_ps_mode; |
490 | param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; | 561 | param->probe_req_compensation = c->probe_req_compensation; |
491 | param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; | 562 | param->scan_window_compensation = c->scan_window_compensation; |
492 | param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; | 563 | param->antenna_config = c->antenna_config; |
493 | param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; | 564 | param->beacon_miss_threshold = c->beacon_miss_threshold; |
494 | param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; | 565 | param->rate_adaptation_threshold = |
495 | param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; | 566 | cpu_to_le32(c->rate_adaptation_threshold); |
496 | param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; | 567 | param->rate_adaptation_snr = c->rate_adaptation_snr; |
497 | param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; | ||
498 | param->antenna_type = PTA_ANTENNA_TYPE_DEF; | ||
499 | param->signal_type = PTA_SIGNALING_TYPE_DEF; | ||
500 | param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; | ||
501 | param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; | ||
502 | param->max_cts = PTA_MAX_NUM_CTS_DEF; | ||
503 | param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; | ||
504 | param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; | ||
505 | param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; | ||
506 | param->wlan_elp_hp = PTA_ELP_HP_DEF; | ||
507 | param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; | ||
508 | param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; | ||
509 | param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; | ||
510 | param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; | ||
511 | param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; | ||
512 | 568 | ||
513 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 569 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
514 | if (ret < 0) { | 570 | if (ret < 0) { |
@@ -534,8 +590,8 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl) | |||
534 | goto out; | 590 | goto out; |
535 | } | 591 | } |
536 | 592 | ||
537 | detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; | 593 | detection->rx_cca_threshold = cpu_to_le16(wl->conf.rx.rx_cca_threshold); |
538 | detection->tx_energy_detection = 0; | 594 | detection->tx_energy_detection = wl->conf.tx.tx_energy_detection; |
539 | 595 | ||
540 | ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, | 596 | ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, |
541 | detection, sizeof(*detection)); | 597 | detection, sizeof(*detection)); |
@@ -562,10 +618,10 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) | |||
562 | goto out; | 618 | goto out; |
563 | } | 619 | } |
564 | 620 | ||
565 | bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; | 621 | bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); |
566 | bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; | 622 | bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); |
567 | bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; | 623 | bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; |
568 | bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; | 624 | bb->ps_poll_threshold = wl->conf.conn.ps_poll_threshold; |
569 | 625 | ||
570 | ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); | 626 | ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); |
571 | if (ret < 0) { | 627 | if (ret < 0) { |
@@ -591,7 +647,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid) | |||
591 | goto out; | 647 | goto out; |
592 | } | 648 | } |
593 | 649 | ||
594 | acx_aid->aid = aid; | 650 | acx_aid->aid = cpu_to_le16(aid); |
595 | 651 | ||
596 | ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); | 652 | ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); |
597 | if (ret < 0) { | 653 | if (ret < 0) { |
@@ -618,9 +674,8 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask) | |||
618 | } | 674 | } |
619 | 675 | ||
620 | /* high event mask is unused */ | 676 | /* high event mask is unused */ |
621 | mask->high_event_mask = 0xffffffff; | 677 | mask->high_event_mask = cpu_to_le32(0xffffffff); |
622 | 678 | mask->event_mask = cpu_to_le32(event_mask); | |
623 | mask->event_mask = event_mask; | ||
624 | 679 | ||
625 | ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK, | 680 | ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK, |
626 | mask, sizeof(*mask)); | 681 | mask, sizeof(*mask)); |
@@ -703,9 +758,10 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
703 | return 0; | 758 | return 0; |
704 | } | 759 | } |
705 | 760 | ||
706 | int wl1271_acx_rate_policies(struct wl1271 *wl) | 761 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) |
707 | { | 762 | { |
708 | struct acx_rate_policy *acx; | 763 | struct acx_rate_policy *acx; |
764 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | ||
709 | int ret = 0; | 765 | int ret = 0; |
710 | 766 | ||
711 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 767 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -718,11 +774,11 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
718 | } | 774 | } |
719 | 775 | ||
720 | /* configure one default (one-size-fits-all) rate class */ | 776 | /* configure one default (one-size-fits-all) rate class */ |
721 | acx->rate_class_cnt = 1; | 777 | acx->rate_class_cnt = cpu_to_le32(1); |
722 | acx->rate_class[0].enabled_rates = ACX_RATE_MASK_ALL; | 778 | acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); |
723 | acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; | 779 | acx->rate_class[0].short_retry_limit = c->short_retry_limit; |
724 | acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; | 780 | acx->rate_class[0].long_retry_limit = c->long_retry_limit; |
725 | acx->rate_class[0].aflags = 0; | 781 | acx->rate_class[0].aflags = c->aflags; |
726 | 782 | ||
727 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 783 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
728 | if (ret < 0) { | 784 | if (ret < 0) { |
@@ -749,22 +805,14 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl) | |||
749 | goto out; | 805 | goto out; |
750 | } | 806 | } |
751 | 807 | ||
752 | /* | 808 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { |
753 | * FIXME: Configure each AC with appropriate values (most suitable | 809 | struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]); |
754 | * values will probably be different for each AC. | 810 | acx->ac = c->ac; |
755 | */ | 811 | acx->cw_min = c->cw_min; |
756 | for (i = 0; i < WL1271_ACX_AC_COUNT; i++) { | 812 | acx->cw_max = cpu_to_le16(c->cw_max); |
757 | acx->ac = i; | 813 | acx->aifsn = c->aifsn; |
758 | |||
759 | /* | ||
760 | * FIXME: The following default values originate from | ||
761 | * the TI reference driver. What do they mean? | ||
762 | */ | ||
763 | acx->cw_min = 15; | ||
764 | acx->cw_max = 63; | ||
765 | acx->aifsn = 3; | ||
766 | acx->reserved = 0; | 814 | acx->reserved = 0; |
767 | acx->tx_op_limit = 0; | 815 | acx->tx_op_limit = cpu_to_le16(c->tx_op_limit); |
768 | 816 | ||
769 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); | 817 | ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); |
770 | if (ret < 0) { | 818 | if (ret < 0) { |
@@ -793,12 +841,15 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl) | |||
793 | goto out; | 841 | goto out; |
794 | } | 842 | } |
795 | 843 | ||
796 | /* FIXME: configure each TID with a different AC reference */ | 844 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { |
797 | for (i = 0; i < WL1271_ACX_TID_COUNT; i++) { | 845 | struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]); |
798 | acx->queue_id = i; | 846 | acx->queue_id = c->queue_id; |
799 | acx->tsid = WL1271_ACX_AC_BE; | 847 | acx->channel_type = c->channel_type; |
800 | acx->ps_scheme = WL1271_ACX_PS_SCHEME_LEGACY; | 848 | acx->tsid = c->tsid; |
801 | acx->ack_policy = WL1271_ACX_ACK_POLICY_LEGACY; | 849 | acx->ps_scheme = c->ps_scheme; |
850 | acx->ack_policy = c->ack_policy; | ||
851 | acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]); | ||
852 | acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]); | ||
802 | 853 | ||
803 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); | 854 | ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); |
804 | if (ret < 0) { | 855 | if (ret < 0) { |
@@ -826,7 +877,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl) | |||
826 | goto out; | 877 | goto out; |
827 | } | 878 | } |
828 | 879 | ||
829 | acx->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 880 | acx->frag_threshold = cpu_to_le16(wl->conf.tx.frag_threshold); |
830 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); | 881 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); |
831 | if (ret < 0) { | 882 | if (ret < 0) { |
832 | wl1271_warning("Setting of frag threshold failed: %d", ret); | 883 | wl1271_warning("Setting of frag threshold failed: %d", ret); |
@@ -852,8 +903,8 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl) | |||
852 | goto out; | 903 | goto out; |
853 | } | 904 | } |
854 | 905 | ||
855 | acx->tx_compl_timeout = WL1271_ACX_TX_COMPL_TIMEOUT; | 906 | acx->tx_compl_timeout = cpu_to_le16(wl->conf.tx.tx_compl_timeout); |
856 | acx->tx_compl_threshold = WL1271_ACX_TX_COMPL_THRESHOLD; | 907 | acx->tx_compl_threshold = cpu_to_le16(wl->conf.tx.tx_compl_threshold); |
857 | ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx)); | 908 | ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx)); |
858 | if (ret < 0) { | 909 | if (ret < 0) { |
859 | wl1271_warning("Setting of tx options failed: %d", ret); | 910 | wl1271_warning("Setting of tx options failed: %d", ret); |
@@ -879,11 +930,11 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl) | |||
879 | } | 930 | } |
880 | 931 | ||
881 | /* memory config */ | 932 | /* memory config */ |
882 | mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); | 933 | mem_conf->num_stations = DEFAULT_NUM_STATIONS; |
883 | mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; | 934 | mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; |
884 | mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; | 935 | mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; |
885 | mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; | 936 | mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; |
886 | mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS; | 937 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); |
887 | 938 | ||
888 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, | 939 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, |
889 | sizeof(*mem_conf)); | 940 | sizeof(*mem_conf)); |
@@ -906,7 +957,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) | |||
906 | return ret; | 957 | return ret; |
907 | 958 | ||
908 | wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), | 959 | wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), |
909 | GFP_KERNEL); | 960 | GFP_KERNEL); |
910 | if (!wl->target_mem_map) { | 961 | if (!wl->target_mem_map) { |
911 | wl1271_error("couldn't allocate target memory map"); | 962 | wl1271_error("couldn't allocate target memory map"); |
912 | return -ENOMEM; | 963 | return -ENOMEM; |
@@ -923,7 +974,8 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl) | |||
923 | } | 974 | } |
924 | 975 | ||
925 | /* initialize TX block book keeping */ | 976 | /* initialize TX block book keeping */ |
926 | wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks; | 977 | wl->tx_blocks_available = |
978 | le32_to_cpu(wl->target_mem_map->num_tx_mem_blocks); | ||
927 | wl1271_debug(DEBUG_TX, "available tx blocks: %d", | 979 | wl1271_debug(DEBUG_TX, "available tx blocks: %d", |
928 | wl->tx_blocks_available); | 980 | wl->tx_blocks_available); |
929 | 981 | ||
@@ -943,10 +995,10 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) | |||
943 | goto out; | 995 | goto out; |
944 | } | 996 | } |
945 | 997 | ||
946 | rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF; | 998 | rx_conf->threshold = cpu_to_le16(wl->conf.rx.irq_pkt_threshold); |
947 | rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF; | 999 | rx_conf->timeout = cpu_to_le16(wl->conf.rx.irq_timeout); |
948 | rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */ | 1000 | rx_conf->mblk_threshold = cpu_to_le16(wl->conf.rx.irq_blk_threshold); |
949 | rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY; | 1001 | rx_conf->queue_type = wl->conf.rx.queue_type; |
950 | 1002 | ||
951 | ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf, | 1003 | ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf, |
952 | sizeof(*rx_conf)); | 1004 | sizeof(*rx_conf)); |
@@ -959,3 +1011,124 @@ out: | |||
959 | kfree(rx_conf); | 1011 | kfree(rx_conf); |
960 | return ret; | 1012 | return ret; |
961 | } | 1013 | } |
1014 | |||
1015 | int wl1271_acx_smart_reflex(struct wl1271 *wl) | ||
1016 | { | ||
1017 | struct acx_smart_reflex_state *sr_state = NULL; | ||
1018 | struct acx_smart_reflex_config_params *sr_param = NULL; | ||
1019 | int i, ret; | ||
1020 | |||
1021 | wl1271_debug(DEBUG_ACX, "acx smart reflex"); | ||
1022 | |||
1023 | sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); | ||
1024 | if (!sr_param) { | ||
1025 | ret = -ENOMEM; | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { | ||
1030 | struct conf_mart_reflex_err_table *e = | ||
1031 | &(wl->conf.init.sr_err_tbl[i]); | ||
1032 | |||
1033 | sr_param->error_table[i].len = e->len; | ||
1034 | sr_param->error_table[i].upper_limit = e->upper_limit; | ||
1035 | memcpy(sr_param->error_table[i].values, e->values, e->len); | ||
1036 | } | ||
1037 | |||
1038 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, | ||
1039 | sr_param, sizeof(*sr_param)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); | ||
1046 | if (!sr_state) { | ||
1047 | ret = -ENOMEM; | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | /* enable smart reflex */ | ||
1052 | sr_state->enable = wl->conf.init.sr_enable; | ||
1053 | |||
1054 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, | ||
1055 | sr_state, sizeof(*sr_state)); | ||
1056 | if (ret < 0) { | ||
1057 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | |||
1061 | out: | ||
1062 | kfree(sr_state); | ||
1063 | kfree(sr_param); | ||
1064 | return ret; | ||
1065 | |||
1066 | } | ||
1067 | |||
1068 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | ||
1069 | { | ||
1070 | struct wl1271_acx_bet_enable *acx = NULL; | ||
1071 | int ret = 0; | ||
1072 | |||
1073 | wl1271_debug(DEBUG_ACX, "acx bet enable"); | ||
1074 | |||
1075 | if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE) | ||
1076 | goto out; | ||
1077 | |||
1078 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1079 | if (!acx) { | ||
1080 | ret = -ENOMEM; | ||
1081 | goto out; | ||
1082 | } | ||
1083 | |||
1084 | acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; | ||
1085 | acx->max_consecutive = wl->conf.conn.bet_max_consecutive; | ||
1086 | |||
1087 | ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx)); | ||
1088 | if (ret < 0) { | ||
1089 | wl1271_warning("acx bet enable failed: %d", ret); | ||
1090 | goto out; | ||
1091 | } | ||
1092 | |||
1093 | out: | ||
1094 | kfree(acx); | ||
1095 | return ret; | ||
1096 | } | ||
1097 | |||
1098 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | ||
1099 | u8 version) | ||
1100 | { | ||
1101 | struct wl1271_acx_arp_filter *acx; | ||
1102 | int ret; | ||
1103 | |||
1104 | wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable); | ||
1105 | |||
1106 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1107 | if (!acx) { | ||
1108 | ret = -ENOMEM; | ||
1109 | goto out; | ||
1110 | } | ||
1111 | |||
1112 | acx->version = version; | ||
1113 | acx->enable = enable; | ||
1114 | |||
1115 | if (enable == true) { | ||
1116 | if (version == ACX_IPV4_VERSION) | ||
1117 | memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE); | ||
1118 | else if (version == ACX_IPV6_VERSION) | ||
1119 | memcpy(acx->address, address, sizeof(acx->address)); | ||
1120 | else | ||
1121 | wl1271_error("Invalid IP version"); | ||
1122 | } | ||
1123 | |||
1124 | ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER, | ||
1125 | acx, sizeof(*acx)); | ||
1126 | if (ret < 0) { | ||
1127 | wl1271_warning("failed to set arp ip filter: %d", ret); | ||
1128 | goto out; | ||
1129 | } | ||
1130 | |||
1131 | out: | ||
1132 | kfree(acx); | ||
1133 | return ret; | ||
1134 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 9068daaf0ddf..2ce0a8128542 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -61,8 +61,9 @@ | |||
61 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 61 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
62 | WL1271_ACX_INTR_DATA) | 62 | WL1271_ACX_INTR_DATA) |
63 | 63 | ||
64 | #define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \ | 64 | #define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \ |
65 | WL1271_ACX_INTR_EVENT_B | \ | 65 | WL1271_ACX_INTR_EVENT_B | \ |
66 | WL1271_ACX_INTR_HW_AVAILABLE | \ | ||
66 | WL1271_ACX_INTR_DATA) | 67 | WL1271_ACX_INTR_DATA) |
67 | 68 | ||
68 | /* Target's information element */ | 69 | /* Target's information element */ |
@@ -70,11 +71,11 @@ struct acx_header { | |||
70 | struct wl1271_cmd_header cmd; | 71 | struct wl1271_cmd_header cmd; |
71 | 72 | ||
72 | /* acx (or information element) header */ | 73 | /* acx (or information element) header */ |
73 | u16 id; | 74 | __le16 id; |
74 | 75 | ||
75 | /* payload length (not including headers */ | 76 | /* payload length (not including headers */ |
76 | u16 len; | 77 | __le16 len; |
77 | }; | 78 | } __attribute__ ((packed)); |
78 | 79 | ||
79 | struct acx_error_counter { | 80 | struct acx_error_counter { |
80 | struct acx_header header; | 81 | struct acx_header header; |
@@ -82,21 +83,21 @@ struct acx_error_counter { | |||
82 | /* The number of PLCP errors since the last time this */ | 83 | /* The number of PLCP errors since the last time this */ |
83 | /* information element was interrogated. This field is */ | 84 | /* information element was interrogated. This field is */ |
84 | /* automatically cleared when it is interrogated.*/ | 85 | /* automatically cleared when it is interrogated.*/ |
85 | u32 PLCP_error; | 86 | __le32 PLCP_error; |
86 | 87 | ||
87 | /* The number of FCS errors since the last time this */ | 88 | /* The number of FCS errors since the last time this */ |
88 | /* information element was interrogated. This field is */ | 89 | /* information element was interrogated. This field is */ |
89 | /* automatically cleared when it is interrogated.*/ | 90 | /* automatically cleared when it is interrogated.*/ |
90 | u32 FCS_error; | 91 | __le32 FCS_error; |
91 | 92 | ||
92 | /* The number of MPDUs without PLCP header errors received*/ | 93 | /* The number of MPDUs without PLCP header errors received*/ |
93 | /* since the last time this information element was interrogated. */ | 94 | /* since the last time this information element was interrogated. */ |
94 | /* This field is automatically cleared when it is interrogated.*/ | 95 | /* This field is automatically cleared when it is interrogated.*/ |
95 | u32 valid_frame; | 96 | __le32 valid_frame; |
96 | 97 | ||
97 | /* the number of missed sequence numbers in the squentially */ | 98 | /* the number of missed sequence numbers in the squentially */ |
98 | /* values of frames seq numbers */ | 99 | /* values of frames seq numbers */ |
99 | u32 seq_num_miss; | 100 | __le32 seq_num_miss; |
100 | } __attribute__ ((packed)); | 101 | } __attribute__ ((packed)); |
101 | 102 | ||
102 | struct acx_revision { | 103 | struct acx_revision { |
@@ -125,7 +126,7 @@ struct acx_revision { | |||
125 | * (1 = first spin, 2 = second spin, and so on). | 126 | * (1 = first spin, 2 = second spin, and so on). |
126 | * bits 24 - 31: Chip ID - The WiLink chip ID. | 127 | * bits 24 - 31: Chip ID - The WiLink chip ID. |
127 | */ | 128 | */ |
128 | u32 hw_version; | 129 | __le32 hw_version; |
129 | } __attribute__ ((packed)); | 130 | } __attribute__ ((packed)); |
130 | 131 | ||
131 | enum wl1271_psm_mode { | 132 | enum wl1271_psm_mode { |
@@ -170,7 +171,6 @@ enum { | |||
170 | #define DP_RX_PACKET_RING_CHUNK_NUM 2 | 171 | #define DP_RX_PACKET_RING_CHUNK_NUM 2 |
171 | #define DP_TX_PACKET_RING_CHUNK_NUM 2 | 172 | #define DP_TX_PACKET_RING_CHUNK_NUM 2 |
172 | #define DP_TX_COMPLETE_TIME_OUT 20 | 173 | #define DP_TX_COMPLETE_TIME_OUT 20 |
173 | #define FW_TX_CMPLT_BLOCK_SIZE 16 | ||
174 | 174 | ||
175 | #define TX_MSDU_LIFETIME_MIN 0 | 175 | #define TX_MSDU_LIFETIME_MIN 0 |
176 | #define TX_MSDU_LIFETIME_MAX 3000 | 176 | #define TX_MSDU_LIFETIME_MAX 3000 |
@@ -186,7 +186,7 @@ struct acx_rx_msdu_lifetime { | |||
186 | * The maximum amount of time, in TU, before the | 186 | * The maximum amount of time, in TU, before the |
187 | * firmware discards the MSDU. | 187 | * firmware discards the MSDU. |
188 | */ | 188 | */ |
189 | u32 lifetime; | 189 | __le32 lifetime; |
190 | } __attribute__ ((packed)); | 190 | } __attribute__ ((packed)); |
191 | 191 | ||
192 | /* | 192 | /* |
@@ -273,14 +273,14 @@ struct acx_rx_msdu_lifetime { | |||
273 | struct acx_rx_config { | 273 | struct acx_rx_config { |
274 | struct acx_header header; | 274 | struct acx_header header; |
275 | 275 | ||
276 | u32 config_options; | 276 | __le32 config_options; |
277 | u32 filter_options; | 277 | __le32 filter_options; |
278 | } __attribute__ ((packed)); | 278 | } __attribute__ ((packed)); |
279 | 279 | ||
280 | struct acx_packet_detection { | 280 | struct acx_packet_detection { |
281 | struct acx_header header; | 281 | struct acx_header header; |
282 | 282 | ||
283 | u32 threshold; | 283 | __le32 threshold; |
284 | } __attribute__ ((packed)); | 284 | } __attribute__ ((packed)); |
285 | 285 | ||
286 | 286 | ||
@@ -302,8 +302,8 @@ struct acx_slot { | |||
302 | } __attribute__ ((packed)); | 302 | } __attribute__ ((packed)); |
303 | 303 | ||
304 | 304 | ||
305 | #define ADDRESS_GROUP_MAX (8) | 305 | #define ACX_MC_ADDRESS_GROUP_MAX (8) |
306 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) | 306 | #define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX) |
307 | 307 | ||
308 | struct acx_dot11_grp_addr_tbl { | 308 | struct acx_dot11_grp_addr_tbl { |
309 | struct acx_header header; | 309 | struct acx_header header; |
@@ -314,40 +314,17 @@ struct acx_dot11_grp_addr_tbl { | |||
314 | u8 mac_table[ADDRESS_GROUP_MAX_LEN]; | 314 | u8 mac_table[ADDRESS_GROUP_MAX_LEN]; |
315 | } __attribute__ ((packed)); | 315 | } __attribute__ ((packed)); |
316 | 316 | ||
317 | |||
318 | #define RX_TIMEOUT_PS_POLL_MIN 0 | ||
319 | #define RX_TIMEOUT_PS_POLL_MAX (200000) | ||
320 | #define RX_TIMEOUT_PS_POLL_DEF (15) | ||
321 | #define RX_TIMEOUT_UPSD_MIN 0 | ||
322 | #define RX_TIMEOUT_UPSD_MAX (200000) | ||
323 | #define RX_TIMEOUT_UPSD_DEF (15) | ||
324 | |||
325 | struct acx_rx_timeout { | 317 | struct acx_rx_timeout { |
326 | struct acx_header header; | 318 | struct acx_header header; |
327 | 319 | ||
328 | /* | 320 | __le16 ps_poll_timeout; |
329 | * The longest time the STA will wait to receive | 321 | __le16 upsd_timeout; |
330 | * traffic from the AP after a PS-poll has been | ||
331 | * transmitted. | ||
332 | */ | ||
333 | u16 ps_poll_timeout; | ||
334 | |||
335 | /* | ||
336 | * The longest time the STA will wait to receive | ||
337 | * traffic from the AP after a frame has been sent | ||
338 | * from an UPSD enabled queue. | ||
339 | */ | ||
340 | u16 upsd_timeout; | ||
341 | } __attribute__ ((packed)); | 322 | } __attribute__ ((packed)); |
342 | 323 | ||
343 | #define RTS_THRESHOLD_MIN 0 | ||
344 | #define RTS_THRESHOLD_MAX 4096 | ||
345 | #define RTS_THRESHOLD_DEF 2347 | ||
346 | |||
347 | struct acx_rts_threshold { | 324 | struct acx_rts_threshold { |
348 | struct acx_header header; | 325 | struct acx_header header; |
349 | 326 | ||
350 | u16 threshold; | 327 | __le16 threshold; |
351 | u8 pad[2]; | 328 | u8 pad[2]; |
352 | } __attribute__ ((packed)); | 329 | } __attribute__ ((packed)); |
353 | 330 | ||
@@ -408,6 +385,13 @@ struct acx_beacon_filter_ie_table { | |||
408 | u8 pad[3]; | 385 | u8 pad[3]; |
409 | } __attribute__ ((packed)); | 386 | } __attribute__ ((packed)); |
410 | 387 | ||
388 | struct acx_conn_monit_params { | ||
389 | struct acx_header header; | ||
390 | |||
391 | __le32 synch_fail_thold; /* number of beacons missed */ | ||
392 | __le32 bss_lose_timeout; /* number of TU's from synch fail */ | ||
393 | } __attribute__ ((packed)); | ||
394 | |||
411 | enum { | 395 | enum { |
412 | SG_ENABLE = 0, | 396 | SG_ENABLE = 0, |
413 | SG_DISABLE, | 397 | SG_DISABLE, |
@@ -431,6 +415,25 @@ struct acx_bt_wlan_coex { | |||
431 | u8 pad[3]; | 415 | u8 pad[3]; |
432 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
433 | 417 | ||
418 | struct acx_smart_reflex_state { | ||
419 | struct acx_header header; | ||
420 | |||
421 | u8 enable; | ||
422 | u8 padding[3]; | ||
423 | } __attribute__ ((packed)); | ||
424 | |||
425 | struct smart_reflex_err_table { | ||
426 | u8 len; | ||
427 | s8 upper_limit; | ||
428 | s8 values[14]; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct acx_smart_reflex_config_params { | ||
432 | struct acx_header header; | ||
433 | |||
434 | struct smart_reflex_err_table error_table[3]; | ||
435 | } __attribute__ ((packed)); | ||
436 | |||
434 | #define PTA_ANTENNA_TYPE_DEF (0) | 437 | #define PTA_ANTENNA_TYPE_DEF (0) |
435 | #define PTA_BT_HP_MAXTIME_DEF (2000) | 438 | #define PTA_BT_HP_MAXTIME_DEF (2000) |
436 | #define PTA_WLAN_HP_MAX_TIME_DEF (5000) | 439 | #define PTA_WLAN_HP_MAX_TIME_DEF (5000) |
@@ -463,150 +466,34 @@ struct acx_bt_wlan_coex { | |||
463 | struct acx_bt_wlan_coex_param { | 466 | struct acx_bt_wlan_coex_param { |
464 | struct acx_header header; | 467 | struct acx_header header; |
465 | 468 | ||
466 | /* | 469 | __le32 per_threshold; |
467 | * The minimum rate of a received WLAN packet in the STA, | 470 | __le32 max_scan_compensation_time; |
468 | * during protective mode, of which a new BT-HP request | 471 | __le16 nfs_sample_interval; |
469 | * during this Rx will always be respected and gain the antenna. | 472 | u8 load_ratio; |
470 | */ | 473 | u8 auto_ps_mode; |
471 | u32 min_rate; | 474 | u8 probe_req_compensation; |
472 | 475 | u8 scan_window_compensation; | |
473 | /* Max time the BT HP will be respected. */ | 476 | u8 antenna_config; |
474 | u16 bt_hp_max_time; | 477 | u8 beacon_miss_threshold; |
475 | 478 | __le32 rate_adaptation_threshold; | |
476 | /* Max time the WLAN HP will be respected. */ | 479 | s8 rate_adaptation_snr; |
477 | u16 wlan_hp_max_time; | 480 | u8 padding[3]; |
478 | |||
479 | /* | ||
480 | * The time between the last BT activity | ||
481 | * and the moment when the sense mode returns | ||
482 | * to SENSE_INACTIVE. | ||
483 | */ | ||
484 | u16 sense_disable_timer; | ||
485 | |||
486 | /* Time before the next BT HP instance */ | ||
487 | u16 rx_time_bt_hp; | ||
488 | u16 tx_time_bt_hp; | ||
489 | |||
490 | /* range: 10-20000 default: 1500 */ | ||
491 | u16 rx_time_bt_hp_fast; | ||
492 | u16 tx_time_bt_hp_fast; | ||
493 | |||
494 | /* range: 2000-65535 default: 8700 */ | ||
495 | u16 wlan_cycle_fast; | ||
496 | |||
497 | /* range: 0 - 15000 (Msec) default: 1000 */ | ||
498 | u16 bt_anti_starvation_period; | ||
499 | |||
500 | /* range 400-10000(Usec) default: 3000 */ | ||
501 | u16 next_bt_lp_packet; | ||
502 | |||
503 | /* Deafult: worst case for BT DH5 traffic */ | ||
504 | u16 wake_up_beacon; | ||
505 | |||
506 | /* range: 0-50000(Usec) default: 1050 */ | ||
507 | u16 hp_dm_max_guard_time; | ||
508 | |||
509 | /* | ||
510 | * This is to prevent both BT & WLAN antenna | ||
511 | * starvation. | ||
512 | * Range: 100-50000(Usec) default:2550 | ||
513 | */ | ||
514 | u16 next_wlan_packet; | ||
515 | |||
516 | /* 0 -> shared antenna */ | ||
517 | u8 antenna_type; | ||
518 | |||
519 | /* | ||
520 | * 0 -> TI legacy | ||
521 | * 1 -> Palau | ||
522 | */ | ||
523 | u8 signal_type; | ||
524 | |||
525 | /* | ||
526 | * BT AFH status | ||
527 | * 0 -> no AFH | ||
528 | * 1 -> from dedicated GPIO | ||
529 | * 2 -> AFH on (from host) | ||
530 | */ | ||
531 | u8 afh_leverage_on; | ||
532 | |||
533 | /* | ||
534 | * The number of cycles during which no | ||
535 | * TX will be sent after 1 cycle of RX | ||
536 | * transaction in protective mode | ||
537 | */ | ||
538 | u8 quiet_cycle_num; | ||
539 | |||
540 | /* | ||
541 | * The maximum number of CTSs that will | ||
542 | * be sent for receiving RX packet in | ||
543 | * protective mode | ||
544 | */ | ||
545 | u8 max_cts; | ||
546 | |||
547 | /* | ||
548 | * The number of WLAN packets | ||
549 | * transferred in common mode before | ||
550 | * switching to BT. | ||
551 | */ | ||
552 | u8 wlan_packets_num; | ||
553 | |||
554 | /* | ||
555 | * The number of BT packets | ||
556 | * transferred in common mode before | ||
557 | * switching to WLAN. | ||
558 | */ | ||
559 | u8 bt_packets_num; | ||
560 | |||
561 | /* range: 1-255 default: 5 */ | ||
562 | u8 missed_rx_avalanche; | ||
563 | |||
564 | /* range: 0-1 default: 1 */ | ||
565 | u8 wlan_elp_hp; | ||
566 | |||
567 | /* range: 0 - 15 default: 4 */ | ||
568 | u8 bt_anti_starvation_cycles; | ||
569 | |||
570 | u8 ack_mode_dual_ant; | ||
571 | |||
572 | /* | ||
573 | * Allow PA_SD assertion/de-assertion | ||
574 | * during enabled BT activity. | ||
575 | */ | ||
576 | u8 pa_sd_enable; | ||
577 | |||
578 | /* | ||
579 | * Enable/Disable PTA in auto mode: | ||
580 | * Support Both Active & P.S modes | ||
581 | */ | ||
582 | u8 pta_auto_mode_enable; | ||
583 | |||
584 | /* range: 0 - 20 default: 1 */ | ||
585 | u8 bt_hp_respected_num; | ||
586 | } __attribute__ ((packed)); | 481 | } __attribute__ ((packed)); |
587 | 482 | ||
588 | #define CCA_THRSH_ENABLE_ENERGY_D 0x140A | ||
589 | #define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF | ||
590 | |||
591 | struct acx_energy_detection { | 483 | struct acx_energy_detection { |
592 | struct acx_header header; | 484 | struct acx_header header; |
593 | 485 | ||
594 | /* The RX Clear Channel Assessment threshold in the PHY */ | 486 | /* The RX Clear Channel Assessment threshold in the PHY */ |
595 | u16 rx_cca_threshold; | 487 | __le16 rx_cca_threshold; |
596 | u8 tx_energy_detection; | 488 | u8 tx_energy_detection; |
597 | u8 pad; | 489 | u8 pad; |
598 | } __attribute__ ((packed)); | 490 | } __attribute__ ((packed)); |
599 | 491 | ||
600 | #define BCN_RX_TIMEOUT_DEF_VALUE 10000 | ||
601 | #define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 | ||
602 | #define RX_BROADCAST_IN_PS_DEF_VALUE 1 | ||
603 | #define CONSECUTIVE_PS_POLL_FAILURE_DEF 4 | ||
604 | |||
605 | struct acx_beacon_broadcast { | 492 | struct acx_beacon_broadcast { |
606 | struct acx_header header; | 493 | struct acx_header header; |
607 | 494 | ||
608 | u16 beacon_rx_timeout; | 495 | __le16 beacon_rx_timeout; |
609 | u16 broadcast_timeout; | 496 | __le16 broadcast_timeout; |
610 | 497 | ||
611 | /* Enables receiving of broadcast packets in PS mode */ | 498 | /* Enables receiving of broadcast packets in PS mode */ |
612 | u8 rx_broadcast_in_ps; | 499 | u8 rx_broadcast_in_ps; |
@@ -619,8 +506,8 @@ struct acx_beacon_broadcast { | |||
619 | struct acx_event_mask { | 506 | struct acx_event_mask { |
620 | struct acx_header header; | 507 | struct acx_header header; |
621 | 508 | ||
622 | u32 event_mask; | 509 | __le32 event_mask; |
623 | u32 high_event_mask; /* Unused */ | 510 | __le32 high_event_mask; /* Unused */ |
624 | } __attribute__ ((packed)); | 511 | } __attribute__ ((packed)); |
625 | 512 | ||
626 | #define CFG_RX_FCS BIT(2) | 513 | #define CFG_RX_FCS BIT(2) |
@@ -657,11 +544,15 @@ struct acx_event_mask { | |||
657 | #define SCAN_TRIGGERED BIT(2) | 544 | #define SCAN_TRIGGERED BIT(2) |
658 | #define SCAN_PRIORITY_HIGH BIT(3) | 545 | #define SCAN_PRIORITY_HIGH BIT(3) |
659 | 546 | ||
547 | /* When set, disable HW encryption */ | ||
548 | #define DF_ENCRYPTION_DISABLE 0x01 | ||
549 | #define DF_SNIFF_MODE_ENABLE 0x80 | ||
550 | |||
660 | struct acx_feature_config { | 551 | struct acx_feature_config { |
661 | struct acx_header header; | 552 | struct acx_header header; |
662 | 553 | ||
663 | u32 options; | 554 | __le32 options; |
664 | u32 data_flow_options; | 555 | __le32 data_flow_options; |
665 | } __attribute__ ((packed)); | 556 | } __attribute__ ((packed)); |
666 | 557 | ||
667 | struct acx_current_tx_power { | 558 | struct acx_current_tx_power { |
@@ -671,14 +562,6 @@ struct acx_current_tx_power { | |||
671 | u8 padding[3]; | 562 | u8 padding[3]; |
672 | } __attribute__ ((packed)); | 563 | } __attribute__ ((packed)); |
673 | 564 | ||
674 | enum acx_wake_up_event { | ||
675 | WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ | ||
676 | WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ | ||
677 | WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */ | ||
678 | WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */ | ||
679 | WAKE_UP_EVENT_BITS_MASK = 0x0F | ||
680 | }; | ||
681 | |||
682 | struct acx_wake_up_condition { | 565 | struct acx_wake_up_condition { |
683 | struct acx_header header; | 566 | struct acx_header header; |
684 | 567 | ||
@@ -693,7 +576,7 @@ struct acx_aid { | |||
693 | /* | 576 | /* |
694 | * To be set when associated with an AP. | 577 | * To be set when associated with an AP. |
695 | */ | 578 | */ |
696 | u16 aid; | 579 | __le16 aid; |
697 | u8 pad[2]; | 580 | u8 pad[2]; |
698 | } __attribute__ ((packed)); | 581 | } __attribute__ ((packed)); |
699 | 582 | ||
@@ -725,152 +608,152 @@ struct acx_ctsprotect { | |||
725 | } __attribute__ ((packed)); | 608 | } __attribute__ ((packed)); |
726 | 609 | ||
727 | struct acx_tx_statistics { | 610 | struct acx_tx_statistics { |
728 | u32 internal_desc_overflow; | 611 | __le32 internal_desc_overflow; |
729 | } __attribute__ ((packed)); | 612 | } __attribute__ ((packed)); |
730 | 613 | ||
731 | struct acx_rx_statistics { | 614 | struct acx_rx_statistics { |
732 | u32 out_of_mem; | 615 | __le32 out_of_mem; |
733 | u32 hdr_overflow; | 616 | __le32 hdr_overflow; |
734 | u32 hw_stuck; | 617 | __le32 hw_stuck; |
735 | u32 dropped; | 618 | __le32 dropped; |
736 | u32 fcs_err; | 619 | __le32 fcs_err; |
737 | u32 xfr_hint_trig; | 620 | __le32 xfr_hint_trig; |
738 | u32 path_reset; | 621 | __le32 path_reset; |
739 | u32 reset_counter; | 622 | __le32 reset_counter; |
740 | } __attribute__ ((packed)); | 623 | } __attribute__ ((packed)); |
741 | 624 | ||
742 | struct acx_dma_statistics { | 625 | struct acx_dma_statistics { |
743 | u32 rx_requested; | 626 | __le32 rx_requested; |
744 | u32 rx_errors; | 627 | __le32 rx_errors; |
745 | u32 tx_requested; | 628 | __le32 tx_requested; |
746 | u32 tx_errors; | 629 | __le32 tx_errors; |
747 | } __attribute__ ((packed)); | 630 | } __attribute__ ((packed)); |
748 | 631 | ||
749 | struct acx_isr_statistics { | 632 | struct acx_isr_statistics { |
750 | /* host command complete */ | 633 | /* host command complete */ |
751 | u32 cmd_cmplt; | 634 | __le32 cmd_cmplt; |
752 | 635 | ||
753 | /* fiqisr() */ | 636 | /* fiqisr() */ |
754 | u32 fiqs; | 637 | __le32 fiqs; |
755 | 638 | ||
756 | /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ | 639 | /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ |
757 | u32 rx_headers; | 640 | __le32 rx_headers; |
758 | 641 | ||
759 | /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ | 642 | /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ |
760 | u32 rx_completes; | 643 | __le32 rx_completes; |
761 | 644 | ||
762 | /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ | 645 | /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ |
763 | u32 rx_mem_overflow; | 646 | __le32 rx_mem_overflow; |
764 | 647 | ||
765 | /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ | 648 | /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ |
766 | u32 rx_rdys; | 649 | __le32 rx_rdys; |
767 | 650 | ||
768 | /* irqisr() */ | 651 | /* irqisr() */ |
769 | u32 irqs; | 652 | __le32 irqs; |
770 | 653 | ||
771 | /* (INT_STS_ND & INT_TRIG_TX_PROC) */ | 654 | /* (INT_STS_ND & INT_TRIG_TX_PROC) */ |
772 | u32 tx_procs; | 655 | __le32 tx_procs; |
773 | 656 | ||
774 | /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ | 657 | /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ |
775 | u32 decrypt_done; | 658 | __le32 decrypt_done; |
776 | 659 | ||
777 | /* (INT_STS_ND & INT_TRIG_DMA0) */ | 660 | /* (INT_STS_ND & INT_TRIG_DMA0) */ |
778 | u32 dma0_done; | 661 | __le32 dma0_done; |
779 | 662 | ||
780 | /* (INT_STS_ND & INT_TRIG_DMA1) */ | 663 | /* (INT_STS_ND & INT_TRIG_DMA1) */ |
781 | u32 dma1_done; | 664 | __le32 dma1_done; |
782 | 665 | ||
783 | /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ | 666 | /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ |
784 | u32 tx_exch_complete; | 667 | __le32 tx_exch_complete; |
785 | 668 | ||
786 | /* (INT_STS_ND & INT_TRIG_COMMAND) */ | 669 | /* (INT_STS_ND & INT_TRIG_COMMAND) */ |
787 | u32 commands; | 670 | __le32 commands; |
788 | 671 | ||
789 | /* (INT_STS_ND & INT_TRIG_RX_PROC) */ | 672 | /* (INT_STS_ND & INT_TRIG_RX_PROC) */ |
790 | u32 rx_procs; | 673 | __le32 rx_procs; |
791 | 674 | ||
792 | /* (INT_STS_ND & INT_TRIG_PM_802) */ | 675 | /* (INT_STS_ND & INT_TRIG_PM_802) */ |
793 | u32 hw_pm_mode_changes; | 676 | __le32 hw_pm_mode_changes; |
794 | 677 | ||
795 | /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ | 678 | /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ |
796 | u32 host_acknowledges; | 679 | __le32 host_acknowledges; |
797 | 680 | ||
798 | /* (INT_STS_ND & INT_TRIG_PM_PCI) */ | 681 | /* (INT_STS_ND & INT_TRIG_PM_PCI) */ |
799 | u32 pci_pm; | 682 | __le32 pci_pm; |
800 | 683 | ||
801 | /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ | 684 | /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ |
802 | u32 wakeups; | 685 | __le32 wakeups; |
803 | 686 | ||
804 | /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ | 687 | /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ |
805 | u32 low_rssi; | 688 | __le32 low_rssi; |
806 | } __attribute__ ((packed)); | 689 | } __attribute__ ((packed)); |
807 | 690 | ||
808 | struct acx_wep_statistics { | 691 | struct acx_wep_statistics { |
809 | /* WEP address keys configured */ | 692 | /* WEP address keys configured */ |
810 | u32 addr_key_count; | 693 | __le32 addr_key_count; |
811 | 694 | ||
812 | /* default keys configured */ | 695 | /* default keys configured */ |
813 | u32 default_key_count; | 696 | __le32 default_key_count; |
814 | 697 | ||
815 | u32 reserved; | 698 | __le32 reserved; |
816 | 699 | ||
817 | /* number of times that WEP key not found on lookup */ | 700 | /* number of times that WEP key not found on lookup */ |
818 | u32 key_not_found; | 701 | __le32 key_not_found; |
819 | 702 | ||
820 | /* number of times that WEP key decryption failed */ | 703 | /* number of times that WEP key decryption failed */ |
821 | u32 decrypt_fail; | 704 | __le32 decrypt_fail; |
822 | 705 | ||
823 | /* WEP packets decrypted */ | 706 | /* WEP packets decrypted */ |
824 | u32 packets; | 707 | __le32 packets; |
825 | 708 | ||
826 | /* WEP decrypt interrupts */ | 709 | /* WEP decrypt interrupts */ |
827 | u32 interrupt; | 710 | __le32 interrupt; |
828 | } __attribute__ ((packed)); | 711 | } __attribute__ ((packed)); |
829 | 712 | ||
830 | #define ACX_MISSED_BEACONS_SPREAD 10 | 713 | #define ACX_MISSED_BEACONS_SPREAD 10 |
831 | 714 | ||
832 | struct acx_pwr_statistics { | 715 | struct acx_pwr_statistics { |
833 | /* the amount of enters into power save mode (both PD & ELP) */ | 716 | /* the amount of enters into power save mode (both PD & ELP) */ |
834 | u32 ps_enter; | 717 | __le32 ps_enter; |
835 | 718 | ||
836 | /* the amount of enters into ELP mode */ | 719 | /* the amount of enters into ELP mode */ |
837 | u32 elp_enter; | 720 | __le32 elp_enter; |
838 | 721 | ||
839 | /* the amount of missing beacon interrupts to the host */ | 722 | /* the amount of missing beacon interrupts to the host */ |
840 | u32 missing_bcns; | 723 | __le32 missing_bcns; |
841 | 724 | ||
842 | /* the amount of wake on host-access times */ | 725 | /* the amount of wake on host-access times */ |
843 | u32 wake_on_host; | 726 | __le32 wake_on_host; |
844 | 727 | ||
845 | /* the amount of wake on timer-expire */ | 728 | /* the amount of wake on timer-expire */ |
846 | u32 wake_on_timer_exp; | 729 | __le32 wake_on_timer_exp; |
847 | 730 | ||
848 | /* the number of packets that were transmitted with PS bit set */ | 731 | /* the number of packets that were transmitted with PS bit set */ |
849 | u32 tx_with_ps; | 732 | __le32 tx_with_ps; |
850 | 733 | ||
851 | /* the number of packets that were transmitted with PS bit clear */ | 734 | /* the number of packets that were transmitted with PS bit clear */ |
852 | u32 tx_without_ps; | 735 | __le32 tx_without_ps; |
853 | 736 | ||
854 | /* the number of received beacons */ | 737 | /* the number of received beacons */ |
855 | u32 rcvd_beacons; | 738 | __le32 rcvd_beacons; |
856 | 739 | ||
857 | /* the number of entering into PowerOn (power save off) */ | 740 | /* the number of entering into PowerOn (power save off) */ |
858 | u32 power_save_off; | 741 | __le32 power_save_off; |
859 | 742 | ||
860 | /* the number of entries into power save mode */ | 743 | /* the number of entries into power save mode */ |
861 | u16 enable_ps; | 744 | __le16 enable_ps; |
862 | 745 | ||
863 | /* | 746 | /* |
864 | * the number of exits from power save, not including failed PS | 747 | * the number of exits from power save, not including failed PS |
865 | * transitions | 748 | * transitions |
866 | */ | 749 | */ |
867 | u16 disable_ps; | 750 | __le16 disable_ps; |
868 | 751 | ||
869 | /* | 752 | /* |
870 | * the number of times the TSF counter was adjusted because | 753 | * the number of times the TSF counter was adjusted because |
871 | * of drift | 754 | * of drift |
872 | */ | 755 | */ |
873 | u32 fix_tsf_ps; | 756 | __le32 fix_tsf_ps; |
874 | 757 | ||
875 | /* Gives statistics about the spread continuous missed beacons. | 758 | /* Gives statistics about the spread continuous missed beacons. |
876 | * The 16 LSB are dedicated for the PS mode. | 759 | * The 16 LSB are dedicated for the PS mode. |
@@ -881,53 +764,53 @@ struct acx_pwr_statistics { | |||
881 | * ... | 764 | * ... |
882 | * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. | 765 | * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. |
883 | */ | 766 | */ |
884 | u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; | 767 | __le32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; |
885 | 768 | ||
886 | /* the number of beacons in awake mode */ | 769 | /* the number of beacons in awake mode */ |
887 | u32 rcvd_awake_beacons; | 770 | __le32 rcvd_awake_beacons; |
888 | } __attribute__ ((packed)); | 771 | } __attribute__ ((packed)); |
889 | 772 | ||
890 | struct acx_mic_statistics { | 773 | struct acx_mic_statistics { |
891 | u32 rx_pkts; | 774 | __le32 rx_pkts; |
892 | u32 calc_failure; | 775 | __le32 calc_failure; |
893 | } __attribute__ ((packed)); | 776 | } __attribute__ ((packed)); |
894 | 777 | ||
895 | struct acx_aes_statistics { | 778 | struct acx_aes_statistics { |
896 | u32 encrypt_fail; | 779 | __le32 encrypt_fail; |
897 | u32 decrypt_fail; | 780 | __le32 decrypt_fail; |
898 | u32 encrypt_packets; | 781 | __le32 encrypt_packets; |
899 | u32 decrypt_packets; | 782 | __le32 decrypt_packets; |
900 | u32 encrypt_interrupt; | 783 | __le32 encrypt_interrupt; |
901 | u32 decrypt_interrupt; | 784 | __le32 decrypt_interrupt; |
902 | } __attribute__ ((packed)); | 785 | } __attribute__ ((packed)); |
903 | 786 | ||
904 | struct acx_event_statistics { | 787 | struct acx_event_statistics { |
905 | u32 heart_beat; | 788 | __le32 heart_beat; |
906 | u32 calibration; | 789 | __le32 calibration; |
907 | u32 rx_mismatch; | 790 | __le32 rx_mismatch; |
908 | u32 rx_mem_empty; | 791 | __le32 rx_mem_empty; |
909 | u32 rx_pool; | 792 | __le32 rx_pool; |
910 | u32 oom_late; | 793 | __le32 oom_late; |
911 | u32 phy_transmit_error; | 794 | __le32 phy_transmit_error; |
912 | u32 tx_stuck; | 795 | __le32 tx_stuck; |
913 | } __attribute__ ((packed)); | 796 | } __attribute__ ((packed)); |
914 | 797 | ||
915 | struct acx_ps_statistics { | 798 | struct acx_ps_statistics { |
916 | u32 pspoll_timeouts; | 799 | __le32 pspoll_timeouts; |
917 | u32 upsd_timeouts; | 800 | __le32 upsd_timeouts; |
918 | u32 upsd_max_sptime; | 801 | __le32 upsd_max_sptime; |
919 | u32 upsd_max_apturn; | 802 | __le32 upsd_max_apturn; |
920 | u32 pspoll_max_apturn; | 803 | __le32 pspoll_max_apturn; |
921 | u32 pspoll_utilization; | 804 | __le32 pspoll_utilization; |
922 | u32 upsd_utilization; | 805 | __le32 upsd_utilization; |
923 | } __attribute__ ((packed)); | 806 | } __attribute__ ((packed)); |
924 | 807 | ||
925 | struct acx_rxpipe_statistics { | 808 | struct acx_rxpipe_statistics { |
926 | u32 rx_prep_beacon_drop; | 809 | __le32 rx_prep_beacon_drop; |
927 | u32 descr_host_int_trig_rx_data; | 810 | __le32 descr_host_int_trig_rx_data; |
928 | u32 beacon_buffer_thres_host_int_trig_rx_data; | 811 | __le32 beacon_buffer_thres_host_int_trig_rx_data; |
929 | u32 missed_beacon_host_int_trig_rx_data; | 812 | __le32 missed_beacon_host_int_trig_rx_data; |
930 | u32 tx_xfr_host_int_trig_rx_data; | 813 | __le32 tx_xfr_host_int_trig_rx_data; |
931 | } __attribute__ ((packed)); | 814 | } __attribute__ ((packed)); |
932 | 815 | ||
933 | struct acx_statistics { | 816 | struct acx_statistics { |
@@ -946,13 +829,8 @@ struct acx_statistics { | |||
946 | struct acx_rxpipe_statistics rxpipe; | 829 | struct acx_rxpipe_statistics rxpipe; |
947 | } __attribute__ ((packed)); | 830 | } __attribute__ ((packed)); |
948 | 831 | ||
949 | #define ACX_MAX_RATE_CLASSES 8 | ||
950 | #define ACX_RATE_MASK_UNSPECIFIED 0 | ||
951 | #define ACX_RATE_MASK_ALL 0x1eff | ||
952 | #define ACX_RATE_RETRY_LIMIT 10 | ||
953 | |||
954 | struct acx_rate_class { | 832 | struct acx_rate_class { |
955 | u32 enabled_rates; | 833 | __le32 enabled_rates; |
956 | u8 short_retry_limit; | 834 | u8 short_retry_limit; |
957 | u8 long_retry_limit; | 835 | u8 long_retry_limit; |
958 | u8 aflags; | 836 | u8 aflags; |
@@ -962,47 +840,20 @@ struct acx_rate_class { | |||
962 | struct acx_rate_policy { | 840 | struct acx_rate_policy { |
963 | struct acx_header header; | 841 | struct acx_header header; |
964 | 842 | ||
965 | u32 rate_class_cnt; | 843 | __le32 rate_class_cnt; |
966 | struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES]; | 844 | struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES]; |
967 | } __attribute__ ((packed)); | 845 | } __attribute__ ((packed)); |
968 | 846 | ||
969 | #define WL1271_ACX_AC_COUNT 4 | ||
970 | |||
971 | struct acx_ac_cfg { | 847 | struct acx_ac_cfg { |
972 | struct acx_header header; | 848 | struct acx_header header; |
973 | u8 ac; | 849 | u8 ac; |
974 | u8 cw_min; | 850 | u8 cw_min; |
975 | u16 cw_max; | 851 | __le16 cw_max; |
976 | u8 aifsn; | 852 | u8 aifsn; |
977 | u8 reserved; | 853 | u8 reserved; |
978 | u16 tx_op_limit; | 854 | __le16 tx_op_limit; |
979 | } __attribute__ ((packed)); | 855 | } __attribute__ ((packed)); |
980 | 856 | ||
981 | enum wl1271_acx_ac { | ||
982 | WL1271_ACX_AC_BE = 0, | ||
983 | WL1271_ACX_AC_BK = 1, | ||
984 | WL1271_ACX_AC_VI = 2, | ||
985 | WL1271_ACX_AC_VO = 3, | ||
986 | WL1271_ACX_AC_CTS2SELF = 4, | ||
987 | WL1271_ACX_AC_ANY_TID = 0x1F, | ||
988 | WL1271_ACX_AC_INVALID = 0xFF, | ||
989 | }; | ||
990 | |||
991 | enum wl1271_acx_ps_scheme { | ||
992 | WL1271_ACX_PS_SCHEME_LEGACY = 0, | ||
993 | WL1271_ACX_PS_SCHEME_UPSD_TRIGGER = 1, | ||
994 | WL1271_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, | ||
995 | WL1271_ACX_PS_SCHEME_SAPSD = 3, | ||
996 | }; | ||
997 | |||
998 | enum wl1271_acx_ack_policy { | ||
999 | WL1271_ACX_ACK_POLICY_LEGACY = 0, | ||
1000 | WL1271_ACX_ACK_POLICY_NO_ACK = 1, | ||
1001 | WL1271_ACX_ACK_POLICY_BLOCK = 2, | ||
1002 | }; | ||
1003 | |||
1004 | #define WL1271_ACX_TID_COUNT 7 | ||
1005 | |||
1006 | struct acx_tid_config { | 857 | struct acx_tid_config { |
1007 | struct acx_header header; | 858 | struct acx_header header; |
1008 | u8 queue_id; | 859 | u8 queue_id; |
@@ -1011,22 +862,19 @@ struct acx_tid_config { | |||
1011 | u8 ps_scheme; | 862 | u8 ps_scheme; |
1012 | u8 ack_policy; | 863 | u8 ack_policy; |
1013 | u8 padding[3]; | 864 | u8 padding[3]; |
1014 | u32 apsd_conf[2]; | 865 | __le32 apsd_conf[2]; |
1015 | } __attribute__ ((packed)); | 866 | } __attribute__ ((packed)); |
1016 | 867 | ||
1017 | struct acx_frag_threshold { | 868 | struct acx_frag_threshold { |
1018 | struct acx_header header; | 869 | struct acx_header header; |
1019 | u16 frag_threshold; | 870 | __le16 frag_threshold; |
1020 | u8 padding[2]; | 871 | u8 padding[2]; |
1021 | } __attribute__ ((packed)); | 872 | } __attribute__ ((packed)); |
1022 | 873 | ||
1023 | #define WL1271_ACX_TX_COMPL_TIMEOUT 5 | ||
1024 | #define WL1271_ACX_TX_COMPL_THRESHOLD 5 | ||
1025 | |||
1026 | struct acx_tx_config_options { | 874 | struct acx_tx_config_options { |
1027 | struct acx_header header; | 875 | struct acx_header header; |
1028 | u16 tx_compl_timeout; /* msec */ | 876 | __le16 tx_compl_timeout; /* msec */ |
1029 | u16 tx_compl_threshold; /* number of packets */ | 877 | __le16 tx_compl_threshold; /* number of packets */ |
1030 | } __attribute__ ((packed)); | 878 | } __attribute__ ((packed)); |
1031 | 879 | ||
1032 | #define ACX_RX_MEM_BLOCKS 64 | 880 | #define ACX_RX_MEM_BLOCKS 64 |
@@ -1041,79 +889,87 @@ struct wl1271_acx_config_memory { | |||
1041 | u8 tx_min_mem_block_num; | 889 | u8 tx_min_mem_block_num; |
1042 | u8 num_stations; | 890 | u8 num_stations; |
1043 | u8 num_ssid_profiles; | 891 | u8 num_ssid_profiles; |
1044 | u32 total_tx_descriptors; | 892 | __le32 total_tx_descriptors; |
1045 | } __attribute__ ((packed)); | 893 | } __attribute__ ((packed)); |
1046 | 894 | ||
1047 | struct wl1271_acx_mem_map { | 895 | struct wl1271_acx_mem_map { |
1048 | struct acx_header header; | 896 | struct acx_header header; |
1049 | 897 | ||
1050 | void *code_start; | 898 | __le32 code_start; |
1051 | void *code_end; | 899 | __le32 code_end; |
1052 | 900 | ||
1053 | void *wep_defkey_start; | 901 | __le32 wep_defkey_start; |
1054 | void *wep_defkey_end; | 902 | __le32 wep_defkey_end; |
1055 | 903 | ||
1056 | void *sta_table_start; | 904 | __le32 sta_table_start; |
1057 | void *sta_table_end; | 905 | __le32 sta_table_end; |
1058 | 906 | ||
1059 | void *packet_template_start; | 907 | __le32 packet_template_start; |
1060 | void *packet_template_end; | 908 | __le32 packet_template_end; |
1061 | 909 | ||
1062 | /* Address of the TX result interface (control block) */ | 910 | /* Address of the TX result interface (control block) */ |
1063 | u32 tx_result; | 911 | __le32 tx_result; |
1064 | u32 tx_result_queue_start; | 912 | __le32 tx_result_queue_start; |
1065 | 913 | ||
1066 | void *queue_memory_start; | 914 | __le32 queue_memory_start; |
1067 | void *queue_memory_end; | 915 | __le32 queue_memory_end; |
1068 | 916 | ||
1069 | u32 packet_memory_pool_start; | 917 | __le32 packet_memory_pool_start; |
1070 | u32 packet_memory_pool_end; | 918 | __le32 packet_memory_pool_end; |
1071 | 919 | ||
1072 | void *debug_buffer1_start; | 920 | __le32 debug_buffer1_start; |
1073 | void *debug_buffer1_end; | 921 | __le32 debug_buffer1_end; |
1074 | 922 | ||
1075 | void *debug_buffer2_start; | 923 | __le32 debug_buffer2_start; |
1076 | void *debug_buffer2_end; | 924 | __le32 debug_buffer2_end; |
1077 | 925 | ||
1078 | /* Number of blocks FW allocated for TX packets */ | 926 | /* Number of blocks FW allocated for TX packets */ |
1079 | u32 num_tx_mem_blocks; | 927 | __le32 num_tx_mem_blocks; |
1080 | 928 | ||
1081 | /* Number of blocks FW allocated for RX packets */ | 929 | /* Number of blocks FW allocated for RX packets */ |
1082 | u32 num_rx_mem_blocks; | 930 | __le32 num_rx_mem_blocks; |
1083 | 931 | ||
1084 | /* the following 4 fields are valid in SLAVE mode only */ | 932 | /* the following 4 fields are valid in SLAVE mode only */ |
1085 | u8 *tx_cbuf; | 933 | u8 *tx_cbuf; |
1086 | u8 *rx_cbuf; | 934 | u8 *rx_cbuf; |
1087 | void *rx_ctrl; | 935 | __le32 rx_ctrl; |
1088 | void *tx_ctrl; | 936 | __le32 tx_ctrl; |
1089 | } __attribute__ ((packed)); | 937 | } __attribute__ ((packed)); |
1090 | 938 | ||
1091 | enum wl1271_acx_rx_queue_type { | ||
1092 | RX_QUEUE_TYPE_RX_LOW_PRIORITY, /* All except the high priority */ | ||
1093 | RX_QUEUE_TYPE_RX_HIGH_PRIORITY, /* Management and voice packets */ | ||
1094 | RX_QUEUE_TYPE_NUM, | ||
1095 | RX_QUEUE_TYPE_MAX = USHORT_MAX | ||
1096 | }; | ||
1097 | |||
1098 | #define WL1271_RX_INTR_THRESHOLD_DEF 0 /* no pacing, send interrupt on | ||
1099 | * every event */ | ||
1100 | #define WL1271_RX_INTR_THRESHOLD_MIN 0 | ||
1101 | #define WL1271_RX_INTR_THRESHOLD_MAX 15 | ||
1102 | |||
1103 | #define WL1271_RX_INTR_TIMEOUT_DEF 5 | ||
1104 | #define WL1271_RX_INTR_TIMEOUT_MIN 1 | ||
1105 | #define WL1271_RX_INTR_TIMEOUT_MAX 100 | ||
1106 | |||
1107 | struct wl1271_acx_rx_config_opt { | 939 | struct wl1271_acx_rx_config_opt { |
1108 | struct acx_header header; | 940 | struct acx_header header; |
1109 | 941 | ||
1110 | u16 mblk_threshold; | 942 | __le16 mblk_threshold; |
1111 | u16 threshold; | 943 | __le16 threshold; |
1112 | u16 timeout; | 944 | __le16 timeout; |
1113 | u8 queue_type; | 945 | u8 queue_type; |
1114 | u8 reserved; | 946 | u8 reserved; |
1115 | } __attribute__ ((packed)); | 947 | } __attribute__ ((packed)); |
1116 | 948 | ||
949 | |||
950 | struct wl1271_acx_bet_enable { | ||
951 | struct acx_header header; | ||
952 | |||
953 | u8 enable; | ||
954 | u8 max_consecutive; | ||
955 | u8 padding[2]; | ||
956 | } __attribute__ ((packed)); | ||
957 | |||
958 | #define ACX_IPV4_VERSION 4 | ||
959 | #define ACX_IPV6_VERSION 6 | ||
960 | #define ACX_IPV4_ADDR_SIZE 4 | ||
961 | struct wl1271_acx_arp_filter { | ||
962 | struct acx_header header; | ||
963 | u8 version; /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */ | ||
964 | u8 enable; /* 1 to enable ARP filtering, 0 to disable */ | ||
965 | u8 padding[2]; | ||
966 | u8 address[16]; /* The configured device IP address - all ARP | ||
967 | requests directed to this IP address will pass | ||
968 | through. For IPv4, the first four bytes are | ||
969 | used. */ | ||
970 | } __attribute__((packed)); | ||
971 | |||
972 | |||
1117 | enum { | 973 | enum { |
1118 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 974 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
1119 | ACX_MEM_CFG = 0x0003, | 975 | ACX_MEM_CFG = 0x0003, |
@@ -1170,6 +1026,9 @@ enum { | |||
1170 | ACX_PEER_HT_CAP = 0x0057, | 1026 | ACX_PEER_HT_CAP = 0x0057, |
1171 | ACX_HT_BSS_OPERATION = 0x0058, | 1027 | ACX_HT_BSS_OPERATION = 0x0058, |
1172 | ACX_COEX_ACTIVITY = 0x0059, | 1028 | ACX_COEX_ACTIVITY = 0x0059, |
1029 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | ||
1030 | ACX_SET_SMART_REFLEX_STATE = 0x005B, | ||
1031 | ACX_SET_SMART_REFLEX_PARAMS = 0x005F, | ||
1173 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1032 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1174 | DOT11_CUR_TX_PWR = 0x100D, | 1033 | DOT11_CUR_TX_PWR = 0x100D, |
1175 | DOT11_RX_DOT11_MODE = 0x1012, | 1034 | DOT11_RX_DOT11_MODE = 0x1012, |
@@ -1182,23 +1041,24 @@ enum { | |||
1182 | }; | 1041 | }; |
1183 | 1042 | ||
1184 | 1043 | ||
1185 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, | 1044 | int wl1271_acx_wake_up_conditions(struct wl1271 *wl); |
1186 | u8 listen_interval); | ||
1187 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); | 1045 | int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); |
1188 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len); | 1046 | int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len); |
1189 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); | 1047 | int wl1271_acx_tx_power(struct wl1271 *wl, int power); |
1190 | int wl1271_acx_feature_cfg(struct wl1271 *wl); | 1048 | int wl1271_acx_feature_cfg(struct wl1271 *wl); |
1191 | int wl1271_acx_mem_map(struct wl1271 *wl, | 1049 | int wl1271_acx_mem_map(struct wl1271 *wl, |
1192 | struct acx_header *mem_map, size_t len); | 1050 | struct acx_header *mem_map, size_t len); |
1193 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time); | 1051 | int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); |
1194 | int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter); | 1052 | int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter); |
1195 | int wl1271_acx_pd_threshold(struct wl1271 *wl); | 1053 | int wl1271_acx_pd_threshold(struct wl1271 *wl); |
1196 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); | 1054 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); |
1197 | int wl1271_acx_group_address_tbl(struct wl1271 *wl); | 1055 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, |
1056 | void *mc_list, u32 mc_list_len); | ||
1198 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1057 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1199 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1058 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); |
1200 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl); | 1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1201 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | ||
1202 | int wl1271_acx_sg_enable(struct wl1271 *wl); | 1062 | int wl1271_acx_sg_enable(struct wl1271 *wl); |
1203 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1063 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1204 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1064 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
@@ -1207,9 +1067,9 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid); | |||
1207 | int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); | 1067 | int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); |
1208 | int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | 1068 | int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); |
1209 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1210 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1211 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1212 | int wl1271_acx_rate_policies(struct wl1271 *wl); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); |
1213 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); |
1214 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); |
1215 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
@@ -1217,5 +1077,9 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl); | |||
1217 | int wl1271_acx_mem_cfg(struct wl1271 *wl); | 1077 | int wl1271_acx_mem_cfg(struct wl1271 *wl); |
1218 | int wl1271_acx_init_mem_config(struct wl1271 *wl); | 1078 | int wl1271_acx_init_mem_config(struct wl1271 *wl); |
1219 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); | 1079 | int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); |
1080 | int wl1271_acx_smart_reflex(struct wl1271 *wl); | ||
1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | ||
1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | ||
1083 | u8 version); | ||
1220 | 1084 | ||
1221 | #endif /* __WL1271_ACX_H__ */ | 1085 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 8228ef474a7e..ba4a2b4f0f56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -39,6 +39,14 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
39 | .start = REGISTERS_BASE, | 39 | .start = REGISTERS_BASE, |
40 | .size = 0x00008800 | 40 | .size = 0x00008800 |
41 | }, | 41 | }, |
42 | .mem2 = { | ||
43 | .start = 0x00000000, | ||
44 | .size = 0x00000000 | ||
45 | }, | ||
46 | .mem3 = { | ||
47 | .start = 0x00000000, | ||
48 | .size = 0x00000000 | ||
49 | }, | ||
42 | }, | 50 | }, |
43 | 51 | ||
44 | [PART_WORK] = { | 52 | [PART_WORK] = { |
@@ -48,7 +56,15 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
48 | }, | 56 | }, |
49 | .reg = { | 57 | .reg = { |
50 | .start = REGISTERS_BASE, | 58 | .start = REGISTERS_BASE, |
51 | .size = 0x0000b000 | 59 | .size = 0x0000a000 |
60 | }, | ||
61 | .mem2 = { | ||
62 | .start = 0x003004f8, | ||
63 | .size = 0x00000004 | ||
64 | }, | ||
65 | .mem3 = { | ||
66 | .start = 0x00040404, | ||
67 | .size = 0x00000000 | ||
52 | }, | 68 | }, |
53 | }, | 69 | }, |
54 | 70 | ||
@@ -60,6 +76,14 @@ static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { | |||
60 | .reg = { | 76 | .reg = { |
61 | .start = DRPW_BASE, | 77 | .start = DRPW_BASE, |
62 | .size = 0x00006000 | 78 | .size = 0x00006000 |
79 | }, | ||
80 | .mem2 = { | ||
81 | .start = 0x00000000, | ||
82 | .size = 0x00000000 | ||
83 | }, | ||
84 | .mem3 = { | ||
85 | .start = 0x00000000, | ||
86 | .size = 0x00000000 | ||
63 | } | 87 | } |
64 | } | 88 | } |
65 | }; | 89 | }; |
@@ -69,19 +93,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
69 | u32 cpu_ctrl; | 93 | u32 cpu_ctrl; |
70 | 94 | ||
71 | /* 10.5.0 run the firmware (I) */ | 95 | /* 10.5.0 run the firmware (I) */ |
72 | cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL); | 96 | cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL); |
73 | 97 | ||
74 | /* 10.5.1 run the firmware (II) */ | 98 | /* 10.5.1 run the firmware (II) */ |
75 | cpu_ctrl |= flag; | 99 | cpu_ctrl |= flag; |
76 | wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 100 | wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
77 | } | 101 | } |
78 | 102 | ||
79 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 103 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
80 | { | 104 | { |
81 | struct wl1271_static_data static_data; | 105 | struct wl1271_static_data static_data; |
82 | 106 | ||
83 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, | 107 | wl1271_spi_read(wl, wl->cmd_box_addr, |
84 | &static_data, sizeof(static_data)); | 108 | &static_data, sizeof(static_data), false); |
85 | 109 | ||
86 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 110 | strncpy(wl->chip.fw_ver, static_data.fw_version, |
87 | sizeof(wl->chip.fw_ver)); | 111 | sizeof(wl->chip.fw_ver)); |
@@ -93,8 +117,9 @@ static void wl1271_boot_fw_version(struct wl1271 *wl) | |||
93 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | 117 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, |
94 | size_t fw_data_len, u32 dest) | 118 | size_t fw_data_len, u32 dest) |
95 | { | 119 | { |
120 | struct wl1271_partition_set partition; | ||
96 | int addr, chunk_num, partition_limit; | 121 | int addr, chunk_num, partition_limit; |
97 | u8 *p; | 122 | u8 *p, *chunk; |
98 | 123 | ||
99 | /* whal_FwCtrl_LoadFwImageSm() */ | 124 | /* whal_FwCtrl_LoadFwImageSm() */ |
100 | 125 | ||
@@ -103,16 +128,20 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
103 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", | 128 | wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", |
104 | fw_data_len, CHUNK_SIZE); | 129 | fw_data_len, CHUNK_SIZE); |
105 | 130 | ||
106 | |||
107 | if ((fw_data_len % 4) != 0) { | 131 | if ((fw_data_len % 4) != 0) { |
108 | wl1271_error("firmware length not multiple of four"); | 132 | wl1271_error("firmware length not multiple of four"); |
109 | return -EIO; | 133 | return -EIO; |
110 | } | 134 | } |
111 | 135 | ||
112 | wl1271_set_partition(wl, dest, | 136 | chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL); |
113 | part_table[PART_DOWN].mem.size, | 137 | if (!chunk) { |
114 | part_table[PART_DOWN].reg.start, | 138 | wl1271_error("allocation for firmware upload chunk failed"); |
115 | part_table[PART_DOWN].reg.size); | 139 | return -ENOMEM; |
140 | } | ||
141 | |||
142 | memcpy(&partition, &part_table[PART_DOWN], sizeof(partition)); | ||
143 | partition.mem.start = dest; | ||
144 | wl1271_set_partition(wl, &partition); | ||
116 | 145 | ||
117 | /* 10.1 set partition limit and chunk num */ | 146 | /* 10.1 set partition limit and chunk num */ |
118 | chunk_num = 0; | 147 | chunk_num = 0; |
@@ -125,21 +154,17 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
125 | addr = dest + chunk_num * CHUNK_SIZE; | 154 | addr = dest + chunk_num * CHUNK_SIZE; |
126 | partition_limit = chunk_num * CHUNK_SIZE + | 155 | partition_limit = chunk_num * CHUNK_SIZE + |
127 | part_table[PART_DOWN].mem.size; | 156 | part_table[PART_DOWN].mem.size; |
128 | 157 | partition.mem.start = addr; | |
129 | /* FIXME: Over 80 chars! */ | 158 | wl1271_set_partition(wl, &partition); |
130 | wl1271_set_partition(wl, | ||
131 | addr, | ||
132 | part_table[PART_DOWN].mem.size, | ||
133 | part_table[PART_DOWN].reg.start, | ||
134 | part_table[PART_DOWN].reg.size); | ||
135 | } | 159 | } |
136 | 160 | ||
137 | /* 10.3 upload the chunk */ | 161 | /* 10.3 upload the chunk */ |
138 | addr = dest + chunk_num * CHUNK_SIZE; | 162 | addr = dest + chunk_num * CHUNK_SIZE; |
139 | p = buf + chunk_num * CHUNK_SIZE; | 163 | p = buf + chunk_num * CHUNK_SIZE; |
164 | memcpy(chunk, p, CHUNK_SIZE); | ||
140 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 165 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
141 | p, addr); | 166 | p, addr); |
142 | wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE); | 167 | wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false); |
143 | 168 | ||
144 | chunk_num++; | 169 | chunk_num++; |
145 | } | 170 | } |
@@ -147,28 +172,31 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
147 | /* 10.4 upload the last chunk */ | 172 | /* 10.4 upload the last chunk */ |
148 | addr = dest + chunk_num * CHUNK_SIZE; | 173 | addr = dest + chunk_num * CHUNK_SIZE; |
149 | p = buf + chunk_num * CHUNK_SIZE; | 174 | p = buf + chunk_num * CHUNK_SIZE; |
175 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | ||
150 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 176 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
151 | fw_data_len % CHUNK_SIZE, p, addr); | 177 | fw_data_len % CHUNK_SIZE, p, addr); |
152 | wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); | 178 | wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
153 | 179 | ||
180 | kfree(chunk); | ||
154 | return 0; | 181 | return 0; |
155 | } | 182 | } |
156 | 183 | ||
157 | static int wl1271_boot_upload_firmware(struct wl1271 *wl) | 184 | static int wl1271_boot_upload_firmware(struct wl1271 *wl) |
158 | { | 185 | { |
159 | u32 chunks, addr, len; | 186 | u32 chunks, addr, len; |
187 | int ret = 0; | ||
160 | u8 *fw; | 188 | u8 *fw; |
161 | 189 | ||
162 | fw = wl->fw; | 190 | fw = wl->fw; |
163 | chunks = be32_to_cpup((u32 *) fw); | 191 | chunks = be32_to_cpup((__be32 *) fw); |
164 | fw += sizeof(u32); | 192 | fw += sizeof(u32); |
165 | 193 | ||
166 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); | 194 | wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); |
167 | 195 | ||
168 | while (chunks--) { | 196 | while (chunks--) { |
169 | addr = be32_to_cpup((u32 *) fw); | 197 | addr = be32_to_cpup((__be32 *) fw); |
170 | fw += sizeof(u32); | 198 | fw += sizeof(u32); |
171 | len = be32_to_cpup((u32 *) fw); | 199 | len = be32_to_cpup((__be32 *) fw); |
172 | fw += sizeof(u32); | 200 | fw += sizeof(u32); |
173 | 201 | ||
174 | if (len > 300000) { | 202 | if (len > 300000) { |
@@ -177,11 +205,13 @@ static int wl1271_boot_upload_firmware(struct wl1271 *wl) | |||
177 | } | 205 | } |
178 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", | 206 | wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", |
179 | chunks, addr, len); | 207 | chunks, addr, len); |
180 | wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); | 208 | ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); |
209 | if (ret != 0) | ||
210 | break; | ||
181 | fw += len; | 211 | fw += len; |
182 | } | 212 | } |
183 | 213 | ||
184 | return 0; | 214 | return ret; |
185 | } | 215 | } |
186 | 216 | ||
187 | static int wl1271_boot_upload_nvs(struct wl1271 *wl) | 217 | static int wl1271_boot_upload_nvs(struct wl1271 *wl) |
@@ -235,7 +265,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
235 | wl1271_debug(DEBUG_BOOT, | 265 | wl1271_debug(DEBUG_BOOT, |
236 | "nvs burst write 0x%x: 0x%x", | 266 | "nvs burst write 0x%x: 0x%x", |
237 | dest_addr, val); | 267 | dest_addr, val); |
238 | wl1271_reg_write32(wl, dest_addr, val); | 268 | wl1271_spi_write32(wl, dest_addr, val); |
239 | 269 | ||
240 | nvs_ptr += 4; | 270 | nvs_ptr += 4; |
241 | dest_addr += 4; | 271 | dest_addr += 4; |
@@ -253,20 +283,18 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
253 | /* FIXME: The driver sets the partition here, but this is not needed, | 283 | /* FIXME: The driver sets the partition here, but this is not needed, |
254 | since it sets to the same one as currently in use */ | 284 | since it sets to the same one as currently in use */ |
255 | /* Now we must set the partition correctly */ | 285 | /* Now we must set the partition correctly */ |
256 | wl1271_set_partition(wl, | 286 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
257 | part_table[PART_WORK].mem.start, | ||
258 | part_table[PART_WORK].mem.size, | ||
259 | part_table[PART_WORK].reg.start, | ||
260 | part_table[PART_WORK].reg.size); | ||
261 | 287 | ||
262 | /* Copy the NVS tables to a new block to ensure alignment */ | 288 | /* Copy the NVS tables to a new block to ensure alignment */ |
263 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 289 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
290 | if (!nvs_aligned) | ||
291 | return -ENOMEM; | ||
264 | 292 | ||
265 | /* And finally we upload the NVS tables */ | 293 | /* And finally we upload the NVS tables */ |
266 | /* FIXME: In wl1271, we upload everything at once. | 294 | /* FIXME: In wl1271, we upload everything at once. |
267 | No endianness handling needed here?! The ref driver doesn't do | 295 | No endianness handling needed here?! The ref driver doesn't do |
268 | anything about it at this point */ | 296 | anything about it at this point */ |
269 | wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len); | 297 | wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false); |
270 | 298 | ||
271 | kfree(nvs_aligned); | 299 | kfree(nvs_aligned); |
272 | return 0; | 300 | return 0; |
@@ -275,9 +303,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
275 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) | 303 | static void wl1271_boot_enable_interrupts(struct wl1271 *wl) |
276 | { | 304 | { |
277 | enable_irq(wl->irq); | 305 | enable_irq(wl->irq); |
278 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 306 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, |
279 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 307 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
280 | wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); | 308 | wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL); |
281 | } | 309 | } |
282 | 310 | ||
283 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 311 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
@@ -286,12 +314,13 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
286 | u32 boot_data; | 314 | u32 boot_data; |
287 | 315 | ||
288 | /* perform soft reset */ | 316 | /* perform soft reset */ |
289 | wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | 317 | wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET, |
318 | ACX_SLV_SOFT_RESET_BIT); | ||
290 | 319 | ||
291 | /* SOFT_RESET is self clearing */ | 320 | /* SOFT_RESET is self clearing */ |
292 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 321 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
293 | while (1) { | 322 | while (1) { |
294 | boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); | 323 | boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET); |
295 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 324 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
296 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 325 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
297 | break; | 326 | break; |
@@ -307,10 +336,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
307 | } | 336 | } |
308 | 337 | ||
309 | /* disable Rx/Tx */ | 338 | /* disable Rx/Tx */ |
310 | wl1271_reg_write32(wl, ENABLE, 0x0); | 339 | wl1271_spi_write32(wl, ENABLE, 0x0); |
311 | 340 | ||
312 | /* disable auto calibration on start*/ | 341 | /* disable auto calibration on start*/ |
313 | wl1271_reg_write32(wl, SPARE_A2, 0xffff); | 342 | wl1271_spi_write32(wl, SPARE_A2, 0xffff); |
314 | 343 | ||
315 | return 0; | 344 | return 0; |
316 | } | 345 | } |
@@ -322,7 +351,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
322 | 351 | ||
323 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 352 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
324 | 353 | ||
325 | chip_id = wl1271_reg_read32(wl, CHIP_ID_B); | 354 | chip_id = wl1271_spi_read32(wl, CHIP_ID_B); |
326 | 355 | ||
327 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 356 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
328 | 357 | ||
@@ -335,7 +364,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
335 | loop = 0; | 364 | loop = 0; |
336 | while (loop++ < INIT_LOOP) { | 365 | while (loop++ < INIT_LOOP) { |
337 | udelay(INIT_LOOP_DELAY); | 366 | udelay(INIT_LOOP_DELAY); |
338 | interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 367 | interrupt = wl1271_spi_read32(wl, |
368 | ACX_REG_INTERRUPT_NO_CLEAR); | ||
339 | 369 | ||
340 | if (interrupt == 0xffffffff) { | 370 | if (interrupt == 0xffffffff) { |
341 | wl1271_error("error reading hardware complete " | 371 | wl1271_error("error reading hardware complete " |
@@ -344,7 +374,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
344 | } | 374 | } |
345 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 375 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
346 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { | 376 | else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { |
347 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK, | 377 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, |
348 | WL1271_ACX_INTR_INIT_COMPLETE); | 378 | WL1271_ACX_INTR_INIT_COMPLETE); |
349 | break; | 379 | break; |
350 | } | 380 | } |
@@ -357,17 +387,13 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
357 | } | 387 | } |
358 | 388 | ||
359 | /* get hardware config command mail box */ | 389 | /* get hardware config command mail box */ |
360 | wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); | 390 | wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR); |
361 | 391 | ||
362 | /* get hardware config event mail box */ | 392 | /* get hardware config event mail box */ |
363 | wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR); | 393 | wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); |
364 | 394 | ||
365 | /* set the working partition to its "running" mode offset */ | 395 | /* set the working partition to its "running" mode offset */ |
366 | wl1271_set_partition(wl, | 396 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
367 | part_table[PART_WORK].mem.start, | ||
368 | part_table[PART_WORK].mem.size, | ||
369 | part_table[PART_WORK].reg.start, | ||
370 | part_table[PART_WORK].reg.size); | ||
371 | 397 | ||
372 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", | 398 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", |
373 | wl->cmd_box_addr, wl->event_box_addr); | 399 | wl->cmd_box_addr, wl->event_box_addr); |
@@ -379,11 +405,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
379 | * ready to receive event from the command mailbox | 405 | * ready to receive event from the command mailbox |
380 | */ | 406 | */ |
381 | 407 | ||
382 | /* enable gpio interrupts */ | 408 | /* unmask required mbox events */ |
383 | wl1271_boot_enable_interrupts(wl); | 409 | wl->event_mask = BSS_LOSE_EVENT_ID | |
384 | 410 | SCAN_COMPLETE_EVENT_ID; | |
385 | /* unmask all mbox events */ | ||
386 | wl->event_mask = 0xffffffff; | ||
387 | 411 | ||
388 | ret = wl1271_event_unmask(wl); | 412 | ret = wl1271_event_unmask(wl); |
389 | if (ret < 0) { | 413 | if (ret < 0) { |
@@ -399,34 +423,13 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
399 | 423 | ||
400 | static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) | 424 | static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) |
401 | { | 425 | { |
402 | u32 polarity, status, i; | 426 | u32 polarity; |
403 | |||
404 | wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); | ||
405 | wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ); | ||
406 | |||
407 | /* Wait until the command is complete (ie. bit 18 is set) */ | ||
408 | for (i = 0; i < OCP_CMD_LOOP; i++) { | ||
409 | polarity = wl1271_reg_read32(wl, OCP_DATA_READ); | ||
410 | if (polarity & OCP_READY_MASK) | ||
411 | break; | ||
412 | } | ||
413 | if (i == OCP_CMD_LOOP) { | ||
414 | wl1271_error("OCP command timeout!"); | ||
415 | return -EIO; | ||
416 | } | ||
417 | 427 | ||
418 | status = polarity & OCP_STATUS_MASK; | 428 | polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY); |
419 | if (status != OCP_STATUS_OK) { | ||
420 | wl1271_error("OCP command failed (%d)", status); | ||
421 | return -EIO; | ||
422 | } | ||
423 | 429 | ||
424 | /* We use HIGH polarity, so unset the LOW bit */ | 430 | /* We use HIGH polarity, so unset the LOW bit */ |
425 | polarity &= ~POLARITY_LOW; | 431 | polarity &= ~POLARITY_LOW; |
426 | 432 | wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity); | |
427 | wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); | ||
428 | wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity); | ||
429 | wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
430 | 433 | ||
431 | return 0; | 434 | return 0; |
432 | } | 435 | } |
@@ -436,16 +439,32 @@ int wl1271_boot(struct wl1271 *wl) | |||
436 | int ret = 0; | 439 | int ret = 0; |
437 | u32 tmp, clk, pause; | 440 | u32 tmp, clk, pause; |
438 | 441 | ||
439 | if (REF_CLOCK == 0 || REF_CLOCK == 2) | 442 | if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4) |
440 | /* ref clk: 19.2/38.4 */ | 443 | /* ref clk: 19.2/38.4/38.4-XTAL */ |
441 | clk = 0x3; | 444 | clk = 0x3; |
442 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) | 445 | else if (REF_CLOCK == 1 || REF_CLOCK == 3) |
443 | /* ref clk: 26/52 */ | 446 | /* ref clk: 26/52 */ |
444 | clk = 0x5; | 447 | clk = 0x5; |
445 | 448 | ||
446 | wl1271_reg_write32(wl, PLL_PARAMETERS, clk); | 449 | if (REF_CLOCK != 0) { |
450 | u16 val; | ||
451 | /* Set clock type */ | ||
452 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | ||
453 | val &= FREF_CLK_TYPE_BITS; | ||
454 | val |= CLK_REQ_PRCM; | ||
455 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | ||
456 | } else { | ||
457 | u16 val; | ||
458 | /* Set clock polarity */ | ||
459 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY); | ||
460 | val &= FREF_CLK_POLARITY_BITS; | ||
461 | val |= CLK_REQ_OUTN_SEL; | ||
462 | wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | ||
463 | } | ||
464 | |||
465 | wl1271_spi_write32(wl, PLL_PARAMETERS, clk); | ||
447 | 466 | ||
448 | pause = wl1271_reg_read32(wl, PLL_PARAMETERS); | 467 | pause = wl1271_spi_read32(wl, PLL_PARAMETERS); |
449 | 468 | ||
450 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 469 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
451 | 470 | ||
@@ -454,39 +473,31 @@ int wl1271_boot(struct wl1271 *wl) | |||
454 | * 0x3ff (magic number ). How does | 473 | * 0x3ff (magic number ). How does |
455 | * this work?! */ | 474 | * this work?! */ |
456 | pause |= WU_COUNTER_PAUSE_VAL; | 475 | pause |= WU_COUNTER_PAUSE_VAL; |
457 | wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause); | 476 | wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause); |
458 | 477 | ||
459 | /* Continue the ELP wake up sequence */ | 478 | /* Continue the ELP wake up sequence */ |
460 | wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 479 | wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
461 | udelay(500); | 480 | udelay(500); |
462 | 481 | ||
463 | wl1271_set_partition(wl, | 482 | wl1271_set_partition(wl, &part_table[PART_DRPW]); |
464 | part_table[PART_DRPW].mem.start, | ||
465 | part_table[PART_DRPW].mem.size, | ||
466 | part_table[PART_DRPW].reg.start, | ||
467 | part_table[PART_DRPW].reg.size); | ||
468 | 483 | ||
469 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 484 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
470 | to be used by DRPw FW. The RTRIM value will be added by the FW | 485 | to be used by DRPw FW. The RTRIM value will be added by the FW |
471 | before taking DRPw out of reset */ | 486 | before taking DRPw out of reset */ |
472 | 487 | ||
473 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); | 488 | wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); |
474 | clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START); | 489 | clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START); |
475 | 490 | ||
476 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 491 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
477 | 492 | ||
478 | /* 2 */ | 493 | /* 2 */ |
479 | clk |= (REF_CLOCK << 1) << 4; | 494 | clk |= (REF_CLOCK << 1) << 4; |
480 | wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk); | 495 | wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk); |
481 | 496 | ||
482 | wl1271_set_partition(wl, | 497 | wl1271_set_partition(wl, &part_table[PART_WORK]); |
483 | part_table[PART_WORK].mem.start, | ||
484 | part_table[PART_WORK].mem.size, | ||
485 | part_table[PART_WORK].reg.start, | ||
486 | part_table[PART_WORK].reg.size); | ||
487 | 498 | ||
488 | /* Disable interrupts */ | 499 | /* Disable interrupts */ |
489 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 500 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
490 | 501 | ||
491 | ret = wl1271_boot_soft_reset(wl); | 502 | ret = wl1271_boot_soft_reset(wl); |
492 | if (ret < 0) | 503 | if (ret < 0) |
@@ -501,21 +512,22 @@ int wl1271_boot(struct wl1271 *wl) | |||
501 | * ACX_EEPROMLESS_IND_REG */ | 512 | * ACX_EEPROMLESS_IND_REG */ |
502 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 513 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
503 | 514 | ||
504 | wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); | 515 | wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG, |
516 | ACX_EEPROMLESS_IND_REG); | ||
505 | 517 | ||
506 | tmp = wl1271_reg_read32(wl, CHIP_ID_B); | 518 | tmp = wl1271_spi_read32(wl, CHIP_ID_B); |
507 | 519 | ||
508 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 520 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
509 | 521 | ||
510 | /* 6. read the EEPROM parameters */ | 522 | /* 6. read the EEPROM parameters */ |
511 | tmp = wl1271_reg_read32(wl, SCR_PAD2); | 523 | tmp = wl1271_spi_read32(wl, SCR_PAD2); |
512 | 524 | ||
513 | ret = wl1271_boot_write_irq_polarity(wl); | 525 | ret = wl1271_boot_write_irq_polarity(wl); |
514 | if (ret < 0) | 526 | if (ret < 0) |
515 | goto out; | 527 | goto out; |
516 | 528 | ||
517 | /* FIXME: Need to check whether this is really what we want */ | 529 | /* FIXME: Need to check whether this is really what we want */ |
518 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 530 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, |
519 | WL1271_ACX_ALL_EVENTS_VECTOR); | 531 | WL1271_ACX_ALL_EVENTS_VECTOR); |
520 | 532 | ||
521 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 533 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
@@ -530,6 +542,9 @@ int wl1271_boot(struct wl1271 *wl) | |||
530 | if (ret < 0) | 542 | if (ret < 0) |
531 | goto out; | 543 | goto out; |
532 | 544 | ||
545 | /* Enable firmware interrupts now */ | ||
546 | wl1271_boot_enable_interrupts(wl); | ||
547 | |||
533 | /* set the wl1271 default filters */ | 548 | /* set the wl1271 default filters */ |
534 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 549 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
535 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 550 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index b0d8fb46a439..412443ee655a 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -50,23 +50,17 @@ struct wl1271_static_data { | |||
50 | #define WU_COUNTER_PAUSE_VAL 0x3FF | 50 | #define WU_COUNTER_PAUSE_VAL 0x3FF |
51 | #define WELP_ARM_COMMAND_VAL 0x4 | 51 | #define WELP_ARM_COMMAND_VAL 0x4 |
52 | 52 | ||
53 | #define OCP_CMD_LOOP 32 | 53 | #define OCP_REG_POLARITY 0x0064 |
54 | 54 | #define OCP_REG_CLK_TYPE 0x0448 | |
55 | #define OCP_CMD_WRITE 0x1 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_CMD_READ 0x2 | ||
57 | |||
58 | #define OCP_READY_MASK BIT(18) | ||
59 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
60 | |||
61 | #define OCP_STATUS_NO_RESP 0x00000 | ||
62 | #define OCP_STATUS_OK 0x10000 | ||
63 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
64 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
65 | |||
66 | #define OCP_REG_POLARITY 0x30032 | ||
67 | 56 | ||
68 | #define CMD_MBOX_ADDRESS 0x407B4 | 57 | #define CMD_MBOX_ADDRESS 0x407B4 |
69 | 58 | ||
70 | #define POLARITY_LOW BIT(1) | 59 | #define POLARITY_LOW BIT(1) |
71 | 60 | ||
61 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | ||
62 | #define CLK_REQ_PRCM 0x100 | ||
63 | #define FREF_CLK_POLARITY_BITS 0xfffff8ff | ||
64 | #define CLK_REQ_OUTN_SEL 0x700 | ||
65 | |||
72 | #endif | 66 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 2a4351ff54dc..0666328ce9ab 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -50,18 +50,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
50 | int ret = 0; | 50 | int ret = 0; |
51 | 51 | ||
52 | cmd = buf; | 52 | cmd = buf; |
53 | cmd->id = id; | 53 | cmd->id = cpu_to_le16(id); |
54 | cmd->status = 0; | 54 | cmd->status = 0; |
55 | 55 | ||
56 | WARN_ON(len % 4 != 0); | 56 | WARN_ON(len % 4 != 0); |
57 | 57 | ||
58 | wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len); | 58 | wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false); |
59 | 59 | ||
60 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); | 60 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); |
61 | 61 | ||
62 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 62 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
63 | 63 | ||
64 | intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 64 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
65 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 65 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
66 | if (time_after(jiffies, timeout)) { | 66 | if (time_after(jiffies, timeout)) { |
67 | wl1271_error("command complete timeout"); | 67 | wl1271_error("command complete timeout"); |
@@ -71,17 +71,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
71 | 71 | ||
72 | msleep(1); | 72 | msleep(1); |
73 | 73 | ||
74 | intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 74 | intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
75 | } | 75 | } |
76 | 76 | ||
77 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK, | 77 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK, |
78 | WL1271_ACX_INTR_CMD_COMPLETE); | 78 | WL1271_ACX_INTR_CMD_COMPLETE); |
79 | 79 | ||
80 | out: | 80 | out: |
81 | return ret; | 81 | return ret; |
82 | } | 82 | } |
83 | 83 | ||
84 | int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) | 84 | static int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) |
85 | { | 85 | { |
86 | struct wl1271_cmd_cal_channel_tune *cmd; | 86 | struct wl1271_cmd_cal_channel_tune *cmd; |
87 | int ret = 0; | 87 | int ret = 0; |
@@ -104,7 +104,7 @@ int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) | |||
104 | return ret; | 104 | return ret; |
105 | } | 105 | } |
106 | 106 | ||
107 | int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) | 107 | static int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) |
108 | { | 108 | { |
109 | struct wl1271_cmd_cal_update_ref_point *cmd; | 109 | struct wl1271_cmd_cal_update_ref_point *cmd; |
110 | int ret = 0; | 110 | int ret = 0; |
@@ -129,7 +129,7 @@ int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) | |||
129 | return ret; | 129 | return ret; |
130 | } | 130 | } |
131 | 131 | ||
132 | int wl1271_cmd_cal_p2g(struct wl1271 *wl) | 132 | static int wl1271_cmd_cal_p2g(struct wl1271 *wl) |
133 | { | 133 | { |
134 | struct wl1271_cmd_cal_p2g *cmd; | 134 | struct wl1271_cmd_cal_p2g *cmd; |
135 | int ret = 0; | 135 | int ret = 0; |
@@ -150,7 +150,7 @@ int wl1271_cmd_cal_p2g(struct wl1271 *wl) | |||
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
152 | 152 | ||
153 | int wl1271_cmd_cal(struct wl1271 *wl) | 153 | static int wl1271_cmd_cal(struct wl1271 *wl) |
154 | { | 154 | { |
155 | /* | 155 | /* |
156 | * FIXME: we must make sure that we're not sleeping when calibration | 156 | * FIXME: we must make sure that we're not sleeping when calibration |
@@ -175,11 +175,9 @@ int wl1271_cmd_cal(struct wl1271 *wl) | |||
175 | return ret; | 175 | return ret; |
176 | } | 176 | } |
177 | 177 | ||
178 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | 178 | int wl1271_cmd_join(struct wl1271 *wl) |
179 | u16 beacon_interval, u8 wait) | ||
180 | { | 179 | { |
181 | static bool do_cal = true; | 180 | static bool do_cal = true; |
182 | unsigned long timeout; | ||
183 | struct wl1271_cmd_join *join; | 181 | struct wl1271_cmd_join *join; |
184 | int ret, i; | 182 | int ret, i; |
185 | u8 *bssid; | 183 | u8 *bssid; |
@@ -193,6 +191,18 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | |||
193 | do_cal = false; | 191 | do_cal = false; |
194 | } | 192 | } |
195 | 193 | ||
194 | /* FIXME: This is a workaround, because with the current stack, we | ||
195 | * cannot know when we have disassociated. So, if we have already | ||
196 | * joined, we disconnect before joining again. */ | ||
197 | if (wl->joined) { | ||
198 | ret = wl1271_cmd_disconnect(wl); | ||
199 | if (ret < 0) { | ||
200 | wl1271_error("failed to disconnect before rejoining"); | ||
201 | goto out; | ||
202 | } | ||
203 | |||
204 | wl->joined = false; | ||
205 | } | ||
196 | 206 | ||
197 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 207 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
198 | if (!join) { | 208 | if (!join) { |
@@ -207,15 +217,34 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | |||
207 | for (i = 0; i < ETH_ALEN; i++) | 217 | for (i = 0; i < ETH_ALEN; i++) |
208 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; | 218 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; |
209 | 219 | ||
210 | join->rx_config_options = wl->rx_config; | 220 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
211 | join->rx_filter_options = wl->rx_filter; | 221 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
222 | join->bss_type = wl->bss_type; | ||
212 | 223 | ||
213 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | | 224 | /* |
214 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; | 225 | * FIXME: disable temporarily all filters because after commit |
226 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
227 | * association. The filter logic needs to be implemented properly | ||
228 | * and once that is done, this hack can be removed. | ||
229 | */ | ||
230 | join->rx_config_options = cpu_to_le32(0); | ||
231 | join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER); | ||
232 | |||
233 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
234 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | ||
235 | CONF_HW_BIT_RATE_2MBPS | | ||
236 | CONF_HW_BIT_RATE_5_5MBPS | | ||
237 | CONF_HW_BIT_RATE_11MBPS); | ||
238 | else { | ||
239 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | ||
240 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | | ||
241 | CONF_HW_BIT_RATE_12MBPS | | ||
242 | CONF_HW_BIT_RATE_24MBPS); | ||
243 | } | ||
244 | |||
245 | join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); | ||
246 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | ||
215 | 247 | ||
216 | join->beacon_interval = beacon_interval; | ||
217 | join->dtim_interval = dtim_interval; | ||
218 | join->bss_type = bss_type; | ||
219 | join->channel = wl->channel; | 248 | join->channel = wl->channel; |
220 | join->ssid_len = wl->ssid_len; | 249 | join->ssid_len = wl->ssid_len; |
221 | memcpy(join->ssid, wl->ssid, wl->ssid_len); | 250 | memcpy(join->ssid, wl->ssid, wl->ssid_len); |
@@ -228,6 +257,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | |||
228 | 257 | ||
229 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; | 258 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; |
230 | 259 | ||
260 | /* reset TX security counters */ | ||
261 | wl->tx_security_last_seq = 0; | ||
262 | wl->tx_security_seq_16 = 0; | ||
263 | wl->tx_security_seq_32 = 0; | ||
231 | 264 | ||
232 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); | 265 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); |
233 | if (ret < 0) { | 266 | if (ret < 0) { |
@@ -235,14 +268,13 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | |||
235 | goto out_free; | 268 | goto out_free; |
236 | } | 269 | } |
237 | 270 | ||
238 | timeout = msecs_to_jiffies(JOIN_TIMEOUT); | 271 | wl->joined = true; |
239 | 272 | ||
240 | /* | 273 | /* |
241 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 274 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to |
242 | * simplify locking we just sleep instead, for now | 275 | * simplify locking we just sleep instead, for now |
243 | */ | 276 | */ |
244 | if (wait) | 277 | msleep(10); |
245 | msleep(10); | ||
246 | 278 | ||
247 | out_free: | 279 | out_free: |
248 | kfree(join); | 280 | kfree(join); |
@@ -274,19 +306,20 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) | |||
274 | 306 | ||
275 | if (answer) { | 307 | if (answer) { |
276 | struct wl1271_command *cmd_answer; | 308 | struct wl1271_command *cmd_answer; |
309 | u16 status; | ||
277 | 310 | ||
278 | /* | 311 | /* |
279 | * The test command got in, we can read the answer. | 312 | * The test command got in, we can read the answer. |
280 | * The answer would be a wl1271_command, where the | 313 | * The answer would be a wl1271_command, where the |
281 | * parameter array contains the actual answer. | 314 | * parameter array contains the actual answer. |
282 | */ | 315 | */ |
283 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); | 316 | wl1271_spi_read(wl, wl->cmd_box_addr, buf, buf_len, false); |
284 | 317 | ||
285 | cmd_answer = buf; | 318 | cmd_answer = buf; |
319 | status = le16_to_cpu(cmd_answer->header.status); | ||
286 | 320 | ||
287 | if (cmd_answer->header.status != CMD_STATUS_SUCCESS) | 321 | if (status != CMD_STATUS_SUCCESS) |
288 | wl1271_error("TEST command answer error: %d", | 322 | wl1271_error("TEST command answer error: %d", status); |
289 | cmd_answer->header.status); | ||
290 | } | 323 | } |
291 | 324 | ||
292 | return 0; | 325 | return 0; |
@@ -307,10 +340,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
307 | 340 | ||
308 | wl1271_debug(DEBUG_CMD, "cmd interrogate"); | 341 | wl1271_debug(DEBUG_CMD, "cmd interrogate"); |
309 | 342 | ||
310 | acx->id = id; | 343 | acx->id = cpu_to_le16(id); |
311 | 344 | ||
312 | /* payload length, does not include any headers */ | 345 | /* payload length, does not include any headers */ |
313 | acx->len = len - sizeof(*acx); | 346 | acx->len = cpu_to_le16(len - sizeof(*acx)); |
314 | 347 | ||
315 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); | 348 | ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); |
316 | if (ret < 0) { | 349 | if (ret < 0) { |
@@ -319,12 +352,12 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
319 | } | 352 | } |
320 | 353 | ||
321 | /* the interrogate command got in, we can read the answer */ | 354 | /* the interrogate command got in, we can read the answer */ |
322 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len); | 355 | wl1271_spi_read(wl, wl->cmd_box_addr, buf, len, false); |
323 | 356 | ||
324 | acx = buf; | 357 | acx = buf; |
325 | if (acx->cmd.status != CMD_STATUS_SUCCESS) | 358 | if (le16_to_cpu(acx->cmd.status) != CMD_STATUS_SUCCESS) |
326 | wl1271_error("INTERROGATE command error: %d", | 359 | wl1271_error("INTERROGATE command error: %d", |
327 | acx->cmd.status); | 360 | le16_to_cpu(acx->cmd.status)); |
328 | 361 | ||
329 | out: | 362 | out: |
330 | return ret; | 363 | return ret; |
@@ -345,10 +378,10 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
345 | 378 | ||
346 | wl1271_debug(DEBUG_CMD, "cmd configure"); | 379 | wl1271_debug(DEBUG_CMD, "cmd configure"); |
347 | 380 | ||
348 | acx->id = id; | 381 | acx->id = cpu_to_le16(id); |
349 | 382 | ||
350 | /* payload length, does not include any headers */ | 383 | /* payload length, does not include any headers */ |
351 | acx->len = len - sizeof(*acx); | 384 | acx->len = cpu_to_le16(len - sizeof(*acx)); |
352 | 385 | ||
353 | ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len); | 386 | ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len); |
354 | if (ret < 0) { | 387 | if (ret < 0) { |
@@ -414,8 +447,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | |||
414 | int ret = 0; | 447 | int ret = 0; |
415 | 448 | ||
416 | /* FIXME: this should be in ps.c */ | 449 | /* FIXME: this should be in ps.c */ |
417 | ret = wl1271_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP, | 450 | ret = wl1271_acx_wake_up_conditions(wl); |
418 | wl->listen_int); | ||
419 | if (ret < 0) { | 451 | if (ret < 0) { |
420 | wl1271_error("couldn't set wake up conditions"); | 452 | wl1271_error("couldn't set wake up conditions"); |
421 | goto out; | 453 | goto out; |
@@ -433,7 +465,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | |||
433 | ps_params->send_null_data = 1; | 465 | ps_params->send_null_data = 1; |
434 | ps_params->retries = 5; | 466 | ps_params->retries = 5; |
435 | ps_params->hang_over_period = 128; | 467 | ps_params->hang_over_period = 128; |
436 | ps_params->null_data_rate = 1; /* 1 Mbps */ | 468 | ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */ |
437 | 469 | ||
438 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 470 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
439 | sizeof(*ps_params)); | 471 | sizeof(*ps_params)); |
@@ -464,8 +496,8 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | |||
464 | WARN_ON(len > MAX_READ_SIZE); | 496 | WARN_ON(len > MAX_READ_SIZE); |
465 | len = min_t(size_t, len, MAX_READ_SIZE); | 497 | len = min_t(size_t, len, MAX_READ_SIZE); |
466 | 498 | ||
467 | cmd->addr = addr; | 499 | cmd->addr = cpu_to_le32(addr); |
468 | cmd->size = len; | 500 | cmd->size = cpu_to_le32(len); |
469 | 501 | ||
470 | ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); | 502 | ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); |
471 | if (ret < 0) { | 503 | if (ret < 0) { |
@@ -474,11 +506,11 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | |||
474 | } | 506 | } |
475 | 507 | ||
476 | /* the read command got in, we can now read the answer */ | 508 | /* the read command got in, we can now read the answer */ |
477 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); | 509 | wl1271_spi_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd), false); |
478 | 510 | ||
479 | if (cmd->header.status != CMD_STATUS_SUCCESS) | 511 | if (le16_to_cpu(cmd->header.status) != CMD_STATUS_SUCCESS) |
480 | wl1271_error("error in read command result: %d", | 512 | wl1271_error("error in read command result: %d", |
481 | cmd->header.status); | 513 | le16_to_cpu(cmd->header.status)); |
482 | 514 | ||
483 | memcpy(answer, cmd->value, len); | 515 | memcpy(answer, cmd->value, len); |
484 | 516 | ||
@@ -488,14 +520,31 @@ out: | |||
488 | } | 520 | } |
489 | 521 | ||
490 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 522 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, |
491 | u8 active_scan, u8 high_prio, u8 num_channels, | 523 | u8 active_scan, u8 high_prio, u8 band, |
492 | u8 probe_requests) | 524 | u8 probe_requests) |
493 | { | 525 | { |
494 | 526 | ||
495 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 527 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
496 | struct wl1271_cmd_scan *params = NULL; | 528 | struct wl1271_cmd_scan *params = NULL; |
497 | int i, ret; | 529 | struct ieee80211_channel *channels; |
530 | int i, j, n_ch, ret; | ||
498 | u16 scan_options = 0; | 531 | u16 scan_options = 0; |
532 | u8 ieee_band; | ||
533 | |||
534 | if (band == WL1271_SCAN_BAND_2_4_GHZ) | ||
535 | ieee_band = IEEE80211_BAND_2GHZ; | ||
536 | else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) | ||
537 | ieee_band = IEEE80211_BAND_2GHZ; | ||
538 | else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) | ||
539 | ieee_band = IEEE80211_BAND_5GHZ; | ||
540 | else | ||
541 | return -EINVAL; | ||
542 | |||
543 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | ||
544 | return -EINVAL; | ||
545 | |||
546 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | ||
547 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | ||
499 | 548 | ||
500 | if (wl->scanning) | 549 | if (wl->scanning) |
501 | return -EINVAL; | 550 | return -EINVAL; |
@@ -512,32 +561,43 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
512 | scan_options |= WL1271_SCAN_OPT_PASSIVE; | 561 | scan_options |= WL1271_SCAN_OPT_PASSIVE; |
513 | if (high_prio) | 562 | if (high_prio) |
514 | scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; | 563 | scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; |
515 | params->params.scan_options = scan_options; | 564 | params->params.scan_options = cpu_to_le16(scan_options); |
516 | 565 | ||
517 | params->params.num_channels = num_channels; | ||
518 | params->params.num_probe_requests = probe_requests; | 566 | params->params.num_probe_requests = probe_requests; |
519 | params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS); | 567 | /* Let the fw autodetect suitable tx_rate for probes */ |
568 | params->params.tx_rate = 0; | ||
520 | params->params.tid_trigger = 0; | 569 | params->params.tid_trigger = 0; |
521 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 570 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
522 | 571 | ||
523 | for (i = 0; i < num_channels; i++) { | 572 | if (band == WL1271_SCAN_BAND_DUAL) |
524 | params->channels[i].min_duration = | 573 | params->params.band = WL1271_SCAN_BAND_2_4_GHZ; |
525 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); | 574 | else |
526 | params->channels[i].max_duration = | 575 | params->params.band = band; |
527 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | 576 | |
528 | memset(¶ms->channels[i].bssid_lsb, 0xff, 4); | 577 | for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) { |
529 | memset(¶ms->channels[i].bssid_msb, 0xff, 2); | 578 | if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) { |
530 | params->channels[i].early_termination = 0; | 579 | params->channels[j].min_duration = |
531 | params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR; | 580 | cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); |
532 | params->channels[i].channel = i + 1; | 581 | params->channels[j].max_duration = |
582 | cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); | ||
583 | memset(¶ms->channels[j].bssid_lsb, 0xff, 4); | ||
584 | memset(¶ms->channels[j].bssid_msb, 0xff, 2); | ||
585 | params->channels[j].early_termination = 0; | ||
586 | params->channels[j].tx_power_att = | ||
587 | WL1271_SCAN_CURRENT_TX_PWR; | ||
588 | params->channels[j].channel = channels[i].hw_value; | ||
589 | j++; | ||
590 | } | ||
533 | } | 591 | } |
534 | 592 | ||
593 | params->params.num_channels = j; | ||
594 | |||
535 | if (len && ssid) { | 595 | if (len && ssid) { |
536 | params->params.ssid_len = len; | 596 | params->params.ssid_len = len; |
537 | memcpy(params->params.ssid, ssid, len); | 597 | memcpy(params->params.ssid, ssid, len); |
538 | } | 598 | } |
539 | 599 | ||
540 | ret = wl1271_cmd_build_probe_req(wl, ssid, len); | 600 | ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band); |
541 | if (ret < 0) { | 601 | if (ret < 0) { |
542 | wl1271_error("PROBE request template failed"); | 602 | wl1271_error("PROBE request template failed"); |
543 | goto out; | 603 | goto out; |
@@ -562,6 +622,19 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
562 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 622 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); |
563 | 623 | ||
564 | wl->scanning = true; | 624 | wl->scanning = true; |
625 | if (wl1271_11a_enabled()) { | ||
626 | wl->scan.state = band; | ||
627 | if (band == WL1271_SCAN_BAND_DUAL) { | ||
628 | wl->scan.active = active_scan; | ||
629 | wl->scan.high_prio = high_prio; | ||
630 | wl->scan.probe_requests = probe_requests; | ||
631 | if (len && ssid) { | ||
632 | wl->scan.ssid_len = len; | ||
633 | memcpy(wl->scan.ssid, ssid, len); | ||
634 | } else | ||
635 | wl->scan.ssid_len = 0; | ||
636 | } | ||
637 | } | ||
565 | 638 | ||
566 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); | 639 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); |
567 | if (ret < 0) { | 640 | if (ret < 0) { |
@@ -569,11 +642,12 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
569 | goto out; | 642 | goto out; |
570 | } | 643 | } |
571 | 644 | ||
572 | wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); | 645 | wl1271_spi_read(wl, wl->cmd_box_addr, params, sizeof(*params), |
646 | false); | ||
573 | 647 | ||
574 | if (params->header.status != CMD_STATUS_SUCCESS) { | 648 | if (le16_to_cpu(params->header.status) != CMD_STATUS_SUCCESS) { |
575 | wl1271_error("Scan command error: %d", | 649 | wl1271_error("Scan command error: %d", |
576 | params->header.status); | 650 | le16_to_cpu(params->header.status)); |
577 | wl->scanning = false; | 651 | wl->scanning = false; |
578 | ret = -EIO; | 652 | ret = -EIO; |
579 | goto out; | 653 | goto out; |
@@ -603,9 +677,9 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
603 | 677 | ||
604 | cmd->len = cpu_to_le16(buf_len); | 678 | cmd->len = cpu_to_le16(buf_len); |
605 | cmd->template_type = template_id; | 679 | cmd->template_type = template_id; |
606 | cmd->enabled_rates = ACX_RATE_MASK_UNSPECIFIED; | 680 | cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); |
607 | cmd->short_retry_limit = ACX_RATE_RETRY_LIMIT; | 681 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; |
608 | cmd->long_retry_limit = ACX_RATE_RETRY_LIMIT; | 682 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; |
609 | 683 | ||
610 | if (buf) | 684 | if (buf) |
611 | memcpy(cmd->template_data, buf, buf_len); | 685 | memcpy(cmd->template_data, buf, buf_len); |
@@ -623,30 +697,62 @@ out: | |||
623 | return ret; | 697 | return ret; |
624 | } | 698 | } |
625 | 699 | ||
626 | static int wl1271_build_basic_rates(char *rates) | 700 | static int wl1271_build_basic_rates(char *rates, u8 band) |
627 | { | 701 | { |
628 | u8 index = 0; | 702 | u8 index = 0; |
629 | 703 | ||
630 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; | 704 | if (band == IEEE80211_BAND_2GHZ) { |
631 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | 705 | rates[index++] = |
632 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | 706 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; |
633 | rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | 707 | rates[index++] = |
708 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; | ||
709 | rates[index++] = | ||
710 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; | ||
711 | rates[index++] = | ||
712 | IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; | ||
713 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
714 | rates[index++] = | ||
715 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; | ||
716 | rates[index++] = | ||
717 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; | ||
718 | rates[index++] = | ||
719 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
720 | } else { | ||
721 | wl1271_error("build_basic_rates invalid band: %d", band); | ||
722 | } | ||
634 | 723 | ||
635 | return index; | 724 | return index; |
636 | } | 725 | } |
637 | 726 | ||
638 | static int wl1271_build_extended_rates(char *rates) | 727 | static int wl1271_build_extended_rates(char *rates, u8 band) |
639 | { | 728 | { |
640 | u8 index = 0; | 729 | u8 index = 0; |
641 | 730 | ||
642 | rates[index++] = IEEE80211_OFDM_RATE_6MB; | 731 | if (band == IEEE80211_BAND_2GHZ) { |
643 | rates[index++] = IEEE80211_OFDM_RATE_9MB; | 732 | rates[index++] = IEEE80211_OFDM_RATE_6MB; |
644 | rates[index++] = IEEE80211_OFDM_RATE_12MB; | 733 | rates[index++] = IEEE80211_OFDM_RATE_9MB; |
645 | rates[index++] = IEEE80211_OFDM_RATE_18MB; | 734 | rates[index++] = IEEE80211_OFDM_RATE_12MB; |
646 | rates[index++] = IEEE80211_OFDM_RATE_24MB; | 735 | rates[index++] = IEEE80211_OFDM_RATE_18MB; |
647 | rates[index++] = IEEE80211_OFDM_RATE_36MB; | 736 | rates[index++] = IEEE80211_OFDM_RATE_24MB; |
648 | rates[index++] = IEEE80211_OFDM_RATE_48MB; | 737 | rates[index++] = IEEE80211_OFDM_RATE_36MB; |
649 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | 738 | rates[index++] = IEEE80211_OFDM_RATE_48MB; |
739 | rates[index++] = IEEE80211_OFDM_RATE_54MB; | ||
740 | } else if (band == IEEE80211_BAND_5GHZ) { | ||
741 | rates[index++] = | ||
742 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; | ||
743 | rates[index++] = | ||
744 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; | ||
745 | rates[index++] = | ||
746 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; | ||
747 | rates[index++] = | ||
748 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; | ||
749 | rates[index++] = | ||
750 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; | ||
751 | rates[index++] = | ||
752 | IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; | ||
753 | } else { | ||
754 | wl1271_error("build_basic_rates invalid band: %d", band); | ||
755 | } | ||
650 | 756 | ||
651 | return index; | 757 | return index; |
652 | } | 758 | } |
@@ -665,7 +771,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) | |||
665 | 771 | ||
666 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 772 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); |
667 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | 773 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | |
668 | IEEE80211_STYPE_NULLFUNC); | 774 | IEEE80211_STYPE_NULLFUNC | |
775 | IEEE80211_FCTL_TODS); | ||
669 | 776 | ||
670 | return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, | 777 | return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, |
671 | sizeof(template)); | 778 | sizeof(template)); |
@@ -678,7 +785,10 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | |||
678 | 785 | ||
679 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | 786 | memcpy(template.bssid, wl->bssid, ETH_ALEN); |
680 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | 787 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); |
681 | template.aid = aid; | 788 | |
789 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
790 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | ||
791 | |||
682 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 792 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); |
683 | 793 | ||
684 | return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, | 794 | return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, |
@@ -686,12 +796,14 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | |||
686 | 796 | ||
687 | } | 797 | } |
688 | 798 | ||
689 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len) | 799 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, |
800 | u8 band) | ||
690 | { | 801 | { |
691 | struct wl12xx_probe_req_template template; | 802 | struct wl12xx_probe_req_template template; |
692 | struct wl12xx_ie_rates *rates; | 803 | struct wl12xx_ie_rates *rates; |
693 | char *ptr; | 804 | char *ptr; |
694 | u16 size; | 805 | u16 size; |
806 | int ret; | ||
695 | 807 | ||
696 | ptr = (char *)&template; | 808 | ptr = (char *)&template; |
697 | size = sizeof(struct ieee80211_header); | 809 | size = sizeof(struct ieee80211_header); |
@@ -713,20 +825,25 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len) | |||
713 | /* Basic Rates */ | 825 | /* Basic Rates */ |
714 | rates = (struct wl12xx_ie_rates *)ptr; | 826 | rates = (struct wl12xx_ie_rates *)ptr; |
715 | rates->header.id = WLAN_EID_SUPP_RATES; | 827 | rates->header.id = WLAN_EID_SUPP_RATES; |
716 | rates->header.len = wl1271_build_basic_rates(rates->rates); | 828 | rates->header.len = wl1271_build_basic_rates(rates->rates, band); |
717 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | 829 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; |
718 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; | 830 | ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; |
719 | 831 | ||
720 | /* Extended rates */ | 832 | /* Extended rates */ |
721 | rates = (struct wl12xx_ie_rates *)ptr; | 833 | rates = (struct wl12xx_ie_rates *)ptr; |
722 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; | 834 | rates->header.id = WLAN_EID_EXT_SUPP_RATES; |
723 | rates->header.len = wl1271_build_extended_rates(rates->rates); | 835 | rates->header.len = wl1271_build_extended_rates(rates->rates, band); |
724 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; | 836 | size += sizeof(struct wl12xx_ie_header) + rates->header.len; |
725 | 837 | ||
726 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); | 838 | wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); |
727 | 839 | ||
728 | return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 840 | if (band == IEEE80211_BAND_2GHZ) |
729 | &template, size); | 841 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
842 | &template, size); | ||
843 | else | ||
844 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | ||
845 | &template, size); | ||
846 | return ret; | ||
730 | } | 847 | } |
731 | 848 | ||
732 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 849 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
@@ -743,7 +860,7 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | |||
743 | } | 860 | } |
744 | 861 | ||
745 | cmd->id = id; | 862 | cmd->id = id; |
746 | cmd->key_action = KEY_SET_ID; | 863 | cmd->key_action = cpu_to_le16(KEY_SET_ID); |
747 | cmd->key_type = KEY_WEP; | 864 | cmd->key_type = KEY_WEP; |
748 | 865 | ||
749 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); | 866 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); |
@@ -759,7 +876,8 @@ out: | |||
759 | } | 876 | } |
760 | 877 | ||
761 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 878 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
762 | u8 key_size, const u8 *key, const u8 *addr) | 879 | u8 key_size, const u8 *key, const u8 *addr, |
880 | u32 tx_seq_32, u16 tx_seq_16) | ||
763 | { | 881 | { |
764 | struct wl1271_cmd_set_keys *cmd; | 882 | struct wl1271_cmd_set_keys *cmd; |
765 | int ret = 0; | 883 | int ret = 0; |
@@ -773,16 +891,18 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
773 | if (key_type != KEY_WEP) | 891 | if (key_type != KEY_WEP) |
774 | memcpy(cmd->addr, addr, ETH_ALEN); | 892 | memcpy(cmd->addr, addr, ETH_ALEN); |
775 | 893 | ||
776 | cmd->key_action = action; | 894 | cmd->key_action = cpu_to_le16(action); |
777 | cmd->key_size = key_size; | 895 | cmd->key_size = key_size; |
778 | cmd->key_type = key_type; | 896 | cmd->key_type = key_type; |
779 | 897 | ||
898 | cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); | ||
899 | cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); | ||
900 | |||
780 | /* we have only one SSID profile */ | 901 | /* we have only one SSID profile */ |
781 | cmd->ssid_profile = 0; | 902 | cmd->ssid_profile = 0; |
782 | 903 | ||
783 | cmd->id = id; | 904 | cmd->id = id; |
784 | 905 | ||
785 | /* FIXME: this is from wl1251, needs to be checked */ | ||
786 | if (key_type == KEY_TKIP) { | 906 | if (key_type == KEY_TKIP) { |
787 | /* | 907 | /* |
788 | * We get the key in the following form: | 908 | * We get the key in the following form: |
@@ -811,3 +931,34 @@ out: | |||
811 | 931 | ||
812 | return ret; | 932 | return ret; |
813 | } | 933 | } |
934 | |||
935 | int wl1271_cmd_disconnect(struct wl1271 *wl) | ||
936 | { | ||
937 | struct wl1271_cmd_disconnect *cmd; | ||
938 | int ret = 0; | ||
939 | |||
940 | wl1271_debug(DEBUG_CMD, "cmd disconnect"); | ||
941 | |||
942 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
943 | if (!cmd) { | ||
944 | ret = -ENOMEM; | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | cmd->rx_config_options = cpu_to_le32(wl->rx_config); | ||
949 | cmd->rx_filter_options = cpu_to_le32(wl->rx_filter); | ||
950 | /* disconnect reason is not used in immediate disconnections */ | ||
951 | cmd->type = DISCONNECT_IMMEDIATE; | ||
952 | |||
953 | ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd)); | ||
954 | if (ret < 0) { | ||
955 | wl1271_error("failed to send disconnect command"); | ||
956 | goto out_free; | ||
957 | } | ||
958 | |||
959 | out_free: | ||
960 | kfree(cmd); | ||
961 | |||
962 | out: | ||
963 | return ret; | ||
964 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 951a8447a516..174b8209dbf3 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -30,8 +30,7 @@ | |||
30 | struct acx_header; | 30 | struct acx_header; |
31 | 31 | ||
32 | int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len); | 32 | int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len); |
33 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, | 33 | int wl1271_cmd_join(struct wl1271 *wl); |
34 | u16 beacon_interval, u8 wait); | ||
35 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 34 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
36 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 35 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
37 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 36 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
@@ -40,16 +39,19 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | |||
40 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 39 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
41 | size_t len); | 40 | size_t len); |
42 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | 41 | int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, |
43 | u8 active_scan, u8 high_prio, u8 num_channels, | 42 | u8 active_scan, u8 high_prio, u8 band, |
44 | u8 probe_requests); | 43 | u8 probe_requests); |
45 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 44 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
46 | void *buf, size_t buf_len); | 45 | void *buf, size_t buf_len); |
47 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 46 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
48 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | 47 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); |
49 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len); | 48 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len, |
49 | u8 band); | ||
50 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 50 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
51 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 51 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
52 | u8 key_size, const u8 *key, const u8 *addr); | 52 | u8 key_size, const u8 *key, const u8 *addr, |
53 | u32 tx_seq_32, u16 tx_seq_16); | ||
54 | int wl1271_cmd_disconnect(struct wl1271 *wl); | ||
53 | 55 | ||
54 | enum wl1271_commands { | 56 | enum wl1271_commands { |
55 | CMD_INTERROGATE = 1, /*use this to read information elements*/ | 57 | CMD_INTERROGATE = 1, /*use this to read information elements*/ |
@@ -118,8 +120,8 @@ enum cmd_templ { | |||
118 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 | 120 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 |
119 | 121 | ||
120 | struct wl1271_cmd_header { | 122 | struct wl1271_cmd_header { |
121 | u16 id; | 123 | __le16 id; |
122 | u16 status; | 124 | __le16 status; |
123 | /* payload */ | 125 | /* payload */ |
124 | u8 data[0]; | 126 | u8 data[0]; |
125 | } __attribute__ ((packed)); | 127 | } __attribute__ ((packed)); |
@@ -172,17 +174,17 @@ struct cmd_read_write_memory { | |||
172 | struct wl1271_cmd_header header; | 174 | struct wl1271_cmd_header header; |
173 | 175 | ||
174 | /* The address of the memory to read from or write to.*/ | 176 | /* The address of the memory to read from or write to.*/ |
175 | u32 addr; | 177 | __le32 addr; |
176 | 178 | ||
177 | /* The amount of data in bytes to read from or write to the WiLink | 179 | /* The amount of data in bytes to read from or write to the WiLink |
178 | * device.*/ | 180 | * device.*/ |
179 | u32 size; | 181 | __le32 size; |
180 | 182 | ||
181 | /* The actual value read from or written to the Wilink. The source | 183 | /* The actual value read from or written to the Wilink. The source |
182 | of this field is the Host in WRITE command or the Wilink in READ | 184 | of this field is the Host in WRITE command or the Wilink in READ |
183 | command. */ | 185 | command. */ |
184 | u8 value[MAX_READ_SIZE]; | 186 | u8 value[MAX_READ_SIZE]; |
185 | }; | 187 | } __attribute__ ((packed)); |
186 | 188 | ||
187 | #define CMDMBOX_HEADER_LEN 4 | 189 | #define CMDMBOX_HEADER_LEN 4 |
188 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 190 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
@@ -196,22 +198,23 @@ enum { | |||
196 | 198 | ||
197 | #define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ | 199 | #define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ |
198 | #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 | 200 | #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 |
201 | #define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10 | ||
199 | 202 | ||
200 | struct wl1271_cmd_join { | 203 | struct wl1271_cmd_join { |
201 | struct wl1271_cmd_header header; | 204 | struct wl1271_cmd_header header; |
202 | 205 | ||
203 | u32 bssid_lsb; | 206 | __le32 bssid_lsb; |
204 | u16 bssid_msb; | 207 | __le16 bssid_msb; |
205 | u16 beacon_interval; /* in TBTTs */ | 208 | __le16 beacon_interval; /* in TBTTs */ |
206 | u32 rx_config_options; | 209 | __le32 rx_config_options; |
207 | u32 rx_filter_options; | 210 | __le32 rx_filter_options; |
208 | 211 | ||
209 | /* | 212 | /* |
210 | * The target uses this field to determine the rate at | 213 | * The target uses this field to determine the rate at |
211 | * which to transmit control frame responses (such as | 214 | * which to transmit control frame responses (such as |
212 | * ACK or CTS frames). | 215 | * ACK or CTS frames). |
213 | */ | 216 | */ |
214 | u32 basic_rate_set; | 217 | __le32 basic_rate_set; |
215 | u8 dtim_interval; | 218 | u8 dtim_interval; |
216 | /* | 219 | /* |
217 | * bits 0-2: This bitwise field specifies the type | 220 | * bits 0-2: This bitwise field specifies the type |
@@ -240,10 +243,10 @@ struct cmd_enabledisable_path { | |||
240 | struct wl1271_cmd_template_set { | 243 | struct wl1271_cmd_template_set { |
241 | struct wl1271_cmd_header header; | 244 | struct wl1271_cmd_header header; |
242 | 245 | ||
243 | u16 len; | 246 | __le16 len; |
244 | u8 template_type; | 247 | u8 template_type; |
245 | u8 index; /* relevant only for KLV_TEMPLATE type */ | 248 | u8 index; /* relevant only for KLV_TEMPLATE type */ |
246 | u32 enabled_rates; | 249 | __le32 enabled_rates; |
247 | u8 short_retry_limit; | 250 | u8 short_retry_limit; |
248 | u8 long_retry_limit; | 251 | u8 long_retry_limit; |
249 | u8 aflags; | 252 | u8 aflags; |
@@ -280,18 +283,13 @@ struct wl1271_cmd_ps_params { | |||
280 | * to power save mode. | 283 | * to power save mode. |
281 | */ | 284 | */ |
282 | u8 hang_over_period; | 285 | u8 hang_over_period; |
283 | u32 null_data_rate; | 286 | __le32 null_data_rate; |
284 | } __attribute__ ((packed)); | 287 | } __attribute__ ((packed)); |
285 | 288 | ||
286 | /* HW encryption keys */ | 289 | /* HW encryption keys */ |
287 | #define NUM_ACCESS_CATEGORIES_COPY 4 | 290 | #define NUM_ACCESS_CATEGORIES_COPY 4 |
288 | #define MAX_KEY_SIZE 32 | 291 | #define MAX_KEY_SIZE 32 |
289 | 292 | ||
290 | /* When set, disable HW encryption */ | ||
291 | #define DF_ENCRYPTION_DISABLE 0x01 | ||
292 | /* When set, disable HW decryption */ | ||
293 | #define DF_SNIFF_MODE_ENABLE 0x80 | ||
294 | |||
295 | enum wl1271_cmd_key_action { | 293 | enum wl1271_cmd_key_action { |
296 | KEY_ADD_OR_REPLACE = 1, | 294 | KEY_ADD_OR_REPLACE = 1, |
297 | KEY_REMOVE = 2, | 295 | KEY_REMOVE = 2, |
@@ -316,9 +314,9 @@ struct wl1271_cmd_set_keys { | |||
316 | u8 addr[ETH_ALEN]; | 314 | u8 addr[ETH_ALEN]; |
317 | 315 | ||
318 | /* key_action_e */ | 316 | /* key_action_e */ |
319 | u16 key_action; | 317 | __le16 key_action; |
320 | 318 | ||
321 | u16 reserved_1; | 319 | __le16 reserved_1; |
322 | 320 | ||
323 | /* key size in bytes */ | 321 | /* key size in bytes */ |
324 | u8 key_size; | 322 | u8 key_size; |
@@ -334,8 +332,8 @@ struct wl1271_cmd_set_keys { | |||
334 | u8 id; | 332 | u8 id; |
335 | u8 reserved_2[6]; | 333 | u8 reserved_2[6]; |
336 | u8 key[MAX_KEY_SIZE]; | 334 | u8 key[MAX_KEY_SIZE]; |
337 | u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; | 335 | __le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; |
338 | u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; | 336 | __le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; |
339 | } __attribute__ ((packed)); | 337 | } __attribute__ ((packed)); |
340 | 338 | ||
341 | 339 | ||
@@ -347,19 +345,22 @@ struct wl1271_cmd_set_keys { | |||
347 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 | 345 | #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 |
348 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ | 346 | #define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ |
349 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ | 347 | #define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ |
348 | #define WL1271_SCAN_BAND_2_4_GHZ 0 | ||
349 | #define WL1271_SCAN_BAND_5_GHZ 1 | ||
350 | #define WL1271_SCAN_BAND_DUAL 2 | ||
350 | 351 | ||
351 | struct basic_scan_params { | 352 | struct basic_scan_params { |
352 | u32 rx_config_options; | 353 | __le32 rx_config_options; |
353 | u32 rx_filter_options; | 354 | __le32 rx_filter_options; |
354 | /* Scan option flags (WL1271_SCAN_OPT_*) */ | 355 | /* Scan option flags (WL1271_SCAN_OPT_*) */ |
355 | u16 scan_options; | 356 | __le16 scan_options; |
356 | /* Number of scan channels in the list (maximum 30) */ | 357 | /* Number of scan channels in the list (maximum 30) */ |
357 | u8 num_channels; | 358 | u8 num_channels; |
358 | /* This field indicates the number of probe requests to send | 359 | /* This field indicates the number of probe requests to send |
359 | per channel for an active scan */ | 360 | per channel for an active scan */ |
360 | u8 num_probe_requests; | 361 | u8 num_probe_requests; |
361 | /* Rate bit field for sending the probes */ | 362 | /* Rate bit field for sending the probes */ |
362 | u32 tx_rate; | 363 | __le32 tx_rate; |
363 | u8 tid_trigger; | 364 | u8 tid_trigger; |
364 | u8 ssid_len; | 365 | u8 ssid_len; |
365 | /* in order to align */ | 366 | /* in order to align */ |
@@ -374,10 +375,10 @@ struct basic_scan_params { | |||
374 | 375 | ||
375 | struct basic_scan_channel_params { | 376 | struct basic_scan_channel_params { |
376 | /* Duration in TU to wait for frames on a channel for active scan */ | 377 | /* Duration in TU to wait for frames on a channel for active scan */ |
377 | u32 min_duration; | 378 | __le32 min_duration; |
378 | u32 max_duration; | 379 | __le32 max_duration; |
379 | u32 bssid_lsb; | 380 | __le32 bssid_lsb; |
380 | u16 bssid_msb; | 381 | __le16 bssid_msb; |
381 | u8 early_termination; | 382 | u8 early_termination; |
382 | u8 tx_power_att; | 383 | u8 tx_power_att; |
383 | u8 channel; | 384 | u8 channel; |
@@ -397,13 +398,13 @@ struct wl1271_cmd_scan { | |||
397 | struct wl1271_cmd_trigger_scan_to { | 398 | struct wl1271_cmd_trigger_scan_to { |
398 | struct wl1271_cmd_header header; | 399 | struct wl1271_cmd_header header; |
399 | 400 | ||
400 | u32 timeout; | 401 | __le32 timeout; |
401 | }; | 402 | } __attribute__ ((packed)); |
402 | 403 | ||
403 | struct wl1271_cmd_test_header { | 404 | struct wl1271_cmd_test_header { |
404 | u8 id; | 405 | u8 id; |
405 | u8 padding[3]; | 406 | u8 padding[3]; |
406 | }; | 407 | } __attribute__ ((packed)); |
407 | 408 | ||
408 | enum wl1271_channel_tune_bands { | 409 | enum wl1271_channel_tune_bands { |
409 | WL1271_CHANNEL_TUNE_BAND_2_4, | 410 | WL1271_CHANNEL_TUNE_BAND_2_4, |
@@ -425,7 +426,7 @@ struct wl1271_cmd_cal_channel_tune { | |||
425 | u8 band; | 426 | u8 band; |
426 | u8 channel; | 427 | u8 channel; |
427 | 428 | ||
428 | u16 radio_status; | 429 | __le16 radio_status; |
429 | } __attribute__ ((packed)); | 430 | } __attribute__ ((packed)); |
430 | 431 | ||
431 | struct wl1271_cmd_cal_update_ref_point { | 432 | struct wl1271_cmd_cal_update_ref_point { |
@@ -433,8 +434,8 @@ struct wl1271_cmd_cal_update_ref_point { | |||
433 | 434 | ||
434 | struct wl1271_cmd_test_header test; | 435 | struct wl1271_cmd_test_header test; |
435 | 436 | ||
436 | s32 ref_power; | 437 | __le32 ref_power; |
437 | s32 ref_detector; | 438 | __le32 ref_detector; |
438 | u8 sub_band; | 439 | u8 sub_band; |
439 | u8 padding[3]; | 440 | u8 padding[3]; |
440 | } __attribute__ ((packed)); | 441 | } __attribute__ ((packed)); |
@@ -449,16 +450,42 @@ struct wl1271_cmd_cal_p2g { | |||
449 | 450 | ||
450 | struct wl1271_cmd_test_header test; | 451 | struct wl1271_cmd_test_header test; |
451 | 452 | ||
452 | u16 len; | 453 | __le16 len; |
453 | u8 buf[MAX_TLV_LENGTH]; | 454 | u8 buf[MAX_TLV_LENGTH]; |
454 | u8 type; | 455 | u8 type; |
455 | u8 padding; | 456 | u8 padding; |
456 | 457 | ||
457 | s16 radio_status; | 458 | __le16 radio_status; |
458 | u8 nvs_version[MAX_NVS_VERSION_LENGTH]; | 459 | u8 nvs_version[MAX_NVS_VERSION_LENGTH]; |
459 | 460 | ||
460 | u8 sub_band_mask; | 461 | u8 sub_band_mask; |
461 | u8 padding2; | 462 | u8 padding2; |
462 | } __attribute__ ((packed)); | 463 | } __attribute__ ((packed)); |
463 | 464 | ||
465 | |||
466 | /* | ||
467 | * There are three types of disconnections: | ||
468 | * | ||
469 | * DISCONNECT_IMMEDIATE: the fw doesn't send any frames | ||
470 | * DISCONNECT_DEAUTH: the fw generates a DEAUTH request with the reason | ||
471 | * we have passed | ||
472 | * DISCONNECT_DISASSOC: the fw generates a DESASSOC request with the reason | ||
473 | * we have passed | ||
474 | */ | ||
475 | enum wl1271_disconnect_type { | ||
476 | DISCONNECT_IMMEDIATE, | ||
477 | DISCONNECT_DEAUTH, | ||
478 | DISCONNECT_DISASSOC | ||
479 | }; | ||
480 | |||
481 | struct wl1271_cmd_disconnect { | ||
482 | __le32 rx_config_options; | ||
483 | __le32 rx_filter_options; | ||
484 | |||
485 | __le16 reason; | ||
486 | u8 type; | ||
487 | |||
488 | u8 padding; | ||
489 | } __attribute__ ((packed)); | ||
490 | |||
464 | #endif /* __WL1271_CMD_H__ */ | 491 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h new file mode 100644 index 000000000000..061d47520a32 --- /dev/null +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -0,0 +1,911 @@ | |||
1 | /* | ||
2 | * This file is part of wl1271 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1271_CONF_H__ | ||
25 | #define __WL1271_CONF_H__ | ||
26 | |||
27 | enum { | ||
28 | CONF_HW_BIT_RATE_1MBPS = BIT(0), | ||
29 | CONF_HW_BIT_RATE_2MBPS = BIT(1), | ||
30 | CONF_HW_BIT_RATE_5_5MBPS = BIT(2), | ||
31 | CONF_HW_BIT_RATE_6MBPS = BIT(3), | ||
32 | CONF_HW_BIT_RATE_9MBPS = BIT(4), | ||
33 | CONF_HW_BIT_RATE_11MBPS = BIT(5), | ||
34 | CONF_HW_BIT_RATE_12MBPS = BIT(6), | ||
35 | CONF_HW_BIT_RATE_18MBPS = BIT(7), | ||
36 | CONF_HW_BIT_RATE_22MBPS = BIT(8), | ||
37 | CONF_HW_BIT_RATE_24MBPS = BIT(9), | ||
38 | CONF_HW_BIT_RATE_36MBPS = BIT(10), | ||
39 | CONF_HW_BIT_RATE_48MBPS = BIT(11), | ||
40 | CONF_HW_BIT_RATE_54MBPS = BIT(12), | ||
41 | CONF_HW_BIT_RATE_MCS_0 = BIT(13), | ||
42 | CONF_HW_BIT_RATE_MCS_1 = BIT(14), | ||
43 | CONF_HW_BIT_RATE_MCS_2 = BIT(15), | ||
44 | CONF_HW_BIT_RATE_MCS_3 = BIT(16), | ||
45 | CONF_HW_BIT_RATE_MCS_4 = BIT(17), | ||
46 | CONF_HW_BIT_RATE_MCS_5 = BIT(18), | ||
47 | CONF_HW_BIT_RATE_MCS_6 = BIT(19), | ||
48 | CONF_HW_BIT_RATE_MCS_7 = BIT(20) | ||
49 | }; | ||
50 | |||
51 | enum { | ||
52 | CONF_HW_RATE_INDEX_1MBPS = 0, | ||
53 | CONF_HW_RATE_INDEX_2MBPS = 1, | ||
54 | CONF_HW_RATE_INDEX_5_5MBPS = 2, | ||
55 | CONF_HW_RATE_INDEX_6MBPS = 3, | ||
56 | CONF_HW_RATE_INDEX_9MBPS = 4, | ||
57 | CONF_HW_RATE_INDEX_11MBPS = 5, | ||
58 | CONF_HW_RATE_INDEX_12MBPS = 6, | ||
59 | CONF_HW_RATE_INDEX_18MBPS = 7, | ||
60 | CONF_HW_RATE_INDEX_22MBPS = 8, | ||
61 | CONF_HW_RATE_INDEX_24MBPS = 9, | ||
62 | CONF_HW_RATE_INDEX_36MBPS = 10, | ||
63 | CONF_HW_RATE_INDEX_48MBPS = 11, | ||
64 | CONF_HW_RATE_INDEX_54MBPS = 12, | ||
65 | CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS, | ||
66 | }; | ||
67 | |||
68 | struct conf_sg_settings { | ||
69 | /* | ||
70 | * Defines the PER threshold in PPM of the BT voice of which reaching | ||
71 | * this value will trigger raising the priority of the BT voice by | ||
72 | * the BT IP until next NFS sample interval time as defined in | ||
73 | * nfs_sample_interval. | ||
74 | * | ||
75 | * Unit: PER value in PPM (parts per million) | ||
76 | * #Error_packets / #Total_packets | ||
77 | |||
78 | * Range: u32 | ||
79 | */ | ||
80 | u32 per_threshold; | ||
81 | |||
82 | /* | ||
83 | * This value is an absolute time in micro-seconds to limit the | ||
84 | * maximum scan duration compensation while in SG | ||
85 | */ | ||
86 | u32 max_scan_compensation_time; | ||
87 | |||
88 | /* Defines the PER threshold of the BT voice of which reaching this | ||
89 | * value will trigger raising the priority of the BT voice until next | ||
90 | * NFS sample interval time as defined in sample_interval. | ||
91 | * | ||
92 | * Unit: msec | ||
93 | * Range: 1-65000 | ||
94 | */ | ||
95 | u16 nfs_sample_interval; | ||
96 | |||
97 | /* | ||
98 | * Defines the load ratio for the BT. | ||
99 | * The WLAN ratio is: 100 - load_ratio | ||
100 | * | ||
101 | * Unit: Percent | ||
102 | * Range: 0-100 | ||
103 | */ | ||
104 | u8 load_ratio; | ||
105 | |||
106 | /* | ||
107 | * true - Co-ex is allowed to enter/exit P.S automatically and | ||
108 | * transparently to the host | ||
109 | * | ||
110 | * false - Co-ex is disallowed to enter/exit P.S and will trigger an | ||
111 | * event to the host to notify for the need to enter/exit P.S | ||
112 | * due to BT change state | ||
113 | * | ||
114 | */ | ||
115 | u8 auto_ps_mode; | ||
116 | |||
117 | /* | ||
118 | * This parameter defines the compensation percentage of num of probe | ||
119 | * requests in case scan is initiated during BT voice/BT ACL | ||
120 | * guaranteed link. | ||
121 | * | ||
122 | * Unit: Percent | ||
123 | * Range: 0-255 (0 - No compensation) | ||
124 | */ | ||
125 | u8 probe_req_compensation; | ||
126 | |||
127 | /* | ||
128 | * This parameter defines the compensation percentage of scan window | ||
129 | * size in case scan is initiated during BT voice/BT ACL Guaranteed | ||
130 | * link. | ||
131 | * | ||
132 | * Unit: Percent | ||
133 | * Range: 0-255 (0 - No compensation) | ||
134 | */ | ||
135 | u8 scan_window_compensation; | ||
136 | |||
137 | /* | ||
138 | * Defines the antenna configuration. | ||
139 | * | ||
140 | * Range: 0 - Single Antenna; 1 - Dual Antenna | ||
141 | */ | ||
142 | u8 antenna_config; | ||
143 | |||
144 | /* | ||
145 | * The percent out of the Max consecutive beacon miss roaming trigger | ||
146 | * which is the threshold for raising the priority of beacon | ||
147 | * reception. | ||
148 | * | ||
149 | * Range: 1-100 | ||
150 | * N = MaxConsecutiveBeaconMiss | ||
151 | * P = coexMaxConsecutiveBeaconMissPrecent | ||
152 | * Threshold = MIN( N-1, round(N * P / 100)) | ||
153 | */ | ||
154 | u8 beacon_miss_threshold; | ||
155 | |||
156 | /* | ||
157 | * The RX rate threshold below which rate adaptation is assumed to be | ||
158 | * occurring at the AP which will raise priority for ACTIVE_RX and RX | ||
159 | * SP. | ||
160 | * | ||
161 | * Range: HW_BIT_RATE_* | ||
162 | */ | ||
163 | u32 rate_adaptation_threshold; | ||
164 | |||
165 | /* | ||
166 | * The SNR above which the RX rate threshold indicating AP rate | ||
167 | * adaptation is valid | ||
168 | * | ||
169 | * Range: -128 - 127 | ||
170 | */ | ||
171 | s8 rate_adaptation_snr; | ||
172 | }; | ||
173 | |||
174 | enum conf_rx_queue_type { | ||
175 | CONF_RX_QUEUE_TYPE_LOW_PRIORITY, /* All except the high priority */ | ||
176 | CONF_RX_QUEUE_TYPE_HIGH_PRIORITY, /* Management and voice packets */ | ||
177 | }; | ||
178 | |||
179 | struct conf_rx_settings { | ||
180 | /* | ||
181 | * The maximum amount of time, in TU, before the | ||
182 | * firmware discards the MSDU. | ||
183 | * | ||
184 | * Range: 0 - 0xFFFFFFFF | ||
185 | */ | ||
186 | u32 rx_msdu_life_time; | ||
187 | |||
188 | /* | ||
189 | * Packet detection threshold in the PHY. | ||
190 | * | ||
191 | * FIXME: details unknown. | ||
192 | */ | ||
193 | u32 packet_detection_threshold; | ||
194 | |||
195 | /* | ||
196 | * The longest time the STA will wait to receive traffic from the AP | ||
197 | * after a PS-poll has been transmitted. | ||
198 | * | ||
199 | * Range: 0 - 200000 | ||
200 | */ | ||
201 | u16 ps_poll_timeout; | ||
202 | /* | ||
203 | * The longest time the STA will wait to receive traffic from the AP | ||
204 | * after a frame has been sent from an UPSD enabled queue. | ||
205 | * | ||
206 | * Range: 0 - 200000 | ||
207 | */ | ||
208 | u16 upsd_timeout; | ||
209 | |||
210 | /* | ||
211 | * The number of octets in an MPDU, below which an RTS/CTS | ||
212 | * handshake is not performed. | ||
213 | * | ||
214 | * Range: 0 - 4096 | ||
215 | */ | ||
216 | u16 rts_threshold; | ||
217 | |||
218 | /* | ||
219 | * The RX Clear Channel Assessment threshold in the PHY | ||
220 | * (the energy threshold). | ||
221 | * | ||
222 | * Range: ENABLE_ENERGY_D == 0x140A | ||
223 | * DISABLE_ENERGY_D == 0xFFEF | ||
224 | */ | ||
225 | u16 rx_cca_threshold; | ||
226 | |||
227 | /* | ||
228 | * Occupied Rx mem-blocks number which requires interrupting the host | ||
229 | * (0 = no buffering, 0xffff = disabled). | ||
230 | * | ||
231 | * Range: u16 | ||
232 | */ | ||
233 | u16 irq_blk_threshold; | ||
234 | |||
235 | /* | ||
236 | * Rx packets number which requires interrupting the host | ||
237 | * (0 = no buffering). | ||
238 | * | ||
239 | * Range: u16 | ||
240 | */ | ||
241 | u16 irq_pkt_threshold; | ||
242 | |||
243 | /* | ||
244 | * Max time in msec the FW may delay RX-Complete interrupt. | ||
245 | * | ||
246 | * Range: 1 - 100 | ||
247 | */ | ||
248 | u16 irq_timeout; | ||
249 | |||
250 | /* | ||
251 | * The RX queue type. | ||
252 | * | ||
253 | * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY, | ||
254 | */ | ||
255 | u8 queue_type; | ||
256 | }; | ||
257 | |||
258 | #define CONF_TX_MAX_RATE_CLASSES 8 | ||
259 | |||
260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 | ||
261 | #define CONF_TX_RATE_MASK_ALL 0x1eff | ||
262 | #define CONF_TX_RATE_RETRY_LIMIT 10 | ||
263 | |||
264 | struct conf_tx_rate_class { | ||
265 | |||
266 | /* | ||
267 | * The rates enabled for this rate class. | ||
268 | * | ||
269 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
270 | */ | ||
271 | u32 enabled_rates; | ||
272 | |||
273 | /* | ||
274 | * The dot11 short retry limit used for TX retries. | ||
275 | * | ||
276 | * Range: u8 | ||
277 | */ | ||
278 | u8 short_retry_limit; | ||
279 | |||
280 | /* | ||
281 | * The dot11 long retry limit used for TX retries. | ||
282 | * | ||
283 | * Range: u8 | ||
284 | */ | ||
285 | u8 long_retry_limit; | ||
286 | |||
287 | /* | ||
288 | * Flags controlling the attributes of TX transmission. | ||
289 | * | ||
290 | * Range: bit 0: Truncate - when set, FW attempts to send a frame stop | ||
291 | * when the total valid per-rate attempts have | ||
292 | * been exhausted; otherwise transmissions | ||
293 | * will continue at the lowest available rate | ||
294 | * until the appropriate one of the | ||
295 | * short_retry_limit, long_retry_limit, | ||
296 | * dot11_max_transmit_msdu_life_time, or | ||
297 | * max_tx_life_time, is exhausted. | ||
298 | * 1: Preamble Override - indicates if the preamble type | ||
299 | * should be used in TX. | ||
300 | * 2: Preamble Type - the type of the preamble to be used by | ||
301 | * the policy (0 - long preamble, 1 - short preamble. | ||
302 | */ | ||
303 | u8 aflags; | ||
304 | }; | ||
305 | |||
306 | #define CONF_TX_MAX_AC_COUNT 4 | ||
307 | |||
308 | /* Slot number setting to start transmission at PIFS interval */ | ||
309 | #define CONF_TX_AIFS_PIFS 1 | ||
310 | /* Slot number setting to start transmission at DIFS interval normal | ||
311 | * DCF access */ | ||
312 | #define CONF_TX_AIFS_DIFS 2 | ||
313 | |||
314 | |||
315 | enum conf_tx_ac { | ||
316 | CONF_TX_AC_BE = 0, /* best effort / legacy */ | ||
317 | CONF_TX_AC_BK = 1, /* background */ | ||
318 | CONF_TX_AC_VI = 2, /* video */ | ||
319 | CONF_TX_AC_VO = 3, /* voice */ | ||
320 | CONF_TX_AC_CTS2SELF = 4, /* fictious AC, follows AC_VO */ | ||
321 | CONF_TX_AC_ANY_TID = 0x1f | ||
322 | }; | ||
323 | |||
324 | struct conf_tx_ac_category { | ||
325 | /* | ||
326 | * The AC class identifier. | ||
327 | * | ||
328 | * Range: enum conf_tx_ac | ||
329 | */ | ||
330 | u8 ac; | ||
331 | |||
332 | /* | ||
333 | * The contention window minimum size (in slots) for the access | ||
334 | * class. | ||
335 | * | ||
336 | * Range: u8 | ||
337 | */ | ||
338 | u8 cw_min; | ||
339 | |||
340 | /* | ||
341 | * The contention window maximum size (in slots) for the access | ||
342 | * class. | ||
343 | * | ||
344 | * Range: u8 | ||
345 | */ | ||
346 | u16 cw_max; | ||
347 | |||
348 | /* | ||
349 | * The AIF value (in slots) for the access class. | ||
350 | * | ||
351 | * Range: u8 | ||
352 | */ | ||
353 | u8 aifsn; | ||
354 | |||
355 | /* | ||
356 | * The TX Op Limit (in microseconds) for the access class. | ||
357 | * | ||
358 | * Range: u16 | ||
359 | */ | ||
360 | u16 tx_op_limit; | ||
361 | }; | ||
362 | |||
363 | #define CONF_TX_MAX_TID_COUNT 7 | ||
364 | |||
365 | enum { | ||
366 | CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/ | ||
367 | CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/ | ||
368 | CONF_CHANNEL_TYPE_HCCA = 2, /* HCCA*/ | ||
369 | }; | ||
370 | |||
371 | enum { | ||
372 | CONF_PS_SCHEME_LEGACY = 0, | ||
373 | CONF_PS_SCHEME_UPSD_TRIGGER = 1, | ||
374 | CONF_PS_SCHEME_LEGACY_PSPOLL = 2, | ||
375 | CONF_PS_SCHEME_SAPSD = 3, | ||
376 | }; | ||
377 | |||
378 | enum { | ||
379 | CONF_ACK_POLICY_LEGACY = 0, | ||
380 | CONF_ACK_POLICY_NO_ACK = 1, | ||
381 | CONF_ACK_POLICY_BLOCK = 2, | ||
382 | }; | ||
383 | |||
384 | |||
385 | struct conf_tx_tid { | ||
386 | u8 queue_id; | ||
387 | u8 channel_type; | ||
388 | u8 tsid; | ||
389 | u8 ps_scheme; | ||
390 | u8 ack_policy; | ||
391 | u32 apsd_conf[2]; | ||
392 | }; | ||
393 | |||
394 | struct conf_tx_settings { | ||
395 | /* | ||
396 | * The TX ED value for TELEC Enable/Disable. | ||
397 | * | ||
398 | * Range: 0, 1 | ||
399 | */ | ||
400 | u8 tx_energy_detection; | ||
401 | |||
402 | /* | ||
403 | * Configuration for rate classes for TX (currently only one | ||
404 | * rate class supported.) | ||
405 | */ | ||
406 | struct conf_tx_rate_class rc_conf; | ||
407 | |||
408 | /* | ||
409 | * Configuration for access categories for TX rate control. | ||
410 | */ | ||
411 | u8 ac_conf_count; | ||
412 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; | ||
413 | |||
414 | /* | ||
415 | * Configuration for TID parameters. | ||
416 | */ | ||
417 | u8 tid_conf_count; | ||
418 | struct conf_tx_tid tid_conf[CONF_TX_MAX_TID_COUNT]; | ||
419 | |||
420 | /* | ||
421 | * The TX fragmentation threshold. | ||
422 | * | ||
423 | * Range: u16 | ||
424 | */ | ||
425 | u16 frag_threshold; | ||
426 | |||
427 | /* | ||
428 | * Max time in msec the FW may delay frame TX-Complete interrupt. | ||
429 | * | ||
430 | * Range: u16 | ||
431 | */ | ||
432 | u16 tx_compl_timeout; | ||
433 | |||
434 | /* | ||
435 | * Completed TX packet count which requires to issue the TX-Complete | ||
436 | * interrupt. | ||
437 | * | ||
438 | * Range: u16 | ||
439 | */ | ||
440 | u16 tx_compl_threshold; | ||
441 | |||
442 | }; | ||
443 | |||
444 | enum { | ||
445 | CONF_WAKE_UP_EVENT_BEACON = 0x01, /* Wake on every Beacon*/ | ||
446 | CONF_WAKE_UP_EVENT_DTIM = 0x02, /* Wake on every DTIM*/ | ||
447 | CONF_WAKE_UP_EVENT_N_DTIM = 0x04, /* Wake every Nth DTIM */ | ||
448 | CONF_WAKE_UP_EVENT_N_BEACONS = 0x08, /* Wake every Nth beacon */ | ||
449 | CONF_WAKE_UP_EVENT_BITS_MASK = 0x0F | ||
450 | }; | ||
451 | |||
452 | #define CONF_MAX_BCN_FILT_IE_COUNT 32 | ||
453 | |||
454 | #define CONF_BCN_RULE_PASS_ON_CHANGE BIT(0) | ||
455 | #define CONF_BCN_RULE_PASS_ON_APPEARANCE BIT(1) | ||
456 | |||
457 | #define CONF_BCN_IE_OUI_LEN 3 | ||
458 | #define CONF_BCN_IE_VER_LEN 2 | ||
459 | |||
460 | struct conf_bcn_filt_rule { | ||
461 | /* | ||
462 | * IE number to which to associate a rule. | ||
463 | * | ||
464 | * Range: u8 | ||
465 | */ | ||
466 | u8 ie; | ||
467 | |||
468 | /* | ||
469 | * Rule to associate with the specific ie. | ||
470 | * | ||
471 | * Range: CONF_BCN_RULE_PASS_ON_* | ||
472 | */ | ||
473 | u8 rule; | ||
474 | |||
475 | /* | ||
476 | * OUI for the vendor specifie IE (221) | ||
477 | */ | ||
478 | u8 oui[CONF_BCN_IE_OUI_LEN]; | ||
479 | |||
480 | /* | ||
481 | * Type for the vendor specifie IE (221) | ||
482 | */ | ||
483 | u8 type; | ||
484 | |||
485 | /* | ||
486 | * Version for the vendor specifie IE (221) | ||
487 | */ | ||
488 | u8 version[CONF_BCN_IE_VER_LEN]; | ||
489 | }; | ||
490 | |||
491 | #define CONF_MAX_RSSI_SNR_TRIGGERS 8 | ||
492 | |||
493 | enum { | ||
494 | CONF_TRIG_METRIC_RSSI_BEACON = 0, | ||
495 | CONF_TRIG_METRIC_RSSI_DATA, | ||
496 | CONF_TRIG_METRIC_SNR_BEACON, | ||
497 | CONF_TRIG_METRIC_SNR_DATA | ||
498 | }; | ||
499 | |||
500 | enum { | ||
501 | CONF_TRIG_EVENT_TYPE_LEVEL = 0, | ||
502 | CONF_TRIG_EVENT_TYPE_EDGE | ||
503 | }; | ||
504 | |||
505 | enum { | ||
506 | CONF_TRIG_EVENT_DIR_LOW = 0, | ||
507 | CONF_TRIG_EVENT_DIR_HIGH, | ||
508 | CONF_TRIG_EVENT_DIR_BIDIR | ||
509 | }; | ||
510 | |||
511 | |||
512 | struct conf_sig_trigger { | ||
513 | /* | ||
514 | * The RSSI / SNR threshold value. | ||
515 | * | ||
516 | * FIXME: what is the range? | ||
517 | */ | ||
518 | s16 threshold; | ||
519 | |||
520 | /* | ||
521 | * Minimum delay between two trigger events for this trigger in ms. | ||
522 | * | ||
523 | * Range: 0 - 60000 | ||
524 | */ | ||
525 | u16 pacing; | ||
526 | |||
527 | /* | ||
528 | * The measurement data source for this trigger. | ||
529 | * | ||
530 | * Range: CONF_TRIG_METRIC_* | ||
531 | */ | ||
532 | u8 metric; | ||
533 | |||
534 | /* | ||
535 | * The trigger type of this trigger. | ||
536 | * | ||
537 | * Range: CONF_TRIG_EVENT_TYPE_* | ||
538 | */ | ||
539 | u8 type; | ||
540 | |||
541 | /* | ||
542 | * The direction of the trigger. | ||
543 | * | ||
544 | * Range: CONF_TRIG_EVENT_DIR_* | ||
545 | */ | ||
546 | u8 direction; | ||
547 | |||
548 | /* | ||
549 | * Hysteresis range of the trigger around the threshold (in dB) | ||
550 | * | ||
551 | * Range: u8 | ||
552 | */ | ||
553 | u8 hysteresis; | ||
554 | |||
555 | /* | ||
556 | * Index of the trigger rule. | ||
557 | * | ||
558 | * Range: 0 - CONF_MAX_RSSI_SNR_TRIGGERS-1 | ||
559 | */ | ||
560 | u8 index; | ||
561 | |||
562 | /* | ||
563 | * Enable / disable this rule (to use for clearing rules.) | ||
564 | * | ||
565 | * Range: 1 - Enabled, 2 - Not enabled | ||
566 | */ | ||
567 | u8 enable; | ||
568 | }; | ||
569 | |||
570 | struct conf_sig_weights { | ||
571 | |||
572 | /* | ||
573 | * RSSI from beacons average weight. | ||
574 | * | ||
575 | * Range: u8 | ||
576 | */ | ||
577 | u8 rssi_bcn_avg_weight; | ||
578 | |||
579 | /* | ||
580 | * RSSI from data average weight. | ||
581 | * | ||
582 | * Range: u8 | ||
583 | */ | ||
584 | u8 rssi_pkt_avg_weight; | ||
585 | |||
586 | /* | ||
587 | * SNR from beacons average weight. | ||
588 | * | ||
589 | * Range: u8 | ||
590 | */ | ||
591 | u8 snr_bcn_avg_weight; | ||
592 | |||
593 | /* | ||
594 | * SNR from data average weight. | ||
595 | * | ||
596 | * Range: u8 | ||
597 | */ | ||
598 | u8 snr_pkt_avg_weight; | ||
599 | }; | ||
600 | |||
601 | enum conf_bcn_filt_mode { | ||
602 | CONF_BCN_FILT_MODE_DISABLED = 0, | ||
603 | CONF_BCN_FILT_MODE_ENABLED = 1 | ||
604 | }; | ||
605 | |||
606 | enum conf_bet_mode { | ||
607 | CONF_BET_MODE_DISABLE = 0, | ||
608 | CONF_BET_MODE_ENABLE = 1, | ||
609 | }; | ||
610 | |||
611 | struct conf_conn_settings { | ||
612 | /* | ||
613 | * Firmware wakeup conditions configuration. The host may set only | ||
614 | * one bit. | ||
615 | * | ||
616 | * Range: CONF_WAKE_UP_EVENT_* | ||
617 | */ | ||
618 | u8 wake_up_event; | ||
619 | |||
620 | /* | ||
621 | * Listen interval for beacons or Dtims. | ||
622 | * | ||
623 | * Range: 0 for beacon and Dtim wakeup | ||
624 | * 1-10 for x Dtims | ||
625 | * 1-255 for x beacons | ||
626 | */ | ||
627 | u8 listen_interval; | ||
628 | |||
629 | /* | ||
630 | * Enable or disable the beacon filtering. | ||
631 | * | ||
632 | * Range: CONF_BCN_FILT_MODE_* | ||
633 | */ | ||
634 | enum conf_bcn_filt_mode bcn_filt_mode; | ||
635 | |||
636 | /* | ||
637 | * Configure Beacon filter pass-thru rules. | ||
638 | */ | ||
639 | u8 bcn_filt_ie_count; | ||
640 | struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT]; | ||
641 | |||
642 | /* | ||
643 | * The number of consequtive beacons to lose, before the firmware | ||
644 | * becomes out of synch. | ||
645 | * | ||
646 | * Range: u32 | ||
647 | */ | ||
648 | u32 synch_fail_thold; | ||
649 | |||
650 | /* | ||
651 | * After out-of-synch, the number of TU's to wait without a further | ||
652 | * received beacon (or probe response) before issuing the BSS_EVENT_LOSE | ||
653 | * event. | ||
654 | * | ||
655 | * Range: u32 | ||
656 | */ | ||
657 | u32 bss_lose_timeout; | ||
658 | |||
659 | /* | ||
660 | * Beacon receive timeout. | ||
661 | * | ||
662 | * Range: u32 | ||
663 | */ | ||
664 | u32 beacon_rx_timeout; | ||
665 | |||
666 | /* | ||
667 | * Broadcast receive timeout. | ||
668 | * | ||
669 | * Range: u32 | ||
670 | */ | ||
671 | u32 broadcast_timeout; | ||
672 | |||
673 | /* | ||
674 | * Enable/disable reception of broadcast packets in power save mode | ||
675 | * | ||
676 | * Range: 1 - enable, 0 - disable | ||
677 | */ | ||
678 | u8 rx_broadcast_in_ps; | ||
679 | |||
680 | /* | ||
681 | * Consequtive PS Poll failures before sending event to driver | ||
682 | * | ||
683 | * Range: u8 | ||
684 | */ | ||
685 | u8 ps_poll_threshold; | ||
686 | |||
687 | /* | ||
688 | * Configuration of signal (rssi/snr) triggers. | ||
689 | */ | ||
690 | u8 sig_trigger_count; | ||
691 | struct conf_sig_trigger sig_trigger[CONF_MAX_RSSI_SNR_TRIGGERS]; | ||
692 | |||
693 | /* | ||
694 | * Configuration of signal average weights. | ||
695 | */ | ||
696 | struct conf_sig_weights sig_weights; | ||
697 | |||
698 | /* | ||
699 | * Specifies if beacon early termination procedure is enabled or | ||
700 | * disabled. | ||
701 | * | ||
702 | * Range: CONF_BET_MODE_* | ||
703 | */ | ||
704 | u8 bet_enable; | ||
705 | |||
706 | /* | ||
707 | * Specifies the maximum number of consecutive beacons that may be | ||
708 | * early terminated. After this number is reached at least one full | ||
709 | * beacon must be correctly received in FW before beacon ET | ||
710 | * resumes. | ||
711 | * | ||
712 | * Range 0 - 255 | ||
713 | */ | ||
714 | u8 bet_max_consecutive; | ||
715 | }; | ||
716 | |||
717 | #define CONF_SR_ERR_TBL_MAX_VALUES 14 | ||
718 | |||
719 | struct conf_mart_reflex_err_table { | ||
720 | /* | ||
721 | * Length of the error table values table. | ||
722 | * | ||
723 | * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES | ||
724 | */ | ||
725 | u8 len; | ||
726 | |||
727 | /* | ||
728 | * Smart Reflex error table upper limit. | ||
729 | * | ||
730 | * Range: s8 | ||
731 | */ | ||
732 | s8 upper_limit; | ||
733 | |||
734 | /* | ||
735 | * Smart Reflex error table values. | ||
736 | * | ||
737 | * Range: s8 | ||
738 | */ | ||
739 | s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; | ||
740 | }; | ||
741 | |||
742 | enum { | ||
743 | CONF_REF_CLK_19_2_E, | ||
744 | CONF_REF_CLK_26_E, | ||
745 | CONF_REF_CLK_38_4_E, | ||
746 | CONF_REF_CLK_52_E | ||
747 | }; | ||
748 | |||
749 | enum single_dual_band_enum { | ||
750 | CONF_SINGLE_BAND, | ||
751 | CONF_DUAL_BAND | ||
752 | }; | ||
753 | |||
754 | struct conf_general_parms { | ||
755 | /* | ||
756 | * RF Reference Clock type / speed | ||
757 | * | ||
758 | * Range: CONF_REF_CLK_* | ||
759 | */ | ||
760 | u8 ref_clk; | ||
761 | |||
762 | /* | ||
763 | * Settling time of the reference clock after boot. | ||
764 | * | ||
765 | * Range: u8 | ||
766 | */ | ||
767 | u8 settling_time; | ||
768 | |||
769 | /* | ||
770 | * Flag defining whether clock is valid on wakeup. | ||
771 | * | ||
772 | * Range: 0 - not valid on wakeup, 1 - valid on wakeup | ||
773 | */ | ||
774 | u8 clk_valid_on_wakeup; | ||
775 | |||
776 | /* | ||
777 | * DC-to-DC mode. | ||
778 | * | ||
779 | * Range: Unknown | ||
780 | */ | ||
781 | u8 dc2dcmode; | ||
782 | |||
783 | /* | ||
784 | * Flag defining whether used as single or dual-band. | ||
785 | * | ||
786 | * Range: CONF_SINGLE_BAND, CONF_DUAL_BAND | ||
787 | */ | ||
788 | u8 single_dual_band; | ||
789 | |||
790 | /* | ||
791 | * TX bip fem autodetect flag. | ||
792 | * | ||
793 | * Range: Unknown | ||
794 | */ | ||
795 | u8 tx_bip_fem_autodetect; | ||
796 | |||
797 | /* | ||
798 | * TX bip gem manufacturer. | ||
799 | * | ||
800 | * Range: Unknown | ||
801 | */ | ||
802 | u8 tx_bip_fem_manufacturer; | ||
803 | |||
804 | /* | ||
805 | * Settings flags. | ||
806 | * | ||
807 | * Range: Unknown | ||
808 | */ | ||
809 | u8 settings; | ||
810 | }; | ||
811 | |||
812 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | ||
813 | #define CONF_NUMBER_OF_SUB_BANDS_5 7 | ||
814 | #define CONF_NUMBER_OF_RATE_GROUPS 6 | ||
815 | #define CONF_NUMBER_OF_CHANNELS_2_4 14 | ||
816 | #define CONF_NUMBER_OF_CHANNELS_5 35 | ||
817 | |||
818 | struct conf_radio_parms { | ||
819 | /* | ||
820 | * Static radio parameters for 2.4GHz | ||
821 | * | ||
822 | * Range: unknown | ||
823 | */ | ||
824 | u8 rx_trace_loss; | ||
825 | u8 tx_trace_loss; | ||
826 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
827 | |||
828 | /* | ||
829 | * Static radio parameters for 5GHz | ||
830 | * | ||
831 | * Range: unknown | ||
832 | */ | ||
833 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
834 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
835 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; | ||
836 | |||
837 | /* | ||
838 | * Dynamic radio parameters for 2.4GHz | ||
839 | * | ||
840 | * Range: unknown | ||
841 | */ | ||
842 | s16 tx_ref_pd_voltage; | ||
843 | s8 tx_ref_power; | ||
844 | s8 tx_offset_db; | ||
845 | |||
846 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | ||
847 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | ||
848 | |||
849 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
850 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | ||
851 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; | ||
852 | |||
853 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | ||
854 | u8 rx_fem_insertion_loss; | ||
855 | |||
856 | /* | ||
857 | * Dynamic radio parameters for 5GHz | ||
858 | * | ||
859 | * Range: unknown | ||
860 | */ | ||
861 | s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
862 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
863 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
864 | |||
865 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
866 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
867 | |||
868 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | ||
869 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
870 | |||
871 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | ||
872 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
873 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | ||
874 | }; | ||
875 | |||
876 | #define CONF_SR_ERR_TBL_COUNT 3 | ||
877 | |||
878 | struct conf_init_settings { | ||
879 | /* | ||
880 | * Configure Smart Reflex error table values. | ||
881 | */ | ||
882 | struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; | ||
883 | |||
884 | /* | ||
885 | * Smart Reflex enable flag. | ||
886 | * | ||
887 | * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled | ||
888 | */ | ||
889 | u8 sr_enable; | ||
890 | |||
891 | /* | ||
892 | * Configure general parameters. | ||
893 | */ | ||
894 | struct conf_general_parms genparam; | ||
895 | |||
896 | /* | ||
897 | * Configure radio parameters. | ||
898 | */ | ||
899 | struct conf_radio_parms radioparam; | ||
900 | |||
901 | }; | ||
902 | |||
903 | struct conf_drv_settings { | ||
904 | struct conf_sg_settings sg; | ||
905 | struct conf_rx_settings rx; | ||
906 | struct conf_tx_settings tx; | ||
907 | struct conf_conn_settings conn; | ||
908 | struct conf_init_settings init; | ||
909 | }; | ||
910 | |||
911 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index f3afd4a6ff33..31d396ba9188 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -26,20 +26,45 @@ | |||
26 | #include "wl1271_spi.h" | 26 | #include "wl1271_spi.h" |
27 | #include "wl1271_event.h" | 27 | #include "wl1271_event.h" |
28 | #include "wl1271_ps.h" | 28 | #include "wl1271_ps.h" |
29 | #include "wl12xx_80211.h" | ||
29 | 30 | ||
30 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 31 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
31 | struct event_mailbox *mbox) | 32 | struct event_mailbox *mbox) |
32 | { | 33 | { |
34 | int size = sizeof(struct wl12xx_probe_req_template); | ||
33 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
34 | mbox->scheduled_scan_status); | 36 | mbox->scheduled_scan_status); |
35 | 37 | ||
36 | if (wl->scanning) { | 38 | if (wl->scanning) { |
37 | mutex_unlock(&wl->mutex); | 39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
38 | ieee80211_scan_completed(wl->hw, false); | 40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
39 | mutex_lock(&wl->mutex); | 41 | NULL, size); |
40 | wl->scanning = false; | 42 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend |
43 | * to the wl1271_cmd_scan function that we are not | ||
44 | * scanning as it checks that. | ||
45 | */ | ||
46 | wl->scanning = false; | ||
47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | ||
48 | wl->scan.active, | ||
49 | wl->scan.high_prio, | ||
50 | WL1271_SCAN_BAND_5_GHZ, | ||
51 | wl->scan.probe_requests); | ||
52 | } else { | ||
53 | if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) | ||
54 | wl1271_cmd_template_set(wl, | ||
55 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
56 | NULL, size); | ||
57 | else | ||
58 | wl1271_cmd_template_set(wl, | ||
59 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
60 | NULL, size); | ||
61 | |||
62 | mutex_unlock(&wl->mutex); | ||
63 | ieee80211_scan_completed(wl->hw, false); | ||
64 | mutex_lock(&wl->mutex); | ||
65 | wl->scanning = false; | ||
66 | } | ||
41 | } | 67 | } |
42 | |||
43 | return 0; | 68 | return 0; |
44 | } | 69 | } |
45 | 70 | ||
@@ -57,7 +82,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
57 | 82 | ||
58 | wl1271_event_mbox_dump(mbox); | 83 | wl1271_event_mbox_dump(mbox); |
59 | 84 | ||
60 | vector = mbox->events_vector & ~(mbox->events_mask); | 85 | vector = le32_to_cpu(mbox->events_vector); |
86 | vector &= ~(le32_to_cpu(mbox->events_mask)); | ||
61 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); | 87 | wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); |
62 | 88 | ||
63 | if (vector & SCAN_COMPLETE_EVENT_ID) { | 89 | if (vector & SCAN_COMPLETE_EVENT_ID) { |
@@ -66,14 +92,16 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
66 | return ret; | 92 | return ret; |
67 | } | 93 | } |
68 | 94 | ||
69 | if (vector & BSS_LOSE_EVENT_ID) { | 95 | /* |
96 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | ||
97 | * filtering) is enabled. Without PSM, the stack will receive all | ||
98 | * beacons and can detect beacon loss by itself. | ||
99 | */ | ||
100 | if (vector & BSS_LOSE_EVENT_ID && wl->psm) { | ||
70 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | 101 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
71 | 102 | ||
72 | if (wl->psm_requested && wl->psm) { | 103 | /* indicate to the stack, that beacons have been lost */ |
73 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 104 | ieee80211_beacon_loss(wl->vif); |
74 | if (ret < 0) | ||
75 | return ret; | ||
76 | } | ||
77 | } | 105 | } |
78 | 106 | ||
79 | return 0; | 107 | return 0; |
@@ -92,14 +120,14 @@ int wl1271_event_unmask(struct wl1271 *wl) | |||
92 | 120 | ||
93 | void wl1271_event_mbox_config(struct wl1271 *wl) | 121 | void wl1271_event_mbox_config(struct wl1271 *wl) |
94 | { | 122 | { |
95 | wl->mbox_ptr[0] = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR); | 123 | wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR); |
96 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 124 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
97 | 125 | ||
98 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", | 126 | wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", |
99 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 127 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
100 | } | 128 | } |
101 | 129 | ||
102 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | 130 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) |
103 | { | 131 | { |
104 | struct event_mailbox mbox; | 132 | struct event_mailbox mbox; |
105 | int ret; | 133 | int ret; |
@@ -110,8 +138,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
110 | return -EINVAL; | 138 | return -EINVAL; |
111 | 139 | ||
112 | /* first we read the mbox descriptor */ | 140 | /* first we read the mbox descriptor */ |
113 | wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, | 141 | wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox, |
114 | sizeof(struct event_mailbox)); | 142 | sizeof(struct event_mailbox), false); |
115 | 143 | ||
116 | /* process the descriptor */ | 144 | /* process the descriptor */ |
117 | ret = wl1271_event_process(wl, &mbox); | 145 | ret = wl1271_event_process(wl, &mbox); |
@@ -119,7 +147,9 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
119 | return ret; | 147 | return ret; |
120 | 148 | ||
121 | /* then we let the firmware know it can go on...*/ | 149 | /* then we let the firmware know it can go on...*/ |
122 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); | 150 | if (do_ack) |
151 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, | ||
152 | INTR_TRIG_EVENT_ACK); | ||
123 | 153 | ||
124 | return 0; | 154 | return 0; |
125 | } | 155 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 2cdce7c34bf0..3ab53d331f15 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -66,33 +66,33 @@ enum { | |||
66 | struct event_debug_report { | 66 | struct event_debug_report { |
67 | u8 debug_event_id; | 67 | u8 debug_event_id; |
68 | u8 num_params; | 68 | u8 num_params; |
69 | u16 pad; | 69 | __le16 pad; |
70 | u32 report_1; | 70 | __le32 report_1; |
71 | u32 report_2; | 71 | __le32 report_2; |
72 | u32 report_3; | 72 | __le32 report_3; |
73 | } __attribute__ ((packed)); | 73 | } __attribute__ ((packed)); |
74 | 74 | ||
75 | #define NUM_OF_RSSI_SNR_TRIGGERS 8 | 75 | #define NUM_OF_RSSI_SNR_TRIGGERS 8 |
76 | 76 | ||
77 | struct event_mailbox { | 77 | struct event_mailbox { |
78 | u32 events_vector; | 78 | __le32 events_vector; |
79 | u32 events_mask; | 79 | __le32 events_mask; |
80 | u32 reserved_1; | 80 | __le32 reserved_1; |
81 | u32 reserved_2; | 81 | __le32 reserved_2; |
82 | 82 | ||
83 | u8 dbg_event_id; | 83 | u8 dbg_event_id; |
84 | u8 num_relevant_params; | 84 | u8 num_relevant_params; |
85 | u16 reserved_3; | 85 | __le16 reserved_3; |
86 | u32 event_report_p1; | 86 | __le32 event_report_p1; |
87 | u32 event_report_p2; | 87 | __le32 event_report_p2; |
88 | u32 event_report_p3; | 88 | __le32 event_report_p3; |
89 | 89 | ||
90 | u8 number_of_scan_results; | 90 | u8 number_of_scan_results; |
91 | u8 scan_tag; | 91 | u8 scan_tag; |
92 | u8 reserved_4[2]; | 92 | u8 reserved_4[2]; |
93 | u32 compl_scheduled_scan_status; | 93 | __le32 compl_scheduled_scan_status; |
94 | 94 | ||
95 | u16 scheduled_scan_attended_channels; | 95 | __le16 scheduled_scan_attended_channels; |
96 | u8 soft_gemini_sense_info; | 96 | u8 soft_gemini_sense_info; |
97 | u8 soft_gemini_protective_info; | 97 | u8 soft_gemini_protective_info; |
98 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; | 98 | s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; |
@@ -105,6 +105,6 @@ struct event_mailbox { | |||
105 | 105 | ||
106 | int wl1271_event_unmask(struct wl1271 *wl); | 106 | int wl1271_event_unmask(struct wl1271 *wl); |
107 | void wl1271_event_mbox_config(struct wl1271 *wl); | 107 | void wl1271_event_mbox_config(struct wl1271 *wl); |
108 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 108 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); |
109 | 109 | ||
110 | #endif | 110 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 490df217605a..417b4152feb1 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -59,6 +59,14 @@ static int wl1271_init_templates_config(struct wl1271 *wl) | |||
59 | if (ret < 0) | 59 | if (ret < 0) |
60 | return ret; | 60 | return ret; |
61 | 61 | ||
62 | if (wl1271_11a_enabled()) { | ||
63 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | ||
64 | NULL, | ||
65 | sizeof(struct wl12xx_probe_req_template)); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | } | ||
69 | |||
62 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 70 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
63 | sizeof(struct wl12xx_null_data_template)); | 71 | sizeof(struct wl12xx_null_data_template)); |
64 | if (ret < 0) | 72 | if (ret < 0) |
@@ -94,7 +102,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) | |||
94 | { | 102 | { |
95 | int ret; | 103 | int ret; |
96 | 104 | ||
97 | ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); | 105 | ret = wl1271_acx_rx_msdu_life_time(wl); |
98 | if (ret < 0) | 106 | if (ret < 0) |
99 | return ret; | 107 | return ret; |
100 | 108 | ||
@@ -117,7 +125,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl) | |||
117 | if (ret < 0) | 125 | if (ret < 0) |
118 | return ret; | 126 | return ret; |
119 | 127 | ||
120 | ret = wl1271_acx_group_address_tbl(wl); | 128 | ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); |
121 | if (ret < 0) | 129 | if (ret < 0) |
122 | return ret; | 130 | return ret; |
123 | 131 | ||
@@ -125,7 +133,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl) | |||
125 | if (ret < 0) | 133 | if (ret < 0) |
126 | return ret; | 134 | return ret; |
127 | 135 | ||
128 | ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); | 136 | ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold); |
129 | if (ret < 0) | 137 | if (ret < 0) |
130 | return ret; | 138 | return ret; |
131 | 139 | ||
@@ -136,7 +144,8 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl) | |||
136 | { | 144 | { |
137 | int ret; | 145 | int ret; |
138 | 146 | ||
139 | ret = wl1271_acx_beacon_filter_opt(wl); | 147 | /* disable beacon filtering at this stage */ |
148 | ret = wl1271_acx_beacon_filter_opt(wl, false); | ||
140 | if (ret < 0) | 149 | if (ret < 0) |
141 | return ret; | 150 | return ret; |
142 | 151 | ||
@@ -187,6 +196,7 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl) | |||
187 | static int wl1271_init_general_parms(struct wl1271 *wl) | 196 | static int wl1271_init_general_parms(struct wl1271 *wl) |
188 | { | 197 | { |
189 | struct wl1271_general_parms *gen_parms; | 198 | struct wl1271_general_parms *gen_parms; |
199 | struct conf_general_parms *g = &wl->conf.init.genparam; | ||
190 | int ret; | 200 | int ret; |
191 | 201 | ||
192 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); | 202 | gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); |
@@ -195,15 +205,14 @@ static int wl1271_init_general_parms(struct wl1271 *wl) | |||
195 | 205 | ||
196 | gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM; | 206 | gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM; |
197 | 207 | ||
198 | gen_parms->ref_clk = REF_CLK_38_4_E; | 208 | gen_parms->ref_clk = g->ref_clk; |
199 | /* FIXME: magic numbers */ | 209 | gen_parms->settling_time = g->settling_time; |
200 | gen_parms->settling_time = 5; | 210 | gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup; |
201 | gen_parms->clk_valid_on_wakeup = 0; | 211 | gen_parms->dc2dcmode = g->dc2dcmode; |
202 | gen_parms->dc2dcmode = 0; | 212 | gen_parms->single_dual_band = g->single_dual_band; |
203 | gen_parms->single_dual_band = 0; | 213 | gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect; |
204 | gen_parms->tx_bip_fem_autodetect = 1; | 214 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; |
205 | gen_parms->tx_bip_fem_manufacturer = 1; | 215 | gen_parms->settings = g->settings; |
206 | gen_parms->settings = 1; | ||
207 | 216 | ||
208 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 217 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
209 | if (ret < 0) { | 218 | if (ret < 0) { |
@@ -217,32 +226,9 @@ static int wl1271_init_general_parms(struct wl1271 *wl) | |||
217 | 226 | ||
218 | static int wl1271_init_radio_parms(struct wl1271 *wl) | 227 | static int wl1271_init_radio_parms(struct wl1271 *wl) |
219 | { | 228 | { |
220 | /* | ||
221 | * FIXME: All these magic numbers should be moved to some place where | ||
222 | * they can be configured (separate file?) | ||
223 | */ | ||
224 | |||
225 | struct wl1271_radio_parms *radio_parms; | 229 | struct wl1271_radio_parms *radio_parms; |
226 | int ret; | 230 | struct conf_radio_parms *r = &wl->conf.init.radioparam; |
227 | u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00, | 231 | int i, ret; |
228 | 0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 }; | ||
229 | |||
230 | u8 tx_rate_limits_normal[] = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }; | ||
231 | u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }; | ||
232 | |||
233 | u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50, | ||
234 | 0x50, 0x50, 0x50, 0x50, | ||
235 | 0x50, 0x50, 0x22, 0x50, | ||
236 | 0x22, 0x50 }; | ||
237 | |||
238 | u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50, | ||
239 | 0x50, 0x50, 0x50, 0x50, | ||
240 | 0x50, 0x50, 0x20, 0x50, | ||
241 | 0x20, 0x50 }; | ||
242 | |||
243 | u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
244 | |||
245 | u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }; | ||
246 | 232 | ||
247 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); | 233 | radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); |
248 | if (!radio_parms) | 234 | if (!radio_parms) |
@@ -251,33 +237,59 @@ static int wl1271_init_radio_parms(struct wl1271 *wl) | |||
251 | radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM; | 237 | radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM; |
252 | 238 | ||
253 | /* Static radio parameters */ | 239 | /* Static radio parameters */ |
254 | radio_parms->rx_trace_loss = 10; | 240 | radio_parms->rx_trace_loss = r->rx_trace_loss; |
255 | radio_parms->tx_trace_loss = 10; | 241 | radio_parms->tx_trace_loss = r->tx_trace_loss; |
256 | memcpy(radio_parms->rx_rssi_and_proc_compens, compensation, | 242 | memcpy(radio_parms->rx_rssi_and_proc_compens, |
257 | sizeof(compensation)); | 243 | r->rx_rssi_and_proc_compens, |
258 | 244 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | |
259 | /* We don't set the 5GHz -- N/A */ | 245 | |
246 | memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5, | ||
247 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
248 | memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5, | ||
249 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
250 | memcpy(radio_parms->rx_rssi_and_proc_compens_5, | ||
251 | r->rx_rssi_and_proc_compens_5, | ||
252 | CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE); | ||
260 | 253 | ||
261 | /* Dynamic radio parameters */ | 254 | /* Dynamic radio parameters */ |
262 | radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e); | 255 | radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage); |
263 | radio_parms->tx_ref_power = 0x78; | 256 | radio_parms->tx_ref_power = r->tx_ref_power; |
264 | radio_parms->tx_offset_db = 0x0; | 257 | radio_parms->tx_offset_db = r->tx_offset_db; |
265 | 258 | ||
266 | memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal, | 259 | memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal, |
267 | sizeof(tx_rate_limits_normal)); | 260 | CONF_NUMBER_OF_RATE_GROUPS); |
268 | memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded, | 261 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, |
269 | sizeof(tx_rate_limits_degraded)); | 262 | CONF_NUMBER_OF_RATE_GROUPS); |
270 | 263 | ||
271 | memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b, | 264 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, |
272 | sizeof(tx_channel_limits_11b)); | 265 | CONF_NUMBER_OF_CHANNELS_2_4); |
273 | memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm, | 266 | memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm, |
274 | sizeof(tx_channel_limits_ofdm)); | 267 | CONF_NUMBER_OF_CHANNELS_2_4); |
275 | memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets, | 268 | memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets, |
276 | sizeof(tx_pdv_rate_offsets)); | 269 | CONF_NUMBER_OF_RATE_GROUPS); |
277 | memcpy(radio_parms->tx_ibias, tx_ibias, | 270 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); |
278 | sizeof(tx_ibias)); | 271 | |
279 | 272 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | |
280 | radio_parms->rx_fem_insertion_loss = 0x14; | 273 | |
274 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | ||
275 | radio_parms->tx_ref_pd_voltage_5[i] = | ||
276 | cpu_to_le16(r->tx_ref_pd_voltage_5[i]); | ||
277 | memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5, | ||
278 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
279 | memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5, | ||
280 | CONF_NUMBER_OF_SUB_BANDS_5); | ||
281 | memcpy(radio_parms->tx_rate_limits_normal_5, | ||
282 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
283 | memcpy(radio_parms->tx_rate_limits_degraded_5, | ||
284 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
285 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | ||
286 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | ||
287 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | ||
288 | CONF_NUMBER_OF_RATE_GROUPS); | ||
289 | memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5, | ||
290 | CONF_NUMBER_OF_RATE_GROUPS); | ||
291 | memcpy(radio_parms->rx_fem_insertion_loss_5, | ||
292 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | ||
281 | 293 | ||
282 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); | 294 | ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); |
283 | if (ret < 0) | 295 | if (ret < 0) |
@@ -311,8 +323,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
311 | 323 | ||
312 | /* RX config */ | 324 | /* RX config */ |
313 | ret = wl1271_init_rx_config(wl, | 325 | ret = wl1271_init_rx_config(wl, |
314 | RX_CFG_PROMISCUOUS | RX_CFG_TSF, | 326 | RX_CFG_PROMISCUOUS | RX_CFG_TSF, |
315 | RX_FILTER_OPTION_DEF); | 327 | RX_FILTER_OPTION_DEF); |
316 | /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, | 328 | /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, |
317 | RX_FILTER_OPTION_FILTER_ALL); */ | 329 | RX_FILTER_OPTION_FILTER_ALL); */ |
318 | if (ret < 0) | 330 | if (ret < 0) |
@@ -323,6 +335,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
323 | if (ret < 0) | 335 | if (ret < 0) |
324 | goto out_free_memmap; | 336 | goto out_free_memmap; |
325 | 337 | ||
338 | /* Initialize connection monitoring thresholds */ | ||
339 | ret = wl1271_acx_conn_monit_params(wl); | ||
340 | if (ret < 0) | ||
341 | goto out_free_memmap; | ||
342 | |||
326 | /* Beacon filtering */ | 343 | /* Beacon filtering */ |
327 | ret = wl1271_init_beacon_filter(wl); | 344 | ret = wl1271_init_beacon_filter(wl); |
328 | if (ret < 0) | 345 | if (ret < 0) |
@@ -369,7 +386,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
369 | goto out_free_memmap; | 386 | goto out_free_memmap; |
370 | 387 | ||
371 | /* Configure TX rate classes */ | 388 | /* Configure TX rate classes */ |
372 | ret = wl1271_acx_rate_policies(wl); | 389 | ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); |
373 | if (ret < 0) | 390 | if (ret < 0) |
374 | goto out_free_memmap; | 391 | goto out_free_memmap; |
375 | 392 | ||
@@ -388,10 +405,16 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
388 | if (ret < 0) | 405 | if (ret < 0) |
389 | goto out_free_memmap; | 406 | goto out_free_memmap; |
390 | 407 | ||
408 | /* Configure smart reflex */ | ||
409 | ret = wl1271_acx_smart_reflex(wl); | ||
410 | if (ret < 0) | ||
411 | goto out_free_memmap; | ||
412 | |||
391 | return 0; | 413 | return 0; |
392 | 414 | ||
393 | out_free_memmap: | 415 | out_free_memmap: |
394 | kfree(wl->target_mem_map); | 416 | kfree(wl->target_mem_map); |
417 | wl->target_mem_map = NULL; | ||
395 | 418 | ||
396 | return ret; | 419 | return ret; |
397 | } | 420 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h index bd8ff0fa2272..6e21ceee76a6 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ b/drivers/net/wireless/wl12xx/wl1271_init.h | |||
@@ -48,19 +48,6 @@ struct wl1271_general_parms { | |||
48 | u8 settings; | 48 | u8 settings; |
49 | } __attribute__ ((packed)); | 49 | } __attribute__ ((packed)); |
50 | 50 | ||
51 | enum ref_clk_enum { | ||
52 | REF_CLK_19_2_E, | ||
53 | REF_CLK_26_E, | ||
54 | REF_CLK_38_4_E, | ||
55 | REF_CLK_52_E | ||
56 | }; | ||
57 | |||
58 | #define RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | ||
59 | #define NUMBER_OF_SUB_BANDS_5 7 | ||
60 | #define NUMBER_OF_RATE_GROUPS 6 | ||
61 | #define NUMBER_OF_CHANNELS_2_4 14 | ||
62 | #define NUMBER_OF_CHANNELS_5 35 | ||
63 | |||
64 | struct wl1271_radio_parms { | 51 | struct wl1271_radio_parms { |
65 | u8 id; | 52 | u8 id; |
66 | u8 padding[3]; | 53 | u8 padding[3]; |
@@ -69,45 +56,45 @@ struct wl1271_radio_parms { | |||
69 | /* 2.4GHz */ | 56 | /* 2.4GHz */ |
70 | u8 rx_trace_loss; | 57 | u8 rx_trace_loss; |
71 | u8 tx_trace_loss; | 58 | u8 tx_trace_loss; |
72 | s8 rx_rssi_and_proc_compens[RSSI_AND_PROCESS_COMPENSATION_SIZE]; | 59 | s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; |
73 | 60 | ||
74 | /* 5GHz */ | 61 | /* 5GHz */ |
75 | u8 rx_trace_loss_5[NUMBER_OF_SUB_BANDS_5]; | 62 | u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
76 | u8 tx_trace_loss_5[NUMBER_OF_SUB_BANDS_5]; | 63 | u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
77 | s8 rx_rssi_and_proc_compens_5[RSSI_AND_PROCESS_COMPENSATION_SIZE]; | 64 | s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE]; |
78 | 65 | ||
79 | /* Dynamic radio parameters */ | 66 | /* Dynamic radio parameters */ |
80 | /* 2.4GHz */ | 67 | /* 2.4GHz */ |
81 | s16 tx_ref_pd_voltage; | 68 | __le16 tx_ref_pd_voltage; |
82 | s8 tx_ref_power; | 69 | s8 tx_ref_power; |
83 | s8 tx_offset_db; | 70 | s8 tx_offset_db; |
84 | 71 | ||
85 | s8 tx_rate_limits_normal[NUMBER_OF_RATE_GROUPS]; | 72 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
86 | s8 tx_rate_limits_degraded[NUMBER_OF_RATE_GROUPS]; | 73 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
87 | 74 | ||
88 | s8 tx_channel_limits_11b[NUMBER_OF_CHANNELS_2_4]; | 75 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
89 | s8 tx_channel_limits_ofdm[NUMBER_OF_CHANNELS_2_4]; | 76 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
90 | s8 tx_pdv_rate_offsets[NUMBER_OF_RATE_GROUPS]; | 77 | s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS]; |
91 | 78 | ||
92 | u8 tx_ibias[NUMBER_OF_RATE_GROUPS]; | 79 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
93 | u8 rx_fem_insertion_loss; | 80 | u8 rx_fem_insertion_loss; |
94 | 81 | ||
95 | u8 padding2; | 82 | u8 padding2; |
96 | 83 | ||
97 | /* 5GHz */ | 84 | /* 5GHz */ |
98 | s16 tx_ref_pd_voltage_5[NUMBER_OF_SUB_BANDS_5]; | 85 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
99 | s8 tx_ref_power_5[NUMBER_OF_SUB_BANDS_5]; | 86 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
100 | s8 tx_offset_db_5[NUMBER_OF_SUB_BANDS_5]; | 87 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
101 | 88 | ||
102 | s8 tx_rate_limits_normal_5[NUMBER_OF_RATE_GROUPS]; | 89 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
103 | s8 tx_rate_limits_degraded_5[NUMBER_OF_RATE_GROUPS]; | 90 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
104 | 91 | ||
105 | s8 tx_channel_limits_ofdm_5[NUMBER_OF_CHANNELS_5]; | 92 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
106 | s8 tx_pdv_rate_offsets_5[NUMBER_OF_RATE_GROUPS]; | 93 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
107 | 94 | ||
108 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | 95 | /* FIXME: this is inconsistent with the types for 2.4GHz */ |
109 | s8 tx_ibias_5[NUMBER_OF_RATE_GROUPS]; | 96 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
110 | s8 rx_fem_insertion_loss_5[NUMBER_OF_SUB_BANDS_5]; | 97 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
111 | 98 | ||
112 | u8 padding3[2]; | 99 | u8 padding3[2]; |
113 | } __attribute__ ((packed)); | 100 | } __attribute__ ((packed)); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 27298b19d5bd..86132bb00787 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -30,7 +30,9 @@ | |||
30 | #include <linux/spi/spi.h> | 30 | #include <linux/spi/spi.h> |
31 | #include <linux/crc32.h> | 31 | #include <linux/crc32.h> |
32 | #include <linux/etherdevice.h> | 32 | #include <linux/etherdevice.h> |
33 | #include <linux/vmalloc.h> | ||
33 | #include <linux/spi/wl12xx.h> | 34 | #include <linux/spi/wl12xx.h> |
35 | #include <linux/inetdevice.h> | ||
34 | 36 | ||
35 | #include "wl1271.h" | 37 | #include "wl1271.h" |
36 | #include "wl12xx_80211.h" | 38 | #include "wl12xx_80211.h" |
@@ -45,6 +47,308 @@ | |||
45 | #include "wl1271_cmd.h" | 47 | #include "wl1271_cmd.h" |
46 | #include "wl1271_boot.h" | 48 | #include "wl1271_boot.h" |
47 | 49 | ||
50 | static struct conf_drv_settings default_conf = { | ||
51 | .sg = { | ||
52 | .per_threshold = 7500, | ||
53 | .max_scan_compensation_time = 120000, | ||
54 | .nfs_sample_interval = 400, | ||
55 | .load_ratio = 50, | ||
56 | .auto_ps_mode = 0, | ||
57 | .probe_req_compensation = 170, | ||
58 | .scan_window_compensation = 50, | ||
59 | .antenna_config = 0, | ||
60 | .beacon_miss_threshold = 60, | ||
61 | .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS, | ||
62 | .rate_adaptation_snr = 0 | ||
63 | }, | ||
64 | .rx = { | ||
65 | .rx_msdu_life_time = 512000, | ||
66 | .packet_detection_threshold = 0, | ||
67 | .ps_poll_timeout = 15, | ||
68 | .upsd_timeout = 15, | ||
69 | .rts_threshold = 2347, | ||
70 | .rx_cca_threshold = 0xFFEF, | ||
71 | .irq_blk_threshold = 0, | ||
72 | .irq_pkt_threshold = USHORT_MAX, | ||
73 | .irq_timeout = 5, | ||
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | ||
75 | }, | ||
76 | .tx = { | ||
77 | .tx_energy_detection = 0, | ||
78 | .rc_conf = { | ||
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | ||
80 | .short_retry_limit = 10, | ||
81 | .long_retry_limit = 10, | ||
82 | .aflags = 0 | ||
83 | }, | ||
84 | .ac_conf_count = 4, | ||
85 | .ac_conf = { | ||
86 | [0] = { | ||
87 | .ac = CONF_TX_AC_BE, | ||
88 | .cw_min = 15, | ||
89 | .cw_max = 63, | ||
90 | .aifsn = 3, | ||
91 | .tx_op_limit = 0, | ||
92 | }, | ||
93 | [1] = { | ||
94 | .ac = CONF_TX_AC_BK, | ||
95 | .cw_min = 15, | ||
96 | .cw_max = 63, | ||
97 | .aifsn = 7, | ||
98 | .tx_op_limit = 0, | ||
99 | }, | ||
100 | [2] = { | ||
101 | .ac = CONF_TX_AC_VI, | ||
102 | .cw_min = 15, | ||
103 | .cw_max = 63, | ||
104 | .aifsn = CONF_TX_AIFS_PIFS, | ||
105 | .tx_op_limit = 3008, | ||
106 | }, | ||
107 | [3] = { | ||
108 | .ac = CONF_TX_AC_VO, | ||
109 | .cw_min = 15, | ||
110 | .cw_max = 63, | ||
111 | .aifsn = CONF_TX_AIFS_PIFS, | ||
112 | .tx_op_limit = 1504, | ||
113 | }, | ||
114 | }, | ||
115 | .tid_conf_count = 7, | ||
116 | .tid_conf = { | ||
117 | [0] = { | ||
118 | .queue_id = 0, | ||
119 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
120 | .tsid = CONF_TX_AC_BE, | ||
121 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
122 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
123 | .apsd_conf = {0, 0}, | ||
124 | }, | ||
125 | [1] = { | ||
126 | .queue_id = 1, | ||
127 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
128 | .tsid = CONF_TX_AC_BE, | ||
129 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
130 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
131 | .apsd_conf = {0, 0}, | ||
132 | }, | ||
133 | [2] = { | ||
134 | .queue_id = 2, | ||
135 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
136 | .tsid = CONF_TX_AC_BE, | ||
137 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
138 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
139 | .apsd_conf = {0, 0}, | ||
140 | }, | ||
141 | [3] = { | ||
142 | .queue_id = 3, | ||
143 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
144 | .tsid = CONF_TX_AC_BE, | ||
145 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
146 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
147 | .apsd_conf = {0, 0}, | ||
148 | }, | ||
149 | [4] = { | ||
150 | .queue_id = 4, | ||
151 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
152 | .tsid = CONF_TX_AC_BE, | ||
153 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
154 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
155 | .apsd_conf = {0, 0}, | ||
156 | }, | ||
157 | [5] = { | ||
158 | .queue_id = 5, | ||
159 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
160 | .tsid = CONF_TX_AC_BE, | ||
161 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
162 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
163 | .apsd_conf = {0, 0}, | ||
164 | }, | ||
165 | [6] = { | ||
166 | .queue_id = 6, | ||
167 | .channel_type = CONF_CHANNEL_TYPE_DCF, | ||
168 | .tsid = CONF_TX_AC_BE, | ||
169 | .ps_scheme = CONF_PS_SCHEME_LEGACY, | ||
170 | .ack_policy = CONF_ACK_POLICY_LEGACY, | ||
171 | .apsd_conf = {0, 0}, | ||
172 | } | ||
173 | }, | ||
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | ||
175 | .tx_compl_timeout = 5, | ||
176 | .tx_compl_threshold = 5 | ||
177 | }, | ||
178 | .conn = { | ||
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | ||
180 | .listen_interval = 0, | ||
181 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | ||
182 | .bcn_filt_ie_count = 1, | ||
183 | .bcn_filt_ie = { | ||
184 | [0] = { | ||
185 | .ie = WLAN_EID_CHANNEL_SWITCH, | ||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | ||
187 | } | ||
188 | }, | ||
189 | .synch_fail_thold = 5, | ||
190 | .bss_lose_timeout = 100, | ||
191 | .beacon_rx_timeout = 10000, | ||
192 | .broadcast_timeout = 20000, | ||
193 | .rx_broadcast_in_ps = 1, | ||
194 | .ps_poll_threshold = 4, | ||
195 | .sig_trigger_count = 2, | ||
196 | .sig_trigger = { | ||
197 | [0] = { | ||
198 | .threshold = -75, | ||
199 | .pacing = 500, | ||
200 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
201 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
202 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
203 | .hysteresis = 2, | ||
204 | .index = 0, | ||
205 | .enable = 1 | ||
206 | }, | ||
207 | [1] = { | ||
208 | .threshold = -75, | ||
209 | .pacing = 500, | ||
210 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
211 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
212 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
213 | .hysteresis = 2, | ||
214 | .index = 1, | ||
215 | .enable = 1 | ||
216 | } | ||
217 | }, | ||
218 | .sig_weights = { | ||
219 | .rssi_bcn_avg_weight = 10, | ||
220 | .rssi_pkt_avg_weight = 10, | ||
221 | .snr_bcn_avg_weight = 10, | ||
222 | .snr_pkt_avg_weight = 10 | ||
223 | }, | ||
224 | .bet_enable = CONF_BET_MODE_ENABLE, | ||
225 | .bet_max_consecutive = 100 | ||
226 | }, | ||
227 | .init = { | ||
228 | .sr_err_tbl = { | ||
229 | [0] = { | ||
230 | .len = 7, | ||
231 | .upper_limit = 0x03, | ||
232 | .values = { | ||
233 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
234 | 0x00 } | ||
235 | }, | ||
236 | [1] = { | ||
237 | .len = 7, | ||
238 | .upper_limit = 0x03, | ||
239 | .values = { | ||
240 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
241 | 0x00 } | ||
242 | }, | ||
243 | [2] = { | ||
244 | .len = 7, | ||
245 | .upper_limit = 0x03, | ||
246 | .values = { | ||
247 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
248 | 0x00 } | ||
249 | } | ||
250 | }, | ||
251 | .sr_enable = 1, | ||
252 | .genparam = { | ||
253 | /* | ||
254 | * FIXME: The correct value CONF_REF_CLK_38_4_E | ||
255 | * causes the firmware to crash on boot. | ||
256 | * The value 5 apparently is an | ||
257 | * unnoficial XTAL configuration of the | ||
258 | * same frequency, which appears to work. | ||
259 | */ | ||
260 | .ref_clk = 5, | ||
261 | .settling_time = 5, | ||
262 | .clk_valid_on_wakeup = 0, | ||
263 | .dc2dcmode = 0, | ||
264 | .single_dual_band = CONF_SINGLE_BAND, | ||
265 | .tx_bip_fem_autodetect = 0, | ||
266 | .tx_bip_fem_manufacturer = 1, | ||
267 | .settings = 1, | ||
268 | }, | ||
269 | .radioparam = { | ||
270 | .rx_trace_loss = 10, | ||
271 | .tx_trace_loss = 10, | ||
272 | .rx_rssi_and_proc_compens = { | ||
273 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | ||
274 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | ||
275 | 0x00, 0x0a, 0x14 }, | ||
276 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
277 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | ||
278 | .rx_rssi_and_proc_compens_5 = { | ||
279 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
280 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
281 | 0x00, 0x00, 0x00 }, | ||
282 | .tx_ref_pd_voltage = 0x24e, | ||
283 | .tx_ref_power = 0x78, | ||
284 | .tx_offset_db = 0x0, | ||
285 | .tx_rate_limits_normal = { | ||
286 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | ||
287 | .tx_rate_limits_degraded = { | ||
288 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
289 | .tx_channel_limits_11b = { | ||
290 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
291 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | ||
292 | 0x22, 0x50 }, | ||
293 | .tx_channel_limits_ofdm = { | ||
294 | 0x20, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
295 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | ||
296 | 0x20, 0x50 }, | ||
297 | .tx_pdv_rate_offsets = { | ||
298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
299 | .tx_ibias = { | ||
300 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | ||
301 | .rx_fem_insertion_loss = 0x14, | ||
302 | .tx_ref_pd_voltage_5 = { | ||
303 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | ||
304 | 0x020a, 0x021c }, | ||
305 | .tx_ref_power_5 = { | ||
306 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, | ||
307 | .tx_offset_db_5 = { | ||
308 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
309 | .tx_rate_limits_normal_5 = { | ||
310 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
311 | .tx_rate_limits_degraded_5 = { | ||
312 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
313 | .tx_channel_limits_ofdm_5 = { | ||
314 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
315 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
316 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
317 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | ||
318 | 0x50, 0x50, 0x50 }, | ||
319 | .tx_pdv_rate_offsets_5 = { | ||
320 | 0x01, 0x02, 0x02, 0x02, 0x02, 0x00 }, | ||
321 | .tx_ibias_5 = { | ||
322 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | ||
323 | .rx_fem_insertion_loss_5 = { | ||
324 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | ||
325 | } | ||
326 | } | ||
327 | }; | ||
328 | |||
329 | static LIST_HEAD(wl_list); | ||
330 | |||
331 | static void wl1271_conf_init(struct wl1271 *wl) | ||
332 | { | ||
333 | |||
334 | /* | ||
335 | * This function applies the default configuration to the driver. This | ||
336 | * function is invoked upon driver load (spi probe.) | ||
337 | * | ||
338 | * The configuration is stored in a run-time structure in order to | ||
339 | * facilitate for run-time adjustment of any of the parameters. Making | ||
340 | * changes to the configuration structure will apply the new values on | ||
341 | * the next interface up (wl1271_op_start.) | ||
342 | */ | ||
343 | |||
344 | /* apply driver default configuration */ | ||
345 | memcpy(&wl->conf, &default_conf, sizeof(default_conf)); | ||
346 | |||
347 | if (wl1271_11a_enabled()) | ||
348 | wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND; | ||
349 | } | ||
350 | |||
351 | |||
48 | static int wl1271_plt_init(struct wl1271 *wl) | 352 | static int wl1271_plt_init(struct wl1271 *wl) |
49 | { | 353 | { |
50 | int ret; | 354 | int ret; |
@@ -75,20 +379,14 @@ static void wl1271_power_on(struct wl1271 *wl) | |||
75 | wl->set_power(true); | 379 | wl->set_power(true); |
76 | } | 380 | } |
77 | 381 | ||
78 | static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) | 382 | static void wl1271_fw_status(struct wl1271 *wl, |
383 | struct wl1271_fw_status *status) | ||
79 | { | 384 | { |
80 | u32 total = 0; | 385 | u32 total = 0; |
81 | int i; | 386 | int i; |
82 | 387 | ||
83 | /* | 388 | wl1271_spi_read(wl, FW_STATUS_ADDR, status, |
84 | * FIXME: Reading the FW status directly from the registers seems to | 389 | sizeof(*status), false); |
85 | * be the right thing to do, but it doesn't work. And in the | ||
86 | * reference driver, there is a workaround called | ||
87 | * USE_SDIO_24M_WORKAROUND, which reads the status from memory | ||
88 | * instead, so we do the same here. | ||
89 | */ | ||
90 | |||
91 | wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status)); | ||
92 | 390 | ||
93 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 391 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
94 | "drv_rx_counter = %d, tx_results_counter = %d)", | 392 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -99,25 +397,28 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
99 | 397 | ||
100 | /* update number of available TX blocks */ | 398 | /* update number of available TX blocks */ |
101 | for (i = 0; i < NUM_TX_QUEUES; i++) { | 399 | for (i = 0; i < NUM_TX_QUEUES; i++) { |
102 | u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i]; | 400 | u32 cnt = le32_to_cpu(status->tx_released_blks[i]) - |
103 | wl->tx_blocks_freed[i] = status->tx_released_blks[i]; | 401 | wl->tx_blocks_freed[i]; |
402 | |||
403 | wl->tx_blocks_freed[i] = | ||
404 | le32_to_cpu(status->tx_released_blks[i]); | ||
104 | wl->tx_blocks_available += cnt; | 405 | wl->tx_blocks_available += cnt; |
105 | total += cnt; | 406 | total += cnt; |
106 | } | 407 | } |
107 | 408 | ||
108 | /* if more blocks are available now, schedule some tx work */ | 409 | /* if more blocks are available now, schedule some tx work */ |
109 | if (total && !skb_queue_empty(&wl->tx_queue)) | 410 | if (total && !skb_queue_empty(&wl->tx_queue)) |
110 | schedule_work(&wl->tx_work); | 411 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
111 | 412 | ||
112 | /* update the host-chipset time offset */ | 413 | /* update the host-chipset time offset */ |
113 | wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime; | 414 | wl->time_offset = jiffies_to_usecs(jiffies) - |
415 | le32_to_cpu(status->fw_localtime); | ||
114 | } | 416 | } |
115 | 417 | ||
116 | #define WL1271_IRQ_MAX_LOOPS 10 | ||
117 | static void wl1271_irq_work(struct work_struct *work) | 418 | static void wl1271_irq_work(struct work_struct *work) |
118 | { | 419 | { |
119 | u32 intr, ctr = WL1271_IRQ_MAX_LOOPS; | ||
120 | int ret; | 420 | int ret; |
421 | u32 intr; | ||
121 | struct wl1271 *wl = | 422 | struct wl1271 *wl = |
122 | container_of(work, struct wl1271, irq_work); | 423 | container_of(work, struct wl1271, irq_work); |
123 | 424 | ||
@@ -132,9 +433,10 @@ static void wl1271_irq_work(struct work_struct *work) | |||
132 | if (ret < 0) | 433 | if (ret < 0) |
133 | goto out; | 434 | goto out; |
134 | 435 | ||
135 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 436 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
136 | 437 | ||
137 | intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | 438 | wl1271_fw_status(wl, wl->fw_status); |
439 | intr = le32_to_cpu(wl->fw_status->intr); | ||
138 | if (!intr) { | 440 | if (!intr) { |
139 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); | 441 | wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); |
140 | goto out_sleep; | 442 | goto out_sleep; |
@@ -142,46 +444,39 @@ static void wl1271_irq_work(struct work_struct *work) | |||
142 | 444 | ||
143 | intr &= WL1271_INTR_MASK; | 445 | intr &= WL1271_INTR_MASK; |
144 | 446 | ||
145 | do { | 447 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
146 | wl1271_fw_status(wl, wl->fw_status); | 448 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; |
147 | 449 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | |
148 | 450 | wl1271_event_handle(wl, 0, do_ack); | |
149 | if (intr & (WL1271_ACX_INTR_EVENT_A | | 451 | } |
150 | WL1271_ACX_INTR_EVENT_B)) { | ||
151 | wl1271_debug(DEBUG_IRQ, | ||
152 | "WL1271_ACX_INTR_EVENT (0x%x)", intr); | ||
153 | if (intr & WL1271_ACX_INTR_EVENT_A) | ||
154 | wl1271_event_handle(wl, 0); | ||
155 | else | ||
156 | wl1271_event_handle(wl, 1); | ||
157 | } | ||
158 | 452 | ||
159 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 453 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
160 | wl1271_debug(DEBUG_IRQ, | 454 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
161 | "WL1271_ACX_INTR_INIT_COMPLETE"); | 455 | wl1271_event_handle(wl, 1, true); |
456 | } | ||
162 | 457 | ||
163 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) | 458 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
164 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); | 459 | wl1271_debug(DEBUG_IRQ, |
460 | "WL1271_ACX_INTR_INIT_COMPLETE"); | ||
165 | 461 | ||
166 | if (intr & WL1271_ACX_INTR_DATA) { | 462 | if (intr & WL1271_ACX_INTR_HW_AVAILABLE) |
167 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | 463 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); |
168 | wl->tx_results_count; | ||
169 | 464 | ||
170 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 465 | if (intr & WL1271_ACX_INTR_DATA) { |
466 | u8 tx_res_cnt = wl->fw_status->tx_results_counter - | ||
467 | wl->tx_results_count; | ||
171 | 468 | ||
172 | /* check for tx results */ | 469 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
173 | if (tx_res_cnt) | ||
174 | wl1271_tx_complete(wl, tx_res_cnt); | ||
175 | 470 | ||
176 | wl1271_rx(wl, wl->fw_status); | 471 | /* check for tx results */ |
177 | } | 472 | if (tx_res_cnt) |
473 | wl1271_tx_complete(wl, tx_res_cnt); | ||
178 | 474 | ||
179 | intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | 475 | wl1271_rx(wl, wl->fw_status); |
180 | intr &= WL1271_INTR_MASK; | 476 | } |
181 | } while (intr && --ctr); | ||
182 | 477 | ||
183 | out_sleep: | 478 | out_sleep: |
184 | wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 479 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, |
185 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); | 480 | WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); |
186 | wl1271_ps_elp_sleep(wl); | 481 | wl1271_ps_elp_sleep(wl); |
187 | 482 | ||
@@ -205,7 +500,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
205 | wl->elp_compl = NULL; | 500 | wl->elp_compl = NULL; |
206 | } | 501 | } |
207 | 502 | ||
208 | schedule_work(&wl->irq_work); | 503 | ieee80211_queue_work(wl->hw, &wl->irq_work); |
209 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 504 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
210 | 505 | ||
211 | return IRQ_HANDLED; | 506 | return IRQ_HANDLED; |
@@ -231,7 +526,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
231 | } | 526 | } |
232 | 527 | ||
233 | wl->fw_len = fw->size; | 528 | wl->fw_len = fw->size; |
234 | wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); | 529 | wl->fw = vmalloc(wl->fw_len); |
235 | 530 | ||
236 | if (!wl->fw) { | 531 | if (!wl->fw) { |
237 | wl1271_error("could not allocate memory for the firmware"); | 532 | wl1271_error("could not allocate memory for the firmware"); |
@@ -292,7 +587,7 @@ static void wl1271_fw_wakeup(struct wl1271 *wl) | |||
292 | u32 elp_reg; | 587 | u32 elp_reg; |
293 | 588 | ||
294 | elp_reg = ELPCTRL_WAKE_UP; | 589 | elp_reg = ELPCTRL_WAKE_UP; |
295 | wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); | 590 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); |
296 | } | 591 | } |
297 | 592 | ||
298 | static int wl1271_setup(struct wl1271 *wl) | 593 | static int wl1271_setup(struct wl1271 *wl) |
@@ -314,6 +609,7 @@ static int wl1271_setup(struct wl1271 *wl) | |||
314 | 609 | ||
315 | static int wl1271_chip_wakeup(struct wl1271 *wl) | 610 | static int wl1271_chip_wakeup(struct wl1271 *wl) |
316 | { | 611 | { |
612 | struct wl1271_partition_set partition; | ||
317 | int ret = 0; | 613 | int ret = 0; |
318 | 614 | ||
319 | wl1271_power_on(wl); | 615 | wl1271_power_on(wl); |
@@ -323,11 +619,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
323 | 619 | ||
324 | /* We don't need a real memory partition here, because we only want | 620 | /* We don't need a real memory partition here, because we only want |
325 | * to use the registers at this point. */ | 621 | * to use the registers at this point. */ |
326 | wl1271_set_partition(wl, | 622 | memset(&partition, 0, sizeof(partition)); |
327 | 0x00000000, | 623 | partition.reg.start = REGISTERS_BASE; |
328 | 0x00000000, | 624 | partition.reg.size = REGISTERS_DOWN_SIZE; |
329 | REGISTERS_BASE, | 625 | wl1271_set_partition(wl, &partition); |
330 | REGISTERS_DOWN_SIZE); | ||
331 | 626 | ||
332 | /* ELP module wake up */ | 627 | /* ELP module wake up */ |
333 | wl1271_fw_wakeup(wl); | 628 | wl1271_fw_wakeup(wl); |
@@ -335,7 +630,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
335 | /* whal_FwCtrl_BootSm() */ | 630 | /* whal_FwCtrl_BootSm() */ |
336 | 631 | ||
337 | /* 0. read chip id from CHIP_ID */ | 632 | /* 0. read chip id from CHIP_ID */ |
338 | wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B); | 633 | wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B); |
339 | 634 | ||
340 | /* 1. check if chip id is valid */ | 635 | /* 1. check if chip id is valid */ |
341 | 636 | ||
@@ -346,7 +641,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
346 | 641 | ||
347 | ret = wl1271_setup(wl); | 642 | ret = wl1271_setup(wl); |
348 | if (ret < 0) | 643 | if (ret < 0) |
349 | goto out; | 644 | goto out_power_off; |
350 | break; | 645 | break; |
351 | case CHIP_ID_1271_PG20: | 646 | case CHIP_ID_1271_PG20: |
352 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 647 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -354,56 +649,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
354 | 649 | ||
355 | ret = wl1271_setup(wl); | 650 | ret = wl1271_setup(wl); |
356 | if (ret < 0) | 651 | if (ret < 0) |
357 | goto out; | 652 | goto out_power_off; |
358 | break; | 653 | break; |
359 | default: | 654 | default: |
360 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 655 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); |
361 | ret = -ENODEV; | 656 | ret = -ENODEV; |
362 | goto out; | 657 | goto out_power_off; |
363 | } | 658 | } |
364 | 659 | ||
365 | if (wl->fw == NULL) { | 660 | if (wl->fw == NULL) { |
366 | ret = wl1271_fetch_firmware(wl); | 661 | ret = wl1271_fetch_firmware(wl); |
367 | if (ret < 0) | 662 | if (ret < 0) |
368 | goto out; | 663 | goto out_power_off; |
369 | } | 664 | } |
370 | 665 | ||
371 | /* No NVS from netlink, try to get it from the filesystem */ | 666 | /* No NVS from netlink, try to get it from the filesystem */ |
372 | if (wl->nvs == NULL) { | 667 | if (wl->nvs == NULL) { |
373 | ret = wl1271_fetch_nvs(wl); | 668 | ret = wl1271_fetch_nvs(wl); |
374 | if (ret < 0) | 669 | if (ret < 0) |
375 | goto out; | 670 | goto out_power_off; |
376 | } | 671 | } |
377 | 672 | ||
378 | out: | 673 | goto out; |
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static void wl1271_filter_work(struct work_struct *work) | ||
383 | { | ||
384 | struct wl1271 *wl = | ||
385 | container_of(work, struct wl1271, filter_work); | ||
386 | int ret; | ||
387 | |||
388 | mutex_lock(&wl->mutex); | ||
389 | |||
390 | if (wl->state == WL1271_STATE_OFF) | ||
391 | goto out; | ||
392 | |||
393 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
394 | if (ret < 0) | ||
395 | goto out; | ||
396 | |||
397 | /* FIXME: replace the magic numbers with proper definitions */ | ||
398 | ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); | ||
399 | if (ret < 0) | ||
400 | goto out_sleep; | ||
401 | 674 | ||
402 | out_sleep: | 675 | out_power_off: |
403 | wl1271_ps_elp_sleep(wl); | 676 | wl1271_power_off(wl); |
404 | 677 | ||
405 | out: | 678 | out: |
406 | mutex_unlock(&wl->mutex); | 679 | return ret; |
407 | } | 680 | } |
408 | 681 | ||
409 | int wl1271_plt_start(struct wl1271 *wl) | 682 | int wl1271_plt_start(struct wl1271 *wl) |
@@ -429,13 +702,26 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
429 | 702 | ||
430 | ret = wl1271_boot(wl); | 703 | ret = wl1271_boot(wl); |
431 | if (ret < 0) | 704 | if (ret < 0) |
432 | goto out; | 705 | goto out_power_off; |
433 | 706 | ||
434 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | 707 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); |
435 | 708 | ||
436 | ret = wl1271_plt_init(wl); | 709 | ret = wl1271_plt_init(wl); |
437 | if (ret < 0) | 710 | if (ret < 0) |
438 | goto out; | 711 | goto out_irq_disable; |
712 | |||
713 | /* Make sure power saving is disabled */ | ||
714 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
715 | if (ret < 0) | ||
716 | goto out_irq_disable; | ||
717 | |||
718 | goto out; | ||
719 | |||
720 | out_irq_disable: | ||
721 | wl1271_disable_interrupts(wl); | ||
722 | |||
723 | out_power_off: | ||
724 | wl1271_power_off(wl); | ||
439 | 725 | ||
440 | out: | 726 | out: |
441 | mutex_unlock(&wl->mutex); | 727 | mutex_unlock(&wl->mutex); |
@@ -462,6 +748,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
462 | wl1271_power_off(wl); | 748 | wl1271_power_off(wl); |
463 | 749 | ||
464 | wl->state = WL1271_STATE_OFF; | 750 | wl->state = WL1271_STATE_OFF; |
751 | wl->rx_counter = 0; | ||
465 | 752 | ||
466 | out: | 753 | out: |
467 | mutex_unlock(&wl->mutex); | 754 | mutex_unlock(&wl->mutex); |
@@ -481,7 +768,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
481 | * before that, the tx_work will not be initialized! | 768 | * before that, the tx_work will not be initialized! |
482 | */ | 769 | */ |
483 | 770 | ||
484 | schedule_work(&wl->tx_work); | 771 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
485 | 772 | ||
486 | /* | 773 | /* |
487 | * The workqueue is slow to process the tx_queue and we need stop | 774 | * The workqueue is slow to process the tx_queue and we need stop |
@@ -501,6 +788,93 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
501 | return NETDEV_TX_OK; | 788 | return NETDEV_TX_OK; |
502 | } | 789 | } |
503 | 790 | ||
791 | static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | ||
792 | void *arg) | ||
793 | { | ||
794 | struct net_device *dev; | ||
795 | struct wireless_dev *wdev; | ||
796 | struct wiphy *wiphy; | ||
797 | struct ieee80211_hw *hw; | ||
798 | struct wl1271 *wl; | ||
799 | struct wl1271 *wl_temp; | ||
800 | struct in_device *idev; | ||
801 | struct in_ifaddr *ifa = arg; | ||
802 | int ret = 0; | ||
803 | |||
804 | /* FIXME: this ugly function should probably be implemented in the | ||
805 | * mac80211, and here should only be a simple callback handling actual | ||
806 | * setting of the filters. Now we need to dig up references to | ||
807 | * various structures to gain access to what we need. | ||
808 | * Also, because of this, there is no "initial" setting of the filter | ||
809 | * in "op_start", because we don't want to dig up struct net_device | ||
810 | * there - the filter will be set upon first change of the interface | ||
811 | * IP address. */ | ||
812 | |||
813 | dev = ifa->ifa_dev->dev; | ||
814 | |||
815 | wdev = dev->ieee80211_ptr; | ||
816 | if (wdev == NULL) | ||
817 | return -ENODEV; | ||
818 | |||
819 | wiphy = wdev->wiphy; | ||
820 | if (wiphy == NULL) | ||
821 | return -ENODEV; | ||
822 | |||
823 | hw = wiphy_priv(wiphy); | ||
824 | if (hw == NULL) | ||
825 | return -ENODEV; | ||
826 | |||
827 | /* Check that the interface is one supported by this driver. */ | ||
828 | wl_temp = hw->priv; | ||
829 | list_for_each_entry(wl, &wl_list, list) { | ||
830 | if (wl == wl_temp) | ||
831 | break; | ||
832 | } | ||
833 | if (wl == NULL) | ||
834 | return -ENODEV; | ||
835 | |||
836 | /* Get the interface IP address for the device. "ifa" will become | ||
837 | NULL if: | ||
838 | - there is no IPV4 protocol address configured | ||
839 | - there are multiple (virtual) IPV4 addresses configured | ||
840 | When "ifa" is NULL, filtering will be disabled. | ||
841 | */ | ||
842 | ifa = NULL; | ||
843 | idev = dev->ip_ptr; | ||
844 | if (idev) | ||
845 | ifa = idev->ifa_list; | ||
846 | |||
847 | if (ifa && ifa->ifa_next) | ||
848 | ifa = NULL; | ||
849 | |||
850 | mutex_lock(&wl->mutex); | ||
851 | |||
852 | if (wl->state == WL1271_STATE_OFF) | ||
853 | goto out; | ||
854 | |||
855 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
856 | if (ret < 0) | ||
857 | goto out; | ||
858 | if (ifa) | ||
859 | ret = wl1271_acx_arp_ip_filter(wl, true, | ||
860 | (u8 *)&ifa->ifa_address, | ||
861 | ACX_IPV4_VERSION); | ||
862 | else | ||
863 | ret = wl1271_acx_arp_ip_filter(wl, false, NULL, | ||
864 | ACX_IPV4_VERSION); | ||
865 | wl1271_ps_elp_sleep(wl); | ||
866 | |||
867 | out: | ||
868 | mutex_unlock(&wl->mutex); | ||
869 | |||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | static struct notifier_block wl1271_dev_notifier = { | ||
874 | .notifier_call = wl1271_dev_notify, | ||
875 | }; | ||
876 | |||
877 | |||
504 | static int wl1271_op_start(struct ieee80211_hw *hw) | 878 | static int wl1271_op_start(struct ieee80211_hw *hw) |
505 | { | 879 | { |
506 | struct wl1271 *wl = hw->priv; | 880 | struct wl1271 *wl = hw->priv; |
@@ -523,22 +897,32 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
523 | 897 | ||
524 | ret = wl1271_boot(wl); | 898 | ret = wl1271_boot(wl); |
525 | if (ret < 0) | 899 | if (ret < 0) |
526 | goto out; | 900 | goto out_power_off; |
527 | 901 | ||
528 | ret = wl1271_hw_init(wl); | 902 | ret = wl1271_hw_init(wl); |
529 | if (ret < 0) | 903 | if (ret < 0) |
530 | goto out; | 904 | goto out_irq_disable; |
531 | 905 | ||
532 | wl->state = WL1271_STATE_ON; | 906 | wl->state = WL1271_STATE_ON; |
533 | 907 | ||
534 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 908 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
535 | 909 | ||
536 | out: | 910 | goto out; |
537 | if (ret < 0) | 911 | |
538 | wl1271_power_off(wl); | 912 | out_irq_disable: |
913 | wl1271_disable_interrupts(wl); | ||
539 | 914 | ||
915 | out_power_off: | ||
916 | wl1271_power_off(wl); | ||
917 | |||
918 | out: | ||
540 | mutex_unlock(&wl->mutex); | 919 | mutex_unlock(&wl->mutex); |
541 | 920 | ||
921 | if (!ret) { | ||
922 | list_add(&wl->list, &wl_list); | ||
923 | register_inetaddr_notifier(&wl1271_dev_notifier); | ||
924 | } | ||
925 | |||
542 | return ret; | 926 | return ret; |
543 | } | 927 | } |
544 | 928 | ||
@@ -551,6 +935,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
551 | 935 | ||
552 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | 936 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); |
553 | 937 | ||
938 | unregister_inetaddr_notifier(&wl1271_dev_notifier); | ||
939 | list_del(&wl->list); | ||
940 | |||
554 | mutex_lock(&wl->mutex); | 941 | mutex_lock(&wl->mutex); |
555 | 942 | ||
556 | WARN_ON(wl->state != WL1271_STATE_ON); | 943 | WARN_ON(wl->state != WL1271_STATE_ON); |
@@ -570,7 +957,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
570 | 957 | ||
571 | cancel_work_sync(&wl->irq_work); | 958 | cancel_work_sync(&wl->irq_work); |
572 | cancel_work_sync(&wl->tx_work); | 959 | cancel_work_sync(&wl->tx_work); |
573 | cancel_work_sync(&wl->filter_work); | ||
574 | 960 | ||
575 | mutex_lock(&wl->mutex); | 961 | mutex_lock(&wl->mutex); |
576 | 962 | ||
@@ -581,8 +967,8 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
581 | memset(wl->bssid, 0, ETH_ALEN); | 967 | memset(wl->bssid, 0, ETH_ALEN); |
582 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 968 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
583 | wl->ssid_len = 0; | 969 | wl->ssid_len = 0; |
584 | wl->listen_int = 1; | ||
585 | wl->bss_type = MAX_BSS_TYPE; | 970 | wl->bss_type = MAX_BSS_TYPE; |
971 | wl->band = IEEE80211_BAND_2GHZ; | ||
586 | 972 | ||
587 | wl->rx_counter = 0; | 973 | wl->rx_counter = 0; |
588 | wl->elp = false; | 974 | wl->elp = false; |
@@ -592,8 +978,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
592 | wl->tx_blocks_available = 0; | 978 | wl->tx_blocks_available = 0; |
593 | wl->tx_results_count = 0; | 979 | wl->tx_results_count = 0; |
594 | wl->tx_packets_count = 0; | 980 | wl->tx_packets_count = 0; |
981 | wl->tx_security_last_seq = 0; | ||
982 | wl->tx_security_seq_16 = 0; | ||
983 | wl->tx_security_seq_32 = 0; | ||
595 | wl->time_offset = 0; | 984 | wl->time_offset = 0; |
596 | wl->session_counter = 0; | 985 | wl->session_counter = 0; |
986 | wl->joined = false; | ||
987 | |||
597 | for (i = 0; i < NUM_TX_QUEUES; i++) | 988 | for (i = 0; i < NUM_TX_QUEUES; i++) |
598 | wl->tx_blocks_freed[i] = 0; | 989 | wl->tx_blocks_freed[i] = 0; |
599 | 990 | ||
@@ -611,6 +1002,12 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
611 | conf->type, conf->mac_addr); | 1002 | conf->type, conf->mac_addr); |
612 | 1003 | ||
613 | mutex_lock(&wl->mutex); | 1004 | mutex_lock(&wl->mutex); |
1005 | if (wl->vif) { | ||
1006 | ret = -EBUSY; | ||
1007 | goto out; | ||
1008 | } | ||
1009 | |||
1010 | wl->vif = conf->vif; | ||
614 | 1011 | ||
615 | switch (conf->type) { | 1012 | switch (conf->type) { |
616 | case NL80211_IFTYPE_STATION: | 1013 | case NL80211_IFTYPE_STATION: |
@@ -634,7 +1031,12 @@ out: | |||
634 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1031 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
635 | struct ieee80211_if_init_conf *conf) | 1032 | struct ieee80211_if_init_conf *conf) |
636 | { | 1033 | { |
1034 | struct wl1271 *wl = hw->priv; | ||
1035 | |||
1036 | mutex_lock(&wl->mutex); | ||
637 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 1037 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
1038 | wl->vif = NULL; | ||
1039 | mutex_unlock(&wl->mutex); | ||
638 | } | 1040 | } |
639 | 1041 | ||
640 | #if 0 | 1042 | #if 0 |
@@ -657,7 +1059,15 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, | |||
657 | if (ret < 0) | 1059 | if (ret < 0) |
658 | goto out; | 1060 | goto out; |
659 | 1061 | ||
660 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | 1062 | if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) { |
1063 | wl1271_debug(DEBUG_MAC80211, "bssid changed"); | ||
1064 | |||
1065 | memcpy(wl->bssid, conf->bssid, ETH_ALEN); | ||
1066 | |||
1067 | ret = wl1271_cmd_join(wl); | ||
1068 | if (ret < 0) | ||
1069 | goto out_sleep; | ||
1070 | } | ||
661 | 1071 | ||
662 | ret = wl1271_cmd_build_null_data(wl); | 1072 | ret = wl1271_cmd_build_null_data(wl); |
663 | if (ret < 0) | 1073 | if (ret < 0) |
@@ -667,13 +1077,6 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, | |||
667 | if (wl->ssid_len) | 1077 | if (wl->ssid_len) |
668 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); | 1078 | memcpy(wl->ssid, conf->ssid, wl->ssid_len); |
669 | 1079 | ||
670 | if (wl->bss_type != BSS_TYPE_IBSS) { | ||
671 | /* FIXME: replace the magic numbers with proper definitions */ | ||
672 | ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1); | ||
673 | if (ret < 0) | ||
674 | goto out_sleep; | ||
675 | } | ||
676 | |||
677 | if (conf->changed & IEEE80211_IFCC_BEACON) { | 1080 | if (conf->changed & IEEE80211_IFCC_BEACON) { |
678 | beacon = ieee80211_beacon_get(hw, vif); | 1081 | beacon = ieee80211_beacon_get(hw, vif); |
679 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1082 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
@@ -691,12 +1094,6 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw, | |||
691 | 1094 | ||
692 | if (ret < 0) | 1095 | if (ret < 0) |
693 | goto out_sleep; | 1096 | goto out_sleep; |
694 | |||
695 | /* FIXME: replace the magic numbers with proper definitions */ | ||
696 | ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); | ||
697 | |||
698 | if (ret < 0) | ||
699 | goto out_sleep; | ||
700 | } | 1097 | } |
701 | 1098 | ||
702 | out_sleep: | 1099 | out_sleep: |
@@ -724,20 +1121,20 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
724 | 1121 | ||
725 | mutex_lock(&wl->mutex); | 1122 | mutex_lock(&wl->mutex); |
726 | 1123 | ||
1124 | wl->band = conf->channel->band; | ||
1125 | |||
727 | ret = wl1271_ps_elp_wakeup(wl, false); | 1126 | ret = wl1271_ps_elp_wakeup(wl, false); |
728 | if (ret < 0) | 1127 | if (ret < 0) |
729 | goto out; | 1128 | goto out; |
730 | 1129 | ||
731 | if (channel != wl->channel) { | 1130 | if (channel != wl->channel) { |
732 | u8 old_channel = wl->channel; | 1131 | /* |
1132 | * We assume that the stack will configure the right channel | ||
1133 | * before associating, so we don't need to send a join | ||
1134 | * command here. We will join the right channel when the | ||
1135 | * BSSID changes | ||
1136 | */ | ||
733 | wl->channel = channel; | 1137 | wl->channel = channel; |
734 | |||
735 | /* FIXME: use beacon interval provided by mac80211 */ | ||
736 | ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); | ||
737 | if (ret < 0) { | ||
738 | wl->channel = old_channel; | ||
739 | goto out_sleep; | ||
740 | } | ||
741 | } | 1138 | } |
742 | 1139 | ||
743 | ret = wl1271_cmd_build_null_data(wl); | 1140 | ret = wl1271_cmd_build_null_data(wl); |
@@ -782,6 +1179,45 @@ out: | |||
782 | return ret; | 1179 | return ret; |
783 | } | 1180 | } |
784 | 1181 | ||
1182 | struct wl1271_filter_params { | ||
1183 | bool enabled; | ||
1184 | int mc_list_length; | ||
1185 | u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN]; | ||
1186 | }; | ||
1187 | |||
1188 | static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, | ||
1189 | struct dev_addr_list *mc_list) | ||
1190 | { | ||
1191 | struct wl1271_filter_params *fp; | ||
1192 | int i; | ||
1193 | |||
1194 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | ||
1195 | if (!fp) { | ||
1196 | wl1271_error("Out of memory setting filters."); | ||
1197 | return 0; | ||
1198 | } | ||
1199 | |||
1200 | /* update multicast filtering parameters */ | ||
1201 | fp->enabled = true; | ||
1202 | if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) { | ||
1203 | mc_count = 0; | ||
1204 | fp->enabled = false; | ||
1205 | } | ||
1206 | |||
1207 | fp->mc_list_length = 0; | ||
1208 | for (i = 0; i < mc_count; i++) { | ||
1209 | if (mc_list->da_addrlen == ETH_ALEN) { | ||
1210 | memcpy(fp->mc_list[fp->mc_list_length], | ||
1211 | mc_list->da_addr, ETH_ALEN); | ||
1212 | fp->mc_list_length++; | ||
1213 | } else | ||
1214 | wl1271_warning("Unknown mc address length."); | ||
1215 | mc_list = mc_list->next; | ||
1216 | } | ||
1217 | |||
1218 | return (u64)(unsigned long)fp; | ||
1219 | } | ||
1220 | |||
785 | #define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ | 1221 | #define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ |
786 | FIF_ALLMULTI | \ | 1222 | FIF_ALLMULTI | \ |
787 | FIF_FCSFAIL | \ | 1223 | FIF_FCSFAIL | \ |
@@ -791,28 +1227,53 @@ out: | |||
791 | 1227 | ||
792 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | 1228 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, |
793 | unsigned int changed, | 1229 | unsigned int changed, |
794 | unsigned int *total,u64 multicast) | 1230 | unsigned int *total, u64 multicast) |
795 | { | 1231 | { |
1232 | struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; | ||
796 | struct wl1271 *wl = hw->priv; | 1233 | struct wl1271 *wl = hw->priv; |
1234 | int ret; | ||
797 | 1235 | ||
798 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter"); | 1236 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter"); |
799 | 1237 | ||
1238 | mutex_lock(&wl->mutex); | ||
1239 | |||
1240 | if (wl->state == WL1271_STATE_OFF) | ||
1241 | goto out; | ||
1242 | |||
1243 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
1244 | if (ret < 0) | ||
1245 | goto out; | ||
1246 | |||
800 | *total &= WL1271_SUPPORTED_FILTERS; | 1247 | *total &= WL1271_SUPPORTED_FILTERS; |
801 | changed &= WL1271_SUPPORTED_FILTERS; | 1248 | changed &= WL1271_SUPPORTED_FILTERS; |
802 | 1249 | ||
1250 | if (*total & FIF_ALLMULTI) | ||
1251 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | ||
1252 | else if (fp) | ||
1253 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, | ||
1254 | fp->mc_list, | ||
1255 | fp->mc_list_length); | ||
1256 | if (ret < 0) | ||
1257 | goto out_sleep; | ||
1258 | |||
1259 | kfree(fp); | ||
1260 | |||
1261 | /* FIXME: We still need to set our filters properly */ | ||
1262 | |||
1263 | /* determine, whether supported filter values have changed */ | ||
803 | if (changed == 0) | 1264 | if (changed == 0) |
804 | return; | 1265 | goto out_sleep; |
805 | 1266 | ||
806 | /* FIXME: wl->rx_config and wl->rx_filter are not protected */ | 1267 | /* apply configured filters */ |
807 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1268 | ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter); |
808 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 1269 | if (ret < 0) |
1270 | goto out_sleep; | ||
809 | 1271 | ||
810 | /* | 1272 | out_sleep: |
811 | * FIXME: workqueues need to be properly cancelled on stop(), for | 1273 | wl1271_ps_elp_sleep(wl); |
812 | * now let's just disable changing the filter settings. They will | 1274 | |
813 | * be updated any on config(). | 1275 | out: |
814 | */ | 1276 | mutex_unlock(&wl->mutex); |
815 | /* schedule_work(&wl->filter_work); */ | ||
816 | } | 1277 | } |
817 | 1278 | ||
818 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1279 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
@@ -823,6 +1284,8 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
823 | struct wl1271 *wl = hw->priv; | 1284 | struct wl1271 *wl = hw->priv; |
824 | const u8 *addr; | 1285 | const u8 *addr; |
825 | int ret; | 1286 | int ret; |
1287 | u32 tx_seq_32 = 0; | ||
1288 | u16 tx_seq_16 = 0; | ||
826 | u8 key_type; | 1289 | u8 key_type; |
827 | 1290 | ||
828 | static const u8 bcast_addr[ETH_ALEN] = | 1291 | static const u8 bcast_addr[ETH_ALEN] = |
@@ -861,11 +1324,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
861 | key_type = KEY_TKIP; | 1324 | key_type = KEY_TKIP; |
862 | 1325 | ||
863 | key_conf->hw_key_idx = key_conf->keyidx; | 1326 | key_conf->hw_key_idx = key_conf->keyidx; |
1327 | tx_seq_32 = wl->tx_security_seq_32; | ||
1328 | tx_seq_16 = wl->tx_security_seq_16; | ||
864 | break; | 1329 | break; |
865 | case ALG_CCMP: | 1330 | case ALG_CCMP: |
866 | key_type = KEY_AES; | 1331 | key_type = KEY_AES; |
867 | 1332 | ||
868 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1333 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1334 | tx_seq_32 = wl->tx_security_seq_32; | ||
1335 | tx_seq_16 = wl->tx_security_seq_16; | ||
869 | break; | 1336 | break; |
870 | default: | 1337 | default: |
871 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1338 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); |
@@ -879,7 +1346,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
879 | ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, | 1346 | ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, |
880 | key_conf->keyidx, key_type, | 1347 | key_conf->keyidx, key_type, |
881 | key_conf->keylen, key_conf->key, | 1348 | key_conf->keylen, key_conf->key, |
882 | addr); | 1349 | addr, tx_seq_32, tx_seq_16); |
883 | if (ret < 0) { | 1350 | if (ret < 0) { |
884 | wl1271_error("Could not add or replace key"); | 1351 | wl1271_error("Could not add or replace key"); |
885 | goto out_sleep; | 1352 | goto out_sleep; |
@@ -890,7 +1357,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
890 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | 1357 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, |
891 | key_conf->keyidx, key_type, | 1358 | key_conf->keyidx, key_type, |
892 | key_conf->keylen, key_conf->key, | 1359 | key_conf->keylen, key_conf->key, |
893 | addr); | 1360 | addr, 0, 0); |
894 | if (ret < 0) { | 1361 | if (ret < 0) { |
895 | wl1271_error("Could not remove key"); | 1362 | wl1271_error("Could not remove key"); |
896 | goto out_sleep; | 1363 | goto out_sleep; |
@@ -921,13 +1388,13 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
921 | struct wl1271 *wl = hw->priv; | 1388 | struct wl1271 *wl = hw->priv; |
922 | int ret; | 1389 | int ret; |
923 | u8 *ssid = NULL; | 1390 | u8 *ssid = NULL; |
924 | size_t ssid_len = 0; | 1391 | size_t len = 0; |
925 | 1392 | ||
926 | wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan"); | 1393 | wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan"); |
927 | 1394 | ||
928 | if (req->n_ssids) { | 1395 | if (req->n_ssids) { |
929 | ssid = req->ssids[0].ssid; | 1396 | ssid = req->ssids[0].ssid; |
930 | ssid_len = req->ssids[0].ssid_len; | 1397 | len = req->ssids[0].ssid_len; |
931 | } | 1398 | } |
932 | 1399 | ||
933 | mutex_lock(&wl->mutex); | 1400 | mutex_lock(&wl->mutex); |
@@ -936,7 +1403,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
936 | if (ret < 0) | 1403 | if (ret < 0) |
937 | goto out; | 1404 | goto out; |
938 | 1405 | ||
939 | ret = wl1271_cmd_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); | 1406 | if (wl1271_11a_enabled()) |
1407 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | ||
1408 | WL1271_SCAN_BAND_DUAL, 3); | ||
1409 | else | ||
1410 | ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0, | ||
1411 | WL1271_SCAN_BAND_2_4_GHZ, 3); | ||
940 | 1412 | ||
941 | wl1271_ps_elp_sleep(wl); | 1413 | wl1271_ps_elp_sleep(wl); |
942 | 1414 | ||
@@ -969,6 +1441,22 @@ out: | |||
969 | return ret; | 1441 | return ret; |
970 | } | 1442 | } |
971 | 1443 | ||
1444 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | ||
1445 | { | ||
1446 | struct ieee80211_supported_band *band; | ||
1447 | u32 enabled_rates = 0; | ||
1448 | int bit; | ||
1449 | |||
1450 | band = wl->hw->wiphy->bands[wl->band]; | ||
1451 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1452 | if (basic_rate_set & 0x1) | ||
1453 | enabled_rates |= band->bitrates[bit].hw_value; | ||
1454 | basic_rate_set >>= 1; | ||
1455 | } | ||
1456 | |||
1457 | return enabled_rates; | ||
1458 | } | ||
1459 | |||
972 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1460 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
973 | struct ieee80211_vif *vif, | 1461 | struct ieee80211_vif *vif, |
974 | struct ieee80211_bss_conf *bss_conf, | 1462 | struct ieee80211_bss_conf *bss_conf, |
@@ -990,6 +1478,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
990 | if (bss_conf->assoc) { | 1478 | if (bss_conf->assoc) { |
991 | wl->aid = bss_conf->aid; | 1479 | wl->aid = bss_conf->aid; |
992 | 1480 | ||
1481 | /* | ||
1482 | * with wl1271, we don't need to update the | ||
1483 | * beacon_int and dtim_period, because the firmware | ||
1484 | * updates it by itself when the first beacon is | ||
1485 | * received after a join. | ||
1486 | */ | ||
993 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); | 1487 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); |
994 | if (ret < 0) | 1488 | if (ret < 0) |
995 | goto out_sleep; | 1489 | goto out_sleep; |
@@ -1005,8 +1499,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1005 | if (ret < 0) | 1499 | if (ret < 0) |
1006 | goto out_sleep; | 1500 | goto out_sleep; |
1007 | } | 1501 | } |
1502 | } else { | ||
1503 | /* use defaults when not associated */ | ||
1504 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | ||
1505 | wl->aid = 0; | ||
1008 | } | 1506 | } |
1507 | |||
1009 | } | 1508 | } |
1509 | |||
1010 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1510 | if (changed & BSS_CHANGED_ERP_SLOT) { |
1011 | if (bss_conf->use_short_slot) | 1511 | if (bss_conf->use_short_slot) |
1012 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | 1512 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); |
@@ -1036,6 +1536,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1036 | } | 1536 | } |
1037 | } | 1537 | } |
1038 | 1538 | ||
1539 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1540 | wl->basic_rate_set = wl1271_enabled_rates_get( | ||
1541 | wl, bss_conf->basic_rates); | ||
1542 | |||
1543 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1544 | if (ret < 0) { | ||
1545 | wl1271_warning("Set rate policies failed %d", ret); | ||
1546 | goto out_sleep; | ||
1547 | } | ||
1548 | } | ||
1549 | |||
1039 | out_sleep: | 1550 | out_sleep: |
1040 | wl1271_ps_elp_sleep(wl); | 1551 | wl1271_ps_elp_sleep(wl); |
1041 | 1552 | ||
@@ -1047,44 +1558,44 @@ out: | |||
1047 | /* can't be const, mac80211 writes to this */ | 1558 | /* can't be const, mac80211 writes to this */ |
1048 | static struct ieee80211_rate wl1271_rates[] = { | 1559 | static struct ieee80211_rate wl1271_rates[] = { |
1049 | { .bitrate = 10, | 1560 | { .bitrate = 10, |
1050 | .hw_value = 0x1, | 1561 | .hw_value = CONF_HW_BIT_RATE_1MBPS, |
1051 | .hw_value_short = 0x1, }, | 1562 | .hw_value_short = CONF_HW_BIT_RATE_1MBPS, }, |
1052 | { .bitrate = 20, | 1563 | { .bitrate = 20, |
1053 | .hw_value = 0x2, | 1564 | .hw_value = CONF_HW_BIT_RATE_2MBPS, |
1054 | .hw_value_short = 0x2, | 1565 | .hw_value_short = CONF_HW_BIT_RATE_2MBPS, |
1055 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | 1566 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
1056 | { .bitrate = 55, | 1567 | { .bitrate = 55, |
1057 | .hw_value = 0x4, | 1568 | .hw_value = CONF_HW_BIT_RATE_5_5MBPS, |
1058 | .hw_value_short = 0x4, | 1569 | .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS, |
1059 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | 1570 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
1060 | { .bitrate = 110, | 1571 | { .bitrate = 110, |
1061 | .hw_value = 0x20, | 1572 | .hw_value = CONF_HW_BIT_RATE_11MBPS, |
1062 | .hw_value_short = 0x20, | 1573 | .hw_value_short = CONF_HW_BIT_RATE_11MBPS, |
1063 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | 1574 | .flags = IEEE80211_RATE_SHORT_PREAMBLE }, |
1064 | { .bitrate = 60, | 1575 | { .bitrate = 60, |
1065 | .hw_value = 0x8, | 1576 | .hw_value = CONF_HW_BIT_RATE_6MBPS, |
1066 | .hw_value_short = 0x8, }, | 1577 | .hw_value_short = CONF_HW_BIT_RATE_6MBPS, }, |
1067 | { .bitrate = 90, | 1578 | { .bitrate = 90, |
1068 | .hw_value = 0x10, | 1579 | .hw_value = CONF_HW_BIT_RATE_9MBPS, |
1069 | .hw_value_short = 0x10, }, | 1580 | .hw_value_short = CONF_HW_BIT_RATE_9MBPS, }, |
1070 | { .bitrate = 120, | 1581 | { .bitrate = 120, |
1071 | .hw_value = 0x40, | 1582 | .hw_value = CONF_HW_BIT_RATE_12MBPS, |
1072 | .hw_value_short = 0x40, }, | 1583 | .hw_value_short = CONF_HW_BIT_RATE_12MBPS, }, |
1073 | { .bitrate = 180, | 1584 | { .bitrate = 180, |
1074 | .hw_value = 0x80, | 1585 | .hw_value = CONF_HW_BIT_RATE_18MBPS, |
1075 | .hw_value_short = 0x80, }, | 1586 | .hw_value_short = CONF_HW_BIT_RATE_18MBPS, }, |
1076 | { .bitrate = 240, | 1587 | { .bitrate = 240, |
1077 | .hw_value = 0x200, | 1588 | .hw_value = CONF_HW_BIT_RATE_24MBPS, |
1078 | .hw_value_short = 0x200, }, | 1589 | .hw_value_short = CONF_HW_BIT_RATE_24MBPS, }, |
1079 | { .bitrate = 360, | 1590 | { .bitrate = 360, |
1080 | .hw_value = 0x400, | 1591 | .hw_value = CONF_HW_BIT_RATE_36MBPS, |
1081 | .hw_value_short = 0x400, }, | 1592 | .hw_value_short = CONF_HW_BIT_RATE_36MBPS, }, |
1082 | { .bitrate = 480, | 1593 | { .bitrate = 480, |
1083 | .hw_value = 0x800, | 1594 | .hw_value = CONF_HW_BIT_RATE_48MBPS, |
1084 | .hw_value_short = 0x800, }, | 1595 | .hw_value_short = CONF_HW_BIT_RATE_48MBPS, }, |
1085 | { .bitrate = 540, | 1596 | { .bitrate = 540, |
1086 | .hw_value = 0x1000, | 1597 | .hw_value = CONF_HW_BIT_RATE_54MBPS, |
1087 | .hw_value_short = 0x1000, }, | 1598 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, |
1088 | }; | 1599 | }; |
1089 | 1600 | ||
1090 | /* can't be const, mac80211 writes to this */ | 1601 | /* can't be const, mac80211 writes to this */ |
@@ -1112,6 +1623,88 @@ static struct ieee80211_supported_band wl1271_band_2ghz = { | |||
1112 | .n_bitrates = ARRAY_SIZE(wl1271_rates), | 1623 | .n_bitrates = ARRAY_SIZE(wl1271_rates), |
1113 | }; | 1624 | }; |
1114 | 1625 | ||
1626 | /* 5 GHz data rates for WL1273 */ | ||
1627 | static struct ieee80211_rate wl1271_rates_5ghz[] = { | ||
1628 | { .bitrate = 60, | ||
1629 | .hw_value = CONF_HW_BIT_RATE_6MBPS, | ||
1630 | .hw_value_short = CONF_HW_BIT_RATE_6MBPS, }, | ||
1631 | { .bitrate = 90, | ||
1632 | .hw_value = CONF_HW_BIT_RATE_9MBPS, | ||
1633 | .hw_value_short = CONF_HW_BIT_RATE_9MBPS, }, | ||
1634 | { .bitrate = 120, | ||
1635 | .hw_value = CONF_HW_BIT_RATE_12MBPS, | ||
1636 | .hw_value_short = CONF_HW_BIT_RATE_12MBPS, }, | ||
1637 | { .bitrate = 180, | ||
1638 | .hw_value = CONF_HW_BIT_RATE_18MBPS, | ||
1639 | .hw_value_short = CONF_HW_BIT_RATE_18MBPS, }, | ||
1640 | { .bitrate = 240, | ||
1641 | .hw_value = CONF_HW_BIT_RATE_24MBPS, | ||
1642 | .hw_value_short = CONF_HW_BIT_RATE_24MBPS, }, | ||
1643 | { .bitrate = 360, | ||
1644 | .hw_value = CONF_HW_BIT_RATE_36MBPS, | ||
1645 | .hw_value_short = CONF_HW_BIT_RATE_36MBPS, }, | ||
1646 | { .bitrate = 480, | ||
1647 | .hw_value = CONF_HW_BIT_RATE_48MBPS, | ||
1648 | .hw_value_short = CONF_HW_BIT_RATE_48MBPS, }, | ||
1649 | { .bitrate = 540, | ||
1650 | .hw_value = CONF_HW_BIT_RATE_54MBPS, | ||
1651 | .hw_value_short = CONF_HW_BIT_RATE_54MBPS, }, | ||
1652 | }; | ||
1653 | |||
1654 | /* 5 GHz band channels for WL1273 */ | ||
1655 | static struct ieee80211_channel wl1271_channels_5ghz[] = { | ||
1656 | { .hw_value = 183, .center_freq = 4915}, | ||
1657 | { .hw_value = 184, .center_freq = 4920}, | ||
1658 | { .hw_value = 185, .center_freq = 4925}, | ||
1659 | { .hw_value = 187, .center_freq = 4935}, | ||
1660 | { .hw_value = 188, .center_freq = 4940}, | ||
1661 | { .hw_value = 189, .center_freq = 4945}, | ||
1662 | { .hw_value = 192, .center_freq = 4960}, | ||
1663 | { .hw_value = 196, .center_freq = 4980}, | ||
1664 | { .hw_value = 7, .center_freq = 5035}, | ||
1665 | { .hw_value = 8, .center_freq = 5040}, | ||
1666 | { .hw_value = 9, .center_freq = 5045}, | ||
1667 | { .hw_value = 11, .center_freq = 5055}, | ||
1668 | { .hw_value = 12, .center_freq = 5060}, | ||
1669 | { .hw_value = 16, .center_freq = 5080}, | ||
1670 | { .hw_value = 34, .center_freq = 5170}, | ||
1671 | { .hw_value = 36, .center_freq = 5180}, | ||
1672 | { .hw_value = 38, .center_freq = 5190}, | ||
1673 | { .hw_value = 40, .center_freq = 5200}, | ||
1674 | { .hw_value = 42, .center_freq = 5210}, | ||
1675 | { .hw_value = 44, .center_freq = 5220}, | ||
1676 | { .hw_value = 46, .center_freq = 5230}, | ||
1677 | { .hw_value = 48, .center_freq = 5240}, | ||
1678 | { .hw_value = 52, .center_freq = 5260}, | ||
1679 | { .hw_value = 56, .center_freq = 5280}, | ||
1680 | { .hw_value = 60, .center_freq = 5300}, | ||
1681 | { .hw_value = 64, .center_freq = 5320}, | ||
1682 | { .hw_value = 100, .center_freq = 5500}, | ||
1683 | { .hw_value = 104, .center_freq = 5520}, | ||
1684 | { .hw_value = 108, .center_freq = 5540}, | ||
1685 | { .hw_value = 112, .center_freq = 5560}, | ||
1686 | { .hw_value = 116, .center_freq = 5580}, | ||
1687 | { .hw_value = 120, .center_freq = 5600}, | ||
1688 | { .hw_value = 124, .center_freq = 5620}, | ||
1689 | { .hw_value = 128, .center_freq = 5640}, | ||
1690 | { .hw_value = 132, .center_freq = 5660}, | ||
1691 | { .hw_value = 136, .center_freq = 5680}, | ||
1692 | { .hw_value = 140, .center_freq = 5700}, | ||
1693 | { .hw_value = 149, .center_freq = 5745}, | ||
1694 | { .hw_value = 153, .center_freq = 5765}, | ||
1695 | { .hw_value = 157, .center_freq = 5785}, | ||
1696 | { .hw_value = 161, .center_freq = 5805}, | ||
1697 | { .hw_value = 165, .center_freq = 5825}, | ||
1698 | }; | ||
1699 | |||
1700 | |||
1701 | static struct ieee80211_supported_band wl1271_band_5ghz = { | ||
1702 | .channels = wl1271_channels_5ghz, | ||
1703 | .n_channels = ARRAY_SIZE(wl1271_channels_5ghz), | ||
1704 | .bitrates = wl1271_rates_5ghz, | ||
1705 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | ||
1706 | }; | ||
1707 | |||
1115 | static const struct ieee80211_ops wl1271_ops = { | 1708 | static const struct ieee80211_ops wl1271_ops = { |
1116 | .start = wl1271_op_start, | 1709 | .start = wl1271_op_start, |
1117 | .stop = wl1271_op_stop, | 1710 | .stop = wl1271_op_stop, |
@@ -1119,6 +1712,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1119 | .remove_interface = wl1271_op_remove_interface, | 1712 | .remove_interface = wl1271_op_remove_interface, |
1120 | .config = wl1271_op_config, | 1713 | .config = wl1271_op_config, |
1121 | /* .config_interface = wl1271_op_config_interface, */ | 1714 | /* .config_interface = wl1271_op_config_interface, */ |
1715 | .prepare_multicast = wl1271_op_prepare_multicast, | ||
1122 | .configure_filter = wl1271_op_configure_filter, | 1716 | .configure_filter = wl1271_op_configure_filter, |
1123 | .tx = wl1271_op_tx, | 1717 | .tx = wl1271_op_tx, |
1124 | .set_key = wl1271_op_set_key, | 1718 | .set_key = wl1271_op_set_key, |
@@ -1151,24 +1745,25 @@ static int wl1271_register_hw(struct wl1271 *wl) | |||
1151 | 1745 | ||
1152 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 1746 | static int wl1271_init_ieee80211(struct wl1271 *wl) |
1153 | { | 1747 | { |
1154 | /* | 1748 | /* The tx descriptor buffer and the TKIP space. */ |
1155 | * The tx descriptor buffer and the TKIP space. | 1749 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + |
1156 | * | 1750 | sizeof(struct wl1271_tx_hw_descr); |
1157 | * FIXME: add correct 1271 descriptor size | ||
1158 | */ | ||
1159 | wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE; | ||
1160 | 1751 | ||
1161 | /* unit us */ | 1752 | /* unit us */ |
1162 | /* FIXME: find a proper value */ | 1753 | /* FIXME: find a proper value */ |
1163 | wl->hw->channel_change_time = 10000; | 1754 | wl->hw->channel_change_time = 10000; |
1164 | 1755 | ||
1165 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1756 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1166 | IEEE80211_HW_NOISE_DBM; | 1757 | IEEE80211_HW_NOISE_DBM | |
1758 | IEEE80211_HW_BEACON_FILTER; | ||
1167 | 1759 | ||
1168 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
1169 | wl->hw->wiphy->max_scan_ssids = 1; | 1761 | wl->hw->wiphy->max_scan_ssids = 1; |
1170 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1171 | 1763 | ||
1764 | if (wl1271_11a_enabled()) | ||
1765 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | ||
1766 | |||
1172 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); | 1767 | SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); |
1173 | 1768 | ||
1174 | return 0; | 1769 | return 0; |
@@ -1213,17 +1808,18 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1213 | wl = hw->priv; | 1808 | wl = hw->priv; |
1214 | memset(wl, 0, sizeof(*wl)); | 1809 | memset(wl, 0, sizeof(*wl)); |
1215 | 1810 | ||
1811 | INIT_LIST_HEAD(&wl->list); | ||
1812 | |||
1216 | wl->hw = hw; | 1813 | wl->hw = hw; |
1217 | dev_set_drvdata(&spi->dev, wl); | 1814 | dev_set_drvdata(&spi->dev, wl); |
1218 | wl->spi = spi; | 1815 | wl->spi = spi; |
1219 | 1816 | ||
1220 | skb_queue_head_init(&wl->tx_queue); | 1817 | skb_queue_head_init(&wl->tx_queue); |
1221 | 1818 | ||
1222 | INIT_WORK(&wl->filter_work, wl1271_filter_work); | 1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1223 | wl->channel = WL1271_DEFAULT_CHANNEL; | 1820 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1224 | wl->scanning = false; | 1821 | wl->scanning = false; |
1225 | wl->default_key = 0; | 1822 | wl->default_key = 0; |
1226 | wl->listen_int = 1; | ||
1227 | wl->rx_counter = 0; | 1823 | wl->rx_counter = 0; |
1228 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1229 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
@@ -1232,10 +1828,12 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1232 | wl->psm_requested = false; | 1828 | wl->psm_requested = false; |
1233 | wl->tx_queue_stopped = false; | 1829 | wl->tx_queue_stopped = false; |
1234 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1830 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1831 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | ||
1832 | wl->band = IEEE80211_BAND_2GHZ; | ||
1833 | wl->vif = NULL; | ||
1834 | wl->joined = false; | ||
1235 | 1835 | ||
1236 | /* We use the default power on sleep time until we know which chip | 1836 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1237 | * we're using */ | ||
1238 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | ||
1239 | wl->tx_frames[i] = NULL; | 1837 | wl->tx_frames[i] = NULL; |
1240 | 1838 | ||
1241 | spin_lock_init(&wl->wl_lock); | 1839 | spin_lock_init(&wl->wl_lock); |
@@ -1250,13 +1848,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1250 | wl->state = WL1271_STATE_OFF; | 1848 | wl->state = WL1271_STATE_OFF; |
1251 | mutex_init(&wl->mutex); | 1849 | mutex_init(&wl->mutex); |
1252 | 1850 | ||
1253 | wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); | ||
1254 | if (!wl->rx_descriptor) { | ||
1255 | wl1271_error("could not allocate memory for rx descriptor"); | ||
1256 | ret = -ENOMEM; | ||
1257 | goto out_free; | ||
1258 | } | ||
1259 | |||
1260 | /* This is the only SPI value that we need to set here, the rest | 1851 | /* This is the only SPI value that we need to set here, the rest |
1261 | * comes from the board-peripherals file */ | 1852 | * comes from the board-peripherals file */ |
1262 | spi->bits_per_word = 32; | 1853 | spi->bits_per_word = 32; |
@@ -1298,6 +1889,9 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1298 | } | 1889 | } |
1299 | dev_set_drvdata(&wl1271_device.dev, wl); | 1890 | dev_set_drvdata(&wl1271_device.dev, wl); |
1300 | 1891 | ||
1892 | /* Apply default driver configuration. */ | ||
1893 | wl1271_conf_init(wl); | ||
1894 | |||
1301 | ret = wl1271_init_ieee80211(wl); | 1895 | ret = wl1271_init_ieee80211(wl); |
1302 | if (ret) | 1896 | if (ret) |
1303 | goto out_platform; | 1897 | goto out_platform; |
@@ -1319,9 +1913,6 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1319 | free_irq(wl->irq, wl); | 1913 | free_irq(wl->irq, wl); |
1320 | 1914 | ||
1321 | out_free: | 1915 | out_free: |
1322 | kfree(wl->rx_descriptor); | ||
1323 | wl->rx_descriptor = NULL; | ||
1324 | |||
1325 | ieee80211_free_hw(hw); | 1916 | ieee80211_free_hw(hw); |
1326 | 1917 | ||
1327 | return ret; | 1918 | return ret; |
@@ -1337,14 +1928,11 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
1337 | platform_device_unregister(&wl1271_device); | 1928 | platform_device_unregister(&wl1271_device); |
1338 | free_irq(wl->irq, wl); | 1929 | free_irq(wl->irq, wl); |
1339 | kfree(wl->target_mem_map); | 1930 | kfree(wl->target_mem_map); |
1340 | kfree(wl->fw); | 1931 | vfree(wl->fw); |
1341 | wl->fw = NULL; | 1932 | wl->fw = NULL; |
1342 | kfree(wl->nvs); | 1933 | kfree(wl->nvs); |
1343 | wl->nvs = NULL; | 1934 | wl->nvs = NULL; |
1344 | 1935 | ||
1345 | kfree(wl->rx_descriptor); | ||
1346 | wl->rx_descriptor = NULL; | ||
1347 | |||
1348 | kfree(wl->fw_status); | 1936 | kfree(wl->fw_status); |
1349 | kfree(wl->tx_res_if); | 1937 | kfree(wl->tx_res_if); |
1350 | 1938 | ||
@@ -1391,3 +1979,4 @@ module_exit(wl1271_exit); | |||
1391 | 1979 | ||
1392 | MODULE_LICENSE("GPL"); | 1980 | MODULE_LICENSE("GPL"); |
1393 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 1981 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); |
1982 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 1dc74b0c7736..507cd91d7eed 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -27,25 +27,38 @@ | |||
27 | 27 | ||
28 | #define WL1271_WAKEUP_TIMEOUT 500 | 28 | #define WL1271_WAKEUP_TIMEOUT 500 |
29 | 29 | ||
30 | void wl1271_elp_work(struct work_struct *work) | ||
31 | { | ||
32 | struct delayed_work *dwork; | ||
33 | struct wl1271 *wl; | ||
34 | |||
35 | dwork = container_of(work, struct delayed_work, work); | ||
36 | wl = container_of(dwork, struct wl1271, elp_work); | ||
37 | |||
38 | wl1271_debug(DEBUG_PSM, "elp work"); | ||
39 | |||
40 | mutex_lock(&wl->mutex); | ||
41 | |||
42 | if (wl->elp || !wl->psm) | ||
43 | goto out; | ||
44 | |||
45 | wl1271_debug(DEBUG_PSM, "chip to elp"); | ||
46 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | ||
47 | wl->elp = true; | ||
48 | |||
49 | out: | ||
50 | mutex_unlock(&wl->mutex); | ||
51 | } | ||
52 | |||
53 | #define ELP_ENTRY_DELAY 5 | ||
54 | |||
30 | /* Routines to toggle sleep mode while in ELP */ | 55 | /* Routines to toggle sleep mode while in ELP */ |
31 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 56 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
32 | { | 57 | { |
33 | /* | 58 | if (wl->psm) { |
34 | * FIXME: due to a problem in the firmware (causing a firmware | 59 | cancel_delayed_work(&wl->elp_work); |
35 | * crash), ELP entry is prevented below. Remove the "true" to | 60 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
36 | * re-enable ELP entry. | 61 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
37 | */ | ||
38 | if (true || wl->elp || !wl->psm) | ||
39 | return; | ||
40 | |||
41 | /* | ||
42 | * Go to ELP unless there is work already pending - pending work | ||
43 | * will immediately wakeup the chipset anyway. | ||
44 | */ | ||
45 | if (!work_pending(&wl->irq_work) && !work_pending(&wl->tx_work)) { | ||
46 | wl1271_debug(DEBUG_PSM, "chip to elp"); | ||
47 | wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | ||
48 | wl->elp = true; | ||
49 | } | 62 | } |
50 | } | 63 | } |
51 | 64 | ||
@@ -73,7 +86,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
73 | wl->elp_compl = &compl; | 86 | wl->elp_compl = &compl; |
74 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 87 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
75 | 88 | ||
76 | wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); | 89 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); |
77 | 90 | ||
78 | if (!pending) { | 91 | if (!pending) { |
79 | ret = wait_for_completion_timeout( | 92 | ret = wait_for_completion_timeout( |
@@ -111,6 +124,17 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
111 | switch (mode) { | 124 | switch (mode) { |
112 | case STATION_POWER_SAVE_MODE: | 125 | case STATION_POWER_SAVE_MODE: |
113 | wl1271_debug(DEBUG_PSM, "entering psm"); | 126 | wl1271_debug(DEBUG_PSM, "entering psm"); |
127 | |||
128 | /* enable beacon filtering */ | ||
129 | ret = wl1271_acx_beacon_filter_opt(wl, true); | ||
130 | if (ret < 0) | ||
131 | return ret; | ||
132 | |||
133 | /* enable beacon early termination */ | ||
134 | ret = wl1271_acx_bet_enable(wl, true); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
114 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); | 138 | ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); |
115 | if (ret < 0) | 139 | if (ret < 0) |
116 | return ret; | 140 | return ret; |
@@ -128,6 +152,16 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
128 | if (ret < 0) | 152 | if (ret < 0) |
129 | return ret; | 153 | return ret; |
130 | 154 | ||
155 | /* disable beacon early termination */ | ||
156 | ret = wl1271_acx_bet_enable(wl, false); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | /* disable beacon filtering */ | ||
161 | ret = wl1271_acx_beacon_filter_opt(wl, false); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
131 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); | 165 | ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); |
132 | if (ret < 0) | 166 | if (ret < 0) |
133 | return ret; | 167 | return ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h index de2bd3c7dc9c..779653d0ae85 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ b/drivers/net/wireless/wl12xx/wl1271_ps.h | |||
@@ -30,6 +30,6 @@ | |||
30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); | 30 | int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); |
31 | void wl1271_ps_elp_sleep(struct wl1271 *wl); | 31 | void wl1271_ps_elp_sleep(struct wl1271 *wl); |
32 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); | 32 | int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); |
33 | 33 | void wl1271_elp_work(struct work_struct *work); | |
34 | 34 | ||
35 | #endif /* __WL1271_PS_H__ */ | 35 | #endif /* __WL1271_PS_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h index f8ed4a4fc691..1f237389d1c7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ b/drivers/net/wireless/wl12xx/wl1271_reg.h | |||
@@ -34,7 +34,7 @@ | |||
34 | #define REGISTERS_WORK_SIZE 0x0000b000 | 34 | #define REGISTERS_WORK_SIZE 0x0000b000 |
35 | 35 | ||
36 | #define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC | 36 | #define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC |
37 | #define STATUS_MEM_ADDRESS 0x40400 | 37 | #define FW_STATUS_ADDR (0x14FC0 + 0xA000) |
38 | 38 | ||
39 | /* ELP register commands */ | 39 | /* ELP register commands */ |
40 | #define ELPCTRL_WAKE_UP 0x1 | 40 | #define ELPCTRL_WAKE_UP 0x1 |
@@ -213,7 +213,6 @@ | |||
213 | ==============================================*/ | 213 | ==============================================*/ |
214 | #define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) | 214 | #define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) |
215 | 215 | ||
216 | #define RX_DRIVER_DUMMY_WRITE_ADDRESS (REGISTERS_BASE + 0x0534) | ||
217 | #define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538) | 216 | #define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538) |
218 | 217 | ||
219 | /* Device Configuration registers*/ | 218 | /* Device Configuration registers*/ |
@@ -614,50 +613,6 @@ enum { | |||
614 | MAX_RADIO_BANDS = 0xFF | 613 | MAX_RADIO_BANDS = 0xFF |
615 | }; | 614 | }; |
616 | 615 | ||
617 | enum { | ||
618 | NO_RATE = 0, | ||
619 | RATE_1MBPS = 0x0A, | ||
620 | RATE_2MBPS = 0x14, | ||
621 | RATE_5_5MBPS = 0x37, | ||
622 | RATE_6MBPS = 0x0B, | ||
623 | RATE_9MBPS = 0x0F, | ||
624 | RATE_11MBPS = 0x6E, | ||
625 | RATE_12MBPS = 0x0A, | ||
626 | RATE_18MBPS = 0x0E, | ||
627 | RATE_22MBPS = 0xDC, | ||
628 | RATE_24MBPS = 0x09, | ||
629 | RATE_36MBPS = 0x0D, | ||
630 | RATE_48MBPS = 0x08, | ||
631 | RATE_54MBPS = 0x0C | ||
632 | }; | ||
633 | |||
634 | enum { | ||
635 | RATE_INDEX_1MBPS = 0, | ||
636 | RATE_INDEX_2MBPS = 1, | ||
637 | RATE_INDEX_5_5MBPS = 2, | ||
638 | RATE_INDEX_6MBPS = 3, | ||
639 | RATE_INDEX_9MBPS = 4, | ||
640 | RATE_INDEX_11MBPS = 5, | ||
641 | RATE_INDEX_12MBPS = 6, | ||
642 | RATE_INDEX_18MBPS = 7, | ||
643 | RATE_INDEX_22MBPS = 8, | ||
644 | RATE_INDEX_24MBPS = 9, | ||
645 | RATE_INDEX_36MBPS = 10, | ||
646 | RATE_INDEX_48MBPS = 11, | ||
647 | RATE_INDEX_54MBPS = 12, | ||
648 | RATE_INDEX_MAX = RATE_INDEX_54MBPS, | ||
649 | MAX_RATE_INDEX, | ||
650 | INVALID_RATE_INDEX = MAX_RATE_INDEX, | ||
651 | RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF | ||
652 | }; | ||
653 | |||
654 | enum { | ||
655 | RATE_MASK_1MBPS = 0x1, | ||
656 | RATE_MASK_2MBPS = 0x2, | ||
657 | RATE_MASK_5_5MBPS = 0x4, | ||
658 | RATE_MASK_11MBPS = 0x20, | ||
659 | }; | ||
660 | |||
661 | #define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ | 616 | #define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ |
662 | #define OFDM_RATE_BIT BIT(6) | 617 | #define OFDM_RATE_BIT BIT(6) |
663 | #define PBCC_RATE_BIT BIT(7) | 618 | #define PBCC_RATE_BIT BIT(7) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index ad8b6904c5eb..37d81ab6acc0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -30,14 +30,15 @@ | |||
30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, | 30 | static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, |
31 | u32 drv_rx_counter) | 31 | u32 drv_rx_counter) |
32 | { | 32 | { |
33 | return status->rx_pkt_descs[drv_rx_counter] & RX_MEM_BLOCK_MASK; | 33 | return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & |
34 | RX_MEM_BLOCK_MASK; | ||
34 | } | 35 | } |
35 | 36 | ||
36 | static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | 37 | static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, |
37 | u32 drv_rx_counter) | 38 | u32 drv_rx_counter) |
38 | { | 39 | { |
39 | return (status->rx_pkt_descs[drv_rx_counter] & RX_BUF_SIZE_MASK) >> | 40 | return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) & |
40 | RX_BUF_SIZE_SHIFT_DIV; | 41 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; |
41 | } | 42 | } |
42 | 43 | ||
43 | /* The values of this table must match the wl1271_rates[] array */ | 44 | /* The values of this table must match the wl1271_rates[] array */ |
@@ -70,6 +71,36 @@ static u8 wl1271_rx_rate_to_idx[] = { | |||
70 | 0 /* WL1271_RATE_1 */ | 71 | 0 /* WL1271_RATE_1 */ |
71 | }; | 72 | }; |
72 | 73 | ||
74 | /* The values of this table must match the wl1271_rates[] array */ | ||
75 | static u8 wl1271_5_ghz_rx_rate_to_idx[] = { | ||
76 | /* MCS rates are used only with 11n */ | ||
77 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
78 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
79 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
80 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
81 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
82 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
83 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
84 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
85 | |||
86 | 7, /* WL1271_RATE_54 */ | ||
87 | 6, /* WL1271_RATE_48 */ | ||
88 | 5, /* WL1271_RATE_36 */ | ||
89 | 4, /* WL1271_RATE_24 */ | ||
90 | |||
91 | /* TI-specific rate */ | ||
92 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
93 | |||
94 | 3, /* WL1271_RATE_18 */ | ||
95 | 2, /* WL1271_RATE_12 */ | ||
96 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ | ||
97 | 1, /* WL1271_RATE_9 */ | ||
98 | 0, /* WL1271_RATE_6 */ | ||
99 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ | ||
100 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ | ||
101 | WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ | ||
102 | }; | ||
103 | |||
73 | static void wl1271_rx_status(struct wl1271 *wl, | 104 | static void wl1271_rx_status(struct wl1271 *wl, |
74 | struct wl1271_rx_descriptor *desc, | 105 | struct wl1271_rx_descriptor *desc, |
75 | struct ieee80211_rx_status *status, | 106 | struct ieee80211_rx_status *status, |
@@ -77,12 +108,21 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
77 | { | 108 | { |
78 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 109 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
79 | 110 | ||
80 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) | 111 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == |
112 | WL1271_RX_DESC_BAND_BG) { | ||
81 | status->band = IEEE80211_BAND_2GHZ; | 113 | status->band = IEEE80211_BAND_2GHZ; |
82 | else | 114 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; |
115 | } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | ||
116 | WL1271_RX_DESC_BAND_A) { | ||
117 | status->band = IEEE80211_BAND_5GHZ; | ||
118 | status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; | ||
119 | } else | ||
83 | wl1271_warning("unsupported band 0x%x", | 120 | wl1271_warning("unsupported band 0x%x", |
84 | desc->flags & WL1271_RX_DESC_BAND_MASK); | 121 | desc->flags & WL1271_RX_DESC_BAND_MASK); |
85 | 122 | ||
123 | if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) | ||
124 | wl1271_warning("unsupported rate"); | ||
125 | |||
86 | /* | 126 | /* |
87 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | 127 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the |
88 | * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we | 128 | * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we |
@@ -91,12 +131,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
91 | */ | 131 | */ |
92 | status->signal = desc->rssi; | 132 | status->signal = desc->rssi; |
93 | 133 | ||
94 | /* FIXME: Should this be optimized? */ | ||
95 | status->qual = (desc->rssi - WL1271_RX_MIN_RSSI) * 100 / | ||
96 | (WL1271_RX_MAX_RSSI - WL1271_RX_MIN_RSSI); | ||
97 | status->qual = min(status->qual, 100); | ||
98 | status->qual = max(status->qual, 0); | ||
99 | |||
100 | /* | 134 | /* |
101 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we | 135 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we |
102 | * need to divide by two for now, but TI has been discussing about | 136 | * need to divide by two for now, but TI has been discussing about |
@@ -109,17 +143,11 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
109 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 143 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
110 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 144 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; |
111 | 145 | ||
112 | if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL))) | 146 | if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL))) |
113 | status->flag |= RX_FLAG_DECRYPTED; | 147 | status->flag |= RX_FLAG_DECRYPTED; |
114 | 148 | if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL)) | |
115 | if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL)) | ||
116 | status->flag |= RX_FLAG_MMIC_ERROR; | 149 | status->flag |= RX_FLAG_MMIC_ERROR; |
117 | } | 150 | } |
118 | |||
119 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; | ||
120 | |||
121 | if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED) | ||
122 | wl1271_warning("unsupported rate"); | ||
123 | } | 151 | } |
124 | 152 | ||
125 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | 153 | static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) |
@@ -138,7 +166,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
138 | } | 166 | } |
139 | 167 | ||
140 | buf = skb_put(skb, length); | 168 | buf = skb_put(skb, length); |
141 | wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); | 169 | wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); |
142 | 170 | ||
143 | /* the data read starts with the descriptor */ | 171 | /* the data read starts with the descriptor */ |
144 | desc = (struct wl1271_rx_descriptor *) buf; | 172 | desc = (struct wl1271_rx_descriptor *) buf; |
@@ -156,7 +184,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
156 | beacon ? "beacon" : ""); | 184 | beacon ? "beacon" : ""); |
157 | 185 | ||
158 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 186 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
159 | ieee80211_rx(wl->hw, skb); | 187 | ieee80211_rx_ni(wl->hw, skb); |
160 | } | 188 | } |
161 | 189 | ||
162 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | 190 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) |
@@ -176,15 +204,15 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
176 | break; | 204 | break; |
177 | } | 205 | } |
178 | 206 | ||
179 | wl->rx_mem_pool_addr.addr = | 207 | wl->rx_mem_pool_addr.addr = (mem_block << 8) + |
180 | (mem_block << 8) + wl_mem_map->packet_memory_pool_start; | 208 | le32_to_cpu(wl_mem_map->packet_memory_pool_start); |
181 | wl->rx_mem_pool_addr.addr_extra = | 209 | wl->rx_mem_pool_addr.addr_extra = |
182 | wl->rx_mem_pool_addr.addr + 4; | 210 | wl->rx_mem_pool_addr.addr + 4; |
183 | 211 | ||
184 | /* Choose the block we want to read */ | 212 | /* Choose the block we want to read */ |
185 | wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA, | 213 | wl1271_spi_write(wl, WL1271_SLV_REG_DATA, |
186 | &wl->rx_mem_pool_addr, | 214 | &wl->rx_mem_pool_addr, |
187 | sizeof(wl->rx_mem_pool_addr), false); | 215 | sizeof(wl->rx_mem_pool_addr), false); |
188 | 216 | ||
189 | wl1271_rx_handle_data(wl, buf_size); | 217 | wl1271_rx_handle_data(wl, buf_size); |
190 | 218 | ||
@@ -192,9 +220,5 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) | |||
192 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; | 220 | drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; |
193 | } | 221 | } |
194 | 222 | ||
195 | wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); | 223 | wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); |
196 | |||
197 | /* This is a workaround for some problems in the chip */ | ||
198 | wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1); | ||
199 | |||
200 | } | 224 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index d1ca60e43a25..1ae6d1783ed4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h | |||
@@ -102,14 +102,14 @@ | |||
102 | #define RX_BUF_SIZE_SHIFT_DIV 6 | 102 | #define RX_BUF_SIZE_SHIFT_DIV 6 |
103 | 103 | ||
104 | struct wl1271_rx_descriptor { | 104 | struct wl1271_rx_descriptor { |
105 | u16 length; | 105 | __le16 length; |
106 | u8 status; | 106 | u8 status; |
107 | u8 flags; | 107 | u8 flags; |
108 | u8 rate; | 108 | u8 rate; |
109 | u8 channel; | 109 | u8 channel; |
110 | s8 rssi; | 110 | s8 rssi; |
111 | u8 snr; | 111 | u8 snr; |
112 | u32 timestamp; | 112 | __le32 timestamp; |
113 | u8 packet_class; | 113 | u8 packet_class; |
114 | u8 process_id; | 114 | u8 process_id; |
115 | u8 pad_len; | 115 | u8 pad_len; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 4a12880c16a8..02978a16e732 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -30,17 +30,29 @@ | |||
30 | #include "wl12xx_80211.h" | 30 | #include "wl12xx_80211.h" |
31 | #include "wl1271_spi.h" | 31 | #include "wl1271_spi.h" |
32 | 32 | ||
33 | static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr) | 33 | static int wl1271_translate_addr(struct wl1271 *wl, int addr) |
34 | { | 34 | { |
35 | return addr - wl->physical_reg_addr + wl->virtual_reg_addr; | 35 | /* |
36 | } | 36 | * To translate, first check to which window of addresses the |
37 | 37 | * particular address belongs. Then subtract the starting address | |
38 | static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr) | 38 | * of that window from the address. Then, add offset of the |
39 | { | 39 | * translated region. |
40 | return addr - wl->physical_mem_addr + wl->virtual_mem_addr; | 40 | * |
41 | * The translated regions occur next to each other in physical device | ||
42 | * memory, so just add the sizes of the preceeding address regions to | ||
43 | * get the offset to the new region. | ||
44 | * | ||
45 | * Currently, only the two first regions are addressed, and the | ||
46 | * assumption is that all addresses will fall into either of those | ||
47 | * two. | ||
48 | */ | ||
49 | if ((addr >= wl->part.reg.start) && | ||
50 | (addr < wl->part.reg.start + wl->part.reg.size)) | ||
51 | return addr - wl->part.reg.start + wl->part.mem.size; | ||
52 | else | ||
53 | return addr - wl->part.mem.start; | ||
41 | } | 54 | } |
42 | 55 | ||
43 | |||
44 | void wl1271_spi_reset(struct wl1271 *wl) | 56 | void wl1271_spi_reset(struct wl1271 *wl) |
45 | { | 57 | { |
46 | u8 *cmd; | 58 | u8 *cmd; |
@@ -123,133 +135,137 @@ void wl1271_spi_init(struct wl1271 *wl) | |||
123 | 135 | ||
124 | /* Set the SPI partitions to access the chip addresses | 136 | /* Set the SPI partitions to access the chip addresses |
125 | * | 137 | * |
126 | * There are two VIRTUAL (SPI) partitions (the memory partition and the | 138 | * To simplify driver code, a fixed (virtual) memory map is defined for |
127 | * registers partition), which are mapped to two different areas of the | 139 | * register and memory addresses. Because in the chipset, in different stages |
128 | * PHYSICAL (hardware) memory. This function also makes other checks to | 140 | * of operation, those addresses will move around, an address translation |
129 | * ensure that the partitions are not overlapping. In the diagram below, the | 141 | * mechanism is required. |
130 | * memory partition comes before the register partition, but the opposite is | ||
131 | * also supported. | ||
132 | * | 142 | * |
133 | * PHYSICAL address | 143 | * There are four partitions (three memory and one register partition), |
144 | * which are mapped to two different areas of the hardware memory. | ||
145 | * | ||
146 | * Virtual address | ||
134 | * space | 147 | * space |
135 | * | 148 | * |
136 | * | | | 149 | * | | |
137 | * ...+----+--> mem_start | 150 | * ...+----+--> mem.start |
138 | * VIRTUAL address ... | | | 151 | * Physical address ... | | |
139 | * space ... | | [PART_0] | 152 | * space ... | | [PART_0] |
140 | * ... | | | 153 | * ... | | |
141 | * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size | 154 | * 00000000 <--+----+... ...+----+--> mem.start + mem.size |
142 | * | | ... | | | 155 | * | | ... | | |
143 | * |MEM | ... | | | 156 | * |MEM | ... | | |
144 | * | | ... | | | 157 | * | | ... | | |
145 | * part_size <--+----+... | | {unused area) | 158 | * mem.size <--+----+... | | {unused area) |
146 | * | | ... | | | 159 | * | | ... | | |
147 | * |REG | ... | | | 160 | * |REG | ... | | |
148 | * part_size | | ... | | | 161 | * mem.size | | ... | | |
149 | * + <--+----+... ...+----+--> reg_start | 162 | * + <--+----+... ...+----+--> reg.start |
150 | * reg_size ... | | | 163 | * reg.size | | ... | | |
151 | * ... | | [PART_1] | 164 | * |MEM2| ... | | [PART_1] |
152 | * ... | | | 165 | * | | ... | | |
153 | * ...+----+--> reg_start + reg_size | 166 | * ...+----+--> reg.start + reg.size |
154 | * | | | 167 | * | | |
155 | * | 168 | * |
156 | */ | 169 | */ |
157 | int wl1271_set_partition(struct wl1271 *wl, | 170 | int wl1271_set_partition(struct wl1271 *wl, |
158 | u32 mem_start, u32 mem_size, | 171 | struct wl1271_partition_set *p) |
159 | u32 reg_start, u32 reg_size) | ||
160 | { | 172 | { |
161 | struct wl1271_partition *partition; | 173 | /* copy partition info */ |
162 | struct spi_transfer t; | 174 | memcpy(&wl->part, p, sizeof(*p)); |
163 | struct spi_message m; | ||
164 | size_t len, cmd_len; | ||
165 | u32 *cmd; | ||
166 | int addr; | ||
167 | |||
168 | cmd_len = sizeof(u32) + 2 * sizeof(struct wl1271_partition); | ||
169 | cmd = kzalloc(cmd_len, GFP_KERNEL); | ||
170 | if (!cmd) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | spi_message_init(&m); | ||
174 | memset(&t, 0, sizeof(t)); | ||
175 | |||
176 | partition = (struct wl1271_partition *) (cmd + 1); | ||
177 | addr = HW_ACCESS_PART0_SIZE_ADDR; | ||
178 | len = 2 * sizeof(struct wl1271_partition); | ||
179 | |||
180 | *cmd |= WSPI_CMD_WRITE; | ||
181 | *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; | ||
182 | *cmd |= addr & WSPI_CMD_BYTE_ADDR; | ||
183 | 175 | ||
184 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | 176 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", |
185 | mem_start, mem_size); | 177 | p->mem.start, p->mem.size); |
186 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | 178 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", |
187 | reg_start, reg_size); | 179 | p->reg.start, p->reg.size); |
188 | 180 | wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X", | |
189 | /* Make sure that the two partitions together don't exceed the | 181 | p->mem2.start, p->mem2.size); |
190 | * address range */ | 182 | wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X", |
191 | if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { | 183 | p->mem3.start, p->mem3.size); |
192 | wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual" | 184 | |
193 | " address range. Truncating partition[0]."); | 185 | /* write partition info to the chipset */ |
194 | mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; | 186 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); |
195 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | 187 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); |
196 | mem_start, mem_size); | 188 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); |
197 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | 189 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); |
198 | reg_start, reg_size); | 190 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); |
199 | } | 191 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); |
192 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | ||
200 | 193 | ||
201 | if ((mem_start < reg_start) && | 194 | return 0; |
202 | ((mem_start + mem_size) > reg_start)) { | 195 | } |
203 | /* Guarantee that the memory partition doesn't overlap the | ||
204 | * registers partition */ | ||
205 | wl1271_debug(DEBUG_SPI, "End of partition[0] is " | ||
206 | "overlapping partition[1]. Adjusted."); | ||
207 | mem_size = reg_start - mem_start; | ||
208 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
209 | mem_start, mem_size); | ||
210 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
211 | reg_start, reg_size); | ||
212 | } else if ((reg_start < mem_start) && | ||
213 | ((reg_start + reg_size) > mem_start)) { | ||
214 | /* Guarantee that the register partition doesn't overlap the | ||
215 | * memory partition */ | ||
216 | wl1271_debug(DEBUG_SPI, "End of partition[1] is" | ||
217 | " overlapping partition[0]. Adjusted."); | ||
218 | reg_size = mem_start - reg_start; | ||
219 | wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", | ||
220 | mem_start, mem_size); | ||
221 | wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", | ||
222 | reg_start, reg_size); | ||
223 | } | ||
224 | 196 | ||
225 | partition[0].start = mem_start; | 197 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
226 | partition[0].size = mem_size; | ||
227 | partition[1].start = reg_start; | ||
228 | partition[1].size = reg_size; | ||
229 | 198 | ||
230 | wl->physical_mem_addr = mem_start; | 199 | /* FIXME: Check busy words, removed due to SPI bug */ |
231 | wl->physical_reg_addr = reg_start; | 200 | #if 0 |
201 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
202 | { | ||
203 | struct spi_transfer t[1]; | ||
204 | struct spi_message m; | ||
205 | u32 *busy_buf; | ||
206 | int num_busy_bytes = 0; | ||
232 | 207 | ||
233 | wl->virtual_mem_addr = 0; | 208 | wl1271_info("spi read BUSY!"); |
234 | wl->virtual_reg_addr = mem_size; | ||
235 | 209 | ||
236 | t.tx_buf = cmd; | 210 | /* |
237 | t.len = cmd_len; | 211 | * Look for the non-busy word in the read buffer, and if found, |
238 | spi_message_add_tail(&t, &m); | 212 | * read in the remaining data into the buffer. |
213 | */ | ||
214 | busy_buf = (u32 *)buf; | ||
215 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
216 | num_busy_bytes += sizeof(u32); | ||
217 | if (*busy_buf & 0x1) { | ||
218 | spi_message_init(&m); | ||
219 | memset(t, 0, sizeof(t)); | ||
220 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
221 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
222 | t[0].len = num_busy_bytes; | ||
223 | spi_message_add_tail(&t[0], &m); | ||
224 | spi_sync(wl->spi, &m); | ||
225 | return; | ||
226 | } | ||
227 | } | ||
239 | 228 | ||
240 | spi_sync(wl->spi, &m); | 229 | /* |
230 | * Read further busy words from SPI until a non-busy word is | ||
231 | * encountered, then read the data itself into the buffer. | ||
232 | */ | ||
233 | wl1271_info("spi read BUSY-polling needed!"); | ||
241 | 234 | ||
242 | kfree(cmd); | 235 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
236 | busy_buf = wl->buffer_busyword; | ||
237 | while (num_busy_bytes) { | ||
238 | num_busy_bytes--; | ||
239 | spi_message_init(&m); | ||
240 | memset(t, 0, sizeof(t)); | ||
241 | t[0].rx_buf = busy_buf; | ||
242 | t[0].len = sizeof(u32); | ||
243 | spi_message_add_tail(&t[0], &m); | ||
244 | spi_sync(wl->spi, &m); | ||
245 | |||
246 | if (*busy_buf & 0x1) { | ||
247 | spi_message_init(&m); | ||
248 | memset(t, 0, sizeof(t)); | ||
249 | t[0].rx_buf = buf; | ||
250 | t[0].len = len; | ||
251 | spi_message_add_tail(&t[0], &m); | ||
252 | spi_sync(wl->spi, &m); | ||
253 | return; | ||
254 | } | ||
255 | } | ||
243 | 256 | ||
244 | return 0; | 257 | /* The SPI bus is unresponsive, the read failed. */ |
258 | memset(buf, 0, len); | ||
259 | wl1271_error("SPI read busy-word timeout!\n"); | ||
245 | } | 260 | } |
261 | #endif | ||
246 | 262 | ||
247 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | 263 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
248 | size_t len, bool fixed) | 264 | size_t len, bool fixed) |
249 | { | 265 | { |
250 | struct spi_transfer t[3]; | 266 | struct spi_transfer t[3]; |
251 | struct spi_message m; | 267 | struct spi_message m; |
252 | u8 *busy_buf; | 268 | u32 *busy_buf; |
253 | u32 *cmd; | 269 | u32 *cmd; |
254 | 270 | ||
255 | cmd = &wl->buffer_cmd; | 271 | cmd = &wl->buffer_cmd; |
@@ -281,14 +297,16 @@ void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | |||
281 | 297 | ||
282 | spi_sync(wl->spi, &m); | 298 | spi_sync(wl->spi, &m); |
283 | 299 | ||
284 | /* FIXME: check busy words */ | 300 | /* FIXME: Check busy words, removed due to SPI bug */ |
301 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | ||
302 | wl1271_spi_read_busy(wl, buf, len); */ | ||
285 | 303 | ||
286 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 304 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
287 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 305 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
288 | } | 306 | } |
289 | 307 | ||
290 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, | 308 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
291 | size_t len, bool fixed) | 309 | size_t len, bool fixed) |
292 | { | 310 | { |
293 | struct spi_transfer t[2]; | 311 | struct spi_transfer t[2]; |
294 | struct spi_message m; | 312 | struct spi_message m; |
@@ -321,62 +339,77 @@ void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, | |||
321 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); | 339 | wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); |
322 | } | 340 | } |
323 | 341 | ||
324 | void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, | 342 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, |
325 | size_t len) | 343 | bool fixed) |
326 | { | 344 | { |
327 | int physical; | 345 | int physical; |
328 | 346 | ||
329 | physical = wl1271_translate_mem_addr(wl, addr); | 347 | physical = wl1271_translate_addr(wl, addr); |
330 | 348 | ||
331 | wl1271_spi_read(wl, physical, buf, len, false); | 349 | wl1271_spi_raw_read(wl, physical, buf, len, fixed); |
332 | } | 350 | } |
333 | 351 | ||
334 | void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, | 352 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, |
335 | size_t len) | 353 | bool fixed) |
336 | { | 354 | { |
337 | int physical; | 355 | int physical; |
338 | 356 | ||
339 | physical = wl1271_translate_mem_addr(wl, addr); | 357 | physical = wl1271_translate_addr(wl, addr); |
340 | 358 | ||
341 | wl1271_spi_write(wl, physical, buf, len, false); | 359 | wl1271_spi_raw_write(wl, physical, buf, len, fixed); |
342 | } | 360 | } |
343 | 361 | ||
344 | void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len, | 362 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr) |
345 | bool fixed) | ||
346 | { | 363 | { |
347 | int physical; | 364 | return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); |
348 | 365 | } | |
349 | physical = wl1271_translate_reg_addr(wl, addr); | ||
350 | 366 | ||
351 | wl1271_spi_read(wl, physical, buf, len, fixed); | 367 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val) |
368 | { | ||
369 | wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val); | ||
352 | } | 370 | } |
353 | 371 | ||
354 | void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len, | 372 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
355 | bool fixed) | ||
356 | { | 373 | { |
357 | int physical; | 374 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
375 | addr = (addr >> 1) + 0x30000; | ||
376 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); | ||
358 | 377 | ||
359 | physical = wl1271_translate_reg_addr(wl, addr); | 378 | /* write value to OCP_POR_WDATA */ |
379 | wl1271_spi_write32(wl, OCP_DATA_WRITE, val); | ||
360 | 380 | ||
361 | wl1271_spi_write(wl, physical, buf, len, fixed); | 381 | /* write 1 to OCP_CMD */ |
382 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE); | ||
362 | } | 383 | } |
363 | 384 | ||
364 | u32 wl1271_mem_read32(struct wl1271 *wl, int addr) | 385 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr) |
365 | { | 386 | { |
366 | return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr)); | 387 | u32 val; |
367 | } | 388 | int timeout = OCP_CMD_LOOP; |
368 | 389 | ||
369 | void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val) | 390 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
370 | { | 391 | addr = (addr >> 1) + 0x30000; |
371 | wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val); | 392 | wl1271_spi_write32(wl, OCP_POR_CTR, addr); |
372 | } | ||
373 | 393 | ||
374 | u32 wl1271_reg_read32(struct wl1271 *wl, int addr) | 394 | /* write 2 to OCP_CMD */ |
375 | { | 395 | wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ); |
376 | return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr)); | ||
377 | } | ||
378 | 396 | ||
379 | void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val) | 397 | /* poll for data ready */ |
380 | { | 398 | do { |
381 | wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val); | 399 | val = wl1271_spi_read32(wl, OCP_DATA_READ); |
400 | timeout--; | ||
401 | } while (!(val & OCP_READY_MASK) && timeout); | ||
402 | |||
403 | if (!timeout) { | ||
404 | wl1271_warning("Top register access timed out."); | ||
405 | return 0xffff; | ||
406 | } | ||
407 | |||
408 | /* check data status and return if OK */ | ||
409 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | ||
410 | return val & 0xffff; | ||
411 | else { | ||
412 | wl1271_warning("Top register access returned error."); | ||
413 | return 0xffff; | ||
414 | } | ||
382 | } | 415 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h index 2c9968458646..cb7df1c56314 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ b/drivers/net/wireless/wl12xx/wl1271_spi.h | |||
@@ -29,10 +29,14 @@ | |||
29 | 29 | ||
30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 | 30 | #define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 |
31 | 31 | ||
32 | #define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0 | 32 | #define HW_PARTITION_REGISTERS_ADDR 0x1ffc0 |
33 | #define HW_ACCESS_PART0_START_ADDR 0x1FFC4 | 33 | #define HW_PART0_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR) |
34 | #define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8 | 34 | #define HW_PART0_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 4) |
35 | #define HW_ACCESS_PART1_START_ADDR 0x1FFCC | 35 | #define HW_PART1_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 8) |
36 | #define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12) | ||
37 | #define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16) | ||
38 | #define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20) | ||
39 | #define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24) | ||
36 | 40 | ||
37 | #define HW_ACCESS_REGISTER_SIZE 4 | 41 | #define HW_ACCESS_REGISTER_SIZE 4 |
38 | 42 | ||
@@ -67,47 +71,56 @@ | |||
67 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) | 71 | ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) |
68 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 | 72 | #define HW_ACCESS_WSPI_INIT_CMD_MASK 0 |
69 | 73 | ||
74 | #define OCP_CMD_LOOP 32 | ||
75 | |||
76 | #define OCP_CMD_WRITE 0x1 | ||
77 | #define OCP_CMD_READ 0x2 | ||
78 | |||
79 | #define OCP_READY_MASK BIT(18) | ||
80 | #define OCP_STATUS_MASK (BIT(16) | BIT(17)) | ||
81 | |||
82 | #define OCP_STATUS_NO_RESP 0x00000 | ||
83 | #define OCP_STATUS_OK 0x10000 | ||
84 | #define OCP_STATUS_REQ_FAILED 0x20000 | ||
85 | #define OCP_STATUS_RESP_ERROR 0x30000 | ||
70 | 86 | ||
71 | /* Raw target IO, address is not translated */ | 87 | /* Raw target IO, address is not translated */ |
72 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, | 88 | void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, |
73 | size_t len, bool fixed); | 89 | size_t len, bool fixed); |
74 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, | 90 | void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
75 | size_t len, bool fixed); | 91 | size_t len, bool fixed); |
76 | 92 | ||
77 | /* Memory target IO, address is tranlated to partition 0 */ | 93 | /* Translated target IO */ |
78 | void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, size_t len); | 94 | void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len, |
79 | void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, size_t len); | 95 | bool fixed); |
80 | u32 wl1271_mem_read32(struct wl1271 *wl, int addr); | 96 | void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len, |
81 | void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val); | 97 | bool fixed); |
98 | u32 wl1271_spi_read32(struct wl1271 *wl, int addr); | ||
99 | void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val); | ||
82 | 100 | ||
83 | /* Registers IO */ | 101 | /* Top Register IO */ |
84 | void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len, | 102 | void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val); |
85 | bool fixed); | 103 | u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); |
86 | void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len, | ||
87 | bool fixed); | ||
88 | u32 wl1271_reg_read32(struct wl1271 *wl, int addr); | ||
89 | void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val); | ||
90 | 104 | ||
91 | /* INIT and RESET words */ | 105 | /* INIT and RESET words */ |
92 | void wl1271_spi_reset(struct wl1271 *wl); | 106 | void wl1271_spi_reset(struct wl1271 *wl); |
93 | void wl1271_spi_init(struct wl1271 *wl); | 107 | void wl1271_spi_init(struct wl1271 *wl); |
94 | int wl1271_set_partition(struct wl1271 *wl, | 108 | int wl1271_set_partition(struct wl1271 *wl, |
95 | u32 part_start, u32 part_size, | 109 | struct wl1271_partition_set *p); |
96 | u32 reg_start, u32 reg_size); | ||
97 | 110 | ||
98 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | 111 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) |
99 | { | 112 | { |
100 | wl1271_spi_read(wl, addr, &wl->buffer_32, | 113 | wl1271_spi_raw_read(wl, addr, &wl->buffer_32, |
101 | sizeof(wl->buffer_32), false); | 114 | sizeof(wl->buffer_32), false); |
102 | 115 | ||
103 | return wl->buffer_32; | 116 | return wl->buffer_32; |
104 | } | 117 | } |
105 | 118 | ||
106 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | 119 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) |
107 | { | 120 | { |
108 | wl->buffer_32 = val; | 121 | wl->buffer_32 = val; |
109 | wl1271_spi_write(wl, addr, &wl->buffer_32, | 122 | wl1271_spi_raw_write(wl, addr, &wl->buffer_32, |
110 | sizeof(wl->buffer_32), false); | 123 | sizeof(wl->buffer_32), false); |
111 | } | 124 | } |
112 | 125 | ||
113 | #endif /* __WL1271_SPI_H__ */ | 126 | #endif /* __WL1271_SPI_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index ff221258b941..00af065c77c2 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -33,8 +33,7 @@ | |||
33 | static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) | 33 | static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) |
34 | { | 34 | { |
35 | int i; | 35 | int i; |
36 | 36 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | |
37 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | ||
38 | if (wl->tx_frames[i] == NULL) { | 37 | if (wl->tx_frames[i] == NULL) { |
39 | wl->tx_frames[i] = skb; | 38 | wl->tx_frames[i] = skb; |
40 | return i; | 39 | return i; |
@@ -58,8 +57,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) | |||
58 | /* approximate the number of blocks required for this packet | 57 | /* approximate the number of blocks required for this packet |
59 | in the firmware */ | 58 | in the firmware */ |
60 | /* FIXME: try to figure out what is done here and make it cleaner */ | 59 | /* FIXME: try to figure out what is done here and make it cleaner */ |
61 | total_blocks = (skb->len) >> TX_HW_BLOCK_SHIFT_DIV; | 60 | total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV; |
62 | excluded = (total_blocks << 2) + (skb->len & 0xff) + 34; | 61 | excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34; |
63 | total_blocks += (excluded > 252) ? 2 : 1; | 62 | total_blocks += (excluded > 252) ? 2 : 1; |
64 | total_blocks += TX_HW_BLOCK_SPARE; | 63 | total_blocks += TX_HW_BLOCK_SPARE; |
65 | 64 | ||
@@ -89,15 +88,25 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
89 | { | 88 | { |
90 | struct wl1271_tx_hw_descr *desc; | 89 | struct wl1271_tx_hw_descr *desc; |
91 | int pad; | 90 | int pad; |
91 | u16 tx_attr; | ||
92 | 92 | ||
93 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 93 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
94 | 94 | ||
95 | /* relocate space for security header */ | ||
96 | if (extra) { | ||
97 | void *framestart = skb->data + sizeof(*desc); | ||
98 | u16 fc = *(u16 *)(framestart + extra); | ||
99 | int hdrlen = ieee80211_hdrlen(cpu_to_le16(fc)); | ||
100 | memmove(framestart, framestart + extra, hdrlen); | ||
101 | } | ||
102 | |||
95 | /* configure packet life time */ | 103 | /* configure packet life time */ |
96 | desc->start_time = jiffies_to_usecs(jiffies) - wl->time_offset; | 104 | desc->start_time = cpu_to_le32(jiffies_to_usecs(jiffies) - |
97 | desc->life_time = TX_HW_MGMT_PKT_LIFETIME_TU; | 105 | wl->time_offset); |
106 | desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); | ||
98 | 107 | ||
99 | /* configure the tx attributes */ | 108 | /* configure the tx attributes */ |
100 | desc->tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; | 109 | tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; |
101 | /* FIXME: do we know the packet priority? can we identify mgmt | 110 | /* FIXME: do we know the packet priority? can we identify mgmt |
102 | packets, and use max prio for them at least? */ | 111 | packets, and use max prio for them at least? */ |
103 | desc->tid = 0; | 112 | desc->tid = 0; |
@@ -106,11 +115,13 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
106 | 115 | ||
107 | /* align the length (and store in terms of words) */ | 116 | /* align the length (and store in terms of words) */ |
108 | pad = WL1271_TX_ALIGN(skb->len); | 117 | pad = WL1271_TX_ALIGN(skb->len); |
109 | desc->length = pad >> 2; | 118 | desc->length = cpu_to_le16(pad >> 2); |
110 | 119 | ||
111 | /* calculate number of padding bytes */ | 120 | /* calculate number of padding bytes */ |
112 | pad = pad - skb->len; | 121 | pad = pad - skb->len; |
113 | desc->tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
123 | |||
124 | desc->tx_attr = cpu_to_le16(tx_attr); | ||
114 | 125 | ||
115 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 126 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
116 | return 0; | 127 | return 0; |
@@ -147,11 +158,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, | |||
147 | len = WL1271_TX_ALIGN(skb->len); | 158 | len = WL1271_TX_ALIGN(skb->len); |
148 | 159 | ||
149 | /* perform a fixed address block write with the packet */ | 160 | /* perform a fixed address block write with the packet */ |
150 | wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); | 161 | wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); |
151 | 162 | ||
152 | /* write packet new counter into the write access register */ | 163 | /* write packet new counter into the write access register */ |
153 | wl->tx_packets_count++; | 164 | wl->tx_packets_count++; |
154 | wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); | 165 | wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); |
155 | 166 | ||
156 | desc = (struct wl1271_tx_hw_descr *) skb->data; | 167 | desc = (struct wl1271_tx_hw_descr *) skb->data; |
157 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", | 168 | wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", |
@@ -254,14 +265,13 @@ out: | |||
254 | static void wl1271_tx_complete_packet(struct wl1271 *wl, | 265 | static void wl1271_tx_complete_packet(struct wl1271 *wl, |
255 | struct wl1271_tx_hw_res_descr *result) | 266 | struct wl1271_tx_hw_res_descr *result) |
256 | { | 267 | { |
257 | |||
258 | struct ieee80211_tx_info *info; | 268 | struct ieee80211_tx_info *info; |
259 | struct sk_buff *skb; | 269 | struct sk_buff *skb; |
260 | u32 header_len; | 270 | u16 seq; |
261 | int id = result->id; | 271 | int id = result->id; |
262 | 272 | ||
263 | /* check for id legality */ | 273 | /* check for id legality */ |
264 | if (id >= TX_HW_RESULT_QUEUE_LEN || wl->tx_frames[id] == NULL) { | 274 | if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { |
265 | wl1271_warning("TX result illegal id: %d", id); | 275 | wl1271_warning("TX result illegal id: %d", id); |
266 | return; | 276 | return; |
267 | } | 277 | } |
@@ -284,22 +294,32 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
284 | /* info->status.retry_count = result->ack_failures; */ | 294 | /* info->status.retry_count = result->ack_failures; */ |
285 | wl->stats.retry_count += result->ack_failures; | 295 | wl->stats.retry_count += result->ack_failures; |
286 | 296 | ||
287 | /* get header len */ | 297 | /* update security sequence number */ |
298 | seq = wl->tx_security_seq_16 + | ||
299 | (result->lsb_security_sequence_number - | ||
300 | wl->tx_security_last_seq); | ||
301 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | ||
302 | |||
303 | if (seq < wl->tx_security_seq_16) | ||
304 | wl->tx_security_seq_32++; | ||
305 | wl->tx_security_seq_16 = seq; | ||
306 | |||
307 | /* remove private header from packet */ | ||
308 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | ||
309 | |||
310 | /* remove TKIP header space if present */ | ||
288 | if (info->control.hw_key && | 311 | if (info->control.hw_key && |
289 | info->control.hw_key->alg == ALG_TKIP) | 312 | info->control.hw_key->alg == ALG_TKIP) { |
290 | header_len = WL1271_TKIP_IV_SPACE + | 313 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
291 | sizeof(struct wl1271_tx_hw_descr); | 314 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); |
292 | else | 315 | skb_pull(skb, WL1271_TKIP_IV_SPACE); |
293 | header_len = sizeof(struct wl1271_tx_hw_descr); | 316 | } |
294 | 317 | ||
295 | wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" | 318 | wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" |
296 | " status 0x%x", | 319 | " status 0x%x", |
297 | result->id, skb, result->ack_failures, | 320 | result->id, skb, result->ack_failures, |
298 | result->rate_class_index, result->status); | 321 | result->rate_class_index, result->status); |
299 | 322 | ||
300 | /* remove private header from packet */ | ||
301 | skb_pull(skb, header_len); | ||
302 | |||
303 | /* return the packet to the stack */ | 323 | /* return the packet to the stack */ |
304 | ieee80211_tx_status(wl->hw, skb); | 324 | ieee80211_tx_status(wl->hw, skb); |
305 | wl->tx_frames[result->id] = NULL; | 325 | wl->tx_frames[result->id] = NULL; |
@@ -315,8 +335,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
315 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 335 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
316 | 336 | ||
317 | /* read the tx results from the chipset */ | 337 | /* read the tx results from the chipset */ |
318 | wl1271_spi_mem_read(wl, memmap->tx_result, | 338 | wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result), |
319 | wl->tx_res_if, sizeof(*wl->tx_res_if)); | 339 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
320 | 340 | ||
321 | /* verify that the result buffer is not getting overrun */ | 341 | /* verify that the result buffer is not getting overrun */ |
322 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 342 | if (count > TX_HW_RESULT_QUEUE_LEN) { |
@@ -337,10 +357,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
337 | } | 357 | } |
338 | 358 | ||
339 | /* write host counter to chipset (to ack) */ | 359 | /* write host counter to chipset (to ack) */ |
340 | wl1271_mem_write32(wl, memmap->tx_result + | 360 | wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) + |
341 | offsetof(struct wl1271_tx_hw_res_if, | 361 | offsetof(struct wl1271_tx_hw_res_if, |
342 | tx_result_host_counter), | 362 | tx_result_host_counter), |
343 | wl->tx_res_if->tx_result_fw_counter); | 363 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); |
344 | } | 364 | } |
345 | 365 | ||
346 | /* caller must hold wl->mutex */ | 366 | /* caller must hold wl->mutex */ |
@@ -364,7 +384,7 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
364 | ieee80211_tx_status(wl->hw, skb); | 384 | ieee80211_tx_status(wl->hw, skb); |
365 | } | 385 | } |
366 | 386 | ||
367 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | 387 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
368 | if (wl->tx_frames[i] != NULL) { | 388 | if (wl->tx_frames[i] != NULL) { |
369 | skb = wl->tx_frames[i]; | 389 | skb = wl->tx_frames[i]; |
370 | info = IEEE80211_SKB_CB(skb); | 390 | info = IEEE80211_SKB_CB(skb); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 4a614067ddba..416396caf0a0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -58,7 +58,7 @@ | |||
58 | 58 | ||
59 | struct wl1271_tx_hw_descr { | 59 | struct wl1271_tx_hw_descr { |
60 | /* Length of packet in words, including descriptor+header+data */ | 60 | /* Length of packet in words, including descriptor+header+data */ |
61 | u16 length; | 61 | __le16 length; |
62 | /* Number of extra memory blocks to allocate for this packet in | 62 | /* Number of extra memory blocks to allocate for this packet in |
63 | addition to the number of blocks derived from the packet length */ | 63 | addition to the number of blocks derived from the packet length */ |
64 | u8 extra_mem_blocks; | 64 | u8 extra_mem_blocks; |
@@ -67,12 +67,12 @@ struct wl1271_tx_hw_descr { | |||
67 | HW!! */ | 67 | HW!! */ |
68 | u8 total_mem_blocks; | 68 | u8 total_mem_blocks; |
69 | /* Device time (in us) when the packet arrived to the driver */ | 69 | /* Device time (in us) when the packet arrived to the driver */ |
70 | u32 start_time; | 70 | __le32 start_time; |
71 | /* Max delay in TUs until transmission. The last device time the | 71 | /* Max delay in TUs until transmission. The last device time the |
72 | packet can be transmitted is: startTime+(1024*LifeTime) */ | 72 | packet can be transmitted is: startTime+(1024*LifeTime) */ |
73 | u16 life_time; | 73 | __le16 life_time; |
74 | /* Bitwise fields - see TX_ATTR... definitions above. */ | 74 | /* Bitwise fields - see TX_ATTR... definitions above. */ |
75 | u16 tx_attr; | 75 | __le16 tx_attr; |
76 | /* Packet identifier used also in the Tx-Result. */ | 76 | /* Packet identifier used also in the Tx-Result. */ |
77 | u8 id; | 77 | u8 id; |
78 | /* The packet TID value (as User-Priority) */ | 78 | /* The packet TID value (as User-Priority) */ |
@@ -100,12 +100,12 @@ struct wl1271_tx_hw_res_descr { | |||
100 | several possible reasons for failure. */ | 100 | several possible reasons for failure. */ |
101 | u8 status; | 101 | u8 status; |
102 | /* Total air access duration including all retrys and overheads.*/ | 102 | /* Total air access duration including all retrys and overheads.*/ |
103 | u16 medium_usage; | 103 | __le16 medium_usage; |
104 | /* The time passed from host xfer to Tx-complete.*/ | 104 | /* The time passed from host xfer to Tx-complete.*/ |
105 | u32 fw_handling_time; | 105 | __le32 fw_handling_time; |
106 | /* Total media delay | 106 | /* Total media delay |
107 | (from 1st EDCA AIFS counter until TX Complete). */ | 107 | (from 1st EDCA AIFS counter until TX Complete). */ |
108 | u32 medium_delay; | 108 | __le32 medium_delay; |
109 | /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ | 109 | /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ |
110 | u8 lsb_security_sequence_number; | 110 | u8 lsb_security_sequence_number; |
111 | /* Retry count - number of transmissions without successful ACK.*/ | 111 | /* Retry count - number of transmissions without successful ACK.*/ |
@@ -118,8 +118,8 @@ struct wl1271_tx_hw_res_descr { | |||
118 | } __attribute__ ((packed)); | 118 | } __attribute__ ((packed)); |
119 | 119 | ||
120 | struct wl1271_tx_hw_res_if { | 120 | struct wl1271_tx_hw_res_if { |
121 | u32 tx_result_fw_counter; | 121 | __le32 tx_result_fw_counter; |
122 | u32 tx_result_host_counter; | 122 | __le32 tx_result_host_counter; |
123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; | 123 | struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; |
124 | } __attribute__ ((packed)); | 124 | } __attribute__ ((packed)); |
125 | 125 | ||
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h index 657c2dbcb7d3..055d7bc6f592 100644 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h | |||
@@ -122,8 +122,8 @@ struct wl12xx_null_data_template { | |||
122 | } __attribute__ ((packed)); | 122 | } __attribute__ ((packed)); |
123 | 123 | ||
124 | struct wl12xx_ps_poll_template { | 124 | struct wl12xx_ps_poll_template { |
125 | u16 fc; | 125 | __le16 fc; |
126 | u16 aid; | 126 | __le16 aid; |
127 | u8 bssid[ETH_ALEN]; | 127 | u8 bssid[ETH_ALEN]; |
128 | u8 ta[ETH_ALEN]; | 128 | u8 ta[ETH_ALEN]; |
129 | } __attribute__ ((packed)); | 129 | } __attribute__ ((packed)); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 4e79a9800134..dfa1b9bc22c8 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -755,7 +755,7 @@ static int hw_reset_phy(struct zd_chip *chip) | |||
755 | static int zd1211_hw_init_hmac(struct zd_chip *chip) | 755 | static int zd1211_hw_init_hmac(struct zd_chip *chip) |
756 | { | 756 | { |
757 | static const struct zd_ioreq32 ioreqs[] = { | 757 | static const struct zd_ioreq32 ioreqs[] = { |
758 | { CR_ZD1211_RETRY_MAX, 0x2 }, | 758 | { CR_ZD1211_RETRY_MAX, ZD1211_RETRY_COUNT }, |
759 | { CR_RX_THRESHOLD, 0x000c0640 }, | 759 | { CR_RX_THRESHOLD, 0x000c0640 }, |
760 | }; | 760 | }; |
761 | 761 | ||
@@ -767,7 +767,7 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) | |||
767 | static int zd1211b_hw_init_hmac(struct zd_chip *chip) | 767 | static int zd1211b_hw_init_hmac(struct zd_chip *chip) |
768 | { | 768 | { |
769 | static const struct zd_ioreq32 ioreqs[] = { | 769 | static const struct zd_ioreq32 ioreqs[] = { |
770 | { CR_ZD1211B_RETRY_MAX, 0x02020202 }, | 770 | { CR_ZD1211B_RETRY_MAX, ZD1211B_RETRY_COUNT }, |
771 | { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f }, | 771 | { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f }, |
772 | { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f }, | 772 | { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f }, |
773 | { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f }, | 773 | { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f }, |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 678c139a840c..9fd8f3508d66 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -642,13 +642,29 @@ enum { | |||
642 | #define CR_ZD1211B_TXOP CTL_REG(0x0b20) | 642 | #define CR_ZD1211B_TXOP CTL_REG(0x0b20) |
643 | #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) | 643 | #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) |
644 | 644 | ||
645 | /* Value for CR_ZD1211_RETRY_MAX & CR_ZD1211B_RETRY_MAX. Vendor driver uses 2, | ||
646 | * we use 0. The first rate is tried (count+2), then all next rates are tried | ||
647 | * twice, until 1 Mbits is tried. */ | ||
648 | #define ZD1211_RETRY_COUNT 0 | ||
649 | #define ZD1211B_RETRY_COUNT \ | ||
650 | (ZD1211_RETRY_COUNT << 0)| \ | ||
651 | (ZD1211_RETRY_COUNT << 8)| \ | ||
652 | (ZD1211_RETRY_COUNT << 16)| \ | ||
653 | (ZD1211_RETRY_COUNT << 24) | ||
654 | |||
645 | /* Used to detect PLL lock */ | 655 | /* Used to detect PLL lock */ |
646 | #define UW2453_INTR_REG ((zd_addr_t)0x85c1) | 656 | #define UW2453_INTR_REG ((zd_addr_t)0x85c1) |
647 | 657 | ||
648 | #define CWIN_SIZE 0x007f043f | 658 | #define CWIN_SIZE 0x007f043f |
649 | 659 | ||
650 | 660 | ||
651 | #define HWINT_ENABLED 0x004f0000 | 661 | #define HWINT_ENABLED \ |
662 | (INT_TX_COMPLETE_EN| \ | ||
663 | INT_RX_COMPLETE_EN| \ | ||
664 | INT_RETRY_FAIL_EN| \ | ||
665 | INT_WAKEUP_EN| \ | ||
666 | INT_CFG_NEXT_BCN_EN) | ||
667 | |||
652 | #define HWINT_DISABLED 0 | 668 | #define HWINT_DISABLED 0 |
653 | 669 | ||
654 | #define E2P_PWR_INT_GUARD 8 | 670 | #define E2P_PWR_INT_GUARD 8 |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6d666359a42f..8a243732c519 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -88,6 +88,34 @@ static const struct ieee80211_rate zd_rates[] = { | |||
88 | .flags = 0 }, | 88 | .flags = 0 }, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | /* | ||
92 | * Zydas retry rates table. Each line is listed in the same order as | ||
93 | * in zd_rates[] and contains all the rate used when a packet is sent | ||
94 | * starting with a given rates. Let's consider an example : | ||
95 | * | ||
96 | * "11 Mbits : 4, 3, 2, 1, 0" means : | ||
97 | * - packet is sent using 4 different rates | ||
98 | * - 1st rate is index 3 (ie 11 Mbits) | ||
99 | * - 2nd rate is index 2 (ie 5.5 Mbits) | ||
100 | * - 3rd rate is index 1 (ie 2 Mbits) | ||
101 | * - 4th rate is index 0 (ie 1 Mbits) | ||
102 | */ | ||
103 | |||
104 | static const struct tx_retry_rate zd_retry_rates[] = { | ||
105 | { /* 1 Mbits */ 1, { 0 }}, | ||
106 | { /* 2 Mbits */ 2, { 1, 0 }}, | ||
107 | { /* 5.5 Mbits */ 3, { 2, 1, 0 }}, | ||
108 | { /* 11 Mbits */ 4, { 3, 2, 1, 0 }}, | ||
109 | { /* 6 Mbits */ 5, { 4, 3, 2, 1, 0 }}, | ||
110 | { /* 9 Mbits */ 6, { 5, 4, 3, 2, 1, 0}}, | ||
111 | { /* 12 Mbits */ 5, { 6, 3, 2, 1, 0 }}, | ||
112 | { /* 18 Mbits */ 6, { 7, 6, 3, 2, 1, 0 }}, | ||
113 | { /* 24 Mbits */ 6, { 8, 6, 3, 2, 1, 0 }}, | ||
114 | { /* 36 Mbits */ 7, { 9, 8, 6, 3, 2, 1, 0 }}, | ||
115 | { /* 48 Mbits */ 8, {10, 9, 8, 6, 3, 2, 1, 0 }}, | ||
116 | { /* 54 Mbits */ 9, {11, 10, 9, 8, 6, 3, 2, 1, 0 }} | ||
117 | }; | ||
118 | |||
91 | static const struct ieee80211_channel zd_channels[] = { | 119 | static const struct ieee80211_channel zd_channels[] = { |
92 | { .center_freq = 2412, .hw_value = 1 }, | 120 | { .center_freq = 2412, .hw_value = 1 }, |
93 | { .center_freq = 2417, .hw_value = 2 }, | 121 | { .center_freq = 2417, .hw_value = 2 }, |
@@ -282,7 +310,7 @@ static void zd_op_stop(struct ieee80211_hw *hw) | |||
282 | } | 310 | } |
283 | 311 | ||
284 | /** | 312 | /** |
285 | * tx_status - reports tx status of a packet if required | 313 | * zd_mac_tx_status - reports tx status of a packet if required |
286 | * @hw - a &struct ieee80211_hw pointer | 314 | * @hw - a &struct ieee80211_hw pointer |
287 | * @skb - a sk-buffer | 315 | * @skb - a sk-buffer |
288 | * @flags: extra flags to set in the TX status info | 316 | * @flags: extra flags to set in the TX status info |
@@ -295,15 +323,49 @@ static void zd_op_stop(struct ieee80211_hw *hw) | |||
295 | * | 323 | * |
296 | * If no status information has been requested, the skb is freed. | 324 | * If no status information has been requested, the skb is freed. |
297 | */ | 325 | */ |
298 | static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | 326 | static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, |
299 | int ackssi, bool success) | 327 | int ackssi, struct tx_status *tx_status) |
300 | { | 328 | { |
301 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 329 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
330 | int i; | ||
331 | int success = 1, retry = 1; | ||
332 | int first_idx; | ||
333 | const struct tx_retry_rate *retries; | ||
302 | 334 | ||
303 | ieee80211_tx_info_clear_status(info); | 335 | ieee80211_tx_info_clear_status(info); |
304 | 336 | ||
305 | if (success) | 337 | if (tx_status) { |
338 | success = !tx_status->failure; | ||
339 | retry = tx_status->retry + success; | ||
340 | } | ||
341 | |||
342 | if (success) { | ||
343 | /* success */ | ||
306 | info->flags |= IEEE80211_TX_STAT_ACK; | 344 | info->flags |= IEEE80211_TX_STAT_ACK; |
345 | } else { | ||
346 | /* failure */ | ||
347 | info->flags &= ~IEEE80211_TX_STAT_ACK; | ||
348 | } | ||
349 | |||
350 | first_idx = info->status.rates[0].idx; | ||
351 | ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); | ||
352 | retries = &zd_retry_rates[first_idx]; | ||
353 | ZD_ASSERT(0<=retry && retry<=retries->count); | ||
354 | |||
355 | info->status.rates[0].idx = retries->rate[0]; | ||
356 | info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1); | ||
357 | |||
358 | for (i=1; i<IEEE80211_TX_MAX_RATES-1 && i<retry; i++) { | ||
359 | info->status.rates[i].idx = retries->rate[i]; | ||
360 | info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2); | ||
361 | } | ||
362 | for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) { | ||
363 | info->status.rates[i].idx = retries->rate[retry-1]; | ||
364 | info->status.rates[i].count = 1; // (success ? 1:2); | ||
365 | } | ||
366 | if (i<IEEE80211_TX_MAX_RATES) | ||
367 | info->status.rates[i].idx = -1; /* terminate */ | ||
368 | |||
307 | info->status.ack_signal = ackssi; | 369 | info->status.ack_signal = ackssi; |
308 | ieee80211_tx_status_irqsafe(hw, skb); | 370 | ieee80211_tx_status_irqsafe(hw, skb); |
309 | } | 371 | } |
@@ -316,16 +378,79 @@ static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
316 | * transferred. The first frame from the tx queue, will be selected and | 378 | * transferred. The first frame from the tx queue, will be selected and |
317 | * reported as error to the upper layers. | 379 | * reported as error to the upper layers. |
318 | */ | 380 | */ |
319 | void zd_mac_tx_failed(struct ieee80211_hw *hw) | 381 | void zd_mac_tx_failed(struct urb *urb) |
320 | { | 382 | { |
321 | struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; | 383 | struct ieee80211_hw * hw = zd_usb_to_hw(urb->context); |
384 | struct zd_mac *mac = zd_hw_mac(hw); | ||
385 | struct sk_buff_head *q = &mac->ack_wait_queue; | ||
322 | struct sk_buff *skb; | 386 | struct sk_buff *skb; |
387 | struct tx_status *tx_status = (struct tx_status *)urb->transfer_buffer; | ||
388 | unsigned long flags; | ||
389 | int success = !tx_status->failure; | ||
390 | int retry = tx_status->retry + success; | ||
391 | int found = 0; | ||
392 | int i, position = 0; | ||
323 | 393 | ||
324 | skb = skb_dequeue(q); | 394 | q = &mac->ack_wait_queue; |
325 | if (skb == NULL) | 395 | spin_lock_irqsave(&q->lock, flags); |
326 | return; | 396 | |
397 | skb_queue_walk(q, skb) { | ||
398 | struct ieee80211_hdr *tx_hdr; | ||
399 | struct ieee80211_tx_info *info; | ||
400 | int first_idx, final_idx; | ||
401 | const struct tx_retry_rate *retries; | ||
402 | u8 final_rate; | ||
403 | |||
404 | position ++; | ||
405 | |||
406 | /* if the hardware reports a failure and we had a 802.11 ACK | ||
407 | * pending, then we skip the first skb when searching for a | ||
408 | * matching frame */ | ||
409 | if (tx_status->failure && mac->ack_pending && | ||
410 | skb_queue_is_first(q, skb)) { | ||
411 | continue; | ||
412 | } | ||
413 | |||
414 | tx_hdr = (struct ieee80211_hdr *)skb->data; | ||
415 | |||
416 | /* we skip all frames not matching the reported destination */ | ||
417 | if (unlikely(memcmp(tx_hdr->addr1, tx_status->mac, ETH_ALEN))) { | ||
418 | continue; | ||
419 | } | ||
420 | |||
421 | /* we skip all frames not matching the reported final rate */ | ||
327 | 422 | ||
328 | tx_status(hw, skb, 0, 0); | 423 | info = IEEE80211_SKB_CB(skb); |
424 | first_idx = info->status.rates[0].idx; | ||
425 | ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); | ||
426 | retries = &zd_retry_rates[first_idx]; | ||
427 | if (retry < 0 || retry > retries->count) { | ||
428 | continue; | ||
429 | } | ||
430 | |||
431 | ZD_ASSERT(0<=retry && retry<=retries->count); | ||
432 | final_idx = retries->rate[retry-1]; | ||
433 | final_rate = zd_rates[final_idx].hw_value; | ||
434 | |||
435 | if (final_rate != tx_status->rate) { | ||
436 | continue; | ||
437 | } | ||
438 | |||
439 | found = 1; | ||
440 | break; | ||
441 | } | ||
442 | |||
443 | if (found) { | ||
444 | for (i=1; i<=position; i++) { | ||
445 | skb = __skb_dequeue(q); | ||
446 | zd_mac_tx_status(hw, skb, | ||
447 | mac->ack_pending ? mac->ack_signal : 0, | ||
448 | i == position ? tx_status : NULL); | ||
449 | mac->ack_pending = 0; | ||
450 | } | ||
451 | } | ||
452 | |||
453 | spin_unlock_irqrestore(&q->lock, flags); | ||
329 | } | 454 | } |
330 | 455 | ||
331 | /** | 456 | /** |
@@ -342,18 +467,27 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error) | |||
342 | { | 467 | { |
343 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 468 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
344 | struct ieee80211_hw *hw = info->rate_driver_data[0]; | 469 | struct ieee80211_hw *hw = info->rate_driver_data[0]; |
470 | struct zd_mac *mac = zd_hw_mac(hw); | ||
471 | |||
472 | ieee80211_tx_info_clear_status(info); | ||
345 | 473 | ||
346 | skb_pull(skb, sizeof(struct zd_ctrlset)); | 474 | skb_pull(skb, sizeof(struct zd_ctrlset)); |
347 | if (unlikely(error || | 475 | if (unlikely(error || |
348 | (info->flags & IEEE80211_TX_CTL_NO_ACK))) { | 476 | (info->flags & IEEE80211_TX_CTL_NO_ACK))) { |
349 | tx_status(hw, skb, 0, !error); | 477 | /* |
478 | * FIXME : do we need to fill in anything ? | ||
479 | */ | ||
480 | ieee80211_tx_status_irqsafe(hw, skb); | ||
350 | } else { | 481 | } else { |
351 | struct sk_buff_head *q = | 482 | struct sk_buff_head *q = &mac->ack_wait_queue; |
352 | &zd_hw_mac(hw)->ack_wait_queue; | ||
353 | 483 | ||
354 | skb_queue_tail(q, skb); | 484 | skb_queue_tail(q, skb); |
355 | while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) | 485 | while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) { |
356 | zd_mac_tx_failed(hw); | 486 | zd_mac_tx_status(hw, skb_dequeue(q), |
487 | mac->ack_pending ? mac->ack_signal : 0, | ||
488 | NULL); | ||
489 | mac->ack_pending = 0; | ||
490 | } | ||
357 | } | 491 | } |
358 | } | 492 | } |
359 | 493 | ||
@@ -606,27 +740,47 @@ fail: | |||
606 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, | 740 | static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, |
607 | struct ieee80211_rx_status *stats) | 741 | struct ieee80211_rx_status *stats) |
608 | { | 742 | { |
743 | struct zd_mac *mac = zd_hw_mac(hw); | ||
609 | struct sk_buff *skb; | 744 | struct sk_buff *skb; |
610 | struct sk_buff_head *q; | 745 | struct sk_buff_head *q; |
611 | unsigned long flags; | 746 | unsigned long flags; |
747 | int found = 0; | ||
748 | int i, position = 0; | ||
612 | 749 | ||
613 | if (!ieee80211_is_ack(rx_hdr->frame_control)) | 750 | if (!ieee80211_is_ack(rx_hdr->frame_control)) |
614 | return 0; | 751 | return 0; |
615 | 752 | ||
616 | q = &zd_hw_mac(hw)->ack_wait_queue; | 753 | q = &mac->ack_wait_queue; |
617 | spin_lock_irqsave(&q->lock, flags); | 754 | spin_lock_irqsave(&q->lock, flags); |
618 | skb_queue_walk(q, skb) { | 755 | skb_queue_walk(q, skb) { |
619 | struct ieee80211_hdr *tx_hdr; | 756 | struct ieee80211_hdr *tx_hdr; |
620 | 757 | ||
758 | position ++; | ||
759 | |||
760 | if (mac->ack_pending && skb_queue_is_first(q, skb)) | ||
761 | continue; | ||
762 | |||
621 | tx_hdr = (struct ieee80211_hdr *)skb->data; | 763 | tx_hdr = (struct ieee80211_hdr *)skb->data; |
622 | if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) | 764 | if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) |
623 | { | 765 | { |
624 | __skb_unlink(skb, q); | 766 | found = 1; |
625 | tx_status(hw, skb, stats->signal, 1); | 767 | break; |
626 | goto out; | ||
627 | } | 768 | } |
628 | } | 769 | } |
629 | out: | 770 | |
771 | if (found) { | ||
772 | for (i=1; i<position; i++) { | ||
773 | skb = __skb_dequeue(q); | ||
774 | zd_mac_tx_status(hw, skb, | ||
775 | mac->ack_pending ? mac->ack_signal : 0, | ||
776 | NULL); | ||
777 | mac->ack_pending = 0; | ||
778 | } | ||
779 | |||
780 | mac->ack_pending = 1; | ||
781 | mac->ack_signal = stats->signal; | ||
782 | } | ||
783 | |||
630 | spin_unlock_irqrestore(&q->lock, flags); | 784 | spin_unlock_irqrestore(&q->lock, flags); |
631 | return 1; | 785 | return 1; |
632 | } | 786 | } |
@@ -709,6 +863,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
709 | skb_reserve(skb, 2); | 863 | skb_reserve(skb, 2); |
710 | } | 864 | } |
711 | 865 | ||
866 | /* FIXME : could we avoid this big memcpy ? */ | ||
712 | memcpy(skb_put(skb, length), buffer, length); | 867 | memcpy(skb_put(skb, length), buffer, length); |
713 | 868 | ||
714 | memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); | 869 | memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); |
@@ -999,7 +1154,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
999 | hw->queues = 1; | 1154 | hw->queues = 1; |
1000 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); | 1155 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); |
1001 | 1156 | ||
1157 | /* | ||
1158 | * Tell mac80211 that we support multi rate retries | ||
1159 | */ | ||
1160 | hw->max_rates = IEEE80211_TX_MAX_RATES; | ||
1161 | hw->max_rate_tries = 18; /* 9 rates * 2 retries/rate */ | ||
1162 | |||
1002 | skb_queue_head_init(&mac->ack_wait_queue); | 1163 | skb_queue_head_init(&mac->ack_wait_queue); |
1164 | mac->ack_pending = 0; | ||
1003 | 1165 | ||
1004 | zd_chip_init(&mac->chip, hw, intf); | 1166 | zd_chip_init(&mac->chip, hw, intf); |
1005 | housekeeping_init(mac); | 1167 | housekeeping_init(mac); |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 7c2759118d13..630c298a730e 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -140,6 +140,21 @@ struct rx_status { | |||
140 | #define ZD_RX_CRC16_ERROR 0x40 | 140 | #define ZD_RX_CRC16_ERROR 0x40 |
141 | #define ZD_RX_ERROR 0x80 | 141 | #define ZD_RX_ERROR 0x80 |
142 | 142 | ||
143 | struct tx_retry_rate { | ||
144 | int count; /* number of valid element in rate[] array */ | ||
145 | int rate[10]; /* retry rates, described by an index in zd_rates[] */ | ||
146 | }; | ||
147 | |||
148 | struct tx_status { | ||
149 | u8 type; /* must always be 0x01 : USB_INT_TYPE */ | ||
150 | u8 id; /* must always be 0xa0 : USB_INT_ID_RETRY_FAILED */ | ||
151 | u8 rate; | ||
152 | u8 pad; | ||
153 | u8 mac[ETH_ALEN]; | ||
154 | u8 retry; | ||
155 | u8 failure; | ||
156 | } __attribute__((packed)); | ||
157 | |||
143 | enum mac_flags { | 158 | enum mac_flags { |
144 | MAC_FIXED_CHANNEL = 0x01, | 159 | MAC_FIXED_CHANNEL = 0x01, |
145 | }; | 160 | }; |
@@ -150,7 +165,7 @@ struct housekeeping { | |||
150 | 165 | ||
151 | #define ZD_MAC_STATS_BUFFER_SIZE 16 | 166 | #define ZD_MAC_STATS_BUFFER_SIZE 16 |
152 | 167 | ||
153 | #define ZD_MAC_MAX_ACK_WAITERS 10 | 168 | #define ZD_MAC_MAX_ACK_WAITERS 50 |
154 | 169 | ||
155 | struct zd_mac { | 170 | struct zd_mac { |
156 | struct zd_chip chip; | 171 | struct zd_chip chip; |
@@ -184,6 +199,12 @@ struct zd_mac { | |||
184 | 199 | ||
185 | /* whether to pass control frames to stack */ | 200 | /* whether to pass control frames to stack */ |
186 | unsigned int pass_ctrl:1; | 201 | unsigned int pass_ctrl:1; |
202 | |||
203 | /* whether we have received a 802.11 ACK that is pending */ | ||
204 | unsigned int ack_pending:1; | ||
205 | |||
206 | /* signal strength of the last 802.11 ACK received */ | ||
207 | int ack_signal; | ||
187 | }; | 208 | }; |
188 | 209 | ||
189 | #define ZD_REGDOMAIN_FCC 0x10 | 210 | #define ZD_REGDOMAIN_FCC 0x10 |
@@ -279,7 +300,7 @@ int zd_mac_preinit_hw(struct ieee80211_hw *hw); | |||
279 | int zd_mac_init_hw(struct ieee80211_hw *hw); | 300 | int zd_mac_init_hw(struct ieee80211_hw *hw); |
280 | 301 | ||
281 | int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length); | 302 | int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length); |
282 | void zd_mac_tx_failed(struct ieee80211_hw *hw); | 303 | void zd_mac_tx_failed(struct urb *urb); |
283 | void zd_mac_tx_to_dev(struct sk_buff *skb, int error); | 304 | void zd_mac_tx_to_dev(struct sk_buff *skb, int error); |
284 | 305 | ||
285 | #ifdef DEBUG | 306 | #ifdef DEBUG |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 23a6a6d4863b..d46f20a57b7d 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -419,7 +419,7 @@ static void int_urb_complete(struct urb *urb) | |||
419 | handle_regs_int(urb); | 419 | handle_regs_int(urb); |
420 | break; | 420 | break; |
421 | case USB_INT_ID_RETRY_FAILED: | 421 | case USB_INT_ID_RETRY_FAILED: |
422 | zd_mac_tx_failed(zd_usb_to_hw(urb->context)); | 422 | zd_mac_tx_failed(urb); |
423 | break; | 423 | break; |
424 | default: | 424 | default: |
425 | dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, | 425 | dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, |
@@ -553,6 +553,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, | |||
553 | 553 | ||
554 | if (length < sizeof(struct rx_length_info)) { | 554 | if (length < sizeof(struct rx_length_info)) { |
555 | /* It's not a complete packet anyhow. */ | 555 | /* It's not a complete packet anyhow. */ |
556 | printk("%s: invalid, small RX packet : %d\n", | ||
557 | __func__, length); | ||
556 | return; | 558 | return; |
557 | } | 559 | } |
558 | length_info = (struct rx_length_info *) | 560 | length_info = (struct rx_length_info *) |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 538c570df337..f1dcd7969a5c 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -551,13 +551,13 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | |||
551 | might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); | 551 | might_sleep_if(pdev->id.coreid != SSB_DEV_PCI); |
552 | 552 | ||
553 | /* Enable interrupts for this device. */ | 553 | /* Enable interrupts for this device. */ |
554 | if (bus->host_pci && | 554 | if ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE)) { |
555 | ((pdev->id.revision >= 6) || (pdev->id.coreid == SSB_DEV_PCIE))) { | ||
556 | u32 coremask; | 555 | u32 coremask; |
557 | 556 | ||
558 | /* Calculate the "coremask" for the device. */ | 557 | /* Calculate the "coremask" for the device. */ |
559 | coremask = (1 << dev->core_index); | 558 | coremask = (1 << dev->core_index); |
560 | 559 | ||
560 | SSB_WARN_ON(bus->bustype != SSB_BUSTYPE_PCI); | ||
561 | err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); | 561 | err = pci_read_config_dword(bus->host_pci, SSB_PCI_IRQMASK, &tmp); |
562 | if (err) | 562 | if (err) |
563 | goto out; | 563 | goto out; |