Deleted Added
full compact
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 */
338 IWN_DEBUG_TXRATE = 0x00002000, /* TX rate debugging */
339 IWN_DEBUG_PWRSAVE = 0x00004000, /* Power save operations */
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)
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;
2116 uint8_t txant1, txant2;
2109 int i, plcp, rate, ridx;
2117 uint32_t plcp = 0;
2118 int ridx;
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 */
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)
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;
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
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);
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));
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
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);
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);
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);
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() */
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
3778 /* Group or management frame. */
3779 tx->linkq = 0;
3780 txant = IWN_LSB(sc->txchainmask);
3781 tx->rate |= htole32(IWN_RFLAG_ANT(txant));
3782
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
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];
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)
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
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 ---