Pull in some hardware support from FreeBSD. Also fix 5GHz mode by

adapting the method described in: https://forums.freebsd.org/threads/53574/.
This commit is contained in:
mlelstv 2017-07-19 16:55:12 +00:00
parent fbbc1f22f4
commit b5afb4ec18
3 changed files with 130 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_iwn.c,v 1.84 2017/02/02 10:05:35 nonaka Exp $ */
/* $NetBSD: if_iwn.c,v 1.85 2017/07/19 16:55:12 mlelstv Exp $ */
/* $OpenBSD: if_iwn.c,v 1.135 2014/09/10 07:22:09 dcoppa Exp $ */
/*-
@ -22,7 +22,7 @@
* adapters.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.84 2017/02/02 10:05:35 nonaka Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_iwn.c,v 1.85 2017/07/19 16:55:12 mlelstv Exp $");
#define IWN_USE_RBUF /* Use local storage for RX */
#undef IWN_HWCRYPTO /* XXX does not even compile yet */
@ -790,7 +790,7 @@ iwn5000_attach(struct iwn_softc *sc, pci_product_id_t pid)
sc->fwname = "iwlwifi-6000g2a-5.ucode";
break;
case IWN_HW_REV_TYPE_2030:
sc->limits = &iwn2000_sensitivity_limits;
sc->limits = &iwn2030_sensitivity_limits;
sc->fwname = "iwlwifi-2030-6.ucode";
ops->config_bt_coex = iwn_config_bt_coex_adv2;
break;
@ -1781,6 +1781,7 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
struct iwn_eeprom_enhinfo enhinfo[35];
uint16_t val, base;
int8_t maxpwr;
uint8_t flags;
int i;
iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
@ -1790,7 +1791,8 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
memset(sc->enh_maxpwr, 0, sizeof sc->enh_maxpwr);
for (i = 0; i < __arraycount(enhinfo); i++) {
if (enhinfo[i].chan == 0 || enhinfo[i].reserved != 0)
flags = enhinfo[i].flags;
if (!(flags & IWN_ENHINFO_VALID))
continue; /* Skip invalid entries. */
maxpwr = 0;
@ -1915,6 +1917,10 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
sc->calib.state = IWN_CALIB_STATE_INIT;
/* Wait until we hear a beacon before we transmit */
if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))
sc->sc_beacon_wait = 1;
if ((error = iwn_auth(sc)) != 0) {
aprint_error_dev(sc->sc_dev,
"could not move to auth state\n");
@ -1923,6 +1929,18 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
break;
case IEEE80211_S_RUN:
/*
* RUN -> RUN transition; Just restart timers.
*/
if (ic->ic_state == IEEE80211_S_RUN) {
sc->calib_cnt = 0;
break;
}
/* Wait until we hear a beacon before we transmit */
if (IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan))
sc->sc_beacon_wait = 1;
if ((error = iwn_run(sc)) != 0) {
aprint_error_dev(sc->sc_dev,
"could not move to run state\n");
@ -1933,6 +1951,13 @@ iwn_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_S_INIT:
sc->sc_flags &= ~IWN_FLAG_SCANNING;
sc->calib.state = IWN_CALIB_STATE_INIT;
/*
* Purge the xmit queue so we don't have old frames
* during a new association attempt.
*/
sc->sc_beacon_wait = 0;
ifp->if_flags &= ~IFF_OACTIVE;
iwn_start(ifp);
break;
}
@ -2154,6 +2179,25 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
}
/*
* If it's a beacon and we're waiting, then do the wakeup.
*/
if (sc->sc_beacon_wait) {
uint8_t type, subtype;
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
/*
* This assumes at this point we've received our own
* beacon.
*/
if (type == IEEE80211_FC0_TYPE_MGT &&
subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
sc->sc_beacon_wait = 0;
ifp->if_flags &= ~IFF_OACTIVE;
iwn_start(ifp);
}
}
/* Send the frame to the 802.11 layer. */
ieee80211_input(ic, m, ni, rssi, 0);
@ -3142,6 +3186,11 @@ iwn_start(struct ifnet *ifp)
return;
for (;;) {
if (sc->sc_beacon_wait == 1) {
ifp->if_flags |= IFF_OACTIVE;
break;
}
if (sc->qfullmsk != 0) {
ifp->if_flags |= IFF_OACTIVE;
break;
@ -3184,7 +3233,8 @@ iwn_start(struct ifnet *ifp)
ac = (eh->ether_type != htons(ETHERTYPE_PAE)) ?
M_WME_GETAC(m) : WME_AC_BE;
bpf_mtap(ifp, m);
if (sc->sc_beacon_wait == 0)
bpf_mtap(ifp, m);
if ((m = ieee80211_encap(ic, m, ni)) == NULL) {
ieee80211_free_node(ni);
@ -3192,6 +3242,9 @@ iwn_start(struct ifnet *ifp)
continue;
}
sendit:
if (sc->sc_beacon_wait)
continue;
bpf_mtap3(ic->ic_rawbpf, m);
if (iwn_tx(sc, m, ni, ac) != 0) {
@ -3203,6 +3256,9 @@ sendit:
sc->sc_tx_timer = 5;
ifp->if_timer = 1;
}
if (sc->sc_beacon_wait > 1)
sc->sc_beacon_wait = 0;
}
static void
@ -3695,6 +3751,7 @@ static int
iwn5000_set_txpower(struct iwn_softc *sc, int async)
{
struct iwn5000_cmd_txpower cmd;
int cmdid;
/*
* TX power calibration is handled automatically by the firmware
@ -3705,7 +3762,11 @@ iwn5000_set_txpower(struct iwn_softc *sc, int async)
cmd.flags = IWN5000_TXPOWER_NO_CLOSED;
cmd.srv_limit = IWN5000_TXPOWER_AUTO;
DPRINTF(("setting TX power\n"));
return iwn_cmd(sc, IWN_CMD_TXPOWER_DBM, &cmd, sizeof cmd, async);
if (IWN_UCODE_API(sc->ucode_rev) == 1)
cmdid = IWN_CMD_TXPOWER_DBM_V1;
else
cmdid = IWN_CMD_TXPOWER_DBM;
return iwn_cmd(sc, cmdid, &cmd, sizeof cmd, async);
}
/*
@ -4166,7 +4227,7 @@ iwn_send_sensitivity(struct iwn_softc *sc)
cmd.energy_cck = htole16(calib->energy_cck);
/* Barker modulation: use default values. */
cmd.corr_barker = htole16(190);
cmd.corr_barker_mrc = htole16(390);
cmd.corr_barker_mrc = htole16(sc->limits->barker_mrc);
if (!(sc->sc_flags & IWN_FLAG_ENH_SENS))
goto send;
/* Enhanced sensitivity settings. */
@ -5677,6 +5738,8 @@ iwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw)
ptr = (const uint32_t *)fw->data;
rev = le32toh(*ptr++);
sc->ucode_rev = rev;
/* Check firmware API version. */
if (IWN_FW_API(rev) <= 1) {
aprint_error_dev(sc->sc_dev,
@ -5742,6 +5805,7 @@ iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw,
}
DPRINTF(("FW: \"%.64s\", build 0x%x\n", hdr->descr,
le32toh(hdr->build)));
sc->ucode_rev = le32toh(hdr->rev);
/*
* Select the closest supported alternative that is less than
@ -6330,6 +6394,8 @@ iwn_init(struct ifnet *ifp)
goto fail;
}
sc->sc_beacon_wait = 0;
ifp->if_flags &= ~IFF_OACTIVE;
ifp->if_flags |= IFF_RUNNING;

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_iwnreg.h,v 1.16 2017/03/11 21:23:36 maya Exp $ */
/* $NetBSD: if_iwnreg.h,v 1.17 2017/07/19 16:55:12 mlelstv Exp $ */
/* $OpenBSD: if_iwnreg.h,v 1.49 2014/09/09 18:56:24 sthen Exp $ */
/*-
@ -440,6 +440,7 @@ struct iwn_tx_cmd {
#define IWN_CMD_TXPOWER_DBM 149
#define IWN_CMD_TXPOWER 151
#define IWN5000_CMD_TX_ANT_CONFIG 152
#define IWN_CMD_TXPOWER_DBM_V1 152
#define IWN_CMD_BT_COEX 155
#define IWN_CMD_GET_STATISTICS 156
#define IWN_CMD_SET_CRITICAL_TEMP 164
@ -1594,7 +1595,17 @@ struct iwn_eeprom_chan {
} __packed;
struct iwn_eeprom_enhinfo {
uint16_t chan;
uint8_t flags;
#define IWN_ENHINFO_VALID (1 << 0)
#define IWN_ENHINFO_5GHZ (1 << 1)
#define IWN_ENHINFO_OFDM (1 << 2)
#define IWN_ENHINFO_HT40 (1 << 3)
#define IWN_ENHINFO_HTAP (1 << 4)
#define IWN_ENHINFO_RES1 (1 << 5)
#define IWN_ENHINFO_RES2 (1 << 6)
#define IWN_ENHINFO_COMMON (1 << 7)
uint8_t chan;
int8_t chain[3]; /* max power in half-dBm */
uint8_t reserved;
int8_t mimo2; /* max power in half-dBm */
@ -1813,6 +1824,7 @@ struct iwn_sensitivity_limits {
uint32_t min_energy_cck;
uint32_t energy_cck;
uint32_t energy_ofdm;
uint32_t barker_mrc;
};
/*
@ -1827,7 +1839,8 @@ static const struct iwn_sensitivity_limits iwn4965_sensitivity_limits = {
200, 400,
97,
100,
100
100,
390
};
static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {
@ -1839,7 +1852,8 @@ static const struct iwn_sensitivity_limits iwn5000_sensitivity_limits = {
170, 400,
95,
95,
95
95,
390
};
static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {
@ -1851,7 +1865,8 @@ static const struct iwn_sensitivity_limits iwn5150_sensitivity_limits = {
170, 400,
95,
95,
95
95,
390
};
static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {
@ -1863,7 +1878,8 @@ static const struct iwn_sensitivity_limits iwn1000_sensitivity_limits = {
170, 400,
95,
95,
95
95,
390
};
static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
@ -1875,7 +1891,21 @@ static const struct iwn_sensitivity_limits iwn6000_sensitivity_limits = {
160, 310,
97,
97,
100
100,
390
};
static const struct iwn_sensitivity_limits iwn6235_sensitivity_limits = {
105, 110,
192, 232,
80, 145,
128, 232,
125, 175,
160, 310,
100,
110,
110,
336
};
static const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = {
@ -1887,7 +1917,21 @@ static const struct iwn_sensitivity_limits iwn2000_sensitivity_limits = {
160, 310,
97,
97,
100
100,
336
};
static const struct iwn_sensitivity_limits iwn2030_sensitivity_limits = {
105,110,
128,232,
80,145,
128,232,
125,175,
160,310,
97,
97,
110,
390
};
/* Map TID to TX scheduler's FIFO. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_iwnvar.h,v 1.19 2017/02/02 10:05:35 nonaka Exp $ */
/* $NetBSD: if_iwnvar.h,v 1.20 2017/07/19 16:55:12 mlelstv Exp $ */
/* $OpenBSD: if_iwnvar.h,v 1.28 2014/09/09 18:55:08 sthen Exp $ */
/*-
@ -338,7 +338,11 @@ struct iwn_softc {
#define sc_txtap sc_txtapu.th
int sc_txtap_len;
#define IWN_UCODE_API(ver) (((ver) & 0x0000ff00) >> 8)
uint32_t ucode_rev;
kmutex_t sc_mtx; /* mutex for init/stop */
int sc_beacon_wait; /* defer/skip sending */
};