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
This commit is contained in:
@@ -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));
|
||||
|
||||
@@ -64,8 +64,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_phy.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -54,7 +54,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_regdomain.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <compat/net/ethernet.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
#include <net80211/ieee80211_superg.h>
|
||||
#endif
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* $OpenBSD: ieee80211_amrr.c,v 1.1 2006/06/17 19:07:19 damien Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
|
||||
* Copyright (c) 2006
|
||||
* Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
@@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_amrr.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#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, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <machine/stdarg.h>
|
||||
|
||||
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, ...)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
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];
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*-
|
||||
* Copyright (c) 2010 Bernhard Schmidt <bschmidt@FreeBSD.org>
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_wlan.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#ifdef INET
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
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);
|
||||
@@ -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 <rpaulo@FreeBSD.org>
|
||||
* Copyright (c) 2003, 2004 David Young. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
@@ -42,6 +43,7 @@
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_rssadapt.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
#include <net80211/ieee80211_superg.h>
|
||||
#endif
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
* Definitions for IEEE 802.11 drivers.
|
||||
*/
|
||||
/* NB: portability glue must go first */
|
||||
#ifdef __NetBSD__
|
||||
#if defined(__NetBSD__)
|
||||
#include <net80211/ieee80211_netbsd.h>
|
||||
#elif __FreeBSD__
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <net80211/ieee80211_freebsd.h>
|
||||
#elif __linux__
|
||||
#elif defined(__linux__)
|
||||
#include <net80211/ieee80211_linux.h>
|
||||
#elif __HAIKU__
|
||||
#include <net80211/ieee80211_haiku.h>
|
||||
@@ -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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user