if_iwn.c (252717) | if_iwn.c (252727) |
---|---|
1/*- 2 * Copyright (c) 2007-2009 3 * Damien Bergamini <damien.bergamini@free.fr> 4 * Copyright (c) 2008 5 * Benjamin Close <benjsc@FreeBSD.org> 6 * Copyright (c) 2008 Sam Leffler, Errno Consulting 7 * 8 * Permission to use, copy, modify, and distribute this software for any --- 10 unchanged lines hidden (view full) --- 19 */ 20 21/* 22 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network 23 * adapters. 24 */ 25 26#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2007-2009 3 * Damien Bergamini <damien.bergamini@free.fr> 4 * Copyright (c) 2008 5 * Benjamin Close <benjsc@FreeBSD.org> 6 * Copyright (c) 2008 Sam Leffler, Errno Consulting 7 * 8 * Permission to use, copy, modify, and distribute this software for any --- 10 unchanged lines hidden (view full) --- 19 */ 20 21/* 22 * Driver for Intel WiFi Link 4965 and 1000/5000/6000 Series 802.11 network 23 * adapters. 24 */ 25 26#include <sys/cdefs.h> |
27__FBSDID("$FreeBSD: head/sys/dev/iwn/if_iwn.c 252717 2013-07-04 19:45:34Z adrian $"); | 27__FBSDID("$FreeBSD: head/sys/dev/iwn/if_iwn.c 252727 2013-07-04 21:16:49Z adrian $"); |
28 29#include "opt_wlan.h" 30 31#include <sys/param.h> 32#include <sys/sockio.h> 33#include <sys/sysctl.h> 34#include <sys/mbuf.h> 35#include <sys/kernel.h> --- 294 unchanged lines hidden (view full) --- 330 IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */ 331 IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */ 332 IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ 333 IWN_DEBUG_INTR = 0x00000100, /* ISR */ 334 IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */ 335 IWN_DEBUG_NODE = 0x00000400, /* node management */ 336 IWN_DEBUG_LED = 0x00000800, /* led management */ 337 IWN_DEBUG_CMD = 0x00001000, /* cmd submission */ | 28 29#include "opt_wlan.h" 30 31#include <sys/param.h> 32#include <sys/sockio.h> 33#include <sys/sysctl.h> 34#include <sys/mbuf.h> 35#include <sys/kernel.h> --- 294 unchanged lines hidden (view full) --- 330 IWN_DEBUG_OPS = 0x00000020, /* iwn_ops processing */ 331 IWN_DEBUG_BEACON = 0x00000040, /* beacon handling */ 332 IWN_DEBUG_WATCHDOG = 0x00000080, /* watchdog timeout */ 333 IWN_DEBUG_INTR = 0x00000100, /* ISR */ 334 IWN_DEBUG_CALIBRATE = 0x00000200, /* periodic calibration */ 335 IWN_DEBUG_NODE = 0x00000400, /* node management */ 336 IWN_DEBUG_LED = 0x00000800, /* led management */ 337 IWN_DEBUG_CMD = 0x00001000, /* cmd submission */ |
338 IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */ 339 IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */ |
|
338 IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ 339 IWN_DEBUG_ANY = 0xffffffff 340}; 341 342#define DPRINTF(sc, m, fmt, ...) do { \ 343 if (sc->sc_debug & (m)) \ 344 printf(fmt, __VA_ARGS__); \ 345} while (0) --- 1747 unchanged lines hidden (view full) --- 2093 case 2: return 10; 2094 case 4: return 20; 2095 case 11: return 55; 2096 case 22: return 110; 2097 } 2098 return 0; 2099} 2100 | 340 IWN_DEBUG_FATAL = 0x80000000, /* fatal errors */ 341 IWN_DEBUG_ANY = 0xffffffff 342}; 343 344#define DPRINTF(sc, m, fmt, ...) do { \ 345 if (sc->sc_debug & (m)) \ 346 printf(fmt, __VA_ARGS__); \ 347} while (0) --- 1747 unchanged lines hidden (view full) --- 2095 case 2: return 10; 2096 case 4: return 20; 2097 case 11: return 55; 2098 case 22: return 110; 2099 } 2100 return 0; 2101} 2102 |
2101static void 2102iwn_newassoc(struct ieee80211_node *ni, int isnew) | 2103/* 2104 * Calculate the required PLCP value from the given rate, 2105 * to the given node. 2106 * 2107 * This will take the node configuration (eg 11n, rate table 2108 * setup, etc) into consideration. 2109 */ 2110static uint32_t 2111iwn_rate_to_plcp(struct iwn_softc *sc, struct ieee80211_node *ni, 2112 uint8_t rate) |
2103{ 2104#define RV(v) ((v) & IEEE80211_RATE_VAL) 2105 struct ieee80211com *ic = ni->ni_ic; | 2113{ 2114#define RV(v) ((v) & IEEE80211_RATE_VAL) 2115 struct ieee80211com *ic = ni->ni_ic; |
2106 struct iwn_softc *sc = ic->ic_ifp->if_softc; 2107 struct iwn_node *wn = (void *)ni; | |
2108 uint8_t txant1, txant2; | 2116 uint8_t txant1, txant2; |
2109 int i, plcp, rate, ridx; | 2117 uint32_t plcp = 0; 2118 int ridx; |
2110 2111 /* Use the first valid TX antenna. */ 2112 txant1 = IWN_LSB(sc->txchainmask); 2113 txant2 = IWN_LSB(sc->txchainmask & ~txant1); 2114 | 2119 2120 /* Use the first valid TX antenna. */ 2121 txant1 = IWN_LSB(sc->txchainmask); 2122 txant2 = IWN_LSB(sc->txchainmask & ~txant1); 2123 |
2124 /* 2125 * If it's an MCS rate, let's set the plcp correctly 2126 * and set the relevant flags based on the node config. 2127 */ |
|
2115 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { | 2128 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) { |
2116 ridx = ni->ni_rates.rs_nrates - 1; 2117 for (i = ni->ni_htrates.rs_nrates - 1; i >= 0; i--) { 2118 plcp = RV(ni->ni_htrates.rs_rates[i]) | IWN_RFLAG_MCS; 2119 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { 2120 plcp |= IWN_RFLAG_HT40; 2121 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 2122 plcp |= IWN_RFLAG_SGI; 2123 } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) | 2129 /* 2130 * Set the initial PLCP value to be between 0->31 for 2131 * MCS 0 -> MCS 31, then set the "I'm an MCS rate!" 2132 * flag. 2133 */ 2134 plcp = RV(rate) | IWN_RFLAG_MCS; 2135 2136 /* 2137 * XXX the following should only occur if both 2138 * the local configuration _and_ the remote node 2139 * advertise these capabilities. Thus this code 2140 * may need fixing! 2141 */ 2142 2143 /* 2144 * Set the channel width and guard interval. 2145 */ 2146 if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { 2147 plcp |= IWN_RFLAG_HT40; 2148 if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) |
2124 plcp |= IWN_RFLAG_SGI; | 2149 plcp |= IWN_RFLAG_SGI; |
2125 if (RV(ni->ni_htrates.rs_rates[i]) > 7) 2126 plcp |= IWN_RFLAG_ANT(txant1 | txant2); 2127 else 2128 plcp |= IWN_RFLAG_ANT(txant1); 2129 if (ridx >= 0) { 2130 rate = RV(ni->ni_rates.rs_rates[ridx]); 2131 wn->ridx[rate] = plcp; 2132 } 2133 wn->ridx[IEEE80211_RATE_MCS | i] = plcp; 2134 ridx--; | 2150 } else if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) { 2151 plcp |= IWN_RFLAG_SGI; |
2135 } | 2152 } |
2136 } else { 2137 for (i = 0; i < ni->ni_rates.rs_nrates; i++) { 2138 rate = RV(ni->ni_rates.rs_rates[i]); 2139 plcp = rate2plcp(rate); 2140 ridx = ic->ic_rt->rateCodeToIndex[rate]; 2141 if (ridx < IWN_RIDX_OFDM6 && 2142 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 2143 plcp |= IWN_RFLAG_CCK; | 2153 2154 /* 2155 * If it's a two stream rate, enable TX on both 2156 * antennas. 2157 * 2158 * XXX three stream rates? 2159 */ 2160 if (rate > 0x87) 2161 plcp |= IWN_RFLAG_ANT(txant1 | txant2); 2162 else |
2144 plcp |= IWN_RFLAG_ANT(txant1); | 2163 plcp |= IWN_RFLAG_ANT(txant1); |
2145 wn->ridx[rate] = htole32(plcp); 2146 } | 2164 } else { 2165 /* 2166 * Set the initial PLCP - fine for both 2167 * OFDM and CCK rates. 2168 */ 2169 plcp = rate2plcp(rate); 2170 2171 /* Set CCK flag if it's CCK */ 2172 2173 /* XXX It would be nice to have a method 2174 * to map the ridx -> phy table entry 2175 * so we could just query that, rather than 2176 * this hack to check against IWN_RIDX_OFDM6. 2177 */ 2178 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 2179 rate & IEEE80211_RATE_VAL); 2180 if (ridx < IWN_RIDX_OFDM6 && 2181 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 2182 plcp |= IWN_RFLAG_CCK; 2183 2184 /* Set antenna configuration */ 2185 plcp |= IWN_RFLAG_ANT(txant1); |
2147 } | 2186 } |
2187 2188 DPRINTF(sc, IWN_DEBUG_TXRATE, "%s: rate=0x%02x, plcp=0x%08x\n", 2189 __func__, 2190 rate, 2191 plcp); 2192 2193 return (htole32(plcp)); |
|
2148#undef RV 2149} 2150 | 2194#undef RV 2195} 2196 |
2197static void 2198iwn_newassoc(struct ieee80211_node *ni, int isnew) 2199{ 2200 /* Doesn't do anything at the moment */ 2201} 2202 |
|
2151static int 2152iwn_media_change(struct ifnet *ifp) 2153{ 2154 int error; 2155 2156 error = ieee80211_media_change(ifp); 2157 /* NB: only the fixed rate can change and that doesn't need a reset */ 2158 return (error == ENETRESET ? 0 : error); --- 1237 unchanged lines hidden (view full) --- 3396 rate = tp->mcastrate; 3397 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 3398 rate = tp->ucastrate; 3399 else { 3400 /* XXX pass pktlen */ 3401 (void) ieee80211_ratectl_rate(ni, NULL, 0); 3402 rate = ni->ni_txrate; 3403 } | 2203static int 2204iwn_media_change(struct ifnet *ifp) 2205{ 2206 int error; 2207 2208 error = ieee80211_media_change(ifp); 2209 /* NB: only the fixed rate can change and that doesn't need a reset */ 2210 return (error == ENETRESET ? 0 : error); --- 1237 unchanged lines hidden (view full) --- 3448 rate = tp->mcastrate; 3449 else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) 3450 rate = tp->ucastrate; 3451 else { 3452 /* XXX pass pktlen */ 3453 (void) ieee80211_ratectl_rate(ni, NULL, 0); 3454 rate = ni->ni_txrate; 3455 } |
3404 ridx = ic->ic_rt->rateCodeToIndex[rate]; | 3456 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 3457 rate & IEEE80211_RATE_VAL); |
3405 3406 /* Encrypt the frame if need be. */ 3407 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3408 /* Retrieve key for TX. */ 3409 k = ieee80211_crypto_encap(ni, m); 3410 if (k == NULL) { 3411 m_freem(m); 3412 return ENOBUFS; --- 89 unchanged lines hidden (view full) --- 3502 } else 3503 pad = 0; 3504 3505 tx->len = htole16(totlen); 3506 tx->tid = tid; 3507 tx->rts_ntries = 60; 3508 tx->data_ntries = 15; 3509 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); | 3458 3459 /* Encrypt the frame if need be. */ 3460 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 3461 /* Retrieve key for TX. */ 3462 k = ieee80211_crypto_encap(ni, m); 3463 if (k == NULL) { 3464 m_freem(m); 3465 return ENOBUFS; --- 89 unchanged lines hidden (view full) --- 3555 } else 3556 pad = 0; 3557 3558 tx->len = htole16(totlen); 3559 tx->tid = tid; 3560 tx->rts_ntries = 60; 3561 tx->data_ntries = 15; 3562 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); |
3510 tx->rate = wn->ridx[rate]; | 3563 tx->rate = iwn_rate_to_plcp(sc, ni, rate); |
3511 if (tx->id == sc->broadcast_id) { 3512 /* Group or management frame. */ 3513 tx->linkq = 0; 3514 /* XXX Alternate between antenna A and B? */ 3515 txant = IWN_LSB(sc->txchainmask); 3516 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); 3517 } else { 3518 tx->linkq = ni->ni_rates.rs_nrates - ridx - 1; --- 114 unchanged lines hidden (view full) --- 3633 ac = params->ibp_pri & 3; 3634 3635 ring = &sc->txq[ac]; 3636 desc = &ring->desc[ring->cur]; 3637 data = &ring->data[ring->cur]; 3638 3639 /* Choose a TX rate index. */ 3640 rate = params->ibp_rate0; | 3564 if (tx->id == sc->broadcast_id) { 3565 /* Group or management frame. */ 3566 tx->linkq = 0; 3567 /* XXX Alternate between antenna A and B? */ 3568 txant = IWN_LSB(sc->txchainmask); 3569 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); 3570 } else { 3571 tx->linkq = ni->ni_rates.rs_nrates - ridx - 1; --- 114 unchanged lines hidden (view full) --- 3686 ac = params->ibp_pri & 3; 3687 3688 ring = &sc->txq[ac]; 3689 desc = &ring->desc[ring->cur]; 3690 data = &ring->data[ring->cur]; 3691 3692 /* Choose a TX rate index. */ 3693 rate = params->ibp_rate0; |
3641 ridx = ic->ic_rt->rateCodeToIndex[rate]; | 3694 ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 3695 rate & IEEE80211_RATE_VAL); |
3642 if (ridx == (uint8_t)-1) { 3643 /* XXX fall back to mcast/mgmt rate? */ 3644 m_freem(m); 3645 return EINVAL; 3646 } 3647 3648 totlen = m->m_pkthdr.len; 3649 --- 59 unchanged lines hidden (view full) --- 3709 } 3710 3711 tx->len = htole16(totlen); 3712 tx->tid = 0; 3713 tx->id = sc->broadcast_id; 3714 tx->rts_ntries = params->ibp_try1; 3715 tx->data_ntries = params->ibp_try0; 3716 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); | 3696 if (ridx == (uint8_t)-1) { 3697 /* XXX fall back to mcast/mgmt rate? */ 3698 m_freem(m); 3699 return EINVAL; 3700 } 3701 3702 totlen = m->m_pkthdr.len; 3703 --- 59 unchanged lines hidden (view full) --- 3763 } 3764 3765 tx->len = htole16(totlen); 3766 tx->tid = 0; 3767 tx->id = sc->broadcast_id; 3768 tx->rts_ntries = params->ibp_try1; 3769 tx->data_ntries = params->ibp_try0; 3770 tx->lifetime = htole32(IWN_LIFETIME_INFINITE); |
3771 3772 /* XXX should just use iwn_rate_to_plcp() */ |
|
3717 tx->rate = htole32(rate2plcp(rate)); 3718 if (ridx < IWN_RIDX_OFDM6 && 3719 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 3720 tx->rate |= htole32(IWN_RFLAG_CCK); | 3773 tx->rate = htole32(rate2plcp(rate)); 3774 if (ridx < IWN_RIDX_OFDM6 && 3775 IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) 3776 tx->rate |= htole32(IWN_RFLAG_CCK); |
3777 |
|
3721 /* Group or management frame. */ 3722 tx->linkq = 0; 3723 txant = IWN_LSB(sc->txchainmask); 3724 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); | 3778 /* Group or management frame. */ 3779 tx->linkq = 0; 3780 txant = IWN_LSB(sc->txchainmask); 3781 tx->rate |= htole32(IWN_RFLAG_ANT(txant)); |
3782 |
|
3725 /* Set physical address of "scratch area". */ 3726 tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); 3727 tx->hiaddr = IWN_HIADDR(data->scratch_paddr); 3728 3729 /* Copy 802.11 header in TX command. */ 3730 memcpy((uint8_t *)(tx + 1), wh, hdrlen); 3731 3732 /* Trim 802.11 header. */ --- 339 unchanged lines hidden (view full) --- 4072 linkq.ampdu_limit = htole16(4000); /* 4ms */ 4073 4074 /* Start at highest available bit-rate. */ 4075 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4076 txrate = ni->ni_htrates.rs_nrates - 1; 4077 else 4078 txrate = rs->rs_nrates - 1; 4079 for (i = 0; i < IWN_MAX_TX_RETRIES; i++) { | 3783 /* Set physical address of "scratch area". */ 3784 tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); 3785 tx->hiaddr = IWN_HIADDR(data->scratch_paddr); 3786 3787 /* Copy 802.11 header in TX command. */ 3788 memcpy((uint8_t *)(tx + 1), wh, hdrlen); 3789 3790 /* Trim 802.11 header. */ --- 339 unchanged lines hidden (view full) --- 4130 linkq.ampdu_limit = htole16(4000); /* 4ms */ 4131 4132 /* Start at highest available bit-rate. */ 4133 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4134 txrate = ni->ni_htrates.rs_nrates - 1; 4135 else 4136 txrate = rs->rs_nrates - 1; 4137 for (i = 0; i < IWN_MAX_TX_RETRIES; i++) { |
4138 uint32_t plcp; 4139 |
|
4080 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4081 rate = IEEE80211_RATE_MCS | txrate; 4082 else 4083 rate = RV(rs->rs_rates[txrate]); | 4140 if (IEEE80211_IS_CHAN_HT(ni->ni_chan)) 4141 rate = IEEE80211_RATE_MCS | txrate; 4142 else 4143 rate = RV(rs->rs_rates[txrate]); |
4084 linkq.retry[i] = wn->ridx[rate]; | |
4085 | 4144 |
4086 if ((le32toh(wn->ridx[rate]) & IWN_RFLAG_MCS) && 4087 RV(le32toh(wn->ridx[rate])) > 7) | 4145 /* Do rate -> PLCP config mapping */ 4146 plcp = iwn_rate_to_plcp(sc, ni, rate); 4147 linkq.retry[i] = plcp; 4148 4149 /* Special case for dual-stream rates? */ 4150 if ((le32toh(plcp) & IWN_RFLAG_MCS) && 4151 RV(le32toh(plcp)) > 7) |
4088 linkq.mimo = i + 1; 4089 4090 /* Next retry at immediate lower bit-rate. */ 4091 if (txrate > 0) 4092 txrate--; 4093 } 4094 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, 1); 4095#undef RV --- 839 unchanged lines hidden (view full) --- 4935iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async) 4936{ 4937 struct iwn_pmgt_cmd cmd; 4938 const struct iwn_pmgt *pmgt; 4939 uint32_t max, skip_dtim; 4940 uint32_t reg; 4941 int i; 4942 | 4152 linkq.mimo = i + 1; 4153 4154 /* Next retry at immediate lower bit-rate. */ 4155 if (txrate > 0) 4156 txrate--; 4157 } 4158 return iwn_cmd(sc, IWN_CMD_LINK_QUALITY, &linkq, sizeof linkq, 1); 4159#undef RV --- 839 unchanged lines hidden (view full) --- 4999iwn_set_pslevel(struct iwn_softc *sc, int dtim, int level, int async) 5000{ 5001 struct iwn_pmgt_cmd cmd; 5002 const struct iwn_pmgt *pmgt; 5003 uint32_t max, skip_dtim; 5004 uint32_t reg; 5005 int i; 5006 |
5007 DPRINTF(sc, IWN_DEBUG_PWRSAVE, 5008 "%s: dtim=%d, level=%d, async=%d\n", 5009 __func__, 5010 dtim, 5011 level, 5012 async); 5013 |
|
4943 /* Select which PS parameters to use. */ 4944 if (dtim <= 2) 4945 pmgt = &iwn_pmgt[0][level]; 4946 else if (dtim <= 10) 4947 pmgt = &iwn_pmgt[1][level]; 4948 else 4949 pmgt = &iwn_pmgt[2][level]; 4950 --- 2153 unchanged lines hidden --- | 5014 /* Select which PS parameters to use. */ 5015 if (dtim <= 2) 5016 pmgt = &iwn_pmgt[0][level]; 5017 else if (dtim <= 10) 5018 pmgt = &iwn_pmgt[1][level]; 5019 else 5020 pmgt = &iwn_pmgt[2][level]; 5021 --- 2153 unchanged lines hidden --- |