Deleted Added
full compact
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 ---