From 4e5a521c2adf5efa14b277e53ddfaf0fa0ea61a5 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 8 Jan 2019 20:54:21 -0500 Subject: [PATCH] iprowifi4965: Upgrade to FreeBSD 12. Tested on a ThinkPad T61. --- .../kernel/drivers/network/wlan/Jamfile | 4 +- .../wlan/iprowifi4965/dev/iwn/if_iwn.c | 902 +++++++++--------- .../iprowifi4965/dev/iwn/if_iwn_chip_cfg.h | 2 +- .../wlan/iprowifi4965/dev/iwn/if_iwn_debug.h | 4 +- .../wlan/iprowifi4965/dev/iwn/if_iwn_devid.h | 2 +- .../wlan/iprowifi4965/dev/iwn/if_iwn_ioctl.h | 2 +- .../wlan/iprowifi4965/dev/iwn/if_iwnreg.h | 40 +- .../wlan/iprowifi4965/dev/iwn/if_iwnvar.h | 19 +- 8 files changed, 503 insertions(+), 472 deletions(-) diff --git a/src/add-ons/kernel/drivers/network/wlan/Jamfile b/src/add-ons/kernel/drivers/network/wlan/Jamfile index d29532544e..5478113968 100644 --- a/src/add-ons/kernel/drivers/network/wlan/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/Jamfile @@ -1,11 +1,9 @@ SubDir HAIKU_TOP src add-ons kernel drivers network wlan ; # FreeBSD 11.1 drivers -SubInclude HAIKU_TOP src add-ons kernel drivers network wlan atheroswifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan broadcom43xx ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2100 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi3945 ; -SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8335 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8363 ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ; @@ -16,5 +14,7 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network wlan wavelanwifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi2200 ; # FreeBSD 12 drivers +SubInclude HAIKU_TOP src add-ons kernel drivers network wlan atheroswifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan aironetwifi ; SubInclude HAIKU_TOP src add-ons kernel drivers network wlan idualwifi7260 ; +SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c index 54576cba13..62adfb428c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn.c @@ -25,7 +25,7 @@ */ #include -__FBSDID("$FreeBSD$"); +__FBSDID("$FreeBSD: releng/12.0/sys/dev/iwn/if_iwn.c 338949 2018-09-26 17:12:30Z imp $"); #include #include @@ -193,16 +193,13 @@ static void iwn_newassoc(struct ieee80211_node *, int); static int iwn_media_change(struct ifnet *); static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void iwn_calib_timeout(void *); -static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *, - struct iwn_rx_data *); +static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); -static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *, - struct iwn_rx_data *); +static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *); static void iwn5000_rx_calib_results(struct iwn_softc *, - struct iwn_rx_desc *, struct iwn_rx_data *); -static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *, - struct iwn_rx_data *); + struct iwn_rx_desc *); +static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *); static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, @@ -214,7 +211,7 @@ static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, int, static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_notif_intr(struct iwn_softc *); static void iwn_wakeup_intr(struct iwn_softc *); -static void iwn_rftoggle_intr(struct iwn_softc *); +static void iwn_rftoggle_task(void *, int); static void iwn_fatal_intr(struct iwn_softc *); static void iwn_intr(void *); static void iwn4965_update_sched(struct iwn_softc *, int, int, uint8_t, @@ -229,6 +226,8 @@ static int iwn_tx_data(struct iwn_softc *, struct mbuf *, static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *, struct ieee80211_node *, const struct ieee80211_bpf_params *params); +static int iwn_tx_cmd(struct iwn_softc *, struct mbuf *, + struct ieee80211_node *, struct iwn_tx_ring *); static void iwn_xmit_task(void *arg0, int pending); static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); @@ -246,15 +245,15 @@ static int iwn_set_link_quality(struct iwn_softc *, struct ieee80211_node *); static int iwn_add_broadcast_node(struct iwn_softc *, int); static int iwn_updateedca(struct ieee80211com *); +static void iwn_set_promisc(struct iwn_softc *); +static void iwn_update_promisc(struct ieee80211com *); static void iwn_update_mcast(struct ieee80211com *); static void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t); static int iwn_set_critical_temp(struct iwn_softc *); static int iwn_set_timing(struct iwn_softc *, struct ieee80211_node *); static void iwn4965_power_calibration(struct iwn_softc *, int); -static int iwn4965_set_txpower(struct iwn_softc *, - struct ieee80211_channel *, int); -static int iwn5000_set_txpower(struct iwn_softc *, - struct ieee80211_channel *, int); +static int iwn4965_set_txpower(struct iwn_softc *, int); +static int iwn5000_set_txpower(struct iwn_softc *, int); static int iwn4965_get_rssi(struct iwn_softc *, struct iwn_rx_stat *); static int iwn5000_get_rssi(struct iwn_softc *, struct iwn_rx_stat *); static int iwn_get_noise(const struct iwn_rx_general_stats *); @@ -277,6 +276,10 @@ static int iwn_set_pslevel(struct iwn_softc *, int, int, int); static int iwn_send_btcoex(struct iwn_softc *); static int iwn_send_advanced_btcoex(struct iwn_softc *); static int iwn5000_runtime_calib(struct iwn_softc *); +static int iwn_check_bss_filter(struct iwn_softc *); +static int iwn4965_rxon_assoc(struct iwn_softc *, int); +static int iwn5000_rxon_assoc(struct iwn_softc *, int); +static int iwn_send_rxon(struct iwn_softc *, int, int); static int iwn_config(struct iwn_softc *); static int iwn_scan(struct iwn_softc *, struct ieee80211vap *, struct ieee80211_scan_state *, struct ieee80211_channel *); @@ -331,11 +334,9 @@ static int iwn5000_nic_config(struct iwn_softc *); static int iwn_hw_prepare(struct iwn_softc *); static int iwn_hw_init(struct iwn_softc *); static void iwn_hw_stop(struct iwn_softc *); -static void iwn_radio_on(void *, int); -static void iwn_radio_off(void *, int); static void iwn_panicked(void *, int); -static void iwn_init_locked(struct iwn_softc *); -static void iwn_init(struct iwn_softc *); +static int iwn_init_locked(struct iwn_softc *); +static int iwn_init(struct iwn_softc *); static void iwn_stop_locked(struct iwn_softc *); static void iwn_stop(struct iwn_softc *); static void iwn_scan_start(struct ieee80211com *); @@ -368,7 +369,8 @@ static driver_t iwn_driver = { static devclass_t iwn_devclass; DRIVER_MODULE(iwn, pci, iwn_driver, iwn_devclass, NULL, NULL); - +MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, iwn, iwn_ident_table, + nitems(iwn_ident_table) - 1); MODULE_VERSION(iwn, 1); MODULE_DEPEND(iwn, firmware, 1, 1, 1); @@ -380,7 +382,7 @@ static d_ioctl_t iwn_cdev_ioctl; static d_open_t iwn_cdev_open; static d_close_t iwn_cdev_close; -static struct cdevsw = { +static struct cdevsw iwn_cdevsw = { .d_version = D_VERSION, .d_flags = 0, .d_open = iwn_cdev_open, @@ -664,6 +666,7 @@ iwn_attach(device_t dev) ic->ic_addba_stop = iwn_ampdu_tx_stop; ic->ic_newassoc = iwn_newassoc; ic->ic_wme.wme_update = iwn_updateedca; + ic->ic_update_promisc = iwn_update_promisc; ic->ic_update_mcast = iwn_update_mcast; ic->ic_scan_start = iwn_scan_start; ic->ic_scan_end = iwn_scan_end; @@ -678,8 +681,7 @@ iwn_attach(device_t dev) callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); callout_init_mtx(&sc->scan_timeout, &sc->sc_mtx, 0); callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); - TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc); - TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc); + TASK_INIT(&sc->sc_rftoggle_task, 0, iwn_rftoggle_task, sc); TASK_INIT(&sc->sc_panic_task, 0, iwn_panicked, sc); TASK_INIT(&sc->sc_xmit_task, 0, iwn_xmit_task, sc); @@ -717,8 +719,8 @@ iwn_attach(device_t dev) ieee80211_announce(ic); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); - /* Add debug ioctl right at the end */ #ifndef __HAIKU__ + /* Add debug ioctl right at the end */ sc->sc_cdev = make_dev(&iwn_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "%s", device_get_nameunit(dev)); if (sc->sc_cdev == NULL) { @@ -1235,6 +1237,7 @@ iwn4965_attach(struct iwn_softc *sc, uint16_t pid) ops->set_txpower = iwn4965_set_txpower; ops->init_gains = iwn4965_init_gains; ops->set_gains = iwn4965_set_gains; + ops->rxon_assoc = iwn4965_rxon_assoc; ops->add_node = iwn4965_add_node; ops->tx_done = iwn4965_tx_done; ops->ampdu_tx_start = iwn4965_ampdu_tx_start; @@ -1279,6 +1282,7 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid) ops->set_txpower = iwn5000_set_txpower; ops->init_gains = iwn5000_init_gains; ops->set_gains = iwn5000_set_gains; + ops->rxon_assoc = iwn5000_rxon_assoc; ops->add_node = iwn5000_add_node; ops->tx_done = iwn5000_tx_done; ops->ampdu_tx_start = iwn5000_ampdu_tx_start; @@ -1405,10 +1409,9 @@ iwn_detach(device_t dev) iwn_xmit_queue_drain(sc); IWN_UNLOCK(sc); - ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task); - ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task); iwn_stop(sc); + taskqueue_drain_all(sc->sc_tq); taskqueue_free(sc->sc_tq); callout_drain(&sc->watchdog_to); @@ -2654,7 +2657,15 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc) static struct ieee80211_node * iwn_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) { - return malloc(sizeof (struct iwn_node), M_80211_NODE,M_NOWAIT | M_ZERO); + struct iwn_node *wn; + + wn = malloc(sizeof (struct iwn_node), M_80211_NODE, M_NOWAIT | M_ZERO); + if (wn == NULL) + return (NULL); + + wn->id = IWN_ID_UNDEFINED; + + return (&wn->ni); } static __inline int @@ -2677,6 +2688,26 @@ rate2plcp(int rate) return 0; } +static __inline uint8_t +plcp2rate(const uint8_t rate_plcp) +{ + switch (rate_plcp) { + case 0xd: return 12; + case 0xf: return 18; + case 0x5: return 24; + case 0x7: return 36; + case 0x9: return 48; + case 0xb: return 72; + case 0x1: return 96; + case 0x3: return 108; + case 10: return 2; + case 20: return 4; + case 55: return 11; + case 110: return 22; + default: return 0; + } +} + static int iwn_get_1stream_tx_antmask(struct iwn_softc *sc) { @@ -2948,13 +2979,11 @@ iwn_calib_timeout(void *arg) * followed by an MPDU_RX_DONE notification. */ static void -iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc, - struct iwn_rx_data *data) +iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *desc) { struct iwn_rx_stat *stat = (struct iwn_rx_stat *)(desc + 1); DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: received PHY stats\n", __func__); - bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); /* Save RX statistics, they will be used on MPDU_RX_DONE. */ memcpy(&sc->last_rx_stat, stat, sizeof (*stat)); @@ -2972,7 +3001,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct iwn_rx_ring *ring = &sc->rxq; - struct ieee80211_frame *wh; + struct ieee80211_frame_min *wh; struct ieee80211_node *ni; struct mbuf *m, *m1; struct iwn_rx_stat *stat; @@ -2994,8 +3023,6 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, } else stat = (struct iwn_rx_stat *)(desc + 1); - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); - if (stat->cfg_phy_len > IWN_STAT_MAXLEN) { device_printf(sc->sc_dev, "%s: invalid RX statistic header, len %d\n", __func__, @@ -3076,9 +3103,9 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, m->m_pkthdr.len = m->m_len = len; /* Grab a reference to the source node. */ - wh = mtod(m, struct ieee80211_frame *); + wh = mtod(m, struct ieee80211_frame_min *); if (len >= sizeof(struct ieee80211_frame_min)) - ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); + ni = ieee80211_find_rxnode(ic, wh); else ni = NULL; nf = (ni != NULL && ni->ni_vap->iv_state == IEEE80211_S_RUN && @@ -3088,6 +3115,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, if (ieee80211_radiotap_active(ic)) { struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap; + uint32_t rate = le32toh(stat->rate); tap->wr_flags = 0; if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE)) @@ -3095,24 +3123,11 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, tap->wr_dbm_antsignal = (int8_t)rssi; tap->wr_dbm_antnoise = (int8_t)nf; tap->wr_tsft = stat->tstamp; - switch (stat->rate) { - /* CCK rates. */ - case 10: tap->wr_rate = 2; break; - case 20: tap->wr_rate = 4; break; - case 55: tap->wr_rate = 11; break; - case 110: tap->wr_rate = 22; break; - /* OFDM rates. */ - case 0xd: tap->wr_rate = 12; break; - case 0xf: tap->wr_rate = 18; break; - case 0x5: tap->wr_rate = 24; break; - case 0x7: tap->wr_rate = 36; break; - case 0x9: tap->wr_rate = 48; break; - case 0xb: tap->wr_rate = 72; break; - case 0x1: tap->wr_rate = 96; break; - case 0x3: tap->wr_rate = 108; break; - /* Unknown rate: should not happen. */ - default: tap->wr_rate = 0; - } + if (rate & IWN_RFLAG_MCS) { + tap->wr_rate = rate & IWN_RFLAG_RATE_MCS; + tap->wr_rate |= IEEE80211_RATE_MCS; + } else + tap->wr_rate = plcp2rate(rate & IWN_RFLAG_RATE); } /* @@ -3122,7 +3137,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, if (sc->sc_beacon_wait) { uint8_t type, subtype; /* NB: Re-assign wh */ - wh = mtod(m, struct ieee80211_frame *); + wh = mtod(m, struct ieee80211_frame_min *); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; /* @@ -3161,8 +3176,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, /* Process an incoming Compressed BlockAck. */ static void -iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, - struct iwn_rx_data *data) +iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc) { struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct iwn_ops *ops = &sc->ops; @@ -3181,8 +3195,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); - bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); - qid = le16toh(ba->qid); txq = &sc->txq[ba->qid]; tap = sc->qid2tap[ba->qid]; @@ -3267,8 +3279,7 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, * firmware on response to a CMD_CALIB_CONFIG command (5000 only). */ static void -iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc, - struct iwn_rx_data *data) +iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc) { struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1); int len, idx = -1; @@ -3277,12 +3288,11 @@ iwn5000_rx_calib_results(struct iwn_softc *sc, struct iwn_rx_desc *desc, /* Runtime firmware should not send such a notification. */ if (sc->sc_flags & IWN_FLAG_CALIB_DONE){ - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s received after clib done\n", - __func__); + DPRINTF(sc, IWN_DEBUG_TRACE, + "->%s received after calib done\n", __func__); return; } len = (le32toh(desc->len) & 0x3fff) - 4; - bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); switch (calib->code) { case IWN5000_PHY_CALIB_DC: @@ -3391,8 +3401,7 @@ iwn_stats_update(struct iwn_softc *sc, struct iwn_calib_state *calib, * The latter is sent by the firmware after each received beacon. */ static void -iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, - struct iwn_rx_data *data) +iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc) { struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; @@ -3412,8 +3421,6 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc, return; } - bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); - DPRINTF(sc, IWN_DEBUG_CALIBRATE | IWN_DEBUG_STATS, "%s: received statistics, cmd %d, len %d\n", __func__, desc->type, le16toh(desc->len)); @@ -3501,11 +3508,7 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_rx_data *data) { struct iwn4965_tx_stat *stat = (struct iwn4965_tx_stat *)(desc + 1); - struct iwn_tx_ring *ring; - int qid; - - qid = desc->qid & 0xf; - ring = &sc->txq[qid]; + int qid = desc->qid & IWN_RX_DESC_QID_MSK; DPRINTF(sc, IWN_DEBUG_XMIT, "%s: " "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n", @@ -3516,7 +3519,6 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, stat->rate, le16toh(stat->duration), le32toh(stat->status)); - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, stat->rtsfailcnt, stat->ackfailcnt, &stat->status); @@ -3531,11 +3533,7 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_rx_data *data) { struct iwn5000_tx_stat *stat = (struct iwn5000_tx_stat *)(desc + 1); - struct iwn_tx_ring *ring; - int qid; - - qid = desc->qid & 0xf; - ring = &sc->txq[qid]; + int qid = desc->qid & IWN_RX_DESC_QID_MSK; DPRINTF(sc, IWN_DEBUG_XMIT, "%s: " "qid %d idx %d RTS retries %d ACK retries %d nkill %d rate %x duration %d status %x\n", @@ -3548,10 +3546,9 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, #ifdef notyet /* Reset TX scheduler slot. */ - iwn5000_reset_sched(sc, desc->qid & 0xf, desc->idx); + iwn5000_reset_sched(sc, qid, desc->idx); #endif - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, stat->rtsfailcnt, stat->ackfailcnt, &stat->status); @@ -3569,7 +3566,7 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, int ackfailcnt, uint8_t status) { struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; - struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; + struct iwn_tx_ring *ring = &sc->txq[desc->qid & IWN_RX_DESC_QID_MSK]; struct iwn_tx_data *data = &ring->data[desc->idx]; struct mbuf *m; struct ieee80211_node *ni; @@ -3843,16 +3840,16 @@ iwn_notif_intr(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_RECV, "%s: cur=%d; qid %x idx %d flags %x type %d(%s) len %d\n", - __func__, sc->rxq.cur, desc->qid & 0xf, desc->idx, desc->flags, - desc->type, iwn_intr_str(desc->type), - le16toh(desc->len)); + __func__, sc->rxq.cur, desc->qid & IWN_RX_DESC_QID_MSK, + desc->idx, desc->flags, desc->type, + iwn_intr_str(desc->type), le16toh(desc->len)); if (!(desc->qid & IWN_UNSOLICITED_RX_NOTIF)) /* Reply to a command. */ iwn_cmd_done(sc, desc); switch (desc->type) { case IWN_RX_PHY: - iwn_rx_phy(sc, desc, data); + iwn_rx_phy(sc, desc); break; case IWN_RX_DONE: /* 4965AGN only. */ @@ -3863,7 +3860,7 @@ iwn_notif_intr(struct iwn_softc *sc) case IWN_RX_COMPRESSED_BA: /* A Compressed BlockAck has been received. */ - iwn_rx_compressed_ba(sc, desc, data); + iwn_rx_compressed_ba(sc, desc); break; case IWN_TX_DONE: @@ -3873,7 +3870,7 @@ iwn_notif_intr(struct iwn_softc *sc) case IWN_RX_STATISTICS: case IWN_BEACON_STATISTICS: - iwn_rx_statistics(sc, desc, data); + iwn_rx_statistics(sc, desc); break; case IWN_BEACON_MISSED: @@ -3882,8 +3879,6 @@ iwn_notif_intr(struct iwn_softc *sc) (struct iwn_beacon_missed *)(desc + 1); int misses; - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); misses = le32toh(miss->consecutive); DPRINTF(sc, IWN_DEBUG_STATE, @@ -3911,8 +3906,6 @@ iwn_notif_intr(struct iwn_softc *sc) (struct iwn_ucode_info *)(desc + 1); /* The microcontroller is ready. */ - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); DPRINTF(sc, IWN_DEBUG_RESET, "microcode alive notification version=%d.%d " "subtype=%x alive=%x\n", uc->major, uc->minor, @@ -3931,6 +3924,7 @@ iwn_notif_intr(struct iwn_softc *sc) sc->errptr = le32toh(uc->errptr); break; } +#ifdef IWN_DEBUG case IWN_STATE_CHANGED: { /* @@ -3938,33 +3932,24 @@ iwn_notif_intr(struct iwn_softc *sc) * noted. However, we handle this in iwn_intr as we * get both the enable/disble intr. */ - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); -#ifdef IWN_DEBUG uint32_t *status = (uint32_t *)(desc + 1); DPRINTF(sc, IWN_DEBUG_INTR | IWN_DEBUG_STATE, "state changed to %x\n", le32toh(*status)); -#endif break; } case IWN_START_SCAN: { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); -#ifdef IWN_DEBUG struct iwn_start_scan *scan = (struct iwn_start_scan *)(desc + 1); DPRINTF(sc, IWN_DEBUG_ANY, "%s: scanning channel %d status %x\n", __func__, scan->chan, le32toh(scan->status)); -#endif break; } +#endif case IWN_STOP_SCAN: { - bus_dmamap_sync(sc->rxq.data_dmat, data->map, - BUS_DMASYNC_POSTREAD); #ifdef IWN_DEBUG struct iwn_stop_scan *scan = (struct iwn_stop_scan *)(desc + 1); @@ -3980,7 +3965,7 @@ iwn_notif_intr(struct iwn_softc *sc) break; } case IWN5000_CALIBRATION_RESULT: - iwn5000_rx_calib_results(sc, desc, data); + iwn5000_rx_calib_results(sc, desc); break; case IWN5000_CALIBRATION_DONE: @@ -4018,19 +4003,28 @@ iwn_wakeup_intr(struct iwn_softc *sc) } static void -iwn_rftoggle_intr(struct iwn_softc *sc) +iwn_rftoggle_task(void *arg, int npending) { + struct iwn_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; - uint32_t tmp = IWN_READ(sc, IWN_GP_CNTRL); + uint32_t tmp; - IWN_LOCK_ASSERT(sc); + IWN_LOCK(sc); + tmp = IWN_READ(sc, IWN_GP_CNTRL); + IWN_UNLOCK(sc); device_printf(sc->sc_dev, "RF switch: radio %s\n", (tmp & IWN_GP_CNTRL_RFKILL) ? "enabled" : "disabled"); - if (tmp & IWN_GP_CNTRL_RFKILL) - ieee80211_runtask(ic, &sc->sc_radioon_task); - else - ieee80211_runtask(ic, &sc->sc_radiooff_task); + if (!(tmp & IWN_GP_CNTRL_RFKILL)) { + ieee80211_suspend_all(ic); + + /* Enable interrupts to get RF toggle notification. */ + IWN_LOCK(sc); + IWN_WRITE(sc, IWN_INT, 0xffffffff); + IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); + IWN_UNLOCK(sc); + } else + ieee80211_resume_all(ic); } /* @@ -4103,7 +4097,7 @@ iwn_intr(void *arg) IWN_LOCK(sc); -#if !defined(__HAIKU__) +#ifndef __HAIKU__ /* Disable interrupts. */ IWN_WRITE(sc, IWN_INT_MASK, 0); @@ -4149,7 +4143,7 @@ iwn_intr(void *arg) IWN_WRITE(sc, IWN_FH_INT, r2); if (r1 & IWN_INT_RF_TOGGLED) { - iwn_rftoggle_intr(sc); + taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task); goto done; } if (r1 & IWN_INT_CT_REACHED) { @@ -4375,32 +4369,25 @@ iwn_tx_rate_to_linkq_offset(struct iwn_softc *sc, struct ieee80211_node *ni, static int iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { - struct iwn_ops *ops = &sc->ops; - const struct ieee80211_txparam *tp; + const struct ieee80211_txparam *tp = ni->ni_txparms; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct iwn_node *wn = (void *)ni; struct iwn_tx_ring *ring; - struct iwn_tx_desc *desc; - struct iwn_tx_data *data; struct iwn_tx_cmd *cmd; struct iwn_cmd_data *tx; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; - struct mbuf *m1; uint32_t flags; - uint16_t qos; - u_int hdrlen; - bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER]; + uint16_t seqno, qos; uint8_t tid, type; - int ac, i, totlen, error, pad, nsegs = 0, rate; + int ac, totlen, rate; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); IWN_LOCK_ASSERT(sc); wh = mtod(m, struct ieee80211_frame *); - hdrlen = ieee80211_anyhdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; /* Select EDCA Access Category and TX ring for this frame. */ @@ -4411,13 +4398,35 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) qos = 0; tid = 0; } + + /* Choose a TX rate index. */ + if (type == IEEE80211_FC0_TYPE_MGT || + type == IEEE80211_FC0_TYPE_CTL || + (m->m_flags & M_EAPOL) != 0) + rate = tp->mgmtrate; + else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) + rate = tp->mcastrate; + else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) + rate = tp->ucastrate; + else { + /* XXX pass pktlen */ + (void) ieee80211_ratectl_rate(ni, NULL, 0); + rate = ni->ni_txrate; + } + + /* + * XXX TODO: Group addressed frames aren't aggregated and must + * go to the normal non-aggregation queue, and have a NONQOS TID + * assigned from net80211. + */ + ac = M_WME_GETAC(m); + seqno = ni->ni_txseqs[tid]; if (m->m_flags & M_AMPDU_MPDU) { - uint16_t seqno; struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; if (!IEEE80211_AMPDU_RUNNING(tap)) { - return EINVAL; + return (EINVAL); } /* @@ -4428,40 +4437,10 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) * being used! */ ac = *(int *)tap->txa_private; - seqno = ni->ni_txseqs[tid]; *(uint16_t *)wh->i_seq = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); - ring = &sc->txq[ac]; - if ((seqno % 256) != ring->cur) { - device_printf(sc->sc_dev, - "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n", - __func__, - m, - seqno, - seqno % 256, - ring->cur); - } ni->ni_txseqs[tid]++; } - ring = &sc->txq[ac]; - desc = &ring->desc[ring->cur]; - data = &ring->data[ring->cur]; - - /* Choose a TX rate index. */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; - if (type == IEEE80211_FC0_TYPE_MGT) - rate = tp->mgmtrate; - else if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - rate = tp->mcastrate; - else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) - rate = tp->ucastrate; - else if (m->m_flags & M_EAPOL) - rate = tp->mgmtrate; - else { - /* XXX pass pktlen */ - (void) ieee80211_ratectl_rate(ni, NULL, 0); - rate = ni->ni_txrate; - } /* Encrypt the frame if need be. */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { @@ -4486,17 +4465,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) ieee80211_radiotap_tx(vap, m); } - /* Prepare TX firmware command. */ - cmd = &ring->cmd[ring->cur]; - cmd->code = IWN_CMD_TX_DATA; - cmd->flags = 0; - cmd->qid = ring->qid; - cmd->idx = ring->cur; - - tx = (struct iwn_cmd_data *)cmd->data; - /* NB: No need to clear tx, all fields are reinitialized here. */ - tx->scratch = 0; /* clear "scratch" area */ - flags = 0; if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { /* Unicast frame, check if an ACK is expected. */ @@ -4539,6 +4507,25 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) } } + ring = &sc->txq[ac]; + if ((m->m_flags & M_AMPDU_MPDU) != 0 && + (seqno % 256) != ring->cur) { + device_printf(sc->sc_dev, + "%s: m=%p: seqno (%d) (%d) != ring index (%d) !\n", + __func__, + m, + seqno, + seqno % 256, + ring->cur); + } + + /* Prepare TX firmware command. */ + cmd = &ring->cmd[ring->cur]; + tx = (struct iwn_cmd_data *)cmd->data; + + /* NB: No need to clear tx, all fields are reinitialized here. */ + tx->scratch = 0; /* clear "scratch" area */ + if (IEEE80211_IS_MULTICAST(wh->i_addr1) || type != IEEE80211_FC0_TYPE_DATA) tx->id = sc->broadcast_id; @@ -4559,19 +4546,6 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) } else tx->timeout = htole16(0); - if (hdrlen & 3) { - /* First segment length must be a multiple of 4. */ - flags |= IWN_TX_NEED_PADDING; - pad = 4 - (hdrlen & 3); - } else - pad = 0; - - tx->len = htole16(totlen); - tx->tid = tid; - tx->rts_ntries = 60; - tx->data_ntries = 15; - tx->lifetime = htole32(IWN_LIFETIME_INFINITE); - tx->rate = iwn_rate_to_plcp(sc, ni, rate); if (tx->id == sc->broadcast_id) { /* Group or management frame. */ tx->linkq = 0; @@ -4580,115 +4554,28 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) flags |= IWN_TX_LINKQ; /* enable MRR */ } - /* Set physical address of "scratch area". */ - tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); - tx->hiaddr = IWN_HIADDR(data->scratch_paddr); - - /* Copy 802.11 header in TX command. */ - memcpy((uint8_t *)(tx + 1), wh, hdrlen); - - /* Trim 802.11 header. */ - m_adj(m, hdrlen); + tx->tid = tid; + tx->rts_ntries = 60; + tx->data_ntries = 15; + tx->lifetime = htole32(IWN_LIFETIME_INFINITE); + tx->rate = iwn_rate_to_plcp(sc, ni, rate); tx->security = 0; tx->flags = htole32(flags); - error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs, - &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - if (error != EFBIG) { - device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, error); - return error; - } - /* Too many DMA segments, linearize mbuf. */ - m1 = m_collapse(m, M_NOWAIT, IWN_MAX_SCATTER - 1); - if (m1 == NULL) { - device_printf(sc->sc_dev, - "%s: could not defrag mbuf\n", __func__); - return ENOBUFS; - } - m = m1; - - error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, - segs, &nsegs, BUS_DMA_NOWAIT); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, error); - return error; - } - } - - data->m = m; - data->ni = ni; - - DPRINTF(sc, IWN_DEBUG_XMIT, - "%s: qid %d idx %d len %d nsegs %d flags 0x%08x rate 0x%04x plcp 0x%08x\n", - __func__, - ring->qid, - ring->cur, - m->m_pkthdr.len, - nsegs, - flags, - rate, - tx->rate); - - /* Fill TX descriptor. */ - desc->nsegs = 1; - if (m->m_len != 0) - desc->nsegs += nsegs; - /* First DMA segment is used by the TX command. */ - desc->segs[0].addr = htole32(IWN_LOADDR(data->cmd_paddr)); - desc->segs[0].len = htole16(IWN_HIADDR(data->cmd_paddr) | - (4 + sizeof (*tx) + hdrlen + pad) << 4); - /* Other DMA segments are for data payload. */ - seg = &segs[0]; - for (i = 1; i <= nsegs; i++) { - desc->segs[i].addr = htole32(IWN_LOADDR(seg->ds_addr)); - desc->segs[i].len = htole16(IWN_HIADDR(seg->ds_addr) | - seg->ds_len << 4); - seg++; - } - - bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(ring->cmd_dma.tag, ring->cmd_dma.map, - BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, - BUS_DMASYNC_PREWRITE); - - /* Update TX scheduler. */ - if (ring->qid >= sc->firstaggqueue) - ops->update_sched(sc, ring->qid, ring->cur, tx->id, totlen); - - /* Kick TX ring. */ - ring->cur = (ring->cur + 1) % IWN_TX_RING_COUNT; - IWN_WRITE(sc, IWN_HBUS_TARG_WRPTR, ring->qid << 8 | ring->cur); - - /* Mark TX ring as full if we reach a certain threshold. */ - if (++ring->queued > IWN_TX_RING_HIMARK) - sc->qfullmsk |= 1 << ring->qid; - - DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); - - return 0; + return (iwn_tx_cmd(sc, m, ni, ring)); } static int iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { - struct iwn_ops *ops = &sc->ops; struct ieee80211vap *vap = ni->ni_vap; struct iwn_tx_cmd *cmd; struct iwn_cmd_data *tx; struct ieee80211_frame *wh; struct iwn_tx_ring *ring; - struct iwn_tx_desc *desc; - struct iwn_tx_data *data; - struct mbuf *m1; - bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER]; uint32_t flags; - u_int hdrlen; - int ac, totlen, error, pad, nsegs = 0, i, rate; + int ac, rate; uint8_t type; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); @@ -4696,29 +4583,12 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, IWN_LOCK_ASSERT(sc); wh = mtod(m, struct ieee80211_frame *); - hdrlen = ieee80211_anyhdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; ac = params->ibp_pri & 3; - ring = &sc->txq[ac]; - desc = &ring->desc[ring->cur]; - data = &ring->data[ring->cur]; - /* Choose a TX rate. */ rate = params->ibp_rate0; - totlen = m->m_pkthdr.len; - - /* Prepare TX firmware command. */ - cmd = &ring->cmd[ring->cur]; - cmd->code = IWN_CMD_TX_DATA; - cmd->flags = 0; - cmd->qid = ring->qid; - cmd->idx = ring->cur; - - tx = (struct iwn_cmd_data *)cmd->data; - /* NB: No need to clear tx, all fields are reinitialized here. */ - tx->scratch = 0; /* clear "scratch" area */ flags = 0; if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) @@ -4739,6 +4609,23 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, } else flags |= IWN_TX_NEED_CTS | IWN_TX_FULL_TXOP; } + + if (ieee80211_radiotap_active_vap(vap)) { + struct iwn_tx_radiotap_header *tap = &sc->sc_txtap; + + tap->wt_flags = 0; + tap->wt_rate = rate; + + ieee80211_radiotap_tx(vap, m); + } + + ring = &sc->txq[ac]; + cmd = &ring->cmd[ring->cur]; + + tx = (struct iwn_cmd_data *)cmd->data; + /* NB: No need to clear tx, all fields are reinitialized here. */ + tx->scratch = 0; /* clear "scratch" area */ + if (type == IEEE80211_FC0_TYPE_MGT) { uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; @@ -4754,44 +4641,68 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, } else tx->timeout = htole16(0); - if (hdrlen & 3) { - /* First segment length must be a multiple of 4. */ - flags |= IWN_TX_NEED_PADDING; - pad = 4 - (hdrlen & 3); - } else - pad = 0; - - if (ieee80211_radiotap_active_vap(vap)) { - struct iwn_tx_radiotap_header *tap = &sc->sc_txtap; - - tap->wt_flags = 0; - tap->wt_rate = rate; - - ieee80211_radiotap_tx(vap, m); - } - - tx->len = htole16(totlen); tx->tid = 0; tx->id = sc->broadcast_id; tx->rts_ntries = params->ibp_try1; tx->data_ntries = params->ibp_try0; tx->lifetime = htole32(IWN_LIFETIME_INFINITE); tx->rate = iwn_rate_to_plcp(sc, ni, rate); + tx->security = 0; + tx->flags = htole32(flags); /* Group or management frame. */ tx->linkq = 0; + return (iwn_tx_cmd(sc, m, ni, ring)); +} + +static int +iwn_tx_cmd(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, + struct iwn_tx_ring *ring) +{ + struct iwn_ops *ops = &sc->ops; + struct iwn_tx_cmd *cmd; + struct iwn_cmd_data *tx; + struct ieee80211_frame *wh; + struct iwn_tx_desc *desc; + struct iwn_tx_data *data; + bus_dma_segment_t *seg, segs[IWN_MAX_SCATTER]; + struct mbuf *m1; + u_int hdrlen; + int totlen, error, pad, nsegs = 0, i; + + wh = mtod(m, struct ieee80211_frame *); + hdrlen = ieee80211_anyhdrsize(wh); + totlen = m->m_pkthdr.len; + + desc = &ring->desc[ring->cur]; + data = &ring->data[ring->cur]; + + /* Prepare TX firmware command. */ + cmd = &ring->cmd[ring->cur]; + cmd->code = IWN_CMD_TX_DATA; + cmd->flags = 0; + cmd->qid = ring->qid; + cmd->idx = ring->cur; + + tx = (struct iwn_cmd_data *)cmd->data; + tx->len = htole16(totlen); + /* Set physical address of "scratch area". */ tx->loaddr = htole32(IWN_LOADDR(data->scratch_paddr)); tx->hiaddr = IWN_HIADDR(data->scratch_paddr); + if (hdrlen & 3) { + /* First segment length must be a multiple of 4. */ + tx->flags |= htole32(IWN_TX_NEED_PADDING); + pad = 4 - (hdrlen & 3); + } else + pad = 0; /* Copy 802.11 header in TX command. */ memcpy((uint8_t *)(tx + 1), wh, hdrlen); /* Trim 802.11 header. */ m_adj(m, hdrlen); - tx->security = 0; - tx->flags = htole32(flags); error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs, &nsegs, BUS_DMA_NOWAIT); @@ -4813,17 +4724,28 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m, error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs, &nsegs, BUS_DMA_NOWAIT); if (error != 0) { + /* XXX fix this */ + /* + * NB: Do not return error; + * original mbuf does not exist anymore. + */ device_printf(sc->sc_dev, - "%s: can't map mbuf (error %d)\n", __func__, error); - return error; + "%s: can't map mbuf (error %d)\n", + __func__, error); + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + m_freem(m); + return 0; } } data->m = m; data->ni = ni; - DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d\n", - __func__, ring->qid, ring->cur, m->m_pkthdr.len, nsegs); + DPRINTF(sc, IWN_DEBUG_XMIT, "%s: qid %d idx %d len %d nsegs %d " + "plcp %d\n", + __func__, ring->qid, ring->cur, totlen, nsegs, tx->rate); /* Fill TX descriptor. */ desc->nsegs = 1; @@ -5089,25 +5011,28 @@ static void iwn_parent(struct ieee80211com *ic) { struct iwn_softc *sc = ic->ic_softc; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - int startall = 0, stop = 0; + struct ieee80211vap *vap; + int error; - IWN_LOCK(sc); if (ic->ic_nrunning > 0) { - if (!(sc->sc_flags & IWN_FLAG_RUNNING)) { - iwn_init_locked(sc); - if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL) - startall = 1; - else - stop = 1; + error = iwn_init(sc); + + switch (error) { + case 0: + ieee80211_start_all(ic); + break; + case 1: + /* radio is disabled via RFkill switch */ + taskqueue_enqueue(sc->sc_tq, &sc->sc_rftoggle_task); + break; + default: + vap = TAILQ_FIRST(&ic->ic_vaps); + if (vap != NULL) + ieee80211_stop(vap); + break; } - } else if (sc->sc_flags & IWN_FLAG_RUNNING) - iwn_stop_locked(sc); - IWN_UNLOCK(sc); - if (startall) - ieee80211_start_all(ic); - else if (vap != NULL && stop) - ieee80211_stop(vap); + } else + iwn_stop(sc); } /* @@ -5390,17 +5315,19 @@ iwn_updateedca(struct ieee80211com *ic) #define IWN_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ struct iwn_softc *sc = ic->ic_softc; struct iwn_edca_params cmd; + struct chanAccParams chp; int aci; DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__); + ieee80211_wme_ic_getparams(ic, &chp); + memset(&cmd, 0, sizeof cmd); cmd.flags = htole32(IWN_EDCA_UPDATE); IEEE80211_LOCK(ic); for (aci = 0; aci < WME_NUM_AC; aci++) { - const struct wmeParams *ac = - &ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; + const struct wmeParams *ac = &chp.cap_wmeParams[aci]; cmd.ac[aci].aifsn = ac->wmep_aifsn; cmd.ac[aci].cwmin = htole16(IWN_EXP2(ac->wmep_logcwmin)); cmd.ac[aci].cwmax = htole16(IWN_EXP2(ac->wmep_logcwmax)); @@ -5419,6 +5346,43 @@ iwn_updateedca(struct ieee80211com *ic) #undef IWN_EXP2 } +static void +iwn_set_promisc(struct iwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t promisc_filter; + + promisc_filter = IWN_FILTER_CTL | IWN_FILTER_PROMISC; + if (ic->ic_promisc > 0 || ic->ic_opmode == IEEE80211_M_MONITOR) + sc->rxon->filter |= htole32(promisc_filter); + else + sc->rxon->filter &= ~htole32(promisc_filter); +} + +static void +iwn_update_promisc(struct ieee80211com *ic) +{ + struct iwn_softc *sc = ic->ic_softc; + int error; + + if (ic->ic_opmode == IEEE80211_M_MONITOR) + return; /* nothing to do */ + + IWN_LOCK(sc); + if (!(sc->sc_flags & IWN_FLAG_RUNNING)) { + IWN_UNLOCK(sc); + return; + } + + iwn_set_promisc(sc); + if ((error = iwn_send_rxon(sc, 1, 1)) != 0) { + device_printf(sc->sc_dev, + "%s: could not send RXON, error %d\n", + __func__, error); + } + IWN_UNLOCK(sc); +} + static void iwn_update_mcast(struct ieee80211com *ic) { @@ -5501,7 +5465,6 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni) static void iwn4965_power_calibration(struct iwn_softc *sc, int temp) { - struct ieee80211com *ic = &sc->sc_ic; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -5511,7 +5474,7 @@ iwn4965_power_calibration(struct iwn_softc *sc, int temp) if (abs(temp - sc->temp) >= 3) { /* Record temperature of last calibration. */ sc->temp = temp; - (void)iwn4965_set_txpower(sc, ic->ic_bsschan, 1); + (void)iwn4965_set_txpower(sc, 1); } } @@ -5521,8 +5484,7 @@ iwn4965_power_calibration(struct iwn_softc *sc, int temp) * the current temperature and the current voltage. */ static int -iwn4965_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, - int async) +iwn4965_set_txpower(struct iwn_softc *sc, int async) { /* Fixed-point arithmetic division using a n-bit fractional part. */ #define fdivround(a, b, n) \ @@ -5537,20 +5499,21 @@ iwn4965_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, struct iwn4965_eeprom_chan_samples *chans; const uint8_t *rf_gain, *dsp_gain; int32_t vdiff, tdiff; - int i, c, grp, maxpwr; + int i, is_chan_5ghz, c, grp, maxpwr; uint8_t chan; sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; /* Retrieve current channel from last RXON. */ chan = sc->rxon->chan; + is_chan_5ghz = (sc->rxon->flags & htole32(IWN_RXON_24GHZ)) == 0; DPRINTF(sc, IWN_DEBUG_RESET, "setting TX power for channel %d\n", chan); memset(&cmd, 0, sizeof cmd); - cmd.band = IEEE80211_IS_CHAN_5GHZ(ch) ? 0 : 1; + cmd.band = is_chan_5ghz ? 0 : 1; cmd.chan = chan; - if (IEEE80211_IS_CHAN_5GHZ(ch)) { + if (is_chan_5ghz) { maxpwr = sc->maxpwr5GHz; rf_gain = iwn4965_rf_gain_5ghz; dsp_gain = iwn4965_dsp_gain_5ghz; @@ -5672,8 +5635,7 @@ iwn4965_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, } static int -iwn5000_set_txpower(struct iwn_softc *sc, struct ieee80211_channel *ch, - int async) +iwn5000_set_txpower(struct iwn_softc *sc, int async) { struct iwn5000_cmd_txpower cmd; int cmdid; @@ -6529,9 +6491,108 @@ iwn_get_rxon_ht_flags(struct iwn_softc *sc, struct ieee80211_channel *c) } static int -iwn_config(struct iwn_softc *sc) +iwn_check_bss_filter(struct iwn_softc *sc) +{ + return ((sc->rxon->filter & htole32(IWN_FILTER_BSS)) != 0); +} + +static int +iwn4965_rxon_assoc(struct iwn_softc *sc, int async) +{ + struct iwn4965_rxon_assoc cmd; + struct iwn_rxon *rxon = sc->rxon; + + cmd.flags = rxon->flags; + cmd.filter = rxon->filter; + cmd.ofdm_mask = rxon->ofdm_mask; + cmd.cck_mask = rxon->cck_mask; + cmd.ht_single_mask = rxon->ht_single_mask; + cmd.ht_dual_mask = rxon->ht_dual_mask; + cmd.rxchain = rxon->rxchain; + cmd.reserved = 0; + + return (iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof(cmd), async)); +} + +static int +iwn5000_rxon_assoc(struct iwn_softc *sc, int async) +{ + struct iwn5000_rxon_assoc cmd; + struct iwn_rxon *rxon = sc->rxon; + + cmd.flags = rxon->flags; + cmd.filter = rxon->filter; + cmd.ofdm_mask = rxon->ofdm_mask; + cmd.cck_mask = rxon->cck_mask; + cmd.reserved1 = 0; + cmd.ht_single_mask = rxon->ht_single_mask; + cmd.ht_dual_mask = rxon->ht_dual_mask; + cmd.ht_triple_mask = rxon->ht_triple_mask; + cmd.reserved2 = 0; + cmd.rxchain = rxon->rxchain; + cmd.acquisition = rxon->acquisition; + cmd.reserved3 = 0; + + return (iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof(cmd), async)); +} + +static int +iwn_send_rxon(struct iwn_softc *sc, int assoc, int async) { struct iwn_ops *ops = &sc->ops; + int error; + + IWN_LOCK_ASSERT(sc); + + if (assoc && iwn_check_bss_filter(sc) != 0) { + error = ops->rxon_assoc(sc, async); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: RXON_ASSOC command failed, error %d\n", + __func__, error); + return (error); + } + } else { + if (sc->sc_is_scanning) + device_printf(sc->sc_dev, + "%s: is_scanning set, before RXON\n", + __func__); + + error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, async); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: RXON command failed, error %d\n", + __func__, error); + return (error); + } + + /* + * Reconfiguring RXON clears the firmware nodes table so + * we must add the broadcast node again. + */ + if (iwn_check_bss_filter(sc) == 0 && + (error = iwn_add_broadcast_node(sc, async)) != 0) { + device_printf(sc->sc_dev, + "%s: could not add broadcast node, error %d\n", + __func__, error); + return (error); + } + } + + /* Configuration has changed, set TX power accordingly. */ + if ((error = ops->set_txpower(sc, async)) != 0) { + device_printf(sc->sc_dev, + "%s: could not set TX power, error %d\n", + __func__, error); + return (error); + } + + return (0); +} + +static int +iwn_config(struct iwn_softc *sc) +{ struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); const uint8_t *macaddr; @@ -6623,20 +6684,20 @@ iwn_config(struct iwn_softc *sc) sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF); if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ); + + sc->rxon->filter = htole32(IWN_FILTER_MULTICAST); switch (ic->ic_opmode) { case IEEE80211_M_STA: sc->rxon->mode = IWN_MODE_STA; - sc->rxon->filter = htole32(IWN_FILTER_MULTICAST); break; case IEEE80211_M_MONITOR: sc->rxon->mode = IWN_MODE_MONITOR; - sc->rxon->filter = htole32(IWN_FILTER_MULTICAST | - IWN_FILTER_CTL | IWN_FILTER_PROMISC); break; default: /* Should not get there. */ break; } + iwn_set_promisc(sc); sc->rxon->cck_mask = 0x0f; /* not yet negotiated */ sc->rxon->ofdm_mask = 0xff; /* not yet negotiated */ sc->rxon->ht_single_mask = 0xff; @@ -6666,26 +6727,8 @@ iwn_config(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_RESET, "%s: setting configuration; flags=0x%08x\n", __func__, le32toh(sc->rxon->flags)); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); - error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 0); - if (error != 0) { - device_printf(sc->sc_dev, "%s: RXON command failed\n", - __func__); - return error; - } - - if ((error = iwn_add_broadcast_node(sc, 0)) != 0) { - device_printf(sc->sc_dev, "%s: could not add broadcast node\n", - __func__); - return error; - } - - /* Configuration has changed, set TX power accordingly. */ - if ((error = ops->set_txpower(sc, ic->ic_curchan, 0)) != 0) { - device_printf(sc->sc_dev, "%s: could not set TX power\n", + if ((error = iwn_send_rxon(sc, 0, 0)) != 0) { + device_printf(sc->sc_dev, "%s: could not send RXON\n", __func__); return error; } @@ -7039,7 +7082,6 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, static int iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap) { - struct iwn_ops *ops = &sc->ops; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = vap->iv_bss; int error; @@ -7075,37 +7117,16 @@ iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap) DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x cck %x ofdm %x\n", sc->rxon->chan, sc->rxon->flags, sc->rxon->cck_mask, sc->rxon->ofdm_mask); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); - error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1); - if (error != 0) { - device_printf(sc->sc_dev, "%s: RXON command failed, error %d\n", - __func__, error); - return error; - } - /* Configuration has changed, set TX power accordingly. */ - if ((error = ops->set_txpower(sc, ni->ni_chan, 1)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set TX power, error %d\n", __func__, error); - return error; - } - /* - * Reconfiguring RXON clears the firmware nodes table so we must - * add the broadcast node again. - */ - if ((error = iwn_add_broadcast_node(sc, 1)) != 0) { - device_printf(sc->sc_dev, - "%s: could not add broadcast node, error %d\n", __func__, - error); - return error; + if ((error = iwn_send_rxon(sc, 0, 1)) != 0) { + device_printf(sc->sc_dev, "%s: could not send RXON\n", + __func__); + return (error); } DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); - return 0; + return (0); } static int @@ -7158,22 +7179,10 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap) sc->rxon->filter |= htole32(IWN_FILTER_BSS); DPRINTF(sc, IWN_DEBUG_STATE, "rxon chan %d flags %x, curhtprotmode=%d\n", sc->rxon->chan, le32toh(sc->rxon->flags), ic->ic_curhtprotmode); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); - error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, 1); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not update configuration, error %d\n", __func__, - error); - return error; - } - /* Configuration has changed, set TX power accordingly. */ - if ((error = ops->set_txpower(sc, ni->ni_chan, 1)) != 0) { - device_printf(sc->sc_dev, - "%s: could not set TX power, error %d\n", __func__, error); + if ((error = iwn_send_rxon(sc, 0, 1)) != 0) { + device_printf(sc->sc_dev, "%s: could not send RXON\n", + __func__); return error; } @@ -7257,6 +7266,9 @@ iwn_ampdu_rx_start(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap, tid = MS(le16toh(baparamset), IEEE80211_BAPS_TID); ssn = MS(le16toh(baseqctl), IEEE80211_BASEQ_START); + if (wn->id == IWN_ID_UNDEFINED) + return (ENOENT); + memset(&node, 0, sizeof node); node.id = wn->id; node.control = IWN_NODE_UPDATE; @@ -7288,6 +7300,9 @@ iwn_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap) DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); + if (wn->id == IWN_ID_UNDEFINED) + goto end; + /* XXX: tid as an argument */ for (tid = 0; tid < WME_NUM_TID; tid++) { if (&ni->ni_rx_ampdu[tid] == rap) @@ -7301,6 +7316,7 @@ iwn_ampdu_rx_stop(struct ieee80211_node *ni, struct ieee80211_rx_ampdu *rap) node.delba_tid = tid; DPRINTF(sc, IWN_DEBUG_RECV, "DELBA RA=%d TID=%d\n", wn->id, tid); (void)ops->add_node(sc, &node, 1); +end: sc->sc_ampdu_rx_stop(ni, rap); } @@ -7375,6 +7391,9 @@ iwn_ampdu_tx_start(struct ieee80211com *ic, struct ieee80211_node *ni, DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); + if (wn->id == IWN_ID_UNDEFINED) + return (0); + /* Enable TX for the specified RA/TID. */ wn->disable_tid &= ~(1 << tid); memset(&node, 0, sizeof node); @@ -7490,10 +7509,10 @@ static void iwn5000_ampdu_tx_start(struct iwn_softc *sc, struct ieee80211_node *ni, int qid, uint8_t tid, uint16_t ssn) { - struct iwn_node *wn = (void *)ni; - DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); + struct iwn_node *wn = (void *)ni; + /* Stop TX scheduler while we're changing its configuration. */ iwn_prph_write(sc, IWN5000_SCHED_QUEUE_STATUS(qid), IWN5000_TXQ_STATUS_CHGACT); @@ -8687,41 +8706,6 @@ iwn_hw_stop(struct iwn_softc *sc) iwn_apm_stop(sc); } -static void -iwn_radio_on(void *arg0, int pending) -{ - struct iwn_softc *sc = arg0; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); - - if (vap != NULL) { - iwn_init(sc); - ieee80211_init(vap); - } -} - -static void -iwn_radio_off(void *arg0, int pending) -{ - struct iwn_softc *sc = arg0; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); - - iwn_stop(sc); - if (vap != NULL) - ieee80211_stop(vap); - - /* Enable interrupts to get RF toggle notification. */ - IWN_LOCK(sc); - IWN_WRITE(sc, IWN_INT, 0xffffffff); - IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); - IWN_UNLOCK(sc); -} - static void iwn_panicked(void *arg0, int pending) { @@ -8753,7 +8737,11 @@ iwn_panicked(void *arg0, int pending) IWN_LOCK(sc); iwn_stop_locked(sc); - iwn_init_locked(sc); + if ((error = iwn_init_locked(sc)) != 0) { + device_printf(sc->sc_dev, + "%s: could not init hardware\n", __func__); + goto unlock; + } if (vap->iv_state >= IEEE80211_S_AUTH && (error = iwn_auth(sc, vap)) != 0) { device_printf(sc->sc_dev, @@ -8765,11 +8753,12 @@ iwn_panicked(void *arg0, int pending) "%s: could not move to run state\n", __func__); } +unlock: IWN_UNLOCK(sc); #endif } -static void +static int iwn_init_locked(struct iwn_softc *sc) { int error; @@ -8778,6 +8767,9 @@ iwn_init_locked(struct iwn_softc *sc) IWN_LOCK_ASSERT(sc); + if (sc->sc_flags & IWN_FLAG_RUNNING) + goto end; + sc->sc_flags |= IWN_FLAG_RUNNING; if ((error = iwn_hw_prepare(sc)) != 0) { @@ -8792,12 +8784,10 @@ iwn_init_locked(struct iwn_softc *sc) /* Check that the radio is not disabled by hardware switch. */ if (!(IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)) { - device_printf(sc->sc_dev, - "radio is disabled by hardware switch\n"); - /* Enable interrupts to get RF toggle notifications. */ - IWN_WRITE(sc, IWN_INT, 0xffffffff); - IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); - return; + iwn_stop_locked(sc); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); + + return (1); } /* Read firmware images from the filesystem. */ @@ -8828,26 +8818,29 @@ iwn_init_locked(struct iwn_softc *sc) callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc); +end: DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); - return; + return (0); fail: - sc->sc_flags &= ~IWN_FLAG_RUNNING; iwn_stop_locked(sc); + DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__); + + return (-1); } -static void +static int iwn_init(struct iwn_softc *sc) { + int error; IWN_LOCK(sc); - iwn_init_locked(sc); + error = iwn_init_locked(sc); IWN_UNLOCK(sc); - if (sc->sc_flags & IWN_FLAG_RUNNING) - ieee80211_start_all(&sc->sc_ic); + return (error); } static void @@ -8856,6 +8849,9 @@ iwn_stop_locked(struct iwn_softc *sc) IWN_LOCK_ASSERT(sc); + if (!(sc->sc_flags & IWN_FLAG_RUNNING)) + return; + sc->sc_is_scanning = 0; sc->sc_tx_timer = 0; callout_stop(&sc->watchdog_to); diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_chip_cfg.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_chip_cfg.h index 041238681a..1547fabb22 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_chip_cfg.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_chip_cfg.h @@ -14,7 +14,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD$ + * $FreeBSD: releng/12.0/sys/dev/iwn/if_iwn_chip_cfg.h 335785 2018-06-28 21:59:45Z eadler $ */ #ifndef __IF_IWN_CHIP_CFG_H__ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h index 2932c7e4ab..06ded6afd5 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_debug.h @@ -19,7 +19,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD$ + * $FreeBSD: releng/12.0/sys/dev/iwn/if_iwn_debug.h 315946 2017-03-25 13:15:43Z avos $ */ #ifndef __IF_IWN_DEBUG_H__ @@ -72,6 +72,7 @@ iwn_intr_str(uint8_t cmd) case IWN_RX_PHY: return "RX_PHY"; case IWN_MPDU_RX_DONE: return "MPDU_RX_DONE"; case IWN_RX_DONE: return "RX_DONE"; + case IWN_RX_COMPRESSED_BA: return "RX_COMPRESSED_BA"; /* Command Notifications */ case IWN_CMD_RXON: return "IWN_CMD_RXON"; @@ -81,6 +82,7 @@ iwn_intr_str(uint8_t cmd) case IWN_CMD_LINK_QUALITY: return "IWN_CMD_LINK_QUALITY"; case IWN_CMD_SET_LED: return "IWN_CMD_SET_LED"; case IWN5000_CMD_WIMAX_COEX: return "IWN5000_CMD_WIMAX_COEX"; + case IWN_TEMP_NOTIFICATION: return "IWN_TEMP_NOTIFICATION"; case IWN5000_CMD_CALIB_CONFIG: return "IWN5000_CMD_CALIB_CONFIG"; case IWN5000_CMD_CALIB_RESULT: return "IWN5000_CMD_CALIB_RESULT"; case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE"; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_devid.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_devid.h index 8470038185..f9e0987a03 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_devid.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_devid.h @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD$ + * $FreeBSD: releng/12.0/sys/dev/iwn/if_iwn_devid.h 335812 2018-06-30 04:30:08Z eadler $ */ #ifndef __IF_IWN_DEVID_H__ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_ioctl.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_ioctl.h index c289683ed0..89b2f3c582 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_ioctl.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwn_ioctl.h @@ -13,7 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD$ + * $FreeBSD: releng/12.0/sys/dev/iwn/if_iwn_ioctl.h 287312 2015-08-30 21:54:33Z adrian $ */ #ifndef __IF_IWN_IOCTL_H__ #define __IF_IWN_IOCTL_H__ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h index 05ababf392..1a97f6e34f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnreg.h @@ -1,4 +1,4 @@ -/* $FreeBSD$ */ +/* $FreeBSD: releng/12.0/sys/dev/iwn/if_iwnreg.h 315958 2017-03-25 15:57:47Z avos $ */ /* $OpenBSD: if_iwnreg.h,v 1.40 2010/05/05 19:41:57 damien Exp $ */ /*- @@ -617,6 +617,34 @@ struct iwn_rxon { #define IWN4965_RXONSZ (sizeof (struct iwn_rxon) - 6) #define IWN5000_RXONSZ (sizeof (struct iwn_rxon)) +/* Structure for command IWN_CMD_RXON_ASSOC (4965AGN only.) */ +struct iwn4965_rxon_assoc { + uint32_t flags; + uint32_t filter; + uint8_t ofdm_mask; + uint8_t cck_mask; + uint8_t ht_single_mask; + uint8_t ht_dual_mask; + uint16_t rxchain; + uint16_t reserved; +} __packed; + +/* Structure for command IWN_CMD_RXON_ASSOC (5000 Series only.) */ +struct iwn5000_rxon_assoc { + uint32_t flags; + uint32_t filter; + uint8_t ofdm_mask; + uint8_t cck_mask; + uint16_t reserved1; + uint8_t ht_single_mask; + uint8_t ht_dual_mask; + uint8_t ht_triple_mask; + uint8_t reserved2; + uint16_t rxchain; + uint16_t acquisition; + uint32_t reserved3; +} __packed; + /* Structure for command IWN_CMD_ASSOCIATE. */ struct iwn_assoc { uint32_t flags; @@ -662,13 +690,15 @@ struct iwn_node_info { uint8_t macaddr[IEEE80211_ADDR_LEN]; uint16_t reserved2; uint8_t id; -#define IWN_ID_BSS 0 +#define IWN_ID_BSS 0 #define IWN_STA_ID 1 -#define IWN_PAN_ID_BCAST 14 +#define IWN_PAN_ID_BCAST 14 #define IWN5000_ID_BROADCAST 15 #define IWN4965_ID_BROADCAST 31 +#define IWN_ID_UNDEFINED (uint8_t)-1 + uint8_t flags; #define IWN_FLAG_SET_KEY (1 << 0) #define IWN_FLAG_SET_DISABLE_TID (1 << 1) @@ -736,6 +766,10 @@ struct iwn4965_node_info { uint32_t reserved7; } __packed; +#define IWN_RFLAG_RATE 0xff +#define IWN_RFLAG_RATE_MCS 0x1f +#define IWN_RFLAG_HT40_DUP 0x20 + #define IWN_RFLAG_MCS (1 << 8) #define IWN_RFLAG_CCK (1 << 9) #define IWN_RFLAG_GREENFIELD (1 << 10) diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h index 61ce8456dd..e88d523c22 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/dev/iwn/if_iwnvar.h @@ -1,4 +1,4 @@ -/* $FreeBSD$ */ +/* $FreeBSD: releng/12.0/sys/dev/iwn/if_iwnvar.h 314923 2017-03-08 22:49:22Z avos $ */ /* $OpenBSD: if_iwnvar.h,v 1.18 2010/04/30 16:06:46 damien Exp $ */ /*- @@ -206,10 +206,10 @@ struct iwn_ops { uint16_t); int (*get_temperature)(struct iwn_softc *); int (*get_rssi)(struct iwn_softc *, struct iwn_rx_stat *); - int (*set_txpower)(struct iwn_softc *, - struct ieee80211_channel *, int); + int (*set_txpower)(struct iwn_softc *, int); int (*init_gains)(struct iwn_softc *); int (*set_gains)(struct iwn_softc *); + int (*rxon_assoc)(struct iwn_softc *, int); int (*add_node)(struct iwn_softc *, struct iwn_node_info *, int); void (*tx_done)(struct iwn_softc *, struct iwn_rx_desc *, @@ -305,8 +305,7 @@ struct iwn_softc { int sc_cap_off; /* PCIe Capabilities. */ /* Tasks used by the driver */ - struct task sc_radioon_task; - struct task sc_radiooff_task; + struct task sc_rftoggle_task; struct task sc_panic_task; struct task sc_xmit_task; @@ -405,11 +404,6 @@ struct iwn_softc { struct iwn_rx_radiotap_header sc_rxtap; struct iwn_tx_radiotap_header sc_txtap; -#if defined(__HAIKU__) - uint32_t sc_intr_status_1; - uint32_t sc_intr_status_2; -#endif - /* The power save level originally configured by user */ int desired_pwrsave_level; @@ -431,6 +425,11 @@ struct iwn_softc { * frames whilst waiting for beacons.) */ struct mbufq sc_xmit_queue; + +#if defined(__HAIKU__) + uint32_t sc_intr_status_1; + uint32_t sc_intr_status_2; +#endif }; #define IWN_LOCK_INIT(_sc) \