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_watchdog = an_watchdog;
|
||||||
ifp->if_init = an_init;
|
ifp->if_init = an_init;
|
||||||
ifp->if_baudrate = 10000000;
|
ifp->if_baudrate = 10000000;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename));
|
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_var.h>
|
||||||
#include <net80211/ieee80211_radiotap.h>
|
#include <net80211/ieee80211_radiotap.h>
|
||||||
#include <net80211/ieee80211_regdomain.h>
|
#include <net80211/ieee80211_regdomain.h>
|
||||||
#include <net80211/ieee80211_amrr.h>
|
|
||||||
#include <net80211/ieee80211_phy.h>
|
#include <net80211/ieee80211_phy.h>
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#include <net/bpf.h>
|
#include <net/bpf.h>
|
||||||
|
|
||||||
@@ -112,9 +112,6 @@ static void bwi_set_channel(struct ieee80211com *);
|
|||||||
static void bwi_scan_end(struct ieee80211com *);
|
static void bwi_scan_end(struct ieee80211com *);
|
||||||
static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
static int bwi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
||||||
static void bwi_updateslot(struct ifnet *);
|
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 int bwi_media_change(struct ifnet *);
|
||||||
|
|
||||||
static void bwi_calibrate(void *);
|
static void bwi_calibrate(void *);
|
||||||
@@ -465,8 +462,8 @@ bwi_attach(struct bwi_softc *sc)
|
|||||||
ifp->if_ioctl = bwi_ioctl;
|
ifp->if_ioctl = bwi_ioctl;
|
||||||
ifp->if_start = bwi_start;
|
ifp->if_start = bwi_start;
|
||||||
ifp->if_watchdog = bwi_watchdog;
|
ifp->if_watchdog = bwi_watchdog;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
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_vap_delete = bwi_vap_delete;
|
||||||
ic->ic_raw_xmit = bwi_raw_xmit;
|
ic->ic_raw_xmit = bwi_raw_xmit;
|
||||||
ic->ic_updateslot = bwi_updateslot;
|
ic->ic_updateslot = bwi_updateslot;
|
||||||
ic->ic_node_alloc = bwi_node_alloc;
|
|
||||||
ic->ic_scan_start = bwi_scan_start;
|
ic->ic_scan_start = bwi_scan_start;
|
||||||
ic->ic_scan_end = bwi_scan_end;
|
ic->ic_scan_end = bwi_scan_end;
|
||||||
ic->ic_set_channel = bwi_set_channel;
|
ic->ic_set_channel = bwi_set_channel;
|
||||||
@@ -620,10 +616,7 @@ bwi_vap_create(struct ieee80211com *ic,
|
|||||||
#if 0
|
#if 0
|
||||||
vap->iv_update_beacon = bwi_beacon_update;
|
vap->iv_update_beacon = bwi_beacon_update;
|
||||||
#endif
|
#endif
|
||||||
ieee80211_amrr_init(&bvp->bv_amrr, vap,
|
ieee80211_ratectl_init(vap);
|
||||||
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
|
|
||||||
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
|
|
||||||
500 /*ms*/);
|
|
||||||
|
|
||||||
/* complete setup */
|
/* complete setup */
|
||||||
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
|
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);
|
struct bwi_vap *bvp = BWI_VAP(vap);
|
||||||
|
|
||||||
ieee80211_amrr_cleanup(&bvp->bv_amrr);
|
ieee80211_ratectl_deinit(vap);
|
||||||
ieee80211_vap_detach(vap);
|
ieee80211_vap_detach(vap);
|
||||||
free(bvp, M_80211_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;
|
enum ieee80211_state ostate = vap->iv_state;
|
||||||
struct bwi_softc *sc = ifp->if_softc;
|
struct bwi_softc *sc = ifp->if_softc;
|
||||||
struct bwi_mac *mac;
|
struct bwi_mac *mac;
|
||||||
struct ieee80211_node *ni = vap->iv_bss;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
BWI_LOCK(sc);
|
BWI_LOCK(sc);
|
||||||
@@ -1830,10 +1822,6 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
#else
|
#else
|
||||||
sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
|
sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
|
||||||
#endif
|
#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);
|
callout_reset(&sc->sc_calib_ch, hz, bwi_calibrate, sc);
|
||||||
}
|
}
|
||||||
@@ -1843,25 +1831,6 @@ back:
|
|||||||
return error;
|
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
|
static int
|
||||||
bwi_media_change(struct ifnet *ifp)
|
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) {
|
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
||||||
rate = rate_fb = tp->ucastrate;
|
rate = rate_fb = tp->ucastrate;
|
||||||
} else {
|
} else {
|
||||||
rix = ieee80211_amrr_choose(ni, &BWI_NODE(ni)->amn);
|
rix = ieee80211_ratectl_rate(ni, NULL, pkt_len);
|
||||||
rate = ni->ni_txrate;
|
rate = ni->ni_txrate;
|
||||||
|
|
||||||
if (rix > 0) {
|
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;
|
struct bwi_txbuf *tb;
|
||||||
int ring_idx, buf_idx;
|
int ring_idx, buf_idx;
|
||||||
struct ieee80211_node *ni;
|
struct ieee80211_node *ni;
|
||||||
|
struct ieee80211vap *vap;
|
||||||
|
|
||||||
if (tx_id == 0) {
|
if (tx_id == 0) {
|
||||||
if_printf(ifp, "%s: zero tx id\n", __func__);
|
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;
|
ni = tb->tb_ni;
|
||||||
if (tb->tb_ni != NULL) {
|
if (tb->tb_ni != NULL) {
|
||||||
struct bwi_node *bn = (struct bwi_node *) tb->tb_ni;
|
|
||||||
const struct bwi_txbuf_hdr *hdr =
|
const struct bwi_txbuf_hdr *hdr =
|
||||||
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
|
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
|
||||||
|
vap = ni->ni_vap;
|
||||||
|
|
||||||
/* NB: update rate control only for unicast frames */
|
/* NB: update rate control only for unicast frames */
|
||||||
if (hdr->txh_mac_ctrl & htole32(BWI_TXH_MAC_C_ACK)) {
|
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
|
* well so to avoid over-aggressive downshifting we
|
||||||
* treat any number of retries as "1".
|
* treat any number of retries as "1".
|
||||||
*/
|
*/
|
||||||
ieee80211_amrr_tx_complete(&bn->amn, acked,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
data_txcnt > 1);
|
(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, 0x4318,"Broadcom BCM4318 802.11b/g Wireless Lan" },
|
||||||
{ PCI_VENDOR_BROADCOM, 0x4319,"Broadcom BCM4318 802.11a/b/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" },
|
{ PCI_VENDOR_BROADCOM, 0x431a,"Broadcom BCM4318 802.11a Wireless Lan" },
|
||||||
{ 0, 0, NULL}
|
{ 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -533,15 +533,8 @@ struct bwi_rx_radiotap_hdr {
|
|||||||
/* TODO: sq */
|
/* 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 bwi_vap {
|
||||||
struct ieee80211vap bv_vap;
|
struct ieee80211vap bv_vap;
|
||||||
struct ieee80211_amrr bv_amrr;
|
|
||||||
int (*bv_newstate)(struct ieee80211vap *,
|
int (*bv_newstate)(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
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_config(struct iwi_softc *);
|
||||||
static int iwi_get_firmware(struct iwi_softc *, enum ieee80211_opmode);
|
static int iwi_get_firmware(struct iwi_softc *, enum ieee80211_opmode);
|
||||||
static void iwi_put_firmware(struct iwi_softc *);
|
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 int iwi_scanchan(struct iwi_softc *, unsigned long, int);
|
||||||
static void iwi_scan_start(struct ieee80211com *);
|
static void iwi_scan_start(struct ieee80211com *);
|
||||||
static void iwi_scan_end(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_restarttask, 0, iwi_restart, sc);
|
||||||
TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
|
TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
|
||||||
TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, 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_wdtimer, &sc->sc_mtx, 0);
|
||||||
callout_init_mtx(&sc->sc_rftimer, &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_init = iwi_init;
|
||||||
ifp->if_ioctl = iwi_ioctl;
|
ifp->if_ioctl = iwi_ioctl;
|
||||||
ifp->if_start = iwi_start;
|
ifp->if_start = iwi_start;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
@@ -460,6 +462,7 @@ iwi_detach(device_t dev)
|
|||||||
ieee80211_draintask(ic, &sc->sc_radiofftask);
|
ieee80211_draintask(ic, &sc->sc_radiofftask);
|
||||||
ieee80211_draintask(ic, &sc->sc_restarttask);
|
ieee80211_draintask(ic, &sc->sc_restarttask);
|
||||||
ieee80211_draintask(ic, &sc->sc_disassoctask);
|
ieee80211_draintask(ic, &sc->sc_disassoctask);
|
||||||
|
ieee80211_draintask(ic, &sc->sc_monitortask);
|
||||||
|
|
||||||
iwi_stop(sc);
|
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.
|
* This is all totally bogus and needs to be redone.
|
||||||
*/
|
*/
|
||||||
iwi_auth_and_assoc(sc, vap);
|
iwi_auth_and_assoc(sc, vap);
|
||||||
}
|
} else if (vap->iv_opmode == IEEE80211_M_MONITOR)
|
||||||
|
ieee80211_runtask(ic, &sc->sc_monitortask);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_S_ASSOC:
|
case IEEE80211_S_ASSOC:
|
||||||
/*
|
/*
|
||||||
@@ -1364,7 +1368,7 @@ iwi_checkforqos(struct ieee80211vap *vap,
|
|||||||
|
|
||||||
ni = vap->iv_bss;
|
ni = vap->iv_bss;
|
||||||
ni->ni_capinfo = capinfo;
|
ni->ni_capinfo = capinfo;
|
||||||
ni->ni_associd = associd;
|
ni->ni_associd = associd & 0x3fff;
|
||||||
if (wme != NULL)
|
if (wme != NULL)
|
||||||
ni->ni_flags |= IEEE80211_NODE_QOS;
|
ni->ni_flags |= IEEE80211_NODE_QOS;
|
||||||
else
|
else
|
||||||
@@ -1407,6 +1411,18 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
|
|||||||
|
|
||||||
IWI_STATE_END(sc, IWI_FW_SCANNING);
|
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) {
|
if (scan->status == IWI_SCAN_COMPLETED) {
|
||||||
/* NB: don't need to defer, net80211 does it for us */
|
/* NB: don't need to defer, net80211 does it for us */
|
||||||
ieee80211_scan_next(vap);
|
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_STATE_END(sc, IWI_FW_ASSOCIATING);
|
||||||
iwi_checkforqos(vap,
|
iwi_checkforqos(vap,
|
||||||
(const struct ieee80211_frame *)(assoc+1),
|
(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);
|
ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
|
||||||
break;
|
break;
|
||||||
case IWI_ASSOC_INIT:
|
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.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
|
||||||
config.disable_unicast_decryption = 1;
|
config.disable_unicast_decryption = 1;
|
||||||
config.disable_multicast_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"));
|
DPRINTF(("Configuring adapter\n"));
|
||||||
error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
|
error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
|
||||||
if (error != 0)
|
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;
|
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.
|
* 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_restarttask; /* restart adapter processing */
|
||||||
struct task sc_disassoctask;
|
struct task sc_disassoctask;
|
||||||
struct task sc_wmetask; /* set wme parameters */
|
struct task sc_wmetask; /* set wme parameters */
|
||||||
|
struct task sc_monitortask;
|
||||||
|
|
||||||
unsigned int sc_softled : 1, /* enable LED gpio status */
|
unsigned int sc_softled : 1, /* enable LED gpio status */
|
||||||
sc_ledstate: 1, /* LED on/off state */
|
sc_ledstate: 1, /* LED on/off state */
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ KernelAddon iprowifi3945 :
|
|||||||
libfreebsd_network.a
|
libfreebsd_network.a
|
||||||
;
|
;
|
||||||
|
|
||||||
HAIKU_WIFI_FIRMWARE_PACKAGE on iprowifi3945 = iwlwifi-3945-ucode-2.14.1.5 ;
|
HAIKU_WIFI_FIRMWARE_PACKAGE on iprowifi3945 = iwlwifi-3945-ucode-15.32.2.9 ;
|
||||||
HAIKU_WIFI_FIRMWARE_ARCHIVE on iprowifi3945 = iwlwifi-3945-ucode-2.14.1.5.tgz ;
|
HAIKU_WIFI_FIRMWARE_ARCHIVE on iprowifi3945 = iwlwifi-3945-ucode-15.32.2.9.tgz ;
|
||||||
HAIKU_WIFI_FIRMWARE_DO_EXTRACT on iprowifi3945 = true ;
|
HAIKU_WIFI_FIRMWARE_DO_EXTRACT on iprowifi3945 = true ;
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <net80211/ieee80211_var.h>
|
#include <net80211/ieee80211_var.h>
|
||||||
#include <net80211/ieee80211_radiotap.h>
|
#include <net80211/ieee80211_radiotap.h>
|
||||||
#include <net80211/ieee80211_regdomain.h>
|
#include <net80211/ieee80211_regdomain.h>
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
@@ -126,7 +127,7 @@ enum {
|
|||||||
WPI_DEBUG_ANY = 0xffffffff
|
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");
|
SYSCTL_INT(_debug, OID_AUTO, wpi, CTLFLAG_RW, &wpi_debug, 0, "wpi debug level");
|
||||||
TUNABLE_INT("debug.wpi", &wpi_debug);
|
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);
|
int, int);
|
||||||
static void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
|
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 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 int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
||||||
static void wpi_mem_lock(struct wpi_softc *);
|
static void wpi_mem_lock(struct wpi_softc *);
|
||||||
static void wpi_mem_unlock(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(struct wpi_softc *);
|
||||||
static void wpi_stop_locked(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 *,
|
static int wpi_set_txpower(struct wpi_softc *, struct ieee80211_channel *,
|
||||||
int);
|
int);
|
||||||
static void wpi_calib_timeout(void *);
|
static void wpi_calib_timeout(void *);
|
||||||
@@ -665,14 +663,12 @@ wpi_attach(device_t dev)
|
|||||||
ifp->if_init = wpi_init;
|
ifp->if_init = wpi_init;
|
||||||
ifp->if_ioctl = wpi_ioctl;
|
ifp->if_ioctl = wpi_ioctl;
|
||||||
ifp->if_start = wpi_start;
|
ifp->if_start = wpi_start;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ieee80211_ifattach(ic, macaddr);
|
ieee80211_ifattach(ic, macaddr);
|
||||||
/* override default methods */
|
/* override default methods */
|
||||||
ic->ic_node_alloc = wpi_node_alloc;
|
|
||||||
ic->ic_newassoc = wpi_newassoc;
|
|
||||||
ic->ic_raw_xmit = wpi_raw_xmit;
|
ic->ic_raw_xmit = wpi_raw_xmit;
|
||||||
ic->ic_wme.wme_update = wpi_wme_update;
|
ic->ic_wme.wme_update = wpi_wme_update;
|
||||||
ic->ic_scan_start = wpi_scan_start;
|
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 wpi_softc *sc = device_get_softc(dev);
|
||||||
struct ifnet *ifp = sc->sc_ifp;
|
struct ifnet *ifp = sc->sc_ifp;
|
||||||
struct ieee80211com *ic = ifp->if_l2com;
|
struct ieee80211com *ic;
|
||||||
int ac;
|
int ac;
|
||||||
|
|
||||||
ieee80211_draintask(ic, &sc->sc_restarttask);
|
|
||||||
ieee80211_draintask(ic, &sc->sc_radiotask);
|
|
||||||
|
|
||||||
if (ifp != NULL) {
|
if (ifp != NULL) {
|
||||||
|
ic = ifp->if_l2com;
|
||||||
|
|
||||||
|
ieee80211_draintask(ic, &sc->sc_restarttask);
|
||||||
|
ieee80211_draintask(ic, &sc->sc_radiotask);
|
||||||
wpi_stop(sc);
|
wpi_stop(sc);
|
||||||
callout_drain(&sc->watchdog_to);
|
callout_drain(&sc->watchdog_to);
|
||||||
callout_drain(&sc->calib_to);
|
callout_drain(&sc->calib_to);
|
||||||
@@ -786,11 +783,7 @@ wpi_vap_create(struct ieee80211com *ic,
|
|||||||
wvp->newstate = vap->iv_newstate;
|
wvp->newstate = vap->iv_newstate;
|
||||||
vap->iv_newstate = wpi_newstate;
|
vap->iv_newstate = wpi_newstate;
|
||||||
|
|
||||||
ieee80211_amrr_init(&wvp->amrr, vap,
|
ieee80211_ratectl_init(vap);
|
||||||
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
|
|
||||||
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
|
|
||||||
500 /*ms*/);
|
|
||||||
|
|
||||||
/* complete setup */
|
/* complete setup */
|
||||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||||
ic->ic_opmode = opmode;
|
ic->ic_opmode = opmode;
|
||||||
@@ -802,7 +795,7 @@ wpi_vap_delete(struct ieee80211vap *vap)
|
|||||||
{
|
{
|
||||||
struct wpi_vap *wvp = WPI_VAP(vap);
|
struct wpi_vap *wvp = WPI_VAP(vap);
|
||||||
|
|
||||||
ieee80211_amrr_cleanup(&wvp->amrr);
|
ieee80211_ratectl_deinit(vap);
|
||||||
ieee80211_vap_detach(vap);
|
ieee80211_vap_detach(vap);
|
||||||
free(wvp, M_80211_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);
|
wpi_dma_contig_free(&ring->desc_dma);
|
||||||
|
|
||||||
for (i = 0; i < WPI_RX_RING_COUNT; i++)
|
for (i = 0; i < WPI_RX_RING_COUNT; i++) {
|
||||||
if (ring->data[i].m != NULL)
|
struct wpi_rx_data *data = &ring->data[i];
|
||||||
m_freem(ring->data[i].m);
|
|
||||||
|
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
|
static int
|
||||||
@@ -1240,18 +1242,6 @@ wpi_resume(device_t dev)
|
|||||||
return 0;
|
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
|
* 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);
|
IEEE80211_UNLOCK(ic);
|
||||||
WPI_LOCK(sc);
|
WPI_LOCK(sc);
|
||||||
if (nstate == IEEE80211_S_AUTH) {
|
if (nstate == IEEE80211_S_SCAN && vap->iv_state != IEEE80211_S_INIT) {
|
||||||
/* The node must be registered in the firmware before auth */
|
/*
|
||||||
|
* 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);
|
error = wpi_auth(sc, vap);
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
@@ -1466,6 +1473,7 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
|
||||||
head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len);
|
head = (struct wpi_rx_head *)((caddr_t)(stat + 1) + stat->len);
|
||||||
tail = (struct wpi_rx_tail *)((caddr_t)(head + 1) + le16toh(head->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++;
|
ifp->if_ierrors++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
bus_dmamap_unload(ring->data_dmat, data->map);
|
||||||
|
|
||||||
error = bus_dmamap_load(ring->data_dmat, data->map,
|
error = bus_dmamap_load(ring->data_dmat, data->map,
|
||||||
mtod(mnew, caddr_t), MJUMPAGESIZE,
|
mtod(mnew, caddr_t), MJUMPAGESIZE,
|
||||||
wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
|
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_ring *ring = &sc->txq[desc->qid & 0x3];
|
||||||
struct wpi_tx_data *txdata = &ring->data[desc->idx];
|
struct wpi_tx_data *txdata = &ring->data[desc->idx];
|
||||||
struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
|
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 "
|
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,
|
"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.
|
* the lowest available bit-rate.
|
||||||
* XXX frames w/o ACK shouldn't be used either
|
* XXX frames w/o ACK shouldn't be used either
|
||||||
*/
|
*/
|
||||||
wn->amn.amn_txcnt++;
|
|
||||||
if (stat->ntries > 0) {
|
if (stat->ntries > 0) {
|
||||||
DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries));
|
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 */
|
/* XXX oerrors should only count errors !maxtries */
|
||||||
if ((le32toh(stat->status) & 0xff) != 1)
|
if ((le32toh(stat->status) & 0xff) != 1)
|
||||||
@@ -1647,9 +1660,15 @@ wpi_notif_intr(struct wpi_softc *sc)
|
|||||||
struct wpi_rx_data *data;
|
struct wpi_rx_data *data;
|
||||||
uint32_t hw;
|
uint32_t hw;
|
||||||
|
|
||||||
|
bus_dmamap_sync(sc->shared_dma.tag, sc->shared_dma.map,
|
||||||
|
BUS_DMASYNC_POSTREAD);
|
||||||
|
|
||||||
hw = le32toh(sc->shared->next);
|
hw = le32toh(sc->shared->next);
|
||||||
while (sc->rxq.cur != hw) {
|
while (sc->rxq.cur != hw) {
|
||||||
data = &sc->rxq.data[sc->rxq.cur];
|
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;
|
desc = (void *)data->m->m_ext.ext_buf;
|
||||||
|
|
||||||
DPRINTFN(WPI_DEBUG_NOTIFY,
|
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) {
|
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
||||||
rate = tp->ucastrate;
|
rate = tp->ucastrate;
|
||||||
} else {
|
} else {
|
||||||
(void) ieee80211_amrr_choose(ni, &WPI_NODE(ni)->amn);
|
(void) ieee80211_ratectl_rate(ni, NULL, 0);
|
||||||
rate = ni->ni_txrate;
|
rate = ni->ni_txrate;
|
||||||
}
|
}
|
||||||
tx->rate = wpi_plcp_signal(rate);
|
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)) {
|
if (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) {
|
||||||
sc->config.flags |= htole32(WPI_CONFIG_AUTO |
|
sc->config.flags |= htole32(WPI_CONFIG_AUTO |
|
||||||
WPI_CONFIG_24GHZ);
|
WPI_CONFIG_24GHZ);
|
||||||
|
} else {
|
||||||
|
sc->config.flags &= ~htole32(WPI_CONFIG_AUTO |
|
||||||
|
WPI_CONFIG_24GHZ);
|
||||||
}
|
}
|
||||||
if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
|
if (IEEE80211_IS_CHAN_A(ni->ni_chan)) {
|
||||||
sc->config.cck_mask = 0;
|
sc->config.cck_mask = 0;
|
||||||
@@ -3011,14 +3033,12 @@ wpi_rfkill_resume(struct wpi_softc *sc)
|
|||||||
if (ntries == 1000) {
|
if (ntries == 1000) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"timeout waiting for thermal calibration\n");
|
"timeout waiting for thermal calibration\n");
|
||||||
WPI_UNLOCK(sc);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
|
DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
|
||||||
|
|
||||||
if (wpi_config(sc) != 0) {
|
if (wpi_config(sc) != 0) {
|
||||||
device_printf(sc->sc_dev, "device config failed\n");
|
device_printf(sc->sc_dev, "device config failed\n");
|
||||||
WPI_UNLOCK(sc);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3220,15 +3240,6 @@ wpi_stop(struct wpi_softc *sc)
|
|||||||
WPI_UNLOCK(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
|
static void
|
||||||
wpi_calib_timeout(void *arg)
|
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.
|
* are already taken care of by their respective firmware commands.
|
||||||
*/
|
*/
|
||||||
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
|
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
|
||||||
|
WPI_LOCK(sc);
|
||||||
error = wpi_config(sc);
|
error = wpi_config(sc);
|
||||||
|
WPI_UNLOCK(sc);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"error %d settting channel\n", error);
|
"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, pci, 1, 1, 1);
|
||||||
MODULE_DEPEND(wpi, wlan, 1, 1, 1);
|
MODULE_DEPEND(wpi, wlan, 1, 1, 1);
|
||||||
MODULE_DEPEND(wpi, firmware, 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;
|
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 {
|
struct wpi_power_sample {
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
int8_t power;
|
int8_t power;
|
||||||
@@ -127,7 +121,6 @@ struct wpi_power_group {
|
|||||||
|
|
||||||
struct wpi_vap {
|
struct wpi_vap {
|
||||||
struct ieee80211vap vap;
|
struct ieee80211vap vap;
|
||||||
struct ieee80211_amrr amrr;
|
|
||||||
|
|
||||||
int (*newstate)(struct ieee80211vap *,
|
int (*newstate)(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ NO_HAIKU_FBSD_MII_DRIVER();
|
|||||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||||
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);
|
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);
|
||||||
HAIKU_FIRMWARE_VERSION(2144);
|
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
|
int
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ KernelAddon iprowifi4965 :
|
|||||||
;
|
;
|
||||||
|
|
||||||
HAIKU_WIFI_FIRMWARE_PACKAGES on iprowifi4965 =
|
HAIKU_WIFI_FIRMWARE_PACKAGES on iprowifi4965 =
|
||||||
iwlwifi-1000-ucode-128.50.3.1 iwlwifi-4965-ucode-228.61.2.24
|
iwlwifi-1000-ucode-39.31.5.1 iwlwifi-4965-ucode-228.61.2.24
|
||||||
iwlwifi-5000-ucode-8.24.2.12 iwlwifi-5150-ucode-8.24.2.2
|
iwlwifi-5000-ucode-8.83.5.1 iwlwifi-5150-ucode-8.24.2.2
|
||||||
iwlwifi-6000-ucode-9.221.4.1 iwlwifi-6050-ucode-9.201.4.1 ;
|
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 =
|
HAIKU_WIFI_FIRMWARE_ARCHIVES on iprowifi4965 =
|
||||||
iwlwifi-1000-ucode-128.50.3.1.tgz iwlwifi-4965-ucode-228.61.2.24.tgz
|
iwlwifi-1000-ucode-39.31.5.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-5000-ucode-8.83.5.1.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-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 ;
|
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 void iwn_read_eeprom_enhinfo(struct iwn_softc *);
|
||||||
static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *,
|
static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *,
|
||||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
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_media_change(struct ifnet *);
|
||||||
static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
static int iwn_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
||||||
static void iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,
|
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 *,
|
static void iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *,
|
||||||
struct iwn_rx_data *);
|
struct iwn_rx_data *);
|
||||||
#endif
|
#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 *,
|
static void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *,
|
||||||
struct iwn_rx_data *);
|
struct iwn_rx_data *);
|
||||||
static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
|
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);
|
struct ieee80211_node *, uint8_t, uint16_t);
|
||||||
static void iwn5000_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t);
|
static void iwn5000_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t);
|
||||||
#endif
|
#endif
|
||||||
static int iwn5000_query_calibration(struct iwn_softc *);
|
static int iwn5000_send_calib_results(struct iwn_softc *);
|
||||||
static int iwn5000_send_calibration(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 iwn5000_send_wimax_coex(struct iwn_softc *);
|
||||||
static int iwn4965_post_alive(struct iwn_softc *);
|
static int iwn4965_post_alive(struct iwn_softc *);
|
||||||
static int iwn5000_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,
|
static int iwn5000_load_firmware_section(struct iwn_softc *, uint32_t,
|
||||||
const uint8_t *, int);
|
const uint8_t *, int);
|
||||||
static int iwn5000_load_firmware(struct iwn_softc *);
|
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_read_firmware(struct iwn_softc *);
|
||||||
static int iwn_clock_wait(struct iwn_softc *);
|
static int iwn_clock_wait(struct iwn_softc *);
|
||||||
static int iwn_apm_init(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, 0x423D, "Intel(R) PRO/Wireless 5150" },
|
||||||
{ 0x8086, 0x4235, "Intel(R) PRO/Wireless 5300" },
|
{ 0x8086, 0x4235, "Intel(R) PRO/Wireless 5300" },
|
||||||
{ 0x8086, 0x4236, "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, 0x423A, "Intel(R) PRO/Wireless 5350" },
|
||||||
{ 0x8086, 0x423B, "Intel(R) PRO/Wireless 5350" },
|
{ 0x8086, 0x423B, "Intel(R) PRO/Wireless 5350" },
|
||||||
{ 0x8086, 0x0083, "Intel(R) PRO/Wireless 1000" },
|
{ 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, 0x4239, "Intel(R) PRO/Wireless 6000" },
|
||||||
{ 0x8086, 0x422B, "Intel(R) PRO/Wireless 6000" },
|
{ 0x8086, 0x422B, "Intel(R) PRO/Wireless 6000" },
|
||||||
{ 0x8086, 0x422C, "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 6250" },
|
||||||
{ 0x8086, 0x0087, "Intel(R) PRO/Wireless 6050" },
|
{ 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 }
|
{ 0, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -627,8 +642,8 @@ iwn_attach(device_t dev)
|
|||||||
ifp->if_init = iwn_init;
|
ifp->if_init = iwn_init;
|
||||||
ifp->if_ioctl = iwn_ioctl;
|
ifp->if_ioctl = iwn_ioctl;
|
||||||
ifp->if_start = iwn_start;
|
ifp->if_start = iwn_start;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ieee80211_ifattach(ic, macaddr);
|
ieee80211_ifattach(ic, macaddr);
|
||||||
@@ -636,7 +651,6 @@ iwn_attach(device_t dev)
|
|||||||
ic->ic_vap_delete = iwn_vap_delete;
|
ic->ic_vap_delete = iwn_vap_delete;
|
||||||
ic->ic_raw_xmit = iwn_raw_xmit;
|
ic->ic_raw_xmit = iwn_raw_xmit;
|
||||||
ic->ic_node_alloc = iwn_node_alloc;
|
ic->ic_node_alloc = iwn_node_alloc;
|
||||||
ic->ic_newassoc = iwn_newassoc;
|
|
||||||
ic->ic_wme.wme_update = iwn_wme_update;
|
ic->ic_wme.wme_update = iwn_wme_update;
|
||||||
ic->ic_update_mcast = iwn_update_mcast;
|
ic->ic_update_mcast = iwn_update_mcast;
|
||||||
ic->ic_scan_start = iwn_scan_start;
|
ic->ic_scan_start = iwn_scan_start;
|
||||||
@@ -692,6 +706,9 @@ iwn_hal_attach(struct iwn_softc *sc)
|
|||||||
sc->fwname = "iwn5000fw";
|
sc->fwname = "iwn5000fw";
|
||||||
sc->txchainmask = IWN_ANT_B;
|
sc->txchainmask = IWN_ANT_B;
|
||||||
sc->rxchainmask = IWN_ANT_AB;
|
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;
|
break;
|
||||||
case IWN_HW_REV_TYPE_5150:
|
case IWN_HW_REV_TYPE_5150:
|
||||||
sc->sc_hal = &iwn5000_hal;
|
sc->sc_hal = &iwn5000_hal;
|
||||||
@@ -699,6 +716,8 @@ iwn_hal_attach(struct iwn_softc *sc)
|
|||||||
sc->fwname = "iwn5150fw";
|
sc->fwname = "iwn5150fw";
|
||||||
sc->txchainmask = IWN_ANT_A;
|
sc->txchainmask = IWN_ANT_A;
|
||||||
sc->rxchainmask = IWN_ANT_AB;
|
sc->rxchainmask = IWN_ANT_AB;
|
||||||
|
sc->calib_init = IWN_CALIB_DC | IWN_CALIB_LO |
|
||||||
|
IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND;
|
||||||
break;
|
break;
|
||||||
case IWN_HW_REV_TYPE_5300:
|
case IWN_HW_REV_TYPE_5300:
|
||||||
case IWN_HW_REV_TYPE_5350:
|
case IWN_HW_REV_TYPE_5350:
|
||||||
@@ -707,6 +726,9 @@ iwn_hal_attach(struct iwn_softc *sc)
|
|||||||
sc->fwname = "iwn5000fw";
|
sc->fwname = "iwn5000fw";
|
||||||
sc->txchainmask = IWN_ANT_ABC;
|
sc->txchainmask = IWN_ANT_ABC;
|
||||||
sc->rxchainmask = 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;
|
break;
|
||||||
case IWN_HW_REV_TYPE_1000:
|
case IWN_HW_REV_TYPE_1000:
|
||||||
sc->sc_hal = &iwn5000_hal;
|
sc->sc_hal = &iwn5000_hal;
|
||||||
@@ -714,6 +736,9 @@ iwn_hal_attach(struct iwn_softc *sc)
|
|||||||
sc->fwname = "iwn1000fw";
|
sc->fwname = "iwn1000fw";
|
||||||
sc->txchainmask = IWN_ANT_A;
|
sc->txchainmask = IWN_ANT_A;
|
||||||
sc->rxchainmask = IWN_ANT_AB;
|
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;
|
break;
|
||||||
case IWN_HW_REV_TYPE_6000:
|
case IWN_HW_REV_TYPE_6000:
|
||||||
sc->sc_hal = &iwn5000_hal;
|
sc->sc_hal = &iwn5000_hal;
|
||||||
@@ -729,15 +754,31 @@ iwn_hal_attach(struct iwn_softc *sc)
|
|||||||
default:
|
default:
|
||||||
sc->txchainmask = IWN_ANT_ABC;
|
sc->txchainmask = IWN_ANT_ABC;
|
||||||
sc->rxchainmask = IWN_ANT_ABC;
|
sc->rxchainmask = IWN_ANT_ABC;
|
||||||
|
sc->calib_runtime = IWN_CALIB_DC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
sc->calib_init = IWN_CALIB_XTAL | IWN_CALIB_LO |
|
||||||
|
IWN_CALIB_TX_IQ | IWN_CALIB_BASE_BAND;
|
||||||
break;
|
break;
|
||||||
case IWN_HW_REV_TYPE_6050:
|
case IWN_HW_REV_TYPE_6050:
|
||||||
sc->sc_hal = &iwn5000_hal;
|
sc->sc_hal = &iwn5000_hal;
|
||||||
sc->limits = &iwn6000_sensitivity_limits;
|
sc->limits = &iwn6000_sensitivity_limits;
|
||||||
sc->fwname = "iwn6000fw";
|
sc->fwname = "iwn6050fw";
|
||||||
sc->txchainmask = IWN_ANT_AB;
|
sc->txchainmask = IWN_ANT_AB;
|
||||||
sc->rxchainmask = 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;
|
break;
|
||||||
default:
|
default:
|
||||||
device_printf(sc->sc_dev, "adapter type %d not supported\n",
|
device_printf(sc->sc_dev, "adapter type %d not supported\n",
|
||||||
@@ -826,6 +867,8 @@ iwn_cleanup(device_t dev)
|
|||||||
ieee80211_ifdetach(ic);
|
ieee80211_ifdetach(ic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iwn5000_free_calib_results(sc);
|
||||||
|
|
||||||
/* Free DMA resources. */
|
/* Free DMA resources. */
|
||||||
iwn_free_rx_ring(sc, &sc->rxq);
|
iwn_free_rx_ring(sc, &sc->rxq);
|
||||||
if (sc->sc_hal != NULL)
|
if (sc->sc_hal != NULL)
|
||||||
@@ -1670,7 +1713,7 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
|
|||||||
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
|
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
|
||||||
"%s: calib version=%u pa type=%u voltage=%u\n",
|
"%s: calib version=%u pa type=%u voltage=%u\n",
|
||||||
__func__, hdr.version, hdr.pa_type, le16toh(hdr.volt));
|
__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) {
|
if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
|
||||||
/* Compute temperature offset. */
|
/* Compute temperature offset. */
|
||||||
@@ -1681,12 +1724,6 @@ iwn5000_read_eeprom(struct iwn_softc *sc)
|
|||||||
sc->temp_off = temp - (volt / -5);
|
sc->temp_off = temp - (volt / -5);
|
||||||
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "temp=%d volt=%d offset=%dK\n",
|
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "temp=%d volt=%d offset=%dK\n",
|
||||||
temp, volt, sc->temp_off);
|
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);
|
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
|
static int
|
||||||
iwn_media_change(struct ifnet *ifp)
|
iwn_media_change(struct ifnet *ifp)
|
||||||
{
|
{
|
||||||
@@ -1927,27 +1955,45 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
IWN_LOCK(sc);
|
IWN_LOCK(sc);
|
||||||
callout_stop(&sc->sc_timer_to);
|
callout_stop(&sc->sc_timer_to);
|
||||||
|
|
||||||
if (nstate == IEEE80211_S_AUTH && vap->iv_state != IEEE80211_S_AUTH) {
|
switch (nstate) {
|
||||||
/* !AUTH -> AUTH requires adapter config */
|
case IEEE80211_S_ASSOC:
|
||||||
/* Reset state to handle reassociations correctly. */
|
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.associd = 0;
|
||||||
sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
|
sc->rxon.filter &= ~htole32(IWN_FILTER_BSS);
|
||||||
iwn_calib_reset(sc);
|
iwn_calib_reset(sc);
|
||||||
error = iwn_auth(sc, vap);
|
error = iwn_auth(sc, vap);
|
||||||
}
|
break;
|
||||||
if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
|
|
||||||
|
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
|
* !RUN -> RUN requires setting the association id
|
||||||
* which is done with a firmware cmd. We also defer
|
* which is done with a firmware cmd. We also defer
|
||||||
* starting the timers until that work is done.
|
* starting the timers until that work is done.
|
||||||
*/
|
*/
|
||||||
error = iwn_run(sc, vap);
|
error = iwn_run(sc, vap);
|
||||||
}
|
break;
|
||||||
if (nstate == IEEE80211_S_RUN) {
|
|
||||||
/*
|
default:
|
||||||
* RUN -> RUN transition; just restart the timers.
|
break;
|
||||||
*/
|
|
||||||
iwn_calib_reset(sc);
|
|
||||||
}
|
}
|
||||||
IWN_UNLOCK(sc);
|
IWN_UNLOCK(sc);
|
||||||
IEEE80211_LOCK(ic);
|
IEEE80211_LOCK(ic);
|
||||||
@@ -2164,64 +2210,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
|||||||
}
|
}
|
||||||
#endif
|
#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.
|
* Process an RX_STATISTICS or BEACON_STATISTICS firmware notification.
|
||||||
* The latter is sent by the firmware after each received beacon.
|
* The latter is sent by the firmware after each received beacon.
|
||||||
@@ -2579,7 +2567,7 @@ iwn_notif_intr(struct iwn_softc *sc)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IWN5000_CALIBRATION_RESULT:
|
case IWN5000_CALIBRATION_RESULT:
|
||||||
iwn5000_rx_calib_results(sc, desc, data);
|
iwn5000_rx_calib_result(sc, desc, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IWN5000_CALIBRATION_DONE:
|
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);
|
txant = IWN_LSB(sc->txchainmask);
|
||||||
tx->rflags |= IWN_RFLAG_ANT(txant);
|
tx->rflags |= IWN_RFLAG_ANT(txant);
|
||||||
} else {
|
} else {
|
||||||
tx->linkq = 0;
|
tx->linkq = IWN_RIDX_OFDM54 - ridx;
|
||||||
flags |= IWN_TX_LINKQ; /* enable MRR */
|
flags |= IWN_TX_LINKQ; /* enable MRR */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4134,10 +4122,14 @@ iwn_collect_noise(struct iwn_softc *sc,
|
|||||||
val = MAX(calib->rssi[2], val);
|
val = MAX(calib->rssi[2], val);
|
||||||
|
|
||||||
/* Determine which antennas are connected. */
|
/* Determine which antennas are connected. */
|
||||||
sc->chainmask = 0;
|
sc->chainmask = sc->rxchainmask;
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
if (val - calib->rssi[i] <= 15 * 20)
|
if (val - calib->rssi[i] > 15 * 20)
|
||||||
sc->chainmask |= 1 << i;
|
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 none of the TX antennas are connected, keep at least one. */
|
||||||
if ((sc->chainmask & sc->txchainmask) == 0)
|
if ((sc->chainmask & sc->txchainmask) == 0)
|
||||||
sc->chainmask |= IWN_LSB(sc->txchainmask);
|
sc->chainmask |= IWN_LSB(sc->txchainmask);
|
||||||
@@ -4864,11 +4856,9 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
|
|||||||
struct iwn_node_info node;
|
struct iwn_node_info node;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
sc->calib.state = IWN_CALIB_STATE_INIT;
|
|
||||||
|
|
||||||
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
|
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
|
||||||
/* Link LED blinks while monitoring. */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
error = iwn_set_timing(sc, ni);
|
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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Query calibration tables from the initialization firmware. We do this
|
* Send calibration results to the runtime firmware. These results were
|
||||||
* only once at first boot. Called from a process context.
|
* obtained on first boot from the initialization firmware, or by reading
|
||||||
|
* the EEPROM for crystal calibration.
|
||||||
*/
|
*/
|
||||||
static int
|
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;
|
struct iwn5000_calib_config cmd;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof cmd);
|
memset(&cmd, 0, sizeof cmd);
|
||||||
cmd.ucode.once.enable = 0xffffffff;
|
cmd.ucode.once.enable = CALIB_INIT_CFG;
|
||||||
cmd.ucode.once.start = 0xffffffff;
|
if (cfg == 0) {
|
||||||
cmd.ucode.once.send = 0xffffffff;
|
cmd.ucode.once.start = CALIB_INIT_CFG;
|
||||||
cmd.ucode.flags = 0xffffffff;
|
cmd.ucode.once.send = CALIB_INIT_CFG;
|
||||||
DPRINTF(sc, IWN_DEBUG_CALIBRATE, "%s: sending calibration query\n",
|
cmd.ucode.flags = CALIB_INIT_CFG;
|
||||||
__func__);
|
} 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);
|
error = iwn_cmd(sc, IWN5000_CMD_CALIB_CONFIG, &cmd, sizeof cmd, 0);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return error;
|
return error;
|
||||||
@@ -5236,34 +5347,56 @@ iwn5000_query_calibration(struct iwn_softc *sc)
|
|||||||
/* Wait at most two seconds for calibration to complete. */
|
/* Wait at most two seconds for calibration to complete. */
|
||||||
if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE))
|
if (!(sc->sc_flags & IWN_FLAG_CALIB_DONE))
|
||||||
error = msleep(sc, &sc->sc_mtx, PCATCH, "iwninit", 2 * hz);
|
error = msleep(sc, &sc->sc_mtx, PCATCH, "iwninit", 2 * hz);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
#undef CALIB_INIT_CFG
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send calibration results to the runtime firmware. These results were
|
* Process a CALIBRATION_RESULT notification sent by the initialization
|
||||||
* obtained on first boot from the initialization firmware.
|
* firmware on response to a CMD_CALIB_CONFIG command.
|
||||||
*/
|
*/
|
||||||
static int
|
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++) {
|
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
|
||||||
if (sc->calibcmd[idx].buf == NULL)
|
len = (le32toh(desc->len) & FRAME_SIZE_MASK);
|
||||||
continue; /* No results available. */
|
|
||||||
|
/* 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,
|
DPRINTF(sc, IWN_DEBUG_CALIBRATE,
|
||||||
"send calibration result idx=%d len=%d\n",
|
"%s: unknown calibration code=%d\n", __func__, calib->code);
|
||||||
idx, sc->calibcmd[idx].len);
|
return EINVAL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return iwn5000_save_calib_result(sc, calib, len, idx);
|
||||||
|
#undef FRAME_SIZE_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -5411,36 +5544,40 @@ iwn5000_post_alive(struct iwn_softc *sc)
|
|||||||
__func__, error);
|
__func__, error);
|
||||||
return 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)) {
|
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) {
|
if (error != 0) {
|
||||||
device_printf(sc->sc_dev,
|
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);
|
__func__, error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have the calibration results now, reboot with the
|
* We have the calibration results now, reboot with the
|
||||||
* runtime firmware (call ourselves recursively!)
|
* runtime firmware (call ourselves recursively!)
|
||||||
@@ -5448,8 +5585,24 @@ iwn5000_post_alive(struct iwn_softc *sc)
|
|||||||
iwn_hw_stop(sc);
|
iwn_hw_stop(sc);
|
||||||
error = iwn_hw_init(sc);
|
error = iwn_hw_init(sc);
|
||||||
} else {
|
} 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;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -5642,17 +5795,159 @@ iwn5000_load_firmware(struct iwn_softc *sc)
|
|||||||
return 0;
|
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
|
static int
|
||||||
iwn_read_firmware(struct iwn_softc *sc)
|
iwn_read_firmware(struct iwn_softc *sc)
|
||||||
{
|
{
|
||||||
const struct iwn_hal *hal = sc->sc_hal;
|
const struct iwn_hal *hal = sc->sc_hal;
|
||||||
struct iwn_fw_info *fw = &sc->fw;
|
struct iwn_fw_info *fw = &sc->fw;
|
||||||
const uint32_t *ptr;
|
int error;
|
||||||
uint32_t rev;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
IWN_UNLOCK(sc);
|
IWN_UNLOCK(sc);
|
||||||
|
|
||||||
|
memset(fw, 0, sizeof (*fw));
|
||||||
|
|
||||||
/* Read firmware image from filesystem. */
|
/* Read firmware image from filesystem. */
|
||||||
sc->fw_fp = firmware_get(sc->fwname);
|
sc->fw_fp = firmware_get(sc->fwname);
|
||||||
if (sc->fw_fp == NULL) {
|
if (sc->fw_fp == NULL) {
|
||||||
@@ -5664,63 +5959,39 @@ iwn_read_firmware(struct iwn_softc *sc)
|
|||||||
}
|
}
|
||||||
IWN_LOCK(sc);
|
IWN_LOCK(sc);
|
||||||
|
|
||||||
size = sc->fw_fp->datasize;
|
fw->size = sc->fw_fp->datasize;
|
||||||
if (size < 28) {
|
fw->data = (const uint8_t *)sc->fw_fp->data;
|
||||||
|
if (fw->size < sizeof (uint32_t)) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: truncated firmware header: %zu bytes\n",
|
"%s: firmware file too short: %zu bytes\n",
|
||||||
__func__, size);
|
__func__, fw->size);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process firmware header. */
|
/* Retrieve text and data sections. */
|
||||||
ptr = (const uint32_t *)sc->fw_fp->data;
|
if (*(const uint32_t *)fw->data != 0) /* Legacy image. */
|
||||||
rev = le32toh(*ptr++);
|
error = iwn_read_firmware_leg(sc, fw);
|
||||||
/* Check firmware API version. */
|
else
|
||||||
if (IWN_FW_API(rev) <= 1) {
|
error = iwn_read_firmware_tlv(sc, fw, 1);
|
||||||
|
if (error != 0) {
|
||||||
device_printf(sc->sc_dev,
|
device_printf(sc->sc_dev,
|
||||||
"%s: bad firmware, need API version >=2\n", __func__);
|
"%s: could not read firmware sections\n", __func__);
|
||||||
return EINVAL;
|
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 ||
|
if (fw->main.textsz > hal->fw_text_maxsz ||
|
||||||
fw->main.datasz > hal->fw_data_maxsz ||
|
fw->main.datasz > hal->fw_data_maxsz ||
|
||||||
fw->init.textsz > hal->fw_text_maxsz ||
|
fw->init.textsz > hal->fw_text_maxsz ||
|
||||||
fw->init.datasz > hal->fw_data_maxsz ||
|
fw->init.datasz > hal->fw_data_maxsz ||
|
||||||
fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ ||
|
fw->boot.textsz > IWN_FW_BOOT_TEXT_MAXSZ ||
|
||||||
(fw->boot.textsz & 3) != 0) {
|
(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,
|
device_printf(sc->sc_dev,
|
||||||
"%s: firmware file too short: %zu bytes\n",
|
"%s: firmware sections too large\n", __func__);
|
||||||
__func__, size);
|
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get pointers to firmware sections. */
|
/* We can proceed with loading the firmware. */
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5769,8 +6040,7 @@ iwn_apm_init(struct iwn_softc *sc)
|
|||||||
IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
|
IWN_CLRBITS(sc, IWN_GIO, IWN_GIO_L0S_ENA);
|
||||||
|
|
||||||
if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
|
if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
|
||||||
sc->hw_type != IWN_HW_REV_TYPE_6000 &&
|
sc->hw_type <= IWN_HW_REV_TYPE_1000)
|
||||||
sc->hw_type != IWN_HW_REV_TYPE_6050)
|
|
||||||
IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT);
|
IWN_SETBITS(sc, IWN_ANA_PLL, IWN_ANA_PLL_INIT);
|
||||||
|
|
||||||
/* Wait for clock stabilization before accessing prph. */
|
/* Wait for clock stabilization before accessing prph. */
|
||||||
@@ -5885,9 +6155,9 @@ iwn5000_nic_config(struct iwn_softc *sc)
|
|||||||
/* Use internal power amplifier only. */
|
/* Use internal power amplifier only. */
|
||||||
IWN_WRITE(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_RADIO_2X2_IPA);
|
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) {
|
if (sc->hw_type == IWN_HW_REV_TYPE_6050 && sc->calib_ver >= 6) {
|
||||||
/* Indicate that ROM calibration version is >=6. */
|
/* Indicate that ROM calibration version is >=6. */
|
||||||
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);
|
IWN_SETBITS(sc, IWN_GP_DRIVER, IWN_GP_DRIVER_CALIB_VER6);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* $FreeBSD$ */
|
/* $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
|
* Copyright (c) 2007, 2008
|
||||||
@@ -204,6 +204,7 @@
|
|||||||
#define IWN_HW_REV_TYPE_1000 6
|
#define IWN_HW_REV_TYPE_1000 6
|
||||||
#define IWN_HW_REV_TYPE_6000 7
|
#define IWN_HW_REV_TYPE_6000 7
|
||||||
#define IWN_HW_REV_TYPE_6050 8
|
#define IWN_HW_REV_TYPE_6050 8
|
||||||
|
#define IWN_HW_REV_TYPE_6005 11
|
||||||
|
|
||||||
/* Possible flags for register IWN_GIO_CHICKEN. */
|
/* Possible flags for register IWN_GIO_CHICKEN. */
|
||||||
#define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23)
|
#define IWN_GIO_CHICKEN_L1A_NO_L0S_RX (1 << 23)
|
||||||
@@ -1259,6 +1260,34 @@ struct iwn_fw_dump {
|
|||||||
uint32_t time[2];
|
uint32_t time[2];
|
||||||
} __packed;
|
} __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_TEXT_MAXSZ ( 96 * 1024)
|
||||||
#define IWN4965_FW_DATA_MAXSZ ( 40 * 1024)
|
#define IWN4965_FW_DATA_MAXSZ ( 40 * 1024)
|
||||||
#define IWN5000_FW_TEXT_MAXSZ (256 * 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 IWN4965_FWSZ (IWN4965_FW_TEXT_MAXSZ + IWN4965_FW_DATA_MAXSZ)
|
||||||
#define IWN5000_FWSZ IWN5000_FW_TEXT_MAXSZ
|
#define IWN5000_FWSZ IWN5000_FW_TEXT_MAXSZ
|
||||||
|
|
||||||
#define IWN_FW_API(x) (((x) >> 8) & 0xff)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offsets into EEPROM.
|
* Offsets into EEPROM.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* $FreeBSD$ */
|
/* $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
|
* Copyright (c) 2007, 2008
|
||||||
@@ -150,7 +150,8 @@ struct iwn_fw_part {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct iwn_fw_info {
|
struct iwn_fw_info {
|
||||||
u_char *data;
|
const uint8_t *data;
|
||||||
|
size_t size;
|
||||||
struct iwn_fw_part init;
|
struct iwn_fw_part init;
|
||||||
struct iwn_fw_part main;
|
struct iwn_fw_part main;
|
||||||
struct iwn_fw_part boot;
|
struct iwn_fw_part boot;
|
||||||
@@ -262,9 +263,24 @@ struct iwn_softc {
|
|||||||
|
|
||||||
int calib_cnt;
|
int calib_cnt;
|
||||||
struct iwn_calib_state calib;
|
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_fw_info fw;
|
||||||
struct iwn_calib_info calibcmd[5];
|
|
||||||
uint32_t errptr;
|
uint32_t errptr;
|
||||||
|
|
||||||
struct iwn_rx_stat last_rx_stat;
|
struct iwn_rx_stat last_rx_stat;
|
||||||
@@ -283,7 +299,6 @@ struct iwn_softc {
|
|||||||
uint16_t rfcfg;
|
uint16_t rfcfg;
|
||||||
uint8_t calib_ver;
|
uint8_t calib_ver;
|
||||||
char eeprom_domain[4];
|
char eeprom_domain[4];
|
||||||
uint32_t eeprom_crystal;
|
|
||||||
int16_t eeprom_voltage;
|
int16_t eeprom_voltage;
|
||||||
int8_t maxpwr2GHz;
|
int8_t maxpwr2GHz;
|
||||||
int8_t maxpwr5GHz;
|
int8_t maxpwr5GHz;
|
||||||
@@ -312,7 +327,7 @@ struct iwn_softc {
|
|||||||
|
|
||||||
#define IWN_LOCK_INIT(_sc) \
|
#define IWN_LOCK_INIT(_sc) \
|
||||||
mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
|
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(_sc) mtx_lock(&(_sc)->sc_mtx)
|
||||||
#define IWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
|
#define IWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
|
||||||
#define IWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
#define IWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ NO_HAIKU_FBSD_MII_DRIVER();
|
|||||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||||
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);
|
HAIKU_DRIVER_REQUIREMENTS(FBSD_TASKQUEUES | FBSD_WLAN);
|
||||||
HAIKU_FIRMWARE_VERSION(44417);
|
HAIKU_FIRMWARE_VERSION(44417);
|
||||||
HAIKU_FIRMWARE_NAME_MAP(5) = {
|
HAIKU_FIRMWARE_NAME_MAP(7) = {
|
||||||
{"iwn1000fw", "iwlwifi-1000-3.ucode"},
|
{"iwn1000fw", "iwlwifi-1000-5.ucode"},
|
||||||
{"iwn4965fw", "iwlwifi-4965-2.ucode"},
|
{"iwn4965fw", "iwlwifi-4965-2.ucode"},
|
||||||
{"iwn5000fw", "iwlwifi-5000-2.ucode"},
|
{"iwn5000fw", "iwlwifi-5000-5.ucode"},
|
||||||
{"iwn5150fw", "iwlwifi-5150-2.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_watchdog = malo_watchdog;
|
||||||
ifp->if_ioctl = malo_ioctl;
|
ifp->if_ioctl = malo_ioctl;
|
||||||
ifp->if_init = malo_init;
|
ifp->if_init = malo_init;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
@@ -2099,7 +2099,7 @@ malo_rx_proc(void *arg, int npending)
|
|||||||
* payload prior to constructing the header.
|
* payload prior to constructing the header.
|
||||||
*/
|
*/
|
||||||
m = bf->bf_m;
|
m = bf->bf_m;
|
||||||
data = mtod(m, uint8_t *);;
|
data = mtod(m, uint8_t *);
|
||||||
hdrlen = ieee80211_anyhdrsize(data + sizeof(uint16_t));
|
hdrlen = ieee80211_anyhdrsize(data + sizeof(uint16_t));
|
||||||
off = sizeof(uint16_t) + sizeof(struct ieee80211_frame_addr4);
|
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);
|
DRIVER_MODULE(malo, pci, malo_pci_driver, malo_devclass, 0, 0);
|
||||||
MODULE_VERSION(malo, 1);
|
MODULE_VERSION(malo, 1);
|
||||||
MODULE_DEPEND(malo, wlan, 1, 1, 1); /* 802.11 media layer */
|
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_watchdog = mwl_watchdog;
|
||||||
ifp->if_ioctl = mwl_ioctl;
|
ifp->if_ioctl = mwl_ioctl;
|
||||||
ifp->if_init = mwl_init;
|
ifp->if_init = mwl_init;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ mwl_pci_attach(device_t dev)
|
|||||||
BUS_SPACE_MAXADDR, /* maxsize */
|
BUS_SPACE_MAXADDR, /* maxsize */
|
||||||
MWL_TXDESC, /* nsegments */
|
MWL_TXDESC, /* nsegments */
|
||||||
BUS_SPACE_MAXADDR, /* maxsegsize */
|
BUS_SPACE_MAXADDR, /* maxsegsize */
|
||||||
BUS_DMA_ALLOCNOW, /* flags */
|
0, /* flags */
|
||||||
NULL, /* lockfunc */
|
NULL, /* lockfunc */
|
||||||
NULL, /* lockarg */
|
NULL, /* lockarg */
|
||||||
&sc->sc_dmat)) {
|
&sc->sc_dmat)) {
|
||||||
@@ -313,4 +313,4 @@ static devclass_t mwl_devclass;
|
|||||||
DRIVER_MODULE(mwl, pci, mwl_pci_driver, mwl_devclass, 0, 0);
|
DRIVER_MODULE(mwl, pci, mwl_pci_driver, mwl_devclass, 0, 0);
|
||||||
MODULE_VERSION(mwl, 1);
|
MODULE_VERSION(mwl, 1);
|
||||||
MODULE_DEPEND(mwl, wlan, 1, 1, 1); /* 802.11 media layer */
|
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_var.h>
|
||||||
#include <net80211/ieee80211_radiotap.h>
|
#include <net80211/ieee80211_radiotap.h>
|
||||||
#include <net80211/ieee80211_regdomain.h>
|
#include <net80211/ieee80211_regdomain.h>
|
||||||
#include <net80211/ieee80211_amrr.h>
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
@@ -103,9 +103,6 @@ static void rt2560_reset_rx_ring(struct rt2560_softc *,
|
|||||||
struct rt2560_rx_ring *);
|
struct rt2560_rx_ring *);
|
||||||
static void rt2560_free_rx_ring(struct rt2560_softc *,
|
static void rt2560_free_rx_ring(struct rt2560_softc *,
|
||||||
struct rt2560_rx_ring *);
|
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 *,
|
static int rt2560_newstate(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
static uint16_t rt2560_eeprom_read(struct rt2560_softc *, uint8_t);
|
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_init = rt2560_init;
|
||||||
ifp->if_ioctl = rt2560_ioctl;
|
ifp->if_ioctl = rt2560_ioctl;
|
||||||
ifp->if_start = rt2560_start;
|
ifp->if_start = rt2560_start;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
@@ -303,11 +300,9 @@ rt2560_attach(device_t dev, int id)
|
|||||||
ieee80211_init_channels(ic, NULL, &bands);
|
ieee80211_init_channels(ic, NULL, &bands);
|
||||||
|
|
||||||
ieee80211_ifattach(ic, macaddr);
|
ieee80211_ifattach(ic, macaddr);
|
||||||
ic->ic_newassoc = rt2560_newassoc;
|
|
||||||
ic->ic_raw_xmit = rt2560_raw_xmit;
|
ic->ic_raw_xmit = rt2560_raw_xmit;
|
||||||
ic->ic_updateslot = rt2560_update_slot;
|
ic->ic_updateslot = rt2560_update_slot;
|
||||||
ic->ic_update_promisc = rt2560_update_promisc;
|
ic->ic_update_promisc = rt2560_update_promisc;
|
||||||
ic->ic_node_alloc = rt2560_node_alloc;
|
|
||||||
ic->ic_scan_start = rt2560_scan_start;
|
ic->ic_scan_start = rt2560_scan_start;
|
||||||
ic->ic_scan_end = rt2560_scan_end;
|
ic->ic_scan_end = rt2560_scan_end;
|
||||||
ic->ic_set_channel = rt2560_set_channel;
|
ic->ic_set_channel = rt2560_set_channel;
|
||||||
@@ -430,11 +425,7 @@ rt2560_vap_create(struct ieee80211com *ic,
|
|||||||
vap->iv_newstate = rt2560_newstate;
|
vap->iv_newstate = rt2560_newstate;
|
||||||
vap->iv_update_beacon = rt2560_beacon_update;
|
vap->iv_update_beacon = rt2560_beacon_update;
|
||||||
|
|
||||||
ieee80211_amrr_init(&rvp->amrr, vap,
|
ieee80211_ratectl_init(vap);
|
||||||
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
|
|
||||||
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
|
|
||||||
500 /* ms */);
|
|
||||||
|
|
||||||
/* complete setup */
|
/* complete setup */
|
||||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
||||||
@@ -447,7 +438,7 @@ rt2560_vap_delete(struct ieee80211vap *vap)
|
|||||||
{
|
{
|
||||||
struct rt2560_vap *rvp = RT2560_VAP(vap);
|
struct rt2560_vap *rvp = RT2560_VAP(vap);
|
||||||
|
|
||||||
ieee80211_amrr_cleanup(&rvp->amrr);
|
ieee80211_ratectl_deinit(vap);
|
||||||
ieee80211_vap_detach(vap);
|
ieee80211_vap_detach(vap);
|
||||||
free(rvp, M_80211_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);
|
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
|
static int
|
||||||
rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
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 ifnet *ifp = sc->sc_ifp;
|
||||||
struct rt2560_tx_desc *desc;
|
struct rt2560_tx_desc *desc;
|
||||||
struct rt2560_tx_data *data;
|
struct rt2560_tx_data *data;
|
||||||
struct rt2560_node *rn;
|
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
int retrycnt;
|
int retrycnt;
|
||||||
|
struct ieee80211vap *vap;
|
||||||
|
struct ieee80211_node *ni;
|
||||||
|
|
||||||
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
|
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
|
||||||
BUS_DMASYNC_POSTREAD);
|
BUS_DMASYNC_POSTREAD);
|
||||||
@@ -973,15 +944,19 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
|||||||
!(flags & RT2560_TX_VALID))
|
!(flags & RT2560_TX_VALID))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rn = (struct rt2560_node *)data->ni;
|
|
||||||
m = data->m;
|
m = data->m;
|
||||||
|
ni = data->ni;
|
||||||
|
vap = ni->ni_vap;
|
||||||
|
|
||||||
switch (flags & RT2560_TX_RESULT_MASK) {
|
switch (flags & RT2560_TX_RESULT_MASK) {
|
||||||
case RT2560_TX_SUCCESS:
|
case RT2560_TX_SUCCESS:
|
||||||
|
retrycnt = 0;
|
||||||
|
|
||||||
DPRINTFN(sc, 10, "%s\n", "data frame sent successfully");
|
DPRINTFN(sc, 10, "%s\n", "data frame sent successfully");
|
||||||
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
||||||
ieee80211_amrr_tx_complete(&rn->amrr,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
IEEE80211_AMRR_SUCCESS, 0);
|
IEEE80211_RATECTL_TX_SUCCESS,
|
||||||
|
&retrycnt, NULL);
|
||||||
ifp->if_opackets++;
|
ifp->if_opackets++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -991,8 +966,9 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
|||||||
DPRINTFN(sc, 9, "data frame sent after %u retries\n",
|
DPRINTFN(sc, 9, "data frame sent after %u retries\n",
|
||||||
retrycnt);
|
retrycnt);
|
||||||
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
||||||
ieee80211_amrr_tx_complete(&rn->amrr,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
IEEE80211_AMRR_SUCCESS, retrycnt);
|
IEEE80211_RATECTL_TX_SUCCESS,
|
||||||
|
&retrycnt, NULL);
|
||||||
ifp->if_opackets++;
|
ifp->if_opackets++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1002,8 +978,9 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
|||||||
DPRINTFN(sc, 9, "data frame failed after %d retries\n",
|
DPRINTFN(sc, 9, "data frame failed after %d retries\n",
|
||||||
retrycnt);
|
retrycnt);
|
||||||
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
||||||
ieee80211_amrr_tx_complete(&rn->amrr,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
IEEE80211_AMRR_FAILURE, retrycnt);
|
IEEE80211_RATECTL_TX_FAILURE,
|
||||||
|
&retrycnt, NULL);
|
||||||
ifp->if_oerrors++;
|
ifp->if_oerrors++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1823,7 +1800,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
|
|||||||
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
||||||
rate = tp->ucastrate;
|
rate = tp->ucastrate;
|
||||||
} else {
|
} else {
|
||||||
(void) ieee80211_amrr_choose(ni, &RT2560_NODE(ni)->amrr);
|
(void) ieee80211_ratectl_rate(ni, NULL, 0);
|
||||||
rate = ni->ni_txrate;
|
rate = ni->ni_txrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2682,8 +2659,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
|
|||||||
RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY);
|
RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY);
|
||||||
|
|
||||||
if (rt2560_bbp_init(sc) != 0) {
|
if (rt2560_bbp_init(sc) != 0) {
|
||||||
rt2560_stop(sc);
|
rt2560_stop_locked(sc);
|
||||||
RAL_UNLOCK(sc);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,16 +95,9 @@ struct rt2560_rx_ring {
|
|||||||
int cur_decrypt;
|
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 rt2560_vap {
|
||||||
struct ieee80211vap ral_vap;
|
struct ieee80211vap ral_vap;
|
||||||
struct ieee80211_beacon_offsets ral_bo;
|
struct ieee80211_beacon_offsets ral_bo;
|
||||||
struct ieee80211_amrr amrr;
|
|
||||||
|
|
||||||
int (*ral_newstate)(struct ieee80211vap *,
|
int (*ral_newstate)(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <net80211/ieee80211_var.h>
|
#include <net80211/ieee80211_var.h>
|
||||||
#include <net80211/ieee80211_radiotap.h>
|
#include <net80211/ieee80211_radiotap.h>
|
||||||
#include <net80211/ieee80211_regdomain.h>
|
#include <net80211/ieee80211_regdomain.h>
|
||||||
#include <net80211/ieee80211_amrr.h>
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
@@ -100,9 +100,6 @@ static void rt2661_reset_rx_ring(struct rt2661_softc *,
|
|||||||
struct rt2661_rx_ring *);
|
struct rt2661_rx_ring *);
|
||||||
static void rt2661_free_rx_ring(struct rt2661_softc *,
|
static void rt2661_free_rx_ring(struct rt2661_softc *,
|
||||||
struct rt2661_rx_ring *);
|
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 *,
|
static int rt2661_newstate(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
static uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
|
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_init = rt2661_init;
|
||||||
ifp->if_ioctl = rt2661_ioctl;
|
ifp->if_ioctl = rt2661_ioctl;
|
||||||
ifp->if_start = rt2661_start;
|
ifp->if_start = rt2661_start;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
@@ -306,8 +303,6 @@ rt2661_attach(device_t dev, int id)
|
|||||||
ieee80211_init_channels(ic, NULL, &bands);
|
ieee80211_init_channels(ic, NULL, &bands);
|
||||||
|
|
||||||
ieee80211_ifattach(ic, macaddr);
|
ieee80211_ifattach(ic, macaddr);
|
||||||
ic->ic_newassoc = rt2661_newassoc;
|
|
||||||
ic->ic_node_alloc = rt2661_node_alloc;
|
|
||||||
#if 0
|
#if 0
|
||||||
ic->ic_wme.wme_update = rt2661_wme_update;
|
ic->ic_wme.wme_update = rt2661_wme_update;
|
||||||
#endif
|
#endif
|
||||||
@@ -428,11 +423,7 @@ rt2661_vap_create(struct ieee80211com *ic,
|
|||||||
vap->iv_update_beacon = rt2661_beacon_update;
|
vap->iv_update_beacon = rt2661_beacon_update;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ieee80211_amrr_init(&rvp->amrr, vap,
|
ieee80211_ratectl_init(vap);
|
||||||
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
|
|
||||||
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
|
|
||||||
500 /* ms */);
|
|
||||||
|
|
||||||
/* complete setup */
|
/* complete setup */
|
||||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
||||||
@@ -445,7 +436,7 @@ rt2661_vap_delete(struct ieee80211vap *vap)
|
|||||||
{
|
{
|
||||||
struct rt2661_vap *rvp = RT2661_VAP(vap);
|
struct rt2661_vap *rvp = RT2661_VAP(vap);
|
||||||
|
|
||||||
ieee80211_amrr_cleanup(&rvp->amrr);
|
ieee80211_ratectl_deinit(vap);
|
||||||
ieee80211_vap_detach(vap);
|
ieee80211_vap_detach(vap);
|
||||||
free(rvp, M_80211_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);
|
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
|
static int
|
||||||
rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
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 ifnet *ifp = sc->sc_ifp;
|
||||||
struct rt2661_tx_ring *txq;
|
struct rt2661_tx_ring *txq;
|
||||||
struct rt2661_tx_data *data;
|
struct rt2661_tx_data *data;
|
||||||
struct rt2661_node *rn;
|
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
int qid, retrycnt;
|
int qid, retrycnt;
|
||||||
|
struct ieee80211vap *vap;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct ieee80211_node *ni;
|
struct ieee80211_node *ni;
|
||||||
@@ -925,8 +895,8 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
|||||||
/* if no frame has been sent, ignore */
|
/* if no frame has been sent, ignore */
|
||||||
if (ni == NULL)
|
if (ni == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
else
|
||||||
rn = RT2661_NODE(ni);
|
vap = ni->ni_vap;
|
||||||
|
|
||||||
switch (RT2661_TX_RESULT(val)) {
|
switch (RT2661_TX_RESULT(val)) {
|
||||||
case RT2661_TX_SUCCESS:
|
case RT2661_TX_SUCCESS:
|
||||||
@@ -935,8 +905,9 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
|||||||
DPRINTFN(sc, 10, "data frame sent successfully after "
|
DPRINTFN(sc, 10, "data frame sent successfully after "
|
||||||
"%d retries\n", retrycnt);
|
"%d retries\n", retrycnt);
|
||||||
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
||||||
ieee80211_amrr_tx_complete(&rn->amrr,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
IEEE80211_AMRR_SUCCESS, retrycnt);
|
IEEE80211_RATECTL_TX_SUCCESS,
|
||||||
|
&retrycnt, NULL);
|
||||||
ifp->if_opackets++;
|
ifp->if_opackets++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -946,8 +917,9 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
|||||||
DPRINTFN(sc, 9, "%s\n",
|
DPRINTFN(sc, 9, "%s\n",
|
||||||
"sending data frame failed (too much retries)");
|
"sending data frame failed (too much retries)");
|
||||||
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
if (data->rix != IEEE80211_FIXED_RATE_NONE)
|
||||||
ieee80211_amrr_tx_complete(&rn->amrr,
|
ieee80211_ratectl_tx_complete(vap, ni,
|
||||||
IEEE80211_AMRR_FAILURE, retrycnt);
|
IEEE80211_RATECTL_TX_FAILURE,
|
||||||
|
&retrycnt, NULL);
|
||||||
ifp->if_oerrors++;
|
ifp->if_oerrors++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1513,7 +1485,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
|
|||||||
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
} else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
|
||||||
rate = tp->ucastrate;
|
rate = tp->ucastrate;
|
||||||
} else {
|
} else {
|
||||||
(void) ieee80211_amrr_choose(ni, &RT2661_NODE(ni)->amrr);
|
(void) ieee80211_ratectl_rate(ni, NULL, 0);
|
||||||
rate = ni->ni_txrate;
|
rate = ni->ni_txrate;
|
||||||
}
|
}
|
||||||
rate &= IEEE80211_RATE_VAL;
|
rate &= IEEE80211_RATE_VAL;
|
||||||
|
|||||||
@@ -88,15 +88,8 @@ struct rt2661_rx_ring {
|
|||||||
int next;
|
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 rt2661_vap {
|
||||||
struct ieee80211vap ral_vap;
|
struct ieee80211vap ral_vap;
|
||||||
struct ieee80211_amrr amrr;
|
|
||||||
|
|
||||||
int (*ral_newstate)(struct ieee80211vap *,
|
int (*ral_newstate)(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
|
|||||||
@@ -333,8 +333,8 @@ wi_attach(device_t dev)
|
|||||||
ifp->if_ioctl = wi_ioctl;
|
ifp->if_ioctl = wi_ioctl;
|
||||||
ifp->if_start = wi_start;
|
ifp->if_start = wi_start;
|
||||||
ifp->if_init = wi_init;
|
ifp->if_init = wi_init;
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
ic->ic_ifp = ifp;
|
ic->ic_ifp = ifp;
|
||||||
|
|||||||
@@ -634,6 +634,7 @@ void if_attach(struct ifnet *);
|
|||||||
int if_delmulti(struct ifnet *, struct sockaddr *);
|
int if_delmulti(struct ifnet *, struct sockaddr *);
|
||||||
void if_detach(struct ifnet *);
|
void if_detach(struct ifnet *);
|
||||||
void if_purgeaddrs(struct ifnet *);
|
void if_purgeaddrs(struct ifnet *);
|
||||||
|
void if_delallmulti(struct ifnet *);
|
||||||
void if_purgemaddrs(struct ifnet *);
|
void if_purgemaddrs(struct ifnet *);
|
||||||
void if_down(struct ifnet *);
|
void if_down(struct ifnet *);
|
||||||
void if_free(struct ifnet *);
|
void if_free(struct ifnet *);
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
#include <compat/net/ethernet.h>
|
#include <compat/net/ethernet.h>
|
||||||
|
|
||||||
|
|
||||||
|
int ifqmaxlen = IFQ_MAXLEN;
|
||||||
|
|
||||||
|
|
||||||
#define IFNET_HOLD (void *)(uintptr_t)(-1)
|
#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 *
|
static struct ifmultiaddr *
|
||||||
_if_addmulti(struct ifnet *ifp, struct sockaddr *address)
|
_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
|
static void
|
||||||
if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma)
|
if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma)
|
||||||
{
|
{
|
||||||
@@ -450,60 +565,41 @@ if_delete_multiaddr(struct ifnet *ifp, struct ifmultiaddr *ifma)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
if_delmulti(struct ifnet *ifp, struct sockaddr *address)
|
if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
|
||||||
{
|
{
|
||||||
struct ifmultiaddr *addr;
|
struct ifmultiaddr *ifma;
|
||||||
int deleted = 0;
|
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);
|
IF_ADDR_LOCK(ifp);
|
||||||
addr = if_findmulti(ifp, address);
|
lastref = 0;
|
||||||
if (addr != NULL) {
|
ifma = if_findmulti(ifp, sa);
|
||||||
addr->ifma_refcount--;
|
if (ifma != NULL)
|
||||||
if (addr->ifma_refcount == 0) {
|
lastref = if_delmulti_locked(ifp, ifma, 0);
|
||||||
if_delete_multiaddr(ifp, addr);
|
|
||||||
deleted = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IF_ADDR_UNLOCK(ifp);
|
IF_ADDR_UNLOCK(ifp);
|
||||||
|
|
||||||
if (deleted && ifp->if_ioctl != NULL)
|
if (ifma == NULL)
|
||||||
ifp->if_ioctl(ifp, SIOCDELMULTI, NULL);
|
return (ENOENT);
|
||||||
|
|
||||||
return 0;
|
if (lastref && ifp->if_ioctl != NULL) {
|
||||||
}
|
(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 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 (--ifma->ifma_refcount > 0)
|
return (0);
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (ifp != NULL)
|
|
||||||
TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
|
|
||||||
|
|
||||||
if_freemulti(ifma);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,10 @@ KernelStaticLibrary libfreebsd_wlan.a :
|
|||||||
ieee80211_power.c
|
ieee80211_power.c
|
||||||
ieee80211_proto.c
|
ieee80211_proto.c
|
||||||
ieee80211_radiotap.c
|
ieee80211_radiotap.c
|
||||||
|
ieee80211_ratectl.c
|
||||||
|
ieee80211_ratectl_none.c
|
||||||
ieee80211_regdomain.c
|
ieee80211_regdomain.c
|
||||||
|
ieee80211_rssadapt.c
|
||||||
ieee80211_scan_sta.c
|
ieee80211_scan_sta.c
|
||||||
ieee80211_scan.c
|
ieee80211_scan.c
|
||||||
ieee80211_sta.c
|
ieee80211_sta.c
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||||
#include <net80211/ieee80211_superg.h>
|
#include <net80211/ieee80211_superg.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#include <net/bpf.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_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
|
||||||
ifp->if_start = ieee80211_start;
|
ifp->if_start = ieee80211_start;
|
||||||
ifp->if_ioctl = ieee80211_ioctl;
|
ifp->if_ioctl = ieee80211_ioctl;
|
||||||
ifp->if_watchdog = NULL; /* NB: no watchdog routine */
|
|
||||||
ifp->if_init = ieee80211_init;
|
ifp->if_init = ieee80211_init;
|
||||||
/* NB: input+output filled in by ether_ifattach */
|
/* NB: input+output filled in by ether_ifattach */
|
||||||
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
|
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||||
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
|
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||||
IFQ_SET_READY(&ifp->if_snd);
|
IFQ_SET_READY(&ifp->if_snd);
|
||||||
|
|
||||||
vap->iv_ifp = ifp;
|
vap->iv_ifp = ifp;
|
||||||
@@ -443,6 +443,9 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
|||||||
/* auto-enable s/w beacon miss support */
|
/* auto-enable s/w beacon miss support */
|
||||||
if (flags & IEEE80211_CLONE_NOBEACONS)
|
if (flags & IEEE80211_CLONE_NOBEACONS)
|
||||||
vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS;
|
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
|
* Enable various functionality by default if we're
|
||||||
* capable; the driver can override us if it knows better.
|
* 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_scan_vattach(vap);
|
||||||
ieee80211_regdomain_vattach(vap);
|
ieee80211_regdomain_vattach(vap);
|
||||||
ieee80211_radiotap_vattach(vap);
|
ieee80211_radiotap_vattach(vap);
|
||||||
|
ieee80211_ratectl_set(vap, IEEE80211_RATECTL_NONE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ ieee80211_send_action_register(int cat, int act, ieee80211_send_action_func *f)
|
|||||||
meshlm_send_action[act] = f;
|
meshlm_send_action[act] = f;
|
||||||
return 0;
|
return 0;
|
||||||
case IEEE80211_ACTION_CAT_MESHPATH:
|
case IEEE80211_ACTION_CAT_MESHPATH:
|
||||||
if (act > N(hwmp_send_action))
|
if (act >= N(hwmp_send_action))
|
||||||
break;
|
break;
|
||||||
hwmp_send_action[act] = f;
|
hwmp_send_action[act] = f;
|
||||||
return 0;
|
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_frame *wh;
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
struct ether_header *eh;
|
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 dir, type, subtype, qos;
|
||||||
uint8_t *bssid;
|
uint8_t *bssid;
|
||||||
uint16_t rxseq;
|
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"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
ni->ni_inact = ni->ni_inact_reload;
|
ni->ni_inact = ni->ni_inact_reload;
|
||||||
|
|
||||||
need_tap = 1; /* mbuf need to be tapped. */
|
|
||||||
type = -1; /* undefined */
|
type = -1; /* undefined */
|
||||||
|
|
||||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
|
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 $ */
|
/* $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
|
* Copyright (c) 2006
|
||||||
* Damien Bergamini <damien.bergamini@free.fr>
|
* Damien Bergamini <damien.bergamini@free.fr>
|
||||||
*
|
*
|
||||||
@@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <net80211/ieee80211_var.h>
|
#include <net80211/ieee80211_var.h>
|
||||||
#include <net80211/ieee80211_amrr.h>
|
#include <net80211/ieee80211_amrr.h>
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#define is_success(amn) \
|
#define is_success(amn) \
|
||||||
((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
|
((amn)->amn_retrycnt < (amn)->amn_txcnt / 10)
|
||||||
@@ -54,15 +56,45 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define is_enough(amn) \
|
#define is_enough(amn) \
|
||||||
((amn)->amn_txcnt > 10)
|
((amn)->amn_txcnt > 10)
|
||||||
|
|
||||||
static void amrr_sysctlattach(struct ieee80211_amrr *amrr,
|
static void amrr_setinterval(const struct ieee80211vap *, int);
|
||||||
struct sysctl_ctx_list *ctx, struct sysctl_oid *tree);
|
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 */
|
/* number of references from net80211 layer */
|
||||||
static int nrefs = 0;
|
static int nrefs = 0;
|
||||||
|
|
||||||
void
|
static const struct ieee80211_ratectl amrr = {
|
||||||
ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs)
|
.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;
|
int t;
|
||||||
|
|
||||||
if (msecs < 100)
|
if (msecs < 100)
|
||||||
@@ -71,29 +103,49 @@ ieee80211_amrr_setinterval(struct ieee80211_amrr *amrr, int msecs)
|
|||||||
amrr->amrr_interval = (t < 1) ? 1 : t;
|
amrr->amrr_interval = (t < 1) ? 1 : t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ieee80211_amrr_init(struct ieee80211_amrr *amrr,
|
amrr_init(struct ieee80211vap *vap)
|
||||||
struct ieee80211vap *vap, int amin, int amax, int interval)
|
|
||||||
{
|
{
|
||||||
/* XXX bounds check? */
|
struct ieee80211_amrr *amrr;
|
||||||
amrr->amrr_min_success_threshold = amin;
|
|
||||||
amrr->amrr_max_success_threshold = amax;
|
|
||||||
ieee80211_amrr_setinterval(amrr, interval);
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
ieee80211_amrr_cleanup(struct ieee80211_amrr *amrr)
|
amrr_deinit(struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
|
free(vap->iv_rs, M_80211_RATECTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ieee80211_amrr_node_init(struct ieee80211_amrr *amrr,
|
amrr_node_init(struct ieee80211_node *ni)
|
||||||
struct ieee80211_amrr_node *amn, struct ieee80211_node *ni)
|
|
||||||
{
|
{
|
||||||
const struct ieee80211_rateset *rs = &ni->ni_rates;
|
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_amrr = amrr;
|
||||||
amn->amn_success = 0;
|
amn->amn_success = 0;
|
||||||
amn->amn_recovery = 0;
|
amn->amn_recovery = 0;
|
||||||
@@ -112,6 +164,12 @@ ieee80211_amrr_node_init(struct ieee80211_amrr *amrr,
|
|||||||
"AMRR initial rate %d", ni->ni_txrate);
|
"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
|
static int
|
||||||
amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn,
|
amrr_update(struct ieee80211_amrr *amrr, struct ieee80211_amrr_node *amn,
|
||||||
struct ieee80211_node *ni)
|
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.
|
* Update our internal state if it's been long enough.
|
||||||
* If the rate changes we also update ni_txrate to match.
|
* If the rate changes we also update ni_txrate to match.
|
||||||
*/
|
*/
|
||||||
int
|
static int
|
||||||
ieee80211_amrr_choose(struct ieee80211_node *ni,
|
amrr_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
|
||||||
struct ieee80211_amrr_node *amn)
|
|
||||||
{
|
{
|
||||||
|
struct ieee80211_amrr_node *amn = ni->ni_rctls;
|
||||||
struct ieee80211_amrr *amrr = amn->amn_amrr;
|
struct ieee80211_amrr *amrr = amn->amn_amrr;
|
||||||
int rix;
|
int rix;
|
||||||
|
|
||||||
@@ -189,27 +247,65 @@ ieee80211_amrr_choose(struct ieee80211_node *ni,
|
|||||||
return rix;
|
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
|
static int
|
||||||
amrr_sysctl_interval(SYSCTL_HANDLER_ARGS)
|
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 msecs = ticks_to_msecs(amrr->amrr_interval);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = sysctl_handle_int(oidp, &msecs, 0, req);
|
error = sysctl_handle_int(oidp, &msecs, 0, req);
|
||||||
if (error || !req->newptr)
|
if (error || !req->newptr)
|
||||||
return error;
|
return error;
|
||||||
ieee80211_amrr_setinterval(amrr, msecs);
|
amrr_setinterval(vap, msecs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
amrr_sysctlattach(struct ieee80211_amrr *amrr,
|
amrr_sysctlattach(struct ieee80211vap *vap,
|
||||||
struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
|
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,
|
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)");
|
0, amrr_sysctl_interval, "I", "amrr operation interval (ms)");
|
||||||
/* XXX bounds check values */
|
/* XXX bounds check values */
|
||||||
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
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_min_sucess_threshold", CTLFLAG_RW,
|
||||||
&amrr->amrr_min_success_threshold, 0, "");
|
&amrr->amrr_min_success_threshold, 0, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,44 +58,4 @@ struct ieee80211_amrr_node {
|
|||||||
u_int amn_retrycnt;
|
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_ */
|
#endif /* _FBSD_COMPAT_NET80211_IEEE80211_AMRR_H_ */
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ tkip_setkey(struct ieee80211_key *k)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
k->wk_keytsc = 1; /* TSC starts at 1 */
|
k->wk_keytsc = 1; /* TSC starts at 1 */
|
||||||
|
ctx->rx_phase1_done = 0;
|
||||||
return 1;
|
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_LOCK(_aq) mtx_lock(&(_aq)->aq_lock)
|
||||||
#define IEEE80211_AGEQ_UNLOCK(_aq) mtx_unlock(&(_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.
|
* Node reference counting definitions.
|
||||||
*
|
*
|
||||||
@@ -311,6 +321,23 @@ void ieee80211_scan_sta_init(void);
|
|||||||
void ieee80211_scan_sta_uninit(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;
|
struct ieee80211req;
|
||||||
typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
|
typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
|
||||||
struct ieee80211req *);
|
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_frame *wh;
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
struct ether_header *eh;
|
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 dir, type, subtype, qos;
|
||||||
uint8_t *bssid;
|
uint8_t *bssid;
|
||||||
uint16_t rxseq;
|
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"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
ni->ni_inact = ni->ni_inact_reload;
|
ni->ni_inact = ni->ni_inact_reload;
|
||||||
|
|
||||||
need_tap = 1; /* mbuf need to be tapped. */
|
|
||||||
type = -1; /* undefined */
|
type = -1; /* undefined */
|
||||||
|
|
||||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
|
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 = mtod(m, struct ieee80211_frame *);
|
||||||
wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
|
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);
|
vap->iv_recv_mgmt(ni, m, subtype, rssi, nf);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -1252,7 +1259,7 @@ ieee80211_parse_wpa(struct ieee80211vap *vap, const uint8_t *frm,
|
|||||||
return IEEE80211_REASON_IE_INVALID;
|
return IEEE80211_REASON_IE_INVALID;
|
||||||
}
|
}
|
||||||
frm += 6, len -= 4; /* NB: len is payload only */
|
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);
|
w = LE_READ_2(frm);
|
||||||
if (w != WPA_VERSION) {
|
if (w != WPA_VERSION) {
|
||||||
IEEE80211_DISCARD_IE(vap,
|
IEEE80211_DISCARD_IE(vap,
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ typedef uint32_t ieee80211_hwmp_seq;
|
|||||||
struct ieee80211_hwmp_route {
|
struct ieee80211_hwmp_route {
|
||||||
ieee80211_hwmp_seq hr_seq; /* last HWMP seq seen from dst*/
|
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_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;
|
int hr_preqretries;
|
||||||
};
|
};
|
||||||
struct ieee80211_hwmp_state {
|
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_ttl;
|
||||||
*frm++ = perr->perr_ndests;
|
*frm++ = perr->perr_ndests;
|
||||||
for (i = 0; i < perr->perr_ndests; i++) {
|
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);
|
IEEE80211_ADDR_COPY(frm, perr->perr_dests[i].dest_addr);
|
||||||
frm += 6;
|
frm += 6;
|
||||||
ADDWORD(frm, perr->perr_dests[i].dest_seq);
|
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,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, vap->iv_bss,
|
||||||
"%s", "send broadcast RANN");
|
"%s", "send broadcast RANN");
|
||||||
|
|
||||||
|
rann.rann_flags = 0;
|
||||||
if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
|
if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
|
||||||
rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR;
|
rann.rann_flags |= IEEE80211_MESHRANN_FLAGS_PR;
|
||||||
rann.rann_hopcount = 0;
|
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);
|
rtorig = ieee80211_mesh_rt_find(vap, preq->preq_origaddr);
|
||||||
if (rtorig == NULL)
|
if (rtorig == NULL)
|
||||||
rtorig = ieee80211_mesh_rt_add(vap, preq->preq_origaddr);
|
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);
|
hrorig = IEEE80211_MESH_ROUTE_PRIV(rtorig, struct ieee80211_hwmp_route);
|
||||||
/*
|
/*
|
||||||
* Sequence number validation.
|
* Sequence number validation.
|
||||||
@@ -733,12 +738,12 @@ hwmp_recv_preq(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
|||||||
prep.prep_flags = 0;
|
prep.prep_flags = 0;
|
||||||
prep.prep_hopcount = 0;
|
prep.prep_hopcount = 0;
|
||||||
prep.prep_ttl = ms->ms_ttl;
|
prep.prep_ttl = ms->ms_ttl;
|
||||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr, preq->preq_origaddr);
|
IEEE80211_ADDR_COPY(prep.prep_targetaddr, vap->iv_myaddr);
|
||||||
prep.prep_targetseq = preq->preq_origseq;
|
prep.prep_targetseq = ++hs->hs_seq;
|
||||||
prep.prep_lifetime = preq->preq_lifetime;
|
prep.prep_lifetime = preq->preq_lifetime;
|
||||||
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
||||||
IEEE80211_ADDR_COPY(prep.prep_origaddr, vap->iv_myaddr);
|
IEEE80211_ADDR_COPY(prep.prep_origaddr, preq->preq_origaddr);
|
||||||
prep.prep_origseq = ++hs->hs_seq;
|
prep.prep_origseq = preq->preq_origseq;
|
||||||
hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
|
hwmp_send_prep(ni, vap->iv_myaddr, wh->i_addr2, &prep);
|
||||||
/*
|
/*
|
||||||
* Build the reverse path, if we don't have it already.
|
* 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_flags = 0;
|
||||||
prep.prep_hopcount = 0;
|
prep.prep_hopcount = 0;
|
||||||
prep.prep_ttl = ms->ms_ttl;
|
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_origseq = preq->preq_origseq;
|
||||||
prep.prep_targetseq = ++hs->hs_seq;
|
|
||||||
prep.prep_lifetime = preq->preq_lifetime;
|
prep.prep_lifetime = preq->preq_lifetime;
|
||||||
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
prep.prep_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
||||||
IEEE80211_ADDR_COPY(prep.prep_targetaddr, rootmac);
|
IEEE80211_ADDR_COPY(prep.prep_targetaddr,
|
||||||
prep.prep_targetseq = PREQ_TSEQ(0);
|
vap->iv_myaddr);
|
||||||
|
prep.prep_targetseq = ++hs->hs_seq;
|
||||||
hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
|
hwmp_send_prep(vap->iv_bss, vap->iv_myaddr,
|
||||||
broadcastaddr, &prep);
|
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_hopcount = rt->rt_nhops + 1;
|
||||||
prep.prep_ttl = ms->ms_ttl;
|
prep.prep_ttl = ms->ms_ttl;
|
||||||
IEEE80211_ADDR_COPY(&prep.prep_targetaddr,
|
IEEE80211_ADDR_COPY(&prep.prep_targetaddr,
|
||||||
preq->preq_origaddr);
|
PREQ_TADDR(0));
|
||||||
prep.prep_targetseq = hrorig->hr_seq;
|
prep.prep_targetseq = hrorig->hr_seq;
|
||||||
prep.prep_lifetime = preq->preq_lifetime;
|
prep.prep_lifetime = preq->preq_lifetime;
|
||||||
prep.prep_metric = rt->rt_metric +
|
prep.prep_metric = rt->rt_metric +
|
||||||
ms->ms_pmetric->mpm_metric(ni);
|
ms->ms_pmetric->mpm_metric(ni);
|
||||||
IEEE80211_ADDR_COPY(&prep.prep_origaddr,
|
IEEE80211_ADDR_COPY(&prep.prep_origaddr,
|
||||||
PREQ_TADDR(0));
|
preq->preq_origaddr);
|
||||||
prep.prep_origseq = hrorig->hr_seq;
|
prep.prep_origseq = hrorig->hr_seq;
|
||||||
hwmp_send_prep(ni, vap->iv_myaddr,
|
hwmp_send_prep(ni, vap->iv_myaddr,
|
||||||
broadcastaddr, &prep);
|
broadcastaddr, &prep);
|
||||||
@@ -951,19 +956,19 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
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 (rt == NULL) {
|
||||||
/*
|
/*
|
||||||
* If we have no entry this could be a reply to a root PREQ.
|
* If we have no entry this could be a reply to a root PREQ.
|
||||||
*/
|
*/
|
||||||
if (hs->hs_rootmode != IEEE80211_HWMP_ROOTMODE_DISABLED) {
|
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) {
|
if (rt == NULL) {
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP,
|
||||||
ni, "unable to add PREP path to %s",
|
ni, "unable to add PREP path to %s",
|
||||||
ether_sprintf(prep->prep_origaddr));
|
ether_sprintf(prep->prep_targetaddr));
|
||||||
vap->iv_stats.is_mesh_rtaddfailed++;
|
vap->iv_stats.is_mesh_rtaddfailed++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -974,7 +979,7 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
|||||||
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
|
rt->rt_flags |= IEEE80211_MESHRT_FLAGS_VALID;
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"add root path to %s nhops %d metric %d (PREP)",
|
"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);
|
rt->rt_nhops, rt->rt_metric);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -984,30 +989,30 @@ hwmp_recv_prep(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
|||||||
* Sequence number validation.
|
* Sequence number validation.
|
||||||
*/
|
*/
|
||||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
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,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"discard PREP from %s, old seq no %u <= %u",
|
"discard PREP from %s, old seq no %u <= %u",
|
||||||
ether_sprintf(prep->prep_origaddr),
|
ether_sprintf(prep->prep_targetaddr),
|
||||||
prep->prep_origseq, hr->hr_seq);
|
prep->prep_targetseq, hr->hr_seq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hr->hr_seq = prep->prep_origseq;
|
hr->hr_seq = prep->prep_targetseq;
|
||||||
/*
|
/*
|
||||||
* If it's NOT for us, propagate the PREP.
|
* 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) {
|
prep->prep_ttl > 1 && prep->prep_hopcount < hs->hs_maxhops) {
|
||||||
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
|
struct ieee80211_meshprep_ie pprep; /* propagated PREP */
|
||||||
|
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"propagate PREP from %s",
|
"propagate PREP from %s",
|
||||||
ether_sprintf(prep->prep_origaddr));
|
ether_sprintf(prep->prep_targetaddr));
|
||||||
|
|
||||||
memcpy(&pprep, prep, sizeof(pprep));
|
memcpy(&pprep, prep, sizeof(pprep));
|
||||||
pprep.prep_hopcount += 1;
|
pprep.prep_hopcount += 1;
|
||||||
pprep.prep_ttl -= 1;
|
pprep.prep_ttl -= 1;
|
||||||
pprep.prep_metric += ms->ms_pmetric->mpm_metric(ni);
|
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);
|
hwmp_send_prep(ni, vap->iv_myaddr, broadcastaddr, &pprep);
|
||||||
}
|
}
|
||||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
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 */;
|
/* NB: never clobber a proxy entry */;
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"discard PREP for %s, route is marked PROXY",
|
"discard PREP for %s, route is marked PROXY",
|
||||||
ether_sprintf(prep->prep_origaddr));
|
ether_sprintf(prep->prep_targetaddr));
|
||||||
vap->iv_stats.is_hwmp_proxy++;
|
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.
|
* Check if we already have a path to this node.
|
||||||
* If we do, check if this path reply contains a
|
* 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 {
|
} else {
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"ignore PREP for %s, hopcount %d:%d metric %d:%d",
|
"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_nhops, prep->prep_hopcount,
|
||||||
rt->rt_metric, prep->prep_metric);
|
rt->rt_metric, prep->prep_metric);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
|
||||||
"discard PREP for %s, wrong seqno %u != %u",
|
"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);
|
hr->hr_seq);
|
||||||
vap->iv_stats.is_hwmp_wrongseq++;
|
vap->iv_stats.is_hwmp_wrongseq++;
|
||||||
}
|
}
|
||||||
@@ -1114,6 +1119,7 @@ hwmp_peerdown(struct ieee80211_node *ni)
|
|||||||
"%s", "delete route entry");
|
"%s", "delete route entry");
|
||||||
perr.perr_ttl = ms->ms_ttl;
|
perr.perr_ttl = ms->ms_ttl;
|
||||||
perr.perr_ndests = 1;
|
perr.perr_ndests = 1;
|
||||||
|
PERR_DFLAGS(0) = 0;
|
||||||
if (hr->hr_seq == 0)
|
if (hr->hr_seq == 0)
|
||||||
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
|
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_USN;
|
||||||
PERR_DFLAGS(0) |= IEEE80211_MESHPERR_DFLAGS_RC;
|
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;
|
struct ieee80211_meshrann_ie prann;
|
||||||
|
|
||||||
if (ni == vap->iv_bss ||
|
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;
|
return;
|
||||||
|
|
||||||
rt = ieee80211_mesh_rt_find(vap, rann->rann_addr);
|
rt = ieee80211_mesh_rt_find(vap, rann->rann_addr);
|
||||||
@@ -1236,15 +1243,18 @@ hwmp_recv_rann(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
hr = IEEE80211_MESH_ROUTE_PRIV(rt, struct ieee80211_hwmp_route);
|
||||||
if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq) && rann->rann_ttl > 1 &&
|
if (HWMP_SEQ_GT(rann->rann_seq, hr->hr_seq)) {
|
||||||
rann->rann_hopcount < hs->hs_maxhops &&
|
hr->hr_seq = rann->rann_seq;
|
||||||
(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
|
if (rann->rann_ttl > 1 &&
|
||||||
memcpy(&prann, rann, sizeof(prann));
|
rann->rann_hopcount < hs->hs_maxhops &&
|
||||||
prann.rann_hopcount += 1;
|
(ms->ms_flags & IEEE80211_MESHFLAGS_FWD)) {
|
||||||
prann.rann_ttl -= 1;
|
memcpy(&prann, rann, sizeof(prann));
|
||||||
prann.rann_metric += ms->ms_pmetric->mpm_metric(ni);
|
prann.rann_hopcount += 1;
|
||||||
hwmp_send_rann(vap->iv_bss, vap->iv_myaddr, broadcastaddr,
|
prann.rann_ttl -= 1;
|
||||||
&prann);
|
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,
|
hr = IEEE80211_MESH_ROUTE_PRIV(rt,
|
||||||
struct ieee80211_hwmp_route);
|
struct ieee80211_hwmp_route);
|
||||||
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
|
if ((rt->rt_flags & IEEE80211_MESHRT_FLAGS_VALID) == 0) {
|
||||||
if (hr->hr_targetseq == 0)
|
if (hr->hr_origseq == 0)
|
||||||
hr->hr_targetseq = ++hs->hs_seq;
|
hr->hr_origseq = ++hs->hs_seq;
|
||||||
rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
rt->rt_metric = IEEE80211_MESHLMETRIC_INITIALVAL;
|
||||||
rt->rt_lifetime =
|
rt->rt_lifetime =
|
||||||
ticks_to_msecs(ieee80211_hwmp_pathtimeout);
|
ticks_to_msecs(ieee80211_hwmp_pathtimeout);
|
||||||
@@ -1324,7 +1334,7 @@ hwmp_discover(struct ieee80211vap *vap,
|
|||||||
preq.preq_ttl = ms->ms_ttl;
|
preq.preq_ttl = ms->ms_ttl;
|
||||||
preq.preq_id = ++hs->hs_preqid;
|
preq.preq_id = ++hs->hs_preqid;
|
||||||
IEEE80211_ADDR_COPY(preq.preq_origaddr, vap->iv_myaddr);
|
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_lifetime = rt->rt_lifetime;
|
||||||
preq.preq_metric = rt->rt_metric;
|
preq.preq_metric = rt->rt_metric;
|
||||||
preq.preq_tcount = 1;
|
preq.preq_tcount = 1;
|
||||||
|
|||||||
@@ -734,7 +734,8 @@ ieee80211_ssid_mismatch(struct ieee80211vap *vap, const char *tag,
|
|||||||
* Return the bssid of a frame.
|
* Return the bssid of a frame.
|
||||||
*/
|
*/
|
||||||
static const uint8_t *
|
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)
|
if (vap->iv_opmode == IEEE80211_M_STA)
|
||||||
return wh->i_addr2;
|
return wh->i_addr2;
|
||||||
@@ -748,7 +749,7 @@ ieee80211_getbssid(struct ieee80211vap *vap, const struct ieee80211_frame *wh)
|
|||||||
#include <machine/stdarg.h>
|
#include <machine/stdarg.h>
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_note(struct ieee80211vap *vap, const char *fmt, ...)
|
ieee80211_note(const struct ieee80211vap *vap, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char buf[128]; /* XXX */
|
char buf[128]; /* XXX */
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -761,7 +762,7 @@ ieee80211_note(struct ieee80211vap *vap, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_note_frame(struct ieee80211vap *vap,
|
ieee80211_note_frame(const struct ieee80211vap *vap,
|
||||||
const struct ieee80211_frame *wh,
|
const struct ieee80211_frame *wh,
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -776,7 +777,7 @@ ieee80211_note_frame(struct ieee80211vap *vap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_note_mac(struct ieee80211vap *vap,
|
ieee80211_note_mac(const struct ieee80211vap *vap,
|
||||||
const uint8_t mac[IEEE80211_ADDR_LEN],
|
const uint8_t mac[IEEE80211_ADDR_LEN],
|
||||||
const char *fmt, ...)
|
const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -790,7 +791,7 @@ ieee80211_note_mac(struct ieee80211vap *vap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_discard_frame(struct ieee80211vap *vap,
|
ieee80211_discard_frame(const struct ieee80211vap *vap,
|
||||||
const struct ieee80211_frame *wh,
|
const struct ieee80211_frame *wh,
|
||||||
const char *type, const char *fmt, ...)
|
const char *type, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -811,7 +812,7 @@ ieee80211_discard_frame(struct ieee80211vap *vap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_discard_ie(struct ieee80211vap *vap,
|
ieee80211_discard_ie(const struct ieee80211vap *vap,
|
||||||
const struct ieee80211_frame *wh,
|
const struct ieee80211_frame *wh,
|
||||||
const char *type, const char *fmt, ...)
|
const char *type, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@@ -830,7 +831,7 @@ ieee80211_discard_ie(struct ieee80211vap *vap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_discard_mac(struct ieee80211vap *vap,
|
ieee80211_discard_mac(const struct ieee80211vap *vap,
|
||||||
const uint8_t mac[IEEE80211_ADDR_LEN],
|
const uint8_t mac[IEEE80211_ADDR_LEN],
|
||||||
const char *type, const char *fmt, ...)
|
const char *type, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1598,8 +1598,10 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
|||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
error = copyin(ireq->i_data, list, ireq->i_len);
|
error = copyin(ireq->i_data, list, ireq->i_len);
|
||||||
if (error)
|
if (error) {
|
||||||
|
free(list, M_TEMP);
|
||||||
return error;
|
return error;
|
||||||
|
}
|
||||||
nchan = 0;
|
nchan = 0;
|
||||||
chanlist = list + ireq->i_len; /* NB: zero'd already */
|
chanlist = list + ireq->i_len; /* NB: zero'd already */
|
||||||
maxchan = ireq->i_len * NBBY;
|
maxchan = ireq->i_len * NBBY;
|
||||||
@@ -1615,8 +1617,10 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
|||||||
nchan++;
|
nchan++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nchan == 0)
|
if (nchan == 0) {
|
||||||
|
free(list, M_TEMP);
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
}
|
||||||
if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
|
if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
|
||||||
isclr(chanlist, ic->ic_bsschan->ic_ieee))
|
isclr(chanlist, ic->ic_bsschan->ic_ieee))
|
||||||
ic->ic_bsschan = IEEE80211_CHAN_ANYC;
|
ic->ic_bsschan = IEEE80211_CHAN_ANYC;
|
||||||
@@ -3207,15 +3211,18 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
|
|||||||
void *ioctl;
|
void *ioctl;
|
||||||
|
|
||||||
IEEE80211_LOCK(ic);
|
IEEE80211_LOCK(ic);
|
||||||
if_purgemaddrs(parent);
|
if_delallmulti(parent);
|
||||||
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
|
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
|
||||||
parent->if_ioctl = NULL;
|
parent->if_ioctl = NULL;
|
||||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||||
struct ifnet *ifp = vap->iv_ifp;
|
struct ifnet *ifp = vap->iv_ifp;
|
||||||
struct ifmultiaddr *ifma;
|
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);
|
(void) if_addmulti(parent, ifma->ifma_addr, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent->if_ioctl = ioctl;
|
parent->if_ioctl = ioctl;
|
||||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
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++) {
|
for (i = 0; i < N(mesh_proto_paths); i++) {
|
||||||
if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
|
if (strcasecmp(mesh_proto_paths[i].mpp_descr, name) == 0) {
|
||||||
ms->ms_ppath = &mesh_proto_paths[i];
|
ms->ms_ppath = &mesh_proto_paths[i];
|
||||||
if (vap->iv_state == IEEE80211_S_RUN)
|
|
||||||
vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
|
|
||||||
return 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++) {
|
for (i = 0; i < N(mesh_proto_metrics); i++) {
|
||||||
if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
|
if (strcasecmp(mesh_proto_metrics[i].mpm_descr, name) == 0) {
|
||||||
ms->ms_pmetric = &mesh_proto_metrics[i];
|
ms->ms_pmetric = &mesh_proto_metrics[i];
|
||||||
if (vap->iv_state == IEEE80211_S_RUN)
|
|
||||||
vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
|
|
||||||
return 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) {
|
ni->ni_mlstate != IEEE80211_NODE_MESH_ESTABLISHED) {
|
||||||
KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
|
KASSERT(ms->ms_neighbors < 65535, ("neighbor count overflow"));
|
||||||
ms->ms_neighbors++;
|
ms->ms_neighbors++;
|
||||||
|
ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
|
||||||
} else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
|
} else if (ni->ni_mlstate == IEEE80211_NODE_MESH_ESTABLISHED &&
|
||||||
state != IEEE80211_NODE_MESH_ESTABLISHED) {
|
state != IEEE80211_NODE_MESH_ESTABLISHED) {
|
||||||
KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
|
KASSERT(ms->ms_neighbors > 0, ("neighbor count 0"));
|
||||||
ms->ms_neighbors--;
|
ms->ms_neighbors--;
|
||||||
|
ieee80211_beacon_notify(vap, IEEE80211_BEACON_MESHCONF);
|
||||||
}
|
}
|
||||||
ni->ni_mlstate = state;
|
ni->ni_mlstate = state;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -2552,6 +2550,18 @@ ieee80211_mesh_init_neighbor(struct ieee80211_node *ni,
|
|||||||
ieee80211_parse_meshid(ni, sp->meshid);
|
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
|
static int
|
||||||
mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
mesh_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -469,6 +469,8 @@ struct ieee80211_scanparams;
|
|||||||
void ieee80211_mesh_init_neighbor(struct ieee80211_node *,
|
void ieee80211_mesh_init_neighbor(struct ieee80211_node *,
|
||||||
const struct ieee80211_frame *,
|
const struct ieee80211_frame *,
|
||||||
const struct ieee80211_scanparams *);
|
const struct ieee80211_scanparams *);
|
||||||
|
void ieee80211_mesh_update_beacon(struct ieee80211vap *,
|
||||||
|
struct ieee80211_beacon_offsets *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return non-zero if proxy operation is enabled.
|
* Return non-zero if proxy operation is enabled.
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ struct ieee80211_node {
|
|||||||
struct ieee80211_nodestats ni_stats; /* per-node statistics */
|
struct ieee80211_nodestats ni_stats; /* per-node statistics */
|
||||||
|
|
||||||
struct ieee80211vap *ni_wdsvap; /* associated WDS vap */
|
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)
|
#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
|
#ifdef IEEE80211_SUPPORT_MESH
|
||||||
if (vap->iv_opmode == IEEE80211_M_MBSS) {
|
if (vap->iv_opmode == IEEE80211_M_MBSS) {
|
||||||
frm = ieee80211_add_meshid(frm, vap);
|
frm = ieee80211_add_meshid(frm, vap);
|
||||||
|
bo->bo_meshconf = frm;
|
||||||
frm = ieee80211_add_meshconf(frm, vap);
|
frm = ieee80211_add_meshconf(frm, vap);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2675,13 +2676,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
|
|||||||
*(uint16_t *)wh->i_dur = 0;
|
*(uint16_t *)wh->i_dur = 0;
|
||||||
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
||||||
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
|
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
|
||||||
#ifdef IEEE80211_SUPPORT_MESH
|
IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid);
|
||||||
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);
|
|
||||||
*(uint16_t *)wh->i_seq = 0;
|
*(uint16_t *)wh->i_seq = 0;
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
@@ -2786,6 +2781,11 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
|||||||
ieee80211_tdma_update_beacon(vap, bo);
|
ieee80211_tdma_update_beacon(vap, bo);
|
||||||
}
|
}
|
||||||
#endif
|
#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 ||
|
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||||
vap->iv_opmode == IEEE80211_M_MBSS) { /* NB: no IBSS support*/
|
vap->iv_opmode == IEEE80211_M_MBSS) { /* NB: no IBSS support*/
|
||||||
struct ieee80211_tim_ie *tie =
|
struct ieee80211_tim_ie *tie =
|
||||||
@@ -2839,6 +2839,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef IEEE80211_TDMA_SUPPORT
|
#ifdef IEEE80211_TDMA_SUPPORT
|
||||||
bo->bo_tdma += adjust;
|
bo->bo_tdma += adjust;
|
||||||
|
#endif
|
||||||
|
#ifdef IEEE80211_MESH_SUPPORT
|
||||||
|
bo->bo_meshconf += adjust;
|
||||||
#endif
|
#endif
|
||||||
bo->bo_appie += adjust;
|
bo->bo_appie += adjust;
|
||||||
bo->bo_wme += adjust;
|
bo->bo_wme += adjust;
|
||||||
@@ -2890,6 +2893,9 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef IEEE80211_TDMA_SUPPORT
|
#ifdef IEEE80211_TDMA_SUPPORT
|
||||||
bo->bo_tdma += sizeof(*csa);
|
bo->bo_tdma += sizeof(*csa);
|
||||||
|
#endif
|
||||||
|
#ifdef IEEE80211_MESH_SUPPORT
|
||||||
|
bo->bo_meshconf += sizeof(*csa);
|
||||||
#endif
|
#endif
|
||||||
bo->bo_appie += sizeof(*csa);
|
bo->bo_appie += sizeof(*csa);
|
||||||
bo->bo_csa_trailer_len += sizeof(*csa);
|
bo->bo_csa_trailer_len += sizeof(*csa);
|
||||||
|
|||||||
@@ -1432,8 +1432,6 @@ ieee80211_swbmiss(void *arg)
|
|||||||
} else if (vap->iv_swbmiss_count == 0) {
|
} else if (vap->iv_swbmiss_count == 0) {
|
||||||
if (vap->iv_bmiss != NULL)
|
if (vap->iv_bmiss != NULL)
|
||||||
ieee80211_runtask(ic, &vap->iv_swbmiss_task);
|
ieee80211_runtask(ic, &vap->iv_swbmiss_task);
|
||||||
if (vap->iv_bmiss_count == 0) /* don't re-arm timer */
|
|
||||||
return;
|
|
||||||
} else
|
} else
|
||||||
vap->iv_swbmiss_count = 0;
|
vap->iv_swbmiss_count = 0;
|
||||||
callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
|
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_ath; /* start of ATH parameters */
|
||||||
uint8_t *bo_appie; /* start of AppIE element */
|
uint8_t *bo_appie; /* start of AppIE element */
|
||||||
uint16_t bo_appie_len; /* AppIE length in bytes */
|
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_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 mbuf *ieee80211_beacon_alloc(struct ieee80211_node *,
|
||||||
struct ieee80211_beacon_offsets *);
|
struct ieee80211_beacon_offsets *);
|
||||||
@@ -347,6 +348,7 @@ enum {
|
|||||||
IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */
|
IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */
|
||||||
IEEE80211_BEACON_TDMA = 9, /* TDMA Info */
|
IEEE80211_BEACON_TDMA = 9, /* TDMA Info */
|
||||||
IEEE80211_BEACON_ATH = 10, /* ATH parameters */
|
IEEE80211_BEACON_ATH = 10, /* ATH parameters */
|
||||||
|
IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */
|
||||||
};
|
};
|
||||||
int ieee80211_beacon_update(struct ieee80211_node *,
|
int ieee80211_beacon_update(struct ieee80211_node *,
|
||||||
struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
|
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 {
|
enum ieee80211_ratealgs {
|
||||||
IEEE80211_RATECTL_AMRR = 0,
|
IEEE80211_RATECTL_AMRR = 0,
|
||||||
IEEE80211_RATECTL_RSSADAPT = 1,
|
IEEE80211_RATECTL_RSSADAPT = 1,
|
||||||
IEEE80211_RATECTL_ONOE = 2,
|
IEEE80211_RATECTL_ONOE = 2,
|
||||||
IEEE80211_RATECTL_SAMPLE = 3,
|
IEEE80211_RATECTL_SAMPLE = 3,
|
||||||
|
IEEE80211_RATECTL_NONE = 4,
|
||||||
IEEE80211_RATECTL_MAX
|
IEEE80211_RATECTL_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,15 +57,10 @@ struct ieee80211_ratectl {
|
|||||||
|
|
||||||
void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
|
void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
|
||||||
void ieee80211_ratectl_unregister(int);
|
void ieee80211_ratectl_unregister(int);
|
||||||
|
void ieee80211_ratectl_init(struct ieee80211vap *);
|
||||||
void ieee80211_ratectl_set(struct ieee80211vap *, int);
|
void ieee80211_ratectl_set(struct ieee80211vap *, int);
|
||||||
|
|
||||||
MALLOC_DECLARE(M_80211_RATECTL);
|
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
|
static void __inline
|
||||||
ieee80211_ratectl_deinit(struct ieee80211vap *vap)
|
ieee80211_ratectl_deinit(struct ieee80211vap *vap)
|
||||||
@@ -76,8 +72,9 @@ static void __inline
|
|||||||
ieee80211_ratectl_node_init(struct ieee80211_node *ni)
|
ieee80211_ratectl_node_init(struct ieee80211_node *ni)
|
||||||
{
|
{
|
||||||
const struct ieee80211vap *vap = ni->ni_vap;
|
const struct ieee80211vap *vap = ni->ni_vap;
|
||||||
|
kernel_debugger("ieee80211_ratectl_node_init\n");
|
||||||
vap->iv_rate->ir_node_init(ni);
|
vap->iv_rate->ir_node_init(ni);
|
||||||
|
kernel_debugger("ieee80211_ratectl_node_init exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __inline
|
static void __inline
|
||||||
@@ -85,8 +82,6 @@ ieee80211_ratectl_node_deinit(struct ieee80211_node *ni)
|
|||||||
{
|
{
|
||||||
const struct ieee80211vap *vap = ni->ni_vap;
|
const struct ieee80211vap *vap = ni->ni_vap;
|
||||||
|
|
||||||
if (ni->ni_rctls == NULL) /* ratectl not setup */
|
|
||||||
return;
|
|
||||||
vap->iv_rate->ir_node_deinit(ni);
|
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;
|
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);
|
return vap->iv_rate->ir_rate(ni, arg, iarg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +97,6 @@ static void __inline
|
|||||||
ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
|
ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
|
||||||
const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
|
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);
|
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)
|
if (vap->iv_rate->ir_tx_update == NULL)
|
||||||
return;
|
return;
|
||||||
if (ni->ni_rctls == NULL) /* ratectl not setup */
|
|
||||||
return;
|
|
||||||
vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3);
|
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;
|
return;
|
||||||
vap->iv_rate->ir_setinterval(vap, msecs);
|
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$ */
|
/* $FreeBSD$ */
|
||||||
/* $NetBSD: ieee80211_rssadapt.c,v 1.9 2005/02/26 22:45:09 perry Exp $ */
|
/* $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.
|
* Copyright (c) 2003, 2004 David Young. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or
|
* Redistribution and use in source and binary forms, with or
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
|
|
||||||
#include <net80211/ieee80211_var.h>
|
#include <net80211/ieee80211_var.h>
|
||||||
#include <net80211/ieee80211_rssadapt.h>
|
#include <net80211/ieee80211_rssadapt.h>
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
struct rssadapt_expavgctl {
|
struct rssadapt_expavgctl {
|
||||||
/* RSS threshold decay. */
|
/* RSS threshold decay. */
|
||||||
@@ -56,12 +58,12 @@ struct rssadapt_expavgctl {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct rssadapt_expavgctl master_expavgctl = {
|
static struct rssadapt_expavgctl master_expavgctl = {
|
||||||
rc_decay_denom : 16,
|
.rc_decay_denom = 16,
|
||||||
rc_decay_old : 15,
|
.rc_decay_old = 15,
|
||||||
rc_thresh_denom : 8,
|
.rc_thresh_denom = 8,
|
||||||
rc_thresh_old : 4,
|
.rc_thresh_old = 4,
|
||||||
rc_avgrssi_denom : 8,
|
.rc_avgrssi_denom = 8,
|
||||||
rc_avgrssi_old : 4
|
.rc_avgrssi_old = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef interpolate
|
#ifdef interpolate
|
||||||
@@ -71,15 +73,45 @@ static struct rssadapt_expavgctl master_expavgctl = {
|
|||||||
(parm##_denom - parm##_old) * (new)) / \
|
(parm##_denom - parm##_old) * (new)) / \
|
||||||
parm##_denom)
|
parm##_denom)
|
||||||
|
|
||||||
static void rssadapt_sysctlattach(struct ieee80211_rssadapt *rs,
|
static void rssadapt_setinterval(const struct ieee80211vap *, int);
|
||||||
struct sysctl_ctx_list *ctx, struct sysctl_oid *tree);
|
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 */
|
/* number of references from net80211 layer */
|
||||||
static int nrefs = 0;
|
static int nrefs = 0;
|
||||||
|
|
||||||
void
|
static const struct ieee80211_ratectl rssadapt = {
|
||||||
ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs)
|
.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;
|
int t;
|
||||||
|
|
||||||
if (msecs < 100)
|
if (msecs < 100)
|
||||||
@@ -88,18 +120,29 @@ ieee80211_rssadapt_setinterval(struct ieee80211_rssadapt *rs, int msecs)
|
|||||||
rs->interval = (t < 1) ? 1 : t;
|
rs->interval = (t < 1) ? 1 : t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ieee80211_rssadapt_init(struct ieee80211_rssadapt *rs, struct ieee80211vap *vap, int interval)
|
rssadapt_init(struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
rs->vap = vap;
|
struct ieee80211_rssadapt *rs;
|
||||||
ieee80211_rssadapt_setinterval(rs, interval);
|
|
||||||
|
|
||||||
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
|
static void
|
||||||
ieee80211_rssadapt_cleanup(struct ieee80211_rssadapt *rs)
|
rssadapt_deinit(struct ieee80211vap *vap)
|
||||||
{
|
{
|
||||||
|
free(vap->iv_rs, M_80211_RATECTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -118,12 +161,25 @@ rssadapt_updatestats(struct ieee80211_rssadapt_node *ra)
|
|||||||
ra->ra_raise_interval = msecs_to_ticks(interval);
|
ra->ra_raise_interval = msecs_to_ticks(interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa,
|
rssadapt_node_init(struct ieee80211_node *ni)
|
||||||
struct ieee80211_rssadapt_node *ra, 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;
|
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_rs = rsa;
|
||||||
ra->ra_rates = *rs;
|
ra->ra_rates = *rs;
|
||||||
rssadapt_updatestats(ra);
|
rssadapt_updatestats(ra);
|
||||||
@@ -140,6 +196,13 @@ ieee80211_rssadapt_node_init(struct ieee80211_rssadapt *rsa,
|
|||||||
"RSSADAPT initial rate %d", ni->ni_txrate);
|
"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
|
static __inline int
|
||||||
bucket(int pktlen)
|
bucket(int pktlen)
|
||||||
{
|
{
|
||||||
@@ -155,10 +218,11 @@ bucket(int pktlen)
|
|||||||
return thridx;
|
return thridx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
ieee80211_rssadapt_choose(struct ieee80211_node *ni,
|
rssadapt_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg)
|
||||||
struct ieee80211_rssadapt_node *ra, u_int pktlen)
|
|
||||||
{
|
{
|
||||||
|
struct ieee80211_rssadapt_node *ra = ni->ni_rctls;
|
||||||
|
u_int pktlen = iarg;
|
||||||
const struct ieee80211_rateset *rs = &ra->ra_rates;
|
const struct ieee80211_rateset *rs = &ra->ra_rates;
|
||||||
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
||||||
int rix, rssi;
|
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
|
* raise the RSS threshold for transmitting packets of similar length at
|
||||||
* the same data rate.
|
* the same data rate.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra,
|
rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi)
|
||||||
int pktlen, int rssi)
|
|
||||||
{
|
{
|
||||||
uint16_t last_thr;
|
uint16_t last_thr;
|
||||||
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
||||||
@@ -214,9 +277,8 @@ ieee80211_rssadapt_lower_rate(struct ieee80211_rssadapt_node *ra,
|
|||||||
last_thr, (*thrs)[rix], rssi);
|
last_thr, (*thrs)[rix], rssi);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ieee80211_rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra,
|
rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi)
|
||||||
int pktlen, int rssi)
|
|
||||||
{
|
{
|
||||||
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
uint16_t (*thrs)[IEEE80211_RATE_SIZE];
|
||||||
uint16_t newthr, oldthr;
|
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
|
static int
|
||||||
rssadapt_sysctl_interval(SYSCTL_HANDLER_ARGS)
|
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 msecs = ticks_to_msecs(rs->interval);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = sysctl_handle_int(oidp, &msecs, 0, req);
|
error = sysctl_handle_int(oidp, &msecs, 0, req);
|
||||||
if (error || !req->newptr)
|
if (error || !req->newptr)
|
||||||
return error;
|
return error;
|
||||||
ieee80211_rssadapt_setinterval(rs, msecs);
|
rssadapt_setinterval(vap, msecs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rssadapt_sysctlattach(struct ieee80211_rssadapt *rs,
|
rssadapt_sysctlattach(struct ieee80211vap *vap,
|
||||||
struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
|
struct sysctl_ctx_list *ctx, struct sysctl_oid *tree)
|
||||||
{
|
{
|
||||||
|
|
||||||
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
|
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)");
|
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 */
|
#define IEEE80211_RSSADAPT_BKTPOWER 3 /* 2**_BKTPOWER */
|
||||||
|
|
||||||
struct ieee80211_rssadapt {
|
struct ieee80211_rssadapt {
|
||||||
struct ieee80211vap *vap;
|
const struct ieee80211vap *vap;
|
||||||
int interval; /* update interval (ticks) */
|
int interval; /* update interval (ticks) */
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,36 +66,6 @@ struct ieee80211_rssadapt_node {
|
|||||||
[IEEE80211_RATE_SIZE];
|
[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_SUCCESS 1
|
||||||
#define IEEE80211_RSSADAPT_FAILURE 0
|
#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_ */
|
#endif /* _FBSD_COMPAT_NET80211_IEEE80211_RSSADAPT_H_ */
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ struct sta_entry {
|
|||||||
CTASSERT(MAX_IEEE_CHAN >= 256);
|
CTASSERT(MAX_IEEE_CHAN >= 256);
|
||||||
|
|
||||||
struct sta_table {
|
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 */
|
TAILQ_HEAD(, sta_entry) st_entry; /* all entries */
|
||||||
LIST_HEAD(, sta_entry) st_hash[STA_HASHSIZE];
|
LIST_HEAD(, sta_entry) st_hash[STA_HASHSIZE];
|
||||||
struct mtx st_scanlock; /* on st_scaniter */
|
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);
|
M_80211_SCAN, M_NOWAIT | M_ZERO);
|
||||||
if (st == NULL)
|
if (st == NULL)
|
||||||
return 0;
|
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);
|
mtx_init(&st->st_scanlock, "scangen", "802.11 scangen", MTX_DEF);
|
||||||
TAILQ_INIT(&st->st_entry);
|
TAILQ_INIT(&st->st_entry);
|
||||||
ss->ss_priv = st;
|
ss->ss_priv = st;
|
||||||
@@ -179,7 +179,7 @@ sta_detach(struct ieee80211_scan_state *ss)
|
|||||||
|
|
||||||
if (st != NULL) {
|
if (st != NULL) {
|
||||||
sta_flush_table(st);
|
sta_flush_table(st);
|
||||||
mtx_destroy(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK_DESTROY(st);
|
||||||
mtx_destroy(&st->st_scanlock);
|
mtx_destroy(&st->st_scanlock);
|
||||||
free(st, M_80211_SCAN);
|
free(st, M_80211_SCAN);
|
||||||
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
|
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
|
||||||
@@ -196,9 +196,9 @@ sta_flush(struct ieee80211_scan_state *ss)
|
|||||||
{
|
{
|
||||||
struct sta_table *st = ss->ss_priv;
|
struct sta_table *st = ss->ss_priv;
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
sta_flush_table(st);
|
sta_flush_table(st);
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
ss->ss_last = 0;
|
ss->ss_last = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -244,14 +244,14 @@ sta_add(struct ieee80211_scan_state *ss,
|
|||||||
|
|
||||||
hash = STA_HASH(macaddr);
|
hash = STA_HASH(macaddr);
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
|
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
|
||||||
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
|
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
|
||||||
goto found;
|
goto found;
|
||||||
se = (struct sta_entry *) malloc(sizeof(struct sta_entry),
|
se = (struct sta_entry *) malloc(sizeof(struct sta_entry),
|
||||||
M_80211_SCAN, M_NOWAIT | M_ZERO);
|
M_80211_SCAN, M_NOWAIT | M_ZERO);
|
||||||
if (se == NULL) {
|
if (se == NULL) {
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
se->se_scangen = st->st_scaniter-1;
|
se->se_scangen = st->st_scaniter-1;
|
||||||
@@ -370,7 +370,7 @@ found:
|
|||||||
if (rssi > st->st_maxrssi[sp->bchan])
|
if (rssi > st->st_maxrssi[sp->bchan])
|
||||||
st->st_maxrssi[sp->bchan] = rssi;
|
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
|
* 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))
|
if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS))
|
||||||
fail |= MATCH_CAPINFO;
|
fail |= MATCH_CAPINFO;
|
||||||
else if (se->se_meshid == NULL)
|
else if (se->se_meshid[0] != IEEE80211_ELEMID_MESHID)
|
||||||
fail |= MATCH_MESH_NOID;
|
fail |= MATCH_MESH_NOID;
|
||||||
else if (ms->ms_idlen != 0 &&
|
else if (ms->ms_idlen != 0 &&
|
||||||
match_id(se->se_meshid, ms->ms_id, ms->ms_idlen))
|
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;
|
struct sta_entry *se;
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
TAILQ_FOREACH(se, &st->st_entry, se_list) {
|
TAILQ_FOREACH(se, &st->st_entry, se_list) {
|
||||||
/*
|
/*
|
||||||
* If seen the reset and don't bump the count;
|
* If seen the reset and don't bump the count;
|
||||||
@@ -1146,7 +1146,7 @@ sta_update_notseen(struct sta_table *st)
|
|||||||
else
|
else
|
||||||
se->se_notseen++;
|
se->se_notseen++;
|
||||||
}
|
}
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1154,11 +1154,11 @@ sta_dec_fails(struct sta_table *st)
|
|||||||
{
|
{
|
||||||
struct sta_entry *se;
|
struct sta_entry *se;
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
TAILQ_FOREACH(se, &st->st_entry, se_list)
|
TAILQ_FOREACH(se, &st->st_entry, se_list)
|
||||||
if (se->se_fails)
|
if (se->se_fails)
|
||||||
se->se_fails--;
|
se->se_fails--;
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sta_entry *
|
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",
|
IEEE80211_DPRINTF(vap, debug, " %s\n",
|
||||||
"macaddr bssid chan rssi rate flag wep essid");
|
"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) {
|
TAILQ_FOREACH(se, &st->st_entry, se_list) {
|
||||||
ieee80211_ies_expand(&se->base.se_ies);
|
ieee80211_ies_expand(&se->base.se_ies);
|
||||||
if (match_bss(vap, ss, se, debug) == 0) {
|
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;
|
selbs = se;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
|
|
||||||
return selbs;
|
return selbs;
|
||||||
}
|
}
|
||||||
@@ -1258,11 +1258,11 @@ sta_lookup(struct sta_table *st, const uint8_t macaddr[IEEE80211_ADDR_LEN])
|
|||||||
struct sta_entry *se;
|
struct sta_entry *se;
|
||||||
int hash = STA_HASH(macaddr);
|
int hash = STA_HASH(macaddr);
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
|
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
|
||||||
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
|
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
|
||||||
break;
|
break;
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
|
|
||||||
return se; /* NB: unlocked */
|
return se; /* NB: unlocked */
|
||||||
}
|
}
|
||||||
@@ -1361,7 +1361,7 @@ sta_age(struct ieee80211_scan_state *ss)
|
|||||||
KASSERT(vap->iv_opmode == IEEE80211_M_STA,
|
KASSERT(vap->iv_opmode == IEEE80211_M_STA,
|
||||||
("wrong mode %u", vap->iv_opmode));
|
("wrong mode %u", vap->iv_opmode));
|
||||||
if (vap->iv_roaming == IEEE80211_ROAMING_AUTO &&
|
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)
|
vap->iv_state >= IEEE80211_S_RUN)
|
||||||
/* XXX vap is implicit */
|
/* XXX vap is implicit */
|
||||||
sta_roam_check(ss, vap);
|
sta_roam_check(ss, vap);
|
||||||
@@ -1382,18 +1382,18 @@ sta_iterate(struct ieee80211_scan_state *ss,
|
|||||||
mtx_lock(&st->st_scanlock);
|
mtx_lock(&st->st_scanlock);
|
||||||
gen = st->st_scaniter++;
|
gen = st->st_scaniter++;
|
||||||
restart:
|
restart:
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
TAILQ_FOREACH(se, &st->st_entry, se_list) {
|
TAILQ_FOREACH(se, &st->st_entry, se_list) {
|
||||||
if (se->se_scangen != gen) {
|
if (se->se_scangen != gen) {
|
||||||
se->se_scangen = gen;
|
se->se_scangen = gen;
|
||||||
/* update public state */
|
/* update public state */
|
||||||
se->base.se_age = ticks - se->se_lastupdate;
|
se->base.se_age = ticks - se->se_lastupdate;
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
(*f)(arg, &se->base);
|
(*f)(arg, &se->base);
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
|
|
||||||
mtx_unlock(&st->st_scanlock);
|
mtx_unlock(&st->st_scanlock);
|
||||||
}
|
}
|
||||||
@@ -1509,7 +1509,7 @@ adhoc_pick_channel(struct ieee80211_scan_state *ss, int flags)
|
|||||||
bestchan = NULL;
|
bestchan = NULL;
|
||||||
bestrssi = -1;
|
bestrssi = -1;
|
||||||
|
|
||||||
mtx_lock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_LOCK(st);
|
||||||
for (i = 0; i < ss->ss_last; i++) {
|
for (i = 0; i < ss->ss_last; i++) {
|
||||||
c = ss->ss_chans[i];
|
c = ss->ss_chans[i];
|
||||||
/* never consider a channel with radar */
|
/* 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)
|
if (bestchan == NULL || maxrssi < bestrssi)
|
||||||
bestchan = c;
|
bestchan = c;
|
||||||
}
|
}
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
|
|
||||||
return bestchan;
|
return bestchan;
|
||||||
}
|
}
|
||||||
@@ -1637,7 +1637,7 @@ adhoc_age(struct ieee80211_scan_state *ss)
|
|||||||
struct sta_table *st = ss->ss_priv;
|
struct sta_table *st = ss->ss_priv;
|
||||||
struct sta_entry *se, *next;
|
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) {
|
TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) {
|
||||||
if (se->se_notseen > STA_PURGE_SCANS) {
|
if (se->se_notseen > STA_PURGE_SCANS) {
|
||||||
TAILQ_REMOVE(&st->st_entry, se, se_list);
|
TAILQ_REMOVE(&st->st_entry, se, se_list);
|
||||||
@@ -1646,7 +1646,7 @@ adhoc_age(struct ieee80211_scan_state *ss)
|
|||||||
free(se, M_80211_SCAN);
|
free(se, M_80211_SCAN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mtx_unlock(&st->st_lock);
|
IEEE80211_SCAN_TABLE_UNLOCK(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ieee80211_scanner adhoc_default = {
|
static const struct ieee80211_scanner adhoc_default = {
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||||
#include <net80211/ieee80211_superg.h>
|
#include <net80211/ieee80211_superg.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <net80211/ieee80211_ratectl.h>
|
||||||
|
|
||||||
#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
|
#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);
|
vap->iv_bss->ni_essid, vap->iv_bss->ni_esslen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callout_stop(&vap->iv_swbmiss);
|
||||||
vap->iv_bmiss_count = 0;
|
vap->iv_bmiss_count = 0;
|
||||||
vap->iv_stats.is_beacon_miss++;
|
vap->iv_stats.is_beacon_miss++;
|
||||||
if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) {
|
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_frame *wh;
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
struct ether_header *eh;
|
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 dir, type, subtype, qos;
|
||||||
uint8_t *bssid;
|
uint8_t *bssid;
|
||||||
uint16_t rxseq;
|
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"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
ni->ni_inact = ni->ni_inact_reload;
|
ni->ni_inact = ni->ni_inact_reload;
|
||||||
|
|
||||||
need_tap = 1; /* mbuf need to be tapped. */
|
|
||||||
type = -1; /* undefined */
|
type = -1; /* undefined */
|
||||||
|
|
||||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
|
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);
|
IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
|
||||||
ni->ni_noise = nf;
|
ni->ni_noise = nf;
|
||||||
if (HAS_SEQ(type)) {
|
if (HAS_SEQ(type) && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
|
||||||
uint8_t tid = ieee80211_gettid(wh);
|
uint8_t tid = ieee80211_gettid(wh);
|
||||||
if (IEEE80211_QOS_HAS_SEQ(wh) &&
|
if (IEEE80211_QOS_HAS_SEQ(wh) &&
|
||||||
TID_TO_WME_AC(tid) >= WME_AC_VI)
|
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 */
|
/* copy to listener after decrypt */
|
||||||
if (ieee80211_radiotap_active_vap(vap))
|
if (ieee80211_radiotap_active_vap(vap))
|
||||||
ieee80211_radiotap_tx(vap, m);
|
ieee80211_radiotap_rx(vap, m);
|
||||||
need_tap = 0;
|
need_tap = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1595,6 +1597,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
|
|||||||
IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
|
IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
|
||||||
ieee80211_setup_basic_htrates(ni, htinfo);
|
ieee80211_setup_basic_htrates(ni, htinfo);
|
||||||
ieee80211_node_setuptxparms(ni);
|
ieee80211_node_setuptxparms(ni);
|
||||||
|
ieee80211_ratectl_node_init(ni);
|
||||||
} else {
|
} else {
|
||||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||||
if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_ATH))
|
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",
|
"beacon miss, mode %u state %s\n",
|
||||||
vap->iv_opmode, ieee80211_state_name[vap->iv_state]);
|
vap->iv_opmode, ieee80211_state_name[vap->iv_state]);
|
||||||
|
|
||||||
|
callout_stop(&vap->iv_swbmiss);
|
||||||
|
|
||||||
if (ts->tdma_peer != NULL) { /* XXX? can this be null? */
|
if (ts->tdma_peer != NULL) { /* XXX? can this be null? */
|
||||||
ieee80211_notify_node_leave(vap->iv_bss);
|
ieee80211_notify_node_leave(vap->iv_bss);
|
||||||
ts->tdma_peer = NULL;
|
ts->tdma_peer = NULL;
|
||||||
|
|||||||
@@ -33,11 +33,11 @@
|
|||||||
* Definitions for IEEE 802.11 drivers.
|
* Definitions for IEEE 802.11 drivers.
|
||||||
*/
|
*/
|
||||||
/* NB: portability glue must go first */
|
/* NB: portability glue must go first */
|
||||||
#ifdef __NetBSD__
|
#if defined(__NetBSD__)
|
||||||
#include <net80211/ieee80211_netbsd.h>
|
#include <net80211/ieee80211_netbsd.h>
|
||||||
#elif __FreeBSD__
|
#elif defined(__FreeBSD__)
|
||||||
#include <net80211/ieee80211_freebsd.h>
|
#include <net80211/ieee80211_freebsd.h>
|
||||||
#elif __linux__
|
#elif defined(__linux__)
|
||||||
#include <net80211/ieee80211_linux.h>
|
#include <net80211/ieee80211_linux.h>
|
||||||
#elif __HAIKU__
|
#elif __HAIKU__
|
||||||
#include <net80211/ieee80211_haiku.h>
|
#include <net80211/ieee80211_haiku.h>
|
||||||
@@ -436,6 +436,9 @@ struct ieee80211vap {
|
|||||||
const struct ieee80211_aclator *iv_acl; /* acl glue */
|
const struct ieee80211_aclator *iv_acl; /* acl glue */
|
||||||
void *iv_as; /* private aclator state */
|
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_tdma_state *iv_tdma; /* tdma state */
|
||||||
struct ieee80211_mesh_state *iv_mesh; /* MBSS state */
|
struct ieee80211_mesh_state *iv_mesh; /* MBSS state */
|
||||||
struct ieee80211_hwmp_state *iv_hwmp; /* HWMP state */
|
struct ieee80211_hwmp_state *iv_hwmp; /* HWMP state */
|
||||||
@@ -471,7 +474,7 @@ struct ieee80211vap {
|
|||||||
/* 802.3 output method for raw frame xmit */
|
/* 802.3 output method for raw frame xmit */
|
||||||
int (*iv_output)(struct ifnet *, struct mbuf *,
|
int (*iv_output)(struct ifnet *, struct mbuf *,
|
||||||
struct sockaddr *, struct route *);
|
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)
|
#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 */
|
/* NB: immutable: should be set only when creating a vap */
|
||||||
#define IEEE80211_FEXT_WDSLEGACY 0x00010000 /* CONF: legacy WDS operation */
|
#define IEEE80211_FEXT_WDSLEGACY 0x00010000 /* CONF: legacy WDS operation */
|
||||||
#define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/
|
#define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/
|
||||||
|
#define IEEE80211_FEXT_UNIQMAC 0x00040000 /* CONF: user or computed mac */
|
||||||
|
|
||||||
#define IEEE80211_FEXT_BITS \
|
#define IEEE80211_FEXT_BITS \
|
||||||
"\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \
|
"\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \
|
||||||
"\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \
|
"\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \
|
||||||
"\20BPF\21WDSLEGACY\22PROBECHAN"
|
"\20BPF\21WDSLEGACY\22PROBECHAN\23UNIQMAC"
|
||||||
|
|
||||||
/* ic_flags_ht/iv_flags_ht */
|
/* ic_flags_ht/iv_flags_ht */
|
||||||
#define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */
|
#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)) \
|
if (ieee80211_msg(_vap, _m)) \
|
||||||
ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__); \
|
ieee80211_note_frame(_vap, _wh, _fmt, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
void ieee80211_note(struct ieee80211vap *, const char *, ...);
|
void ieee80211_note(const struct ieee80211vap *, const char *, ...);
|
||||||
void ieee80211_note_mac(struct ieee80211vap *,
|
void ieee80211_note_mac(const struct ieee80211vap *,
|
||||||
const uint8_t mac[IEEE80211_ADDR_LEN], const char *, ...);
|
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 *, ...);
|
const struct ieee80211_frame *, const char *, ...);
|
||||||
#define ieee80211_msg_debug(_vap) \
|
#define ieee80211_msg_debug(_vap) \
|
||||||
((_vap)->iv_debug & IEEE80211_MSG_DEBUG)
|
((_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__);\
|
ieee80211_discard_mac(_vap, _mac, _type, _fmt, __VA_ARGS__);\
|
||||||
} while (0)
|
} 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, ...);
|
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, ...);
|
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 uint8_t mac[IEEE80211_ADDR_LEN], const char *type,
|
||||||
const char *fmt, ...);
|
const char *fmt, ...);
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
|
|||||||
struct ieee80211_frame *wh;
|
struct ieee80211_frame *wh;
|
||||||
struct ieee80211_key *key;
|
struct ieee80211_key *key;
|
||||||
struct ether_header *eh;
|
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 dir, type, subtype, qos;
|
||||||
uint16_t rxseq;
|
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"));
|
KASSERT(ni != NULL, ("null node"));
|
||||||
|
|
||||||
need_tap = 1; /* mbuf need to be tapped. */
|
|
||||||
type = -1; /* undefined */
|
type = -1; /* undefined */
|
||||||
|
|
||||||
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
|
if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user