svn commit: r280084 - head/sys/dev/wpi
Adrian Chadd
adrian at FreeBSD.org
Sun Mar 15 20:51:58 UTC 2015
Author: adrian
Date: Sun Mar 15 20:51:56 2015
New Revision: 280084
URL: https://svnweb.freebsd.org/changeset/base/280084
Log:
Use ieee80211_beacon_update() for dynamic beacon contents.
PR: kern/197143
Submitted by: Andriy Voskoboinyk <s3erios at gmail.com>
Modified:
head/sys/dev/wpi/if_wpi.c
head/sys/dev/wpi/if_wpivar.h
Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c Sun Mar 15 20:51:06 2015 (r280083)
+++ head/sys/dev/wpi/if_wpi.c Sun Mar 15 20:51:56 2015 (r280084)
@@ -227,8 +227,9 @@ static uint16_t wpi_get_passive_dwell_ti
struct ieee80211_channel *);
static int wpi_scan(struct wpi_softc *, struct ieee80211_channel *);
static int wpi_auth(struct wpi_softc *, struct ieee80211vap *);
-static void wpi_update_beacon(struct ieee80211vap *, int);
+static int wpi_config_beacon(struct wpi_vap *);
static int wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
+static void wpi_update_beacon(struct ieee80211vap *, int);
static void wpi_newassoc(struct ieee80211_node *, int);
static int wpi_run(struct wpi_softc *, struct ieee80211vap *);
static int wpi_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
@@ -639,10 +640,17 @@ static void
wpi_vap_delete(struct ieee80211vap *vap)
{
struct wpi_vap *wvp = WPI_VAP(vap);
+ struct wpi_buf *bcn = &wvp->wv_bcbuf;
+ enum ieee80211_opmode opmode = vap->iv_opmode;
ieee80211_ratectl_deinit(vap);
ieee80211_vap_detach(vap);
+ if (opmode == IEEE80211_M_IBSS) {
+ if (bcn->m != NULL)
+ m_freem(bcn->m);
+ }
+
free(wvp, M_80211_VAP);
}
@@ -3945,51 +3953,127 @@ wpi_auth(struct wpi_softc *sc, struct ie
}
static int
+wpi_config_beacon(struct wpi_vap *wvp)
+{
+ struct ieee80211com *ic = wvp->vap.iv_ic;
+ struct ieee80211_beacon_offsets *bo = &wvp->wv_boff;
+ struct wpi_buf *bcn = &wvp->wv_bcbuf;
+ struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data;
+ struct ieee80211_tim_ie *tie;
+ struct mbuf *m;
+ uint8_t *ptr;
+ int error;
+
+ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
+
+ WPI_LOCK_ASSERT(sc);
+
+ cmd->len = htole16(bcn->m->m_pkthdr.len);
+ cmd->plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ?
+ wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1];
+
+ /* XXX seems to be unused */
+ if (*(bo->bo_tim) == IEEE80211_ELEMID_TIM) {
+ tie = (struct ieee80211_tim_ie *) bo->bo_tim;
+ ptr = mtod(bcn->m, uint8_t *);
+
+ cmd->tim = htole16(bo->bo_tim - ptr);
+ cmd->timsz = tie->tim_len;
+ }
+
+ /* Necessary for recursion in ieee80211_beacon_update(). */
+ m = bcn->m;
+ bcn->m = m_dup(m, M_NOWAIT);
+ if (bcn->m == NULL) {
+ device_printf(sc->sc_dev,
+ "%s: could not copy beacon frame\n", __func__);
+ error = ENOMEM;
+ goto end;
+ }
+
+ if ((error = wpi_cmd2(sc, bcn)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not update beacon frame, error %d", __func__,
+ error);
+ }
+
+ /* Restore mbuf. */
+end: bcn->m = m;
+
+ return error;
+}
+
+static int
wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct wpi_vap *wvp = WPI_VAP(ni->ni_vap);
struct wpi_buf *bcn = &wvp->wv_bcbuf;
- struct ieee80211_beacon_offsets bo;
- struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data;
+ struct ieee80211_beacon_offsets *bo = &wvp->wv_boff;
struct mbuf *m;
+ int error;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
if (ni->ni_chan == IEEE80211_CHAN_ANYC)
return EINVAL;
- m = ieee80211_beacon_alloc(ni, &bo);
+ m = ieee80211_beacon_alloc(ni, bo);
if (m == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
return ENOMEM;
}
- cmd->len = htole16(m->m_pkthdr.len);
- cmd->plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ?
- wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1];
+ if (bcn->m != NULL)
+ m_freem(bcn->m);
- /* NB: m will be freed in wpi_cmd_done() */
bcn->m = m;
- return wpi_cmd2(sc, bcn);
+ error = wpi_config_beacon(wvp);
+
+ return error;
}
static void
wpi_update_beacon(struct ieee80211vap *vap, int item)
{
struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct wpi_vap *wvp = WPI_VAP(vap);
+ struct wpi_buf *bcn = &wvp->wv_bcbuf;
+ struct ieee80211_beacon_offsets *bo = &wvp->wv_boff;
struct ieee80211_node *ni = vap->iv_bss;
- int error;
+ int mcast = 0;
+
+ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
WPI_LOCK(sc);
- if ((error = wpi_setup_beacon(sc, ni)) != 0) {
- device_printf(sc->sc_dev,
- "%s: could not update beacon frame, error %d", __func__,
- error);
+ if (bcn->m == NULL) {
+ bcn->m = ieee80211_beacon_alloc(ni, bo);
+ if (bcn->m == NULL) {
+ device_printf(sc->sc_dev,
+ "%s: could not allocate beacon frame\n", __func__);
+ WPI_UNLOCK(sc);
+
+ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR,
+ __func__);
+
+ return;
+ }
}
WPI_UNLOCK(sc);
+
+ if (item == IEEE80211_BEACON_TIM)
+ mcast = 1; /* TODO */
+
+ setbit(bo->bo_flags, item);
+ ieee80211_beacon_update(ni, bo, bcn->m, mcast);
+
+ WPI_LOCK(sc);
+ wpi_config_beacon(wvp);
+ WPI_UNLOCK(sc);
+
+ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
}
static void
Modified: head/sys/dev/wpi/if_wpivar.h
==============================================================================
--- head/sys/dev/wpi/if_wpivar.h Sun Mar 15 20:51:06 2015 (r280083)
+++ head/sys/dev/wpi/if_wpivar.h Sun Mar 15 20:51:56 2015 (r280084)
@@ -121,11 +121,13 @@ struct wpi_buf {
};
struct wpi_vap {
- struct ieee80211vap vap;
- struct wpi_buf wv_bcbuf;
+ struct ieee80211vap vap;
- int (*newstate)(struct ieee80211vap *,
- enum ieee80211_state, int);
+ struct wpi_buf wv_bcbuf;
+ struct ieee80211_beacon_offsets wv_boff;
+
+ int (*newstate)(struct ieee80211vap *,
+ enum ieee80211_state, int);
};
#define WPI_VAP(vap) ((struct wpi_vap *)(vap))
More information about the svn-src-head
mailing list