From 8dc03de632faeed754033a549eec60b411308cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 11 Apr 2011 22:48:42 +0000 Subject: [PATCH] merged changes from 8.2 FreeBSD release for most wlan drivers and net80211. updated several firmwares for iprowifi4965 and iprowifi3945. Tested on iprowifi4965 only. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41240 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/wlan/aironetwifi/dev/an/if_an.c | 4 +- .../wlan/broadcom43xx/dev/bwi/if_bwi.c | 51 +- .../wlan/broadcom43xx/dev/bwi/if_bwi_pci.c | 2 +- .../wlan/broadcom43xx/dev/bwi/if_bwivar.h | 7 - .../wlan/iprowifi2200/dev/iwi/if_iwi.c | 42 +- .../wlan/iprowifi2200/dev/iwi/if_iwivar.h | 1 + .../drivers/network/wlan/iprowifi3945/Jamfile | 4 +- .../wlan/iprowifi3945/dev/wpi/if_wpi.c | 114 +-- .../wlan/iprowifi3945/dev/wpi/if_wpivar.h | 7 - .../drivers/network/wlan/iprowifi3945/glue.c | 2 +- .../drivers/network/wlan/iprowifi4965/Jamfile | 14 +- .../wlan/iprowifi4965/dev/iwn/if_iwn.c | 680 ++++++++++++------ .../wlan/iprowifi4965/dev/iwn/if_iwnreg.h | 33 +- .../wlan/iprowifi4965/dev/iwn/if_iwnvar.h | 25 +- .../drivers/network/wlan/iprowifi4965/glue.c | 10 +- .../wlan/marvell88w8335/dev/malo/if_malo.c | 6 +- .../marvell88w8335/dev/malo/if_malo_pci.c | 2 +- .../wlan/marvell88w8363/dev/mwl/if_mwl.c | 4 +- .../wlan/marvell88w8363/dev/mwl/if_mwl_pci.c | 4 +- .../network/wlan/ralinkwifi/dev/ral/rt2560.c | 68 +- .../wlan/ralinkwifi/dev/ral/rt2560var.h | 7 - .../network/wlan/ralinkwifi/dev/ral/rt2661.c | 58 +- .../wlan/ralinkwifi/dev/ral/rt2661var.h | 7 - .../network/wlan/wavelanwifi/dev/wi/if_wi.c | 4 +- .../freebsd_network/compat/net/if_var.h | 1 + src/libs/compat/freebsd_network/if.c | 188 +++-- src/libs/compat/freebsd_wlan/net80211/Jamfile | 3 + .../compat/freebsd_wlan/net80211/ieee80211.c | 10 +- .../freebsd_wlan/net80211/ieee80211_action.c | 2 +- .../freebsd_wlan/net80211/ieee80211_adhoc.c | 3 +- .../freebsd_wlan/net80211/ieee80211_amrr.c | 145 +++- .../freebsd_wlan/net80211/ieee80211_amrr.h | 40 -- .../net80211/ieee80211_crypto_tkip.c | 1 + .../freebsd_wlan/net80211/ieee80211_haiku.h | 27 + .../freebsd_wlan/net80211/ieee80211_hostap.c | 13 +- .../freebsd_wlan/net80211/ieee80211_hwmp.c | 92 +-- .../freebsd_wlan/net80211/ieee80211_input.c | 15 +- .../freebsd_wlan/net80211/ieee80211_ioctl.c | 15 +- .../freebsd_wlan/net80211/ieee80211_mesh.c | 18 +- .../freebsd_wlan/net80211/ieee80211_mesh.h | 2 + .../freebsd_wlan/net80211/ieee80211_node.h | 3 +- .../freebsd_wlan/net80211/ieee80211_output.c | 20 +- .../freebsd_wlan/net80211/ieee80211_proto.c | 2 - .../freebsd_wlan/net80211/ieee80211_proto.h | 6 +- .../freebsd_wlan/net80211/ieee80211_ratectl.c | 92 +++ .../freebsd_wlan/net80211/ieee80211_ratectl.h | 22 +- .../net80211/ieee80211_ratectl_none.c | 114 +++ .../net80211/ieee80211_rssadapt.c | 152 +++- .../net80211/ieee80211_rssadapt.h | 32 +- .../net80211/ieee80211_scan_sta.c | 50 +- .../freebsd_wlan/net80211/ieee80211_sta.c | 11 +- .../freebsd_wlan/net80211/ieee80211_tdma.c | 2 + .../freebsd_wlan/net80211/ieee80211_var.h | 26 +- .../freebsd_wlan/net80211/ieee80211_wds.c | 3 +- 54 files changed, 1498 insertions(+), 768 deletions(-) create mode 100644 src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.c create mode 100644 src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl_none.c diff --git a/src/add-ons/kernel/drivers/network/wlan/aironetwifi/dev/an/if_an.c b/src/add-ons/kernel/drivers/network/wlan/aironetwifi/dev/an/if_an.c index 1347af5c85..63cface801 100644 --- a/src/add-ons/kernel/drivers/network/wlan/aironetwifi/dev/an/if_an.c +++ b/src/add-ons/kernel/drivers/network/wlan/aironetwifi/dev/an/if_an.c @@ -773,8 +773,8 @@ an_attach(struct an_softc *sc, int unit, int flags) ifp->if_watchdog = an_watchdog; ifp->if_init = an_init; ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c index fefc55b931..450605888f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi.c @@ -64,8 +64,8 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include +#include #include @@ -112,9 +112,6 @@ static void bwi_set_channel(struct ieee80211com *); static void bwi_scan_end(struct ieee80211com *); static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void bwi_updateslot(struct ifnet *); -static struct ieee80211_node *bwi_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); -static void bwi_newassoc(struct ieee80211_node *, int); static int bwi_media_change(struct ifnet *); static void bwi_calibrate(void *); @@ -465,8 +462,8 @@ bwi_attach(struct bwi_softc *sc) ifp->if_ioctl = bwi_ioctl; ifp->if_start = bwi_start; ifp->if_watchdog = bwi_watchdog; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); /* @@ -525,7 +522,6 @@ bwi_attach(struct bwi_softc *sc) ic->ic_vap_delete = bwi_vap_delete; ic->ic_raw_xmit = bwi_raw_xmit; ic->ic_updateslot = bwi_updateslot; - ic->ic_node_alloc = bwi_node_alloc; ic->ic_scan_start = bwi_scan_start; ic->ic_scan_end = bwi_scan_end; ic->ic_set_channel = bwi_set_channel; @@ -620,10 +616,7 @@ bwi_vap_create(struct ieee80211com *ic, #if 0 vap->iv_update_beacon = bwi_beacon_update; #endif - ieee80211_amrr_init(&bvp->bv_amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /*ms*/); + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status); @@ -636,7 +629,7 @@ bwi_vap_delete(struct ieee80211vap *vap) { struct bwi_vap *bvp = BWI_VAP(vap); - ieee80211_amrr_cleanup(&bvp->bv_amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(bvp, M_80211_VAP); } @@ -1782,7 +1775,6 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) enum ieee80211_state ostate = vap->iv_state; struct bwi_softc *sc = ifp->if_softc; struct bwi_mac *mac; - struct ieee80211_node *ni = vap->iv_bss; int error; BWI_LOCK(sc); @@ -1830,10 +1822,6 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #else sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; #endif - if (vap->iv_opmode == IEEE80211_M_STA) { - /* fake a join to init the tx rate */ - bwi_newassoc(ni, 1); - } callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc); } @@ -1843,25 +1831,6 @@ back: return error; } -/* ARGUSED */ -static struct ieee80211_node * -bwi_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct bwi_node *bn; - - bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO); - return bn != NULL ? &bn->ni : NULL; -} - -static void -bwi_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&BWI_VAP(vap)->bv_amrr, - &BWI_NODE(ni)->amn, ni); -} - static int bwi_media_change(struct ifnet *ifp) { @@ -3013,7 +2982,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = rate_fb = tp->ucastrate; } else { - rix = ieee80211_amrr_choose(ni, &BWI_NODE(ni)->amn); + rix = ieee80211_ratectl_rate(ni, NULL, pkt_len); rate = ni->ni_txrate; if (rix > 0) { @@ -3370,6 +3339,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) struct bwi_txbuf *tb; int ring_idx, buf_idx; struct ieee80211_node *ni; + struct ieee80211vap *vap; if (tx_id == 0) { if_printf(ifp, "%s: zero tx id\n", __func__); @@ -3395,9 +3365,9 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) ni = tb->tb_ni; if (tb->tb_ni != NULL) { - struct bwi_node *bn = (struct bwi_node *) tb->tb_ni; const struct bwi_txbuf_hdr *hdr = mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); + vap = ni->ni_vap; /* NB: update rate control only for unicast frames */ if (hdr->txh_mac_ctrl & htole32(BWI_TXH_MAC_C_ACK)) { @@ -3408,8 +3378,9 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) * well so to avoid over-aggressive downshifting we * treat any number of retries as "1". */ - ieee80211_amrr_tx_complete(&bn->amn, acked, - data_txcnt > 1); + ieee80211_ratectl_tx_complete(vap, ni, + (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : + IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); } /* diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c index eab1accc39..fdf282b4bb 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwi_pci.c @@ -92,7 +92,7 @@ static const struct bwi_dev { { PCI_VENDOR_BROADCOM, 0x4318,"Broadcom BCM4318 802.11b/g Wireless Lan" }, { PCI_VENDOR_BROADCOM, 0x4319,"Broadcom BCM4318 802.11a/b/g Wireless Lan" }, { PCI_VENDOR_BROADCOM, 0x431a,"Broadcom BCM4318 802.11a Wireless Lan" }, - { 0, 0, NULL} + { 0, 0, NULL } }; static int diff --git a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h index 43628bb745..e89ec1a020 100644 --- a/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/broadcom43xx/dev/bwi/if_bwivar.h @@ -533,15 +533,8 @@ struct bwi_rx_radiotap_hdr { /* TODO: sq */ }; -struct bwi_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define BWI_NODE(ni) ((struct bwi_node *)(ni)) - struct bwi_vap { struct ieee80211vap bv_vap; - struct ieee80211_amrr bv_amrr; int (*bv_newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c index 4933e83327..f9ed03b481 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwi.c @@ -180,6 +180,7 @@ static void iwi_release_fw_dma(struct iwi_softc *sc); static int iwi_config(struct iwi_softc *); static int iwi_get_firmware(struct iwi_softc *, enum ieee80211_opmode); static void iwi_put_firmware(struct iwi_softc *); +static void iwi_monitor_scan(void *, int); static int iwi_scanchan(struct iwi_softc *, unsigned long, int); static void iwi_scan_start(struct ieee80211com *); static void iwi_scan_end(struct ieee80211com *); @@ -292,6 +293,7 @@ iwi_attach(device_t dev) TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc); TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc); TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, sc); + TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc); callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0); callout_init_mtx(&sc->sc_rftimer, &sc->sc_mtx, 0); @@ -363,8 +365,8 @@ iwi_attach(device_t dev) ifp->if_init = iwi_init; ifp->if_ioctl = iwi_ioctl; ifp->if_start = iwi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; @@ -460,6 +462,7 @@ iwi_detach(device_t dev) ieee80211_draintask(ic, &sc->sc_radiofftask); ieee80211_draintask(ic, &sc->sc_restarttask); ieee80211_draintask(ic, &sc->sc_disassoctask); + ieee80211_draintask(ic, &sc->sc_monitortask); iwi_stop(sc); @@ -988,7 +991,8 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * This is all totally bogus and needs to be redone. */ iwi_auth_and_assoc(sc, vap); - } + } else if (vap->iv_opmode == IEEE80211_M_MONITOR) + ieee80211_runtask(ic, &sc->sc_monitortask); break; case IEEE80211_S_ASSOC: /* @@ -1364,7 +1368,7 @@ iwi_checkforqos(struct ieee80211vap *vap, ni = vap->iv_bss; ni->ni_capinfo = capinfo; - ni->ni_associd = associd; + ni->ni_associd = associd & 0x3fff; if (wme != NULL) ni->ni_flags |= IEEE80211_NODE_QOS; else @@ -1407,6 +1411,18 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) IWI_STATE_END(sc, IWI_FW_SCANNING); + /* + * Monitor mode works by doing a passive scan to set + * the channel and enable rx. Because we don't want + * to abort a scan lest the firmware crash we scan + * for a short period of time and automatically restart + * the scan when notified the sweep has completed. + */ + if (vap->iv_opmode == IEEE80211_M_MONITOR) { + ieee80211_runtask(ic, &sc->sc_monitortask); + break; + } + if (scan->status == IWI_SCAN_COMPLETED) { /* NB: don't need to defer, net80211 does it for us */ ieee80211_scan_next(vap); @@ -1467,7 +1483,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) IWI_STATE_END(sc, IWI_FW_ASSOCIATING); iwi_checkforqos(vap, (const struct ieee80211_frame *)(assoc+1), - le16toh(notif->len) - sizeof(*assoc)); + le16toh(notif->len) - sizeof(*assoc) - 1); ieee80211_new_state(vap, IEEE80211_S_RUN, -1); break; case IWI_ASSOC_INIT: @@ -2561,6 +2577,11 @@ iwi_config(struct iwi_softc *sc) config.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0; config.disable_unicast_decryption = 1; config.disable_multicast_decryption = 1; + if (ic->ic_opmode == IEEE80211_M_MONITOR) { + config.allow_invalid_frames = 1; + config.allow_beacon_and_probe_resp = 1; + config.allow_mgt = 1; + } DPRINTF(("Configuring adapter\n")); error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config); if (error != 0) @@ -2646,6 +2667,17 @@ scan_band(const struct ieee80211_channel *c) return IEEE80211_IS_CHAN_5GHZ(c) ? IWI_CHAN_5GHZ : IWI_CHAN_2GHZ; } +static void +iwi_monitor_scan(void *arg, int npending) +{ + struct iwi_softc *sc = arg; + IWI_LOCK_DECL; + + IWI_LOCK(sc); + (void) iwi_scanchan(sc, 2000, 0); + IWI_UNLOCK(sc); +} + /* * Start a scan on the current channel or all channels. */ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h index 19568979bf..10d5bba9df 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi2200/dev/iwi/if_iwivar.h @@ -193,6 +193,7 @@ struct iwi_softc { struct task sc_restarttask; /* restart adapter processing */ struct task sc_disassoctask; struct task sc_wmetask; /* set wme parameters */ + struct task sc_monitortask; unsigned int sc_softled : 1, /* enable LED gpio status */ sc_ledstate: 1, /* LED on/off state */ diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/Jamfile b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/Jamfile index c5ad69649b..76f022480c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/Jamfile @@ -23,7 +23,7 @@ KernelAddon iprowifi3945 : libfreebsd_network.a ; -HAIKU_WIFI_FIRMWARE_PACKAGE on iprowifi3945 = iwlwifi-3945-ucode-2.14.1.5 ; -HAIKU_WIFI_FIRMWARE_ARCHIVE on iprowifi3945 = iwlwifi-3945-ucode-2.14.1.5.tgz ; +HAIKU_WIFI_FIRMWARE_PACKAGE on iprowifi3945 = iwlwifi-3945-ucode-15.32.2.9 ; +HAIKU_WIFI_FIRMWARE_ARCHIVE on iprowifi3945 = iwlwifi-3945-ucode-15.32.2.9.tgz ; HAIKU_WIFI_FIRMWARE_DO_EXTRACT on iprowifi3945 = true ; diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c index 0a0d2c63fc..7d8721a92f 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpi.c @@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -126,7 +127,7 @@ enum { WPI_DEBUG_ANY = 0xffffffff }; -static int wpi_debug = 1; +static int wpi_debug = 0; SYSCTL_INT(_debug, OID_AUTO, wpi, CTLFLAG_RW, &wpi_debug, 0, "wpi debug level"); TUNABLE_INT("debug.wpi", &wpi_debug); @@ -173,8 +174,6 @@ static int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *, int, int); static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); static void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *); -static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *, - const uint8_t mac[IEEE80211_ADDR_LEN]); static int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void wpi_mem_lock(struct wpi_softc *); static void wpi_mem_unlock(struct wpi_softc *); @@ -235,7 +234,6 @@ static void wpi_init_locked(struct wpi_softc *, int); static void wpi_stop(struct wpi_softc *); static void wpi_stop_locked(struct wpi_softc *); -static void wpi_newassoc(struct ieee80211_node *, int); static int wpi_set_txpower(struct wpi_softc *, struct ieee80211_channel *, int); static void wpi_calib_timeout(void *); @@ -665,14 +663,12 @@ wpi_attach(device_t dev) ifp->if_init = wpi_init; ifp->if_ioctl = wpi_ioctl; ifp->if_start = wpi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ieee80211_ifattach(ic, macaddr); /* override default methods */ - ic->ic_node_alloc = wpi_node_alloc; - ic->ic_newassoc = wpi_newassoc; ic->ic_raw_xmit = wpi_raw_xmit; ic->ic_wme.wme_update = wpi_wme_update; ic->ic_scan_start = wpi_scan_start; @@ -716,13 +712,14 @@ wpi_detach(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic; int ac; - ieee80211_draintask(ic, &sc->sc_restarttask); - ieee80211_draintask(ic, &sc->sc_radiotask); - if (ifp != NULL) { + ic = ifp->if_l2com; + + ieee80211_draintask(ic, &sc->sc_restarttask); + ieee80211_draintask(ic, &sc->sc_radiotask); wpi_stop(sc); callout_drain(&sc->watchdog_to); callout_drain(&sc->calib_to); @@ -786,11 +783,7 @@ wpi_vap_create(struct ieee80211com *ic, wvp->newstate = vap->iv_newstate; vap->iv_newstate = wpi_newstate; - ieee80211_amrr_init(&wvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /*ms*/); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); ic->ic_opmode = opmode; @@ -802,7 +795,7 @@ wpi_vap_delete(struct ieee80211vap *vap) { struct wpi_vap *wvp = WPI_VAP(vap); - ieee80211_amrr_cleanup(&wvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(wvp, M_80211_VAP); } @@ -1062,9 +1055,18 @@ wpi_free_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring) wpi_dma_contig_free(&ring->desc_dma); - for (i = 0; i < WPI_RX_RING_COUNT; i++) - if (ring->data[i].m != NULL) - m_freem(ring->data[i].m); + for (i = 0; i < WPI_RX_RING_COUNT; i++) { + struct wpi_rx_data *data = &ring->data[i]; + + if (data->m != NULL) { + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + } + if (data->map != NULL) + bus_dmamap_destroy(ring->data_dmat, data->map); + } } static int @@ -1240,18 +1242,6 @@ wpi_resume(device_t dev) return 0; } -/* ARGSUSED */ -static struct ieee80211_node * -wpi_node_alloc(struct ieee80211vap *vap __unused, - const uint8_t mac[IEEE80211_ADDR_LEN] __unused) -{ - struct wpi_node *wn; - - wn = malloc(sizeof (struct wpi_node), M_80211_NODE, M_NOWAIT | M_ZERO); - - return &wn->ni; -} - /** * Called by net80211 when ever there is a change to 80211 state machine */ @@ -1270,8 +1260,25 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) IEEE80211_UNLOCK(ic); WPI_LOCK(sc); - if (nstate == IEEE80211_S_AUTH) { - /* The node must be registered in the firmware before auth */ + if (nstate == IEEE80211_S_SCAN && vap->iv_state != IEEE80211_S_INIT) { + /* + * On !INIT -> SCAN transitions, we need to clear any possible + * knowledge about associations. + */ + error = wpi_config(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: device config failed, error %d\n", + __func__, error); + } + } + if (nstate == IEEE80211_S_AUTH || + (nstate == IEEE80211_S_ASSOC && vap->iv_state == IEEE80211_S_RUN)) { + /* + * The node must be registered in the firmware before auth. + * Also the associd must be cleared on RUN -> ASSOC + * transitions. + */ error = wpi_auth(sc, vap); if (error != 0) { device_printf(sc->sc_dev, @@ -1466,6 +1473,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc, return; } + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len); tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + le16toh(head->len)); @@ -1496,6 +1504,8 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc, ifp->if_ierrors++; return; } + bus_dmamap_unload(ring->data_dmat, data->map); + error = bus_dmamap_load(ring->data_dmat, data->map, mtod(mnew, caddr_t), MJUMPAGESIZE, wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT); @@ -1571,7 +1581,9 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; struct wpi_tx_data *txdata = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); - struct wpi_node *wn = (struct wpi_node *)txdata->ni; + struct ieee80211_node *ni = txdata->ni; + struct ieee80211vap *vap = ni->ni_vap; + int retrycnt = 0; DPRINTFN(WPI_DEBUG_TX, ("tx done: qid=%d idx=%d retries=%d nkill=%d " "rate=%x duration=%d status=%x\n", desc->qid, desc->idx, @@ -1584,11 +1596,12 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc) * the lowest available bit-rate. * XXX frames w/o ACK shouldn't be used either */ - wn->amn.amn_txcnt++; if (stat->ntries > 0) { DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries)); - wn->amn.amn_retrycnt++; + retrycnt = 1; } + ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); /* XXX oerrors should only count errors !maxtries */ if ((le32toh(stat->status) & 0xff) != 1) @@ -1647,9 +1660,15 @@ wpi_notif_intr(struct wpi_softc *sc) struct wpi_rx_data *data; uint32_t hw; + bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map, + BUS_DMASYNC_POSTREAD); + hw = le32toh(sc->shared->next); while (sc->rxq.cur != hw) { data = &sc->rxq.data[sc->rxq.cur]; + + bus_dmamap_sync(sc->rxq.data_dmat, data->map, + BUS_DMASYNC_POSTREAD); desc = (void *)data->m->m_ext.ext_buf; DPRINTFN(WPI_DEBUG_NOTIFY, @@ -1928,7 +1947,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &WPI_NODE(ni)->amn); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } tx->rate = wpi_plcp_signal(rate); @@ -2436,6 +2455,9 @@ wpi_auth(struct wpi_softc *sc, struct ieee80211vap *vap) if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) { sc->config.flags |= htole32(WPI_CONFIG_AUTO | WPI_CONFIG_24GHZ); + } else { + sc->config.flags &= ~htole32(WPI_CONFIG_AUTO | + WPI_CONFIG_24GHZ); } if (IEEE80211_IS_CHAN_A(ni->ni_chan)) { sc->config.cck_mask = 0; @@ -3011,14 +3033,12 @@ wpi_rfkill_resume(struct wpi_softc *sc) if (ntries == 1000) { device_printf(sc->sc_dev, "timeout waiting for thermal calibration\n"); - WPI_UNLOCK(sc); return; } DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp)); if (wpi_config(sc) != 0) { device_printf(sc->sc_dev, "device config failed\n"); - WPI_UNLOCK(sc); return; } @@ -3220,15 +3240,6 @@ wpi_stop(struct wpi_softc *sc) WPI_UNLOCK(sc); } -static void -wpi_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - struct wpi_vap *wvp = WPI_VAP(vap); - - ieee80211_amrr_node_init(&wvp->amrr, &WPI_NODE(ni)->amn, ni); -} - static void wpi_calib_timeout(void *arg) { @@ -3562,7 +3573,9 @@ wpi_set_channel(struct ieee80211com *ic) * are already taken care of by their respective firmware commands. */ if (ic->ic_opmode == IEEE80211_M_MONITOR) { + WPI_LOCK(sc); error = wpi_config(sc); + WPI_UNLOCK(sc); if (error != 0) device_printf(sc->sc_dev, "error %d settting channel\n", error); @@ -3715,4 +3728,3 @@ static const char *wpi_cmd_str(int cmd) MODULE_DEPEND(wpi, pci, 1, 1, 1); MODULE_DEPEND(wpi, wlan, 1, 1, 1); MODULE_DEPEND(wpi, firmware, 1, 1, 1); -MODULE_DEPEND(wpi, wlan_amrr, 1, 1, 1); diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h index a4371d3ac1..09100c869e 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/dev/wpi/if_wpivar.h @@ -106,12 +106,6 @@ struct wpi_amrr { int recovery; }; -struct wpi_node { - struct ieee80211_node ni; /* must be the first */ - struct ieee80211_amrr_node amn; -}; -#define WPI_NODE(ni) ((struct wpi_node *)(ni)) - struct wpi_power_sample { uint8_t index; int8_t power; @@ -127,7 +121,6 @@ struct wpi_power_group { struct wpi_vap { struct ieee80211vap vap; - struct ieee80211_amrr amrr; int (*newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/glue.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/glue.c index 3df1b99e37..f989844692 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/glue.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi3945/glue.c @@ -23,7 +23,7 @@ NO_HAIKU_FBSD_MII_DRIVER(); NO_HAIKU_REENABLE_INTERRUPTS(); HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN); HAIKU_FIRMWARE_VERSION(2144); -HAIKU_FIRMWARE_NAME_MAP(1) = {{"wpifw", "iwlwifi-3945-1.ucode"}}; +HAIKU_FIRMWARE_NAME_MAP(1) = {{"wpifw", "iwlwifi-3945-2.ucode"}}; int diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/Jamfile b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/Jamfile index afaba42bc9..1e0bfca845 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/Jamfile @@ -25,12 +25,14 @@ KernelAddon iprowifi4965 : ; HAIKU_WIFI_FIRMWARE_PACKAGES on iprowifi4965 = - iwlwifi-1000-ucode-128.50.3.1 iwlwifi-4965-ucode-228.61.2.24 - iwlwifi-5000-ucode-8.24.2.12 iwlwifi-5150-ucode-8.24.2.2 - iwlwifi-6000-ucode-9.221.4.1 iwlwifi-6050-ucode-9.201.4.1 ; + iwlwifi-1000-ucode-39.31.5.1 iwlwifi-4965-ucode-228.61.2.24 + iwlwifi-5000-ucode-8.83.5.1 iwlwifi-5150-ucode-8.24.2.2 + iwlwifi-6000-ucode-9.221.4.1 iwlwifi-6000g2a-ucode-17.168.5.2 + iwlwifi-6050-ucode-41.28.5.1 ; HAIKU_WIFI_FIRMWARE_ARCHIVES on iprowifi4965 = - iwlwifi-1000-ucode-128.50.3.1.tgz iwlwifi-4965-ucode-228.61.2.24.tgz - iwlwifi-5000-ucode-8.24.2.12.tgz iwlwifi-5150-ucode-8.24.2.2.tgz - iwlwifi-6000-ucode-9.221.4.1.tgz iwlwifi-6050-ucode-9.201.4.1.tgz ; + iwlwifi-1000-ucode-39.31.5.1.tgz iwlwifi-4965-ucode-228.61.2.24.tgz + iwlwifi-5000-ucode-8.83.5.1.tgz iwlwifi-5150-ucode-8.24.2.2.tgz + iwlwifi-6000-ucode-9.221.4.1.tgz iwlwifi-6000g2a-ucode-17.168.5.2.tgz + iwlwifi-6050-ucode-41.28.5.1.tgz ; HAIKU_WIFI_FIRMWARE_DO_EXTRACT on iprowifi4965 = true ; 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 7324bacc41..ea035aefda 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 @@ -122,7 +122,6 @@ static void iwn_read_eeprom_channels(struct iwn_softc *, int, static void iwn_read_eeprom_enhinfo(struct iwn_softc *); static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN]); -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_rx_phy(struct iwn_softc *, struct iwn_rx_desc *, @@ -135,8 +134,6 @@ static void iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *, static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); #endif -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 *); static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *, @@ -220,8 +217,14 @@ static void iwn5000_ampdu_tx_start(struct iwn_softc *, struct ieee80211_node *, uint8_t, uint16_t); static void iwn5000_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t); #endif -static int iwn5000_query_calibration(struct iwn_softc *); -static int iwn5000_send_calibration(struct iwn_softc *); +static int iwn5000_send_calib_results(struct iwn_softc *); +static int iwn5000_save_calib_result(struct iwn_softc *, + struct iwn_phy_calib *, int, int); +static void iwn5000_free_calib_results(struct iwn_softc *); +static int iwn5000_chrystal_calib(struct iwn_softc *); +static int iwn5000_send_calib_query(struct iwn_softc *, uint32_t); +static int iwn5000_rx_calib_result(struct iwn_softc *, + struct iwn_rx_desc *, struct iwn_rx_data *); static int iwn5000_send_wimax_coex(struct iwn_softc *); static int iwn4965_post_alive(struct iwn_softc *); static int iwn5000_post_alive(struct iwn_softc *); @@ -231,6 +234,10 @@ static int iwn4965_load_firmware(struct iwn_softc *); static int iwn5000_load_firmware_section(struct iwn_softc *, uint32_t, const uint8_t *, int); static int iwn5000_load_firmware(struct iwn_softc *); +static int iwn_read_firmware_leg(struct iwn_softc *, + struct iwn_fw_info *); +static int iwn_read_firmware_tlv(struct iwn_softc *, + struct iwn_fw_info *, uint16_t); static int iwn_read_firmware(struct iwn_softc *); static int iwn_clock_wait(struct iwn_softc *); static int iwn_apm_init(struct iwn_softc *); @@ -310,7 +317,6 @@ static const struct iwn_ident iwn_ident_table [] = { { 0x8086, 0x423D, "Intel(R) PRO/Wireless 5150" }, { 0x8086, 0x4235, "Intel(R) PRO/Wireless 5300" }, { 0x8086, 0x4236, "Intel(R) PRO/Wireless 5300" }, - { 0x8086, 0x4236, "Intel(R) PRO/Wireless 5350" }, { 0x8086, 0x423A, "Intel(R) PRO/Wireless 5350" }, { 0x8086, 0x423B, "Intel(R) PRO/Wireless 5350" }, { 0x8086, 0x0083, "Intel(R) PRO/Wireless 1000" }, @@ -321,8 +327,17 @@ static const struct iwn_ident iwn_ident_table [] = { { 0x8086, 0x4239, "Intel(R) PRO/Wireless 6000" }, { 0x8086, 0x422B, "Intel(R) PRO/Wireless 6000" }, { 0x8086, 0x422C, "Intel(R) PRO/Wireless 6000" }, - { 0x8086, 0x0086, "Intel(R) PRO/Wireless 6050" }, - { 0x8086, 0x0087, "Intel(R) PRO/Wireless 6050" }, + { 0x8086, 0x0087, "Intel(R) PRO/Wireless 6250" }, + { 0x8086, 0x0089, "Intel(R) PRO/Wireless 6250" }, + { 0x8086, 0x0082, "Intel(R) PRO/Wireless 6205a" }, + { 0x8086, 0x0085, "Intel(R) PRO/Wireless 6205a" }, +#ifdef notyet + { 0x8086, 0x008a, "Intel(R) PRO/Wireless 6205b" }, + { 0x8086, 0x008b, "Intel(R) PRO/Wireless 6205b" }, + { 0x8086, 0x008f, "Intel(R) PRO/Wireless 6205b" }, + { 0x8086, 0x0090, "Intel(R) PRO/Wireless 6205b" }, + { 0x8086, 0x0091, "Intel(R) PRO/Wireless 6205b" }, +#endif { 0, 0, NULL } }; @@ -627,8 +642,8 @@ iwn_attach(device_t dev) ifp->if_init = iwn_init; ifp->if_ioctl = iwn_ioctl; ifp->if_start = iwn_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ieee80211_ifattach(ic, macaddr); @@ -636,7 +651,6 @@ iwn_attach(device_t dev) ic->ic_vap_delete = iwn_vap_delete; ic->ic_raw_xmit = iwn_raw_xmit; ic->ic_node_alloc = iwn_node_alloc; - ic->ic_newassoc = iwn_newassoc; ic->ic_wme.wme_update = iwn_wme_update; ic->ic_update_mcast = iwn_update_mcast; ic->ic_scan_start = iwn_scan_start; @@ -692,6 +706,9 @@ iwn_hal_attach(struct iwn_softc *sc) sc->fwname = "iwn5000fw"; sc->txchainmask = IWN_ANT_B; sc->rxchainmask = IWN_ANT_AB; + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_TX_IQ_PERIODIC | + IWN_CALIB_BASE_BAND; break; case IWN_HW_REV_TYPE_5150: sc->sc_hal = &iwn5000_hal; @@ -699,6 +716,8 @@ iwn_hal_attach(struct iwn_softc *sc) sc->fwname = "iwn5150fw"; sc->txchainmask = IWN_ANT_A; sc->rxchainmask = IWN_ANT_AB; + sc->calib_init = IWN_CALIB_DC | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND; break; case IWN_HW_REV_TYPE_5300: case IWN_HW_REV_TYPE_5350: @@ -707,6 +726,9 @@ iwn_hal_attach(struct iwn_softc *sc) sc->fwname = "iwn5000fw"; sc->txchainmask = IWN_ANT_ABC; sc->rxchainmask = IWN_ANT_ABC; + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_TX_IQ_PERIODIC | + IWN_CALIB_BASE_BAND; break; case IWN_HW_REV_TYPE_1000: sc->sc_hal = &iwn5000_hal; @@ -714,6 +736,9 @@ iwn_hal_attach(struct iwn_softc *sc) sc->fwname = "iwn1000fw"; sc->txchainmask = IWN_ANT_A; sc->rxchainmask = IWN_ANT_AB; + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_TX_IQ_PERIODIC | + IWN_CALIB_BASE_BAND; break; case IWN_HW_REV_TYPE_6000: sc->sc_hal = &iwn5000_hal; @@ -729,15 +754,31 @@ iwn_hal_attach(struct iwn_softc *sc) default: sc->txchainmask = IWN_ANT_ABC; sc->rxchainmask = IWN_ANT_ABC; + sc->calib_runtime = IWN_CALIB_DC; break; } + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND; break; case IWN_HW_REV_TYPE_6050: sc->sc_hal = &iwn5000_hal; sc->limits = &iwn6000_sensitivity_limits; - sc->fwname = "iwn6000fw"; + sc->fwname = "iwn6050fw"; sc->txchainmask = IWN_ANT_AB; sc->rxchainmask = IWN_ANT_AB; + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND; + sc->calib_runtime = IWN_CALIB_DC; + break; + case IWN_HW_REV_TYPE_6005: + sc->sc_hal = &iwn5000_hal; + sc->limits = &iwn6000_sensitivity_limits; + sc->fwname = "iwn6005fw"; + sc->txchainmask = IWN_ANT_AB; + sc->rxchainmask = IWN_ANT_AB; + sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO | + IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND; + sc->calib_runtime = IWN_CALIB_DC; break; default: device_printf(sc->sc_dev, "adapter type %d not supported\n", @@ -826,6 +867,8 @@ iwn_cleanup(device_t dev) ieee80211_ifdetach(ic); } + iwn5000_free_calib_results(sc); + /* Free DMA resources. */ iwn_free_rx_ring(sc, &sc->rxq); if (sc->sc_hal != NULL) @@ -1670,7 +1713,7 @@ iwn5000_read_eeprom(struct iwn_softc *sc) DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: calib version=%u pa type=%u voltage=%u\n", __func__, hdr.version, hdr.pa_type, le16toh(hdr.volt)); - sc->calib_ver = hdr.version; + sc->calib_ver = hdr.version; if (sc->hw_type == IWN_HW_REV_TYPE_5150) { /* Compute temperature offset. */ @@ -1681,12 +1724,6 @@ iwn5000_read_eeprom(struct iwn_softc *sc) sc->temp_off = temp - (volt / -5); DPRINTF(sc, IWN_DEBUG_CALIBRATE, "temp=%d volt=%d offset=%dK\n", temp, volt, sc->temp_off); - } else { - /* Read crystal calibration. */ - iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL, - &sc->eeprom_crystal, sizeof (uint32_t)); - DPRINTF(sc, IWN_DEBUG_CALIBRATE, "crystal calibration 0x%08x\n", - le32toh(sc->eeprom_crystal)); } } @@ -1894,15 +1931,6 @@ 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); } -static void -iwn_newassoc(struct ieee80211_node *ni, int isnew) -{ - /* XXX move */ -#if 0 - ieee80211_ratectl_node_init(ni); -#endif -} - static int iwn_media_change(struct ifnet *ifp) { @@ -1927,27 +1955,45 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) IWN_LOCK(sc); callout_stop(&sc->sc_timer_to); - if (nstate == IEEE80211_S_AUTH && vap->iv_state != IEEE80211_S_AUTH) { - /* !AUTH -> AUTH requires adapter config */ - /* Reset state to handle reassociations correctly. */ + switch (nstate) { + case IEEE80211_S_ASSOC: + if (vap->iv_state != IEEE80211_S_RUN) + break; + /* FALLTHROUGH */ + case IEEE80211_S_AUTH: + if (vap->iv_state == IEEE80211_S_AUTH) + break; + + /* + * !AUTH -> AUTH transition requires state reset to handle + * reassociations correctly. + */ sc->rxon.associd = 0; sc->rxon.filter &= ~htole32(IWN_FILTER_BSS); iwn_calib_reset(sc); error = iwn_auth(sc, vap); - } - if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) { + break; + + case IEEE80211_S_RUN: + /* + * RUN -> RUN transition; Just restart the timers. + */ + if (vap->iv_state == IEEE80211_S_RUN && + vap->iv_opmode != IEEE80211_M_MONITOR) { + iwn_calib_reset(sc); + break; + } + /* * !RUN -> RUN requires setting the association id * which is done with a firmware cmd. We also defer * starting the timers until that work is done. */ error = iwn_run(sc, vap); - } - if (nstate == IEEE80211_S_RUN) { - /* - * RUN -> RUN transition; just restart the timers. - */ - iwn_calib_reset(sc); + break; + + default: + break; } IWN_UNLOCK(sc); IEEE80211_LOCK(ic); @@ -2164,64 +2210,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, } #endif -/* - * Process a CALIBRATION_RESULT notification sent by the initialization - * 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) -{ - struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1); - int len, idx = -1; - - /* Runtime firmware should not send such a notification. */ - if (sc->sc_flags & IWN_FLAG_CALIB_DONE) - return; - - bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); - len = (le32toh(desc->len) & 0x3fff) - 4; - - switch (calib->code) { - case IWN5000_PHY_CALIB_DC: - if (sc->hw_type == IWN_HW_REV_TYPE_5150 || - sc->hw_type == IWN_HW_REV_TYPE_6050) - idx = 0; - break; - case IWN5000_PHY_CALIB_LO: - idx = 1; - break; - case IWN5000_PHY_CALIB_TX_IQ: - idx = 2; - break; - case IWN5000_PHY_CALIB_TX_IQ_PERIODIC: - if (sc->hw_type < IWN_HW_REV_TYPE_6000 && - sc->hw_type != IWN_HW_REV_TYPE_5150) - idx = 3; - break; - case IWN5000_PHY_CALIB_BASE_BAND: - idx = 4; - break; - } - if (idx == -1) /* Ignore other results. */ - return; - - /* Save calibration result. */ - if (sc->calibcmd[idx].buf != NULL) - free(sc->calibcmd[idx].buf, M_DEVBUF); - sc->calibcmd[idx].buf = malloc(len, M_DEVBUF, M_NOWAIT); - if (sc->calibcmd[idx].buf == NULL) { - DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "not enough memory for calibration result %d\n", - calib->code); - return; - } - DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "saving calibration result code=%d len=%d\n", calib->code, len); - sc->calibcmd[idx].len = len; - memcpy(sc->calibcmd[idx].buf, calib, len); -} - /* * Process an RX_STATISTICS or BEACON_STATISTICS firmware notification. * The latter is sent by the firmware after each received beacon. @@ -2579,7 +2567,7 @@ iwn_notif_intr(struct iwn_softc *sc) break; } case IWN5000_CALIBRATION_RESULT: - iwn5000_rx_calib_results(sc, desc, data); + iwn5000_rx_calib_result(sc, desc, data); break; case IWN5000_CALIBRATION_DONE: @@ -3022,7 +3010,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni, txant = IWN_LSB(sc->txchainmask); tx->rflags |= IWN_RFLAG_ANT(txant); } else { - tx->linkq = 0; + tx->linkq = IWN_RIDX_OFDM54 - ridx; flags |= IWN_TX_LINKQ; /* enable MRR */ } @@ -4134,10 +4122,14 @@ iwn_collect_noise(struct iwn_softc *sc, val = MAX(calib->rssi[2], val); /* Determine which antennas are connected. */ - sc->chainmask = 0; + sc->chainmask = sc->rxchainmask; for (i = 0; i < 3; i++) - if (val - calib->rssi[i] <= 15 * 20) - sc->chainmask |= 1 << i; + if (val - calib->rssi[i] > 15 * 20) + sc->chainmask &= ~(1 << i); + DPRINTF(sc, IWN_DEBUG_CALIBRATE, + "%s: RX chains mask: theoretical=0x%x, actual=0x%x\n", + __func__, sc->rxchainmask, sc->chainmask); + /* If none of the TX antennas are connected, keep at least one. */ if ((sc->chainmask & sc->txchainmask) == 0) sc->chainmask |= IWN_LSB(sc->txchainmask); @@ -4864,11 +4856,9 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap) struct iwn_node_info node; int error; - sc->calib.state = IWN_CALIB_STATE_INIT; - if (ic->ic_opmode == IEEE80211_M_MONITOR) { /* Link LED blinks while monitoring. */ - iwn_set_led(sc, IWN_LED_LINK, 5, 5); + iwn_set_led(sc, IWN_LED_LINK, 20, 20); return 0; } error = iwn_set_timing(sc, ni); @@ -5213,22 +5203,143 @@ iwn5000_ampdu_tx_stop(struct iwn_softc *sc, uint8_t tid, uint16_t ssn) #endif /* - * Query calibration tables from the initialization firmware. We do this - * only once at first boot. Called from a process context. + * Send calibration results to the runtime firmware. These results were + * obtained on first boot from the initialization firmware, or by reading + * the EEPROM for crystal calibration. */ static int -iwn5000_query_calibration(struct iwn_softc *sc) +iwn5000_send_calib_results(struct iwn_softc *sc) { + struct iwn_calib_info *calib_result; + int idx, error; + + for (idx = 0; idx < IWN_CALIB_NUM; idx++) { + calib_result = &sc->calib_results[idx]; + + /* No support for this type of calibration. */ + if ((sc->calib_init & (1 << idx)) == 0) + continue; + + /* No calibration result available. */ + if (calib_result->buf == NULL) + continue; + + DPRINTF(sc, IWN_DEBUG_CALIBRATE, + "%s: send calibration result idx=%d, len=%d\n", + __func__, idx, calib_result->len); + + error = iwn_cmd(sc, IWN_CMD_PHY_CALIB, calib_result->buf, + calib_result->len, 0); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not send calibration result " + "idx=%d, error=%d\n", + __func__, idx, error); + return error; + } + } + return 0; +} + +/* + * Save calibration result at the given index. The index determines + * in which order the results are sent to the runtime firmware. + */ +static int +iwn5000_save_calib_result(struct iwn_softc *sc, struct iwn_phy_calib *calib, + int len, int idx) +{ + struct iwn_calib_info *calib_result = &sc->calib_results[idx]; + + DPRINTF(sc, IWN_DEBUG_CALIBRATE, + "%s: saving calibration result code=%d, idx=%d, len=%d\n", + __func__, calib->code, idx, len); + + if (calib_result->buf != NULL) + free(calib_result->buf, M_DEVBUF); + + calib_result->buf = malloc(len, M_DEVBUF, M_NOWAIT); + if (calib_result->buf == NULL) { + device_printf(sc->sc_dev, + "%s: not enough memory for calibration result " + "code=%d, len=%d\n", __func__, calib->code, len); + return ENOMEM; + } + + calib_result->len = len; + memcpy(calib_result->buf, calib, len); + return 0; +} + +static void +iwn5000_free_calib_results(struct iwn_softc *sc) +{ + struct iwn_calib_info *calib_result; + int idx; + + for (idx = 0; idx < IWN_CALIB_NUM; idx++) { + calib_result = &sc->calib_results[idx]; + + if (calib_result->buf != NULL) + free(calib_result->buf, M_DEVBUF); + + calib_result->buf = NULL; + calib_result->len = 0; + } +} + +/* + * Obtain the crystal calibration result from the EEPROM. + */ +static int +iwn5000_chrystal_calib(struct iwn_softc *sc) +{ + struct iwn5000_phy_calib_crystal cmd; + uint32_t base, crystal; + uint16_t val; + + /* Read crystal calibration. */ + iwn_read_prom_data(sc, IWN5000_EEPROM_CAL, &val, 2); + base = le16toh(val); + iwn_read_prom_data(sc, base + IWN5000_EEPROM_CRYSTAL, &crystal, + sizeof(uint32_t)); + DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: crystal calibration=0x%08x\n", + __func__, le32toh(crystal)); + + memset(&cmd, 0, sizeof cmd); + cmd.code = IWN5000_PHY_CALIB_CRYSTAL; + cmd.ngroups = 1; + cmd.isvalid = 1; + cmd.cap_pin[0] = le32toh(crystal) & 0xff; + cmd.cap_pin[1] = (le32toh(crystal) >> 16) & 0xff; + + return iwn5000_save_calib_result(sc, (struct iwn_phy_calib *)&cmd, + sizeof cmd, IWN_CALIB_IDX_XTAL); +} + +/* + * Query calibration results from the initialization firmware. We do this + * only once at first boot. + */ +static int +iwn5000_send_calib_query(struct iwn_softc *sc, uint32_t cfg) +{ +#define CALIB_INIT_CFG 0xffffffff; struct iwn5000_calib_config cmd; int error; memset(&cmd, 0, sizeof cmd); - cmd.ucode.once.enable = 0xffffffff; - cmd.ucode.once.start = 0xffffffff; - cmd.ucode.once.send = 0xffffffff; - cmd.ucode.flags = 0xffffffff; - DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending calibration query\n", - __func__); + cmd.ucode.once.enable = CALIB_INIT_CFG; + if (cfg == 0) { + cmd.ucode.once.start = CALIB_INIT_CFG; + cmd.ucode.once.send = CALIB_INIT_CFG; + cmd.ucode.flags = CALIB_INIT_CFG; + } else + cmd.ucode.once.start = cfg; + + DPRINTF(sc, IWN_DEBUG_CALIBRATE, + "%s: query calibration results, cfg %x\n", __func__, cfg); + error = iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof cmd, 0); if (error != 0) return error; @@ -5236,34 +5347,56 @@ iwn5000_query_calibration(struct iwn_softc *sc) /* Wait at most two seconds for calibration to complete. */ if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE)) error = msleep(sc, &sc->sc_mtx, PCATCH, "iwninit", 2 * hz); + return error; +#undef CALIB_INIT_CFG } /* - * Send calibration results to the runtime firmware. These results were - * obtained on first boot from the initialization firmware. + * Process a CALIBRATION_RESULT notification sent by the initialization + * firmware on response to a CMD_CALIB_CONFIG command. */ static int -iwn5000_send_calibration(struct iwn_softc *sc) +iwn5000_rx_calib_result(struct iwn_softc *sc, struct iwn_rx_desc *desc, + struct iwn_rx_data *data) { - int idx, error; +#define FRAME_SIZE_MASK 0x3fff + struct iwn_phy_calib *calib = (struct iwn_phy_calib *)(desc + 1); + int len, idx; - for (idx = 0; idx < 5; idx++) { - if (sc->calibcmd[idx].buf == NULL) - continue; /* No results available. */ + bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); + len = (le32toh(desc->len) & FRAME_SIZE_MASK); + + /* Remove length field itself. */ + len -= 4; + + /* + * Determine the order in which the results will be send to the + * runtime firmware. + */ + switch (calib->code) { + case IWN5000_PHY_CALIB_DC: + idx = IWN_CALIB_IDX_DC; + break; + case IWN5000_PHY_CALIB_LO: + idx = IWN_CALIB_IDX_LO; + break; + case IWN5000_PHY_CALIB_TX_IQ: + idx = IWN_CALIB_IDX_TX_IQ; + break; + case IWN5000_PHY_CALIB_TX_IQ_PERIODIC: + idx = IWN_CALIB_IDX_TX_IQ_PERIODIC; + break; + case IWN5000_PHY_CALIB_BASE_BAND: + idx = IWN_CALIB_IDX_BASE_BAND; + break; + default: DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "send calibration result idx=%d len=%d\n", - idx, sc->calibcmd[idx].len); - error = iwn_cmd(sc, IWN_CMD_PHY_CALIB, sc->calibcmd[idx].buf, - sc->calibcmd[idx].len, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: could not send calibration result, error %d\n", - __func__, error); - return error; - } + "%s: unknown calibration code=%d\n", __func__, calib->code); + return EINVAL; } - return 0; + return iwn5000_save_calib_result(sc, calib, len, idx); +#undef FRAME_SIZE_MASK } static int @@ -5411,36 +5544,40 @@ iwn5000_post_alive(struct iwn_softc *sc) __func__, error); return error; } - if (sc->hw_type != IWN_HW_REV_TYPE_5150) { - struct iwn5000_phy_calib_crystal cmd; - /* Perform crystal calibration. */ - memset(&cmd, 0, sizeof cmd); - cmd.code = IWN5000_PHY_CALIB_CRYSTAL; - cmd.ngroups = 1; - cmd.isvalid = 1; - cmd.cap_pin[0] = le32toh(sc->eeprom_crystal) & 0xff; - cmd.cap_pin[1] = (le32toh(sc->eeprom_crystal) >> 16) & 0xff; - DPRINTF(sc, IWN_DEBUG_CALIBRATE, - "sending crystal calibration %d, %d\n", - cmd.cap_pin[0], cmd.cap_pin[1]); - error = iwn_cmd(sc, IWN_CMD_PHY_CALIB, &cmd, sizeof cmd, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "%s: crystal calibration failed, error %d\n", - __func__, error); - return error; - } - } if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE)) { - /* Query calibration from the initialization firmware. */ - error = iwn5000_query_calibration(sc); + /* + * Start calibration by setting and sending the chrystal + * calibration first, this must be done before we are able + * to query the other calibration results. + */ + error = iwn5000_chrystal_calib(sc); if (error != 0) { device_printf(sc->sc_dev, - "%s: could not query calibration, error %d\n", + "%s: could not set chrystal calibration, " + "error=%d\n", __func__, error); + return error; + } + error = iwn5000_send_calib_results(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not send chrystal calibration, " + "error=%d\n", __func__, error); + return error; + } + + /* + * Query other calibration results from the initialization + * firmware. + */ + error = iwn5000_send_calib_query(sc, 0); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not query calibration, error=%d\n", __func__, error); return error; } + /* * We have the calibration results now, reboot with the * runtime firmware (call ourselves recursively!) @@ -5448,8 +5585,24 @@ iwn5000_post_alive(struct iwn_softc *sc) iwn_hw_stop(sc); error = iwn_hw_init(sc); } else { - /* Send calibration results to runtime firmware. */ - error = iwn5000_send_calibration(sc); + /* + * Send calibration results obtained from the initialization + * firmware to the runtime firmware. + */ + error = iwn5000_send_calib_results(sc); + + /* + * Tell the runtime firmware to do certain calibration types. + */ + if (sc->calib_runtime != 0) { + error = iwn5000_send_calib_query(sc, sc->calib_runtime); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not send query calibration, " + "error=%d, cfg=%x\n", __func__, error, + sc->calib_runtime); + } + } } return error; } @@ -5642,17 +5795,159 @@ iwn5000_load_firmware(struct iwn_softc *sc) return 0; } +/* + * Extract text and data sections from a legacy firmware image. + */ +static int +iwn_read_firmware_leg(struct iwn_softc *sc, struct iwn_fw_info *fw) +{ + const uint32_t *ptr; + size_t hdrlen = 24; + uint32_t rev; + + ptr = (const uint32_t *)sc->fw_fp->data; + rev = le32toh(*ptr++); + + /* Check firmware API version. */ + if (IWN_FW_API(rev) <= 1) { + device_printf(sc->sc_dev, + "%s: bad firmware, need API version >=2\n", __func__); + return EINVAL; + } + if (IWN_FW_API(rev) >= 3) { + /* Skip build number (version 2 header). */ + hdrlen += 4; + ptr++; + } + if (fw->size < hdrlen) { + device_printf(sc->sc_dev, + "%s: firmware file too short: %zu bytes\n", + __func__, fw->size); + return EINVAL; + } + fw->main.textsz = le32toh(*ptr++); + fw->main.datasz = le32toh(*ptr++); + fw->init.textsz = le32toh(*ptr++); + fw->init.datasz = le32toh(*ptr++); + fw->boot.textsz = le32toh(*ptr++); + + /* Check that all firmware sections fit. */ + if (fw->size < hdrlen + fw->main.textsz + fw->main.datasz + + fw->init.textsz + fw->init.datasz + fw->boot.textsz) { + device_printf(sc->sc_dev, + "%s: firmware file too short: %zu bytes\n", + __func__, fw->size); + return EINVAL; + } + + /* Get pointers to firmware sections. */ + fw->main.text = (const uint8_t *)ptr; + fw->main.data = fw->main.text + fw->main.textsz; + fw->init.text = fw->main.data + fw->main.datasz; + fw->init.data = fw->init.text + fw->init.textsz; + fw->boot.text = fw->init.data + fw->init.datasz; + + return 0; +} + +/* + * Extract text and data sections from a TLV firmware image. + */ +int +iwn_read_firmware_tlv(struct iwn_softc *sc, struct iwn_fw_info *fw, + uint16_t alt) +{ + const struct iwn_fw_tlv_hdr *hdr; + const struct iwn_fw_tlv *tlv; + const uint8_t *ptr, *end; + uint64_t altmask; + uint32_t len; + + if (fw->size < sizeof (*hdr)) { + device_printf(sc->sc_dev, + "%s: firmware file too short: %zu bytes\n", + __func__, fw->size); + return EINVAL; + } + hdr = (const struct iwn_fw_tlv_hdr *)fw->data; + if (hdr->signature != htole32(IWN_FW_SIGNATURE)) { + device_printf(sc->sc_dev, + "%s: bad firmware file signature 0x%08x\n", + __func__, le32toh(hdr->signature)); + return EINVAL; + } + + /* + * Select the closest supported alternative that is less than + * or equal to the specified one. + */ + altmask = le64toh(hdr->altmask); + while (alt > 0 && !(altmask & (1ULL << alt))) + alt--; /* Downgrade. */ + + ptr = (const uint8_t *)(hdr + 1); + end = (const uint8_t *)(fw->data + fw->size); + + /* Parse type-length-value fields. */ + while (ptr + sizeof (*tlv) <= end) { + tlv = (const struct iwn_fw_tlv *)ptr; + len = le32toh(tlv->len); + + ptr += sizeof (*tlv); + if (ptr + len > end) { + device_printf(sc->sc_dev, + "%s: firmware file too short: %zu bytes\n", + __func__, fw->size); + return EINVAL; + } + /* Skip other alternatives. */ + if (tlv->alt != 0 && tlv->alt != htole16(alt)) + goto next; + + switch (le16toh(tlv->type)) { + case IWN_FW_TLV_MAIN_TEXT: + fw->main.text = ptr; + fw->main.textsz = len; + break; + case IWN_FW_TLV_MAIN_DATA: + fw->main.data = ptr; + fw->main.datasz = len; + break; + case IWN_FW_TLV_INIT_TEXT: + fw->init.text = ptr; + fw->init.textsz = len; + break; + case IWN_FW_TLV_INIT_DATA: + fw->init.data = ptr; + fw->init.datasz = len; + break; + case IWN_FW_TLV_BOOT_TEXT: + fw->boot.text = ptr; + fw->boot.textsz = len; + break; + default: + DPRINTF(sc, IWN_DEBUG_RESET, + "%s: TLV type %d not handled\n", + __func__, le16toh(tlv->type)); + break; + } +next: /* TLV fields are 32-bit aligned. */ + ptr += (len + 3) & ~3; + } + return 0; +} + static int iwn_read_firmware(struct iwn_softc *sc) { const struct iwn_hal *hal = sc->sc_hal; struct iwn_fw_info *fw = &sc->fw; - const uint32_t *ptr; - uint32_t rev; - size_t size; + int error; IWN_UNLOCK(sc); + memset(fw, 0, sizeof (*fw)); + /* Read firmware image from filesystem. */ sc->fw_fp = firmware_get(sc->fwname); if (sc->fw_fp == NULL) { @@ -5664,63 +5959,39 @@ iwn_read_firmware(struct iwn_softc *sc) } IWN_LOCK(sc); - size = sc->fw_fp->datasize; - if (size < 28) { + fw->size = sc->fw_fp->datasize; + fw->data = (const uint8_t *)sc->fw_fp->data; + if (fw->size < sizeof (uint32_t)) { device_printf(sc->sc_dev, - "%s: truncated firmware header: %zu bytes\n", - __func__, size); + "%s: firmware file too short: %zu bytes\n", + __func__, fw->size); return EINVAL; } - /* Process firmware header. */ - ptr = (const uint32_t *)sc->fw_fp->data; - rev = le32toh(*ptr++); - /* Check firmware API version. */ - if (IWN_FW_API(rev) <= 1) { + /* Retrieve text and data sections. */ + if (*(const uint32_t *)fw->data != 0) /* Legacy image. */ + error = iwn_read_firmware_leg(sc, fw); + else + error = iwn_read_firmware_tlv(sc, fw, 1); + if (error != 0) { device_printf(sc->sc_dev, - "%s: bad firmware, need API version >=2\n", __func__); - return EINVAL; + "%s: could not read firmware sections\n", __func__); + return error; } - if (IWN_FW_API(rev) >= 3) { - /* Skip build number (version 2 header). */ - size -= 4; - ptr++; - } - fw->main.textsz = le32toh(*ptr++); - fw->main.datasz = le32toh(*ptr++); - fw->init.textsz = le32toh(*ptr++); - fw->init.datasz = le32toh(*ptr++); - fw->boot.textsz = le32toh(*ptr++); - size -= 24; - /* Sanity-check firmware header. */ + /* Make sure text and data sections fit in hardware memory. */ if (fw->main.textsz > hal->fw_text_maxsz || fw->main.datasz > hal->fw_data_maxsz || fw->init.textsz > hal->fw_text_maxsz || fw->init.datasz > hal->fw_data_maxsz || fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ || (fw->boot.textsz & 3) != 0) { - device_printf(sc->sc_dev, "%s: invalid firmware header\n", - __func__); - return EINVAL; - } - - /* Check that all firmware sections fit. */ - if (fw->main.textsz + fw->main.datasz + fw->init.textsz + - fw->init.datasz + fw->boot.textsz > size) { device_printf(sc->sc_dev, - "%s: firmware file too short: %zu bytes\n", - __func__, size); + "%s: firmware sections too large\n", __func__); return EINVAL; } - /* Get pointers to firmware sections. */ - fw->main.text = (const uint8_t *)ptr; - fw->main.data = fw->main.text + fw->main.textsz; - fw->init.text = fw->main.data + fw->main.datasz; - fw->init.data = fw->init.text + fw->init.textsz; - fw->boot.text = fw->init.data + fw->init.datasz; - + /* We can proceed with loading the firmware. */ return 0; } @@ -5769,8 +6040,7 @@ iwn_apm_init(struct iwn_softc *sc) IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA); if (sc->hw_type != IWN_HW_REV_TYPE_4965 && - sc->hw_type != IWN_HW_REV_TYPE_6000 && - sc->hw_type != IWN_HW_REV_TYPE_6050) + sc->hw_type <= IWN_HW_REV_TYPE_1000) IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT); /* Wait for clock stabilization before accessing prph. */ @@ -5885,9 +6155,9 @@ iwn5000_nic_config(struct iwn_softc *sc) /* Use internal power amplifier only. */ IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA); } - if (sc->hw_type == IWN_HW_REV_TYPE_6050 && sc->calib_ver >= 6) { - /* Indicate that ROM calibration version is >=6. */ - IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6); + if (sc->hw_type == IWN_HW_REV_TYPE_6050 && sc->calib_ver >= 6) { + /* Indicate that ROM calibration version is >=6. */ + IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6); } return 0; } 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 06e03ec744..c0230091ef 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,5 +1,5 @@ /* $FreeBSD$ */ -/* $OpenBSD: if_iwnreg.h,v 1.37 2010/02/17 18:23:00 damien Exp $ */ +/* $OpenBSD: if_iwnreg.h,v 1.40 2010/05/05 19:41:57 damien Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -204,6 +204,7 @@ #define IWN_HW_REV_TYPE_1000 6 #define IWN_HW_REV_TYPE_6000 7 #define IWN_HW_REV_TYPE_6050 8 +#define IWN_HW_REV_TYPE_6005 11 /* Possible flags for register IWN_GIO_CHICKEN. */ #define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23) @@ -1259,6 +1260,34 @@ struct iwn_fw_dump { uint32_t time[2]; } __packed; +/* TLV firmware header. */ +struct iwn_fw_tlv_hdr { + uint32_t zero; /* Always 0, to differentiate from legacy. */ + uint32_t signature; +#define IWN_FW_SIGNATURE 0x0a4c5749 /* "IWL\n" */ + + uint8_t descr[64]; + uint32_t rev; +#define IWN_FW_API(x) (((x) >> 8) & 0xff) + + uint32_t build; + uint64_t altmask; +} __packed; + +/* TLV header. */ +struct iwn_fw_tlv { + uint16_t type; +#define IWN_FW_TLV_MAIN_TEXT 1 +#define IWN_FW_TLV_MAIN_DATA 2 +#define IWN_FW_TLV_INIT_TEXT 3 +#define IWN_FW_TLV_INIT_DATA 4 +#define IWN_FW_TLV_BOOT_TEXT 5 +#define IWN_FW_TLV_PBREQ_MAXLEN 6 + + uint16_t alt; + uint32_t len; +} __packed; + #define IWN4965_FW_TEXT_MAXSZ ( 96 * 1024) #define IWN4965_FW_DATA_MAXSZ ( 40 * 1024) #define IWN5000_FW_TEXT_MAXSZ (256 * 1024) @@ -1267,8 +1296,6 @@ struct iwn_fw_dump { #define IWN4965_FWSZ (IWN4965_FW_TEXT_MAXSZ + IWN4965_FW_DATA_MAXSZ) #define IWN5000_FWSZ IWN5000_FW_TEXT_MAXSZ -#define IWN_FW_API(x) (((x) >> 8) & 0xff) - /* * Offsets into EEPROM. */ 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 c2883b9288..ff1e068b90 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,5 +1,5 @@ /* $FreeBSD$ */ -/* $OpenBSD: if_iwnvar.h,v 1.17 2010/02/17 18:23:00 damien Exp $ */ +/* $OpenBSD: if_iwnvar.h,v 1.18 2010/04/30 16:06:46 damien Exp $ */ /*- * Copyright (c) 2007, 2008 @@ -150,7 +150,8 @@ struct iwn_fw_part { }; struct iwn_fw_info { - u_char *data; + const uint8_t *data; + size_t size; struct iwn_fw_part init; struct iwn_fw_part main; struct iwn_fw_part boot; @@ -262,9 +263,24 @@ struct iwn_softc { int calib_cnt; struct iwn_calib_state calib; + u_int calib_init; + u_int calib_runtime; +#define IWN_CALIB_XTAL (1 << IWN_CALIB_IDX_XTAL) +#define IWN_CALIB_DC (1 << IWN_CALIB_IDX_DC) +#define IWN_CALIB_LO (1 << IWN_CALIB_IDX_LO) +#define IWN_CALIB_TX_IQ (1 << IWN_CALIB_IDX_TX_IQ) +#define IWN_CALIB_TX_IQ_PERIODIC (1 << IWN_CALIB_IDX_TX_IQ_PERIODIC) +#define IWN_CALIB_BASE_BAND (1 << IWN_CALIB_IDX_BASE_BAND) +#define IWN_CALIB_NUM 6 + struct iwn_calib_info calib_results[IWN_CALIB_NUM]; +#define IWN_CALIB_IDX_XTAL 0 +#define IWN_CALIB_IDX_DC 1 +#define IWN_CALIB_IDX_LO 2 +#define IWN_CALIB_IDX_TX_IQ 3 +#define IWN_CALIB_IDX_TX_IQ_PERIODIC 4 +#define IWN_CALIB_IDX_BASE_BAND 5 struct iwn_fw_info fw; - struct iwn_calib_info calibcmd[5]; uint32_t errptr; struct iwn_rx_stat last_rx_stat; @@ -283,7 +299,6 @@ struct iwn_softc { uint16_t rfcfg; uint8_t calib_ver; char eeprom_domain[4]; - uint32_t eeprom_crystal; int16_t eeprom_voltage; int8_t maxpwr2GHz; int8_t maxpwr5GHz; @@ -312,7 +327,7 @@ struct iwn_softc { #define IWN_LOCK_INIT(_sc) \ mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ - MTX_NETWORK_LOCK, MTX_DEF) + MTX_NETWORK_LOCK, MTX_DEF) #define IWN_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define IWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) #define IWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) diff --git a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/glue.c b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/glue.c index 580383c40b..3e87128923 100644 --- a/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/glue.c +++ b/src/add-ons/kernel/drivers/network/wlan/iprowifi4965/glue.c @@ -24,12 +24,14 @@ NO_HAIKU_FBSD_MII_DRIVER(); NO_HAIKU_REENABLE_INTERRUPTS(); HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN); HAIKU_FIRMWARE_VERSION(44417); -HAIKU_FIRMWARE_NAME_MAP(5) = { - {"iwn1000fw", "iwlwifi-1000-3.ucode"}, +HAIKU_FIRMWARE_NAME_MAP(7) = { + {"iwn1000fw", "iwlwifi-1000-5.ucode"}, {"iwn4965fw", "iwlwifi-4965-2.ucode"}, - {"iwn5000fw", "iwlwifi-5000-2.ucode"}, + {"iwn5000fw", "iwlwifi-5000-5.ucode"}, {"iwn5150fw", "iwlwifi-5150-2.ucode"}, - {"iwn6000fw", "iwlwifi-6000-4.ucode"} + {"iwn6000fw", "iwlwifi-6000-4.ucode"}, + {"iwn6005fw", "iwlwifi-6000g2a-5.ucode"}, + {"iwn6050fw", "iwlwifi-6050-5.ucode"} }; diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo.c index d77718b0d1..d547cfce12 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo.c @@ -275,8 +275,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc) ifp->if_watchdog = malo_watchdog; ifp->if_ioctl = malo_ioctl; ifp->if_init = malo_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; @@ -2099,7 +2099,7 @@ malo_rx_proc(void *arg, int npending) * payload prior to constructing the header. */ m = bf->bf_m; - data = mtod(m, uint8_t *);; + data = mtod(m, uint8_t *); hdrlen = ieee80211_anyhdrsize(data + sizeof(uint16_t)); off = sizeof(uint16_t) + sizeof(struct ieee80211_frame_addr4); diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo_pci.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo_pci.c index fbad5ab4c1..65aac7ca63 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8335/dev/malo/if_malo_pci.c @@ -371,4 +371,4 @@ static devclass_t malo_devclass; DRIVER_MODULE(malo, pci, malo_pci_driver, malo_devclass, 0, 0); MODULE_VERSION(malo, 1); MODULE_DEPEND(malo, wlan, 1, 1, 1); /* 802.11 media layer */ -MODULE_DEPEND(malo, malofw_fw, 1, 1, 1); +MODULE_DEPEND(malo, firmware, 1, 1, 1); diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c index de467e90f4..0c030746c4 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl.c @@ -404,8 +404,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) ifp->if_watchdog = mwl_watchdog; ifp->if_ioctl = mwl_ioctl; ifp->if_init = mwl_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c index 2fb09227d0..d800a5470c 100644 --- a/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c +++ b/src/add-ons/kernel/drivers/network/wlan/marvell88w8363/dev/mwl/if_mwl_pci.c @@ -204,7 +204,7 @@ mwl_pci_attach(device_t dev) BUS_SPACE_MAXADDR, /* maxsize */ MWL_TXDESC, /* nsegments */ BUS_SPACE_MAXADDR, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ + 0, /* flags */ NULL, /* lockfunc */ NULL, /* lockarg */ &sc->sc_dmat)) { @@ -313,4 +313,4 @@ static devclass_t mwl_devclass; DRIVER_MODULE(mwl, pci, mwl_pci_driver, mwl_devclass, 0, 0); MODULE_VERSION(mwl, 1); MODULE_DEPEND(mwl, wlan, 1, 1, 1); /* 802.11 media layer */ -MODULE_DEPEND(mwl, mwlfw_fw, 1, 1, 1); /* firmware */ +MODULE_DEPEND(mwl, firmware, 1, 1, 1); diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c index 689aee49a1..7f8502d427 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c @@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include @@ -103,9 +103,6 @@ static void rt2560_reset_rx_ring(struct rt2560_softc *, struct rt2560_rx_ring *); static void rt2560_free_rx_ring(struct rt2560_softc *, struct rt2560_rx_ring *); -static struct ieee80211_node *rt2560_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); -static void rt2560_newassoc(struct ieee80211_node *, int); static int rt2560_newstate(struct ieee80211vap *, enum ieee80211_state, int); static uint16_t rt2560_eeprom_read(struct rt2560_softc *, uint8_t); @@ -269,8 +266,8 @@ rt2560_attach(device_t dev, int id) ifp->if_init = rt2560_init; ifp->if_ioctl = rt2560_ioctl; ifp->if_start = rt2560_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; @@ -303,11 +300,9 @@ rt2560_attach(device_t dev, int id) ieee80211_init_channels(ic, NULL, &bands); ieee80211_ifattach(ic, macaddr); - ic->ic_newassoc = rt2560_newassoc; ic->ic_raw_xmit = rt2560_raw_xmit; ic->ic_updateslot = rt2560_update_slot; ic->ic_update_promisc = rt2560_update_promisc; - ic->ic_node_alloc = rt2560_node_alloc; ic->ic_scan_start = rt2560_scan_start; ic->ic_scan_end = rt2560_scan_end; ic->ic_set_channel = rt2560_set_channel; @@ -430,11 +425,7 @@ rt2560_vap_create(struct ieee80211com *ic, vap->iv_newstate = rt2560_newstate; vap->iv_update_beacon = rt2560_beacon_update; - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /* ms */); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); if (TAILQ_FIRST(&ic->ic_vaps) == vap) @@ -447,7 +438,7 @@ rt2560_vap_delete(struct ieee80211vap *vap) { struct rt2560_vap *rvp = RT2560_VAP(vap); - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -764,27 +755,6 @@ rt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) bus_dma_tag_destroy(ring->data_dmat); } -static struct ieee80211_node * -rt2560_node_alloc(struct ieee80211vap *vap, - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rt2560_node *rn; - - rn = malloc(sizeof (struct rt2560_node), M_80211_NODE, - M_NOWAIT | M_ZERO); - - return (rn != NULL) ? &rn->ni : NULL; -} - -static void -rt2560_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RT2560_VAP(vap)->amrr, - &RT2560_NODE(ni)->amrr, ni); -} - static int rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { @@ -955,10 +925,11 @@ rt2560_tx_intr(struct rt2560_softc *sc) struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; - struct rt2560_node *rn; struct mbuf *m; uint32_t flags; int retrycnt; + struct ieee80211vap *vap; + struct ieee80211_node *ni; bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, BUS_DMASYNC_POSTREAD); @@ -973,15 +944,19 @@ rt2560_tx_intr(struct rt2560_softc *sc) !(flags & RT2560_TX_VALID)) break; - rn = (struct rt2560_node *)data->ni; m = data->m; + ni = data->ni; + vap = ni->ni_vap; switch (flags & RT2560_TX_RESULT_MASK) { case RT2560_TX_SUCCESS: + retrycnt = 0; + DPRINTFN(sc, 10, "%s\n", "data frame sent successfully"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, 0); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -991,8 +966,9 @@ rt2560_tx_intr(struct rt2560_softc *sc) DPRINTFN(sc, 9, "data frame sent after %u retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -1002,8 +978,9 @@ rt2560_tx_intr(struct rt2560_softc *sc) DPRINTFN(sc, 9, "data frame failed after %d retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_FAILURE, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, NULL); ifp->if_oerrors++; break; @@ -1823,7 +1800,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &RT2560_NODE(ni)->amrr); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } @@ -2682,8 +2659,7 @@ rt2560_init_locked(struct rt2560_softc *sc) RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY); if (rt2560_bbp_init(sc) != 0) { - rt2560_stop(sc); - RAL_UNLOCK(sc); + rt2560_stop_locked(sc); return; } diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h index 288577b626..b6a8d68e92 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h @@ -95,16 +95,9 @@ struct rt2560_rx_ring { int cur_decrypt; }; -struct rt2560_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amrr; -}; -#define RT2560_NODE(ni) ((struct rt2560_node *)(ni)) - struct rt2560_vap { struct ieee80211vap ral_vap; struct ieee80211_beacon_offsets ral_bo; - struct ieee80211_amrr amrr; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661.c b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661.c index 99aa138441..d785c1c80b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661.c +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661.c @@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include @@ -100,9 +100,6 @@ static void rt2661_reset_rx_ring(struct rt2661_softc *, struct rt2661_rx_ring *); static void rt2661_free_rx_ring(struct rt2661_softc *, struct rt2661_rx_ring *); -static struct ieee80211_node *rt2661_node_alloc(struct ieee80211vap *, - const uint8_t [IEEE80211_ADDR_LEN]); -static void rt2661_newassoc(struct ieee80211_node *, int); static int rt2661_newstate(struct ieee80211vap *, enum ieee80211_state, int); static uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t); @@ -271,8 +268,8 @@ rt2661_attach(device_t dev, int id) ifp->if_init = rt2661_init; ifp->if_ioctl = rt2661_ioctl; ifp->if_start = rt2661_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; @@ -306,8 +303,6 @@ rt2661_attach(device_t dev, int id) ieee80211_init_channels(ic, NULL, &bands); ieee80211_ifattach(ic, macaddr); - ic->ic_newassoc = rt2661_newassoc; - ic->ic_node_alloc = rt2661_node_alloc; #if 0 ic->ic_wme.wme_update = rt2661_wme_update; #endif @@ -428,11 +423,7 @@ rt2661_vap_create(struct ieee80211com *ic, vap->iv_update_beacon = rt2661_beacon_update; #endif - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 500 /* ms */); - + ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); if (TAILQ_FIRST(&ic->ic_vaps) == vap) @@ -445,7 +436,7 @@ rt2661_vap_delete(struct ieee80211vap *vap) { struct rt2661_vap *rvp = RT2661_VAP(vap); - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } @@ -771,27 +762,6 @@ rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring) bus_dma_tag_destroy(ring->data_dmat); } -static struct ieee80211_node * -rt2661_node_alloc(struct ieee80211vap *vap, - const uint8_t mac[IEEE80211_ADDR_LEN]) -{ - struct rt2661_node *rn; - - rn = malloc(sizeof (struct rt2661_node), M_80211_NODE, - M_NOWAIT | M_ZERO); - - return (rn != NULL) ? &rn->ni : NULL; -} - -static void -rt2661_newassoc(struct ieee80211_node *ni, int isnew) -{ - struct ieee80211vap *vap = ni->ni_vap; - - ieee80211_amrr_node_init(&RT2661_VAP(vap)->amrr, - &RT2661_NODE(ni)->amrr, ni); -} - static int rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { @@ -899,9 +869,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) struct ifnet *ifp = sc->sc_ifp; struct rt2661_tx_ring *txq; struct rt2661_tx_data *data; - struct rt2661_node *rn; uint32_t val; int qid, retrycnt; + struct ieee80211vap *vap; for (;;) { struct ieee80211_node *ni; @@ -925,8 +895,8 @@ rt2661_tx_intr(struct rt2661_softc *sc) /* if no frame has been sent, ignore */ if (ni == NULL) continue; - - rn = RT2661_NODE(ni); + else + vap = ni->ni_vap; switch (RT2661_TX_RESULT(val)) { case RT2661_TX_SUCCESS: @@ -935,8 +905,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) DPRINTFN(sc, 10, "data frame sent successfully after " "%d retries\n", retrycnt); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_SUCCESS, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, + &retrycnt, NULL); ifp->if_opackets++; break; @@ -946,8 +917,9 @@ rt2661_tx_intr(struct rt2661_softc *sc) DPRINTFN(sc, 9, "%s\n", "sending data frame failed (too much retries)"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_amrr_tx_complete(&rn->amrr, - IEEE80211_AMRR_FAILURE, retrycnt); + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, + &retrycnt, NULL); ifp->if_oerrors++; break; @@ -1513,7 +1485,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { - (void) ieee80211_amrr_choose(ni, &RT2661_NODE(ni)->amrr); + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } rate &= IEEE80211_RATE_VAL; diff --git a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h index db1d4de56f..9927d138fa 100644 --- a/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h +++ b/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h @@ -88,15 +88,8 @@ struct rt2661_rx_ring { int next; }; -struct rt2661_node { - struct ieee80211_node ni; - struct ieee80211_amrr_node amrr; -}; -#define RT2661_NODE(ni) ((struct rt2661_node *)(ni)) - struct rt2661_vap { struct ieee80211vap ral_vap; - struct ieee80211_amrr amrr; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); diff --git a/src/add-ons/kernel/drivers/network/wlan/wavelanwifi/dev/wi/if_wi.c b/src/add-ons/kernel/drivers/network/wlan/wavelanwifi/dev/wi/if_wi.c index 70dd6de65a..f29c30d381 100644 --- a/src/add-ons/kernel/drivers/network/wlan/wavelanwifi/dev/wi/if_wi.c +++ b/src/add-ons/kernel/drivers/network/wlan/wavelanwifi/dev/wi/if_wi.c @@ -333,8 +333,8 @@ wi_attach(device_t dev) ifp->if_ioctl = wi_ioctl; ifp->if_start = wi_start; ifp->if_init = wi_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/src/libs/compat/freebsd_network/compat/net/if_var.h b/src/libs/compat/freebsd_network/compat/net/if_var.h index e26198c460..ee915fa8fb 100644 --- a/src/libs/compat/freebsd_network/compat/net/if_var.h +++ b/src/libs/compat/freebsd_network/compat/net/if_var.h @@ -634,6 +634,7 @@ void if_attach(struct ifnet *); int if_delmulti(struct ifnet *, struct sockaddr *); void if_detach(struct ifnet *); void if_purgeaddrs(struct ifnet *); +void if_delallmulti(struct ifnet *); void if_purgemaddrs(struct ifnet *); void if_down(struct ifnet *); void if_free(struct ifnet *); diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index 4fde5603c9..4b6e032806 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -27,6 +27,9 @@ #include +int ifqmaxlen = IFQ_MAXLEN; + + #define IFNET_HOLD (void *)(uintptr_t)(-1) @@ -386,6 +389,28 @@ if_findmulti(struct ifnet *ifp, struct sockaddr *_address) } +/* + * if_freemulti: free ifmultiaddr structure and possibly attached related + * addresses. The caller is responsible for implementing reference + * counting, notifying the driver, handling routing messages, and releasing + * any dependent link layer state. + */ +static void +if_freemulti(struct ifmultiaddr *ifma) +{ + + KASSERT(ifma->ifma_refcount == 0, ("if_freemulti: refcount %d", + ifma->ifma_refcount)); + KASSERT(ifma->ifma_protospec == NULL, + ("if_freemulti: protospec not NULL")); + + if (ifma->ifma_lladdr != NULL) + free(ifma->ifma_lladdr); + free(ifma->ifma_addr); + free(ifma); +} + + static struct ifmultiaddr * _if_addmulti(struct ifnet *ifp, struct sockaddr *address) { @@ -441,6 +466,96 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *address, } +static int +if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, int detaching) +{ + struct ifmultiaddr *ll_ifma; + + if (ifp != NULL && ifma->ifma_ifp != NULL) { + KASSERT(ifma->ifma_ifp == ifp, + ("%s: inconsistent ifp %p", __func__, ifp)); + IF_ADDR_LOCK_ASSERT(ifp); + } + + ifp = ifma->ifma_ifp; + + /* + * If the ifnet is detaching, null out references to ifnet, + * so that upper protocol layers will notice, and not attempt + * to obtain locks for an ifnet which no longer exists. The + * routing socket announcement must happen before the ifnet + * instance is detached from the system. + */ + if (detaching) { +#ifdef DIAGNOSTIC + printf("%s: detaching ifnet instance %p\n", __func__, ifp); +#endif + /* + * ifp may already be nulled out if we are being reentered + * to delete the ll_ifma. + */ + if (ifp != NULL) { +#ifndef __HAIKU__ + rt_newmaddrmsg(RTM_DELMADDR, ifma); +#endif + ifma->ifma_ifp = NULL; + } + } + + if (--ifma->ifma_refcount > 0) + return 0; + +#ifndef __HAIKU__ + /* + * If this ifma is a network-layer ifma, a link-layer ifma may + * have been associated with it. Release it first if so. + */ + ll_ifma = ifma->ifma_llifma; + if (ll_ifma != NULL) { + KASSERT(ifma->ifma_lladdr != NULL, + ("%s: llifma w/o lladdr", __func__)); + if (detaching) + ll_ifma->ifma_ifp = NULL; /* XXX */ + if (--ll_ifma->ifma_refcount == 0) { + if (ifp != NULL) { + TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, + ifma_link); + } + if_freemulti(ll_ifma); + } + } +#endif + + if (ifp != NULL) + TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); + + if_freemulti(ifma); + + /* + * The last reference to this instance of struct ifmultiaddr + * was released; the hardware should be notified of this change. + */ + return 1; +} + + +/* + * Delete all multicast group membership for an interface. + * Should be used to quickly flush all multicast filters. + */ +void +if_delallmulti(struct ifnet *ifp) +{ + struct ifmultiaddr *ifma; + struct ifmultiaddr *next; + + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) + if_delmulti_locked(ifp, ifma, 0); + IF_ADDR_UNLOCK(ifp); +} + + static void if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma) { @@ -450,60 +565,41 @@ if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma) int -if_delmulti(struct ifnet *ifp, struct sockaddr *address) +if_delmulti(struct ifnet *ifp, struct sockaddr *sa) { - struct ifmultiaddr *addr; - int deleted = 0; + struct ifmultiaddr *ifma; + int lastref; +#ifdef INVARIANTS + struct ifnet *oifp; + + IFNET_RLOCK_NOSLEEP(); + TAILQ_FOREACH(oifp, &V_ifnet, if_link) + if (ifp == oifp) + break; + if (ifp != oifp) + ifp = NULL; + IFNET_RUNLOCK_NOSLEEP(); + + KASSERT(ifp != NULL, ("%s: ifnet went away", __func__)); +#endif + if (ifp == NULL) + return (ENOENT); IF_ADDR_LOCK(ifp); - addr = if_findmulti(ifp, address); - if (addr != NULL) { - addr->ifma_refcount--; - if (addr->ifma_refcount == 0) { - if_delete_multiaddr(ifp, addr); - deleted = 1; - } - } + lastref = 0; + ifma = if_findmulti(ifp, sa); + if (ifma != NULL) + lastref = if_delmulti_locked(ifp, ifma, 0); IF_ADDR_UNLOCK(ifp); - if (deleted && ifp->if_ioctl != NULL) - ifp->if_ioctl(ifp, SIOCDELMULTI, NULL); + if (ifma == NULL) + return (ENOENT); - return 0; -} - - -static void -if_freemulti(struct ifmultiaddr *ifma) -{ - if (ifma->ifma_lladdr != NULL) - free(ifma->ifma_lladdr); - free(ifma->ifma_addr); - free(ifma); -} - - -static int -if_delmulti_locked(struct ifnet *ifp, struct ifmultiaddr *ifma, - int detaching) -{ - ifp = ifma->ifma_ifp; - - if (detaching) { - if (ifp != NULL) { - ifma->ifma_ifp = NULL; - } + if (lastref && ifp->if_ioctl != NULL) { + (void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0); } - if (--ifma->ifma_refcount > 0) - return 0; - - if (ifp != NULL) - TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link); - - if_freemulti(ifma); - - return 1; + return (0); } diff --git a/src/libs/compat/freebsd_wlan/net80211/Jamfile b/src/libs/compat/freebsd_wlan/net80211/Jamfile index e9a6faef6c..f43e19c25b 100644 --- a/src/libs/compat/freebsd_wlan/net80211/Jamfile +++ b/src/libs/compat/freebsd_wlan/net80211/Jamfile @@ -42,7 +42,10 @@ KernelStaticLibrary libfreebsd_wlan.a : ieee80211_power.c ieee80211_proto.c ieee80211_radiotap.c + ieee80211_ratectl.c + ieee80211_ratectl_none.c ieee80211_regdomain.c + ieee80211_rssadapt.c ieee80211_scan_sta.c ieee80211_scan.c ieee80211_sta.c diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211.c index de8790a996..2f20bd15eb 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #ifdef IEEE80211_SUPPORT_SUPERG #include #endif +#include #include @@ -393,11 +394,10 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; ifp->if_start = ieee80211_start; ifp->if_ioctl = ieee80211_ioctl; - ifp->if_watchdog = NULL; /* NB: no watchdog routine */ ifp->if_init = ieee80211_init; /* NB: input+output filled in by ether_ifattach */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); vap->iv_ifp = ifp; @@ -443,6 +443,9 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, /* auto-enable s/w beacon miss support */ if (flags & IEEE80211_CLONE_NOBEACONS) vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS; + /* auto-generated or user supplied MAC address */ + if (flags & (IEEE80211_CLONE_BSSID|IEEE80211_CLONE_MACADDR)) + vap->iv_flags_ext |= IEEE80211_FEXT_UNIQMAC; /* * Enable various functionality by default if we're * capable; the driver can override us if it knows better. @@ -486,6 +489,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ieee80211_scan_vattach(vap); ieee80211_regdomain_vattach(vap); ieee80211_radiotap_vattach(vap); + ieee80211_ratectl_set(vap, IEEE80211_RATECTL_NONE); return 0; } diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_action.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_action.c index 5371f6e975..8c11471c89 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_action.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_action.c @@ -105,7 +105,7 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f) meshlm_send_action[act] = f; return 0; case IEEE80211_ACTION_CAT_MESHPATH: - if (act > N(hwmp_send_action)) + if (act >= N(hwmp_send_action)) break; hwmp_send_action[act] = f; return 0; diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_adhoc.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_adhoc.c index 805589016d..d3b43bd572 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_adhoc.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_adhoc.c @@ -293,7 +293,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) struct ieee80211_frame *wh; struct ieee80211_key *key; struct ether_header *eh; - int hdrspace, need_tap; + int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; uint16_t rxseq; @@ -318,7 +318,6 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) KASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; - need_tap = 1; /* mbuf need to be tapped. */ type = -1; /* undefined */ if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.c index 248c3f8493..7902545c28 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.c @@ -1,6 +1,7 @@ /* $OpenBSD: ieee80211_amrr.c,v 1.1 2006/06/17 19:07:19 damien Exp $ */ /*- + * Copyright (c) 2010 Rui Paulo * Copyright (c) 2006 * Damien Bergamini * @@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #define is_success(amn) \ ((amn)->amn_retrycnt < (amn)->amn_txcnt / 10) @@ -54,15 +56,45 @@ __FBSDID("$FreeBSD$"); #define is_enough(amn) \ ((amn)->amn_txcnt > 10) -static void amrr_sysctlattach(struct ieee80211_amrr *amrr, - struct sysctl_ctx_list *ctx, struct sysctl_oid *tree); +static void amrr_setinterval(const struct ieee80211vap *, int); +static void amrr_init(struct ieee80211vap *); +static void amrr_deinit(struct ieee80211vap *); +static void amrr_node_init(struct ieee80211_node *); +static void amrr_node_deinit(struct ieee80211_node *); +static int amrr_update(struct ieee80211_amrr *, + struct ieee80211_amrr_node *, struct ieee80211_node *); +static int amrr_rate(struct ieee80211_node *, void *, uint32_t); +static void amrr_tx_complete(const struct ieee80211vap *, + const struct ieee80211_node *, int, + void *, void *); +static void amrr_tx_update(const struct ieee80211vap *vap, + const struct ieee80211_node *, void *, void *, void *); +static void amrr_sysctlattach(struct ieee80211vap *, + struct sysctl_ctx_list *, struct sysctl_oid *); /* number of references from net80211 layer */ static int nrefs = 0; -void -ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs) +static const struct ieee80211_ratectl amrr = { + .ir_name = "amrr", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = amrr_init, + .ir_deinit = amrr_deinit, + .ir_node_init = amrr_node_init, + .ir_node_deinit = amrr_node_deinit, + .ir_rate = amrr_rate, + .ir_tx_complete = amrr_tx_complete, + .ir_tx_update = amrr_tx_update, + .ir_setinterval = amrr_setinterval, +}; +IEEE80211_RATECTL_MODULE(amrr, 1); +IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr); + +static void +amrr_setinterval(const struct ieee80211vap *vap, int msecs) { + struct ieee80211_amrr *amrr = vap->iv_rs; int t; if (msecs < 100) @@ -71,29 +103,49 @@ ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs) amrr->amrr_interval = (t < 1) ? 1 : t; } -void -ieee80211_amrr_init(struct ieee80211_amrr *amrr, - struct ieee80211vap *vap, int amin, int amax, int interval) +static void +amrr_init(struct ieee80211vap *vap) { - /* XXX bounds check? */ - amrr->amrr_min_success_threshold = amin; - amrr->amrr_max_success_threshold = amax; - ieee80211_amrr_setinterval(amrr, interval); + struct ieee80211_amrr *amrr; - amrr_sysctlattach(amrr, vap->iv_sysctl, vap->iv_oid); + KASSERT(vap->iv_rs == NULL, ("%s called multiple times", __func__)); + + amrr = vap->iv_rs = malloc(sizeof(struct ieee80211_amrr), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (amrr == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n"); + return; + } + amrr->amrr_min_success_threshold = IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD; + amrr->amrr_max_success_threshold = IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD; + amrr_setinterval(vap, 500 /* ms */); + amrr_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid); } -void -ieee80211_amrr_cleanup(struct ieee80211_amrr *amrr) +static void +amrr_deinit(struct ieee80211vap *vap) { + free(vap->iv_rs, M_80211_RATECTL); } -void -ieee80211_amrr_node_init(struct ieee80211_amrr *amrr, - struct ieee80211_amrr_node *amn, struct ieee80211_node *ni) +static void +amrr_node_init(struct ieee80211_node *ni) { const struct ieee80211_rateset *rs = &ni->ni_rates; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_amrr *amrr = vap->iv_rs; + struct ieee80211_amrr_node *amn; + if (ni->ni_rctls == NULL) { + ni->ni_rctls = amn = malloc(sizeof(struct ieee80211_amrr_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (amn == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } + } else + amn = ni->ni_rctls; amn->amn_amrr = amrr; amn->amn_success = 0; amn->amn_recovery = 0; @@ -112,6 +164,12 @@ ieee80211_amrr_node_init(struct ieee80211_amrr *amrr, "AMRR initial rate %d", ni->ni_txrate); } +static void +amrr_node_deinit(struct ieee80211_node *ni) +{ + free(ni->ni_rctls, M_80211_RATECTL); +} + static int amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn, struct ieee80211_node *ni) @@ -168,10 +226,10 @@ amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn, * Update our internal state if it's been long enough. * If the rate changes we also update ni_txrate to match. */ -int -ieee80211_amrr_choose(struct ieee80211_node *ni, - struct ieee80211_amrr_node *amn) +static int +amrr_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused) { + struct ieee80211_amrr_node *amn = ni->ni_rctls; struct ieee80211_amrr *amrr = amn->amn_amrr; int rix; @@ -189,27 +247,65 @@ ieee80211_amrr_choose(struct ieee80211_node *ni, return rix; } +/* + * Update statistics with tx complete status. Ok is non-zero + * if the packet is known to be ACK'd. Retries has the number + * retransmissions (i.e. xmit attempts - 1). + */ +static void +amrr_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int ok, + void *arg1, void *arg2 __unused) +{ + struct ieee80211_amrr_node *amn = ni->ni_rctls; + int retries = *(int *)arg1; + + amn->amn_txcnt++; + if (ok) + amn->amn_success++; + amn->amn_retrycnt += retries; +} + +/* + * Set tx count/retry statistics explicitly. Intended for + * drivers that poll the device for statistics maintained + * in the device. + */ +static void +amrr_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, + void *arg1, void *arg2, void *arg3) +{ + struct ieee80211_amrr_node *amn = ni->ni_rctls; + int txcnt = *(int *)arg1, success = *(int *)arg2, retrycnt = *(int *)arg3; + + amn->amn_txcnt = txcnt; + amn->amn_success = success; + amn->amn_retrycnt = retrycnt; +} + static int amrr_sysctl_interval(SYSCTL_HANDLER_ARGS) { - struct ieee80211_amrr *amrr = arg1; + struct ieee80211vap *vap = arg1; + struct ieee80211_amrr *amrr = vap->iv_rs; int msecs = ticks_to_msecs(amrr->amrr_interval); int error; error = sysctl_handle_int(oidp, &msecs, 0, req); if (error || !req->newptr) return error; - ieee80211_amrr_setinterval(amrr, msecs); + amrr_setinterval(vap, msecs); return 0; } static void -amrr_sysctlattach(struct ieee80211_amrr *amrr, +amrr_sysctlattach(struct ieee80211vap *vap, struct sysctl_ctx_list *ctx, struct sysctl_oid *tree) { + struct ieee80211_amrr *amrr = vap->iv_rs; SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, amrr, + "amrr_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap, 0, amrr_sysctl_interval, "I", "amrr operation interval (ms)"); /* XXX bounds check values */ SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, @@ -219,4 +315,3 @@ amrr_sysctlattach(struct ieee80211_amrr *amrr, "amrr_min_sucess_threshold", CTLFLAG_RW, &amrr->amrr_min_success_threshold, 0, ""); } - diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.h index fe4b224cf4..61357271cc 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_amrr.h @@ -58,44 +58,4 @@ struct ieee80211_amrr_node { u_int amn_retrycnt; }; -void ieee80211_amrr_init(struct ieee80211_amrr *, struct ieee80211vap *, - int, int, int); -void ieee80211_amrr_cleanup(struct ieee80211_amrr *); -void ieee80211_amrr_setinterval(struct ieee80211_amrr *, int); -void ieee80211_amrr_node_init(struct ieee80211_amrr *, - struct ieee80211_amrr_node *, struct ieee80211_node *); -int ieee80211_amrr_choose(struct ieee80211_node *, - struct ieee80211_amrr_node *); - -#define IEEE80211_AMRR_SUCCESS 1 -#define IEEE80211_AMRR_FAILURE 0 - -/* - * Update statistics with tx complete status. Ok is non-zero - * if the packet is known to be ACK'd. Retries has the number - * retransmissions (i.e. xmit attempts - 1). - */ -static __inline void -ieee80211_amrr_tx_complete(struct ieee80211_amrr_node *amn, - int ok, int retries) -{ - amn->amn_txcnt++; - if (ok) - amn->amn_success++; - amn->amn_retrycnt += retries; -} - -/* - * Set tx count/retry statistics explicitly. Intended for - * drivers that poll the device for statistics maintained - * in the device. - */ -static __inline void -ieee80211_amrr_tx_update(struct ieee80211_amrr_node *amn, - int txcnt, int success, int retrycnt) -{ - amn->amn_txcnt = txcnt; - amn->amn_success = success; - amn->amn_retrycnt = retrycnt; -} #endif /* _FBSD_COMPAT_NET80211_IEEE80211_AMRR_H_ */ diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_crypto_tkip.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_crypto_tkip.c index f949255b9c..6e1fda1fc9 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_crypto_tkip.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_crypto_tkip.c @@ -144,6 +144,7 @@ tkip_setkey(struct ieee80211_key *k) return 0; } k->wk_keytsc = 1; /* TSC starts at 1 */ + ctx->rx_phase1_done = 0; return 1; } diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_haiku.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_haiku.h index 32d4fb9245..6186debb96 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_haiku.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_haiku.h @@ -161,6 +161,16 @@ typedef struct mtx ieee80211_ageq_lock_t; #define IEEE80211_AGEQ_LOCK(_aq) mtx_lock(&(_aq)->aq_lock) #define IEEE80211_AGEQ_UNLOCK(_aq) mtx_unlock(&(_aq)->aq_lock) +/* + * Scan table definitions. + */ +typedef struct mtx ieee80211_scan_table_lock_t; +#define IEEE80211_SCAN_TABLE_LOCK_INIT(_st, _name) \ + mtx_init(&(_st)->st_lock, _name, "802.11 scan table", MTX_DEF) +#define IEEE80211_SCAN_TABLE_LOCK_DESTROY(_st) mtx_destroy(&(_st)->st_lock) +#define IEEE80211_SCAN_TABLE_LOCK(_st) mtx_lock(&(_st)->st_lock) +#define IEEE80211_SCAN_TABLE_UNLOCK(_st) mtx_unlock(&(_st)->st_lock) + /* * Node reference counting definitions. * @@ -311,6 +321,23 @@ void ieee80211_scan_sta_init(void); void ieee80211_scan_sta_uninit(void); +/* + * Rate control modules provide tx rate control support. + */ +#define IEEE80211_RATECTL_MODULE(alg, version) \ + _IEEE80211_POLICY_MODULE(ratectl, alg, version); \ + +#define IEEE80211_RATECTL_ALG(name, alg, v) \ +static void \ +alg##_modevent(int type) \ +{ \ + if (type == MOD_LOAD) \ + ieee80211_ratectl_register(alg, &v); \ + else \ + ieee80211_ratectl_unregister(alg); \ +} \ +TEXT_SET(ratectl##_set, alg##_modevent) + struct ieee80211req; typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *, struct ieee80211req *); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_hostap.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_hostap.c index 240ea7cb30..63bcd3c9a1 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_hostap.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_hostap.c @@ -480,7 +480,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) struct ieee80211_frame *wh; struct ieee80211_key *key; struct ether_header *eh; - int hdrspace, need_tap; + int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; uint16_t rxseq; @@ -505,7 +505,6 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) KASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; - need_tap = 1; /* mbuf need to be tapped. */ type = -1; /* undefined */ if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { @@ -884,6 +883,14 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) wh = mtod(m, struct ieee80211_frame *); wh->i_fc[1] &= ~IEEE80211_FC1_WEP; } + /* + * Pass the packet to radiotap before calling iv_recv_mgmt(). + * Otherwise iv_recv_mgmt() might pass another packet to + * radiotap, resulting in out of order packet captures. + */ + if (ieee80211_radiotap_active_vap(vap)) + ieee80211_radiotap_rx(vap, m); + need_tap = 0; vap->iv_recv_mgmt(ni, m, subtype, rssi, nf); goto out; @@ -1252,7 +1259,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm, return IEEE80211_REASON_IE_INVALID; } frm += 6, len -= 4; /* NB: len is payload only */ - /* NB: iswapoui already validated the OUI and type */ + /* NB: iswpaoui already validated the OUI and type */ w = LE_READ_2(frm); if (w != WPA_VERSION) { IEEE80211_DISCARD_IE(vap, diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_hwmp.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_hwmp.c index df988505b7..78729fcb1a 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_hwmp.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_hwmp.c @@ -148,7 +148,7 @@ typedef uint32_t ieee80211_hwmp_seq; struct ieee80211_hwmp_route { ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/ ieee80211_hwmp_seq hr_preqid; /* last PREQ ID seen from dst */ - ieee80211_hwmp_seq hr_targetseq; /* seq. no. on our latest PREQ*/ + ieee80211_hwmp_seq hr_origseq; /* seq. no. on our latest PREQ*/ int hr_preqretries; }; struct ieee80211_hwmp_state { @@ -548,7 +548,7 @@ hwmp_add_meshperr(uint8_t *frm, const struct ieee80211_meshperr_ie *perr) *frm++ = perr->perr_ttl; *frm++ = perr->perr_ndests; for (i = 0; i < perr->perr_ndests; i++) { - *frm += perr->perr_dests[i].dest_flags; + *frm++ = perr->perr_dests[i].dest_flags; IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr); frm += 6; ADDWORD(frm, perr->perr_dests[i].dest_seq); @@ -653,6 +653,7 @@ hwmp_rootmode_rann_cb(void *arg) IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss, "%s", "send broadcast RANN"); + rann.rann_flags = 0; if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL) rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR; rann.rann_hopcount = 0; @@ -706,6 +707,10 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr); if (rtorig == NULL) rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr); + if (rtorig == NULL) { + /* XXX stat */ + return; + } hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route); /* * Sequence number validation. @@ -733,12 +738,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_flags = 0; prep.prep_hopcount = 0; prep.prep_ttl = ms->ms_ttl; - IEEE80211_ADDR_COPY(prep.prep_targetaddr, preq->preq_origaddr); - prep.prep_targetseq = preq->preq_origseq; + IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr); + prep.prep_targetseq = ++hs->hs_seq; prep.prep_lifetime = preq->preq_lifetime; prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; - IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr); - prep.prep_origseq = ++hs->hs_seq; + IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr); + prep.prep_origseq = preq->preq_origseq; hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep); /* * Build the reverse path, if we don't have it already. @@ -784,13 +789,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_flags = 0; prep.prep_hopcount = 0; prep.prep_ttl = ms->ms_ttl; - IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr); + IEEE80211_ADDR_COPY(prep.prep_origaddr, rootmac); prep.prep_origseq = preq->preq_origseq; - prep.prep_targetseq = ++hs->hs_seq; prep.prep_lifetime = preq->preq_lifetime; prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL; - IEEE80211_ADDR_COPY(prep.prep_targetaddr, rootmac); - prep.prep_targetseq = PREQ_TSEQ(0); + IEEE80211_ADDR_COPY(prep.prep_targetaddr, + vap->iv_myaddr); + prep.prep_targetseq = ++hs->hs_seq; hwmp_send_prep(vap->iv_bss, vap->iv_myaddr, broadcastaddr, &prep); } @@ -848,13 +853,13 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni, prep.prep_hopcount = rt->rt_nhops + 1; prep.prep_ttl = ms->ms_ttl; IEEE80211_ADDR_COPY(&prep.prep_targetaddr, - preq->preq_origaddr); + PREQ_TADDR(0)); prep.prep_targetseq = hrorig->hr_seq; prep.prep_lifetime = preq->preq_lifetime; prep.prep_metric = rt->rt_metric + ms->ms_pmetric->mpm_metric(ni); IEEE80211_ADDR_COPY(&prep.prep_origaddr, - PREQ_TADDR(0)); + preq->preq_origaddr); prep.prep_origseq = hrorig->hr_seq; hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &prep); @@ -951,19 +956,19 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, return; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, - "received PREP from %s", ether_sprintf(prep->prep_origaddr)); + "received PREP from %s", ether_sprintf(prep->prep_targetaddr)); - rt = ieee80211_mesh_rt_find(vap, prep->prep_origaddr); + rt = ieee80211_mesh_rt_find(vap, prep->prep_targetaddr); if (rt == NULL) { /* * If we have no entry this could be a reply to a root PREQ. */ if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) { - rt = ieee80211_mesh_rt_add(vap, prep->prep_origaddr); + rt = ieee80211_mesh_rt_add(vap, prep->prep_targetaddr); if (rt == NULL) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "unable to add PREP path to %s", - ether_sprintf(prep->prep_origaddr)); + ether_sprintf(prep->prep_targetaddr)); vap->iv_stats.is_mesh_rtaddfailed++; return; } @@ -974,7 +979,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "add root path to %s nhops %d metric %d (PREP)", - ether_sprintf(prep->prep_origaddr), + ether_sprintf(prep->prep_targetaddr), rt->rt_nhops, rt->rt_metric); return; } @@ -984,30 +989,30 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, * Sequence number validation. */ hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); - if (HWMP_SEQ_LEQ(prep->prep_origseq, hr->hr_seq)) { + if (HWMP_SEQ_LEQ(prep->prep_targetseq, hr->hr_seq)) { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "discard PREP from %s, old seq no %u <= %u", - ether_sprintf(prep->prep_origaddr), - prep->prep_origseq, hr->hr_seq); + ether_sprintf(prep->prep_targetaddr), + prep->prep_targetseq, hr->hr_seq); return; } - hr->hr_seq = prep->prep_origseq; + hr->hr_seq = prep->prep_targetseq; /* * If it's NOT for us, propagate the PREP. */ - if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_targetaddr) && + if (!IEEE80211_ADDR_EQ(vap->iv_myaddr, prep->prep_origaddr) && prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) { struct ieee80211_meshprep_ie pprep; /* propagated PREP */ IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "propagate PREP from %s", - ether_sprintf(prep->prep_origaddr)); + ether_sprintf(prep->prep_targetaddr)); memcpy(&pprep, prep, sizeof(pprep)); pprep.prep_hopcount += 1; pprep.prep_ttl -= 1; pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni); - IEEE80211_ADDR_COPY(pprep.prep_origaddr, vap->iv_myaddr); + IEEE80211_ADDR_COPY(pprep.prep_targetaddr, vap->iv_myaddr); hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep); } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); @@ -1015,9 +1020,9 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, /* NB: never clobber a proxy entry */; IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "discard PREP for %s, route is marked PROXY", - ether_sprintf(prep->prep_origaddr)); + ether_sprintf(prep->prep_targetaddr)); vap->iv_stats.is_hwmp_proxy++; - } else if (prep->prep_targetseq == hr->hr_targetseq) { + } else if (prep->prep_origseq == hr->hr_origseq) { /* * Check if we already have a path to this node. * If we do, check if this path reply contains a @@ -1041,14 +1046,14 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni, } else { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "ignore PREP for %s, hopcount %d:%d metric %d:%d", - ether_sprintf(prep->prep_origaddr), + ether_sprintf(prep->prep_targetaddr), rt->rt_nhops, prep->prep_hopcount, rt->rt_metric, prep->prep_metric); } } else { IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni, "discard PREP for %s, wrong seqno %u != %u", - ether_sprintf(prep->prep_origaddr), prep->prep_targetseq, + ether_sprintf(prep->prep_targetaddr), prep->prep_origseq, hr->hr_seq); vap->iv_stats.is_hwmp_wrongseq++; } @@ -1114,6 +1119,7 @@ hwmp_peerdown(struct ieee80211_node *ni) "%s", "delete route entry"); perr.perr_ttl = ms->ms_ttl; perr.perr_ndests = 1; + PERR_DFLAGS(0) = 0; if (hr->hr_seq == 0) PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN; PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC; @@ -1223,7 +1229,8 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, struct ieee80211_meshrann_ie prann; if (ni == vap->iv_bss || - ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) + ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED || + IEEE80211_ADDR_EQ(rann->rann_addr, vap->iv_myaddr)) return; rt = ieee80211_mesh_rt_find(vap, rann->rann_addr); @@ -1236,15 +1243,18 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni, return; } hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); - if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq) && rann->rann_ttl > 1 && - rann->rann_hopcount < hs->hs_maxhops && - (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) { - memcpy(&prann, rann, sizeof(prann)); - prann.rann_hopcount += 1; - prann.rann_ttl -= 1; - prann.rann_metric += ms->ms_pmetric->mpm_metric(ni); - hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr, - &prann); + if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq)) { + hr->hr_seq = rann->rann_seq; + if (rann->rann_ttl > 1 && + rann->rann_hopcount < hs->hs_maxhops && + (ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) { + memcpy(&prann, rann, sizeof(prann)); + prann.rann_hopcount += 1; + prann.rann_ttl -= 1; + prann.rann_metric += ms->ms_pmetric->mpm_metric(ni); + hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, + broadcastaddr, &prann); + } } } @@ -1305,8 +1315,8 @@ hwmp_discover(struct ieee80211vap *vap, hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route); if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) { - if (hr->hr_targetseq == 0) - hr->hr_targetseq = ++hs->hs_seq; + if (hr->hr_origseq == 0) + hr->hr_origseq = ++hs->hs_seq; rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL; rt->rt_lifetime = ticks_to_msecs(ieee80211_hwmp_pathtimeout); @@ -1324,7 +1334,7 @@ hwmp_discover(struct ieee80211vap *vap, preq.preq_ttl = ms->ms_ttl; preq.preq_id = ++hs->hs_preqid; IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr); - preq.preq_origseq = hr->hr_targetseq; + preq.preq_origseq = hr->hr_origseq; preq.preq_lifetime = rt->rt_lifetime; preq.preq_metric = rt->rt_metric; preq.preq_tcount = 1; diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_input.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_input.c index e701cb5eba..28a58fe06b 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_input.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_input.c @@ -734,7 +734,8 @@ ieee80211_ssid_mismatch(struct ieee80211vap *vap, const char *tag, * Return the bssid of a frame. */ static const uint8_t * -ieee80211_getbssid(struct ieee80211vap *vap, const struct ieee80211_frame *wh) +ieee80211_getbssid(const struct ieee80211vap *vap, + const struct ieee80211_frame *wh) { if (vap->iv_opmode == IEEE80211_M_STA) return wh->i_addr2; @@ -748,7 +749,7 @@ ieee80211_getbssid(struct ieee80211vap *vap, const struct ieee80211_frame *wh) #include void -ieee80211_note(struct ieee80211vap *vap, const char *fmt, ...) +ieee80211_note(const struct ieee80211vap *vap, const char *fmt, ...) { char buf[128]; /* XXX */ va_list ap; @@ -761,7 +762,7 @@ ieee80211_note(struct ieee80211vap *vap, const char *fmt, ...) } void -ieee80211_note_frame(struct ieee80211vap *vap, +ieee80211_note_frame(const struct ieee80211vap *vap, const struct ieee80211_frame *wh, const char *fmt, ...) { @@ -776,7 +777,7 @@ ieee80211_note_frame(struct ieee80211vap *vap, } void -ieee80211_note_mac(struct ieee80211vap *vap, +ieee80211_note_mac(const struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], const char *fmt, ...) { @@ -790,7 +791,7 @@ ieee80211_note_mac(struct ieee80211vap *vap, } void -ieee80211_discard_frame(struct ieee80211vap *vap, +ieee80211_discard_frame(const struct ieee80211vap *vap, const struct ieee80211_frame *wh, const char *type, const char *fmt, ...) { @@ -811,7 +812,7 @@ ieee80211_discard_frame(struct ieee80211vap *vap, } void -ieee80211_discard_ie(struct ieee80211vap *vap, +ieee80211_discard_ie(const struct ieee80211vap *vap, const struct ieee80211_frame *wh, const char *type, const char *fmt, ...) { @@ -830,7 +831,7 @@ ieee80211_discard_ie(struct ieee80211vap *vap, } void -ieee80211_discard_mac(struct ieee80211vap *vap, +ieee80211_discard_mac(const struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], const char *type, const char *fmt, ...) { diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ioctl.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ioctl.c index 4d2da9daa6..fb1a2427e1 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ioctl.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ioctl.c @@ -1598,8 +1598,10 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) if (list == NULL) return ENOMEM; error = copyin(ireq->i_data, list, ireq->i_len); - if (error) + if (error) { + free(list, M_TEMP); return error; + } nchan = 0; chanlist = list + ireq->i_len; /* NB: zero'd already */ maxchan = ireq->i_len * NBBY; @@ -1615,8 +1617,10 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) nchan++; } } - if (nchan == 0) + if (nchan == 0) { + free(list, M_TEMP); return EINVAL; + } if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ isclr(chanlist, ic->ic_bsschan->ic_ieee)) ic->ic_bsschan = IEEE80211_CHAN_ANYC; @@ -3207,15 +3211,18 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic) void *ioctl; IEEE80211_LOCK(ic); - if_purgemaddrs(parent); + if_delallmulti(parent); ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */ parent->if_ioctl = NULL; TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { struct ifnet *ifp = vap->iv_ifp; struct ifmultiaddr *ifma; - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; (void) if_addmulti(parent, ifma->ifma_addr, NULL); + } } parent->if_ioctl = ioctl; ieee80211_runtask(ic, &ic->ic_mcast_task); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.c index a1b594b928..d42d55db72 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.c @@ -388,8 +388,6 @@ mesh_select_proto_path(struct ieee80211vap *vap, const char *name) for (i = 0; i < N(mesh_proto_paths); i++) { if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) { ms->ms_ppath = &mesh_proto_paths[i]; - if (vap->iv_state == IEEE80211_S_RUN) - vap->iv_newstate(vap, IEEE80211_S_INIT, 0); return 0; } } @@ -405,8 +403,6 @@ mesh_select_proto_metric(struct ieee80211vap *vap, const char *name) for (i = 0; i < N(mesh_proto_metrics); i++) { if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) { ms->ms_pmetric = &mesh_proto_metrics[i]; - if (vap->iv_state == IEEE80211_S_RUN) - vap->iv_newstate(vap, IEEE80211_S_INIT, 0); return 0; } } @@ -739,10 +735,12 @@ mesh_linkchange(struct ieee80211_node *ni, enum ieee80211_mesh_mlstate state) ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) { KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow")); ms->ms_neighbors++; + ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF); } else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED && state != IEEE80211_NODE_MESH_ESTABLISHED) { KASSERT(ms->ms_neighbors > 0, ("neighbor count 0")); ms->ms_neighbors--; + ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF); } ni->ni_mlstate = state; switch (state) { @@ -2552,6 +2550,18 @@ ieee80211_mesh_init_neighbor(struct ieee80211_node *ni, ieee80211_parse_meshid(ni, sp->meshid); } +void +ieee80211_mesh_update_beacon(struct ieee80211vap *vap, + struct ieee80211_beacon_offsets *bo) +{ + KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a MBSS vap")); + + if (isset(bo->bo_flags, IEEE80211_BEACON_MESHCONF)) { + (void)ieee80211_add_meshconf(bo->bo_meshconf, vap); + clrbit(bo->bo_flags, IEEE80211_BEACON_MESHCONF); + } +} + static int mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq) { diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.h index 8b014828a8..5a9d148977 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_mesh.h @@ -469,6 +469,8 @@ struct ieee80211_scanparams; void ieee80211_mesh_init_neighbor(struct ieee80211_node *, const struct ieee80211_frame *, const struct ieee80211_scanparams *); +void ieee80211_mesh_update_beacon(struct ieee80211vap *, + struct ieee80211_beacon_offsets *); /* * Return non-zero if proxy operation is enabled. diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_node.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_node.h index 0eeb46eed2..8fae8d6104 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_node.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_node.h @@ -218,7 +218,8 @@ struct ieee80211_node { struct ieee80211_nodestats ni_stats; /* per-node statistics */ struct ieee80211vap *ni_wdsvap; /* associated WDS vap */ - uint64_t ni_spare[4]; + void *ni_rctls; /* private ratectl state */ + uint64_t ni_spare[3]; }; #define IEEE80211_NODE_ATH (IEEE80211_NODE_FF | IEEE80211_NODE_TURBOP) diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_output.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_output.c index 2e598ab585..874ceb8bb8 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_output.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_output.c @@ -2570,6 +2570,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, #ifdef IEEE80211_SUPPORT_MESH if (vap->iv_opmode == IEEE80211_M_MBSS) { frm = ieee80211_add_meshid(frm, vap); + bo->bo_meshconf = frm; frm = ieee80211_add_meshconf(frm, vap); } #endif @@ -2675,13 +2676,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni, *(uint16_t *)wh->i_dur = 0; IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); -#ifdef IEEE80211_SUPPORT_MESH - if (vap->iv_opmode == IEEE80211_M_MBSS) { - static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; - IEEE80211_ADDR_COPY(wh->i_addr3, zerobssid); - } else -#endif - IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); + IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); *(uint16_t *)wh->i_seq = 0; return m; @@ -2786,6 +2781,11 @@ ieee80211_beacon_update(struct ieee80211_node *ni, ieee80211_tdma_update_beacon(vap, bo); } #endif +#ifdef IEEE80211_SUPPORT_MESH + if (vap->iv_opmode == IEEE80211_M_MBSS) + ieee80211_mesh_update_beacon(vap, bo); +#endif + if (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_MBSS) { /* NB: no IBSS support*/ struct ieee80211_tim_ie *tie = @@ -2839,6 +2839,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni, #endif #ifdef IEEE80211_TDMA_SUPPORT bo->bo_tdma += adjust; +#endif +#ifdef IEEE80211_MESH_SUPPORT + bo->bo_meshconf += adjust; #endif bo->bo_appie += adjust; bo->bo_wme += adjust; @@ -2890,6 +2893,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni, #endif #ifdef IEEE80211_TDMA_SUPPORT bo->bo_tdma += sizeof(*csa); +#endif +#ifdef IEEE80211_MESH_SUPPORT + bo->bo_meshconf += sizeof(*csa); #endif bo->bo_appie += sizeof(*csa); bo->bo_csa_trailer_len += sizeof(*csa); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.c index 06d0048c94..fa6b1684fe 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.c @@ -1432,8 +1432,6 @@ ieee80211_swbmiss(void *arg) } else if (vap->iv_swbmiss_count == 0) { if (vap->iv_bmiss != NULL) ieee80211_runtask(ic, &vap->iv_swbmiss_task); - if (vap->iv_bmiss_count == 0) /* don't re-arm timer */ - return; } else vap->iv_swbmiss_count = 0; callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period, diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.h index 965235d9a3..56544f98d5 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_proto.h @@ -317,9 +317,10 @@ struct ieee80211_beacon_offsets { uint8_t *bo_ath; /* start of ATH parameters */ uint8_t *bo_appie; /* start of AppIE element */ uint16_t bo_appie_len; /* AppIE length in bytes */ - uint16_t bo_csa_trailer_len;; + uint16_t bo_csa_trailer_len; uint8_t *bo_csa; /* start of CSA element */ - uint8_t *bo_spare[4]; + uint8_t *bo_meshconf; /* start of MESHCONF element */ + uint8_t *bo_spare[3]; }; struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *, struct ieee80211_beacon_offsets *); @@ -347,6 +348,7 @@ enum { IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */ IEEE80211_BEACON_TDMA = 9, /* TDMA Info */ IEEE80211_BEACON_ATH = 10, /* ATH parameters */ + IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */ }; int ieee80211_beacon_update(struct ieee80211_node *, struct ieee80211_beacon_offsets *, struct mbuf *, int mcast); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.c new file mode 100644 index 0000000000..0ad46bd3bd --- /dev/null +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.c @@ -0,0 +1,92 @@ +/*- + * Copyright (c) 2010 Rui Paulo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static const struct ieee80211_ratectl *ratectls[IEEE80211_RATECTL_MAX]; + +static const char *ratectl_modnames[IEEE80211_RATECTL_MAX] = { + [IEEE80211_RATECTL_AMRR] = "wlan_amrr", + [IEEE80211_RATECTL_RSSADAPT] = "wlan_rssadapt", + [IEEE80211_RATECTL_ONOE] = "wlan_onoe", + [IEEE80211_RATECTL_SAMPLE] = "wlan_sample", + [IEEE80211_RATECTL_NONE] = "wlan_none", +}; + +MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control"); + +void +ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + ratectls[type] = ratectl; +} + +void +ieee80211_ratectl_unregister(int type) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + ratectls[type] = NULL; +} + +void +ieee80211_ratectl_init(struct ieee80211vap *vap) +{ + if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE]) + ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR); + vap->iv_rate->ir_init(vap); +} + +void +ieee80211_ratectl_set(struct ieee80211vap *vap, int type) +{ + if (type >= IEEE80211_RATECTL_MAX) + return; + if (ratectls[type] == NULL) { + ieee80211_load_module(ratectl_modnames[type]); + if (ratectls[type] == NULL) { + IEEE80211_DPRINTF(vap, IEEE80211_MSG_RATECTL, + "%s: unable to load algo %u, module %s\n", + __func__, type, ratectl_modnames[type]); + vap->iv_rate = ratectls[IEEE80211_RATECTL_NONE]; + return; + } + } + vap->iv_rate = ratectls[type]; +} diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.h index 5bcb8cecb4..81a18d0338 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl.h @@ -26,10 +26,11 @@ */ enum ieee80211_ratealgs { - IEEE80211_RATECTL_AMRR = 0, + IEEE80211_RATECTL_AMRR = 0, IEEE80211_RATECTL_RSSADAPT = 1, IEEE80211_RATECTL_ONOE = 2, IEEE80211_RATECTL_SAMPLE = 3, + IEEE80211_RATECTL_NONE = 4, IEEE80211_RATECTL_MAX }; @@ -56,15 +57,10 @@ struct ieee80211_ratectl { void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *); void ieee80211_ratectl_unregister(int); +void ieee80211_ratectl_init(struct ieee80211vap *); void ieee80211_ratectl_set(struct ieee80211vap *, int); MALLOC_DECLARE(M_80211_RATECTL); -#ifndef __HAIKU__ -static void __inline -ieee80211_ratectl_init(struct ieee80211vap *vap) -{ - vap->iv_rate->ir_init(vap); -} static void __inline ieee80211_ratectl_deinit(struct ieee80211vap *vap) @@ -76,8 +72,9 @@ static void __inline ieee80211_ratectl_node_init(struct ieee80211_node *ni) { const struct ieee80211vap *vap = ni->ni_vap; - + kernel_debugger("ieee80211_ratectl_node_init\n"); vap->iv_rate->ir_node_init(ni); + kernel_debugger("ieee80211_ratectl_node_init exit\n"); } static void __inline @@ -85,8 +82,6 @@ ieee80211_ratectl_node_deinit(struct ieee80211_node *ni) { const struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_node_deinit(ni); } @@ -95,8 +90,6 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg) { const struct ieee80211vap *vap = ni->ni_vap; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return 0; return vap->iv_rate->ir_rate(ni, arg, iarg); } @@ -104,8 +97,6 @@ static void __inline ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap, const struct ieee80211_node *ni, int status, void *arg1, void *arg2) { - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2); } @@ -115,8 +106,6 @@ ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, { if (vap->iv_rate->ir_tx_update == NULL) return; - if (ni->ni_rctls == NULL) /* ratectl not setup */ - return; vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3); } @@ -127,4 +116,3 @@ ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs) return; vap->iv_rate->ir_setinterval(vap, msecs); } -#endif diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl_none.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl_none.c new file mode 100644 index 0000000000..0edec449ec --- /dev/null +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_ratectl_none.c @@ -0,0 +1,114 @@ +/*- + * Copyright (c) 2010 Bernhard Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef INET +#include +#include +#endif + +#include +#include + +static void +none_init(struct ieee80211vap *vap) +{ +} + +static void +none_deinit(struct ieee80211vap *vap) +{ + free(vap->iv_rs, M_80211_RATECTL); +} + +static void +none_node_init(struct ieee80211_node *ni) +{ + ni->ni_txrate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL; +} + +static void +none_node_deinit(struct ieee80211_node *ni) +{ +} + +static int +none_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused) +{ + int rix = 0; + + ni->ni_txrate = ni->ni_rates.rs_rates[rix] & IEEE80211_RATE_VAL; + return rix; +} + +static void +none_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int ok, + void *arg1, void *arg2 __unused) +{ +} + +static void +none_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, + void *arg1, void *arg2, void *arg3) +{ +} + +static void +none_setinterval(const struct ieee80211vap *vap, int msecs) +{ +} + +/* number of references from net80211 layer */ +static int nrefs = 0; + +static const struct ieee80211_ratectl none = { + .ir_name = "none", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = none_init, + .ir_deinit = none_deinit, + .ir_node_init = none_node_init, + .ir_node_deinit = none_node_deinit, + .ir_rate = none_rate, + .ir_tx_complete = none_tx_complete, + .ir_tx_update = none_tx_update, + .ir_setinterval = none_setinterval, +}; +IEEE80211_RATECTL_MODULE(ratectl_none, 1); +IEEE80211_RATECTL_ALG(none, IEEE80211_RATECTL_NONE, none); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.c index f1fc409edc..aaf4057a77 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.c @@ -1,6 +1,7 @@ /* $FreeBSD$ */ /* $NetBSD: ieee80211_rssadapt.c,v 1.9 2005/02/26 22:45:09 perry Exp $ */ /*- + * Copyright (c) 2010 Rui Paulo * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or @@ -42,6 +43,7 @@ #include #include +#include struct rssadapt_expavgctl { /* RSS threshold decay. */ @@ -56,12 +58,12 @@ struct rssadapt_expavgctl { }; static struct rssadapt_expavgctl master_expavgctl = { - rc_decay_denom : 16, - rc_decay_old : 15, - rc_thresh_denom : 8, - rc_thresh_old : 4, - rc_avgrssi_denom : 8, - rc_avgrssi_old : 4 + .rc_decay_denom = 16, + .rc_decay_old = 15, + .rc_thresh_denom = 8, + .rc_thresh_old = 4, + .rc_avgrssi_denom = 8, + .rc_avgrssi_old = 4 }; #ifdef interpolate @@ -71,15 +73,45 @@ static struct rssadapt_expavgctl master_expavgctl = { (parm##_denom - parm##_old) * (new)) / \ parm##_denom) -static void rssadapt_sysctlattach(struct ieee80211_rssadapt *rs, - struct sysctl_ctx_list *ctx, struct sysctl_oid *tree); +static void rssadapt_setinterval(const struct ieee80211vap *, int); +static void rssadapt_init(struct ieee80211vap *); +static void rssadapt_deinit(struct ieee80211vap *); +static void rssadapt_updatestats(struct ieee80211_rssadapt_node *); +static void rssadapt_node_init(struct ieee80211_node *); +static void rssadapt_node_deinit(struct ieee80211_node *); +static int rssadapt_rate(struct ieee80211_node *, void *, uint32_t); +static void rssadapt_lower_rate(struct ieee80211_rssadapt_node *, int, int); +static void rssadapt_raise_rate(struct ieee80211_rssadapt_node *, + int, int); +static void rssadapt_tx_complete(const struct ieee80211vap *, + const struct ieee80211_node *, int, + void *, void *); +static void rssadapt_sysctlattach(struct ieee80211vap *, + struct sysctl_ctx_list *, struct sysctl_oid *); /* number of references from net80211 layer */ static int nrefs = 0; -void -ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs) +static const struct ieee80211_ratectl rssadapt = { + .ir_name = "rssadapt", + .ir_attach = NULL, + .ir_detach = NULL, + .ir_init = rssadapt_init, + .ir_deinit = rssadapt_deinit, + .ir_node_init = rssadapt_node_init, + .ir_node_deinit = rssadapt_node_deinit, + .ir_rate = rssadapt_rate, + .ir_tx_complete = rssadapt_tx_complete, + .ir_tx_update = NULL, + .ir_setinterval = rssadapt_setinterval, +}; +IEEE80211_RATECTL_MODULE(rssadapt, 1); +IEEE80211_RATECTL_ALG(rssadapt, IEEE80211_RATECTL_RSSADAPT, rssadapt); + +static void +rssadapt_setinterval(const struct ieee80211vap *vap, int msecs) { + struct ieee80211_rssadapt *rs = vap->iv_rs; int t; if (msecs < 100) @@ -88,18 +120,29 @@ ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs) rs->interval = (t < 1) ? 1 : t; } -void -ieee80211_rssadapt_init(struct ieee80211_rssadapt *rs, struct ieee80211vap *vap, int interval) +static void +rssadapt_init(struct ieee80211vap *vap) { - rs->vap = vap; - ieee80211_rssadapt_setinterval(rs, interval); + struct ieee80211_rssadapt *rs; - rssadapt_sysctlattach(rs, vap->iv_sysctl, vap->iv_oid); + KASSERT(vap->iv_rs == NULL, ("%s: iv_rs already initialized", + __func__)); + + vap->iv_rs = rs = malloc(sizeof(struct ieee80211_rssadapt), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (rs == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc ratectl structure\n"); + return; + } + rs->vap = vap; + rssadapt_setinterval(vap, 500 /* msecs */); + rssadapt_sysctlattach(vap, vap->iv_sysctl, vap->iv_oid); } -void -ieee80211_rssadapt_cleanup(struct ieee80211_rssadapt *rs) +static void +rssadapt_deinit(struct ieee80211vap *vap) { + free(vap->iv_rs, M_80211_RATECTL); } static void @@ -118,12 +161,25 @@ rssadapt_updatestats(struct ieee80211_rssadapt_node *ra) ra->ra_raise_interval = msecs_to_ticks(interval); } -void -ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa, - struct ieee80211_rssadapt_node *ra, struct ieee80211_node *ni) +static void +rssadapt_node_init(struct ieee80211_node *ni) { + struct ieee80211_rssadapt_node *ra; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_rssadapt *rsa = vap->iv_rs; const struct ieee80211_rateset *rs = &ni->ni_rates; + if (ni->ni_rctls == NULL) { + ni->ni_rctls = ra = + malloc(sizeof(struct ieee80211_rssadapt_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (ra == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } + } else + ra = ni->ni_rctls; ra->ra_rs = rsa; ra->ra_rates = *rs; rssadapt_updatestats(ra); @@ -140,6 +196,13 @@ ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa, "RSSADAPT initial rate %d", ni->ni_txrate); } +static void +rssadapt_node_deinit(struct ieee80211_node *ni) +{ + + free(ni->ni_rctls, M_80211_RATECTL); +} + static __inline int bucket(int pktlen) { @@ -155,10 +218,11 @@ bucket(int pktlen) return thridx; } -int -ieee80211_rssadapt_choose(struct ieee80211_node *ni, - struct ieee80211_rssadapt_node *ra, u_int pktlen) +static int +rssadapt_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg) { + struct ieee80211_rssadapt_node *ra = ni->ni_rctls; + u_int pktlen = iarg; const struct ieee80211_rateset *rs = &ra->ra_rates; uint16_t (*thrs)[IEEE80211_RATE_SIZE]; int rix, rssi; @@ -193,9 +257,8 @@ ieee80211_rssadapt_choose(struct ieee80211_node *ni, * raise the RSS threshold for transmitting packets of similar length at * the same data rate. */ -void -ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, - int pktlen, int rssi) +static void +rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi) { uint16_t last_thr; uint16_t (*thrs)[IEEE80211_RATE_SIZE]; @@ -214,9 +277,8 @@ ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, last_thr, (*thrs)[rix], rssi); } -void -ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, - int pktlen, int rssi) +static void +rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi) { uint16_t (*thrs)[IEEE80211_RATE_SIZE]; uint16_t newthr, oldthr; @@ -243,31 +305,45 @@ ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, } } +static void +rssadapt_tx_complete(const struct ieee80211vap *vap, + const struct ieee80211_node *ni, int success, void *arg1, void *arg2) +{ + struct ieee80211_rssadapt_node *ra = ni->ni_rctls; + int pktlen = *(int *)arg1, rssi = *(int *)arg2; + + if (success) { + ra->ra_nok++; + if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates && + (ticks - ra->ra_last_raise) >= ra->ra_raise_interval) + rssadapt_raise_rate(ra, pktlen, rssi); + } else { + ra->ra_nfail++; + rssadapt_lower_rate(ra, pktlen, rssi); + } +} + static int rssadapt_sysctl_interval(SYSCTL_HANDLER_ARGS) { - struct ieee80211_rssadapt *rs = arg1; + struct ieee80211vap *vap = arg1; + struct ieee80211_rssadapt *rs = vap->iv_rs; int msecs = ticks_to_msecs(rs->interval); int error; error = sysctl_handle_int(oidp, &msecs, 0, req); if (error || !req->newptr) return error; - ieee80211_rssadapt_setinterval(rs, msecs); + rssadapt_setinterval(vap, msecs); return 0; } static void -rssadapt_sysctlattach(struct ieee80211_rssadapt *rs, +rssadapt_sysctlattach(struct ieee80211vap *vap, struct sysctl_ctx_list *ctx, struct sysctl_oid *tree) { SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "rssadapt_rate_interval", CTLTYPE_INT | CTLFLAG_RW, rs, + "rssadapt_rate_interval", CTLTYPE_INT | CTLFLAG_RW, vap, 0, rssadapt_sysctl_interval, "I", "rssadapt operation interval (ms)"); } - -/* - * Module glue. - */ -IEEE80211_RATE_MODULE(rssadapt, 1); diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.h index a88e9b2ce5..d3bc711760 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_rssadapt.h @@ -43,7 +43,7 @@ #define IEEE80211_RSSADAPT_BKTPOWER 3 /* 2**_BKTPOWER */ struct ieee80211_rssadapt { - struct ieee80211vap *vap; + const struct ieee80211vap *vap; int interval; /* update interval (ticks) */ }; @@ -66,36 +66,6 @@ struct ieee80211_rssadapt_node { [IEEE80211_RATE_SIZE]; }; -void ieee80211_rssadapt_init(struct ieee80211_rssadapt *, - struct ieee80211vap *, int); -void ieee80211_rssadapt_cleanup(struct ieee80211_rssadapt *); -void ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *, int); -void ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *, - struct ieee80211_rssadapt_node *, struct ieee80211_node *); -int ieee80211_rssadapt_choose(struct ieee80211_node *, - struct ieee80211_rssadapt_node *, u_int); - -/* NB: these are public only for the inline below */ -void ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *, - int pktlen, int rssi); -void ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *, - int pktlen, int rssi); - #define IEEE80211_RSSADAPT_SUCCESS 1 #define IEEE80211_RSSADAPT_FAILURE 0 - -static __inline void -ieee80211_rssadapt_tx_complete(struct ieee80211_rssadapt_node *ra, - int success, int pktlen, int rssi) -{ - if (success) { - ra->ra_nok++; - if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates && - (ticks - ra->ra_last_raise) >= ra->ra_raise_interval) - ieee80211_rssadapt_raise_rate(ra, pktlen, rssi); - } else { - ra->ra_nfail++; - ieee80211_rssadapt_lower_rate(ra, pktlen, rssi); - } -} #endif /* _FBSD_COMPAT_NET80211_IEEE80211_RSSADAPT_H_ */ diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_scan_sta.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_scan_sta.c index 341e85345e..3c1ed811d6 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_scan_sta.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_scan_sta.c @@ -97,7 +97,7 @@ struct sta_entry { CTASSERT(MAX_IEEE_CHAN >= 256); struct sta_table { - struct mtx st_lock; /* on scan table */ + ieee80211_scan_table_lock_t st_lock; /* on scan table */ TAILQ_HEAD(, sta_entry) st_entry; /* all entries */ LIST_HEAD(, sta_entry) st_hash[STA_HASHSIZE]; struct mtx st_scanlock; /* on st_scaniter */ @@ -161,7 +161,7 @@ sta_attach(struct ieee80211_scan_state *ss) M_80211_SCAN, M_NOWAIT | M_ZERO); if (st == NULL) return 0; - mtx_init(&st->st_lock, "scantable", "802.11 scan table", MTX_DEF); + IEEE80211_SCAN_TABLE_LOCK_INIT(st, "scantable"); mtx_init(&st->st_scanlock, "scangen", "802.11 scangen", MTX_DEF); TAILQ_INIT(&st->st_entry); ss->ss_priv = st; @@ -179,7 +179,7 @@ sta_detach(struct ieee80211_scan_state *ss) if (st != NULL) { sta_flush_table(st); - mtx_destroy(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK_DESTROY(st); mtx_destroy(&st->st_scanlock); free(st, M_80211_SCAN); KASSERT(nrefs > 0, ("imbalanced attach/detach")); @@ -196,9 +196,9 @@ sta_flush(struct ieee80211_scan_state *ss) { struct sta_table *st = ss->ss_priv; - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); sta_flush_table(st); - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); ss->ss_last = 0; return 0; } @@ -244,14 +244,14 @@ sta_add(struct ieee80211_scan_state *ss, hash = STA_HASH(macaddr); - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); LIST_FOREACH(se, &st->st_hash[hash], se_hash) if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr)) goto found; se = (struct sta_entry *) malloc(sizeof(struct sta_entry), M_80211_SCAN, M_NOWAIT | M_ZERO); if (se == NULL) { - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); return 0; } se->se_scangen = st->st_scaniter-1; @@ -370,7 +370,7 @@ found: if (rssi > st->st_maxrssi[sp->bchan]) st->st_maxrssi[sp->bchan] = rssi; - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); /* * If looking for a quick choice and nothing's @@ -1013,7 +1013,7 @@ match_bss(struct ieee80211vap *vap, */ if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS)) fail |= MATCH_CAPINFO; - else if (se->se_meshid == NULL) + else if (se->se_meshid[0] != IEEE80211_ELEMID_MESHID) fail |= MATCH_MESH_NOID; else if (ms->ms_idlen != 0 && match_id(se->se_meshid, ms->ms_id, ms->ms_idlen)) @@ -1132,7 +1132,7 @@ sta_update_notseen(struct sta_table *st) { struct sta_entry *se; - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); TAILQ_FOREACH(se, &st->st_entry, se_list) { /* * If seen the reset and don't bump the count; @@ -1146,7 +1146,7 @@ sta_update_notseen(struct sta_table *st) else se->se_notseen++; } - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); } static void @@ -1154,11 +1154,11 @@ sta_dec_fails(struct sta_table *st) { struct sta_entry *se; - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); TAILQ_FOREACH(se, &st->st_entry, se_list) if (se->se_fails) se->se_fails--; - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); } static struct sta_entry * @@ -1169,7 +1169,7 @@ select_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, int debug) IEEE80211_DPRINTF(vap, debug, " %s\n", "macaddr bssid chan rssi rate flag wep essid"); - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); TAILQ_FOREACH(se, &st->st_entry, se_list) { ieee80211_ies_expand(&se->base.se_ies); if (match_bss(vap, ss, se, debug) == 0) { @@ -1179,7 +1179,7 @@ select_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap, int debug) selbs = se; } } - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); return selbs; } @@ -1258,11 +1258,11 @@ sta_lookup(struct sta_table *st, const uint8_t macaddr[IEEE80211_ADDR_LEN]) struct sta_entry *se; int hash = STA_HASH(macaddr); - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); LIST_FOREACH(se, &st->st_hash[hash], se_hash) if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr)) break; - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); return se; /* NB: unlocked */ } @@ -1361,7 +1361,7 @@ sta_age(struct ieee80211_scan_state *ss) KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("wrong mode %u", vap->iv_opmode)); if (vap->iv_roaming == IEEE80211_ROAMING_AUTO && - (vap->iv_ic->ic_flags & IEEE80211_F_BGSCAN) && + (vap->iv_flags & IEEE80211_F_BGSCAN) && vap->iv_state >= IEEE80211_S_RUN) /* XXX vap is implicit */ sta_roam_check(ss, vap); @@ -1382,18 +1382,18 @@ sta_iterate(struct ieee80211_scan_state *ss, mtx_lock(&st->st_scanlock); gen = st->st_scaniter++; restart: - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); TAILQ_FOREACH(se, &st->st_entry, se_list) { if (se->se_scangen != gen) { se->se_scangen = gen; /* update public state */ se->base.se_age = ticks - se->se_lastupdate; - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); (*f)(arg, &se->base); goto restart; } } - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); mtx_unlock(&st->st_scanlock); } @@ -1509,7 +1509,7 @@ adhoc_pick_channel(struct ieee80211_scan_state *ss, int flags) bestchan = NULL; bestrssi = -1; - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); for (i = 0; i < ss->ss_last; i++) { c = ss->ss_chans[i]; /* never consider a channel with radar */ @@ -1531,7 +1531,7 @@ adhoc_pick_channel(struct ieee80211_scan_state *ss, int flags) if (bestchan == NULL || maxrssi < bestrssi) bestchan = c; } - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); return bestchan; } @@ -1637,7 +1637,7 @@ adhoc_age(struct ieee80211_scan_state *ss) struct sta_table *st = ss->ss_priv; struct sta_entry *se, *next; - mtx_lock(&st->st_lock); + IEEE80211_SCAN_TABLE_LOCK(st); TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) { if (se->se_notseen > STA_PURGE_SCANS) { TAILQ_REMOVE(&st->st_entry, se, se_list); @@ -1646,7 +1646,7 @@ adhoc_age(struct ieee80211_scan_state *ss) free(se, M_80211_SCAN); } } - mtx_unlock(&st->st_lock); + IEEE80211_SCAN_TABLE_UNLOCK(st); } static const struct ieee80211_scanner adhoc_default = { diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_sta.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_sta.c index fe8c9fa10e..f377d86e6d 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_sta.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_sta.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #ifdef IEEE80211_SUPPORT_SUPERG #include #endif +#include #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) @@ -141,6 +142,8 @@ sta_beacon_miss(struct ieee80211vap *vap) vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen); return; } + + callout_stop(&vap->iv_swbmiss); vap->iv_bmiss_count = 0; vap->iv_stats.is_beacon_miss++; if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) { @@ -517,7 +520,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) struct ieee80211_frame *wh; struct ieee80211_key *key; struct ether_header *eh; - int hdrspace, need_tap; + int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint8_t *bssid; uint16_t rxseq; @@ -542,7 +545,6 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) KASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; - need_tap = 1; /* mbuf need to be tapped. */ type = -1; /* undefined */ if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { @@ -583,7 +585,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) } IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); ni->ni_noise = nf; - if (HAS_SEQ(type)) { + if (HAS_SEQ(type) && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { uint8_t tid = ieee80211_gettid(wh); if (IEEE80211_QOS_HAS_SEQ(wh) && TID_TO_WME_AC(tid) >= WME_AC_VI) @@ -759,7 +761,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) /* copy to listener after decrypt */ if (ieee80211_radiotap_active_vap(vap)) - ieee80211_radiotap_tx(vap, m); + ieee80211_radiotap_rx(vap, m); need_tap = 0; /* @@ -1595,6 +1597,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, IEEE80211_F_JOIN | IEEE80211_F_DOBRS); ieee80211_setup_basic_htrates(ni, htinfo); ieee80211_node_setuptxparms(ni); + ieee80211_ratectl_node_init(ni); } else { #ifdef IEEE80211_SUPPORT_SUPERG if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_ATH)) diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_tdma.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_tdma.c index 43f32f7fd9..8c191ab92b 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_tdma.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_tdma.c @@ -295,6 +295,8 @@ tdma_beacon_miss(struct ieee80211vap *vap) "beacon miss, mode %u state %s\n", vap->iv_opmode, ieee80211_state_name[vap->iv_state]); + callout_stop(&vap->iv_swbmiss); + if (ts->tdma_peer != NULL) { /* XXX? can this be null? */ ieee80211_notify_node_leave(vap->iv_bss); ts->tdma_peer = NULL; diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_var.h b/src/libs/compat/freebsd_wlan/net80211/ieee80211_var.h index 88a630a07f..6848e0524b 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_var.h +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_var.h @@ -33,11 +33,11 @@ * Definitions for IEEE 802.11 drivers. */ /* NB: portability glue must go first */ -#ifdef __NetBSD__ +#if defined(__NetBSD__) #include -#elif __FreeBSD__ +#elif defined(__FreeBSD__) #include -#elif __linux__ +#elif defined(__linux__) #include #elif __HAIKU__ #include @@ -436,6 +436,9 @@ struct ieee80211vap { const struct ieee80211_aclator *iv_acl; /* acl glue */ void *iv_as; /* private aclator state */ + const struct ieee80211_ratectl *iv_rate; + void *iv_rs; /* private ratectl state */ + struct ieee80211_tdma_state *iv_tdma; /* tdma state */ struct ieee80211_mesh_state *iv_mesh; /* MBSS state */ struct ieee80211_hwmp_state *iv_hwmp; /* HWMP state */ @@ -471,7 +474,7 @@ struct ieee80211vap { /* 802.3 output method for raw frame xmit */ int (*iv_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *); - uint64_t iv_spare[8]; + uint64_t iv_spare[6]; }; #define IEEE80211_ADDR_EQ(a1,a2) (memcmp(a1,a2,IEEE80211_ADDR_LEN) == 0) @@ -547,11 +550,12 @@ struct ieee80211vap { /* NB: immutable: should be set only when creating a vap */ #define IEEE80211_FEXT_WDSLEGACY 0x00010000 /* CONF: legacy WDS operation */ #define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/ +#define IEEE80211_FEXT_UNIQMAC 0x00040000 /* CONF: user or computed mac */ #define IEEE80211_FEXT_BITS \ "\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \ "\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \ - "\20BPF\21WDSLEGACY\22PROBECHAN" + "\20BPF\21WDSLEGACY\22PROBECHAN\23UNIQMAC" /* ic_flags_ht/iv_flags_ht */ #define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */ @@ -850,10 +854,10 @@ ieee80211_htchanflags(const struct ieee80211_channel *c) if (ieee80211_msg(_vap, _m)) \ ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__); \ } while (0) -void ieee80211_note(struct ieee80211vap *, const char *, ...); -void ieee80211_note_mac(struct ieee80211vap *, +void ieee80211_note(const struct ieee80211vap *, const char *, ...); +void ieee80211_note_mac(const struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN], const char *, ...); -void ieee80211_note_frame(struct ieee80211vap *, +void ieee80211_note_frame(const struct ieee80211vap *, const struct ieee80211_frame *, const char *, ...); #define ieee80211_msg_debug(_vap) \ ((_vap)->iv_debug & IEEE80211_MSG_DEBUG) @@ -891,11 +895,11 @@ void ieee80211_note_frame(struct ieee80211vap *, ieee80211_discard_mac(_vap, _mac, _type, _fmt, __VA_ARGS__);\ } while (0) -void ieee80211_discard_frame(struct ieee80211vap *, +void ieee80211_discard_frame(const struct ieee80211vap *, const struct ieee80211_frame *, const char *type, const char *fmt, ...); -void ieee80211_discard_ie(struct ieee80211vap *, +void ieee80211_discard_ie(const struct ieee80211vap *, const struct ieee80211_frame *, const char *type, const char *fmt, ...); -void ieee80211_discard_mac(struct ieee80211vap *, +void ieee80211_discard_mac(const struct ieee80211vap *, const uint8_t mac[IEEE80211_ADDR_LEN], const char *type, const char *fmt, ...); #else diff --git a/src/libs/compat/freebsd_wlan/net80211/ieee80211_wds.c b/src/libs/compat/freebsd_wlan/net80211/ieee80211_wds.c index 807648c6f4..15518d8181 100644 --- a/src/libs/compat/freebsd_wlan/net80211/ieee80211_wds.c +++ b/src/libs/compat/freebsd_wlan/net80211/ieee80211_wds.c @@ -414,7 +414,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) struct ieee80211_frame *wh; struct ieee80211_key *key; struct ether_header *eh; - int hdrspace, need_tap; + int hdrspace, need_tap = 1; /* mbuf need to be tapped. */ uint8_t dir, type, subtype, qos; uint16_t rxseq; @@ -437,7 +437,6 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf) KASSERT(ni != NULL, ("null node")); - need_tap = 1; /* mbuf need to be tapped. */ type = -1; /* undefined */ if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {