Index: sys/dev/usb/wlan/if_rum.c =================================================================== --- sys/dev/usb/wlan/if_rum.c +++ sys/dev/usb/wlan/if_rum.c @@ -218,7 +218,9 @@ static void rum_stop(struct rum_softc *); static void rum_load_microcode(struct rum_softc *, const uint8_t *, size_t); -static int rum_prepare_beacon(struct rum_softc *, +static int rum_set_beacon(struct rum_softc *, + struct ieee80211vap *); +static int rum_alloc_beacon(struct rum_softc *, struct ieee80211vap *); static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); @@ -620,6 +622,7 @@ struct rum_vap *rvp = RUM_VAP(vap); struct ieee80211com *ic = vap->iv_ic; + m_freem(rvp->bcn_mbuf); usb_callout_drain(&rvp->ratectl_ch); ieee80211_draintask(ic, &rvp->ratectl_task); ieee80211_ratectl_deinit(vap); @@ -731,7 +734,7 @@ if (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS) { - if ((ret = rum_prepare_beacon(sc, vap)) != 0) + if ((ret = rum_alloc_beacon(sc, vap)) != 0) goto run_fail; } @@ -2147,42 +2150,59 @@ } static int -rum_prepare_beacon(struct rum_softc *sc, struct ieee80211vap *vap) +rum_set_beacon(struct rum_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; + struct rum_vap *rvp = RUM_VAP(vap); + struct mbuf *m = rvp->bcn_mbuf; const struct ieee80211_txparam *tp; struct rum_tx_desc desc; - struct mbuf *m0; - int ret = 0; - if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC) + RUM_LOCK_ASSERT(sc); + + if (m == NULL) return EINVAL; if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) return EINVAL; - m0 = ieee80211_beacon_alloc(vap->iv_bss, &RUM_VAP(vap)->bo); - if (m0 == NULL) - return ENOMEM; - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)]; rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ, - m0->m_pkthdr.len, tp->mgmtrate); + m->m_pkthdr.len, tp->mgmtrate); - /* copy the first 24 bytes of Tx descriptor into NIC memory */ - if ((ret = rum_write_multi(sc, RT2573_HW_BEACON_BASE0, - (uint8_t *)&desc, 24)) != 0) { - ret = EIO; - goto end; - } + /* copy the Tx descriptor into NIC memory */ + if (rum_write_multi(sc, RT2573_HW_BCN_BASE(0), (uint8_t *)&desc, + RT2573_TX_DESC_SIZE) != 0) + return EIO; /* copy beacon header and payload into NIC memory */ - if ((ret = rum_write_multi(sc, RT2573_HW_BEACON_BASE0 + 24, mtod(m0, uint8_t *), - m0->m_pkthdr.len)) != 0) - ret = EIO; + if (rum_write_multi(sc, RT2573_HW_BCN_BASE(0) + RT2573_TX_DESC_SIZE, + mtod(m, uint8_t *), m->m_pkthdr.len) != 0) + return EIO; + + return 0; +} -end: m_freem(m0); +static int +rum_alloc_beacon(struct rum_softc *sc, struct ieee80211vap *vap) +{ + struct rum_vap *rvp = RUM_VAP(vap); + struct ieee80211_node *ni = vap->iv_bss; + struct ieee80211_beacon_offsets *bo = &rvp->bo; + struct mbuf *m; - return ret; + if (ni->ni_chan == IEEE80211_CHAN_ANYC) + return EINVAL; + + m = ieee80211_beacon_alloc(ni, bo); + if (m == NULL) + return ENOMEM; + + if (rvp->bcn_mbuf != NULL) + m_freem(rvp->bcn_mbuf); + + rvp->bcn_mbuf = m; + + return (rum_set_beacon(sc, vap)); } static int Index: sys/dev/usb/wlan/if_rumreg.h =================================================================== --- sys/dev/usb/wlan/if_rumreg.h +++ sys/dev/usb/wlan/if_rumreg.h @@ -40,7 +40,7 @@ #define RT2573_CWMIN_CSR 0x0404 #define RT2573_CWMAX_CSR 0x0408 #define RT2573_MCU_CODE_BASE 0x0800 -#define RT2573_HW_BEACON_BASE0 0x2400 +#define RT2573_HW_BCN_BASE(id) (0x2400 + (id) * 0x100) #define RT2573_MAC_CSR0 0x3000 #define RT2573_MAC_CSR1 0x3004 #define RT2573_MAC_CSR2 0x3008 Index: sys/dev/usb/wlan/if_rumvar.h =================================================================== --- sys/dev/usb/wlan/if_rumvar.h +++ sys/dev/usb/wlan/if_rumvar.h @@ -73,7 +73,10 @@ struct rum_vap { struct ieee80211vap vap; + + struct mbuf *bcn_mbuf; struct ieee80211_beacon_offsets bo; + struct usb_callout ratectl_ch; struct task ratectl_task;