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 <s3er...@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))
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to