0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <net/dst.h>
0019
0020 #include "xmit.h"
0021 #include "phy.h"
0022 #include "dma.h"
0023 #include "pio.h"
0024
0025
0026
0027 static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
0028 {
0029 switch (plcp->raw[0]) {
0030 case 0x0A:
0031 return 0;
0032 case 0x14:
0033 return 1;
0034 case 0x37:
0035 return 2;
0036 case 0x6E:
0037 return 3;
0038 }
0039 B43legacy_BUG_ON(1);
0040 return -1;
0041 }
0042
0043
0044 static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
0045 bool aphy)
0046 {
0047 int base = aphy ? 0 : 4;
0048
0049 switch (plcp->raw[0] & 0xF) {
0050 case 0xB:
0051 return base + 0;
0052 case 0xF:
0053 return base + 1;
0054 case 0xA:
0055 return base + 2;
0056 case 0xE:
0057 return base + 3;
0058 case 0x9:
0059 return base + 4;
0060 case 0xD:
0061 return base + 5;
0062 case 0x8:
0063 return base + 6;
0064 case 0xC:
0065 return base + 7;
0066 }
0067 B43legacy_BUG_ON(1);
0068 return -1;
0069 }
0070
0071 u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
0072 {
0073 switch (bitrate) {
0074 case B43legacy_CCK_RATE_1MB:
0075 return 0x0A;
0076 case B43legacy_CCK_RATE_2MB:
0077 return 0x14;
0078 case B43legacy_CCK_RATE_5MB:
0079 return 0x37;
0080 case B43legacy_CCK_RATE_11MB:
0081 return 0x6E;
0082 }
0083 B43legacy_BUG_ON(1);
0084 return 0;
0085 }
0086
0087 u8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate)
0088 {
0089 switch (bitrate) {
0090 case B43legacy_OFDM_RATE_6MB:
0091 return 0xB;
0092 case B43legacy_OFDM_RATE_9MB:
0093 return 0xF;
0094 case B43legacy_OFDM_RATE_12MB:
0095 return 0xA;
0096 case B43legacy_OFDM_RATE_18MB:
0097 return 0xE;
0098 case B43legacy_OFDM_RATE_24MB:
0099 return 0x9;
0100 case B43legacy_OFDM_RATE_36MB:
0101 return 0xD;
0102 case B43legacy_OFDM_RATE_48MB:
0103 return 0x8;
0104 case B43legacy_OFDM_RATE_54MB:
0105 return 0xC;
0106 }
0107 B43legacy_BUG_ON(1);
0108 return 0;
0109 }
0110
0111 void b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp,
0112 const u16 octets, const u8 bitrate)
0113 {
0114 __le32 *data = &(plcp->data);
0115 __u8 *raw = plcp->raw;
0116
0117 if (b43legacy_is_ofdm_rate(bitrate)) {
0118 u16 d;
0119
0120 d = b43legacy_plcp_get_ratecode_ofdm(bitrate);
0121 B43legacy_WARN_ON(octets & 0xF000);
0122 d |= (octets << 5);
0123 *data = cpu_to_le32(d);
0124 } else {
0125 u32 plen;
0126
0127 plen = octets * 16 / bitrate;
0128 if ((octets * 16 % bitrate) > 0) {
0129 plen++;
0130 if ((bitrate == B43legacy_CCK_RATE_11MB)
0131 && ((octets * 8 % 11) < 4))
0132 raw[1] = 0x84;
0133 else
0134 raw[1] = 0x04;
0135 } else
0136 raw[1] = 0x04;
0137 *data |= cpu_to_le32(plen << 16);
0138 raw[0] = b43legacy_plcp_get_ratecode_cck(bitrate);
0139 }
0140 }
0141
0142 static u8 b43legacy_calc_fallback_rate(u8 bitrate)
0143 {
0144 switch (bitrate) {
0145 case B43legacy_CCK_RATE_1MB:
0146 return B43legacy_CCK_RATE_1MB;
0147 case B43legacy_CCK_RATE_2MB:
0148 return B43legacy_CCK_RATE_1MB;
0149 case B43legacy_CCK_RATE_5MB:
0150 return B43legacy_CCK_RATE_2MB;
0151 case B43legacy_CCK_RATE_11MB:
0152 return B43legacy_CCK_RATE_5MB;
0153 case B43legacy_OFDM_RATE_6MB:
0154 return B43legacy_CCK_RATE_5MB;
0155 case B43legacy_OFDM_RATE_9MB:
0156 return B43legacy_OFDM_RATE_6MB;
0157 case B43legacy_OFDM_RATE_12MB:
0158 return B43legacy_OFDM_RATE_9MB;
0159 case B43legacy_OFDM_RATE_18MB:
0160 return B43legacy_OFDM_RATE_12MB;
0161 case B43legacy_OFDM_RATE_24MB:
0162 return B43legacy_OFDM_RATE_18MB;
0163 case B43legacy_OFDM_RATE_36MB:
0164 return B43legacy_OFDM_RATE_24MB;
0165 case B43legacy_OFDM_RATE_48MB:
0166 return B43legacy_OFDM_RATE_36MB;
0167 case B43legacy_OFDM_RATE_54MB:
0168 return B43legacy_OFDM_RATE_48MB;
0169 }
0170 B43legacy_BUG_ON(1);
0171 return 0;
0172 }
0173
0174 static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
0175 struct b43legacy_txhdr_fw3 *txhdr,
0176 const unsigned char *fragment_data,
0177 unsigned int fragment_len,
0178 struct ieee80211_tx_info *info,
0179 u16 cookie)
0180 {
0181 const struct ieee80211_hdr *wlhdr;
0182 int use_encryption = !!info->control.hw_key;
0183 u8 rate;
0184 struct ieee80211_rate *rate_fb;
0185 int rate_ofdm;
0186 int rate_fb_ofdm;
0187 unsigned int plcp_fragment_len;
0188 u32 mac_ctl = 0;
0189 u16 phy_ctl = 0;
0190 struct ieee80211_rate *tx_rate;
0191 struct ieee80211_tx_rate *rates;
0192
0193 wlhdr = (const struct ieee80211_hdr *)fragment_data;
0194
0195 memset(txhdr, 0, sizeof(*txhdr));
0196
0197 tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info);
0198
0199 rate = tx_rate->hw_value;
0200 rate_ofdm = b43legacy_is_ofdm_rate(rate);
0201 rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
0202 rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
0203
0204 txhdr->mac_frame_ctl = wlhdr->frame_control;
0205 memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
0206
0207
0208 if ((rate_fb->hw_value == rate) ||
0209 (wlhdr->duration_id & cpu_to_le16(0x8000)) ||
0210 (wlhdr->duration_id == cpu_to_le16(0))) {
0211
0212
0213
0214 txhdr->dur_fb = wlhdr->duration_id;
0215 } else {
0216 txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
0217 info->control.vif,
0218 info->band,
0219 fragment_len,
0220 rate_fb);
0221 }
0222
0223 plcp_fragment_len = fragment_len + FCS_LEN;
0224 if (use_encryption) {
0225 u8 key_idx = info->control.hw_key->hw_key_idx;
0226 struct b43legacy_key *key;
0227 int wlhdr_len;
0228 size_t iv_len;
0229
0230 B43legacy_WARN_ON(key_idx >= dev->max_nr_keys);
0231 key = &(dev->key[key_idx]);
0232
0233 if (key->enabled) {
0234
0235 plcp_fragment_len += info->control.hw_key->icv_len;
0236
0237 key_idx = b43legacy_kidx_to_fw(dev, key_idx);
0238 mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
0239 B43legacy_TX4_MAC_KEYIDX;
0240 mac_ctl |= (key->algorithm <<
0241 B43legacy_TX4_MAC_KEYALG_SHIFT) &
0242 B43legacy_TX4_MAC_KEYALG;
0243 wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
0244 iv_len = min_t(size_t, info->control.hw_key->iv_len,
0245 ARRAY_SIZE(txhdr->iv));
0246 memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
0247 } else {
0248
0249
0250
0251
0252
0253 return -ENOKEY;
0254 }
0255 }
0256 b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
0257 (&txhdr->plcp), plcp_fragment_len,
0258 rate);
0259 b43legacy_generate_plcp_hdr(&txhdr->plcp_fb, plcp_fragment_len,
0260 rate_fb->hw_value);
0261
0262
0263 if (rate_ofdm)
0264 phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
0265 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
0266 phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
0267 phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
0268
0269
0270 rates = info->control.rates;
0271 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
0272 mac_ctl |= B43legacy_TX4_MAC_ACK;
0273 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
0274 mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
0275 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
0276 mac_ctl |= B43legacy_TX4_MAC_STMSDU;
0277 if (rate_fb_ofdm)
0278 mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
0279
0280
0281
0282
0283
0284 if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
0285 (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
0286 rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
0287 mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
0288 } else {
0289 rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
0290 }
0291
0292
0293 if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
0294 (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
0295 unsigned int len;
0296 struct ieee80211_hdr *hdr;
0297 int rts_rate;
0298 int rts_rate_fb;
0299 int rts_rate_fb_ofdm;
0300
0301 rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
0302 rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
0303 rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
0304 if (rts_rate_fb_ofdm)
0305 mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
0306
0307 if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
0308 ieee80211_ctstoself_get(dev->wl->hw,
0309 info->control.vif,
0310 fragment_data,
0311 fragment_len, info,
0312 (struct ieee80211_cts *)
0313 (txhdr->rts_frame));
0314 mac_ctl |= B43legacy_TX4_MAC_SENDCTS;
0315 len = sizeof(struct ieee80211_cts);
0316 } else {
0317 ieee80211_rts_get(dev->wl->hw,
0318 info->control.vif,
0319 fragment_data, fragment_len, info,
0320 (struct ieee80211_rts *)
0321 (txhdr->rts_frame));
0322 mac_ctl |= B43legacy_TX4_MAC_SENDRTS;
0323 len = sizeof(struct ieee80211_rts);
0324 }
0325 len += FCS_LEN;
0326 b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
0327 (&txhdr->rts_plcp),
0328 len, rts_rate);
0329 b43legacy_generate_plcp_hdr(&txhdr->rts_plcp_fb,
0330 len, rts_rate_fb);
0331 hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
0332 txhdr->rts_dur_fb = hdr->duration_id;
0333 }
0334
0335
0336 txhdr->cookie = cpu_to_le16(cookie);
0337
0338
0339 txhdr->mac_ctl = cpu_to_le32(mac_ctl);
0340 txhdr->phy_ctl = cpu_to_le16(phy_ctl);
0341
0342 return 0;
0343 }
0344
0345 int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
0346 u8 *txhdr,
0347 const unsigned char *fragment_data,
0348 unsigned int fragment_len,
0349 struct ieee80211_tx_info *info,
0350 u16 cookie)
0351 {
0352 return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
0353 fragment_data, fragment_len,
0354 info, cookie);
0355 }
0356
0357 static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
0358 u8 in_rssi, int ofdm,
0359 int adjust_2053, int adjust_2050)
0360 {
0361 struct b43legacy_phy *phy = &dev->phy;
0362 s32 tmp;
0363
0364 switch (phy->radio_ver) {
0365 case 0x2050:
0366 if (ofdm) {
0367 tmp = in_rssi;
0368 if (tmp > 127)
0369 tmp -= 256;
0370 tmp *= 73;
0371 tmp /= 64;
0372 if (adjust_2050)
0373 tmp += 25;
0374 else
0375 tmp -= 3;
0376 } else {
0377 if (dev->dev->bus->sprom.boardflags_lo
0378 & B43legacy_BFL_RSSI) {
0379 if (in_rssi > 63)
0380 in_rssi = 63;
0381 tmp = phy->nrssi_lt[in_rssi];
0382 tmp = 31 - tmp;
0383 tmp *= -131;
0384 tmp /= 128;
0385 tmp -= 57;
0386 } else {
0387 tmp = in_rssi;
0388 tmp = 31 - tmp;
0389 tmp *= -149;
0390 tmp /= 128;
0391 tmp -= 68;
0392 }
0393 if (phy->type == B43legacy_PHYTYPE_G &&
0394 adjust_2050)
0395 tmp += 25;
0396 }
0397 break;
0398 case 0x2060:
0399 if (in_rssi > 127)
0400 tmp = in_rssi - 256;
0401 else
0402 tmp = in_rssi;
0403 break;
0404 default:
0405 tmp = in_rssi;
0406 tmp -= 11;
0407 tmp *= 103;
0408 tmp /= 64;
0409 if (adjust_2053)
0410 tmp -= 109;
0411 else
0412 tmp -= 83;
0413 }
0414
0415 return (s8)tmp;
0416 }
0417
0418 void b43legacy_rx(struct b43legacy_wldev *dev,
0419 struct sk_buff *skb,
0420 const void *_rxhdr)
0421 {
0422 struct ieee80211_rx_status status;
0423 struct b43legacy_plcp_hdr6 *plcp;
0424 struct ieee80211_hdr *wlhdr;
0425 const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr;
0426 __le16 fctl;
0427 u16 phystat0;
0428 u16 phystat3;
0429 u16 chanstat;
0430 u16 mactime;
0431 u32 macstat;
0432 u16 chanid;
0433 u8 jssi;
0434 int padding;
0435
0436 memset(&status, 0, sizeof(status));
0437
0438
0439 phystat0 = le16_to_cpu(rxhdr->phy_status0);
0440 phystat3 = le16_to_cpu(rxhdr->phy_status3);
0441 jssi = rxhdr->jssi;
0442 macstat = le16_to_cpu(rxhdr->mac_status);
0443 mactime = le16_to_cpu(rxhdr->mac_time);
0444 chanstat = le16_to_cpu(rxhdr->channel);
0445
0446 if (macstat & B43legacy_RX_MAC_FCSERR)
0447 dev->wl->ieee_stats.dot11FCSErrorCount++;
0448
0449
0450 padding = (macstat & B43legacy_RX_MAC_PADDING) ? 2 : 0;
0451 if (unlikely(skb->len < (sizeof(struct b43legacy_plcp_hdr6) +
0452 padding))) {
0453 b43legacydbg(dev->wl, "RX: Packet size underrun (1)\n");
0454 goto drop;
0455 }
0456 plcp = (struct b43legacy_plcp_hdr6 *)(skb->data + padding);
0457 skb_pull(skb, sizeof(struct b43legacy_plcp_hdr6) + padding);
0458
0459 if (unlikely(skb->len < (2+2+6 + FCS_LEN))) {
0460 b43legacydbg(dev->wl, "RX: Packet size underrun (2)\n");
0461 goto drop;
0462 }
0463 wlhdr = (struct ieee80211_hdr *)(skb->data);
0464 fctl = wlhdr->frame_control;
0465
0466 if ((macstat & B43legacy_RX_MAC_DEC) &&
0467 !(macstat & B43legacy_RX_MAC_DECERR)) {
0468 unsigned int keyidx;
0469 int wlhdr_len;
0470 int iv_len;
0471 int icv_len;
0472
0473 keyidx = ((macstat & B43legacy_RX_MAC_KEYIDX)
0474 >> B43legacy_RX_MAC_KEYIDX_SHIFT);
0475
0476
0477
0478 keyidx = b43legacy_kidx_to_raw(dev, keyidx);
0479 B43legacy_WARN_ON(keyidx >= dev->max_nr_keys);
0480
0481 if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
0482
0483 B43legacy_WARN_ON(!ieee80211_has_protected(fctl));
0484 fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
0485 wlhdr->frame_control = fctl;
0486
0487 wlhdr_len = ieee80211_hdrlen(fctl);
0488 if (unlikely(skb->len < (wlhdr_len + 3))) {
0489 b43legacydbg(dev->wl, "RX: Packet size"
0490 " underrun3\n");
0491 goto drop;
0492 }
0493 if (skb->data[wlhdr_len + 3] & (1 << 5)) {
0494
0495
0496
0497 iv_len = 8;
0498 icv_len = 8;
0499 } else {
0500 iv_len = 4;
0501 icv_len = 4;
0502 }
0503 if (unlikely(skb->len < (wlhdr_len + iv_len +
0504 icv_len))) {
0505 b43legacydbg(dev->wl, "RX: Packet size"
0506 " underrun4\n");
0507 goto drop;
0508 }
0509
0510 memmove(skb->data + iv_len, skb->data, wlhdr_len);
0511 skb_pull(skb, iv_len);
0512
0513 skb_trim(skb, skb->len - icv_len);
0514
0515 status.flag |= RX_FLAG_DECRYPTED;
0516 }
0517 }
0518
0519 status.signal = b43legacy_rssi_postprocess(dev, jssi,
0520 (phystat0 & B43legacy_RX_PHYST0_OFDM),
0521 (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
0522 (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
0523
0524 if (phystat0 & B43legacy_RX_PHYST0_OFDM)
0525 status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
0526 else
0527 status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
0528 status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538 if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
0539 u16 low_mactime_now;
0540
0541 b43legacy_tsf_read(dev, &status.mactime);
0542 low_mactime_now = status.mactime;
0543 status.mactime = status.mactime & ~0xFFFFULL;
0544 status.mactime += mactime;
0545 if (low_mactime_now <= mactime)
0546 status.mactime -= 0x10000;
0547 status.flag |= RX_FLAG_MACTIME_START;
0548 }
0549
0550 chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
0551 B43legacy_RX_CHAN_ID_SHIFT;
0552 switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
0553 case B43legacy_PHYTYPE_B:
0554 case B43legacy_PHYTYPE_G:
0555 status.band = NL80211_BAND_2GHZ;
0556 status.freq = chanid + 2400;
0557 break;
0558 default:
0559 b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
0560 chanstat);
0561 goto drop;
0562 }
0563
0564 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
0565 ieee80211_rx_irqsafe(dev->wl->hw, skb);
0566
0567 return;
0568 drop:
0569 b43legacydbg(dev->wl, "RX: Packet dropped\n");
0570 dev_kfree_skb_any(skb);
0571 }
0572
0573 void b43legacy_handle_txstatus(struct b43legacy_wldev *dev,
0574 const struct b43legacy_txstatus *status)
0575 {
0576 b43legacy_debugfs_log_txstat(dev, status);
0577
0578 if (status->intermediate)
0579 return;
0580 if (status->for_ampdu)
0581 return;
0582 if (!status->acked)
0583 dev->wl->ieee_stats.dot11ACKFailureCount++;
0584 if (status->rts_count) {
0585 if (status->rts_count == 0xF)
0586 dev->wl->ieee_stats.dot11RTSFailureCount++;
0587 else
0588 dev->wl->ieee_stats.dot11RTSSuccessCount++;
0589 }
0590
0591 if (b43legacy_using_pio(dev))
0592 b43legacy_pio_handle_txstatus(dev, status);
0593 else
0594 b43legacy_dma_handle_txstatus(dev, status);
0595 }
0596
0597
0598 void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
0599 const struct b43legacy_hwtxstatus *hw)
0600 {
0601 struct b43legacy_txstatus status;
0602 u8 tmp;
0603
0604 status.cookie = le16_to_cpu(hw->cookie);
0605 status.seq = le16_to_cpu(hw->seq);
0606 status.phy_stat = hw->phy_stat;
0607 tmp = hw->count;
0608 status.frame_count = (tmp >> 4);
0609 status.rts_count = (tmp & 0x0F);
0610 tmp = hw->flags << 1;
0611 status.supp_reason = ((tmp & 0x1C) >> 2);
0612 status.pm_indicated = !!(tmp & 0x80);
0613 status.intermediate = !!(tmp & 0x40);
0614 status.for_ampdu = !!(tmp & 0x20);
0615 status.acked = !!(tmp & 0x02);
0616
0617 b43legacy_handle_txstatus(dev, &status);
0618 }
0619
0620
0621 void b43legacy_tx_suspend(struct b43legacy_wldev *dev)
0622 {
0623 if (b43legacy_using_pio(dev))
0624 b43legacy_pio_freeze_txqueues(dev);
0625 else
0626 b43legacy_dma_tx_suspend(dev);
0627 }
0628
0629
0630 void b43legacy_tx_resume(struct b43legacy_wldev *dev)
0631 {
0632 if (b43legacy_using_pio(dev))
0633 b43legacy_pio_thaw_txqueues(dev);
0634 else
0635 b43legacy_dma_tx_resume(dev);
0636 }
0637
0638
0639 void b43legacy_qos_init(struct b43legacy_wldev *dev)
0640 {
0641
0642
0643 return;
0644
0645 b43legacy_hf_write(dev, b43legacy_hf_read(dev) | B43legacy_HF_EDCF);
0646
0647 b43legacy_write16(dev, 0x688,
0648 b43legacy_read16(dev, 0x688) | 0x4);
0649
0650
0651
0652 }