Module Name: src Committed By: mlelstv Date: Wed Jul 19 16:55:12 UTC 2017
Modified Files: src/sys/dev/pci: if_iwn.c if_iwnreg.h if_iwnvar.h Log Message: Pull in some hardware support from FreeBSD. Also fix 5GHz mode by adapting the method described in: https://forums.freebsd.org/threads/53574/. To generate a diff of this commit: cvs rdiff -u -r1.84 -r1.85 src/sys/dev/pci/if_iwn.c cvs rdiff -u -r1.16 -r1.17 src/sys/dev/pci/if_iwnreg.h cvs rdiff -u -r1.19 -r1.20 src/sys/dev/pci/if_iwnvar.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/if_iwn.c diff -u src/sys/dev/pci/if_iwn.c:1.84 src/sys/dev/pci/if_iwn.c:1.85 --- src/sys/dev/pci/if_iwn.c:1.84 Thu Feb 2 10:05:35 2017 +++ src/sys/dev/pci/if_iwn.c Wed Jul 19 16:55:12 2017 @@ -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 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 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 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, en 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, en 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, en 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 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 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 *s 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 * 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 * } 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; Index: src/sys/dev/pci/if_iwnreg.h diff -u src/sys/dev/pci/if_iwnreg.h:1.16 src/sys/dev/pci/if_iwnreg.h:1.17 --- src/sys/dev/pci/if_iwnreg.h:1.16 Sat Mar 11 21:23:36 2017 +++ src/sys/dev/pci/if_iwnreg.h Wed Jul 19 16:55:12 2017 @@ -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_limi 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_limi 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_limi 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_limi 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_limi 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_limi 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. */ Index: src/sys/dev/pci/if_iwnvar.h diff -u src/sys/dev/pci/if_iwnvar.h:1.19 src/sys/dev/pci/if_iwnvar.h:1.20 --- src/sys/dev/pci/if_iwnvar.h:1.19 Thu Feb 2 10:05:35 2017 +++ src/sys/dev/pci/if_iwnvar.h Wed Jul 19 16:55:12 2017 @@ -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 */ };