hrev52730 adds 2 changesets to branch 'master'
old head: 24e7aa421750a7403332a47827cd739fe5a0f0e1
new head: 4e5a521c2adf5efa14b277e53ddfaf0fa0ea61a5
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=4e5a521c2adf+%5E24e7aa421750
----------------------------------------------------------------------------
27632129b22f: freebsd_network: Implement taskqueue_drain_all.
Required by FreeBSD 12's iprowifi4965.
4e5a521c2adf: iprowifi4965: Upgrade to FreeBSD 12.
Tested on a ThinkPad T61.
[ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]
----------------------------------------------------------------------------
10 files changed, 533 insertions(+), 479 deletions(-)
src/add-ons/kernel/drivers/network/wlan/Jamfile | 4 +-
.../network/wlan/iprowifi4965/dev/iwn/if_iwn.c | 916 +++++++++----------
.../wlan/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 +-
.../freebsd_network/compat/sys/taskqueue.h | 1 +
src/libs/compat/freebsd_network/taskqueue.c | 22 +
############################################################################
Commit: 27632129b22f7b7a8dd67be4dea489ba25abf792
URL: https://git.haiku-os.org/haiku/commit/?id=27632129b22f
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Jan 9 01:52:06 2019 UTC
freebsd_network: Implement taskqueue_drain_all.
Required by FreeBSD 12's iprowifi4965.
----------------------------------------------------------------------------
diff --git a/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
index 2767b321c7..f8d5c7363e 100644
--- a/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
+++ b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h
@@ -32,6 +32,7 @@ void taskqueue_free(struct taskqueue *tq);
void taskqueue_drain(struct taskqueue *tq, struct task *task);
void taskqueue_drain_timeout(struct taskqueue *queue,
struct timeout_task *timeout_task);
+void taskqueue_drain_all(struct taskqueue *tq);
void taskqueue_block(struct taskqueue *queue);
void taskqueue_unblock(struct taskqueue *queue);
int taskqueue_enqueue(struct taskqueue *tq, struct task *task);
diff --git a/src/libs/compat/freebsd_network/taskqueue.c
b/src/libs/compat/freebsd_network/taskqueue.c
index 33826a8ad4..01dfdb918e 100644
--- a/src/libs/compat/freebsd_network/taskqueue.c
+++ b/src/libs/compat/freebsd_network/taskqueue.c
@@ -293,6 +293,28 @@ taskqueue_drain_timeout(struct taskqueue *queue,
}
+static void
+taskqueue_task_nop_fn(void* context, int pending)
+{
+}
+
+
+void
+taskqueue_drain_all(struct taskqueue *taskQueue)
+{
+ struct task t_barrier;
+
+ if (taskQueue == NULL) {
+ printf("taskqueue_drain_all called with NULL taskqueue\n");
+ return;
+ }
+
+ TASK_INIT(&t_barrier, USHRT_MAX, taskqueue_task_nop_fn, &t_barrier);
+ taskqueue_enqueue(taskQueue, &t_barrier);
+ taskqueue_drain(taskQueue, &t_barrier);
+}
+
+
static void
taskqueue_enqueue_locked(struct taskqueue *taskQueue, struct task *task,
cpu_status status)
############################################################################
Revision: hrev52730
Commit: 4e5a521c2adf5efa14b277e53ddfaf0fa0ea61a5
URL: https://git.haiku-os.org/haiku/commit/?id=4e5a521c2adf
Author: Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date: Wed Jan 9 01:54:21 2019 UTC
iprowifi4965: Upgrade to FreeBSD 12.
Tested on a ThinkPad T61.
----------------------------------------------------------------------------
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 <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: releng/12.0/sys/dev/iwn/if_iwn.c 338949 2018-09-26
17:12:30Z imp $");
#include <sys/param.h>
#include <sys/sockio.h>
@@ -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,30 +4609,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
} else
flags |= IWN_TX_NEED_CTS | IWN_TX_FULL_TXOP;
}
- if (type == IEEE80211_FC0_TYPE_MGT) {
- uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
- /* Tell HW to set timestamp in probe responses. */
- if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
- flags |= IWN_TX_INSERT_TSTAMP;
-
- if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
- subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
- tx->timeout = htole16(3);
- else
- tx->timeout = htole16(2);
- } 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;
+ if (ieee80211_radiotap_active_vap(vap)) {
+ struct iwn_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_flags = 0;
tap->wt_rate = rate;
@@ -4770,28 +4619,90 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
ieee80211_radiotap_tx(vap, m);
}
- tx->len = htole16(totlen);
+ 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;
+
+ /* Tell HW to set timestamp in probe responses. */
+ if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+ flags |= IWN_TX_INSERT_TSTAMP;
+
+ if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
+ subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
+ tx->timeout = htole16(3);
+ else
+ tx->timeout = htole16(2);
+ } else
+ tx->timeout = htole16(0);
+
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) \