Change KPI of how device drivers that provide wireless connectivity interact

with the net80211 stack.

Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.

Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:

- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
  the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
  driver about any changes: number of wlan(4) interfaces, number of them
  in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
  driver experiences errors and can not attribute them to any specific
  interface, driver updates ic_oerrors or ic_ierrors counters.

Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
  now provided by net.wlan.devices sysctl.

Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to Olivier Cochard, gjb@, mmoll@,
op@ and lev@, who also participated in testing. Details here:

https://wiki.freebsd.org/projects/ifnet/net80211

Still, drivers: ndis, wtap, mwl, ipw, bwn, wi, upgt, uath were not
tested. Changes to mwl, ipw, bwn, wi, upgt are trivial and chances
of problems are low. The wtap wasn't compilable even before this change.
But the ndis driver is complex, and it is likely to be broken with this
commit. Help with testing and debugging it is appreciated.

Differential Revision:	D2655, D2740
Sponsored by:	Nginx, Inc.
Sponsored by:	Netflix
This commit is contained in:
Gleb Smirnoff 2015-08-07 11:43:14 +00:00
parent 84fe889c63
commit 79d2c5e857
81 changed files with 4045 additions and 6164 deletions

View File

@ -1249,6 +1249,70 @@ ifscript_down()
fi
}
# wlan_up
# Create IEEE802.3 interfaces.
#
wlan_up()
{
local _list _iflist wlan parent ifn
_list=
_iflist=$*
for wlan in `set | egrep ^wlans_[a-z]+[0-9]+=[a-z]+[0-9]+`; do
# Parse wlans_$parent=$ifn
wlan=`echo $wlan | sed -E 's/wlans_([a-z]+[0-9]+)=([a-z]+[0-9]+)/\1:\2/'`
OIFS=$IFS; IFS=:; set -- $wlan; parent=$1; ifn=$2; IFS=$OIFS
case $_iflist in
""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn) ;;
*) continue ;;
esac
# Skip if ${ifn} already exists.
if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
continue
fi
${IFCONFIG_CMD} ${ifn} create wlandev ${parent}
if [ $? -eq 0 ]; then
_list="$_list $ifn"
fi
done
if [ -n "${_list# }" ]; then
echo "Created wlan(4) interfaces: ${_list# }."
fi
debug "Created wlan(4)s: ${_list# }"
}
# wlan_down
# Destroy IEEE802.3 interfaces.
#
wlan_down()
{
local _list _iflist wlan parent ifn
_list=
_iflist=$*
for wlan in `set | egrep ^wlans_[a-z]+[0-9]+=[a-z]+[0-9]+`; do
# Parse wlans_$parent=$ifn
wlan=`echo $wlan | sed -E 's/wlans_([a-z]+[0-9]+)=([a-z]+[0-9]+)/\1:\2/'`
OIFS=$IFS; IFS=:; set -- $wlan; parent=$1; ifn=$2; IFS=$OIFS
case $_iflist in
""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn) ;;
*) continue ;;
esac
# Skip if ${ifn} doesn't exists.
if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
continue
fi
${IFCONFIG_CMD} -n ${ifn} destroy
if [ $? -eq 0 ]; then
_list="$_list $ifn"
fi
done
if [ -n "${_list# }" ]; then
echo "Destroyed wlan(4) interfaces: ${_list# }."
fi
debug "Destroyed wlan(4)s: ${_list# }"
}
# clone_up
# Create cloneable interfaces.
#
@ -1398,6 +1462,9 @@ clone_down()
# Create and configure child interfaces. Return 0 if child
# interfaces are created.
#
# XXXGL: the wlan code in this functions is superseded by wlan_up(),
# and will go away soon.
#
childif_create()
{
local cfg child child_vlans child_wlans create_args debug_flags ifn i

View File

@ -37,6 +37,8 @@ name="netif"
rcvar="${name}_enable"
start_cmd="netif_start"
stop_cmd="netif_stop"
wlanup_cmd="wlan_up"
wlandown_cmd="wlan_down"
cloneup_cmd="clone_up"
clonedown_cmd="clone_down"
clear_cmd="doclear"
@ -65,6 +67,9 @@ netif_start()
trap : 2
fi
# Create IEEE802.3 interface
wlan_up $cmdifn
# Create cloned interfaces
clone_up $cmdifn
@ -91,12 +96,14 @@ netif_start()
netif_stop()
{
_clone_down=1
_wlan_down=1
netif_stop0 $*
}
doclear()
{
_clone_down=
_wlan_down=
netif_stop0 $*
}
@ -111,6 +118,11 @@ netif_stop0()
# Deconfigure the interface(s)
netif_common ifn_stop $cmdifn
# Destroy wlan interfaces
if [ -n "$_wlan_down" ]; then
wlan_down $cmdifn
fi
# Destroy cloned interfaces
if [ -n "$_clone_down" ]; then
clone_down $cmdifn

View File

@ -488,8 +488,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
#define RATE(ix) (DOT11RATE(ix) / 2)
struct sample_node *sn = ATH_NODE_SAMPLE(an);
struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const HAL_RATE_TABLE *rt = sc->sc_currates;
const int size_bin = size_to_bin(frameLen);
int rix, mrr, best_rix, change_rates;
@ -856,8 +855,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
const struct ath_rc_series *rc, const struct ath_tx_status *ts,
int frame_size, int nframes, int nbad)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct sample_node *sn = ATH_NODE_SAMPLE(an);
int final_rix, short_tries, long_tries;
const HAL_RATE_TABLE *rt = sc->sc_currates;
@ -1303,8 +1301,7 @@ static int
ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int error, v;
v = 0;

View File

@ -134,8 +134,7 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
int long_retries, int is_ht40)
{
const HAL_RATE_TABLE *rt = sc->sc_currates;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int rts, cts;
unsigned t_slot = 20;

File diff suppressed because it is too large Load Diff

View File

@ -134,7 +134,7 @@ int
ath_beaconq_config(struct ath_softc *sc)
{
#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1)
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_TXQ_INFO qi;
@ -464,7 +464,7 @@ ath_beacon_proc(void *arg, int pending)
}
if (sc->sc_stagbeacons) { /* staggered beacons */
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tsftu;
tsftu = ath_hal_gettsf32(ah) >> 10;
@ -917,7 +917,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
#define FUDGE 2
struct ath_hal *ah = sc->sc_ah;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
u_int32_t nexttbtt, intval, tsftu;
u_int32_t nexttbtt_u8, intval_u8;

View File

@ -91,9 +91,7 @@ enum {
extern uint64_t ath_debug;
#define IFF_DUMPPKTS(sc, m) \
((sc->sc_debug & (m)) || \
(sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
#define IFF_DUMPPKTS(sc, m) ((sc->sc_debug & (m))
#define DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
@ -112,8 +110,7 @@ extern void ath_printtxstatbuf(struct ath_softc *sc, const struct ath_buf *bf,
#else /* ATH_DEBUG */
#define ATH_KTR(_sc, _km, _kf, ...) do { } while (0)
#define IFF_DUMPPKTS(sc, m) \
((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
#define IFF_DUMPPKTS(sc, m) (0)
#define DPRINTF(sc, m, fmt, ...) do { \
(void) sc; \
} while (0)

View File

@ -425,7 +425,7 @@ int
ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
struct ath_softc *sc = vap->iv_ic->ic_softc;
/*
* Group key allocation must be handled specially for
@ -493,7 +493,7 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
int
ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
struct ath_softc *sc = vap->iv_ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const struct ieee80211_cipher *cip = k->wk_cipher;
u_int keyix = k->wk_keyix;
@ -538,7 +538,7 @@ int
ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
const u_int8_t mac[IEEE80211_ADDR_LEN])
{
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
struct ath_softc *sc = vap->iv_ic->ic_softc;
return ath_keyset(sc, vap, k, vap->iv_bss);
}

View File

@ -65,7 +65,7 @@ extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf);
extern void ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf);
extern void ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf);
extern int ath_reset(struct ifnet *, ATH_RESET_TYPE);
extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE);
extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf,
int fail);
extern void ath_tx_update_ratectrl(struct ath_softc *sc,

View File

@ -154,8 +154,7 @@ __FBSDID("$FreeBSD$");
u_int32_t
ath_calcrxfilter(struct ath_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
u_int32_t rfilt;
rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
@ -164,7 +163,7 @@ ath_calcrxfilter(struct ath_softc *sc)
if (ic->ic_opmode != IEEE80211_M_STA)
rfilt |= HAL_RX_FILTER_PROBEREQ;
/* XXX ic->ic_monvaps != 0? */
if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0)
rfilt |= HAL_RX_FILTER_PROM;
/*
@ -330,7 +329,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
struct ath_softc *sc = vap->iv_ic->ic_softc;
uint64_t tsf_beacon_old, tsf_beacon;
uint64_t nexttbtt;
int64_t tsf_delta;
@ -463,10 +462,9 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
static void
ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m,
ath_rx_tap_vendor(struct ath_softc *sc, struct mbuf *m,
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
{
struct ath_softc *sc = ifp->if_softc;
/* Fill in the extension bitmap */
sc->sc_rx_th.wr_ext_bitmap = htole32(1 << ATH_RADIOTAP_VENDOR_HEADER);
@ -529,14 +527,13 @@ ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m,
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
static void
ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
{
#define CHAN_HT20 htole32(IEEE80211_CHAN_HT20)
#define CHAN_HT40U htole32(IEEE80211_CHAN_HT40U)
#define CHAN_HT40D htole32(IEEE80211_CHAN_HT40D)
#define CHAN_HT (CHAN_HT20|CHAN_HT40U|CHAN_HT40D)
struct ath_softc *sc = ifp->if_softc;
const HAL_RATE_TABLE *rt;
uint8_t rix;
@ -560,7 +557,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
if ((rs->rs_flags & HAL_RX_2040) == 0)
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
@ -617,8 +614,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
{
uint64_t rstamp;
int len, type;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
int is_good = 0;
struct ath_rx_edma *re = &sc->sc_rxedma[qtype];
@ -704,7 +700,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
rs->rs_keyix-32 : rs->rs_keyix);
}
}
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
rx_error:
/*
* Cleanup any pending partial frame.
@ -724,9 +720,9 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
/* NB: bpf needs the mbuf length setup */
len = rs->rs_datalen;
m->m_pkthdr.len = m->m_len = len;
ath_rx_tap(ifp, m, rs, rstamp, nf);
ath_rx_tap(sc, m, rs, rstamp, nf);
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
ieee80211_radiotap_rx_all(ic, m);
}
@ -749,7 +745,6 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
sc->sc_stats.ast_rx_toobig++;
m_freem(re->m_rxpending);
}
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = len;
re->m_rxpending = m;
m = NULL;
@ -766,10 +761,8 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
re->m_rxpending = NULL;
} else {
/*
* Normal single-descriptor receive; setup
* the rcvif and packet length.
* Normal single-descriptor receive; setup packet length.
*/
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = len;
}
@ -830,7 +823,6 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
rs->rs_antenna |= 0x4;
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
/*
@ -841,9 +833,9 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
* noise setting is filled in above.
*/
if (ieee80211_radiotap_active(ic)) {
ath_rx_tap(ifp, m, rs, rstamp, nf);
ath_rx_tap(sc, m, rs, rstamp, nf);
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
}
@ -991,10 +983,9 @@ ath_rx_proc(struct ath_softc *sc, int resched)
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
struct ath_buf *bf;
struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
#ifdef IEEE80211_SUPPORT_SUPERG
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
#endif
struct ath_desc *ds;
struct ath_rx_status *rs;
@ -1189,15 +1180,10 @@ ath_rx_proc(struct ath_softc *sc, int resched)
ATH_PCU_UNLOCK(sc);
}
/* XXX check this inside of IF_LOCK? */
if (resched && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
if (resched)
ieee80211_ff_age_all(ic, 100);
#endif
if (!IFQ_IS_EMPTY(&ifp->if_snd))
ath_tx_kick(sc);
}
#undef PA2DESC
/*
* Put the hardware to sleep again if we're done with it.
@ -1219,7 +1205,7 @@ ath_rx_proc(struct ath_softc *sc, int resched)
sc->sc_rxproc_cnt--;
ATH_PCU_UNLOCK(sc);
}
#undef PA2DESC
#undef ATH_RX_MAX
/*

View File

@ -579,9 +579,8 @@ static void
ath_edma_recv_tasklet(void *arg, int npending)
{
struct ath_softc *sc = (struct ath_softc *) arg;
struct ifnet *ifp = sc->sc_ifp;
#ifdef IEEE80211_SUPPORT_SUPERG
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
#endif
DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n",
@ -617,14 +616,9 @@ ath_edma_recv_tasklet(void *arg, int npending)
ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
/* XXX inside IF_LOCK ? */
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_ff_age_all(ic, 100);
ieee80211_ff_age_all(ic, 100);
#endif
if (! IFQ_IS_EMPTY(&ifp->if_snd))
ath_tx_kick(sc);
}
if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);

View File

@ -367,7 +367,6 @@ static int
ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
struct ifnet *ifp = sc->sc_ifp;
u_int32_t scale;
int error;
@ -381,8 +380,7 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
goto finish;
error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
(ifp->if_drv_flags & IFF_DRV_RUNNING) ?
ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
(sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0;
finish:
ATH_LOCK(sc);
@ -422,7 +420,6 @@ static int
ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
u_int rfkill;
int error;
@ -444,8 +441,7 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
error = EINVAL;
goto finish;
}
error = (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
ath_reset(ifp, ATH_RESET_FULL) : 0;
error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0;
finish:
ATH_LOCK(sc);
@ -671,8 +667,8 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
* doesn't reset ANI related registers, so it'll leave
* things in an inconsistent state.
*/
if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
if (sc->sc_running)
ath_reset(sc, ATH_RESET_NOLOSS);
error = 0;

View File

@ -359,7 +359,7 @@ ath_tdma_update(struct ieee80211_node *ni,
#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;

View File

@ -1051,8 +1051,7 @@ ath_tx_calc_protection(struct ath_softc *sc, struct ath_buf *bf)
uint16_t flags;
int shortPreamble;
const HAL_RATE_TABLE *rt = sc->sc_currates;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
flags = bf->bf_state.bfs_txflags;
rix = bf->bf_state.bfs_rc[0].rix;
@ -1545,8 +1544,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
{
struct ieee80211vap *vap = ni->ni_vap;
struct ath_hal *ah = sc->sc_ah;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
int error, iswep, ismcast, isfrag, ismrr;
int keyix, hdrlen, pktlen, try0 = 0;
@ -2074,8 +2072,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
struct ath_buf *bf, struct mbuf *m0,
const struct ieee80211_bpf_params *params)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211vap *vap = ni->ni_vap;
int error, ismcast, ismrr;
@ -2340,8 +2337,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ath_softc *sc = ifp->if_softc;
struct ath_softc *sc = ic->ic_softc;
struct ath_buf *bf;
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
int error = 0;
@ -2364,10 +2360,9 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
ATH_TX_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__,
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ?
"!running" : "invalid");
if (!sc->sc_running || sc->sc_invalid) {
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, r/i: %d/%d",
__func__, sc->sc_running, sc->sc_invalid);
m_freem(m);
error = ENETDOWN;
goto bad;
@ -2424,7 +2419,6 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
}
}
sc->sc_wd_timer = 5;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
sc->sc_stats.ast_tx_raw++;
/*
@ -2473,7 +2467,6 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
badbad:
ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p",
m, params);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
sc->sc_stats.ast_tx_raw_fail++;
ieee80211_free_node(ni);
@ -5731,7 +5724,7 @@ int
ath_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int dialogtoken, int baparamset, int batimeout)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@ -5809,7 +5802,7 @@ int
ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status, int code, int batimeout)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@ -5856,7 +5849,7 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
void
ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@ -5991,7 +5984,7 @@ void
ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@ -6064,7 +6057,7 @@ void
ath_addba_response_timeout(struct ieee80211_node *ni,
struct ieee80211_tx_ampdu *tap)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];

View File

@ -537,7 +537,6 @@ ath_edma_dma_txteardown(struct ath_softc *sc)
static void
ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
{
struct ifnet *ifp = sc->sc_ifp;
int i;
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
@ -579,9 +578,6 @@ ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
/* XXX dump out the frames */
IF_LOCK(&ifp->if_snd);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
}
@ -834,12 +830,6 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
sc->sc_wd_timer = 0;
if (idx > 0) {
IF_LOCK(&sc->sc_ifp->if_snd);
sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
IF_UNLOCK(&sc->sc_ifp->if_snd);
}
/* Kick software scheduler */
/*
* XXX It's inefficient to do this if the FIFO queue is full,

View File

@ -555,8 +555,8 @@ struct ath_tx_methods {
};
struct ath_softc {
struct ifnet *sc_ifp; /* interface common */
struct ath_stats sc_stats; /* interface statistics */
struct ieee80211com sc_ic;
struct ath_stats sc_stats; /* device statistics */
struct ath_tx_aggr_stats sc_aggr_stats;
struct ath_intr_stats sc_intr_stats;
uint64_t sc_debug;
@ -650,7 +650,8 @@ struct ath_softc {
/*
* Second set of flags.
*/
u_int32_t sc_use_ent : 1,
u_int32_t sc_running : 1, /* initialized */
sc_use_ent : 1,
sc_rx_stbc : 1,
sc_tx_stbc : 1,
sc_hasenforcetxop : 1, /* support enforce TxOP */

View File

@ -832,11 +832,11 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
uint8_t fw_type)
{
const struct bwi_fwhdr *hdr;
struct ifnet *ifp = sc->sc_ifp;
if (fw->datasize < sizeof(*hdr)) {
if_printf(ifp, "invalid firmware (%s): invalid size %zu\n",
fw->name, fw->datasize);
device_printf(sc->sc_dev,
"invalid firmware (%s): invalid size %zu\n",
fw->name, fw->datasize);
return 0;
}
@ -847,25 +847,26 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
* Don't verify IV's size, it has different meaning
*/
if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
if_printf(ifp, "invalid firmware (%s): size mismatch, "
"fw %u, real %zu\n", fw->name,
be32toh(hdr->fw_size),
fw->datasize - sizeof(*hdr));
device_printf(sc->sc_dev,
"invalid firmware (%s): size mismatch, "
"fw %u, real %zu\n", fw->name,
be32toh(hdr->fw_size), fw->datasize - sizeof(*hdr));
return 0;
}
}
if (hdr->fw_type != fw_type) {
if_printf(ifp, "invalid firmware (%s): type mismatch, "
"fw \'%c\', target \'%c\'\n", fw->name,
hdr->fw_type, fw_type);
device_printf(sc->sc_dev,
"invalid firmware (%s): type mismatch, "
"fw \'%c\', target \'%c\'\n", fw->name,
hdr->fw_type, fw_type);
return 0;
}
if (hdr->fw_gen != BWI_FW_GEN_1) {
if_printf(ifp, "invalid firmware (%s): wrong generation, "
"fw %d, target %d\n", fw->name,
hdr->fw_gen, BWI_FW_GEN_1);
device_printf(sc->sc_dev,
"invalid firmware (%s): wrong generation, "
"fw %d, target %d\n", fw->name, hdr->fw_gen, BWI_FW_GEN_1);
return 0;
}
return 1;
@ -1002,7 +1003,6 @@ static int
bwi_mac_fw_load(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
const uint32_t *fw;
uint16_t fw_rev;
int fw_len, i;
@ -1057,7 +1057,8 @@ bwi_mac_fw_load(struct bwi_mac *mac)
DELAY(10);
}
if (i == NRETRY) {
if_printf(ifp, "firmware (ucode&pcm) loading timed out\n");
device_printf(sc->sc_dev,
"firmware (ucode&pcm) loading timed out\n");
return ETIMEDOUT;
}
@ -1067,12 +1068,14 @@ bwi_mac_fw_load(struct bwi_mac *mac)
fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
if (fw_rev > BWI_FW_VERSION3_REVMAX) {
if_printf(ifp, "firmware version 4 is not supported yet\n");
device_printf(sc->sc_dev,
"firmware version 4 is not supported yet\n");
return ENODEV;
}
if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
device_printf(sc->sc_dev,
"firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
return 0;
}
@ -1132,7 +1135,6 @@ static int
bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
const struct bwi_fwhdr *hdr;
const struct bwi_fw_iv *iv;
int n, i, iv_img_size;
@ -1155,7 +1157,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
int sz = 0;
if (iv_img_size < sizeof(iv->iv_ofs)) {
if_printf(ifp, "invalid IV image, ofs\n");
device_printf(sc->sc_dev, "invalid IV image, ofs\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_ofs);
@ -1165,7 +1167,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
if (ofs >= 0x1000) {
if_printf(ifp, "invalid ofs (0x%04x) "
device_printf(sc->sc_dev, "invalid ofs (0x%04x) "
"for %dth iv\n", ofs, i);
return EINVAL;
}
@ -1174,7 +1176,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
uint32_t val32;
if (iv_img_size < sizeof(iv->iv_val.val32)) {
if_printf(ifp, "invalid IV image, val32\n");
device_printf(sc->sc_dev,
"invalid IV image, val32\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_val.val32);
@ -1186,7 +1189,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
uint16_t val16;
if (iv_img_size < sizeof(iv->iv_val.val16)) {
if_printf(ifp, "invalid IV image, val16\n");
device_printf(sc->sc_dev,
"invalid IV image, val16\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_val.val16);
@ -1200,7 +1204,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
}
if (iv_img_size != 0) {
if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size);
device_printf(sc->sc_dev, "invalid IV image, size left %d\n",
iv_img_size);
return EINVAL;
}
return 0;
@ -1209,19 +1214,19 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
static int
bwi_mac_fw_init(struct bwi_mac *mac)
{
struct ifnet *ifp = mac->mac_sc->sc_ifp;
device_t dev = mac->mac_sc->sc_dev;
int error;
error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
if (error) {
if_printf(ifp, "load IV failed\n");
device_printf(dev, "load IV failed\n");
return error;
}
if (mac->mac_iv_ext != NULL) {
error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
if (error)
if_printf(ifp, "load ExtIV failed\n");
device_printf(dev, "load ExtIV failed\n");
}
return error;
}
@ -1230,8 +1235,7 @@ static void
bwi_mac_opmode_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mac_status;
uint16_t pre_tbtt;
@ -1280,7 +1284,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac)
break;
}
if (ic->ic_ifp->if_flags & IFF_PROMISC)
if (ic->ic_promisc > 0)
mac_status |= BWI_MAC_STATUS_PROMISC;
CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
@ -1331,8 +1335,7 @@ bwi_mac_bss_param_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_phy *phy = &mac->mac_phy;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const struct ieee80211_rate_table *rt;
struct bwi_retry_lim lim;
uint16_t cw_min;
@ -1915,8 +1918,7 @@ static void
bwi_mac_lock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
("mac_flags 0x%x", mac->mac_flags));
@ -1939,8 +1941,7 @@ static void
bwi_mac_unlock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
("mac_flags 0x%x", mac->mac_flags));

View File

@ -429,7 +429,7 @@ static void
bwi_phy_init_11b_rev2(struct bwi_mac *mac)
{
/* TODO:11B */
if_printf(mac->mac_sc->sc_ifp,
device_printf(mac->mac_sc->sc_dev,
"%s is not implemented yet\n", __func__);
}

View File

@ -1260,7 +1260,6 @@ static void
bwi_rf_lo_update_11g(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct ifnet *ifp = sc->sc_ifp;
struct bwi_rf *rf = &mac->mac_rf;
struct bwi_phy *phy = &mac->mac_phy;
struct bwi_tpctl *tpctl = &mac->mac_tpctl;
@ -1329,7 +1328,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
PHY_WRITE(mac, 0x812, 0xb2);
}
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
PHY_WRITE(mac, 0x80f, 0x8078);
@ -1352,7 +1351,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
}
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
tpctl = NULL;
bwi_rf_lo_adjust(mac, tpctl);
@ -1462,7 +1461,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
{ 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
struct ifnet *ifp = mac->mac_sc->sc_ifp;
struct bwi_softc *sc = mac->mac_sc;
struct bwi_rf_lo lo_save, *lo;
uint8_t devi_ctrl = 0;
int idx, adj_rf7a = 0;
@ -1476,7 +1475,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
uint16_t tp_ctrl2, rf7a;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
if (idx == 0) {
bzero(&lo_save, sizeof(lo_save));
} else if (init_rf_atten < 0) {

View File

@ -102,10 +102,10 @@ static struct ieee80211vap *bwi_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void bwi_vap_delete(struct ieee80211vap *);
static void bwi_init(void *);
static int bwi_ioctl(struct ifnet *, u_long, caddr_t);
static void bwi_start(struct ifnet *);
static void bwi_start_locked(struct ifnet *);
static void bwi_init(struct bwi_softc *);
static void bwi_parent(struct ieee80211com *);
static int bwi_transmit(struct ieee80211com *, struct mbuf *);
static void bwi_start_locked(struct bwi_softc *);
static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void bwi_watchdog(void *);
@ -352,14 +352,12 @@ bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
int
bwi_attach(struct bwi_softc *sc)
{
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
device_t dev = sc->sc_dev;
struct ifnet *ifp;
struct bwi_mac *mac;
struct bwi_phy *phy;
int i, error;
uint8_t bands;
uint8_t macaddr[IEEE80211_ADDR_LEN];
BWI_LOCK_INIT(sc);
@ -371,8 +369,8 @@ bwi_attach(struct bwi_softc *sc)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc);
callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/*
* Initialize sysctl variables
@ -450,25 +448,6 @@ bwi_attach(struct bwi_softc *sc)
if (error)
goto fail;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
error = ENOSPC;
goto fail;
}
ic = ifp->if_l2com;
/* set these up early for if_printf use */
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = bwi_init;
ifp->if_ioctl = bwi_ioctl;
ifp->if_start = bwi_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0);
/*
@ -485,13 +464,13 @@ bwi_attach(struct bwi_softc *sc)
setbit(&bands, IEEE80211_MODE_11G);
}
bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, macaddr);
if (IEEE80211_IS_MULTICAST(macaddr)) {
bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, macaddr);
if (IEEE80211_IS_MULTICAST(macaddr)) {
bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_macaddr);
if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_macaddr);
if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
device_printf(dev,
"invalid MAC address: %6D\n",
macaddr, ":");
ic->ic_macaddr, ":");
}
}
} else if (phy->phy_mode == IEEE80211_MODE_11A) {
@ -510,7 +489,6 @@ bwi_attach(struct bwi_softc *sc)
/* XXX use locale */
ieee80211_init_channels(ic, NULL, &bands);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_caps = IEEE80211_C_STA |
@ -520,7 +498,7 @@ bwi_attach(struct bwi_softc *sc)
IEEE80211_C_BGSCAN |
IEEE80211_C_MONITOR;
ic->ic_opmode = IEEE80211_M_STA;
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
@ -532,6 +510,8 @@ bwi_attach(struct bwi_softc *sc)
ic->ic_scan_start = bwi_scan_start;
ic->ic_scan_end = bwi_scan_end;
ic->ic_set_channel = bwi_set_channel;
ic->ic_transmit = bwi_transmit;
ic->ic_parent = bwi_parent;
sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
@ -577,8 +557,7 @@ bwi_attach(struct bwi_softc *sc)
int
bwi_detach(struct bwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int i;
bwi_stop(sc, 1);
@ -590,8 +569,8 @@ bwi_detach(struct bwi_softc *sc)
for (i = 0; i < sc->sc_nmac; ++i)
bwi_mac_detach(&sc->sc_mac[i]);
bwi_dma_free(sc);
if_free(ifp);
taskqueue_free(sc->sc_tq);
mbufq_drain(&sc->sc_snd);
BWI_LOCK_DESTROY(sc);
@ -609,14 +588,11 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap),
M_80211_VAP, M_WAITOK | M_ZERO);
if (bvp == NULL)
return NULL;
bvp = malloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &bvp->bv_vap;
/* enable s/w bmiss handling for sta mode */
ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
flags | IEEE80211_CLONE_NOBEACONS, bssid);
/* override default methods */
bvp->bv_newstate = vap->iv_newstate;
@ -627,7 +603,8 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status,
mac);
ic->ic_opmode = opmode;
return vap;
}
@ -651,9 +628,8 @@ bwi_suspend(struct bwi_softc *sc)
void
bwi_resume(struct bwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
if (ifp->if_flags & IFF_UP)
if (sc->sc_ic.ic_nrunning > 0)
bwi_init(sc);
}
@ -1217,27 +1193,26 @@ bwi_set_clock_delay(struct bwi_softc *sc)
}
static void
bwi_init(void *xsc)
bwi_init(struct bwi_softc *sc)
{
struct bwi_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
BWI_LOCK(sc);
bwi_init_statechg(sc, 1);
BWI_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & BWI_F_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
bwi_init_statechg(struct bwi_softc *sc, int statechg)
{
struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int error;
BWI_ASSERT_LOCKED(sc);
bwi_stop_locked(sc, statechg);
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
@ -1247,20 +1222,21 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
mac = &sc->sc_mac[0];
error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
if (error) {
if_printf(ifp, "%s: error %d on regwin switch\n",
device_printf(sc->sc_dev, "%s: error %d on regwin switch\n",
__func__, error);
goto bad;
}
error = bwi_mac_init(mac);
if (error) {
if_printf(ifp, "%s: error %d on MAC init\n", __func__, error);
device_printf(sc->sc_dev, "%s: error %d on MAC init\n",
__func__, error);
goto bad;
}
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, IF_LLADDR(ifp));
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, sc->sc_ic.ic_macaddr);
bwi_mac_reset_hwkeys(mac);
@ -1278,7 +1254,8 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
CSR_READ_4(sc, BWI_TXSTATUS1);
}
if (i == NRETRY)
if_printf(ifp, "%s: can't drain TX status\n", __func__);
device_printf(sc->sc_dev,
"%s: can't drain TX status\n", __func__);
#undef NRETRY
}
@ -1288,14 +1265,14 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
/* Start MAC */
error = bwi_mac_start(mac);
if (error) {
if_printf(ifp, "%s: error %d starting MAC\n", __func__, error);
device_printf(sc->sc_dev, "%s: error %d starting MAC\n",
__func__, error);
goto bad;
}
/* Clear stop flag before enabling interrupt */
sc->sc_flags &= ~BWI_F_STOP;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= BWI_F_RUNNING;
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
/* Enable intrs */
@ -1305,135 +1282,110 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
bwi_stop_locked(sc, 1);
}
static int
bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
#define IS_RUNNING(ifp) \
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
struct bwi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
BWI_LOCK(sc);
if (IS_RUNNING(ifp)) {
struct bwi_mac *mac;
int promisc = -1;
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d",
sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
if ((ifp->if_flags & IFF_PROMISC) &&
(sc->sc_flags & BWI_F_PROMISC) == 0) {
promisc = 1;
sc->sc_flags |= BWI_F_PROMISC;
} else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
(sc->sc_flags & BWI_F_PROMISC)) {
promisc = 0;
sc->sc_flags &= ~BWI_F_PROMISC;
}
if (promisc >= 0)
bwi_mac_set_promisc(mac, promisc);
}
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
bwi_init_statechg(sc, 1);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
bwi_stop_locked(sc, 1);
}
BWI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
#undef IS_RUNNING
}
static void
bwi_start(struct ifnet *ifp)
bwi_parent(struct ieee80211com *ic)
{
struct bwi_softc *sc = ifp->if_softc;
struct bwi_softc *sc = ic->ic_softc;
int startall = 0;
BWI_LOCK(sc);
bwi_start_locked(ifp);
if (ic->ic_nrunning > 0) {
struct bwi_mac *mac;
int promisc = -1;
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d",
sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
if (ic->ic_promisc > 0 && (sc->sc_flags & BWI_F_PROMISC) == 0) {
promisc = 1;
sc->sc_flags |= BWI_F_PROMISC;
} else if (ic->ic_promisc == 0 &&
(sc->sc_flags & BWI_F_PROMISC) != 0) {
promisc = 0;
sc->sc_flags &= ~BWI_F_PROMISC;
}
if (promisc >= 0)
bwi_mac_set_promisc(mac, promisc);
}
if (ic->ic_nrunning > 0) {
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
bwi_init_statechg(sc, 1);
startall = 1;
}
} else if (sc->sc_flags & BWI_F_RUNNING)
bwi_stop_locked(sc, 1);
BWI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static int
bwi_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct bwi_softc *sc = ic->ic_softc;
int error;
BWI_LOCK(sc);
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
BWI_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
BWI_UNLOCK(sc);
return (error);
}
bwi_start_locked(sc);
BWI_UNLOCK(sc);
return (0);
}
static void
bwi_start_locked(struct ifnet *ifp)
bwi_start_locked(struct bwi_softc *sc)
{
struct bwi_softc *sc = ifp->if_softc;
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct ieee80211_key *k;
struct mbuf *m;
int trans, idx;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
BWI_ASSERT_LOCKED(sc);
trans = 0;
idx = tbd->tbd_idx;
while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
if (m == NULL)
break;
while (tbd->tbd_buf[idx].tb_mbuf == NULL &&
tbd->tbd_used + BWI_TX_NSPRDESC < BWI_TX_NDESC &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
wh = mtod(m, struct ieee80211_frame *);
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
ieee80211_free_node(ni);
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
}
wh = NULL; /* Catch any invalid use */
if (bwi_encap(sc, idx, m, ni) != 0) {
/* 'm' is freed in bwi_encap() if we reach here */
if (ni != NULL)
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
ieee80211_crypto_encap(ni, m) == NULL) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
m_freem(m);
continue;
}
if (bwi_encap(sc, idx, m, ni) != 0) {
/* 'm' is freed in bwi_encap() if we reach here */
if (ni != NULL) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
} else
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
continue;
}
trans = 1;
tbd->tbd_used++;
idx = (idx + 1) % BWI_TX_NDESC;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
}
tbd->tbd_idx = idx;
tbd->tbd_idx = idx;
if (trans)
sc->sc_tx_timer = 5;
}
@ -1443,13 +1395,12 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct bwi_softc *sc = ifp->if_softc;
struct bwi_softc *sc = ic->ic_softc;
/* XXX wme? */
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
int idx, error;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@ -1472,16 +1423,12 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
error = bwi_encap_raw(sc, idx, m, ni, params);
}
if (error == 0) {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (++tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
tbd->tbd_used++;
tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC;
sc->sc_tx_timer = 5;
} else {
} else
/* NB: m is reclaimed on encap failure */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
BWI_UNLOCK(sc);
return error;
}
@ -1490,14 +1437,12 @@ static void
bwi_watchdog(void *arg)
{
struct bwi_softc *sc;
struct ifnet *ifp;
sc = arg;
ifp = sc->sc_ifp;
BWI_ASSERT_LOCKED(sc);
if (sc->sc_tx_timer != 0 && --sc->sc_tx_timer == 0) {
if_printf(ifp, "watchdog timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev, "watchdog timeout\n");
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
}
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
@ -1514,7 +1459,6 @@ bwi_stop(struct bwi_softc *sc, int statechg)
static void
bwi_stop_locked(struct bwi_softc *sc, int statechg)
{
struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int i, error, pwr_off = 0;
@ -1525,7 +1469,7 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
sc->sc_led_blinking = 0;
sc->sc_flags |= BWI_F_STOP;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (sc->sc_flags & BWI_F_RUNNING) {
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
@ -1557,14 +1501,13 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
sc->sc_tx_timer = 0;
callout_stop(&sc->sc_watchdog_timer);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~BWI_F_RUNNING;
}
void
bwi_intr(void *xsc)
{
struct bwi_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
uint32_t intr_status;
uint32_t txrx_intr_status[BWI_TXRX_NRING];
@ -1572,7 +1515,7 @@ bwi_intr(void *xsc)
BWI_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
if ((sc->sc_flags & BWI_F_RUNNING) == 0 ||
(sc->sc_flags & BWI_F_STOP)) {
BWI_UNLOCK(sc);
return;
@ -1615,7 +1558,7 @@ bwi_intr(void *xsc)
i, txrx_intr_status[i]);
if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
if_printf(ifp,
device_printf(sc->sc_dev,
"%s: intr fatal TX/RX (%d) error 0x%08x\n",
__func__, i, txrx_intr_status[i]);
txrx_error = 1;
@ -1653,7 +1596,8 @@ bwi_intr(void *xsc)
*/
if (intr_status & BWI_INTR_PHY_TXERR) {
if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
if_printf(ifp, "%s: intr PHY TX error\n", __func__);
device_printf(sc->sc_dev, "%s: intr PHY TX error\n",
__func__);
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
BWI_UNLOCK(sc);
return;
@ -1668,7 +1612,7 @@ bwi_intr(void *xsc)
bwi_mac_config_ps(mac);
if (intr_status & BWI_INTR_EO_ATIM)
if_printf(ifp, "EO_ATIM\n");
device_printf(sc->sc_dev, "EO_ATIM\n");
if (intr_status & BWI_INTR_PMQ) {
for (;;) {
@ -1679,7 +1623,7 @@ bwi_intr(void *xsc)
}
if (intr_status & BWI_INTR_NOISE)
if_printf(ifp, "intr noise\n");
device_printf(sc->sc_dev, "intr noise\n");
if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) {
rx_data = sc->sc_rxeof(sc);
@ -1728,7 +1672,7 @@ bwi_intr(void *xsc)
static void
bwi_scan_start(struct ieee80211com *ic)
{
struct bwi_softc *sc = ic->ic_ifp->if_softc;
struct bwi_softc *sc = ic->ic_softc;
BWI_LOCK(sc);
/* Enable MAC beacon promiscuity */
@ -1739,7 +1683,7 @@ bwi_scan_start(struct ieee80211com *ic)
static void
bwi_set_channel(struct ieee80211com *ic)
{
struct bwi_softc *sc = ic->ic_ifp->if_softc;
struct bwi_softc *sc = ic->ic_softc;
struct ieee80211_channel *c = ic->ic_curchan;
struct bwi_mac *mac;
@ -1765,7 +1709,7 @@ bwi_set_channel(struct ieee80211com *ic)
static void
bwi_scan_end(struct ieee80211com *ic)
{
struct bwi_softc *sc = ic->ic_ifp->if_softc;
struct bwi_softc *sc = ic->ic_softc;
BWI_LOCK(sc);
CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
@ -1777,9 +1721,8 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct bwi_vap *bvp = BWI_VAP(vap);
struct ieee80211com *ic= vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct bwi_softc *sc = ic->ic_softc;
enum ieee80211_state ostate = vap->iv_state;
struct bwi_softc *sc = ifp->if_softc;
struct bwi_mac *mac;
int error;
@ -2625,8 +2568,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
{
struct bwi_ring_data *rd = &sc->sc_rx_rdata;
struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int idx, rx_data = 0;
idx = rbd->rbd_idx;
@ -2645,7 +2587,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
BUS_DMASYNC_POSTREAD);
if (bwi_newbuf(sc, idx, 0)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto next;
}
@ -2659,9 +2601,10 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
buflen = le16toh(hdr->rxh_buflen);
if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
if_printf(ifp, "%s: zero length data, hdr_extra %d\n",
__func__, hdr_extra);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
device_printf(sc->sc_dev,
"%s: zero length data, hdr_extra %d\n",
__func__, hdr_extra);
counter_u64_add(ic->ic_ierrors, 1);
m_freem(m);
goto next;
}
@ -2670,7 +2613,6 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
rssi = bwi_calc_rssi(sc, hdr);
noise = bwi_calc_noise(sc);
m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
m_adj(m, sizeof(*hdr) + wh_ofs);
@ -2804,7 +2746,6 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
{
struct bwi_ring_data *rd;
struct bwi_txbuf_data *tbd;
struct ifnet *ifp = sc->sc_ifp;
uint32_t state, val;
int i;
@ -2825,8 +2766,9 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY) {
if_printf(ifp, "%s: wait for TX ring(%d) stable timed out\n",
__func__, ring_idx);
device_printf(sc->sc_dev,
"%s: wait for TX ring(%d) stable timed out\n",
__func__, ring_idx);
}
CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
@ -2839,7 +2781,7 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY)
if_printf(ifp, "%s: reset TX ring (%d) timed out\n",
device_printf(sc->sc_dev, "%s: reset TX ring (%d) timed out\n",
__func__, ring_idx);
#undef NRETRY
@ -2947,8 +2889,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
@ -3024,7 +2965,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
*/
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
if (m == NULL) {
if_printf(ifp, "%s: prepend TX header failed\n", __func__);
device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
__func__);
return ENOBUFS;
}
hdr = mtod(m, struct bwi_txbuf_hdr *);
@ -3073,7 +3015,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
if (error && error != EFBIG) {
if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
__func__, error);
goto back;
}
@ -3083,8 +3025,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
m_new = m_defrag(m, M_NOWAIT);
if (m_new == NULL) {
if_printf(ifp, "%s: can't defrag TX buffer\n",
__func__);
device_printf(sc->sc_dev,
"%s: can't defrag TX buffer\n", __func__);
error = ENOBUFS;
goto back;
} else {
@ -3095,7 +3037,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
bwi_dma_buf_addr, &paddr,
BUS_DMA_NOWAIT);
if (error) {
if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
device_printf(sc->sc_dev,
"%s: can't load TX buffer (2) %d\n",
__func__, error);
goto back;
}
@ -3137,7 +3080,6 @@ static int
bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
@ -3204,7 +3146,8 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
*/
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
if (m == NULL) {
if_printf(ifp, "%s: prepend TX header failed\n", __func__);
device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
__func__);
return ENOBUFS;
}
hdr = mtod(m, struct bwi_txbuf_hdr *);
@ -3252,14 +3195,15 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
struct mbuf *m_new;
if (error != EFBIG) {
if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
device_printf(sc->sc_dev,
"%s: can't load TX buffer (1) %d\n",
__func__, error);
goto back;
}
m_new = m_defrag(m, M_NOWAIT);
if (m_new == NULL) {
if_printf(ifp, "%s: can't defrag TX buffer\n",
__func__);
device_printf(sc->sc_dev,
"%s: can't defrag TX buffer\n", __func__);
error = ENOBUFS;
goto back;
}
@ -3268,7 +3212,8 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
bwi_dma_buf_addr, &paddr,
BUS_DMA_NOWAIT);
if (error) {
if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
device_printf(sc->sc_dev,
"%s: can't load TX buffer (2) %d\n",
__func__, error);
goto back;
}
@ -3312,7 +3257,6 @@ bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
static void
bwi_txeof_status32(struct bwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t val, ctrl_base;
int end_idx;
@ -3327,8 +3271,7 @@ bwi_txeof_status32(struct bwi_softc *sc)
CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
end_idx * sizeof(struct bwi_desc32));
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
ifp->if_start(ifp);
bwi_start_locked(sc);
}
static void
@ -3340,7 +3283,6 @@ bwi_txeof_status64(struct bwi_softc *sc)
static void
_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
{
struct ifnet *ifp = sc->sc_ifp;
struct bwi_txbuf_data *tbd;
struct bwi_txbuf *tb;
int ring_idx, buf_idx;
@ -3348,7 +3290,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
struct ieee80211vap *vap;
if (tx_id == 0) {
if_printf(ifp, "%s: zero tx id\n", __func__);
device_printf(sc->sc_dev, "%s: zero tx id\n", __func__);
return;
}
@ -3369,8 +3311,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap);
ni = tb->tb_ni;
if (tb->tb_ni != NULL) {
if ((ni = tb->tb_ni) != NULL) {
const struct bwi_txbuf_hdr *hdr =
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
vap = ni->ni_vap;
@ -3388,24 +3329,14 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
(data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
IEEE80211_RATECTL_TX_FAILURE, &acked, NULL);
}
/*
* Do any tx complete callback. Note this must
* be done before releasing the node reference.
*/
if (tb->tb_mbuf->m_flags & M_TXCB)
ieee80211_process_callback(ni, tb->tb_mbuf, !acked);
ieee80211_free_node(tb->tb_ni);
ieee80211_tx_complete(ni, tb->tb_mbuf, !acked);
tb->tb_ni = NULL;
}
m_freem(tb->tb_mbuf);
} else
m_freem(tb->tb_mbuf);
tb->tb_mbuf = NULL;
if (tbd->tbd_used == 0)
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@ -3437,7 +3368,6 @@ bwi_txeof_status(struct bwi_softc *sc, int end_idx)
static void
bwi_txeof(struct bwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
for (;;) {
uint32_t tx_status0, tx_status1;
@ -3460,8 +3390,7 @@ bwi_txeof(struct bwi_softc *sc)
data_txcnt);
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
ifp->if_start(ifp);
bwi_start_locked(sc);
}
static int
@ -3709,7 +3638,6 @@ bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
static void
bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
{
struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
struct bwi_myaddr_bssid buf;
const uint8_t *p;
@ -3722,7 +3650,7 @@ bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr));
bcopy(sc->sc_ic.ic_macaddr, buf.myaddr, sizeof(buf.myaddr));
bcopy(bssid, buf.bssid, sizeof(buf.bssid));
n = sizeof(buf) / sizeof(val);
@ -3745,7 +3673,7 @@ bwi_updateslot(struct ieee80211com *ic)
struct bwi_mac *mac;
BWI_LOCK(sc);
if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (sc->sc_flags & BWI_F_RUNNING) {
DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
@ -3761,16 +3689,12 @@ static void
bwi_calibrate(void *xsc)
{
struct bwi_softc *sc = xsc;
#ifdef INVARIANTS
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
#endif
struct bwi_mac *mac;
BWI_ASSERT_LOCKED(sc);
KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR,
("opmode %d", ic->ic_opmode));
KASSERT(sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR,
("opmode %d", sc->sc_ic.ic_opmode));
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d", sc->sc_cur_regwin->rw_type));
@ -3912,8 +3836,7 @@ bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
static void
bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
int i;
@ -3922,7 +3845,7 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
sc->sc_led_blinking = 0;
}
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
return;
val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
@ -4050,13 +3973,12 @@ static void
bwi_restart(void *xsc, int pending)
{
struct bwi_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
if_printf(ifp, "%s begin, help!\n", __func__);
device_printf(sc->sc_dev, "%s begin, help!\n", __func__);
BWI_LOCK(sc);
bwi_init_statechg(xsc, 0);
bwi_init_statechg(sc, 0);
#if 0
bwi_start_locked(ifp);
bwi_start_locked(sc);
#endif
BWI_UNLOCK(sc);
}

View File

@ -541,10 +541,11 @@ struct bwi_vap {
#define BWI_VAP(vap) ((struct bwi_vap *)(vap))
struct bwi_softc {
struct ifnet *sc_ifp;
uint32_t sc_flags; /* BWI_F_ */
device_t sc_dev;
struct mtx sc_mtx;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
int sc_invalid;
uint32_t sc_cap; /* BWI_CAP_ */
@ -647,6 +648,7 @@ struct bwi_softc {
#define BWI_F_BUS_INITED 0x1
#define BWI_F_PROMISC 0x2
#define BWI_F_STOP 0x4
#define BWI_F_RUNNING 0x8
#define BWI_DBG_MAC 0x00000001
#define BWI_DBG_RF 0x00000002

File diff suppressed because it is too large Load Diff

View File

@ -656,7 +656,6 @@ struct bwn_pio_txqueue {
uint16_t tq_size;
uint16_t tq_used;
uint16_t tq_free;
uint8_t tq_stop;
uint8_t tq_index;
struct bwn_pio_txpkt tq_pkts[BWN_PIO_MAX_TXPACKETS];
TAILQ_HEAD(, bwn_pio_txpkt) tq_pktlist;
@ -897,17 +896,18 @@ struct bwn_vap {
struct bwn_softc {
device_t sc_dev;
struct mtx sc_mtx;
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
unsigned sc_flags;
#define BWN_FLAG_ATTACHED (1 << 0)
#define BWN_FLAG_INVALID (1 << 1)
#define BWN_FLAG_NEED_BEACON_TP (1 << 2)
#define BWN_FLAG_RUNNING (1 << 3)
unsigned sc_debug;
struct bwn_mac *sc_curmac;
TAILQ_HEAD(, bwn_mac) sc_maclist;
uint8_t sc_macaddr[IEEE80211_ADDR_LEN];
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
unsigned int sc_filters;
uint8_t sc_beacons[2];

File diff suppressed because it is too large Load Diff

View File

@ -152,8 +152,22 @@ struct ndisusb_task {
};
struct ndis_softc {
struct ifnet *ifp;
struct ifmedia ifmedia; /* media info */
u_int ndis_80211:1,
ndis_link:1,
ndis_running:1;
union {
struct { /* Ethernet */
struct ifnet *ifp;
struct ifmedia ifmedia;
int ndis_if_flags;
};
struct { /* Wireless */
struct ieee80211com ndis_ic;
struct callout ndis_scan_callout;
int (*ndis_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
};
};
u_long ndis_hwassist;
uint32_t ndis_v4tx;
uint32_t ndis_v4rx;
@ -180,7 +194,6 @@ struct ndis_softc {
ndis_miniport_block *ndis_block;
ndis_miniport_characteristics *ndis_chars;
interface_type ndis_type;
struct callout ndis_scan_callout;
struct callout ndis_stat_callout;
int ndis_maxpkts;
ndis_oid *ndis_oids;
@ -192,13 +205,9 @@ struct ndis_softc {
int ndis_sc;
ndis_cfg *ndis_regvals;
struct nch ndis_cfglist_head;
int ndis_80211;
int ndis_link;
uint32_t ndis_sts;
uint32_t ndis_filter;
int ndis_if_flags;
int ndis_skip;
int ndis_devidx;
interface_type ndis_iftype;
driver_object *ndis_dobj;
@ -217,11 +226,9 @@ struct ndis_softc {
struct ndis_evt ndis_evt[NDIS_EVENTS];
int ndis_evtpidx;
int ndis_evtcidx;
struct ifqueue ndis_rxqueue;
struct mbufq ndis_rxqueue;
kspin_lock ndis_rxlock;
int (*ndis_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
int ndis_tx_timer;
int ndis_hang_timer;

View File

@ -127,14 +127,14 @@ static void ipw_intr(void *);
static void ipw_dma_map_addr(void *, bus_dma_segment_t *, int, int);
static const char * ipw_cmdname(int);
static int ipw_cmd(struct ipw_softc *, uint32_t, void *, uint32_t);
static int ipw_tx_start(struct ifnet *, struct mbuf *,
static int ipw_tx_start(struct ipw_softc *, struct mbuf *,
struct ieee80211_node *);
static int ipw_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void ipw_start(struct ifnet *);
static void ipw_start_locked(struct ifnet *);
static int ipw_transmit(struct ieee80211com *, struct mbuf *);
static void ipw_start(struct ipw_softc *);
static void ipw_watchdog(void *);
static int ipw_ioctl(struct ifnet *, u_long, caddr_t);
static void ipw_parent(struct ieee80211com *);
static void ipw_stop_master(struct ipw_softc *);
static int ipw_enable(struct ipw_softc *);
static int ipw_disable(struct ipw_softc *);
@ -220,18 +220,16 @@ static int
ipw_attach(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
uint16_t val;
int error, i;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
mbufq_init(&sc->sc_snd, ifqmaxlen);
TASK_INIT(&sc->sc_init_task, 0, ipw_init_task, sc);
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
@ -268,24 +266,6 @@ ipw_attach(device_t dev)
goto fail2;
}
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
goto fail3;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = ipw_init;
ifp->if_ioctl = ipw_ioctl;
ifp->if_start = ipw_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@ -303,14 +283,14 @@ ipw_attach(device_t dev)
/* read MAC address from EEPROM */
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0);
macaddr[0] = val >> 8;
macaddr[1] = val & 0xff;
ic->ic_macaddr[0] = val >> 8;
ic->ic_macaddr[1] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 1);
macaddr[2] = val >> 8;
macaddr[3] = val & 0xff;
ic->ic_macaddr[2] = val >> 8;
ic->ic_macaddr[3] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 2);
macaddr[4] = val >> 8;
macaddr[5] = val & 0xff;
ic->ic_macaddr[4] = val >> 8;
ic->ic_macaddr[5] = val & 0xff;
/* set supported .11b channels (read from EEPROM) */
if ((val = ipw_read_prom_word(sc, IPW_EEPROM_CHANNEL_LIST)) == 0)
@ -329,16 +309,17 @@ ipw_attach(device_t dev)
if (!(ipw_read_prom_word(sc, IPW_EEPROM_RADIO) & 8))
sc->flags |= IPW_FLAG_HAS_RADIO_SWITCH;
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_scan_start = ipw_scan_start;
ic->ic_scan_end = ipw_scan_end;
ic->ic_set_channel = ipw_set_channel;
ic->ic_scan_curchan = ipw_scan_curchan;
ic->ic_scan_mindwell = ipw_scan_mindwell;
ic->ic_raw_xmit = ipw_raw_xmit;
ic->ic_vap_create = ipw_vap_create;
ic->ic_vap_delete = ipw_vap_delete;
ic->ic_transmit = ipw_transmit;
ic->ic_parent = ipw_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -366,15 +347,13 @@ ipw_attach(device_t dev)
NULL, ipw_intr, sc, &sc->sc_ih);
if (error != 0) {
device_printf(dev, "could not set up interrupt\n");
goto fail4;
goto fail3;
}
if (bootverbose)
ieee80211_announce(ic);
return 0;
fail4:
if_free(ifp);
fail3:
ipw_release(sc);
fail2:
@ -391,8 +370,7 @@ static int
ipw_detach(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@ -402,6 +380,7 @@ ipw_detach(device_t dev)
ieee80211_ifdetach(ic);
callout_drain(&sc->sc_wdtimer);
mbufq_drain(&sc->sc_snd);
ipw_release(sc);
@ -410,8 +389,6 @@ ipw_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem),
sc->mem);
if_free(ifp);
if (sc->sc_firmware != NULL) {
firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
sc->sc_firmware = NULL;
@ -428,8 +405,7 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
struct ipw_vap *ivp;
struct ieee80211vap *vap;
const struct firmware *fp;
@ -487,19 +463,17 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
return NULL;
}
ivp = (struct ipw_vap *) malloc(sizeof(struct ipw_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (ivp == NULL)
return NULL;
ivp = malloc(sizeof(struct ipw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override with driver methods */
ivp->newstate = vap->iv_newstate;
vap->iv_newstate = ipw_newstate;
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status,
mac);
ic->ic_opmode = opmode;
return vap;
}
@ -827,7 +801,7 @@ static int
ipw_suspend(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
ieee80211_suspend_all(ic);
return 0;
@ -837,7 +811,7 @@ static int
ipw_resume(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
pci_write_config(dev, 0x41, 0, 1);
@ -866,7 +840,7 @@ ipw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
struct ipw_softc *sc = ic->ic_ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
/* read current transmission rate from adapter */
vap->iv_bss->ni_txrate = ipw_cvtrate(
@ -879,8 +853,7 @@ ipw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ipw_vap *ivp = IPW_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
enum ieee80211_state ostate;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
@ -1015,8 +988,7 @@ static void
ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
#define IEEESTATE(vap) ieee80211_state_name[vap->iv_state]
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t state;
@ -1118,8 +1090,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
static void
ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
ic->ic_curchan = chan;
ieee80211_radiotap_chan_change(ic);
@ -1132,8 +1103,7 @@ ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
static void
ipw_fix_channel(struct ipw_softc *sc, struct mbuf *m)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
struct ieee80211_frame *wh;
uint8_t subtype;
@ -1178,8 +1148,7 @@ static void
ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mnew, *m;
struct ieee80211_node *ni;
bus_addr_t physaddr;
@ -1201,7 +1170,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -1222,7 +1191,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -1233,9 +1202,6 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
m = sbuf->m;
sbuf->m = mnew;
sbd->bd->physaddr = htole32(physaddr);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = le32toh(status->len);
rssi = status->rssi + IPW_RSSI_TO_DBM;
@ -1364,7 +1330,6 @@ ipw_release_sbd(struct ipw_softc *sc, struct ipw_soft_bd *sbd)
static void
ipw_tx_intr(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ipw_soft_bd *sbd;
uint32_t r, i;
@ -1375,10 +1340,6 @@ ipw_tx_intr(struct ipw_softc *sc)
for (i = (sc->txold + 1) % IPW_NTBD; i != r; i = (i + 1) % IPW_NTBD) {
sbd = &sc->stbd_list[i];
if (sbd->type == IPW_SBD_TYPE_DATA)
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ipw_release_sbd(sc, sbd);
sc->txfree++;
}
@ -1386,15 +1347,13 @@ ipw_tx_intr(struct ipw_softc *sc)
/* remember what the firmware has processed */
sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ipw_start_locked(ifp);
ipw_start(sc);
}
static void
ipw_fatal_error_intr(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "firmware error\n");
@ -1579,10 +1538,9 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
}
static int
ipw_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
ipw_tx_start(struct ipw_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ipw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ipw_soft_bd *sbd;
@ -1736,38 +1694,42 @@ ipw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
}
static void
ipw_start(struct ifnet *ifp)
static int
ipw_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
int error;
IPW_LOCK(sc);
ipw_start_locked(ifp);
if ((sc->flags & IPW_FLAG_RUNNING) == 0) {
IPW_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
IPW_UNLOCK(sc);
return (error);
}
ipw_start(sc);
IPW_UNLOCK(sc);
return (0);
}
static void
ipw_start_locked(struct ifnet *ifp)
ipw_start(struct ipw_softc *sc)
{
struct ipw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
IPW_LOCK_ASSERT(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (sc->txfree < 1 + IPW_MAX_NSEG) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
while (sc->txfree < 1 + IPW_MAX_NSEG &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (ipw_tx_start(ifp, m, ni) != 0) {
if (ipw_tx_start(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
/* start watchdog timer */
@ -1779,15 +1741,14 @@ static void
ipw_watchdog(void *arg)
{
struct ipw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IPW_LOCK_ASSERT(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev, "device timeout\n");
counter_u64_add(ic->ic_oerrors, 1);
taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
}
}
@ -1803,45 +1764,27 @@ ipw_watchdog(void *arg)
}
}
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->flags & IPW_FLAG_RUNNING)
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
}
static int
ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
ipw_parent(struct ieee80211com *ic)
{
struct ipw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct ipw_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
IPW_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
ipw_init_locked(sc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ipw_stop_locked(sc);
IPW_LOCK(sc);
if (ic->ic_nrunning > 0) {
if (!(sc->flags & IPW_FLAG_RUNNING)) {
ipw_init_locked(sc);
startall = 1;
}
IPW_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
} else if (sc->flags & IPW_FLAG_RUNNING)
ipw_stop_locked(sc);
IPW_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -2057,8 +2000,7 @@ ipw_load_firmware(struct ipw_softc *sc, const char *fw, int size)
static int
ipw_setwepkeys(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ipw_wep_key wepkey;
struct ieee80211_key *wk;
@ -2201,8 +2143,7 @@ ipw_scan(struct ipw_softc *sc)
static int
ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
int error;
@ -2217,8 +2158,7 @@ ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
static void
ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
struct ieee80211_node *ni = vap->iv_bss;
struct ipw_security security;
uint32_t data;
@ -2309,9 +2249,8 @@ ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap)
static void
ipw_disassoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct ieee80211_node *ni = vap->iv_bss;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
DPRINTF(("Disassociate from %6D\n", ni->ni_bssid, ":"));
@ -2345,22 +2284,20 @@ static void
ipw_init(void *priv)
{
struct ipw_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IPW_LOCK(sc);
ipw_init_locked(sc);
IPW_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->flags & IPW_FLAG_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
ipw_init_locked(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
const struct firmware *fp;
const struct ipw_firmware_hdr *hdr;
@ -2444,22 +2381,19 @@ ipw_init_locked(struct ipw_softc *sc)
}
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
sc->flags |= IPW_FLAG_RUNNING;
sc->flags &= ~IPW_FLAG_INIT_LOCKED;
return;
fail:
ipw_stop_locked(sc);
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
sc->flags &= ~IPW_FLAG_INIT_LOCKED;
}
static int
ipw_config(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ipw_configuration config;
uint32_t data;
int error;
@ -2504,7 +2438,7 @@ ipw_config(struct ipw_softc *sc)
IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE);
if (ic->ic_opmode == IEEE80211_M_IBSS)
config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
if (ifp->if_flags & IFF_PROMISC)
if (ic->ic_promisc > 0)
config.flags |= htole32(IPW_CFG_PROMISCUOUS);
config.bss_chan = htole32(0x3fff); /* channels 1-14 */
config.ibss_chan = htole32(0x7ff); /* channels 1-11 */
@ -2562,7 +2496,6 @@ ipw_stop(void *priv)
static void
ipw_stop_locked(struct ipw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int i;
IPW_LOCK_ASSERT(sc);
@ -2579,7 +2512,7 @@ ipw_stop_locked(struct ipw_softc *sc)
ipw_release_sbd(sc, &sc->stbd_list[i]);
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->flags &= ~IPW_FLAG_RUNNING;
}
static int
@ -2677,8 +2610,7 @@ ipw_write_mem_1(struct ipw_softc *sc, bus_size_t offset, const uint8_t *datap,
static void
ipw_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
ipw_scan(sc);
@ -2688,8 +2620,7 @@ ipw_scan_start(struct ieee80211com *ic)
static void
ipw_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
@ -2715,8 +2646,7 @@ ipw_scan_mindwell(struct ieee80211_scan_state *ss)
static void
ipw_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
sc->flags &= ~IPW_FLAG_SCANNING;

View File

@ -87,7 +87,8 @@ struct ipw_vap {
#define IPW_VAP(vap) ((struct ipw_vap *)(vap))
struct ipw_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct mtx sc_mtx;
@ -104,6 +105,7 @@ struct ipw_softc {
#define IPW_FLAG_BUSY 0x0040
#define IPW_FLAG_ASSOCIATING 0x0080
#define IPW_FLAG_ASSOCIATED 0x0100
#define IPW_FLAG_RUNNING 0x0200
struct resource *irq;
struct resource *mem;

View File

@ -166,14 +166,15 @@ static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
static void iwi_intr(void *);
static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t);
static void iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int);
static int iwi_tx_start(struct ifnet *, struct mbuf *,
static int iwi_tx_start(struct iwi_softc *, struct mbuf *,
struct ieee80211_node *, int);
static int iwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void iwi_start_locked(struct ifnet *);
static void iwi_start(struct ifnet *);
static void iwi_start(struct iwi_softc *);
static int iwi_transmit(struct ieee80211com *, struct mbuf *);
static void iwi_watchdog(void *);
static int iwi_ioctl(struct ifnet *, u_long, caddr_t);
static int iwi_ioctl(struct ieee80211com *, u_long, void *);
static void iwi_parent(struct ieee80211com *);
static void iwi_stop_master(struct iwi_softc *);
static int iwi_reset(struct iwi_softc *);
static int iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *);
@ -269,23 +270,15 @@ static int
iwi_attach(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
int i, error;
uint8_t bands;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
return ENXIO;
}
ic = ifp->if_l2com;
IWI_LOCK_INIT(sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
@ -353,17 +346,6 @@ iwi_attach(device_t dev)
iwi_wme_init(sc);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = iwi_init;
ifp->if_ioctl = iwi_ioctl;
ifp->if_start = iwi_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@ -385,14 +367,14 @@ iwi_attach(device_t dev)
/* read MAC address from EEPROM */
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
macaddr[0] = val & 0xff;
macaddr[1] = val >> 8;
ic->ic_macaddr[0] = val & 0xff;
ic->ic_macaddr[1] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
macaddr[2] = val & 0xff;
macaddr[3] = val >> 8;
ic->ic_macaddr[2] = val & 0xff;
ic->ic_macaddr[3] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
macaddr[4] = val & 0xff;
macaddr[5] = val >> 8;
ic->ic_macaddr[4] = val & 0xff;
ic->ic_macaddr[5] = val >> 8;
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
@ -401,7 +383,7 @@ iwi_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
/* override default methods */
ic->ic_node_alloc = iwi_node_alloc;
sc->sc_node_free = ic->ic_node_free;
@ -416,6 +398,9 @@ iwi_attach(device_t dev)
ic->ic_vap_create = iwi_vap_create;
ic->ic_vap_delete = iwi_vap_delete;
ic->ic_ioctl = iwi_ioctl;
ic->ic_transmit = iwi_transmit;
ic->ic_parent = iwi_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -450,8 +435,7 @@ static int
iwi_detach(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@ -482,11 +466,10 @@ iwi_detach(device_t dev)
sc->mem);
delete_unrhdr(sc->sc_unr);
mbufq_drain(&sc->sc_snd);
IWI_LOCK_DESTROY(sc);
if_free(ifp);
return 0;
}
@ -496,8 +479,7 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
struct iwi_vap *ivp;
struct ieee80211vap *vap;
int i;
@ -519,12 +501,9 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (iwi_init_fw_dma(sc, i))
return NULL;
ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (ivp == NULL)
return NULL;
ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->iwi_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override the default, the setting comes from the linux driver */
vap->iv_bmissthreshold = 24;
/* override with driver methods */
@ -532,7 +511,8 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
vap->iv_newstate = iwi_newstate;
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status,
mac);
ic->ic_opmode = opmode;
return vap;
}
@ -859,7 +839,7 @@ static int
iwi_suspend(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
ieee80211_suspend_all(ic);
return 0;
@ -869,7 +849,7 @@ static int
iwi_resume(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
pci_write_config(dev, 0x41, 0, 1);
@ -895,7 +875,7 @@ static void
iwi_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
struct iwi_softc *sc = ic->ic_ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
struct iwi_node *in = (struct iwi_node *)ni;
if (in->in_station != -1) {
@ -939,7 +919,7 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
struct iwi_softc *sc = ic->ic_ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
/* read current transmission rate from adapter */
@ -955,8 +935,7 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct iwi_vap *ivp = IWI_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
IWI_LOCK_DECL;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
@ -1061,7 +1040,7 @@ iwi_wme_init(struct iwi_softc *sc)
static int
iwi_wme_setparams(struct iwi_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const struct wmeParams *wmep;
int ac;
@ -1095,7 +1074,7 @@ iwi_update_wme(void *arg, int npending)
static int
iwi_wme_update(struct ieee80211com *ic)
{
struct iwi_softc *sc = ic->ic_ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
/*
@ -1189,8 +1168,7 @@ iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
static void
iwi_setcurchan(struct iwi_softc *sc, int chan)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
sc->curchan = chan;
ieee80211_radiotap_chan_change(ic);
@ -1200,8 +1178,7 @@ static void
iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
struct iwi_frame *frame)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mnew, *m;
struct ieee80211_node *ni;
int type, error, framelen;
@ -1237,7 +1214,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -1258,7 +1235,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -1271,7 +1248,6 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
CSR_WRITE_4(sc, data->reg, data->physaddr);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
sizeof (struct iwi_frame) + framelen;
@ -1410,8 +1386,7 @@ iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif)
static void
iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwi_notif_scan_channel *chan;
struct iwi_notif_scan_complete *scan;
@ -1632,47 +1607,33 @@ iwi_rx_intr(struct iwi_softc *sc)
static void
iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
{
struct ifnet *ifp = sc->sc_ifp;
struct iwi_tx_data *data;
uint32_t hw;
hw = CSR_READ_4(sc, txq->csr_ridx);
for (; txq->next != hw;) {
while (txq->next != hw) {
data = &txq->data[txq->next];
DPRINTFN(15, ("tx done idx=%u\n", txq->next));
bus_dmamap_sync(txq->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(txq->data_dmat, data->map);
if (data->m->m_flags & M_TXCB)
ieee80211_process_callback(data->ni, data->m, 0/*XXX*/);
m_freem(data->m);
data->m = NULL;
ieee80211_free_node(data->ni);
ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
DPRINTFN(15, ("tx done idx=%u\n", txq->next));
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
data->m = NULL;
txq->queued--;
txq->next = (txq->next + 1) % IWI_TX_RING_COUNT;
}
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
if (sc->sc_softled)
iwi_led_event(sc, IWI_LED_TX);
iwi_start_locked(ifp);
iwi_start(sc);
}
static void
iwi_fatal_error_intr(struct iwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "firmware error\n");
@ -1688,10 +1649,8 @@ iwi_fatal_error_intr(struct iwi_softc *sc)
static void
iwi_radio_off_intr(struct iwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
ieee80211_runtask(ic, &sc->sc_radiofftask);
ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask);
}
static void
@ -1806,10 +1765,9 @@ iwi_write_ibssnode(struct iwi_softc *sc,
}
static int
iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
int ac)
{
struct iwi_softc *sc = ifp->if_softc;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct iwi_node *in = (struct iwi_node *)ni;
@ -1852,9 +1810,10 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
in->in_station = alloc_unr(sc->sc_unr);
if (in->in_station == -1) {
/* h/w table is full */
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
m_freem(m0);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return 0;
}
iwi_write_ibssnode(sc,
@ -1980,141 +1939,139 @@ iwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
}
static void
iwi_start_locked(struct ifnet *ifp)
static int
iwi_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct iwi_softc *sc = ic->ic_softc;
int error;
IWI_LOCK_DECL;
IWI_LOCK(sc);
if (!sc->sc_running) {
IWI_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
IWI_UNLOCK(sc);
return (error);
}
iwi_start(sc);
IWI_UNLOCK(sc);
return (0);
}
static void
iwi_start(struct iwi_softc *sc)
{
struct iwi_softc *sc = ifp->if_softc;
struct mbuf *m;
struct ieee80211_node *ni;
int ac;
IWI_LOCK_ASSERT(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ac = M_WME_GETAC(m);
if (sc->txq[ac].queued > IWI_TX_RING_COUNT - 8) {
/* there is no place left in this ring; tail drop */
/* XXX tail drop */
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (iwi_tx_start(ifp, m, ni, ac) != 0) {
if (iwi_tx_start(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
break;
}
sc->sc_tx_timer = 5;
}
}
static void
iwi_start(struct ifnet *ifp)
{
struct iwi_softc *sc = ifp->if_softc;
IWI_LOCK_DECL;
IWI_LOCK(sc);
iwi_start_locked(ifp);
IWI_UNLOCK(sc);
}
static void
iwi_watchdog(void *arg)
{
struct iwi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_ASSERT(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
device_printf(sc->sc_dev, "device timeout\n");
counter_u64_add(ic->ic_oerrors, 1);
ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
if (sc->sc_state_timer > 0) {
if (--sc->sc_state_timer == 0) {
if_printf(ifp, "firmware stuck in state %d, resetting\n",
device_printf(sc->sc_dev,
"firmware stuck in state %d, resetting\n",
sc->fw_state);
if (sc->fw_state == IWI_FW_SCANNING) {
struct ieee80211com *ic = ifp->if_l2com;
if (sc->fw_state == IWI_FW_SCANNING)
ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps));
}
ieee80211_runtask(ic, &sc->sc_restarttask);
sc->sc_state_timer = 3;
}
}
if (sc->sc_busy_timer > 0) {
if (--sc->sc_busy_timer == 0) {
if_printf(ifp, "firmware command timeout, resetting\n");
device_printf(sc->sc_dev,
"firmware command timeout, resetting\n");
ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
}
static int
iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
iwi_parent(struct ieee80211com *ic)
{
struct iwi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct iwi_softc *sc = ic->ic_softc;
int startall = 0;
IWI_LOCK_DECL;
switch (cmd) {
case SIOCSIFFLAGS:
IWI_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
iwi_init_locked(sc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
iwi_stop_locked(sc);
IWI_LOCK(sc);
if (ic->ic_nrunning > 0) {
if (!sc->sc_running) {
iwi_init_locked(sc);
startall = 1;
}
IWI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
} else if (sc->sc_running)
iwi_stop_locked(sc);
IWI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static int
iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
{
struct ifreq *ifr = data;
struct iwi_softc *sc = ic->ic_softc;
int error;
IWI_LOCK_DECL;
IWI_LOCK(sc);
switch (cmd) {
case SIOCGIWISTATS:
IWI_LOCK(sc);
/* XXX validate permissions/memory/etc? */
error = copyout(&sc->sc_linkqual, ifr->ifr_data,
sizeof(struct iwi_notif_link_quality));
IWI_UNLOCK(sc);
break;
case SIOCZIWISTATS:
IWI_LOCK(sc);
memset(&sc->sc_linkqual, 0,
sizeof(struct iwi_notif_link_quality));
IWI_UNLOCK(sc);
error = 0;
break;
default:
error = EINVAL;
error = ENOTTY;
break;
}
return error;
IWI_UNLOCK(sc);
return (error);
}
static void
@ -2593,8 +2550,7 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap *vap)
static int
iwi_config(struct iwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct iwi_configuration config;
struct iwi_rateset rs;
struct iwi_txpower power;
@ -2603,8 +2559,8 @@ iwi_config(struct iwi_softc *sc)
IWI_LOCK_ASSERT(sc);
DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":"));
error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":"));
error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
IEEE80211_ADDR_LEN);
if (error != 0)
return error;
@ -2724,7 +2680,7 @@ iwi_monitor_scan(void *arg, int npending)
static int
iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
{
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *chan;
struct ieee80211_scan_state *ss;
struct iwi_scan_ext scan;
@ -2741,7 +2697,6 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
}
IWI_STATE_BEGIN(sc, IWI_FW_SCANNING);
ic = sc->sc_ifp->if_l2com;
ss = ic->ic_scan;
memset(&scan, 0, sizeof scan);
@ -3128,7 +3083,6 @@ iwi_init_fw_dma(struct iwi_softc *sc, int size)
static void
iwi_init_locked(struct iwi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct iwi_rx_data *data;
int i;
@ -3202,8 +3156,7 @@ iwi_init_locked(struct iwi_softc *sc)
}
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_running = 1;
return;
fail:
IWI_STATE_END(sc, IWI_FW_LOADING);
@ -3215,15 +3168,14 @@ static void
iwi_init(void *priv)
{
struct iwi_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_DECL;
IWI_LOCK(sc);
iwi_init_locked(sc);
IWI_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_running)
ieee80211_start_all(ic);
}
@ -3231,11 +3183,10 @@ static void
iwi_stop_locked(void *priv)
{
struct iwi_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
IWI_LOCK_ASSERT(sc);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_running = 0;
if (sc->sc_softled) {
callout_stop(&sc->sc_ledtimer);
@ -3296,7 +3247,7 @@ static void
iwi_radio_on(void *arg, int pending)
{
struct iwi_softc *sc = arg;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
device_printf(sc->sc_dev, "radio turned on\n");
@ -3317,10 +3268,7 @@ iwi_rfkill_poll(void *arg)
* it is enabled so we must poll for the latter.
*/
if (!iwi_getrfkill(sc)) {
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
ieee80211_runtask(ic, &sc->sc_radiontask);
ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask);
return;
}
callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc);
@ -3330,7 +3278,7 @@ static void
iwi_radio_off(void *arg, int pending)
{
struct iwi_softc *sc = arg;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_DECL;
device_printf(sc->sc_dev, "radio turned off\n");
@ -3594,8 +3542,8 @@ iwi_scan_start(struct ieee80211com *ic)
static void
iwi_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
if (sc->fw_state == IWI_FW_IDLE)
iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
}
@ -3604,8 +3552,7 @@ static void
iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
struct iwi_softc *sc = vap->iv_ic->ic_softc;
IWI_LOCK_DECL;
IWI_LOCK(sc);
@ -3623,8 +3570,7 @@ iwi_scan_mindwell(struct ieee80211_scan_state *ss)
static void
iwi_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
struct iwi_softc *sc = ic->ic_softc;
IWI_LOCK_DECL;
IWI_LOCK(sc);

View File

@ -125,11 +125,13 @@ struct iwi_vap {
#define IWI_VAP(vap) ((struct iwi_vap *)(vap))
struct iwi_softc {
struct ifnet *sc_ifp;
void (*sc_node_free)(struct ieee80211_node *);
struct mtx sc_mtx;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct mtx sc_mtx;
void (*sc_node_free)(struct ieee80211_node *);
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
struct unrhdr *sc_unr;
@ -193,7 +195,8 @@ struct iwi_softc {
struct task sc_wmetask; /* set wme parameters */
struct task sc_monitortask;
unsigned int sc_softled : 1, /* enable LED gpio status */
unsigned int sc_running : 1, /* initialized */
sc_softled : 1, /* enable LED gpio status */
sc_ledstate: 1, /* LED on/off state */
sc_blinking: 1; /* LED blink operation active */
u_int sc_nictype; /* NIC type from EEPROM */

View File

@ -235,10 +235,11 @@ static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
static void iwn_xmit_task(void *arg0, int pending);
static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void iwn_start(struct ifnet *);
static void iwn_start_locked(struct ifnet *);
static int iwn_transmit(struct ieee80211com *, struct mbuf *);
static void iwn_start_locked(struct iwn_softc *);
static void iwn_watchdog(void *);
static int iwn_ioctl(struct ifnet *, u_long, caddr_t);
static int iwn_ioctl(struct ieee80211com *, u_long , void *);
static void iwn_parent(struct ieee80211com *);
static int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
static int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
int);
@ -336,7 +337,7 @@ static void iwn_radio_on(void *, int);
static void iwn_radio_off(void *, int);
static void iwn_panicked(void *, int);
static void iwn_init_locked(struct iwn_softc *);
static void iwn_init(void *);
static void iwn_init(struct iwn_softc *);
static void iwn_stop_locked(struct iwn_softc *);
static void iwn_stop(struct iwn_softc *);
static void iwn_scan_start(struct ieee80211com *);
@ -406,9 +407,7 @@ iwn_attach(device_t dev)
{
struct iwn_softc *sc = (struct iwn_softc *)device_get_softc(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
int i, error, rid;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@ -464,6 +463,7 @@ iwn_attach(device_t dev)
}
IWN_LOCK_INIT(sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/* Read hardware revision and attach. */
sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
@ -549,14 +549,7 @@ iwn_attach(device_t dev)
/* Clear pending interrupts. */
IWN_WRITE(sc, IWN_INT, 0xffffffff);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not allocate ifnet structure\n");
goto fail;
}
ic = ifp->if_l2com;
ic->ic_ifp = ifp;
ic = &sc->sc_ic;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -581,7 +574,7 @@ iwn_attach(device_t dev)
;
/* Read MAC address, channels, etc from EEPROM. */
if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) {
device_printf(dev, "could not read EEPROM, error %d\n",
error);
goto fail;
@ -599,7 +592,7 @@ iwn_attach(device_t dev)
if (bootverbose) {
device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n",
sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
macaddr, ":");
ic->ic_macaddr, ":");
}
if (sc->sc_flags & IWN_FLAG_HAS_11N) {
@ -640,19 +633,12 @@ iwn_attach(device_t dev)
;
}
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = iwn_init;
ifp->if_ioctl = iwn_ioctl;
ifp->if_start = iwn_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_vap_create = iwn_vap_create;
ic->ic_ioctl = iwn_ioctl;
ic->ic_parent = iwn_parent;
ic->ic_vap_delete = iwn_vap_delete;
ic->ic_transmit = iwn_transmit;
ic->ic_raw_xmit = iwn_raw_xmit;
ic->ic_node_alloc = iwn_node_alloc;
sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
@ -1293,10 +1279,9 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
static void
iwn_radiotap_attach(struct iwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
ieee80211_radiotap_attach(ic,
ieee80211_radiotap_attach(&sc->sc_ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
IWN_TX_RADIOTAP_PRESENT,
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
@ -1326,21 +1311,14 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
struct iwn_softc *sc = ic->ic_softc;
struct iwn_vap *ivp;
struct ieee80211vap *vap;
uint8_t mac1[IEEE80211_ADDR_LEN];
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
IEEE80211_ADDR_COPY(mac1, mac);
ivp = (struct iwn_vap *) malloc(sizeof(struct iwn_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (ivp == NULL)
return NULL;
ivp = malloc(sizeof(struct iwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->iv_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
ivp->ctx = IWN_RXON_BSS_CTX;
IEEE80211_ADDR_COPY(ivp->macaddr, mac1);
vap->iv_bmissthreshold = 10; /* override default */
/* Override with driver methods. */
ivp->iv_newstate = vap->iv_newstate;
@ -1349,7 +1327,8 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* Complete setup. */
ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status,
mac);
ic->ic_opmode = opmode;
return vap;
}
@ -1390,24 +1369,19 @@ static int
iwn_detach(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
int qid;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
if (ifp != NULL) {
ic = ifp->if_l2com;
if (sc->sc_ic.ic_softc != NULL) {
/* Free the mbuf queue and node references */
IWN_LOCK(sc);
iwn_xmit_queue_drain(sc);
IWN_UNLOCK(sc);
ieee80211_draintask(ic, &sc->sc_reinit_task);
ieee80211_draintask(ic, &sc->sc_radioon_task);
ieee80211_draintask(ic, &sc->sc_radiooff_task);
ieee80211_draintask(&sc->sc_ic, &sc->sc_reinit_task);
ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task);
ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task);
iwn_stop(sc);
taskqueue_drain_all(sc->sc_tq);
@ -1415,9 +1389,11 @@ iwn_detach(device_t dev)
callout_drain(&sc->watchdog_to);
callout_drain(&sc->calib_to);
ieee80211_ifdetach(ic);
ieee80211_ifdetach(&sc->sc_ic);
}
mbufq_drain(&sc->sc_snd);
/* Uninstall interrupt handler. */
if (sc->irq != NULL) {
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@ -1440,9 +1416,6 @@ iwn_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
rman_get_rid(sc->mem), sc->mem);
if (ifp != NULL)
if_free(ifp);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n", __func__);
IWN_LOCK_DESTROY(sc);
return 0;
@ -1461,9 +1434,8 @@ static int
iwn_suspend(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
ieee80211_suspend_all(ic);
ieee80211_suspend_all(&sc->sc_ic);
return 0;
}
@ -1471,12 +1443,11 @@ static int
iwn_resume(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
/* Clear device-specific "PCI retry timeout" register (41h). */
pci_write_config(dev, 0x41, 0, 1);
ieee80211_resume_all(ic);
ieee80211_resume_all(&sc->sc_ic);
return 0;
}
@ -2385,8 +2356,7 @@ iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
static void
iwn_read_eeprom_band(struct iwn_softc *sc, int n)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
const struct iwn_chan_band *band = &iwn_bands[n];
struct ieee80211_channel *c;
@ -2445,8 +2415,7 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
static void
iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
const struct iwn_chan_band *band = &iwn_bands[n];
struct ieee80211_channel *c, *cent, *extc;
@ -2514,8 +2483,7 @@ iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
static void
iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
@ -2583,8 +2551,7 @@ static void
iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
{
struct iwn_eeprom_enhinfo enhinfo[35];
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
uint16_t val, base;
int8_t maxpwr;
@ -2967,8 +2934,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct iwn_rx_ring *ring = &sc->rxq;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
@ -3015,14 +2981,14 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) {
DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n",
__func__, flags);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
/* Discard frames that are too short. */
if (len < sizeof (struct ieee80211_frame_ack)) {
DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n",
__func__, len);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -3030,7 +2996,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (m1 == NULL) {
DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n",
__func__);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
bus_dmamap_unload(ring->data_dmat, data->map);
@ -3053,7 +3019,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
ring->desc[ring->cur] = htole32(paddr >> 8);
bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -3065,7 +3031,6 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
BUS_DMASYNC_PREWRITE);
/* Finalize mbuf. */
m->m_pkthdr.rcvif = ifp;
m->m_data = head;
m->m_pkthdr.len = m->m_len = len;
@ -3159,7 +3124,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct iwn_node *wn;
struct ieee80211_node *ni;
struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
@ -3240,12 +3204,10 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
for (i = 0; bitmap; i++) {
if ((bitmap & 1) == 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
tx_err ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
} else {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
tx_ok ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
@ -3391,8 +3353,7 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwn_calib_state *calib = &sc->calib;
struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
@ -3565,7 +3526,6 @@ static void
iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
uint8_t status)
{
struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
struct iwn_tx_data *data = &ring->data[desc->idx];
struct mbuf *m;
@ -3586,15 +3546,12 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
/*
* Update rate control statistics for the node.
*/
if (status & IWN_TX_FAIL) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (status & IWN_TX_FAIL)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
} else {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
else
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
}
/*
* Channels marked for "radar" require traffic to be received
@ -3620,11 +3577,8 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
sc->sc_tx_timer = 0;
if (--ring->queued < IWN_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
if (sc->qfullmsk == 0 &&
(ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
iwn_start_locked(ifp);
}
if (sc->qfullmsk == 0)
iwn_start_locked(sc);
}
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@ -3669,7 +3623,6 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
int ackfailcnt, void *stat)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[qid];
struct iwn_tx_data *data;
struct mbuf *m;
@ -3808,11 +3761,8 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
sc->sc_tx_timer = 0;
if (ring->queued < IWN_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
if (sc->qfullmsk == 0 &&
(ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
iwn_start_locked(ifp);
}
if (sc->qfullmsk == 0)
iwn_start_locked(sc);
}
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@ -3826,8 +3776,7 @@ static void
iwn_notif_intr(struct iwn_softc *sc)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t hw;
@ -4021,8 +3970,7 @@ iwn_wakeup_intr(struct iwn_softc *sc)
static void
iwn_rftoggle_intr(struct iwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp = IWN_READ(sc, IWN_GP_CNTRL);
IWN_LOCK_ASSERT(sc);
@ -4101,7 +4049,6 @@ static void
iwn_intr(void *arg)
{
struct iwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
uint32_t r1, r2, tmp;
IWN_LOCK(sc);
@ -4194,7 +4141,7 @@ iwn_intr(void *arg)
done:
/* Re-enable interrupts. */
if (ifp->if_flags & IFF_UP)
if (sc->sc_flags & IWN_FLAG_RUNNING)
IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
IWN_UNLOCK(sc);
@ -4678,9 +4625,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
struct iwn_ops *ops = &sc->ops;
// struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap = ni->ni_vap;
// struct ieee80211com *ic = ifp->if_l2com;
struct iwn_tx_cmd *cmd;
struct iwn_cmd_data *tx;
struct ieee80211_frame *wh;
@ -4875,7 +4820,6 @@ static void
iwn_xmit_task(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_node *ni;
struct mbuf *m;
int error;
@ -4907,8 +4851,9 @@ iwn_xmit_task(void *arg0, int pending)
error = iwn_tx_data(sc, m, ni);
if (error != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
}
@ -4921,13 +4866,12 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
struct iwn_softc *sc = ic->ic_softc;
int error = 0;
DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@ -4942,8 +4886,9 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (sc->sc_beacon_wait) {
if (iwn_xmit_queue_enqueue(sc, m) != 0) {
m_freem(m);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
IWN_UNLOCK(sc);
return (ENOBUFS);
}
@ -4968,7 +4913,6 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (error != 0) {
/* NB: m is reclaimed on tx failure */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else
sc->sc_tx_timer = 5;
@ -4979,20 +4923,32 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return error;
}
static void
iwn_start(struct ifnet *ifp)
static int
iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct iwn_softc *sc = ifp->if_softc;
struct iwn_softc *sc;
int error;
sc = ic->ic_softc;
IWN_LOCK(sc);
iwn_start_locked(ifp);
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
IWN_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
IWN_UNLOCK(sc);
return (error);
}
iwn_start_locked(sc);
IWN_UNLOCK(sc);
return (0);
}
static void
iwn_start_locked(struct ifnet *ifp)
iwn_start_locked(struct iwn_softc *sc)
{
struct iwn_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
@ -5007,27 +4963,16 @@ iwn_start_locked(struct ifnet *ifp)
}
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ifp->if_drv_flags & IFF_DRV_OACTIVE))
return;
for (;;) {
if (sc->qfullmsk != 0) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while (sc->qfullmsk == 0 &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (iwn_tx_data(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else
sc->sc_tx_timer = 5;
}
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__);
}
@ -5035,12 +4980,11 @@ static void
iwn_watchdog(void *arg)
{
struct iwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
IWN_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
KASSERT(sc->sc_flags & IWN_FLAG_RUNNING, ("not running"));
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@ -5055,41 +4999,13 @@ iwn_watchdog(void *arg)
}
static int
iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
{
struct iwn_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0, stop = 0;
struct ifreq *ifr = data;
struct iwn_softc *sc = ic->ic_softc;
int error = 0;
switch (cmd) {
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
case SIOCSIFFLAGS:
IWN_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
iwn_init_locked(sc);
if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
startall = 1;
else
stop = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
iwn_stop_locked(sc);
}
IWN_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
else if (vap != NULL && stop)
ieee80211_stop(vap);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIWNSTATS:
IWN_LOCK(sc);
/* XXX validate permissions/memory/etc? */
@ -5103,10 +5019,35 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
IWN_UNLOCK(sc);
break;
default:
error = EINVAL;
error = ENOTTY;
break;
}
return error;
return (error);
}
static void
iwn_parent(struct ieee80211com *ic)
{
struct iwn_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int startall = 0, stop = 0;
IWN_LOCK(sc);
if (ic->ic_nrunning > 0) {
if (!(sc->sc_flags & IWN_FLAG_RUNNING)) {
iwn_init_locked(sc);
if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
startall = 1;
else
stop = 1;
}
} else if (sc->sc_flags & IWN_FLAG_RUNNING)
iwn_stop_locked(sc);
IWN_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
else if (vap != NULL && stop)
ieee80211_stop(vap);
}
/*
@ -5340,8 +5281,7 @@ static int
iwn_add_broadcast_node(struct iwn_softc *sc, int async)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct iwn_node_info node;
struct iwn_cmd_link_quality linkq;
uint8_t txant;
@ -5352,7 +5292,7 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async)
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
memset(&node, 0, sizeof node);
IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr);
node.id = sc->broadcast_id;
DPRINTF(sc, IWN_DEBUG_RESET, "%s: adding broadcast node\n", __func__);
if ((error = ops->add_node(sc, &node, async)) != 0)
@ -5501,8 +5441,7 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
static void
iwn4965_power_calibration(struct iwn_softc *sc, int temp)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@ -5872,8 +5811,7 @@ iwn_collect_noise(struct iwn_softc *sc,
{
struct iwn_ops *ops = &sc->ops;
struct iwn_calib_state *calib = &sc->calib;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t val;
int i;
@ -6506,9 +6444,8 @@ iwn5000_runtime_calib(struct iwn_softc *sc)
static uint32_t
iwn_get_rxon_ht_flags(struct iwn_softc *sc, struct ieee80211_channel *c)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t htflags = 0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
if (! IEEE80211_IS_CHAN_HT(c))
return (0);
@ -6535,8 +6472,9 @@ static int
iwn_config(struct iwn_softc *sc)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
const uint8_t *macaddr;
uint32_t txmask;
uint16_t rxchain;
int error;
@ -6618,8 +6556,9 @@ iwn_config(struct iwn_softc *sc)
/* Set mode, channel, RX filter and enable RX. */
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
memset(sc->rxon, 0, sizeof (struct iwn_rxon));
IEEE80211_ADDR_COPY(sc->rxon->myaddr, IF_LLADDR(ifp));
IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
IEEE80211_ADDR_COPY(sc->rxon->myaddr, macaddr);
IEEE80211_ADDR_COPY(sc->rxon->wlap, macaddr);
sc->rxon->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
@ -6732,7 +6671,7 @@ iwn_get_active_dwell_time(struct iwn_softc *sc,
static uint16_t
iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = NULL;
int bintval = 0;
@ -6780,8 +6719,7 @@ static int
iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
struct ieee80211_scan_state *ss, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_scan_hdr *hdr;
struct iwn_cmd_data *tx;
@ -6919,9 +6857,9 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(vap->iv_ifp));
IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_ifp->if_broadcastaddr);
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
@ -7040,8 +6978,7 @@ static int
iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
int error;
@ -7113,8 +7050,7 @@ static int
iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_node_info node;
int error;
@ -8685,8 +8621,7 @@ static void
iwn_radio_on(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@ -8701,8 +8636,7 @@ static void
iwn_radio_off(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@ -8722,8 +8656,7 @@ static void
iwn_panicked(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int error;
@ -8751,7 +8684,7 @@ iwn_panicked(void *arg0, int pending)
}
/* Only run start once the NIC is in a useful state, like associated */
iwn_start_locked(sc->sc_ifp);
iwn_start_locked(sc);
IWN_UNLOCK(sc);
}
@ -8759,13 +8692,14 @@ iwn_panicked(void *arg0, int pending)
static void
iwn_init_locked(struct iwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int error;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
IWN_LOCK_ASSERT(sc);
sc->sc_flags |= IWN_FLAG_RUNNING;
if ((error = iwn_hw_prepare(sc)) != 0) {
device_printf(sc->sc_dev, "%s: hardware not ready, error %d\n",
__func__, error);
@ -8813,38 +8747,33 @@ iwn_init_locked(struct iwn_softc *sc)
goto fail;
}
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
return;
fail: iwn_stop_locked(sc);
fail:
sc->sc_flags &= ~IWN_FLAG_RUNNING;
iwn_stop_locked(sc);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
}
static void
iwn_init(void *arg)
iwn_init(struct iwn_softc *sc)
{
struct iwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
IWN_LOCK(sc);
iwn_init_locked(sc);
IWN_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic);
if (sc->sc_flags & IWN_FLAG_RUNNING)
ieee80211_start_all(&sc->sc_ic);
}
static void
iwn_stop_locked(struct iwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
IWN_LOCK_ASSERT(sc);
@ -8852,7 +8781,7 @@ iwn_stop_locked(struct iwn_softc *sc)
sc->sc_tx_timer = 0;
callout_stop(&sc->watchdog_to);
callout_stop(&sc->calib_to);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~IWN_FLAG_RUNNING;
/* Power OFF hardware. */
iwn_hw_stop(sc);
@ -8872,8 +8801,7 @@ iwn_stop(struct iwn_softc *sc)
static void
iwn_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
struct iwn_softc *sc = ic->ic_softc;
IWN_LOCK(sc);
/* make the link LED blink while we're scanning */
@ -8887,8 +8815,7 @@ iwn_scan_start(struct ieee80211com *ic)
static void
iwn_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
struct iwn_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
IWN_LOCK(sc);
@ -8906,8 +8833,7 @@ static void
iwn_set_channel(struct ieee80211com *ic)
{
const struct ieee80211_channel *c = ic->ic_curchan;
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
struct iwn_softc *sc = ic->ic_softc;
int error;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@ -8964,8 +8890,7 @@ static void
iwn_hw_reset(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);

View File

@ -228,18 +228,16 @@ struct iwn_vap {
enum ieee80211_state, int);
int ctx;
int beacon_int;
uint8_t macaddr[IEEE80211_ADDR_LEN];
};
#define IWN_VAP(_vap) ((struct iwn_vap *)(_vap))
struct iwn_softc {
device_t sc_dev;
struct ifnet *sc_ifp;
int sc_debug;
struct mtx sc_mtx;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
u_int sc_flags;
#define IWN_FLAG_HAS_OTPROM (1 << 1)
@ -251,6 +249,7 @@ struct iwn_softc {
#define IWN_FLAG_ADV_BTCOEX (1 << 8)
#define IWN_FLAG_PAN_SUPPORT (1 << 9)
#define IWN_FLAG_BTCOEX (1 << 10)
#define IWN_FLAG_RUNNING (1 << 11)
uint8_t hw_type;
/* subdevice_id used to adjust configuration */
@ -320,7 +319,6 @@ struct iwn_softc {
struct iwn_calib_state calib;
int last_calib_ticks;
struct callout watchdog_to;
struct callout ct_kill_exit_to;
struct iwn_fw_info fw;
struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT];
uint32_t errptr;

View File

@ -102,13 +102,9 @@ enum {
(IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON))
#define IFF_DUMPPKTS_RECV(sc, wh) \
(((sc->malo_debug & MALO_DEBUG_RECV) && \
((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \
(sc->malo_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == \
(IFF_DEBUG|IFF_LINK2))
((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))))
#define IFF_DUMPPKTS_XMIT(sc) \
((sc->malo_debug & MALO_DEBUG_XMIT) || \
(sc->malo_ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == \
(IFF_DEBUG | IFF_LINK2))
(sc->malo_debug & MALO_DEBUG_XMIT)
#define DPRINTF(sc, m, fmt, ...) do { \
if (sc->malo_debug & (m)) \
printf(fmt, __VA_ARGS__); \
@ -130,9 +126,10 @@ static int malo_dma_setup(struct malo_softc *);
static int malo_setup_hwdma(struct malo_softc *);
static void malo_txq_init(struct malo_softc *, struct malo_txq *, int);
static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *);
static void malo_start(struct ifnet *);
static void malo_parent(struct ieee80211com *);
static int malo_transmit(struct ieee80211com *, struct mbuf *);
static void malo_start(struct malo_softc *);
static void malo_watchdog(void *);
static int malo_ioctl(struct ifnet *, u_long, caddr_t);
static void malo_updateslot(struct ieee80211com *);
static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void malo_scan_start(struct ieee80211com *);
@ -143,7 +140,7 @@ static int malo_raw_xmit(struct ieee80211_node *, struct mbuf *,
static void malo_sysctlattach(struct malo_softc *);
static void malo_announce(struct malo_softc *);
static void malo_dma_cleanup(struct malo_softc *);
static void malo_stop_locked(struct ifnet *, int);
static void malo_stop(struct malo_softc *);
static int malo_chan_set(struct malo_softc *, struct ieee80211_channel *);
static int malo_mode_init(struct malo_softc *);
static void malo_tx_proc(void *, int);
@ -173,30 +170,19 @@ malo_bar0_write4(struct malo_softc *sc, bus_size_t off, uint32_t val)
int
malo_attach(uint16_t devid, struct malo_softc *sc)
{
int error;
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh;
int error;
uint8_t bands;
ifp = sc->malo_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->malo_dev, "can not if_alloc()\n");
return ENOSPC;
}
ic = ifp->if_l2com;
MALO_LOCK_INIT(sc);
callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0);
/* set these up early for if_printf use */
if_initname(ifp, device_get_name(sc->malo_dev),
device_get_unit(sc->malo_dev));
mbufq_init(&sc->malo_snd, ifqmaxlen);
mh = malo_hal_attach(sc->malo_dev, devid,
sc->malo_io1h, sc->malo_io1t, sc->malo_dmat);
if (mh == NULL) {
if_printf(ifp, "unable to attach HAL\n");
device_printf(sc->malo_dev, "unable to attach HAL\n");
error = EIO;
goto bad;
}
@ -209,13 +195,13 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
*/
error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m");
if (error != 0) {
if_printf(ifp, "unable to setup firmware\n");
device_printf(sc->malo_dev, "unable to setup firmware\n");
goto bad1;
}
/* XXX gethwspecs() extracts correct informations? not maybe! */
error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs);
if (error != 0) {
if_printf(ifp, "unable to fetch h/w specs\n");
device_printf(sc->malo_dev, "unable to fetch h/w specs\n");
goto bad1;
}
@ -251,7 +237,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
*/
error = malo_dma_setup(sc);
if (error != 0) {
if_printf(ifp, "failed to setup descriptors: %d\n", error);
device_printf(sc->malo_dev,
"failed to setup descriptors: %d\n", error);
goto bad1;
}
error = malo_setup_hwdma(sc); /* push to firmware */
@ -261,21 +248,11 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->malo_tq);
taskqueue_start_threads(&sc->malo_tq, 1, PI_NET,
"%s taskq", ifp->if_xname);
"%s taskq", device_get_nameunit(sc->malo_dev));
TASK_INIT(&sc->malo_rxtask, 0, malo_rx_proc, sc);
TASK_INIT(&sc->malo_txtask, 0, malo_tx_proc, sc);
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
ifp->if_start = malo_start;
ifp->if_ioctl = malo_ioctl;
ifp->if_init = malo_init;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->malo_dev);
/* XXX not right but it's not used anywhere important */
@ -290,6 +267,7 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
| IEEE80211_C_TXPMGT /* capable of txpow mgt */
| IEEE80211_C_WPA /* capable of WPA1+WPA2 */
;
IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr);
/*
* Transmit requires space in the packet for a special format transmit
@ -301,16 +279,17 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
sizeof(struct ieee80211_frame);
/* call MI attach routine. */
ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr);
ieee80211_ifattach(ic);
/* override default methods */
ic->ic_vap_create = malo_vap_create;
ic->ic_vap_delete = malo_vap_delete;
ic->ic_raw_xmit = malo_raw_xmit;
ic->ic_updateslot = malo_updateslot;
ic->ic_scan_start = malo_scan_start;
ic->ic_scan_end = malo_scan_end;
ic->ic_set_channel = malo_set_channel;
ic->ic_parent = malo_parent;
ic->ic_transmit = malo_transmit;
sc->malo_invalid = 0; /* ready to go, enable int handling */
@ -335,7 +314,6 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
bad1:
malo_hal_detach(mh);
bad:
if_free(ifp);
sc->malo_invalid = 1;
return error;
@ -347,12 +325,12 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct malo_softc *sc = ic->ic_softc;
struct malo_vap *mvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
if_printf(ifp, "multiple vaps not supported\n");
device_printf(sc->malo_dev, "multiple vaps not supported\n");
return NULL;
}
switch (opmode) {
@ -363,18 +341,13 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MONITOR:
break;
default:
if_printf(ifp, "%s mode not supported\n",
device_printf(sc->malo_dev, "%s mode not supported\n",
ieee80211_opmode_name[opmode]);
return NULL; /* unsupported */
}
mvp = (struct malo_vap *) malloc(sizeof(struct malo_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (mvp == NULL) {
if_printf(ifp, "cannot allocate vap state block\n");
return NULL;
}
mvp = malloc(sizeof(struct malo_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &mvp->malo_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
mvp->malo_newstate = vap->iv_newstate;
@ -382,7 +355,7 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap,
ieee80211_media_change, ieee80211_media_status);
ieee80211_media_change, ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@ -461,7 +434,6 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
int nbuf, size_t bufsize, int ndesc, size_t descsize)
{
int error;
struct ifnet *ifp = sc->malo_ifp;
uint8_t *ds;
DPRINTF(sc, MALO_DEBUG_RESET,
@ -488,7 +460,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
NULL, /* lockarg */
&dd->dd_dmat);
if (error != 0) {
if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
device_printf(sc->malo_dev, "cannot allocate %s DMA tag\n",
dd->dd_name);
return error;
}
@ -496,7 +469,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap);
if (error != 0) {
if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
device_printf(sc->malo_dev,
"unable to alloc memory for %u %s descriptors, "
"error %u\n", nbuf * ndesc, dd->dd_name, error);
goto fail1;
}
@ -505,7 +479,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
dd->dd_desc, dd->dd_desc_len,
malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT);
if (error != 0) {
if_printf(ifp, "unable to map %s descriptors, error %u\n",
device_printf(sc->malo_dev,
"unable to map %s descriptors, error %u\n",
dd->dd_name, error);
goto fail2;
}
@ -532,7 +507,6 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
static int
malo_rxdma_setup(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
int error, bsize, i;
struct malo_rxbuf *bf;
struct malo_rxdesc *ds;
@ -549,7 +523,8 @@ malo_rxdma_setup(struct malo_softc *sc)
bsize = malo_rxbuf * sizeof(struct malo_rxbuf);
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
if_printf(ifp, "malloc of %u rx buffers failed\n", bsize);
device_printf(sc->malo_dev,
"malloc of %u rx buffers failed\n", bsize);
return error;
}
sc->malo_rxdma.dd_bufptr = bf;
@ -562,8 +537,9 @@ malo_rxdma_setup(struct malo_softc *sc)
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
if_printf(ifp, "%s: unable to dmamap for rx buffer, "
"error %d\n", __func__, error);
device_printf(sc->malo_dev,
"%s: unable to dmamap for rx buffer, error %d\n",
__func__, error);
return error;
}
/* NB: tail is intentional to preserve descriptor order */
@ -575,7 +551,6 @@ malo_rxdma_setup(struct malo_softc *sc)
static int
malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
{
struct ifnet *ifp = sc->malo_ifp;
int error, bsize, i;
struct malo_txbuf *bf;
struct malo_txdesc *ds;
@ -590,7 +565,7 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
bsize = malo_txbuf * sizeof(struct malo_txbuf);
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
if_printf(ifp, "malloc of %u tx buffers failed\n",
device_printf(sc->malo_dev, "malloc of %u tx buffers failed\n",
malo_txbuf);
return ENOMEM;
}
@ -605,7 +580,8 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
if_printf(ifp, "unable to create dmamap for tx "
device_printf(sc->malo_dev,
"unable to create dmamap for tx "
"buffer %u, error %u\n", i, error);
return error;
}
@ -1004,33 +980,19 @@ malo_tx_processq(struct malo_softc *sc, struct malo_txq *txq)
if (status & MALO_TXD_STATUS_FAILED_AGING)
sc->malo_stats.mst_tx_aging++;
}
/*
* Do any tx complete callback. Note this must
* be done before releasing the node reference.
* XXX no way to figure out if frame was ACK'd
*/
if (bf->bf_m->m_flags & M_TXCB) {
/* XXX strip fw len in case header inspected */
m_adj(bf->bf_m, sizeof(uint16_t));
ieee80211_process_callback(ni, bf->bf_m,
(status & MALO_TXD_STATUS_OK) == 0);
}
/*
* Reclaim reference to node.
*
* NB: the node may be reclaimed here if, for example
* this is a DEAUTH message that was sent and the
* node was timed out due to inactivity.
*/
ieee80211_free_node(ni);
}
/* XXX strip fw len in case header inspected */
m_adj(bf->bf_m, sizeof(uint16_t));
ieee80211_tx_complete(ni, bf->bf_m,
(status & MALO_TXD_STATUS_OK) == 0);
} else
m_freem(bf->bf_m);
ds->status = htole32(MALO_TXD_STATUS_IDLE);
ds->pktlen = htole32(0);
bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap);
m_freem(bf->bf_m);
bf->bf_m = NULL;
bf->bf_node = NULL;
@ -1049,23 +1011,23 @@ static void
malo_tx_proc(void *arg, int npending)
{
struct malo_softc *sc = arg;
struct ifnet *ifp = sc->malo_ifp;
int i, nreaped;
/*
* Process each active queue.
*/
nreaped = 0;
MALO_LOCK(sc);
for (i = 0; i < MALO_NUM_TX_QUEUES; i++) {
if (!STAILQ_EMPTY(&sc->malo_txq[i].active))
nreaped += malo_tx_processq(sc, &sc->malo_txq[i]);
}
if (nreaped != 0) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->malo_timer = 0;
malo_start(ifp);
malo_start(sc);
}
MALO_UNLOCK(sc);
}
static int
@ -1079,8 +1041,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
int error, ismcast, iswep;
int copyhdrlen, hdrlen, pktlen;
struct ieee80211_frame *wh;
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct malo_txdesc *ds;
struct malo_txrec *tr;
@ -1225,7 +1186,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
ds->txpriority = txq->qnum;
break;
default:
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
device_printf(sc->malo_dev, "bogus frame type 0x%x (%s)\n",
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
/* XXX statistic */
m_freem(m0);
@ -1246,37 +1207,52 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
STAILQ_INSERT_TAIL(&txq->active, bf, bf_list);
MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
sc->malo_timer = 5;
MALO_TXQ_UNLOCK(txq);
return 0;
#undef IEEE80211_DIR_DSTODS
}
static void
malo_start(struct ifnet *ifp)
static int
malo_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct malo_softc *sc = ic->ic_softc;
int error;
MALO_LOCK(sc);
if (!sc->malo_running) {
MALO_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->malo_snd, m);
if (error) {
MALO_UNLOCK(sc);
return (error);
}
malo_start(sc);
MALO_UNLOCK(sc);
return (0);
}
static void
malo_start(struct malo_softc *sc)
{
struct malo_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct malo_txq *txq = &sc->malo_txq[0];
struct malo_txbuf *bf = NULL;
struct mbuf *m;
int nqueued = 0;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid)
MALO_LOCK_ASSERT(sc);
if (!sc->malo_running || sc->malo_invalid)
return;
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->malo_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
bf = malo_getbuf(sc, txq);
if (bf == NULL) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
/* XXX blocks other traffic */
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
mbufq_prepend(&sc->malo_snd, m);
sc->malo_stats.mst_tx_qstop++;
break;
}
@ -1284,7 +1260,8 @@ malo_start(struct ifnet *ifp)
* Pass the frame to the h/w for transmission.
*/
if (malo_tx_start(sc, ni, bf, m)) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
if (bf != NULL) {
bf->bf_m = NULL;
bf->bf_node = NULL;
@ -1328,21 +1305,18 @@ malo_start(struct ifnet *ifp)
static void
malo_watchdog(void *arg)
{
struct malo_softc *sc;
struct ifnet *ifp;
struct malo_softc *sc = arg;
sc = arg;
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
if (sc->malo_timer == 0 || --sc->malo_timer > 0)
return;
ifp = sc->malo_ifp;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) {
if_printf(ifp, "watchdog timeout\n");
if (sc->malo_running && !sc->malo_invalid) {
device_printf(sc->malo_dev, "watchdog timeout\n");
/* XXX no way to reset h/w. now */
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->malo_ic.ic_oerrors, 1);
sc->malo_stats.mst_watchdog++;
}
}
@ -1351,8 +1325,7 @@ static int
malo_hal_reset(struct malo_softc *sc)
{
static int first = 0;
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh = sc->malo_mh;
if (first == 0) {
@ -1392,7 +1365,7 @@ malo_getrxmbuf(struct malo_softc *sc, struct malo_rxbuf *bf)
mtod(m, caddr_t), MJUMPAGESIZE,
malo_load_cb, &paddr, BUS_DMA_NOWAIT);
if (error != 0) {
if_printf(sc->malo_ifp,
device_printf(sc->malo_dev,
"%s: bus_dmamap_load failed, error %d\n", __func__, error);
m_freem(m);
return NULL;
@ -1483,26 +1456,23 @@ malo_startrecv(struct malo_softc *sc)
static void
malo_init_locked(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
struct malo_hal *mh = sc->malo_mh;
int error;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
__func__, ifp->if_flags);
MALO_LOCK_ASSERT(sc);
/*
* Stop anything previously setup. This is safe whether this is
* the first time through or not.
*/
malo_stop_locked(ifp, 0);
malo_stop(sc);
/*
* Push state to the firmware.
*/
if (!malo_hal_reset(sc)) {
if_printf(ifp, "%s: unable to reset hardware\n", __func__);
device_printf(sc->malo_dev,
"%s: unable to reset hardware\n", __func__);
return;
}
@ -1511,7 +1481,8 @@ malo_init_locked(struct malo_softc *sc)
*/
error = malo_startrecv(sc);
if (error != 0) {
if_printf(ifp, "%s: unable to start recv logic, error %d\n",
device_printf(sc->malo_dev,
"%s: unable to start recv logic, error %d\n",
__func__, error);
return;
}
@ -1528,7 +1499,7 @@ malo_init_locked(struct malo_softc *sc)
| MALO_A2HRIC_BIT_RADAR_DETECT
| MALO_A2HRIC_BIT_CHAN_SWITCH;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->malo_running = 1;
malo_hal_intrset(mh, sc->malo_imask);
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
}
@ -1537,18 +1508,13 @@ static void
malo_init(void *arg)
{
struct malo_softc *sc = (struct malo_softc *) arg;
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
__func__, ifp->if_flags);
MALO_LOCK(sc);
malo_init_locked(sc);
MALO_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->malo_running)
ieee80211_start_all(ic); /* start all vap's */
}
@ -1558,9 +1524,8 @@ malo_init(void *arg)
static void
malo_setmcastfilter(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ifmultiaddr *ifma;
struct ieee80211com *ic = &sc->malo_ic;
struct ieee80211vap *vap;
uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX];
uint8_t *mp;
int nmc;
@ -1568,26 +1533,32 @@ malo_setmcastfilter(struct malo_softc *sc)
mp = macs;
nmc = 0;
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)))
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
ic->ic_promisc > 0)
goto all;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (nmc == MALO_HAL_MCAST_MAX) {
ifp->if_flags |= IFF_ALLMULTI;
if_maddr_runlock(ifp);
goto all;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
struct ifnet *ifp;
struct ifmultiaddr *ifma;
ifp = vap->iv_ifp;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (nmc == MALO_HAL_MCAST_MAX) {
ifp->if_flags |= IFF_ALLMULTI;
if_maddr_runlock(ifp);
goto all;
}
IEEE80211_ADDR_COPY(mp,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
mp += IEEE80211_ADDR_LEN, nmc++;
}
IEEE80211_ADDR_COPY(mp,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
mp += IEEE80211_ADDR_LEN, nmc++;
if_maddr_runlock(ifp);
}
if_maddr_runlock(ifp);
malo_hal_setmcast(sc->malo_mh, nmc, macs);
@ -1602,8 +1573,7 @@ malo_setmcastfilter(struct malo_softc *sc)
static int
malo_mode_init(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh = sc->malo_mh;
/*
@ -1612,7 +1582,7 @@ malo_mode_init(struct malo_softc *sc)
* identify internal requests (from the bridge)
* versus external requests such as for tcpdump.
*/
malo_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) &&
malo_hal_setpromisc(mh, ic->ic_promisc > 0 &&
ic->ic_opmode != IEEE80211_M_HOSTAP);
malo_setmcastfilter(sc);
@ -1641,8 +1611,7 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
MALO_TXQ_UNLOCK(txq);
#ifdef MALO_DEBUG
if (sc->malo_debug & MALO_DEBUG_RESET) {
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
const struct malo_txrec *tr =
mtod(bf->bf_m, const struct malo_txrec *);
malo_printtxbuf(bf, txq->qnum, ix);
@ -1670,18 +1639,17 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
}
static void
malo_stop_locked(struct ifnet *ifp, int disable)
malo_stop(struct malo_softc *sc)
{
struct malo_softc *sc = ifp->if_softc;
struct malo_hal *mh = sc->malo_mh;
int i;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
__func__, sc->malo_invalid, ifp->if_flags);
DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u running %u\n",
__func__, sc->malo_invalid, sc->malo_running);
MALO_LOCK_ASSERT(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
if (!sc->malo_running)
return;
/*
@ -1693,10 +1661,10 @@ malo_stop_locked(struct ifnet *ifp, int disable)
* Note that some of this work is not possible if the hardware
* is gone (invalid).
*/
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->malo_running = 0;
callout_stop(&sc->malo_watchdog_timer);
sc->malo_timer = 0;
/* diable interrupt. */
/* disable interrupt. */
malo_hal_intrset(mh, 0);
/* turn off the radio. */
malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE);
@ -1706,57 +1674,38 @@ malo_stop_locked(struct ifnet *ifp, int disable)
malo_tx_draintxq(sc, &sc->malo_txq[i]);
}
static int
malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
malo_parent(struct ieee80211com *ic)
{
#define MALO_IS_RUNNING(ifp) \
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
struct malo_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct malo_softc *sc = ic->ic_softc;
int startall = 0;
MALO_LOCK(sc);
switch (cmd) {
case SIOCSIFFLAGS:
if (MALO_IS_RUNNING(ifp)) {
/*
* To avoid rescanning another access point,
* do not call malo_init() here. Instead,
* only reflect promisc mode settings.
*/
malo_mode_init(sc);
} else if (ifp->if_flags & IFF_UP) {
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
* will still be marked UP but not RUNNING.
* However trying to re-init the interface
* is the wrong thing to do as we've already
* torn down much of our state. There's
* probably a better way to deal with this.
*/
if (!sc->malo_invalid) {
malo_init_locked(sc);
startall = 1;
}
} else
malo_stop_locked(ifp, 1);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
default:
error = ether_ioctl(ifp, cmd, data);
break;
}
if (ic->ic_nrunning > 0) {
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
* will still be marked UP but not RUNNING.
* However trying to re-init the interface
* is the wrong thing to do as we've already
* torn down much of our state. There's
* probably a better way to deal with this.
*/
if (!sc->malo_running && !sc->malo_invalid) {
malo_init(sc);
startall = 1;
}
/*
* To avoid rescanning another access point,
* do not call malo_init() here. Instead,
* only reflect promisc mode settings.
*/
malo_mode_init(sc);
} else if (sc->malo_running)
malo_stop(sc);
MALO_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
return error;
#undef MALO_IS_RUNNING
}
/*
@ -1773,7 +1722,7 @@ malo_updateslot(struct ieee80211com *ic)
int error;
/* NB: can be called early; suppress needless cmds */
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if (!sc->malo_running)
return;
DPRINTF(sc, MALO_DEBUG_RESET,
@ -1795,7 +1744,7 @@ static int
malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
struct malo_softc *sc = ic->ic_ifp->if_softc;
struct malo_softc *sc = ic->ic_softc;
struct malo_hal *mh = sc->malo_mh;
int error;
@ -1839,12 +1788,11 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct malo_softc *sc = ifp->if_softc;
struct malo_softc *sc = ic->ic_softc;
struct malo_txbuf *bf;
struct malo_txq *txq;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid) {
if (!sc->malo_running || sc->malo_invalid) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@ -1859,8 +1807,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
txq = &sc->malo_txq[0];
bf = malo_getbuf(sc, txq);
if (bf == NULL) {
/* XXX blocks other traffic */
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ieee80211_free_node(ni);
m_freem(m);
return ENOBUFS;
@ -1870,7 +1816,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
* Pass the frame to the h/w for transmission.
*/
if (malo_tx_start(sc, ni, bf, m) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
bf->bf_m = NULL;
bf->bf_node = NULL;
MALO_TXQ_LOCK(txq);
@ -1915,9 +1860,9 @@ malo_sysctlattach(struct malo_softc *sc)
static void
malo_announce(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
if_printf(ifp, "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
device_printf(sc->malo_dev,
"versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
sc->malo_hwspecs.hwversion,
(sc->malo_hwspecs.fw_releasenum >> 24) & 0xff,
(sc->malo_hwspecs.fw_releasenum >> 16) & 0xff,
@ -1926,9 +1871,11 @@ malo_announce(struct malo_softc *sc)
sc->malo_hwspecs.regioncode);
if (bootverbose || malo_rxbuf != MALO_RXBUF)
if_printf(ifp, "using %u rx buffers\n", malo_rxbuf);
device_printf(sc->malo_dev,
"using %u rx buffers\n", malo_rxbuf);
if (bootverbose || malo_txbuf != MALO_TXBUF)
if_printf(ifp, "using %u tx buffers\n", malo_txbuf);
device_printf(sc->malo_dev,
"using %u tx buffers\n", malo_txbuf);
}
/*
@ -1989,8 +1936,7 @@ malo_chan_set(struct malo_softc *sc, struct ieee80211_channel *chan)
static void
malo_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct malo_softc *sc = ifp->if_softc;
struct malo_softc *sc = ic->ic_softc;
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
}
@ -1998,8 +1944,7 @@ malo_scan_start(struct ieee80211com *ic)
static void
malo_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct malo_softc *sc = ifp->if_softc;
struct malo_softc *sc = ic->ic_softc;
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
}
@ -2007,8 +1952,7 @@ malo_scan_end(struct ieee80211com *ic)
static void
malo_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct malo_softc *sc = ifp->if_softc;
struct malo_softc *sc = ic->ic_softc;
(void) malo_chan_set(sc, ic->ic_curchan);
}
@ -2020,8 +1964,7 @@ malo_rx_proc(void *arg, int npending)
((((const struct ieee80211_frame *)wh)->i_fc[1] & \
IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
struct malo_softc *sc = arg;
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
struct malo_rxbuf *bf;
struct malo_rxdesc *ds;
struct mbuf *m, *mnew;
@ -2078,7 +2021,7 @@ malo_rx_proc(void *arg, int npending)
#endif
status = ds->status;
if (status & MALO_RXD_STATUS_DECRYPT_ERR_MASK) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto rx_next;
}
/*
@ -2117,7 +2060,7 @@ malo_rx_proc(void *arg, int npending)
/* XXX don't need mbuf, just dma buffer */
mnew = malo_getrxmbuf(sc, bf);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto rx_next;
}
/*
@ -2128,7 +2071,6 @@ malo_rx_proc(void *arg, int npending)
bf->bf_m = mnew;
m->m_data += off - hdrlen;
m->m_pkthdr.len = m->m_len = pktlen;
m->m_pkthdr.rcvif = ifp;
/*
* Piece 802.11 header together.
@ -2158,8 +2100,6 @@ malo_rx_proc(void *arg, int npending)
len, ds->rate, rssi);
}
#endif
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
/* dispatch */
ni = ieee80211_find_rxnode(ic,
(struct ieee80211_frame_min *)wh);
@ -2177,22 +2117,11 @@ malo_rx_proc(void *arg, int npending)
malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr);
sc->malo_rxnext = bf;
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
malo_start(ifp);
if (mbufq_first(&sc->malo_snd) != NULL)
malo_start(sc);
#undef IEEE80211_DIR_DSTODS
}
static void
malo_stop(struct ifnet *ifp, int disable)
{
struct malo_softc *sc = ifp->if_softc;
MALO_LOCK(sc);
malo_stop_locked(ifp, disable);
MALO_UNLOCK(sc);
}
/*
* Reclaim all tx queue resources.
*/
@ -2208,13 +2137,9 @@ malo_tx_cleanup(struct malo_softc *sc)
int
malo_detach(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->malo_ic;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
__func__, ifp->if_flags);
malo_stop(ifp, 1);
malo_stop(sc);
if (sc->malo_tq != NULL) {
taskqueue_drain(sc->malo_tq, &sc->malo_rxtask);
@ -2240,8 +2165,7 @@ malo_detach(struct malo_softc *sc)
malo_dma_cleanup(sc);
malo_tx_cleanup(sc);
malo_hal_detach(sc->malo_mh);
if_free(ifp);
mbufq_drain(&sc->malo_snd);
MALO_LOCK_DESTROY(sc);
return 0;
@ -2250,28 +2174,21 @@ malo_detach(struct malo_softc *sc)
void
malo_shutdown(struct malo_softc *sc)
{
malo_stop(sc->malo_ifp, 1);
malo_stop(sc);
}
void
malo_suspend(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
__func__, ifp->if_flags);
malo_stop(ifp, 1);
malo_stop(sc);
}
void
malo_resume(struct malo_softc *sc)
{
struct ifnet *ifp = sc->malo_ifp;
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
__func__, ifp->if_flags);
if (ifp->if_flags & IFF_UP)
if (sc->malo_ic.ic_nrunning > 0)
malo_init(sc);
}

View File

@ -520,8 +520,9 @@ struct malo_vap {
#define MALO_VAP(vap) ((struct malo_vap *)(vap))
struct malo_softc {
struct ieee80211com malo_ic;
struct mbufq malo_snd;
device_t malo_dev;
struct ifnet *malo_ifp; /* interface common */
struct mtx malo_mtx; /* master lock (recursive) */
struct taskqueue *malo_tq; /* private task queue */
@ -531,9 +532,10 @@ struct malo_softc {
bus_space_handle_t malo_io1h; /* BAR 1 */
bus_space_tag_t malo_io1t;
unsigned int malo_invalid : 1,/* disable hardware accesses */
malo_recvsetup : 1, /* recv setup */
malo_fixedrate: 1; /* use fixed tx rate */
unsigned int malo_invalid: 1,/* disable hardware accesses */
malo_recvsetup: 1, /* recv setup */
malo_fixedrate: 1, /* use fixed tx rate */
malo_running: 1;
struct malo_hal *malo_mh; /* h/w access layer */
struct malo_hal_hwspec malo_hwspecs; /* h/w capabilities */

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/errno.h>

View File

@ -244,7 +244,8 @@ struct mwl_vap {
#define MWL_VAP_CONST(vap) ((const struct mwl_vap *)(vap))
struct mwl_softc {
struct ifnet *sc_ifp; /* interface common */
struct ieee80211com sc_ic;
struct mbufq sc_snd;
struct mwl_stats sc_stats; /* interface statistics */
int sc_debug;
device_t sc_dev;
@ -257,7 +258,8 @@ struct mwl_softc {
struct taskqueue *sc_tq; /* private task queue */
struct callout sc_watchdog;
int sc_tx_timer;
unsigned int sc_invalid : 1, /* disable hardware accesses */
unsigned int sc_running : 1,
sc_invalid : 1, /* disable hardware accesses */
sc_recvsetup:1, /* recv setup */
sc_csapending:1,/* 11h channel switch pending */
sc_radarena : 1,/* radar detection enabled */

View File

@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>

View File

@ -127,10 +127,10 @@ static int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
static void rt2560_start_locked(struct ifnet *);
static void rt2560_start(struct ifnet *);
static int rt2560_transmit(struct ieee80211com *, struct mbuf *);
static void rt2560_start(struct rt2560_softc *);
static void rt2560_watchdog(void *);
static int rt2560_ioctl(struct ifnet *, u_long, caddr_t);
static void rt2560_parent(struct ieee80211com *);
static void rt2560_bbp_write(struct rt2560_softc *, uint8_t,
uint8_t);
static uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t);
@ -149,7 +149,8 @@ static void rt2560_set_basicrates(struct rt2560_softc *,
const struct ieee80211_rateset *);
static void rt2560_update_led(struct rt2560_softc *, int, int);
static void rt2560_set_bssid(struct rt2560_softc *, const uint8_t *);
static void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
static void rt2560_set_macaddr(struct rt2560_softc *,
const uint8_t *);
static void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
static void rt2560_update_promisc(struct ieee80211com *);
static const char *rt2560_get_rf(int);
@ -197,11 +198,9 @@ int
rt2560_attach(device_t dev, int id)
{
struct rt2560_softc *sc = device_get_softc(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
int error;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands;
uint8_t macaddr[IEEE80211_ADDR_LEN];
int error;
sc->sc_dev = dev;
@ -209,6 +208,7 @@ rt2560_attach(device_t dev, int id)
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/* retrieve RT2560 rev. no */
sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
@ -252,27 +252,9 @@ rt2560_attach(device_t dev, int id)
goto fail5;
}
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto fail6;
}
ic = ifp->if_l2com;
/* retrieve MAC address */
rt2560_get_macaddr(sc, macaddr);
rt2560_get_macaddr(sc, ic->ic_macaddr);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rt2560_init;
ifp->if_ioctl = rt2560_ioctl;
ifp->if_start = rt2560_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@ -303,7 +285,7 @@ rt2560_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = rt2560_raw_xmit;
ic->ic_updateslot = rt2560_update_slot;
ic->ic_update_promisc = rt2560_update_promisc;
@ -313,6 +295,8 @@ rt2560_attach(device_t dev, int id)
ic->ic_vap_create = rt2560_vap_create;
ic->ic_vap_delete = rt2560_vap_delete;
ic->ic_parent = rt2560_parent;
ic->ic_transmit = rt2560_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -341,7 +325,6 @@ rt2560_attach(device_t dev, int id)
return 0;
fail6: rt2560_free_rx_ring(sc, &sc->rxq);
fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
fail4: rt2560_free_tx_ring(sc, &sc->prioq);
fail3: rt2560_free_tx_ring(sc, &sc->atimq);
@ -355,12 +338,12 @@ int
rt2560_detach(void *xsc)
{
struct rt2560_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
rt2560_stop(sc);
ieee80211_ifdetach(ic);
mbufq_drain(&sc->sc_snd);
rt2560_free_tx_ring(sc, &sc->txq);
rt2560_free_tx_ring(sc, &sc->atimq);
@ -368,8 +351,6 @@ rt2560_detach(void *xsc)
rt2560_free_tx_ring(sc, &sc->bcnq);
rt2560_free_rx_ring(sc, &sc->rxq);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return 0;
@ -381,7 +362,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2560_softc *sc = ic->ic_softc;
struct rt2560_vap *rvp;
struct ieee80211vap *vap;
@ -394,7 +375,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
if_printf(ifp, "only 1 vap supported\n");
device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@ -403,7 +384,8 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
if_printf(ifp, "wds only supported in ap mode\n");
device_printf(sc->sc_dev,
"wds only supported in ap mode\n");
return NULL;
}
/*
@ -414,15 +396,12 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
if_printf(ifp, "unknown opmode %d\n", opmode);
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
rvp = (struct rt2560_vap *) malloc(sizeof(struct rt2560_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (rvp == NULL)
return NULL;
rvp = malloc(sizeof(struct rt2560_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@ -431,7 +410,8 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@ -451,9 +431,8 @@ void
rt2560_resume(void *xsc)
{
struct rt2560_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
if (ifp->if_flags & IFF_UP)
if (sc->sc_ic.ic_nrunning > 0)
rt2560_init(sc);
}
@ -763,8 +742,7 @@ static int
rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2560_vap *rvp = RT2560_VAP(vap);
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct rt2560_softc *sc = ifp->if_softc;
struct rt2560_softc *sc = vap->iv_ic->ic_softc;
int error;
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
@ -792,7 +770,8 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
vap->iv_opmode == IEEE80211_M_MBSS) {
m = ieee80211_beacon_alloc(ni, &rvp->ral_bo);
if (m == NULL) {
if_printf(ifp, "could not allocate beacon\n");
device_printf(sc->sc_dev,
"could not allocate beacon\n");
return ENOBUFS;
}
ieee80211_ref_node(ni);
@ -926,14 +905,13 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
static void
rt2560_tx_intr(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct mbuf *m;
uint32_t flags;
int retrycnt;
struct ieee80211vap *vap;
struct ieee80211_node *ni;
uint32_t flags;
int retrycnt, status;
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
BUS_DMASYNC_POSTREAD);
@ -961,7 +939,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
status = 0;
break;
case RT2560_TX_SUCCESS_RETRY:
@ -973,7 +951,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
status = 0;
break;
case RT2560_TX_FAIL_RETRY:
@ -985,7 +963,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE,
&retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
status = 1;
break;
case RT2560_TX_FAIL_INVALID:
@ -993,16 +971,16 @@ rt2560_tx_intr(struct rt2560_softc *sc)
default:
device_printf(sc->sc_dev, "sending data frame failed "
"0x%08x\n", flags);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
status = 1;
}
bus_dmamap_sync(sc->txq.data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->txq.data_dmat, data->map);
m_freem(m);
data->m = NULL;
ieee80211_free_node(data->ni);
ieee80211_tx_complete(ni, m, status);
data->ni = NULL;
data->m = NULL;
/* descriptor is no longer valid */
desc->flags &= ~htole32(RT2560_TX_VALID);
@ -1019,19 +997,13 @@ rt2560_tx_intr(struct rt2560_softc *sc)
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
sc->sc_tx_timer = 0;
if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) {
sc->sc_flags &= ~RT2560_F_DATA_OACTIVE;
if ((sc->sc_flags &
(RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
rt2560_start_locked(ifp);
}
if (sc->txq.queued < RT2560_TX_RING_COUNT - 1)
rt2560_start(sc);
}
static void
rt2560_prio_intr(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct ieee80211_node *ni;
@ -1103,13 +1075,8 @@ rt2560_prio_intr(struct rt2560_softc *sc)
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
sc->sc_tx_timer = 0;
if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) {
sc->sc_flags &= ~RT2560_F_PRIO_OACTIVE;
if ((sc->sc_flags &
(RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
rt2560_start_locked(ifp);
}
if (sc->prioq.queued < RT2560_PRIO_RING_COUNT)
rt2560_start(sc);
}
/*
@ -1119,8 +1086,7 @@ rt2560_prio_intr(struct rt2560_softc *sc)
static void
rt2560_decryption_intr(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct rt2560_rx_desc *desc;
struct rt2560_rx_data *data;
bus_addr_t physaddr;
@ -1146,13 +1112,13 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
break;
if (data->drop) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
(le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1165,7 +1131,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1188,7 +1154,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1201,7 +1167,6 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
desc->physaddr = htole32(physaddr);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
(le32toh(desc->flags) >> 16) & 0xfff;
@ -1321,8 +1286,7 @@ rt2560_beacon_update(struct ieee80211vap *vap, int item)
static void
rt2560_beacon_expire(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct rt2560_vap *rvp = RT2560_VAP(vap);
struct rt2560_tx_data *data;
@ -1363,7 +1327,6 @@ void
rt2560_intr(void *arg)
{
struct rt2560_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
uint32_t r;
RAL_LOCK(sc);
@ -1372,7 +1335,7 @@ rt2560_intr(void *arg)
RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
/* don't re-enable interrupts if we're shutting down */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & RT2560_F_RUNNING)) {
RAL_UNLOCK(sc);
return;
}
@ -1440,8 +1403,7 @@ static void
rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@ -1916,55 +1878,57 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
return 0;
}
static void
rt2560_start_locked(struct ifnet *ifp)
static int
rt2560_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rt2560_softc *sc = ifp->if_softc;
struct mbuf *m;
struct ieee80211_node *ni;
struct rt2560_softc *sc = ic->ic_softc;
int error;
RAL_LOCK_ASSERT(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
sc->sc_flags |= RT2560_F_DATA_OACTIVE;
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rt2560_tx_data(sc, m, ni) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
sc->sc_tx_timer = 5;
RAL_LOCK(sc);
if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
RAL_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RAL_UNLOCK(sc);
return (error);
}
rt2560_start(sc);
RAL_UNLOCK(sc);
return (0);
}
static void
rt2560_start(struct ifnet *ifp)
rt2560_start(struct rt2560_softc *sc)
{
struct rt2560_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RAL_LOCK(sc);
rt2560_start_locked(ifp);
RAL_UNLOCK(sc);
RAL_LOCK_ASSERT(sc);
while (sc->txq.queued < RT2560_TX_RING_COUNT - 1 &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rt2560_tx_data(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
break;
}
sc->sc_tx_timer = 5;
}
}
static void
rt2560_watchdog(void *arg)
{
struct rt2560_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
KASSERT(sc->sc_flags & RT2560_F_RUNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
@ -1973,51 +1937,33 @@ rt2560_watchdog(void *arg)
rt2560_tx_intr(sc);
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
device_printf(sc->sc_dev, "device timeout\n");
rt2560_init_locked(sc);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/* NB: callout is reset in rt2560_init() */
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
}
static int
rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
rt2560_parent(struct ieee80211com *ic)
{
struct rt2560_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct rt2560_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
RAL_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
rt2560_init_locked(sc);
startall = 1;
} else
rt2560_update_promisc(ic);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rt2560_stop_locked(sc);
}
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
RAL_LOCK(sc);
if (ic->ic_nrunning > 0) {
if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
rt2560_init_locked(sc);
startall = 1;
} else
rt2560_update_promisc(ic);
} else if (sc->sc_flags & RT2560_F_RUNNING)
rt2560_stop_locked(sc);
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -2101,8 +2047,7 @@ rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
static void
rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t power, tmp;
u_int i, chan;
@ -2201,8 +2146,7 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
static void
rt2560_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2560_softc *sc = ifp->if_softc;
struct rt2560_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2560_set_chan(sc, ic->ic_curchan);
@ -2238,8 +2182,7 @@ rt2560_disable_rf_tune(struct rt2560_softc *sc)
static void
rt2560_enable_tsf_sync(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t logcwmin, preload;
uint32_t tmp;
@ -2280,8 +2223,7 @@ rt2560_enable_tsf(struct rt2560_softc *sc)
static void
rt2560_update_plcp(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
/* no short preamble for 1Mbps */
RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400);
@ -2360,8 +2302,7 @@ rt2560_set_basicrates(struct rt2560_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@ -2406,7 +2347,7 @@ rt2560_set_bssid(struct rt2560_softc *sc, const uint8_t *bssid)
}
static void
rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr)
rt2560_set_macaddr(struct rt2560_softc *sc, const uint8_t *addr)
{
uint32_t tmp;
@ -2444,13 +2385,13 @@ rt2560_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2560_RXCSR0);
tmp &= ~RT2560_DROP_NOT_TO_ME;
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2560_DROP_NOT_TO_ME;
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
DPRINTF(sc, "%s promiscuous mode\n",
(ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
(ic->ic_promisc > 0) ? "entering" : "leaving");
}
static const char *
@ -2516,19 +2457,17 @@ rt2560_read_config(struct rt2560_softc *sc)
static void
rt2560_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2560_softc *sc = ifp->if_softc;
struct rt2560_softc *sc = ic->ic_softc;
/* abort TSF synchronization */
RAL_WRITE(sc, RT2560_CSR14, 0);
rt2560_set_bssid(sc, ifp->if_broadcastaddr);
rt2560_set_bssid(sc, ieee80211broadcastaddr);
}
static void
rt2560_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2560_softc *sc = ifp->if_softc;
struct rt2560_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = ic->ic_scan->ss_vap;
rt2560_enable_tsf_sync(sc);
@ -2622,8 +2561,8 @@ static void
rt2560_init_locked(struct rt2560_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
int i;
@ -2654,7 +2593,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
for (i = 0; i < N(rt2560_def_mac); i++)
RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
rt2560_set_macaddr(sc, IF_LLADDR(ifp));
rt2560_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* set basic rate set (will be updated later) */
RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
@ -2684,7 +2623,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
ic->ic_opmode != IEEE80211_M_MBSS)
tmp |= RT2560_DROP_TODS;
if (!(ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2560_DROP_NOT_TO_ME;
}
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
@ -2699,8 +2638,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
/* enable interrupts */
RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= RT2560_F_RUNNING;
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
#undef N
@ -2710,21 +2648,19 @@ static void
rt2560_init(void *priv)
{
struct rt2560_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2560_init_locked(sc);
RAL_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & RT2560_F_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
rt2560_stop_locked(struct rt2560_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
volatile int *flags = &sc->sc_flags;
RAL_LOCK_ASSERT(sc);
@ -2735,8 +2671,8 @@ rt2560_stop_locked(struct rt2560_softc *sc)
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
if (sc->sc_flags & RT2560_F_RUNNING) {
sc->sc_flags &= ~RT2560_F_RUNNING;
/* abort Tx */
RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
@ -2758,7 +2694,6 @@ rt2560_stop_locked(struct rt2560_softc *sc)
rt2560_reset_tx_ring(sc, &sc->bcnq);
rt2560_reset_rx_ring(sc, &sc->rxq);
}
sc->sc_flags &= ~(RT2560_F_PRIO_OACTIVE | RT2560_F_DATA_OACTIVE);
}
void
@ -2776,29 +2711,24 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rt2560_softc *sc = ifp->if_softc;
struct rt2560_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & RT2560_F_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
sc->sc_flags |= RT2560_F_PRIO_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENOBUFS; /* XXX */
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@ -2820,7 +2750,6 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
RAL_UNLOCK(sc);
return EIO; /* XXX */

View File

@ -105,13 +105,13 @@ struct rt2560_vap {
#define RT2560_VAP(vap) ((struct rt2560_vap *)(vap))
struct rt2560_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mtx sc_mtx;
struct mbufq sc_snd;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
struct mtx sc_mtx;
struct callout watchdog_ch;
int sc_tx_timer;
@ -152,8 +152,7 @@ struct rt2560_softc {
struct rt2560_tx_radiotap_header sc_txtap;
int sc_txtap_len;
#define RT2560_F_INPUT_RUNNING 0x1
#define RT2560_F_PRIO_OACTIVE 0x2
#define RT2560_F_DATA_OACTIVE 0x4
#define RT2560_F_RUNNING 0x2
int sc_flags;
};

View File

@ -121,12 +121,12 @@ static int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
struct ieee80211_node *, int);
static int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
struct ieee80211_node *);
static void rt2661_start_locked(struct ifnet *);
static void rt2661_start(struct ifnet *);
static int rt2661_transmit(struct ieee80211com *, struct mbuf *);
static void rt2661_start(struct rt2661_softc *);
static int rt2661_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void rt2661_watchdog(void *);
static int rt2661_ioctl(struct ifnet *, u_long, caddr_t);
static void rt2661_parent(struct ieee80211com *);
static void rt2661_bbp_write(struct rt2661_softc *, uint8_t,
uint8_t);
static uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t);
@ -197,27 +197,19 @@ int
rt2661_attach(device_t dev, int id)
{
struct rt2661_softc *sc = device_get_softc(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t val;
int error, ac, ntries;
uint8_t bands;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_id = id;
sc->sc_dev = dev;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
return ENOMEM;
}
ic = ifp->if_l2com;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/* wait for NIC to initialize */
for (ntries = 0; ntries < 1000; ntries++) {
@ -233,7 +225,7 @@ rt2661_attach(device_t dev, int id)
}
/* retrieve RF rev. no and various other things from EEPROM */
rt2661_read_eeprom(sc, macaddr);
rt2661_read_eeprom(sc, ic->ic_macaddr);
device_printf(dev, "MAC/BBP RT%X, RF %s\n", val,
rt2661_get_rf(sc->rf_rev));
@ -263,17 +255,6 @@ rt2661_attach(device_t dev, int id)
goto fail3;
}
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rt2661_init;
ifp->if_ioctl = rt2661_ioctl;
ifp->if_start = rt2661_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@ -305,7 +286,7 @@ rt2661_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
#if 0
ic->ic_wme.wme_update = rt2661_wme_update;
#endif
@ -315,7 +296,8 @@ rt2661_attach(device_t dev, int id)
ic->ic_updateslot = rt2661_update_slot;
ic->ic_update_promisc = rt2661_update_promisc;
ic->ic_raw_xmit = rt2661_raw_xmit;
ic->ic_transmit = rt2661_transmit;
ic->ic_parent = rt2661_parent;
ic->ic_vap_create = rt2661_vap_create;
ic->ic_vap_delete = rt2661_vap_delete;
@ -339,7 +321,6 @@ fail3: rt2661_free_tx_ring(sc, &sc->mgtq);
fail2: while (--ac >= 0)
rt2661_free_tx_ring(sc, &sc->txq[ac]);
fail1: mtx_destroy(&sc->sc_mtx);
if_free(ifp);
return error;
}
@ -347,14 +328,14 @@ int
rt2661_detach(void *xsc)
{
struct rt2661_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2661_stop_locked(sc);
RAL_UNLOCK(sc);
ieee80211_ifdetach(ic);
mbufq_drain(&sc->sc_snd);
rt2661_free_tx_ring(sc, &sc->txq[0]);
rt2661_free_tx_ring(sc, &sc->txq[1]);
@ -363,8 +344,6 @@ rt2661_detach(void *xsc)
rt2661_free_tx_ring(sc, &sc->mgtq);
rt2661_free_rx_ring(sc, &sc->rxq);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return 0;
@ -376,7 +355,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_softc *sc = ic->ic_softc;
struct rt2661_vap *rvp;
struct ieee80211vap *vap;
@ -389,7 +368,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
if_printf(ifp, "only 1 vap supported\n");
device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@ -398,7 +377,8 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
if_printf(ifp, "wds only supported in ap mode\n");
device_printf(sc->sc_dev,
"wds only supported in ap mode\n");
return NULL;
}
/*
@ -409,15 +389,12 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
if_printf(ifp, "unknown opmode %d\n", opmode);
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
rvp = (struct rt2661_vap *) malloc(sizeof(struct rt2661_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (rvp == NULL)
return NULL;
rvp = malloc(sizeof(struct rt2661_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@ -428,7 +405,8 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@ -464,9 +442,8 @@ void
rt2661_resume(void *xsc)
{
struct rt2661_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
if (ifp->if_flags & IFF_UP)
if (sc->sc_ic.ic_nrunning > 0)
rt2661_init(sc);
}
@ -770,7 +747,7 @@ rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2661_vap *rvp = RT2661_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct rt2661_softc *sc = ic->ic_ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
int error;
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
@ -869,11 +846,10 @@ rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
static void
rt2661_tx_intr(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct rt2661_tx_ring *txq;
struct rt2661_tx_data *data;
uint32_t val;
int qid, retrycnt;
int error, qid, retrycnt;
struct ieee80211vap *vap;
for (;;) {
@ -911,7 +887,7 @@ rt2661_tx_intr(struct rt2661_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
error = 0;
break;
case RT2661_TX_RETRY_FAIL:
@ -923,14 +899,14 @@ rt2661_tx_intr(struct rt2661_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE,
&retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
error = 1;
break;
default:
/* other failure */
device_printf(sc->sc_dev,
"sending data frame failed 0x%08x\n", val);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
error = 1;
}
DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat);
@ -939,17 +915,12 @@ rt2661_tx_intr(struct rt2661_softc *sc)
if (++txq->stat >= txq->count) /* faster than % count */
txq->stat = 0;
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m,
RT2661_TX_RESULT(val) != RT2661_TX_SUCCESS);
m_freem(m);
ieee80211_free_node(ni);
ieee80211_tx_complete(ni, m, error);
}
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
rt2661_start_locked(ifp);
rt2661_start(sc);
}
static void
@ -987,8 +958,7 @@ rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
static void
rt2661_rx_intr(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_rx_desc *desc;
struct rt2661_rx_data *data;
bus_addr_t physaddr;
@ -1017,12 +987,12 @@ rt2661_rx_intr(struct rt2661_softc *sc)
*/
DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n",
le32toh(desc->flags));
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1035,7 +1005,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1058,7 +1028,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1071,7 +1041,6 @@ rt2661_rx_intr(struct rt2661_softc *sc)
desc->physaddr = htole32(physaddr);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
(le32toh(desc->flags) >> 16) & 0xfff;
@ -1156,7 +1125,6 @@ void
rt2661_intr(void *arg)
{
struct rt2661_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
uint32_t r1, r2;
RAL_LOCK(sc);
@ -1166,7 +1134,7 @@ rt2661_intr(void *arg)
RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
/* don't re-enable interrupts if we're shutting down */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & RAL_RUNNING)) {
RAL_UNLOCK(sc);
return;
}
@ -1242,8 +1210,7 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate,
const bus_dma_segment_t *segs, int nsegs, int ac)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int i, remainder;
@ -1461,8 +1428,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
struct ieee80211_node *ni, int ac)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_tx_ring *txq = &sc->txq[ac];
struct rt2661_tx_desc *desc;
struct rt2661_tx_data *data;
@ -1604,10 +1570,31 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
return 0;
}
static void
rt2661_start_locked(struct ifnet *ifp)
static int
rt2661_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rt2661_softc *sc = ic->ic_softc;
int error;
RAL_LOCK(sc);
if ((sc->sc_flags & RAL_RUNNING) == 0) {
RAL_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RAL_UNLOCK(sc);
return (error);
}
rt2661_start(sc);
RAL_UNLOCK(sc);
return (0);
}
static void
rt2661_start(struct rt2661_softc *sc)
{
struct rt2661_softc *sc = ifp->if_softc;
struct mbuf *m;
struct ieee80211_node *ni;
int ac;
@ -1615,69 +1602,50 @@ rt2661_start_locked(struct ifnet *ifp)
RAL_LOCK_ASSERT(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || sc->sc_invalid)
if (!(sc->sc_flags & RAL_RUNNING) || sc->sc_invalid)
return;
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ac = M_WME_GETAC(m);
if (sc->txq[ac].queued >= RT2661_TX_RING_COUNT - 1) {
/* there is no place left in this ring */
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rt2661_tx_data(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
break;
}
sc->sc_tx_timer = 5;
}
}
static void
rt2661_start(struct ifnet *ifp)
{
struct rt2661_softc *sc = ifp->if_softc;
RAL_LOCK(sc);
rt2661_start_locked(ifp);
RAL_UNLOCK(sc);
}
static int
rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_softc *sc = ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & RAL_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENOBUFS; /* XXX */
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
/*
* Legacy path; interpret frame contents to decide
* precisely how to send the frame.
@ -1691,7 +1659,6 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
RAL_UNLOCK(sc);
return EIO; /* XXX */
@ -1701,61 +1668,42 @@ static void
rt2661_watchdog(void *arg)
{
struct rt2661_softc *sc = (struct rt2661_softc *)arg;
struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
KASSERT(sc->sc_flags & RAL_RUNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
device_printf(sc->sc_dev, "device timeout\n");
rt2661_init_locked(sc);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/* NB: callout is reset in rt2661_init() */
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
}
static int
rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
rt2661_parent(struct ieee80211com *ic)
{
struct rt2661_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct rt2661_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
RAL_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
rt2661_init_locked(sc);
startall = 1;
} else
rt2661_update_promisc(ic);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rt2661_stop_locked(sc);
}
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
RAL_LOCK(sc);
if (ic->ic_nrunning > 0) {
if ((sc->sc_flags & RAL_RUNNING) == 0) {
rt2661_init_locked(sc);
startall = 1;
} else
rt2661_update_promisc(ic);
} else if (sc->sc_flags & RAL_RUNNING)
rt2661_stop_locked(sc);
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -1879,8 +1827,7 @@ rt2661_select_antenna(struct rt2661_softc *sc)
static void
rt2661_enable_mrr(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
@ -1896,8 +1843,7 @@ rt2661_enable_mrr(struct rt2661_softc *sc)
static void
rt2661_set_txpreamble(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
@ -1914,8 +1860,7 @@ rt2661_set_basicrates(struct rt2661_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@ -1984,8 +1929,7 @@ rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
static void
rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const struct rfprog *rfprog;
uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
int8_t power;
@ -2088,13 +2032,13 @@ rt2661_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
tmp &= ~RT2661_DROP_NOT_TO_ME;
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2661_DROP_NOT_TO_ME;
RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
DPRINTF(sc, "%s promiscuous mode\n",
(ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
(ic->ic_promisc > 0) ? "entering" : "leaving");
}
/*
@ -2103,7 +2047,7 @@ rt2661_update_promisc(struct ieee80211com *ic)
static int
rt2661_wme_update(struct ieee80211com *ic)
{
struct rt2661_softc *sc = ic->ic_ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
const struct wmeParams *wmep;
wmep = ic->ic_wme.wme_chanParams.cap_wmeParams;
@ -2301,8 +2245,8 @@ static void
rt2661_init_locked(struct rt2661_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp, sta[3];
int i, error, ntries;
@ -2311,7 +2255,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
if ((sc->sc_flags & RAL_FW_LOADED) == 0) {
error = rt2661_load_microcode(sc);
if (error != 0) {
if_printf(ifp,
device_printf(sc->sc_dev,
"%s: could not load 8051 microcode, error %d\n",
__func__, error);
return;
@ -2364,7 +2308,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
for (i = 0; i < N(rt2661_def_mac); i++)
RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
rt2661_set_macaddr(sc, IF_LLADDR(ifp));
rt2661_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* set host ready */
RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
@ -2403,7 +2347,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
ic->ic_opmode != IEEE80211_M_MBSS)
tmp |= RT2661_DROP_TODS;
if (!(ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2661_DROP_NOT_TO_ME;
}
@ -2425,8 +2369,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
/* kick Rx */
RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= RAL_RUNNING;
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
#undef N
@ -2436,23 +2379,21 @@ static void
rt2661_init(void *priv)
{
struct rt2661_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2661_init_locked(sc);
RAL_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & RAL_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
void
rt2661_stop_locked(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
volatile int *flags = &sc->sc_flags;
uint32_t tmp;
while (*flags & RAL_INPUT_RUNNING)
msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10);
@ -2460,8 +2401,8 @@ rt2661_stop_locked(struct rt2661_softc *sc)
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
if (sc->sc_flags & RAL_RUNNING) {
sc->sc_flags &= ~RAL_RUNNING;
/* abort Tx (for all 5 Tx rings) */
RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
@ -2505,7 +2446,6 @@ rt2661_stop(void *priv)
static int
rt2661_load_microcode(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
const struct firmware *fp;
const char *imagename;
int ntries, error;
@ -2517,7 +2457,7 @@ rt2661_load_microcode(struct rt2661_softc *sc)
case 0x0302: imagename = "rt2561fw"; break;
case 0x0401: imagename = "rt2661fw"; break;
default:
if_printf(ifp, "%s: unexpected pci device id 0x%x, "
device_printf(sc->sc_dev, "%s: unexpected pci device id 0x%x, "
"don't know how to retrieve firmware\n",
__func__, sc->sc_id);
return EINVAL;
@ -2526,7 +2466,8 @@ rt2661_load_microcode(struct rt2661_softc *sc)
fp = firmware_get(imagename);
RAL_LOCK(sc);
if (fp == NULL) {
if_printf(ifp, "%s: unable to retrieve firmware image %s\n",
device_printf(sc->sc_dev,
"%s: unable to retrieve firmware image %s\n",
__func__, imagename);
return EINVAL;
}
@ -2557,8 +2498,8 @@ rt2661_load_microcode(struct rt2661_softc *sc)
DELAY(100);
}
if (ntries == 500) {
if_printf(ifp, "%s: timeout waiting for MCU to initialize\n",
__func__);
device_printf(sc->sc_dev,
"%s: timeout waiting for MCU to initialize\n", __func__);
error = EIO;
} else
error = 0;
@ -2726,8 +2667,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc, struct ieee80211vap *vap)
static void
rt2661_enable_tsf_sync(struct rt2661_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@ -2811,21 +2751,19 @@ rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
static void
rt2661_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_softc *sc = ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
uint32_t tmp;
/* abort TSF synchronization */
tmp = RAL_READ(sc, RT2661_TXRX_CSR9);
RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0xffffff);
rt2661_set_bssid(sc, ifp->if_broadcastaddr);
rt2661_set_bssid(sc, ieee80211broadcastaddr);
}
static void
rt2661_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_softc *sc = ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
rt2661_enable_tsf_sync(sc);
@ -2836,8 +2774,7 @@ rt2661_scan_end(struct ieee80211com *ic)
static void
rt2661_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2661_softc *sc = ifp->if_softc;
struct rt2661_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2661_set_chan(sc, ic->ic_curchan);

View File

@ -97,13 +97,13 @@ struct rt2661_vap {
#define RT2661_VAP(vap) ((struct rt2661_vap *)(vap))
struct rt2661_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mtx sc_mtx;
struct mbufq sc_snd;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
struct mtx sc_mtx;
struct callout watchdog_ch;
int sc_tx_timer;
@ -117,6 +117,7 @@ struct rt2661_softc {
int sc_flags;
#define RAL_FW_LOADED 0x1
#define RAL_INPUT_RUNNING 0x2
#define RAL_RUNNING 0x4
int sc_id;
struct ieee80211_channel *sc_curchan;

View File

@ -122,10 +122,10 @@ static int rt2860_raw_xmit(struct ieee80211_node *, struct mbuf *,
static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *,
struct ieee80211_node *,
const struct ieee80211_bpf_params *params);
static void rt2860_start(struct ifnet *);
static void rt2860_start_locked(struct ifnet *);
static int rt2860_transmit(struct ieee80211com *, struct mbuf *);
static void rt2860_start(struct rt2860_softc *);
static void rt2860_watchdog(void *);
static int rt2860_ioctl(struct ifnet *, u_long, caddr_t);
static void rt2860_parent(struct ieee80211com *);
static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t);
static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t);
static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t);
@ -156,7 +156,7 @@ static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *);
static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *);
static void rt2860_update_promisc(struct ieee80211com *);
static void rt2860_updateslot(struct ieee80211com *);
static void rt2860_updateprot(struct ifnet *);
static void rt2860_updateprot(struct rt2860_softc *);
static int rt2860_updateedca(struct ieee80211com *);
#ifdef HW_CRYPTO
static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *,
@ -230,27 +230,19 @@ int
rt2860_attach(device_t dev, int id)
{
struct rt2860_softc *sc = device_get_softc(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int error, ntries, qid;
uint8_t bands;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
sc->sc_debug = 0;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
return ENOMEM;
}
ic = ifp->if_l2com;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/* wait for NIC to initialize */
for (ntries = 0; ntries < 100; ntries++) {
@ -273,11 +265,11 @@ rt2860_attach(device_t dev, int id)
sc->sc_flags |= RT2860_ADVANCED_PS;
/* retrieve RF rev. no and various other things from EEPROM */
rt2860_read_eeprom(sc, macaddr);
rt2860_read_eeprom(sc, ic->ic_macaddr);
device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), "
"RF %s (MIMO %dT%dR), address %6D\n",
sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev),
sc->ntxchains, sc->nrxchains, macaddr, ":");
sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":");
/*
* Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings.
@ -304,17 +296,6 @@ rt2860_attach(device_t dev, int id)
sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ?
WME_AC_VO : 5;
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rt2860_init;
ifp->if_ioctl = rt2860_ioctl;
ifp->if_start = rt2860_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@ -345,7 +326,7 @@ rt2860_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_wme.wme_update = rt2860_updateedca;
ic->ic_scan_start = rt2860_scan_start;
@ -357,7 +338,8 @@ rt2860_attach(device_t dev, int id)
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = rt2860_node_free;
ic->ic_newassoc = rt2860_newassoc;
ic->ic_transmit = rt2860_transmit;
ic->ic_parent = rt2860_parent;
ic->ic_vap_create = rt2860_vap_create;
ic->ic_vap_delete = rt2860_vap_delete;
@ -381,7 +363,6 @@ fail3: rt2860_free_rx_ring(sc, &sc->rxq);
fail2: while (--qid >= 0)
rt2860_free_tx_ring(sc, &sc->txq[qid]);
fail1: mtx_destroy(&sc->sc_mtx);
if_free(ifp);
return error;
}
@ -389,8 +370,7 @@ int
rt2860_detach(void *xsc)
{
struct rt2860_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int qid;
RAL_LOCK(sc);
@ -398,14 +378,12 @@ rt2860_detach(void *xsc)
RAL_UNLOCK(sc);
ieee80211_ifdetach(ic);
mbufq_drain(&sc->sc_snd);
for (qid = 0; qid < 6; qid++)
rt2860_free_tx_ring(sc, &sc->txq[qid]);
rt2860_free_rx_ring(sc, &sc->rxq);
rt2860_free_tx_pool(sc);
if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return 0;
@ -431,9 +409,8 @@ void
rt2860_resume(void *xsc)
{
struct rt2860_softc *sc = xsc;
struct ifnet *ifp = sc->sc_ifp;
if (ifp->if_flags & IFF_UP)
if (sc->sc_ic.ic_nrunning > 0)
rt2860_init(sc);
}
@ -443,7 +420,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2860_softc *sc = ic->ic_softc;
struct rt2860_vap *rvp;
struct ieee80211vap *vap;
@ -456,7 +433,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
if_printf(ifp, "only 1 vap supported\n");
device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@ -465,7 +442,8 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
if_printf(ifp, "wds only supported in ap mode\n");
device_printf(sc->sc_dev,
"wds only supported in ap mode\n");
return NULL;
}
/*
@ -476,14 +454,12 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
if_printf(ifp, "unknown opmode %d\n", opmode);
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_NOWAIT | M_ZERO);
if (rvp == NULL)
return NULL;
rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@ -497,7 +473,8 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@ -829,7 +806,7 @@ rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring)
static void
rt2860_updatestats(struct rt2860_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
/*
* In IBSS or HostAP modes (when the hardware sends beacons), the
@ -856,7 +833,7 @@ static void
rt2860_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211com *ic = ni->ni_ic;
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
uint8_t wcid;
wcid = IEEE80211_AID(ni->ni_associd);
@ -875,7 +852,7 @@ static void
rt2860_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
uint8_t wcid;
if (ni->ni_associd != 0) {
@ -923,7 +900,7 @@ rt2860_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2860_vap *rvp = RT2860_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
uint32_t tmp;
int error;
@ -1101,7 +1078,6 @@ rt2860_intr_coherent(struct rt2860_softc *sc)
static void
rt2860_drain_stats_fifo(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_node *ni;
uint32_t stat;
int retrycnt;
@ -1137,7 +1113,8 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
} else {
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
}
}
}
@ -1145,7 +1122,6 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
static void
rt2860_tx_intr(struct rt2860_softc *sc, int qid)
{
struct ifnet *ifp = sc->sc_ifp;
struct rt2860_tx_ring *ring = &sc->txq[qid];
uint32_t hw;
@ -1163,15 +1139,11 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
ieee80211_process_callback(data->ni, data->m,
0);
}
m_freem(data->m);
ieee80211_free_node(data->ni);
data->m = NULL;
ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
data->m = NULL;
SLIST_INSERT_HEAD(&sc->data_pool, data, next);
ring->data[ring->next] = NULL;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
ring->queued--;
ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT;
@ -1180,8 +1152,7 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
sc->sc_tx_timer = 0;
if (ring->queued < RT2860_TX_RING_COUNT)
sc->qfullmsk &= ~(1 << qid);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
rt2860_start_locked(ifp);
rt2860_start(sc);
}
/*
@ -1206,8 +1177,7 @@ static void
rt2860_rx_intr(struct rt2860_softc *sc)
{
struct rt2860_rx_radiotap_header *tap;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m, *m1;
@ -1234,7 +1204,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
if (__predict_false(rxd->flags &
htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1243,14 +1213,14 @@ rt2860_rx_intr(struct rt2860_softc *sc)
/* report MIC failures to net80211 for TKIP */
ic->ic_stats.is_rx_locmicfail++;
ieee80211_michael_mic_failure(ic, 0/* XXX */);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
#endif
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m1 == NULL)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1274,7 +1244,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
}
/* physical address may have changed */
rxd->sdp0 = htole32(physaddr);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@ -1289,7 +1259,6 @@ rt2860_rx_intr(struct rt2860_softc *sc)
rxwi = mtod(m, struct rt2860_rxwi *);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_data = (caddr_t)(rxwi + 1);
m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff;
@ -1399,7 +1368,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
#endif
/* check if protection mode has changed */
if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) {
rt2860_updateprot(ic);
rt2860_updateprot(sc);
sc->sc_ic_flags = ic->ic_flags;
}
#endif
@ -1408,7 +1377,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
static void
rt2860_gp_intr(struct rt2860_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state));
@ -1480,8 +1449,7 @@ rt2860_intr(void *arg)
static int
rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct rt2860_tx_ring *ring;
struct rt2860_tx_data *data;
@ -1725,14 +1693,13 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rt2860_softc *sc = ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
int error;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & RT2860_RUNNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
@ -1754,7 +1721,6 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (error != 0) {
/* NB: m is reclaimed on tx failure */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
sc->sc_tx_timer = 5;
RAL_UNLOCK(sc);
@ -1765,8 +1731,7 @@ static int
rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct rt2860_tx_ring *ring;
struct rt2860_tx_data *data;
@ -1973,41 +1938,46 @@ rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
return 0;
}
static void
rt2860_start(struct ifnet *ifp)
static int
rt2860_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rt2860_softc *sc = ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
int error;
RAL_LOCK(sc);
rt2860_start_locked(ifp);
if ((sc->sc_flags & RT2860_RUNNNING) == 0) {
RAL_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RAL_UNLOCK(sc);
return (error);
}
rt2860_start(sc);
RAL_UNLOCK(sc);
return (0);
}
static void
rt2860_start_locked(struct ifnet *ifp)
rt2860_start(struct rt2860_softc *sc)
{
struct rt2860_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RAL_LOCK_ASSERT(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(ifp->if_drv_flags & IFF_DRV_OACTIVE))
if ((sc->sc_flags & RT2860_RUNNNING) == 0)
return;
for (;;) {
if (SLIST_EMPTY(&sc->data_pool) || sc->qfullmsk != 0) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (rt2860_tx(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
sc->sc_tx_timer = 5;
@ -2018,61 +1988,42 @@ static void
rt2860_watchdog(void *arg)
{
struct rt2860_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
KASSERT(sc->sc_flags & RT2860_RUNNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
device_printf(sc->sc_dev, "device timeout\n");
rt2860_stop_locked(sc);
rt2860_init_locked(sc);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
}
static int
rt2860_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
rt2860_parent(struct ieee80211com *ic)
{
struct rt2860_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0, startall = 0;
struct rt2860_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
RAL_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
rt2860_init_locked(sc);
startall = 1;
} else
rt2860_update_promisc(ic);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rt2860_stop_locked(sc);
}
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCSIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
RAL_LOCK(sc);
if (ic->ic_nrunning> 0) {
if (!(sc->sc_flags & RT2860_RUNNNING)) {
rt2860_init_locked(sc);
startall = 1;
} else
rt2860_update_promisc(ic);
} else if (sc->sc_flags & RT2860_RUNNNING)
rt2860_stop_locked(sc);
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
/*
@ -2295,8 +2246,7 @@ rt2860_enable_mrr(struct rt2860_softc *sc)
static void
rt2860_set_txpreamble(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG);
@ -2311,8 +2261,7 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@ -2333,8 +2282,7 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
static void
rt2860_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2860_softc *sc = ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
uint32_t tmp;
tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG);
@ -2347,8 +2295,7 @@ rt2860_scan_start(struct ieee80211com *ic)
static void
rt2860_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2860_softc *sc = ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap->iv_state == IEEE80211_S_RUN) {
@ -2360,8 +2307,7 @@ rt2860_scan_end(struct ieee80211com *ic)
static void
rt2860_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rt2860_softc *sc = ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2860_switch_chan(sc, ic->ic_curchan);
@ -3113,10 +3059,9 @@ rt2860_updateslot(struct ieee80211com *ic)
}
static void
rt2860_updateprot(struct ifnet *ifp)
rt2860_updateprot(struct rt2860_softc *sc)
{
struct rt2860_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
@ -3145,7 +3090,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG);
tmp &= ~RT2860_DROP_NOT_MYBSS;
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2860_DROP_NOT_MYBSS;
RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp);
}
@ -3153,7 +3098,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
static int
rt2860_updateedca(struct ieee80211com *ic)
{
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_softc *sc = ic->ic_softc;
const struct wmeParams *wmep;
int aci;
@ -3325,8 +3270,7 @@ rt2860_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
static int8_t
rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c = ic->ic_curchan;
int delta;
@ -3801,8 +3745,7 @@ rt5390_bbp_init(struct rt2860_softc *sc)
static int
rt2860_txrx_enable(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int ntries;
@ -3848,22 +3791,21 @@ static void
rt2860_init(void *arg)
{
struct rt2860_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2860_init_locked(sc);
RAL_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & RT2860_RUNNNING)
ieee80211_start_all(ic);
}
static void
rt2860_init_locked(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
uint8_t bbp1, bbp3;
int i, qid, ridx, ntries, error;
@ -3899,7 +3841,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
return;
}
rt2860_set_macaddr(sc, IF_LLADDR(ifp));
rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* init Tx power for all Tx rates (from EEPROM) */
for (ridx = 0; ridx < 5; ridx++) {
@ -4096,7 +4038,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp);
/* setup initial protection mode */
rt2860_updateprot(ifp);
rt2860_updateprot(sc);
/* turn radio LED on */
rt2860_set_leds(sc, RT2860_LED_RADIO);
@ -4115,8 +4057,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
if (sc->sc_flags & RT2860_ADVANCED_PS)
rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= RT2860_RUNNNING;
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
}
@ -4134,16 +4075,15 @@ rt2860_stop(void *arg)
static void
rt2860_stop_locked(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
int qid;
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & RT2860_RUNNNING)
rt2860_set_leds(sc, 0); /* turn all LEDs off */
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~RT2860_RUNNNING;
/* disable interrupts */
RAL_WRITE(sc, RT2860_INT_MASK, 0);
@ -4294,8 +4234,7 @@ rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux)
static void
rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
@ -4364,8 +4303,7 @@ rt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap)
static void
rt2860_enable_tsf_sync(struct rt2860_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;

View File

@ -115,13 +115,13 @@ struct rt2860_vap {
#define RT2860_VAP(vap) ((struct rt2860_vap *)(vap))
struct rt2860_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
struct mtx sc_mtx;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
struct mtx sc_mtx;
struct callout watchdog_ch;
int sc_invalid;
@ -139,6 +139,7 @@ struct rt2860_softc {
#define RT2860_ENABLED (1 << 0)
#define RT2860_ADVANCED_PS (1 << 1)
#define RT2860_PCIE (1 << 2)
#define RT2860_RUNNNING (1 << 3)
struct ieee80211_node *wcid2ni[RT2860_WCID_MAX];

View File

@ -187,15 +187,13 @@ static struct mbuf *
static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void rsu_init(void *);
static void rsu_init_locked(struct rsu_softc *);
static void rsu_init(struct rsu_softc *);
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
struct mbuf *, struct rsu_data *);
static void rsu_start(struct ifnet *);
static void rsu_start_locked(struct ifnet *);
static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
static void rsu_stop(struct ifnet *, int);
static void rsu_stop_locked(struct ifnet *, int);
static int rsu_transmit(struct ieee80211com *, struct mbuf *);
static void rsu_start(struct rsu_softc *);
static void rsu_parent(struct ieee80211com *);
static void rsu_stop(struct rsu_softc *);
static void rsu_ms_delay(struct rsu_softc *);
static device_method_t rsu_methods[] = {
@ -285,8 +283,7 @@ rsu_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rsu_softc *sc = device_get_softc(self);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
int error;
uint8_t iface_index, bands;
@ -298,6 +295,7 @@ rsu_attach(device_t self)
MTX_DEF);
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
rsu_calib_task, sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/* Allocate Tx/Rx buffers. */
error = rsu_alloc_rx_list(sc);
@ -333,28 +331,9 @@ rsu_attach(device_t self)
device_printf(self, "could not read ROM\n");
goto fail_rom;
}
IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]);
IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->rom[0x12]);
device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(self, "cannot allocate interface\n");
goto fail_ifalloc;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "rsu", device_get_unit(self));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rsu_init;
ifp->if_ioctl = rsu_ioctl;
ifp->if_start = rsu_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_capabilities |= IFCAP_RXCSUM;
ifp->if_capenable |= IFCAP_RXCSUM;
ifp->if_hwassist = CSUM_TCP;
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
@ -387,7 +366,7 @@ rsu_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = rsu_raw_xmit;
ic->ic_scan_start = rsu_scan_start;
ic->ic_scan_end = rsu_scan_end;
@ -395,6 +374,8 @@ rsu_attach(device_t self)
ic->ic_vap_create = rsu_vap_create;
ic->ic_vap_delete = rsu_vap_delete;
ic->ic_update_mcast = rsu_update_mcast;
ic->ic_parent = rsu_parent;
ic->ic_transmit = rsu_transmit;
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
@ -406,7 +387,6 @@ rsu_attach(device_t self)
return (0);
fail_ifalloc:
fail_rom:
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
fail_usb:
@ -418,10 +398,11 @@ static int
rsu_detach(device_t self)
{
struct rsu_softc *sc = device_get_softc(self);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
rsu_stop(ifp, 1);
RSU_LOCK(sc);
rsu_stop(sc);
RSU_UNLOCK(sc);
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
ieee80211_ifdetach(ic);
@ -431,7 +412,7 @@ rsu_detach(device_t self)
rsu_free_tx_list(sc);
rsu_free_rx_list(sc);
if_free(ifp);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -471,14 +452,11 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (uvp == NULL)
return (NULL);
uvp = malloc(sizeof(struct rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags, bssid, mac) != 0) {
flags, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -490,7 +468,7 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
@ -508,9 +486,8 @@ rsu_vap_delete(struct ieee80211vap *vap)
static void
rsu_scan_start(struct ieee80211com *ic)
{
struct rsu_softc *sc = ic->ic_softc;
int error;
struct ifnet *ifp = ic->ic_ifp;
struct rsu_softc *sc = ifp->if_softc;
/* Scanning is done by the firmware. */
RSU_LOCK(sc);
@ -676,11 +653,8 @@ rsu_getbuf(struct rsu_softc *sc)
RSU_ASSERT_LOCKED(sc);
bf = _rsu_getbuf(sc);
if (bf == NULL) {
struct ifnet *ifp = sc->sc_ifp;
if (bf == NULL)
DPRINTF("stop queue\n");
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
}
return (bf);
}
@ -935,7 +909,7 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rsu_vap *uvp = RSU_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct rsu_softc *sc = ic->ic_ifp->if_softc;
struct rsu_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
struct ieee80211_rateset *rs;
enum ieee80211_state ostate;
@ -1033,29 +1007,27 @@ static int
rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
{
struct r92s_fw_cmd_sitesurvey cmd;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
memset(&cmd, 0, sizeof(cmd));
if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1)
if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
cmd.active = htole32(1);
cmd.limit = htole32(48);
if (sc->scan_pass == 1 && vap->iv_des_nssid > 0) {
if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
/* Do a directed scan for second pass. */
cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
vap->iv_des_ssid[0].len);
}
DPRINTF("sending site survey command, pass=%d\n", sc->scan_pass);
DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
}
static int
rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ndis_wlan_bssid_ex *bss;
struct ndis_802_11_fixed_ies *fixed;
@ -1133,8 +1105,7 @@ rsu_disconnect(struct rsu_softc *sc)
static void
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_channel *c;
struct ndis_wlan_bssid_ex *bss;
@ -1165,7 +1136,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
IEEE80211_FC0_SUBTYPE_BEACON;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
USETW(wh->i_dur, 0);
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
*(uint16_t *)wh->i_seq = 0;
@ -1173,7 +1144,6 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
/* Finalize mbuf. */
m->m_pkthdr.len = m->m_len = pktlen;
m->m_pkthdr.rcvif = ifp;
/* Fix the channel. */
c = ieee80211_find_channel_byieee(ic,
le32toh(bss->config.dsconfig),
@ -1191,8 +1161,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
struct r92s_event_join_bss *rsp;
@ -1228,8 +1197,7 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTFN(4, "Rx event code=%d len=%d\n", code, len);
@ -1240,18 +1208,18 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
break;
case R92S_EVT_SURVEY_DONE:
DPRINTF("site survey pass %d done, found %d BSS\n",
sc->scan_pass, le32toh(*(uint32_t *)buf));
sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
if (vap->iv_state != IEEE80211_S_SCAN)
break; /* Ignore if not scanning. */
if (sc->scan_pass == 0 && vap->iv_des_nssid != 0) {
if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
/* Schedule a directed scan for hidden APs. */
sc->scan_pass = 1;
sc->sc_scan_pass = 1;
RSU_UNLOCK(sc);
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
RSU_LOCK(sc);
break;
}
sc->scan_pass = 0;
sc->sc_scan_pass = 0;
break;
case R92S_EVT_JOIN_BSS:
if (vap->iv_state == IEEE80211_S_AUTH)
@ -1274,7 +1242,7 @@ XXX and disrupts the WLAN traffic. Disable for now.
DPRINTF("WPS PBC pushed.\n");
break;
case R92S_EVT_FWDBG:
if (ifp->if_flags & IFF_DEBUG) {
if (vap->iv_ifp->if_flags & IFF_DEBUG) {
buf[60] = '\0';
printf("FWDBG: %s\n", (char *)buf);
}
@ -1341,8 +1309,7 @@ rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
static struct mbuf *
rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct r92s_rx_stat *stat;
uint32_t rxdw0, rxdw3;
@ -1355,11 +1322,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
rxdw3 = le32toh(stat->rxdw3);
if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
@ -1377,11 +1344,9 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m == NULL)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
/* Finalize mbuf. */
m->m_pkthdr.rcvif = ifp;
/* Hardware does Rx TCP checksum offload. */
if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
@ -1479,6 +1444,7 @@ static struct mbuf *
rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
{
struct rsu_softc *sc = data->sc;
struct ieee80211com *ic = &sc->sc_ic;
struct r92s_rx_stat *stat;
int len;
@ -1486,7 +1452,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
if (__predict_false(len < sizeof(*stat))) {
DPRINTF("xfer too short %d\n", len);
if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
/* Determine if it is a firmware C2H event or an 802.11 frame. */
@ -1503,8 +1469,7 @@ static void
rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL, *next;
@ -1564,7 +1529,7 @@ rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
break;
@ -1572,35 +1537,16 @@ rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
static void
rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
RSU_ASSERT_LOCKED(sc);
/*
* Do any tx complete callback. Note this must be done before releasing
* the node reference.
*/
if (data->m) {
m = data->m;
if (m->m_flags & M_TXCB) {
/* XXX status? */
ieee80211_process_callback(data->ni, m, 0);
}
m_freem(m);
/* XXX status? */
ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
}
if (data->ni) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@ -1608,7 +1554,7 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
uint8_t which)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct rsu_data *data;
RSU_ASSERT_LOCKED(sc);
@ -1643,7 +1589,7 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
rsu_txeof(xfer, data);
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
}
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(ic->ic_oerrors, 1);
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@ -1669,8 +1615,7 @@ static int
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct rsu_data *data)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
@ -1772,82 +1717,75 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
return (0);
}
static void
rsu_start(struct ifnet *ifp)
static int
rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rsu_softc *sc = ifp->if_softc;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
struct rsu_softc *sc = ic->ic_softc;
int error;
RSU_LOCK(sc);
rsu_start_locked(ifp);
if (!sc->sc_running) {
RSU_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RSU_UNLOCK(sc);
return (error);
}
rsu_start(sc);
RSU_UNLOCK(sc);
return (0);
}
static void
rsu_start_locked(struct ifnet *ifp)
rsu_start(struct rsu_softc *sc)
{
struct rsu_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct rsu_data *bf;
struct mbuf *m;
RSU_ASSERT_LOCKED(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = rsu_getbuf(sc);
if (bf == NULL) {
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
bf = rsu_getbuf(sc);
if (bf == NULL) {
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
m_freem(m);
ieee80211_free_node(ni);
} else if (rsu_tx_start(sc, ni, m, bf) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (rsu_tx_start(sc, ni, m, bf) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
}
}
}
static int
rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
rsu_parent(struct ieee80211com *ic)
{
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct rsu_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
rsu_init(ifp->if_softc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rsu_stop(ifp, 1);
RSU_LOCK(sc);
if (ic->ic_nrunning > 0) {
if (!sc->sc_running) {
rsu_init(sc);
startall = 1;
}
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
} else if (sc->sc_running)
rsu_stop(sc);
RSU_UNLOCK(sc);
return (error);
if (startall)
ieee80211_start_all(ic);
}
/*
@ -2296,12 +2234,11 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rsu_softc *sc = ifp->if_softc;
struct rsu_softc *sc = ic->ic_softc;
struct rsu_data *bf;
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!sc->sc_running) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@ -2314,10 +2251,8 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RSU_UNLOCK(sc);
return (ENOBUFS);
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (rsu_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
RSU_UNLOCK(sc);
return (EIO);
@ -2328,23 +2263,17 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
}
static void
rsu_init(void *arg)
rsu_init(struct rsu_softc *sc)
{
struct rsu_softc *sc = arg;
RSU_LOCK(sc);
rsu_init_locked(arg);
RSU_UNLOCK(sc);
}
static void
rsu_init_locked(struct rsu_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint8_t macaddr[IEEE80211_ADDR_LEN];
struct r92s_set_pwr_mode cmd;
int error;
int i;
RSU_ASSERT_LOCKED(sc);
/* Init host async commands ring. */
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
@ -2384,14 +2313,14 @@ rsu_init_locked(struct rsu_softc *sc)
rsu_read_1(sc, 0xfe5c) | 0x80);
/* Set MAC address. */
rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp),
IEEE80211_ADDR_LEN);
IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
rsu_write_region_1(sc, R92S_MACID, macaddr, IEEE80211_ADDR_LEN);
/* It really takes 1.5 seconds for the firmware to boot: */
usb_pause_mtx(&sc->sc_mtx, (3 * hz) / 2);
DPRINTF("setting MAC address to %s\n", ether_sprintf(IF_LLADDR(ifp)));
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
DPRINTF("setting MAC address to %s\n", ether_sprintf(macaddr));
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr,
IEEE80211_ADDR_LEN);
if (error != 0) {
device_printf(sc->sc_dev, "could not set MAC address\n");
@ -2427,12 +2356,11 @@ rsu_init_locked(struct rsu_softc *sc)
/* Set default channel. */
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
#endif
sc->scan_pass = 0;
sc->sc_scan_pass = 0;
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
/* We're ready to go. */
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_running = 1;
return;
fail:
/* Need to stop all failed transfers, if any */
@ -2441,22 +2369,11 @@ rsu_init_locked(struct rsu_softc *sc)
}
static void
rsu_stop(struct ifnet *ifp, int disable)
rsu_stop(struct rsu_softc *sc)
{
struct rsu_softc *sc = ifp->if_softc;
RSU_LOCK(sc);
rsu_stop_locked(ifp, disable);
RSU_UNLOCK(sc);
}
static void
rsu_stop_locked(struct ifnet *ifp, int disable __unused)
{
struct rsu_softc *sc = ifp->if_softc;
int i;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_running = 0;
sc->sc_calibrating = 0;
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);

View File

@ -726,7 +726,8 @@ struct rsu_vap {
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
struct rsu_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
int (*sc_newstate)(struct ieee80211com *,
@ -736,17 +737,17 @@ struct rsu_softc {
const uint8_t *qid2idx;
struct mtx sc_mtx;
u_int sc_running:1,
sc_calibrating:1,
sc_scan_pass:1;
u_int cut;
int scan_pass;
struct rsu_host_cmd_ring cmdq;
struct rsu_data sc_rx[RSU_RX_LIST_COUNT];
struct rsu_data sc_tx[RSU_TX_LIST_COUNT];
struct rsu_data *fwcmd_data;
uint8_t cmd_seq;
uint8_t rom[128];
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct usb_xfer *sc_xfer[RSU_N_TRANSFER];
uint8_t sc_calibrating;
STAILQ_HEAD(, rsu_data) sc_rx_active;
STAILQ_HEAD(, rsu_data) sc_rx_inactive;

View File

@ -175,8 +175,9 @@ static int rum_tx_raw(struct rum_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int rum_tx_data(struct rum_softc *, struct mbuf *,
struct ieee80211_node *);
static void rum_start(struct ifnet *);
static int rum_ioctl(struct ifnet *, u_long, caddr_t);
static int rum_transmit(struct ieee80211com *, struct mbuf *);
static void rum_start(struct rum_softc *);
static void rum_parent(struct ieee80211com *);
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
int);
static uint32_t rum_read(struct rum_softc *, uint16_t);
@ -198,7 +199,7 @@ static void rum_set_chan(struct rum_softc *,
struct ieee80211_channel *);
static void rum_enable_tsf_sync(struct rum_softc *);
static void rum_enable_tsf(struct rum_softc *);
static void rum_update_slot(struct ifnet *);
static void rum_update_slot(struct rum_softc *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
static void rum_update_mcast(struct ieee80211com *);
@ -207,8 +208,7 @@ static void rum_setpromisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
static void rum_init_locked(struct rum_softc *);
static void rum_init(void *);
static void rum_init(struct rum_softc *);
static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
@ -425,8 +425,7 @@ rum_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rum_softc *sc = device_get_softc(self);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
uint32_t tmp;
int error, ntries;
@ -437,6 +436,7 @@ rum_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2573_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index,
@ -470,24 +470,6 @@ rum_attach(device_t self)
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
RUM_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto detach;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = rum_init;
ifp->if_ioctl = rum_ioctl;
ifp->if_start = rum_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -512,13 +494,14 @@ rum_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_update_promisc = rum_update_promisc;
ic->ic_raw_xmit = rum_raw_xmit;
ic->ic_scan_start = rum_scan_start;
ic->ic_scan_end = rum_scan_end;
ic->ic_set_channel = rum_set_channel;
ic->ic_transmit = rum_transmit;
ic->ic_parent = rum_parent;
ic->ic_vap_create = rum_vap_create;
ic->ic_vap_delete = rum_vap_delete;
ic->ic_update_mcast = rum_update_mcast;
@ -543,8 +526,6 @@ static int
rum_detach(device_t self)
{
struct rum_softc *sc = device_get_softc(self);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
/* Prevent further ioctls */
RUM_LOCK(sc);
@ -559,11 +540,9 @@ rum_detach(device_t self)
rum_unsetup_tx_list(sc);
RUM_UNLOCK(sc);
if (ifp) {
ic = ifp->if_l2com;
ieee80211_ifdetach(ic);
if_free(ifp);
}
if (sc->sc_ic.ic_softc == sc)
ieee80211_ifdetach(&sc->sc_ic);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@ -595,21 +574,18 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
struct rum_vap *rvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (rvp == NULL)
return NULL;
rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(rvp, M_80211_VAP);
return (NULL);
@ -624,7 +600,8 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@ -648,13 +625,8 @@ rum_tx_free(struct rum_tx_data *data, int txerr)
struct rum_softc *sc = data->sc;
if (data->m != NULL) {
if (data->m->m_flags & M_TXCB)
ieee80211_process_callback(data->ni, data->m,
txerr ? ETIMEDOUT : 0);
m_freem(data->m);
ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@ -711,7 +683,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rum_vap *rvp = RUM_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
@ -745,12 +717,12 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
rum_update_slot(ic->ic_ifp);
rum_update_slot(sc);
rum_enable_mrr(sc);
rum_set_txpreamble(sc);
rum_set_basicrates(sc);
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
rum_set_bssid(sc, sc->sc_bssid);
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
rum_set_bssid(sc, ic->ic_macaddr);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@ -780,7 +752,6 @@ static void
rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct rum_tx_data *data;
struct mbuf *m;
@ -799,9 +770,6 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
rum_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@ -844,16 +812,14 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_transfer_submit(xfer);
}
RUM_UNLOCK(sc);
rum_start(ifp);
RUM_LOCK(sc);
rum_start(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
rum_tx_free(data, error);
@ -880,8 +846,7 @@ static void
rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@ -899,7 +864,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
@ -916,21 +881,20 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RUM_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
usbd_copy_out(pc, RT2573_RX_DESC_SIZE,
mtod(m, uint8_t *), len);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@ -968,10 +932,8 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
(void) ieee80211_input_all(ic, m, rssi,
RT2573_NOISE_FLOOR);
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
rum_start(ifp);
RUM_LOCK(sc);
rum_start(sc);
return;
default: /* Error */
@ -1011,8 +973,7 @@ static void
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@ -1109,8 +1070,7 @@ static int
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@ -1221,8 +1181,7 @@ static int
rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@ -1299,80 +1258,73 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
static void
rum_start(struct ifnet *ifp)
static int
rum_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct rum_softc *sc = ic->ic_softc;
int error;
RUM_LOCK(sc);
if (!sc->sc_running) {
RUM_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RUM_UNLOCK(sc);
return (error);
}
rum_start(sc);
RUM_UNLOCK(sc);
return (0);
}
static void
rum_start(struct rum_softc *sc)
{
struct rum_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RUM_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
RUM_UNLOCK(sc);
RUM_LOCK_ASSERT(sc, MA_OWNED);
if (!sc->sc_running)
return;
}
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (sc->tx_nfree < RUM_TX_MINFREE) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
while (sc->tx_nfree >= RUM_TX_MINFREE &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rum_tx_data(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
RUM_UNLOCK(sc);
}
static int
rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
rum_parent(struct ieee80211com *ic)
{
struct rum_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error;
struct rum_softc *sc = ic->ic_softc;
int startall = 0;
RUM_LOCK(sc);
error = sc->sc_detached ? ENXIO : 0;
RUM_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
RUM_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
rum_init_locked(sc);
startall = 1;
} else
rum_setpromisc(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
rum_stop(sc);
}
if (sc->sc_detached) {
RUM_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
return;
}
return error;
if (ic->ic_nrunning > 0) {
if (!sc->sc_running) {
rum_init(sc);
startall = 1;
} else
rum_setpromisc(sc);
} else if (sc->sc_running)
rum_stop(sc);
RUM_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -1572,8 +1524,7 @@ rum_select_antenna(struct rum_softc *sc)
static void
rum_enable_mrr(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@ -1589,8 +1540,7 @@ rum_enable_mrr(struct rum_softc *sc)
static void
rum_set_txpreamble(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@ -1605,8 +1555,7 @@ rum_set_txpreamble(struct rum_softc *sc)
static void
rum_set_basicrates(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
/* update basic rate set */
if (ic->ic_curmode == IEEE80211_MODE_11B) {
@ -1671,8 +1620,7 @@ rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
const struct rfprog *rfprog;
uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
int8_t power;
@ -1748,8 +1696,7 @@ rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_enable_tsf_sync(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@ -1784,10 +1731,9 @@ rum_enable_tsf(struct rum_softc *sc)
}
static void
rum_update_slot(struct ifnet *ifp)
rum_update_slot(struct rum_softc *sc)
{
struct rum_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t slottime;
uint32_t tmp;
@ -1827,18 +1773,17 @@ rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
static void
rum_setpromisc(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR0);
tmp &= ~RT2573_DROP_NOT_TO_ME;
if (!(ifp->if_flags & IFF_PROMISC))
if (sc->sc_ic.ic_promisc == 0)
tmp |= RT2573_DROP_NOT_TO_ME;
rum_write(sc, RT2573_TXRX_CSR0, tmp);
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ?
"entering" : "leaving");
}
@ -1847,10 +1792,11 @@ rum_update_promisc(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
RUM_LOCK(sc);
if (!sc->sc_running) {
RUM_UNLOCK(sc);
return;
}
rum_setpromisc(sc);
RUM_UNLOCK(sc);
}
@ -1887,7 +1833,7 @@ rum_read_eeprom(struct rum_softc *sc)
#endif
/* read MAC address */
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6);
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6);
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
val = le16toh(val);
@ -1994,10 +1940,10 @@ rum_bbp_init(struct rum_softc *sc)
}
static void
rum_init_locked(struct rum_softc *sc)
rum_init(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
usb_error_t error;
int i, ntries;
@ -2039,7 +1985,7 @@ rum_init_locked(struct rum_softc *sc)
/* clear STA registers */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
rum_set_macaddr(sc, IF_LLADDR(ifp));
rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* initialize ASIC */
rum_write(sc, RT2573_MAC_CSR1, 4);
@ -2058,13 +2004,12 @@ rum_init_locked(struct rum_softc *sc)
RT2573_DROP_ACKCTS;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RT2573_DROP_TODS;
if (!(ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RT2573_DROP_NOT_TO_ME;
}
rum_write(sc, RT2573_TXRX_CSR0, tmp);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_running = 1;
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
return;
@ -2073,30 +2018,14 @@ fail: rum_stop(sc);
#undef N
}
static void
rum_init(void *priv)
{
struct rum_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
RUM_LOCK(sc);
rum_init_locked(sc);
RUM_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
rum_stop(struct rum_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
RUM_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_running = 0;
RUM_UNLOCK(sc);
@ -2188,27 +2117,23 @@ static int
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ifnet *ifp = ni->ni_ic->ic_ifp;
struct rum_softc *sc = ifp->if_softc;
struct rum_softc *sc = ni->ni_ic->ic_softc;
RUM_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!sc->sc_running) {
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RUM_TX_MINFREE) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@ -2228,7 +2153,6 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RUM_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO;
@ -2262,8 +2186,7 @@ rum_ratectl_task(void *arg, int pending)
struct rum_vap *rvp = arg;
struct ieee80211vap *vap = &rvp->vap;
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct rum_softc *sc = ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@ -2283,7 +2206,8 @@ rum_ratectl_task(void *arg, int pending)
(void) ieee80211_ratectl_rate(ni, NULL, 0);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
/* count TX retry-fail as Tx errors */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
RUM_UNLOCK(sc);
@ -2292,15 +2216,14 @@ rum_ratectl_task(void *arg, int pending)
static void
rum_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct rum_softc *sc = ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
uint32_t tmp;
RUM_LOCK(sc);
/* abort TSF synchronization */
tmp = rum_read(sc, RT2573_TXRX_CSR9);
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
rum_set_bssid(sc, ifp->if_broadcastaddr);
rum_set_bssid(sc, ieee80211broadcastaddr);
RUM_UNLOCK(sc);
}
@ -2308,11 +2231,11 @@ rum_scan_start(struct ieee80211com *ic)
static void
rum_scan_end(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
rum_enable_tsf_sync(sc);
rum_set_bssid(sc, sc->sc_bssid);
rum_set_bssid(sc, ic->ic_macaddr);
RUM_UNLOCK(sc);
}
@ -2320,7 +2243,7 @@ rum_scan_end(struct ieee80211com *ic)
static void
rum_set_channel(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
rum_set_chan(sc, ic->ic_curchan);
@ -2330,8 +2253,7 @@ rum_set_channel(struct ieee80211com *ic)
static int
rum_get_rssi(struct rum_softc *sc, uint8_t raw)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int lna, agc, rssi;
lna = (raw >> 5) & 0x3;

View File

@ -85,7 +85,8 @@ enum {
};
struct rum_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@ -105,8 +106,8 @@ struct rum_softc {
uint32_t sta[6];
uint32_t rf_regs[4];
uint8_t txpow[44];
uint8_t sc_bssid[6];
uint8_t sc_detached;
u_int sc_detached:1,
sc_running:1;
struct {
uint8_t val;

View File

@ -410,8 +410,9 @@ static int run_tx_param(struct run_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int run_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void run_start(struct ifnet *);
static int run_ioctl(struct ifnet *, u_long, caddr_t);
static int run_transmit(struct ieee80211com *, struct mbuf *);
static void run_start(struct run_softc *);
static void run_parent(struct ieee80211com *);
static void run_iq_calib(struct run_softc *, u_int);
static void run_set_agc(struct run_softc *, uint8_t);
static void run_select_chan_group(struct run_softc *, int);
@ -457,7 +458,6 @@ static void run_rt3593_rf_setup(struct run_softc *);
static void run_rt5390_rf_setup(struct run_softc *);
static int run_txrx_enable(struct run_softc *);
static void run_adjust_freq_offset(struct run_softc *);
static void run_init(void *);
static void run_init_locked(struct run_softc *);
static void run_stop(void *);
static void run_delay(struct run_softc *, u_int);
@ -702,8 +702,7 @@ run_attach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
struct usb_attach_arg *uaa = device_get_ivars(self);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t ver;
int ntries, error;
uint8_t iface_index, bands;
@ -716,6 +715,7 @@ run_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2860_IFACE_INDEX;
@ -754,28 +754,10 @@ run_attach(device_t self)
device_printf(sc->sc_dev,
"MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n",
sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev),
sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid));
sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr));
RUN_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto detach;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "run", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = run_init;
ifp->if_ioctl = run_ioctl;
ifp->if_start = run_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -812,7 +794,7 @@ run_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_scan_start = run_scan_start;
ic->ic_scan_end = run_scan_end;
@ -824,9 +806,10 @@ run_attach(device_t self)
ic->ic_wme.wme_update = run_wme_update;
ic->ic_raw_xmit = run_raw_xmit;
ic->ic_update_promisc = run_update_promisc;
ic->ic_vap_create = run_vap_create;
ic->ic_vap_delete = run_vap_delete;
ic->ic_transmit = run_transmit;
ic->ic_parent = run_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -852,8 +835,7 @@ static int
run_detach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
int i;
RUN_LOCK(sc);
@ -872,16 +854,15 @@ run_detach(device_t self)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
RUN_UNLOCK(sc);
if (ifp) {
ic = ifp->if_l2com;
if (sc->sc_ic.ic_softc == sc) {
/* drain tasks */
usb_callout_drain(&sc->ratectl_ch);
ieee80211_draintask(ic, &sc->cmdq_task);
ieee80211_draintask(ic, &sc->ratectl_task);
ieee80211_ifdetach(ic);
if_free(ifp);
}
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -893,14 +874,13 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct run_softc *sc = ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp;
struct ieee80211vap *vap;
int i;
if (sc->rvp_cnt >= RUN_VAP_MAX) {
if_printf(ifp, "number of VAPs maxed out\n");
device_printf(sc->sc_dev, "number of VAPs maxed out\n");
return (NULL);
}
@ -926,23 +906,21 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
break;
}
if (vap == NULL) {
if_printf(ifp, "wds only supported in ap mode\n");
device_printf(sc->sc_dev,
"wds only supported in ap mode\n");
return (NULL);
}
break;
default:
if_printf(ifp, "unknown opmode %d\n", opmode);
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return (NULL);
}
rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (rvp == NULL)
return (NULL);
rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->vap;
if (ieee80211_vap_setup(ic, vap, name, unit,
opmode, flags, bssid, mac) != 0) {
if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
bssid) != 0) {
/* out of memory */
free(rvp, M_80211_VAP);
return (NULL);
@ -969,7 +947,8 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status,
mac);
/* make sure id is always unique */
for (i = 0; i < RUN_VAP_MAX; i++) {
@ -995,7 +974,6 @@ static void
run_vap_delete(struct ieee80211vap *vap)
{
struct run_vap *rvp = RUN_VAP(vap);
struct ifnet *ifp;
struct ieee80211com *ic;
struct run_softc *sc;
uint8_t rvp_id;
@ -1004,9 +982,7 @@ run_vap_delete(struct ieee80211vap *vap)
return;
ic = vap->iv_ic;
ifp = ic->ic_ifp;
sc = ifp->if_softc;
sc = ic->ic_softc;
RUN_LOCK(sc);
@ -1740,6 +1716,7 @@ run_get_txpower(struct run_softc *sc)
static int
run_read_eeprom(struct run_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
int8_t delta_2ghz, delta_5ghz;
uint32_t tmp;
uint16_t val;
@ -1760,14 +1737,14 @@ run_read_eeprom(struct run_softc *sc)
/* read MAC address */
run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
sc->sc_bssid[0] = val & 0xff;
sc->sc_bssid[1] = val >> 8;
ic->ic_macaddr[0] = val & 0xff;
ic->ic_macaddr[1] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC23, &val);
sc->sc_bssid[2] = val & 0xff;
sc->sc_bssid[3] = val >> 8;
ic->ic_macaddr[2] = val & 0xff;
ic->ic_macaddr[3] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC45, &val);
sc->sc_bssid[4] = val & 0xff;
sc->sc_bssid[5] = val >> 8;
ic->ic_macaddr[4] = val & 0xff;
ic->ic_macaddr[5] = val >> 8;
if (sc->mac_ver < 0x3593) {
/* read vender BBP settings */
@ -2002,7 +1979,7 @@ run_media_change(struct ifnet *ifp)
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
const struct ieee80211_txparam *tp;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint8_t rate, ridx;
int error;
@ -2033,7 +2010,7 @@ run_media_change(struct ifnet *ifp)
#if 0
if ((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)){
(ifp->if_drv_flags & RUN_RUNNING)){
run_init_locked(sc);
}
#endif
@ -2048,7 +2025,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
const struct ieee80211_txparam *tp;
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
@ -2144,7 +2121,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
run_set_txpreamble(sc);
run_set_basicrates(sc);
ni = ieee80211_ref_node(vap->iv_bss);
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
run_set_bssid(sc, ni->ni_bssid);
ieee80211_free_node(ni);
run_enable_tsf_sync(sc);
@ -2181,7 +2158,7 @@ static void
run_wme_update_cb(void *arg)
{
struct ieee80211com *ic = arg;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct ieee80211_wme_state *wmesp = &ic->ic_wme;
int aci, error = 0;
@ -2234,7 +2211,7 @@ run_wme_update_cb(void *arg)
static int
run_wme_update(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
/* sometime called wothout lock */
if (mtx_owned(&ic->ic_comlock.mtx)) {
@ -2277,7 +2254,7 @@ run_key_set_cb(void *arg)
struct ieee80211vap *vap = cmdq->arg1;
struct ieee80211_key *k = cmdq->k;
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
uint32_t attr;
uint16_t base, associd;
@ -2399,7 +2376,7 @@ run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@ -2467,7 +2444,7 @@ static int
run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct ieee80211_key *k0;
uint32_t i;
@ -2498,7 +2475,7 @@ run_ratectl_to(void *arg)
struct run_softc *sc = arg;
/* do it in a process context, so it can go sleep */
ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task);
ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task);
/* next timeout will be rescheduled in the callback task */
}
@ -2507,7 +2484,7 @@ static void
run_ratectl_cb(void *arg, int pending)
{
struct run_softc *sc = arg;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap == NULL)
@ -2540,7 +2517,6 @@ static void
run_drain_fifo(void *arg)
{
struct run_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
uint32_t stat;
uint16_t (*wstat)[3];
uint8_t wcid, mcs, pid;
@ -2577,7 +2553,7 @@ run_drain_fifo(void *arg)
if (stat & RT2860_TXQ_OK)
(*wstat)[RUN_SUCCESS]++;
else
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/*
* Check if there were retries, ie if the Tx success rate is
* different from the requested rate. Note that it works only
@ -2600,8 +2576,6 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
{
struct run_softc *sc = arg;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct run_node *rn = (void *)ni;
union run_stats sta[2];
uint16_t (*wstat)[3];
@ -2623,7 +2597,8 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
goto fail;
/* count failed TX as errors */
if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail));
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
le16toh(sta[0].error.fail));
retrycnt = le16toh(sta[1].tx.retry);
success = le16toh(sta[1].tx.success);
@ -2661,7 +2636,7 @@ run_newassoc_cb(void *arg)
{
struct run_cmdq *cmdq = arg;
struct ieee80211_node *ni = cmdq->arg1;
struct run_softc *sc = ni->ni_vap->iv_ic->ic_ifp->if_softc;
struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc;
uint8_t wcid = cmdq->wcid;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@ -2679,7 +2654,7 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
struct ieee80211_rateset *rs = &ni->ni_rates;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint8_t rate;
uint8_t ridx;
uint8_t wcid;
@ -2769,8 +2744,7 @@ run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
static void
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct rt2870_rxd *rxd;
@ -2789,7 +2763,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rxwisize += sizeof(uint32_t);
if (__predict_false(len > dmalen)) {
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("bad RXWI length %u > %u\n", len, dmalen);
return;
}
@ -2799,7 +2773,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV");
return;
}
@ -2828,7 +2802,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx);
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("MIC error. Someone is lying.\n");
return;
}
@ -2837,7 +2811,6 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant);
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = len;
if (ni != NULL) {
@ -2890,7 +2863,7 @@ static void
run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m = NULL;
struct mbuf *m0;
uint32_t dmalen;
@ -2928,7 +2901,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (sc->rx_m == NULL) {
DPRINTF("could not allocate mbuf - idle with stall\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
usbd_xfer_set_stall(xfer);
usbd_xfer_set_frames(xfer, 0);
} else {
@ -2948,12 +2921,9 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
if (error == USB_ERR_TIMEOUT)
device_printf(sc->sc_dev, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
if (sc->rx_m != NULL) {
@ -3001,7 +2971,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) {
DPRINTF("could not allocate mbuf\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
break;
}
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
@ -3048,8 +3018,7 @@ static void
run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct run_tx_data *data;
struct ieee80211vap *vap = NULL;
struct usb_page_cache *pc;
@ -3067,14 +3036,9 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
"bytes @ index %d\n", actlen, index);
data = usbd_xfer_get_priv(xfer);
run_tx_free(pq, data, 0);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
usbd_xfer_set_priv(xfer, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@ -3091,11 +3055,7 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
size + 3 + 8) > RUN_MAX_TXSZ) {
DPRINTF("data overflow, %u bytes\n",
m->m_pkthdr.len);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
run_tx_free(pq, data, 1);
goto tr_setup;
}
@ -3132,12 +3092,8 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
usbd_xfer_set_frame_len(xfer, 0, size);
usbd_xfer_set_priv(xfer, data);
usbd_transfer_submit(xfer);
RUN_UNLOCK(sc);
run_start(ifp);
RUN_LOCK(sc);
run_start(sc);
break;
@ -3147,14 +3103,13 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
data = usbd_xfer_get_priv(xfer);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (data != NULL) {
if(data->ni != NULL)
vap = data->ni->ni_vap;
run_tx_free(pq, data, error);
usbd_xfer_set_priv(xfer, NULL);
}
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps);
@ -3220,7 +3175,7 @@ static void
run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
{
struct mbuf *m = data->m;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = data->ni->ni_vap;
struct ieee80211_frame *wh;
struct rt2870_txd *txd;
@ -3283,7 +3238,7 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
static int
run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_channel *chan;
@ -3451,8 +3406,7 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
static int
run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct run_node *rn = (void *)ni;
struct run_tx_data *data;
struct ieee80211_frame *wh;
@ -3483,11 +3437,9 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
USETW(wh->i_dur, dur);
}
if (sc->sc_epq[0].tx_nfree == 0) {
if (sc->sc_epq[0].tx_nfree == 0)
/* let caller free mbuf */
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (EIO);
}
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh);
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next);
sc->sc_epq[0].tx_nfree--;
@ -3555,11 +3507,9 @@ run_sendprot(struct run_softc *sc,
wflags = RT2860_TX_FRAG;
/* check that there are free slots before allocating the mbuf */
if (sc->sc_epq[0].tx_nfree == 0) {
if (sc->sc_epq[0].tx_nfree == 0)
/* let caller free mbuf */
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (ENOBUFS);
}
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
@ -3570,7 +3520,7 @@ run_sendprot(struct run_softc *sc,
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
if (mprot == NULL) {
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("could not allocate mbuf\n");
return (ENOBUFS);
}
@ -3652,7 +3602,6 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
if (sc->sc_epq[0].tx_nfree == 0) {
/* let caller free mbuf */
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
DPRINTF("sending raw frame, but tx ring is full\n");
return (EIO);
}
@ -3691,36 +3640,31 @@ static int
run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ifnet *ifp = ni->ni_ic->ic_ifp;
struct run_softc *sc = ifp->if_softc;
struct run_softc *sc = ni->ni_ic->ic_softc;
int error = 0;
RUN_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
error = ENETDOWN;
if (!(sc->sc_flags & RUN_RUNNING)) {
error = ENETDOWN;
goto done;
}
if (params == NULL) {
/* tx mgt packet */
if ((error = run_tx_mgt(sc, m, ni)) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("mgt tx failed\n");
goto done;
}
} else {
/* tx raw packet with param */
if ((error = run_tx_param(sc, m, ni, params)) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("tx with param failed\n");
goto done;
}
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
done:
RUN_UNLOCK(sc);
@ -3733,83 +3677,71 @@ run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (error);
}
static void
run_start(struct ifnet *ifp)
static int
run_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct run_softc *sc = ic->ic_softc;
int error;
RUN_LOCK(sc);
if ((sc->sc_flags & RUN_RUNNING) == 0) {
RUN_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RUN_UNLOCK(sc);
return (error);
}
run_start(sc);
RUN_UNLOCK(sc);
return (0);
}
static void
run_start(struct run_softc *sc)
{
struct run_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RUN_LOCK(sc);
RUN_LOCK_ASSERT(sc, MA_OWNED);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
if ((sc->sc_flags & RUN_RUNNING) == 0)
return;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (run_tx(sc, m, ni) != 0) {
mbufq_prepend(&sc->sc_snd, m);
break;
}
}
}
static void
run_parent(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
int startall = 0;
RUN_LOCK(sc);
if (sc->sc_detached) {
RUN_UNLOCK(sc);
return;
}
for (;;) {
/* send data frames */
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (run_tx(sc, m, ni) != 0) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
}
if (ic->ic_nrunning > 0) {
if (!(sc->sc_flags & RUN_RUNNING)) {
startall = 1;
run_init_locked(sc);
} else
run_update_promisc_locked(sc);
} else if ((sc->sc_flags & RUN_RUNNING) && sc->rvp_cnt <= 1)
run_stop(sc);
RUN_UNLOCK(sc);
}
static int
run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct run_softc *sc = ifp->if_softc;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int startall = 0;
int error;
RUN_LOCK(sc);
error = sc->sc_detached ? ENXIO : 0;
RUN_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
RUN_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){
startall = 1;
run_init_locked(sc);
} else
run_update_promisc_locked(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
(ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) {
run_stop(sc);
}
}
RUN_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return (error);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -4796,7 +4728,7 @@ run_set_rx_antenna(struct run_softc *sc, int aux)
static int
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
@ -4841,7 +4773,7 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
static void
run_set_channel(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
RUN_LOCK(sc);
run_set_chan(sc, ic->ic_curchan);
@ -4853,7 +4785,7 @@ run_set_channel(struct ieee80211com *ic)
static void
run_scan_start(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
RUN_LOCK(sc);
@ -4863,7 +4795,7 @@ run_scan_start(struct ieee80211com *ic)
run_write(sc, RT2860_BCN_TIME_CFG,
tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
RT2860_TBTT_TIMER_EN));
run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr);
run_set_bssid(sc, ieee80211broadcastaddr);
RUN_UNLOCK(sc);
@ -4873,13 +4805,13 @@ run_scan_start(struct ieee80211com *ic)
static void
run_scan_end(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
RUN_LOCK(sc);
run_enable_tsf_sync(sc);
/* XXX keep local copy */
run_set_bssid(sc, sc->sc_bssid);
run_set_bssid(sc, ic->ic_macaddr);
RUN_UNLOCK(sc);
@ -4894,7 +4826,7 @@ static void
run_update_beacon(struct ieee80211vap *vap, int item)
{
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp = RUN_VAP(vap);
int mcast = 0;
uint32_t i;
@ -4939,7 +4871,7 @@ run_update_beacon_cb(void *arg)
struct ieee80211vap *vap = arg;
struct run_vap *rvp = RUN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
struct rt2860_txwi txwi;
struct mbuf *m;
uint16_t txwisize;
@ -4987,7 +4919,7 @@ run_update_beacon_cb(void *arg)
static void
run_updateprot(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@ -5001,7 +4933,7 @@ static void
run_updateprot_cb(void *arg)
{
struct ieee80211com *ic = arg;
struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
@ -5025,7 +4957,7 @@ static void
run_usb_timeout_cb(void *arg)
{
struct ieee80211vap *vap = arg;
struct run_softc *sc = vap->iv_ic->ic_ifp->if_softc;
struct run_softc *sc = vap->iv_ic->ic_softc;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@ -5071,12 +5003,12 @@ run_update_promisc_locked(struct run_softc *sc)
run_read(sc, RT2860_RX_FILTR_CFG, &tmp);
tmp |= RT2860_DROP_UC_NOME;
if (sc->sc_ifp->if_flags & IFF_PROMISC)
if (sc->sc_ic.ic_promisc > 0)
tmp &= ~RT2860_DROP_UC_NOME;
run_write(sc, RT2860_RX_FILTR_CFG, tmp);
DPRINTF("%s promiscuous mode\n", (sc->sc_ifp->if_flags & IFF_PROMISC) ?
DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ?
"entering" : "leaving");
}
@ -5085,7 +5017,7 @@ run_update_promisc(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if ((sc->sc_flags & RUN_RUNNING) == 0)
return;
RUN_LOCK(sc);
@ -5096,7 +5028,7 @@ run_update_promisc(struct ieee80211com *ic)
static void
run_enable_tsf_sync(struct run_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@ -5161,7 +5093,7 @@ run_enable_mrr(struct run_softc *sc)
static void
run_set_txpreamble(struct run_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
run_read(sc, RT2860_AUTO_RSP_CFG, &tmp);
@ -5175,7 +5107,7 @@ run_set_txpreamble(struct run_softc *sc)
static void
run_set_basicrates(struct run_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
/* set basic rates mask */
if (ic->ic_curmode == IEEE80211_MODE_11B)
@ -5220,7 +5152,7 @@ run_updateslot(struct ieee80211com *ic)
i = RUN_CMDQ_GET(&sc->cmdq_store);
DPRINTF("cmdq_store=%d\n", i);
sc->cmdq[i].func = run_updateslot_cb;
sc->cmdq[i].arg0 = ic->ic_ifp;
sc->cmdq[i].arg0 = ic;
ieee80211_runtask(ic, &sc->cmdq_task);
return;
@ -5230,9 +5162,8 @@ run_updateslot(struct ieee80211com *ic)
static void
run_updateslot_cb(void *arg)
{
struct ifnet *ifp = arg;
struct run_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = arg;
struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp);
@ -5244,15 +5175,12 @@ run_updateslot_cb(void *arg)
static void
run_update_mcast(struct ieee80211com *ic)
{
/* h/w filter supports getting everything or nothing */
ic->ic_ifp->if_flags |= IFF_ALLMULTI;
}
static int8_t
run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c = ic->ic_curchan;
int delta;
@ -5902,7 +5830,7 @@ run_rt5390_rf_setup(struct run_softc *sc)
static int
run_txrx_enable(struct run_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int error, ntries;
@ -5962,8 +5890,8 @@ run_adjust_freq_offset(struct run_softc *sc)
static void
run_init_locked(struct run_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
uint8_t bbp1, bbp3;
int i;
@ -5993,7 +5921,7 @@ run_init_locked(struct run_softc *sc)
for (i = 0; i != RUN_EP_QUEUES; i++)
run_setup_tx_list(sc, &sc->sc_epq[i]);
run_set_macaddr(sc, IF_LLADDR(ifp));
run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
for (ntries = 0; ntries < 100; ntries++) {
if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
@ -6166,8 +6094,7 @@ run_init_locked(struct run_softc *sc)
/* turn radio LED on */
run_set_leds(sc, RT2860_LED_RADIO);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= RUN_RUNNING;
sc->cmdq_run = RUN_CMDQ_GO;
for (i = 0; i != RUN_N_XFER; i++)
@ -6184,36 +6111,20 @@ run_init_locked(struct run_softc *sc)
run_stop(sc);
}
static void
run_init(void *arg)
{
struct run_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
RUN_LOCK(sc);
run_init_locked(sc);
RUN_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic);
}
static void
run_stop(void *arg)
{
struct run_softc *sc = (struct run_softc *)arg;
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
int i;
int ntries;
RUN_LOCK_ASSERT(sc, MA_OWNED);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & RUN_RUNNING)
run_set_leds(sc, 0); /* turn all LEDs off */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~RUN_RUNNING;
sc->ratectl_run = RUN_RATECTL_OFF;
sc->cmdq_run = sc->cmdq_key_set;

View File

@ -151,13 +151,16 @@ struct run_endpoint_queue {
};
struct run_softc {
struct mtx sc_mtx;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
struct ifnet *sc_ifp;
int sc_need_fwload;
int sc_flags;
#define RUN_FLAG_FWLOAD_NEEDED 0x01
#define RUN_RUNNING 0x02
uint16_t wcid_stats[RT2870_WCID_MAX + 1][3];
#define RUN_TXCNT 0
@ -203,10 +206,6 @@ struct run_softc {
uint32_t txpow40mhz_2ghz[5];
uint32_t txpow40mhz_5ghz[5];
uint8_t sc_bssid[6];
struct mtx sc_mtx;
struct run_endpoint_queue sc_epq[RUN_EP_QUEUES];
struct task ratectl_task;

View File

@ -279,12 +279,11 @@ static int uath_alloc_rx_data_list(struct uath_softc *);
static int uath_alloc_tx_data_list(struct uath_softc *);
static void uath_free_rx_data_list(struct uath_softc *);
static void uath_free_tx_data_list(struct uath_softc *);
static int uath_init_locked(void *);
static void uath_init(void *);
static void uath_stop_locked(struct ifnet *);
static void uath_stop(struct ifnet *);
static int uath_ioctl(struct ifnet *, u_long, caddr_t);
static void uath_start(struct ifnet *);
static int uath_init(struct uath_softc *);
static void uath_stop(struct uath_softc *);
static void uath_parent(struct ieee80211com *);
static int uath_transmit(struct ieee80211com *, struct mbuf *);
static void uath_start(struct uath_softc *);
static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void uath_scan_start(struct ieee80211com *);
@ -336,11 +335,9 @@ uath_attach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
usb_error_t error;
uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@ -356,6 +353,7 @@ uath_attach(device_t dev)
MTX_DEF);
callout_init(&sc->stat_ch, 0);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
@ -387,31 +385,24 @@ uath_attach(device_t dev)
error = uath_host_available(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not initialize adapter\n");
goto fail3;
goto fail2;
}
error = uath_get_devcap(sc);
if (error != 0) {
device_printf(sc->sc_dev,
"could not get device capabilities\n");
goto fail3;
goto fail2;
}
UATH_UNLOCK(sc);
/* Create device sysctl node. */
uath_sysctl_node(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not allocate ifnet\n");
error = ENXIO;
goto fail2;
}
UATH_LOCK(sc);
error = uath_get_devstatus(sc, macaddr);
error = uath_get_devstatus(sc, ic->ic_macaddr);
if (error != 0) {
device_printf(sc->sc_dev, "could not get device status\n");
goto fail4;
goto fail2;
}
/*
@ -420,28 +411,15 @@ uath_attach(device_t dev)
error = uath_alloc_rx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Rx data list\n");
goto fail4;
goto fail2;
}
error = uath_alloc_tx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Tx data list\n");
goto fail4;
goto fail2;
}
UATH_UNLOCK(sc);
ifp->if_softc = sc;
if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = uath_init;
ifp->if_ioctl = uath_ioctl;
ifp->if_start = uath_start;
/* XXX UATH_TX_DATA_LIST_COUNT */
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -469,16 +447,17 @@ uath_attach(device_t dev)
/* XXX turbo */
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = uath_raw_xmit;
ic->ic_scan_start = uath_scan_start;
ic->ic_scan_end = uath_scan_end;
ic->ic_set_channel = uath_set_channel;
ic->ic_vap_create = uath_vap_create;
ic->ic_vap_delete = uath_vap_delete;
ic->ic_update_mcast = uath_update_mcast;
ic->ic_update_promisc = uath_update_promisc;
ic->ic_transmit = uath_transmit;
ic->ic_parent = uath_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -491,9 +470,8 @@ uath_attach(device_t dev)
return (0);
fail4: if_free(ifp);
fail3: UATH_UNLOCK(sc);
fail2: uath_free_cmd_list(sc, sc->sc_cmd);
fail2: UATH_UNLOCK(sc);
uath_free_cmd_list(sc, sc->sc_cmd);
fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail:
return (error);
@ -503,8 +481,7 @@ static int
uath_detach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@ -525,9 +502,9 @@ uath_detach(device_t dev)
STAILQ_INIT(&sc->sc_cmd_pending);
STAILQ_INIT(&sc->sc_cmd_waiting);
STAILQ_INIT(&sc->sc_cmd_inactive);
UATH_UNLOCK(sc);
uath_stop(ifp);
uath_stop(sc);
UATH_UNLOCK(sc);
callout_drain(&sc->stat_ch);
callout_drain(&sc->watchdog_ch);
@ -547,7 +524,7 @@ uath_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
ieee80211_ifdetach(ic);
if_free(ifp);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@ -1067,15 +1044,12 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (uvp == NULL)
return (NULL);
uvp = malloc(sizeof(struct uath_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -1087,7 +1061,7 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@ -1102,18 +1076,17 @@ uath_vap_delete(struct ieee80211vap *vap)
}
static int
uath_init_locked(void *arg)
uath_init(struct uath_softc *sc)
{
struct uath_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t val;
int error;
UATH_ASSERT_LOCKED(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
uath_stop_locked(ifp);
if (sc->sc_flags & UATH_FLAG_INITDONE)
uath_stop(sc);
/* reset variables */
sc->sc_intrx_nextnum = sc->sc_msgid = 0;
@ -1122,7 +1095,8 @@ uath_init_locked(void *arg)
uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
/* set MAC address */
uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
uath_config_multi(sc, CFG_MAC_ADDR,
vap ? vap->iv_myaddr : ic->ic_macaddr, IEEE80211_ADDR_LEN);
/* XXX honor net80211 state */
uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
@ -1171,8 +1145,6 @@ uath_init_locked(void *arg)
UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
UATH_FILTER_OP_SET);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UATH_FLAG_INITDONE;
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@ -1180,28 +1152,16 @@ uath_init_locked(void *arg)
return (0);
fail:
uath_stop_locked(ifp);
uath_stop(sc);
return (error);
}
static void
uath_init(void *arg)
uath_stop(struct uath_softc *sc)
{
struct uath_softc *sc = arg;
UATH_LOCK(sc);
(void)uath_init_locked(sc);
UATH_UNLOCK(sc);
}
static void
uath_stop_locked(struct ifnet *ifp)
{
struct uath_softc *sc = ifp->if_softc;
UATH_ASSERT_LOCKED(sc);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UATH_FLAG_INITDONE;
callout_stop(&sc->stat_ch);
@ -1217,16 +1177,6 @@ uath_stop_locked(struct ifnet *ifp)
uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
}
static void
uath_stop(struct ifnet *ifp)
{
struct uath_softc *sc = ifp->if_softc;
UATH_LOCK(sc);
uath_stop_locked(ifp);
UATH_UNLOCK(sc);
}
static int
uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
{
@ -1329,13 +1279,13 @@ static void
uath_watchdog(void *arg)
{
struct uath_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
/*uath_init(ifp); XXX needs a process context! */
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
/*uath_init(sc); XXX needs a process context! */
counter_u64_add(ic->ic_oerrors, 1);
return;
}
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@ -1450,12 +1400,8 @@ uath_getbuf(struct uath_softc *sc)
UATH_ASSERT_LOCKED(sc);
bf = _uath_getbuf(sc);
if (bf == NULL) {
struct ifnet *ifp = sc->sc_ifp;
if (bf == NULL)
DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
}
return (bf);
}
@ -1474,8 +1420,7 @@ static int
uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
{
#ifdef UATH_DEBUG
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
#endif
struct uath_cmd_reset reset;
@ -1554,47 +1499,28 @@ uath_wme_init(struct uath_softc *sc)
return (error);
}
static int
uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
uath_parent(struct ieee80211com *ic)
{
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
struct uath_softc *sc = ifp->if_softc;
int error;
struct uath_softc *sc = ic->ic_softc;
int startall = 0;
UATH_LOCK(sc);
error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
UATH_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
uath_init(ifp->if_softc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
uath_stop(ifp);
}
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
if (sc->sc_flags & UATH_FLAG_INVALID) {
UATH_UNLOCK(sc);
return;
}
return (error);
if (ic->ic_nrunning > 0) {
if (!(sc->sc_flags & UATH_FLAG_INITDONE)) {
uath_init(sc);
startall = 1;
}
} else if (sc->sc_flags & UATH_FLAG_INITDONE)
uath_stop(sc);
UATH_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static int
@ -1763,31 +1689,49 @@ uath_freetx(struct mbuf *m)
} while ((m = next) != NULL);
}
static int
uath_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct uath_softc *sc = ic->ic_softc;
int error;
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
UATH_UNLOCK(sc);
return (error);
}
uath_start(sc);
UATH_UNLOCK(sc);
return (0);
}
static void
uath_start(struct ifnet *ifp)
uath_start(struct uath_softc *sc)
{
struct uath_data *bf;
struct uath_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m, *next;
uath_datahead frags;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
UATH_ASSERT_LOCKED(sc);
if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0 ||
(sc->sc_flags & UATH_FLAG_INVALID))
return;
UATH_LOCK(sc);
for (;;) {
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = uath_getbuf(sc);
if (bf == NULL)
break;
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL) {
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
if (bf == NULL) {
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
@ -1816,7 +1760,8 @@ uath_start(struct ifnet *ifp)
next = m->m_nextpkt;
if (uath_tx_start(sc, m, ni, bf) != 0) {
bad:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
reclaim:
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
@ -1847,7 +1792,6 @@ uath_start(struct ifnet *ifp)
sc->sc_tx_timer = 5;
}
UATH_UNLOCK(sc);
}
static int
@ -1855,19 +1799,19 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct uath_data *bf;
struct uath_softc *sc = ifp->if_softc;
struct uath_softc *sc = ic->ic_softc;
UATH_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
!(sc->sc_flags & UATH_FLAG_INITDONE)) {
m_freem(m);
ieee80211_free_node(ni);
UATH_UNLOCK(sc);
return (ENETDOWN);
}
UATH_LOCK(sc);
/* grab a TX buffer */
bf = uath_getbuf(sc);
if (bf == NULL) {
@ -1880,7 +1824,6 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
sc->sc_seqnum = 0;
if (uath_tx_start(sc, m, ni, bf) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
UATH_UNLOCK(sc);
@ -1907,12 +1850,11 @@ uath_scan_end(struct ieee80211com *ic)
static void
uath_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct uath_softc *sc = ifp->if_softc;
struct uath_softc *sc = ic->ic_softc;
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@ -1933,7 +1875,7 @@ uath_update_mcast(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
(ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@ -1953,7 +1895,7 @@ uath_update_promisc(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
(ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@ -1970,7 +1912,7 @@ static int
uath_create_connection(struct uath_softc *sc, uint32_t connid)
{
const struct ieee80211_rateset *rs;
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_create_connection create;
@ -2021,7 +1963,7 @@ uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
static int
uath_write_associd(struct uath_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_set_associd associd;
@ -2075,7 +2017,7 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int error;
struct ieee80211_node *ni;
struct ieee80211com *ic = vap->iv_ic;
struct uath_softc *sc = ic->ic_ifp->if_softc;
struct uath_softc *sc = ic->ic_softc;
struct uath_vap *uvp = UATH_VAP(vap);
DPRINTF(sc, UATH_DEBUG_STATE,
@ -2542,8 +2484,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
struct uath_rx_desc **pdesc)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct uath_chunk *chunk;
struct uath_rx_desc *desc;
struct mbuf *m = data->m, *mnew, *mp;
@ -2555,14 +2496,14 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (actlen < (int)UATH_MIN_RXBUFSZ) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: wrong xfer size (len=%d)\n", __func__, actlen);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
chunk = (struct uath_chunk *)data->buf;
if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
@ -2595,7 +2536,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
chunklen) > UATH_MAX_INTRX_SIZE) {
UATH_STAT_INC(sc, st_invalidlen);
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@ -2620,7 +2561,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (mnew == NULL) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: can't get new mbuf, drop frame\n", __func__);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@ -2661,7 +2602,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: bad descriptor (len=%d)\n", __func__,
be32toh(desc->len));
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
counter_u64_add(ic->ic_ierrors, 1);
UATH_STAT_INC(sc, st_toobigrxpkt);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
@ -2673,13 +2614,11 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;
mp->m_pkthdr.rcvif = ifp;
mp->m_flags |= M_PKTHDR;
mp->m_pkthdr.len = sc->sc_intrx_len;
m = mp;
@ -2705,7 +2644,6 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
tap->wr_antnoise = -95;
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
UATH_RESET_INTRX(sc);
return (m);
@ -2715,8 +2653,7 @@ static void
uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@ -2776,10 +2713,8 @@ uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
m = NULL;
desc = NULL;
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
uath_start(ifp);
UATH_LOCK(sc);
uath_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@ -2792,7 +2727,7 @@ uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@ -2803,40 +2738,22 @@ static void
uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
UATH_ASSERT_LOCKED(sc);
/*
* Do any tx complete callback. Note this must be done before releasing
* the node reference.
*/
if (data->m) {
m = data->m;
if (m->m_flags & M_TXCB &&
(sc->sc_flags & UATH_FLAG_INVALID) == 0) {
/* XXX status? */
ieee80211_process_callback(data->ni, m, 0);
}
m_freem(m);
/* XXX status? */
ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
}
if (data->ni) {
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_tx_timer = 0;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct uath_data *data;
UATH_ASSERT_LOCKED(sc);
@ -2868,19 +2785,18 @@ uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
UATH_UNLOCK(sc);
uath_start(ifp);
UATH_LOCK(sc);
uath_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
if_inc_counter(data->ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
ieee80211_free_node(data->ni);
data->ni = NULL;
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);

View File

@ -183,7 +183,8 @@ struct uath_vap {
#define UATH_VAP(vap) ((struct uath_vap *)(vap))
struct uath_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
void *sc_cmd_dma_buf;

View File

@ -128,10 +128,10 @@ static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int);
static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int);
static uint32_t upgt_chksum_le(const uint32_t *, size_t);
static void upgt_tx_done(struct upgt_softc *, uint8_t *);
static void upgt_init(void *);
static void upgt_init_locked(struct upgt_softc *);
static int upgt_ioctl(struct ifnet *, u_long, caddr_t);
static void upgt_start(struct ifnet *);
static void upgt_init(struct upgt_softc *);
static void upgt_parent(struct ieee80211com *);
static int upgt_transmit(struct ieee80211com *, struct mbuf *);
static void upgt_start(struct upgt_softc *);
static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void upgt_scan_start(struct ieee80211com *);
@ -240,12 +240,11 @@ upgt_match(device_t dev)
static int
upgt_attach(device_t dev)
{
int error;
struct ieee80211com *ic;
struct ifnet *ifp;
struct upgt_softc *sc = device_get_softc(dev);
struct ieee80211com *ic = &sc->sc_ic;
struct usb_attach_arg *uaa = device_get_ivars(dev);
uint8_t bands, iface_index = UPGT_IFACE_INDEX;
int error;
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@ -258,6 +257,7 @@ upgt_attach(device_t dev)
MTX_DEF);
callout_init(&sc->sc_led_ch, 0);
callout_init(&sc->sc_watchdog_ch, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
@ -280,26 +280,20 @@ upgt_attach(device_t dev)
if (error)
goto fail3;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
goto fail4;
}
/* Initialize the device. */
error = upgt_device_reset(sc);
if (error)
goto fail5;
goto fail4;
/* Verify the firmware. */
error = upgt_fw_verify(sc);
if (error)
goto fail5;
goto fail4;
/* Calculate device memory space. */
if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) {
device_printf(dev,
"could not find memory space addresses on FW\n");
error = EIO;
goto fail5;
goto fail4;
}
sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1;
sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1;
@ -316,31 +310,19 @@ upgt_attach(device_t dev)
/* Load the firmware. */
error = upgt_fw_load(sc);
if (error)
goto fail5;
goto fail4;
/* Read the whole EEPROM content and parse it. */
error = upgt_eeprom_read(sc);
if (error)
goto fail5;
goto fail4;
error = upgt_eeprom_parse(sc);
if (error)
goto fail5;
goto fail4;
/* all works related with the device have done here. */
upgt_abort_xfers(sc);
/* Setup the 802.11 device. */
ifp->if_softc = sc;
if_initname(ifp, "upgt", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = upgt_init;
ifp->if_ioctl = upgt_ioctl;
ifp->if_start = upgt_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -360,15 +342,16 @@ upgt_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_myaddr);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = upgt_raw_xmit;
ic->ic_scan_start = upgt_scan_start;
ic->ic_scan_end = upgt_scan_end;
ic->ic_set_channel = upgt_set_channel;
ic->ic_vap_create = upgt_vap_create;
ic->ic_vap_delete = upgt_vap_delete;
ic->ic_update_mcast = upgt_update_mcast;
ic->ic_transmit = upgt_transmit;
ic->ic_parent = upgt_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -383,7 +366,6 @@ upgt_attach(device_t dev)
return (0);
fail5: if_free(ifp);
fail4: upgt_free_rx(sc);
fail3: upgt_free_tx(sc);
fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
@ -395,30 +377,13 @@ fail1: mtx_destroy(&sc->sc_mtx);
static void
upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
UPGT_ASSERT_LOCKED(sc);
/*
* Do any tx complete callback. Note this must be done before releasing
* the node reference.
*/
if (data->m) {
m = data->m;
if (m->m_flags & M_TXCB) {
/* XXX status? */
ieee80211_process_callback(data->ni, m, 0);
}
m_freem(m);
/* XXX status? */
ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
}
if (data->ni) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
static void
@ -462,77 +427,43 @@ upgt_get_stats(struct upgt_softc *sc)
upgt_bulk_tx(sc, data_cmd);
}
static int
upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
upgt_parent(struct ieee80211com *ic)
{
struct upgt_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error;
struct upgt_softc *sc = ic->ic_softc;
int startall = 0;
UPGT_LOCK(sc);
error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
UPGT_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if ((ifp->if_flags ^ sc->sc_if_flags) &
(IFF_ALLMULTI | IFF_PROMISC))
upgt_set_multi(sc);
} else {
upgt_init(sc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
upgt_stop(sc);
}
sc->sc_if_flags = ifp->if_flags;
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
if (sc->sc_flags & UPGT_FLAG_DETACHED) {
UPGT_UNLOCK(sc);
return;
}
return error;
}
static void
upgt_stop_locked(struct upgt_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
upgt_set_macfilter(sc, IEEE80211_S_INIT);
upgt_abort_xfers_locked(sc);
if (ic->ic_nrunning > 0) {
if (sc->sc_flags & UPGT_FLAG_INITDONE) {
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0)
upgt_set_multi(sc);
} else {
upgt_init(sc);
startall = 1;
}
} else if (sc->sc_flags & UPGT_FLAG_INITDONE)
upgt_stop(sc);
UPGT_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
upgt_stop(struct upgt_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
UPGT_LOCK(sc);
upgt_stop_locked(sc);
UPGT_UNLOCK(sc);
UPGT_ASSERT_LOCKED(sc);
if (sc->sc_flags & UPGT_FLAG_INITDONE)
upgt_set_macfilter(sc, IEEE80211_S_INIT);
upgt_abort_xfers_locked(sc);
/* device down */
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UPGT_FLAG_INITDONE;
}
@ -624,36 +555,18 @@ upgt_set_led_blink(void *arg)
}
static void
upgt_init(void *priv)
upgt_init(struct upgt_softc *sc)
{
struct upgt_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
UPGT_LOCK(sc);
upgt_init_locked(sc);
UPGT_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
upgt_init_locked(struct upgt_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
upgt_stop_locked(sc);
if (sc->sc_flags & UPGT_FLAG_INITDONE)
upgt_stop(sc);
usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]);
(void)upgt_set_macfilter(sc, IEEE80211_S_SCAN);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UPGT_FLAG_INITDONE;
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@ -662,14 +575,12 @@ upgt_init_locked(struct upgt_softc *sc)
static int
upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_filter *filter;
uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
UPGT_ASSERT_LOCKED(sc);
@ -709,10 +620,11 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
case IEEE80211_S_SCAN:
DPRINTF(sc, UPGT_DEBUG_STATE,
"set MAC filter to SCAN (bssid %s)\n",
ether_sprintf(broadcast));
ether_sprintf(ieee80211broadcastaddr));
filter->type = htole16(UPGT_FILTER_TYPE_NONE);
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
IEEE80211_ADDR_COPY(filter->src, broadcast);
IEEE80211_ADDR_COPY(filter->dst,
vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(filter->src, ieee80211broadcastaddr);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
@ -724,7 +636,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
/* XXX monitor mode isn't tested yet. */
if (vap->iv_opmode == IEEE80211_M_MONITOR) {
filter->type = htole16(UPGT_FILTER_TYPE_MONITOR);
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
IEEE80211_ADDR_COPY(filter->dst,
vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@ -736,7 +649,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
"set MAC filter to RUN (bssid %s)\n",
ether_sprintf(ni->ni_bssid));
filter->type = htole16(UPGT_FILTER_TYPE_STA);
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
IEEE80211_ADDR_COPY(filter->dst,
vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@ -765,8 +679,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
static void
upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct upgt_softc *sc = ifp->if_softc;
struct upgt_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
/*
@ -813,39 +726,48 @@ upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
static void
upgt_set_multi(void *arg)
{
struct upgt_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
if (!(ifp->if_flags & IFF_UP))
return;
/* XXX don't know how to set a device. Lack of docs. */
}
/*
* XXX don't know how to set a device. Lack of docs. Just try to set
* IFF_ALLMULTI flag here.
*/
ifp->if_flags |= IFF_ALLMULTI;
static int
upgt_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct upgt_softc *sc = ic->ic_softc;
int error;
UPGT_LOCK(sc);
if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0) {
UPGT_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
UPGT_UNLOCK(sc);
return (error);
}
upgt_start(sc);
UPGT_UNLOCK(sc);
return (0);
}
static void
upgt_start(struct ifnet *ifp)
upgt_start(struct upgt_softc *sc)
{
struct upgt_softc *sc = ifp->if_softc;
struct upgt_data *data_tx;
struct ieee80211_node *ni;
struct mbuf *m;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
UPGT_ASSERT_LOCKED(sc);
if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0)
return;
UPGT_LOCK(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
mbufq_prepend(&sc->sc_snd, m);
break;
}
@ -853,15 +775,15 @@ upgt_start(struct ifnet *ifp)
m->m_pkthdr.rcvif = NULL;
if (upgt_tx_start(sc, m, ni, data_tx) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
sc->sc_tx_timer = 5;
}
UPGT_UNLOCK(sc);
}
static int
@ -869,18 +791,18 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct upgt_softc *sc = ifp->if_softc;
struct upgt_softc *sc = ic->ic_softc;
struct upgt_data *data_tx = NULL;
UPGT_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & UPGT_FLAG_INITDONE)) {
m_freem(m);
ieee80211_free_node(ni);
UPGT_UNLOCK(sc);
return ENETDOWN;
}
UPGT_LOCK(sc);
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
ieee80211_free_node(ni);
@ -893,7 +815,6 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
UPGT_UNLOCK(sc);
return (EIO);
}
@ -907,13 +828,13 @@ static void
upgt_watchdog(void *arg)
{
struct upgt_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "watchdog timeout\n");
/* upgt_init(ifp); XXX needs a process context ? */
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
/* upgt_init(sc); XXX needs a process context ? */
counter_u64_add(ic->ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@ -950,7 +871,7 @@ upgt_scan_end(struct ieee80211com *ic)
static void
upgt_set_channel(struct ieee80211com *ic)
{
struct upgt_softc *sc = ic->ic_ifp->if_softc;
struct upgt_softc *sc = ic->ic_softc;
UPGT_LOCK(sc);
upgt_set_chan(sc, ic->ic_curchan);
@ -960,8 +881,7 @@ upgt_set_channel(struct ieee80211com *ic)
static void
upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_channel *chan;
@ -1044,7 +964,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -1059,7 +979,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@ -1069,7 +989,7 @@ upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct upgt_vap *uvp = UPGT_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct upgt_softc *sc = ic->ic_ifp->if_softc;
struct upgt_softc *sc = ic->ic_softc;
/* do it in a process context */
sc->sc_state = nstate;
@ -1125,6 +1045,7 @@ upgt_update_mcast(struct ieee80211com *ic)
static int
upgt_eeprom_parse(struct upgt_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct upgt_eeprom_header *eeprom_header;
struct upgt_eeprom_option *eeprom_option;
uint16_t option_len;
@ -1169,7 +1090,8 @@ upgt_eeprom_parse(struct upgt_softc *sc)
DPRINTF(sc, UPGT_DEBUG_FW,
"EEPROM mac len=%d\n", option_len);
IEEE80211_ADDR_COPY(sc->sc_myaddr, eeprom_option->data);
IEEE80211_ADDR_COPY(ic->ic_macaddr,
eeprom_option->data);
break;
case UPGT_EEPROM_TYPE_HWRX:
DPRINTF(sc, UPGT_DEBUG_FW,
@ -1518,8 +1440,7 @@ upgt_chksum_le(const uint32_t *buf, size_t size)
static struct mbuf *
upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct upgt_lmac_rx_desc *rxdesc;
struct mbuf *m;
@ -1527,7 +1448,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
if (!(sc->sc_flags & UPGT_FLAG_INITDONE))
return (NULL);
/* access RX packet descriptor */
@ -1545,7 +1466,6 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
memcpy(mtod(m, char *), rxdesc->data, pkglen);
/* trim FCS */
m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN;
m->m_pkthdr.rcvif = ifp;
if (ieee80211_radiotap_active(ic)) {
struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap;
@ -1554,7 +1474,6 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate);
tap->wr_antsignal = rxdesc->rssi;
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__);
*rssi = rxdesc->rssi;
@ -1564,8 +1483,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
static uint8_t
upgt_rx_rate(struct upgt_softc *sc, const int rate)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 };
static const uint8_t ofdm_upgt2rate[12] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
@ -1584,7 +1502,6 @@ upgt_rx_rate(struct upgt_softc *sc, const int rate)
static void
upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
{
struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_tx_done_desc *desc;
int i, freed = 0;
@ -1613,10 +1530,9 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
}
if (freed != 0) {
sc->sc_tx_timer = 0;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
UPGT_UNLOCK(sc);
upgt_start(ifp);
sc->sc_tx_timer = 0;
upgt_start(sc);
UPGT_LOCK(sc);
}
}
@ -2022,8 +1938,7 @@ static int
upgt_detach(device_t dev)
{
struct upgt_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@ -2039,9 +1954,9 @@ upgt_detach(device_t dev)
STAILQ_INIT(&sc->sc_rx_active);
STAILQ_INIT(&sc->sc_rx_inactive);
UPGT_UNLOCK(sc);
upgt_stop(sc);
UPGT_UNLOCK(sc);
callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
@ -2060,7 +1975,7 @@ upgt_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
ieee80211_ifdetach(ic);
if_free(ifp);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -2168,12 +2083,8 @@ upgt_getbuf(struct upgt_softc *sc)
UPGT_ASSERT_LOCKED(sc);
bf = _upgt_getbuf(sc);
if (bf == NULL) {
struct ifnet *ifp = sc->sc_ifp;
if (bf == NULL)
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: stop queue\n", __func__);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
}
return (bf);
}
@ -2191,14 +2102,10 @@ upgt_gettxbuf(struct upgt_softc *sc)
bf->addr = upgt_mem_alloc(sc);
if (bf->addr == 0) {
struct ifnet *ifp = sc->sc_ifp;
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: no free prism memory!\n",
__func__);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UPGT_STAT_INC(sc, st_tx_inactive);
if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (NULL);
}
return (bf);
@ -2212,7 +2119,6 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
int error = 0, len;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_mem *mem;
struct upgt_lmac_tx_desc *txdesc;
@ -2295,7 +2201,7 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
* will stall. It's strange, but it works, so we keep reading
* the statistics here. *shrug*
*/
if (!(ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS) %
if (!(vap->iv_ifp->if_get_counter(vap->iv_ifp, IFCOUNTER_OPACKETS) %
UPGT_TX_STAT_INTERVAL))
upgt_get_stats(sc);
@ -2306,8 +2212,7 @@ static void
upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@ -2355,10 +2260,8 @@ upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
(void) ieee80211_input_all(ic, m, rssi, nf);
m = NULL;
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
upgt_start(ifp);
UPGT_LOCK(sc);
upgt_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@ -2369,7 +2272,7 @@ upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@ -2380,7 +2283,6 @@ static void
upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct upgt_data *data;
UPGT_ASSERT_LOCKED(sc);
@ -2410,18 +2312,17 @@ upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
UPGT_UNLOCK(sc);
upgt_start(ifp);
UPGT_LOCK(sc);
upgt_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
if_inc_counter(data->ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);

View File

@ -418,8 +418,9 @@ struct upgt_vap {
#define UPGT_VAP(vap) ((struct upgt_vap *)(vap))
struct upgt_softc {
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct ifnet *sc_ifp;
struct usb_device *sc_udev;
void *sc_rx_dma_buf;
void *sc_tx_dma_buf;
@ -429,11 +430,8 @@ struct upgt_softc {
#define UPGT_FLAG_FWLOADED (1 << 0)
#define UPGT_FLAG_INITDONE (1 << 1)
#define UPGT_FLAG_DETACHED (1 << 2)
int sc_if_flags;
int sc_debug;
uint8_t sc_myaddr[IEEE80211_ADDR_LEN];
enum ieee80211_state sc_state;
int sc_arg;
int sc_led_blink;

View File

@ -149,8 +149,9 @@ static int ural_tx_mgt(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
static int ural_tx_data(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
static void ural_start(struct ifnet *);
static int ural_ioctl(struct ifnet *, u_long, caddr_t);
static int ural_transmit(struct ieee80211com *, struct mbuf *);
static void ural_start(struct ural_softc *);
static void ural_parent(struct ieee80211com *);
static void ural_set_testmode(struct ural_softc *);
static void ural_eeprom_read(struct ural_softc *, uint16_t, void *,
int);
@ -171,12 +172,12 @@ static void ural_set_chan(struct ural_softc *,
static void ural_disable_rf_tune(struct ural_softc *);
static void ural_enable_tsf_sync(struct ural_softc *);
static void ural_enable_tsf(struct ural_softc *);
static void ural_update_slot(struct ifnet *);
static void ural_update_slot(struct ural_softc *);
static void ural_set_txpreamble(struct ural_softc *);
static void ural_set_basicrates(struct ural_softc *,
const struct ieee80211_channel *);
static void ural_set_bssid(struct ural_softc *, const uint8_t *);
static void ural_set_macaddr(struct ural_softc *, uint8_t *);
static void ural_set_macaddr(struct ural_softc *, const uint8_t *);
static void ural_update_promisc(struct ieee80211com *);
static void ural_setpromisc(struct ural_softc *);
static const char *ural_get_rf(int);
@ -184,8 +185,7 @@ static void ural_read_eeprom(struct ural_softc *);
static int ural_bbp_init(struct ural_softc *);
static void ural_set_txantenna(struct ural_softc *, int);
static void ural_set_rxantenna(struct ural_softc *, int);
static void ural_init_locked(struct ural_softc *);
static void ural_init(void *);
static void ural_init(struct ural_softc *);
static void ural_stop(struct ural_softc *);
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@ -422,8 +422,7 @@ ural_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct ural_softc *sc = device_get_softc(self);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@ -433,6 +432,7 @@ ural_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RAL_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@ -455,24 +455,6 @@ ural_attach(device_t self)
device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
sc->asic_rev, ural_get_rf(sc->rf_rev));
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto detach;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = ural_init;
ifp->if_ioctl = ural_ioctl;
ifp->if_start = ural_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -497,13 +479,14 @@ ural_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_update_promisc = ural_update_promisc;
ic->ic_raw_xmit = ural_raw_xmit;
ic->ic_scan_start = ural_scan_start;
ic->ic_scan_end = ural_scan_end;
ic->ic_set_channel = ural_set_channel;
ic->ic_parent = ural_parent;
ic->ic_transmit = ural_transmit;
ic->ic_vap_create = ural_vap_create;
ic->ic_vap_delete = ural_vap_delete;
@ -527,8 +510,7 @@ static int
ural_detach(device_t self)
{
struct ural_softc *sc = device_get_softc(self);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
/* prevent further ioctls */
RAL_LOCK(sc);
@ -543,11 +525,9 @@ ural_detach(device_t self)
ural_unsetup_tx_list(sc);
RAL_UNLOCK(sc);
if (ifp) {
ic = ifp->if_l2com;
if (ic->ic_softc == sc)
ieee80211_ifdetach(ic);
if_free(ifp);
}
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -580,7 +560,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ural_softc *sc = ic->ic_ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
struct ural_vap *uvp;
struct ieee80211vap *vap;
@ -594,7 +574,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -610,7 +590,8 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@ -634,13 +615,8 @@ ural_tx_free(struct ural_tx_data *data, int txerr)
struct ural_softc *sc = data->sc;
if (data->m != NULL) {
if (data->m->m_flags & M_TXCB)
ieee80211_process_callback(data->ni, data->m,
txerr ? ETIMEDOUT : 0);
m_freem(data->m);
ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@ -697,7 +673,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ural_vap *uvp = URAL_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct ural_softc *sc = ic->ic_ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
struct ieee80211_node *ni;
struct mbuf *m;
@ -731,11 +707,11 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
ural_update_slot(ic->ic_ifp);
ural_update_slot(sc);
ural_set_txpreamble(sc);
ural_set_basicrates(sc, ic->ic_bsschan);
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
ural_set_bssid(sc, sc->sc_bssid);
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
ural_set_bssid(sc, ic->ic_macaddr);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@ -789,7 +765,6 @@ static void
ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct ural_tx_data *data;
struct mbuf *m;
@ -807,9 +782,6 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
ural_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@ -852,16 +824,13 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_transfer_submit(xfer);
}
RAL_UNLOCK(sc);
ural_start(ifp);
RAL_LOCK(sc);
ural_start(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
ural_tx_free(data, error);
@ -883,8 +852,7 @@ static void
ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@ -902,7 +870,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
@ -921,20 +889,19 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RAL_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
usbd_copy_out(pc, 0, mtod(m, uint8_t *), len);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@ -973,10 +940,8 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
} else
(void) ieee80211_input_all(ic, m, rssi, nf);
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
ural_start(ifp);
RAL_LOCK(sc);
ural_start(sc);
return;
default: /* Error */
@ -1016,8 +981,7 @@ static void
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
uint32_t flags, int len, int rate)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@ -1066,12 +1030,10 @@ ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = sc->sc_ifp;
const struct ieee80211_txparam *tp;
struct ural_tx_data *data;
if (sc->tx_nfree == 0) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
m_freem(m0);
ieee80211_free_node(ni);
return (EIO);
@ -1348,78 +1310,73 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
static void
ural_start(struct ifnet *ifp)
static int
ural_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct ural_softc *sc = ic->ic_softc;
int error;
RAL_LOCK(sc);
if (!sc->sc_running) {
RAL_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
RAL_UNLOCK(sc);
return (error);
}
ural_start(sc);
RAL_UNLOCK(sc);
return (0);
}
static void
ural_start(struct ural_softc *sc)
{
struct ural_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RAL_LOCK(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
RAL_UNLOCK(sc);
RAL_LOCK_ASSERT(sc, MA_OWNED);
if (sc->sc_running == 0)
return;
}
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (sc->tx_nfree < RAL_TX_MINFREE) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
while (sc->tx_nfree >= RAL_TX_MINFREE &&
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (ural_tx_data(sc, m, ni) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
RAL_UNLOCK(sc);
}
static int
ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
ural_parent(struct ieee80211com *ic)
{
struct ural_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error;
struct ural_softc *sc = ic->ic_softc;
int startall = 0;
RAL_LOCK(sc);
error = sc->sc_detached ? ENXIO : 0;
RAL_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
RAL_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
ural_init_locked(sc);
startall = 1;
} else
ural_setpromisc(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ural_stop(sc);
}
if (sc->sc_detached) {
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
default:
error = ether_ioctl(ifp, cmd, data);
break;
return;
}
return error;
if (ic->ic_nrunning > 0) {
if (sc->sc_running == 0) {
ural_init(sc);
startall = 1;
} else
ural_setpromisc(sc);
} else if (sc->sc_running)
ural_stop(sc);
RAL_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -1614,23 +1571,22 @@ ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
static void
ural_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ural_softc *sc = ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_write(sc, RAL_TXRX_CSR19, 0);
ural_set_bssid(sc, ifp->if_broadcastaddr);
ural_set_bssid(sc, ieee80211broadcastaddr);
RAL_UNLOCK(sc);
}
static void
ural_scan_end(struct ieee80211com *ic)
{
struct ural_softc *sc = ic->ic_ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_enable_tsf_sync(sc);
ural_set_bssid(sc, sc->sc_bssid);
ural_set_bssid(sc, ic->ic_macaddr);
RAL_UNLOCK(sc);
}
@ -1638,7 +1594,7 @@ ural_scan_end(struct ieee80211com *ic)
static void
ural_set_channel(struct ieee80211com *ic)
{
struct ural_softc *sc = ic->ic_ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_set_chan(sc, ic->ic_curchan);
@ -1648,8 +1604,7 @@ ural_set_channel(struct ieee80211com *ic)
static void
ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t power, tmp;
int i, chan;
@ -1780,8 +1735,7 @@ ural_disable_rf_tune(struct ural_softc *sc)
static void
ural_enable_tsf_sync(struct ural_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t logcwmin, preload, tmp;
@ -1817,10 +1771,9 @@ ural_enable_tsf(struct ural_softc *sc)
#define RAL_RXTX_TURNAROUND 5 /* us */
static void
ural_update_slot(struct ifnet *ifp)
ural_update_slot(struct ural_softc *sc)
{
struct ural_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t slottime, sifs, eifs;
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
@ -1845,8 +1798,7 @@ ural_update_slot(struct ifnet *ifp)
static void
ural_set_txpreamble(struct ural_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR10);
@ -1893,7 +1845,7 @@ ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
}
static void
ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
{
uint16_t tmp;
@ -1912,18 +1864,17 @@ ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
static void
ural_setpromisc(struct ural_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR2);
tmp &= ~RAL_DROP_NOT_TO_ME;
if (!(ifp->if_flags & IFF_PROMISC))
if (sc->sc_ic.ic_promisc == 0)
tmp |= RAL_DROP_NOT_TO_ME;
ural_write(sc, RAL_TXRX_CSR2, tmp);
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ?
"entering" : "leaving");
}
@ -1932,11 +1883,9 @@ ural_update_promisc(struct ieee80211com *ic)
{
struct ural_softc *sc = ic->ic_softc;
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
RAL_LOCK(sc);
ural_setpromisc(sc);
if (sc->sc_running)
ural_setpromisc(sc);
RAL_UNLOCK(sc);
}
@ -1958,6 +1907,7 @@ ural_get_rf(int rev)
static void
ural_read_eeprom(struct ural_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
@ -1970,7 +1920,7 @@ ural_read_eeprom(struct ural_softc *sc)
sc->nb_ant = val & 0x3;
/* read MAC address */
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
/* read default values for BBP registers */
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
@ -2064,11 +2014,11 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
}
static void
ural_init_locked(struct ural_softc *sc)
ural_init(struct ural_softc *sc)
{
#define N(a) ((int)(sizeof (a) / sizeof ((a)[0])))
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t tmp;
int i, ntries;
@ -2115,7 +2065,7 @@ ural_init_locked(struct ural_softc *sc)
ural_set_txantenna(sc, sc->tx_ant);
ural_set_rxantenna(sc, sc->rx_ant);
ural_set_macaddr(sc, IF_LLADDR(ifp));
ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/*
* Allocate Tx and Rx xfer queues.
@ -2128,13 +2078,12 @@ ural_init_locked(struct ural_softc *sc)
tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RAL_DROP_TODS;
if (!(ifp->if_flags & IFF_PROMISC))
if (ic->ic_promisc == 0)
tmp |= RAL_DROP_NOT_TO_ME;
}
ural_write(sc, RAL_TXRX_CSR2, tmp);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_running = 1;
usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
return;
@ -2143,29 +2092,13 @@ fail: ural_stop(sc);
#undef N
}
static void
ural_init(void *priv)
{
struct ural_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
RAL_LOCK(sc);
ural_init_locked(sc);
RAL_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
ural_stop(struct ural_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_running = 0;
/*
* Drain all the transfers, if not already drained:
@ -2193,27 +2126,23 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ural_softc *sc = ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!sc->sc_running) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RAL_TX_MINFREE) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@ -2232,7 +2161,6 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RAL_UNLOCK(sc);
return 0;
bad:
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RAL_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO; /* XXX */
@ -2266,8 +2194,7 @@ ural_ratectl_task(void *arg, int pending)
struct ural_vap *uvp = arg;
struct ieee80211vap *vap = &uvp->vap;
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ural_softc *sc = ifp->if_softc;
struct ural_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@ -2286,7 +2213,8 @@ ural_ratectl_task(void *arg, int pending)
ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
(void) ieee80211_ratectl_rate(ni, NULL, 0);
if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
/* count TX retry-fail as Tx errors */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
RAL_UNLOCK(sc);

View File

@ -89,7 +89,8 @@ enum {
};
struct ural_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@ -109,8 +110,8 @@ struct ural_softc {
uint16_t sta[11];
uint32_t rf_regs[4];
uint8_t txpow[14];
uint8_t sc_bssid[6];
uint8_t sc_detached;
u_int sc_detached:1,
sc_running:1;
struct {
uint8_t val;

View File

@ -651,11 +651,11 @@ static struct ieee80211vap *urtw_vap_create(struct ieee80211com *,
int, const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void urtw_vap_delete(struct ieee80211vap *);
static void urtw_init(void *);
static void urtw_stop(struct ifnet *);
static void urtw_stop_locked(struct ifnet *);
static int urtw_ioctl(struct ifnet *, u_long, caddr_t);
static void urtw_start(struct ifnet *);
static void urtw_init(struct urtw_softc *);
static void urtw_stop(struct urtw_softc *);
static void urtw_parent(struct ieee80211com *);
static int urtw_transmit(struct ieee80211com *, struct mbuf *);
static void urtw_start(struct urtw_softc *);
static int urtw_alloc_rx_data_list(struct urtw_softc *);
static int urtw_alloc_tx_data_list(struct urtw_softc *);
static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *,
@ -784,8 +784,7 @@ urtw_attach(device_t dev)
int ret = ENXIO;
struct urtw_softc *sc = device_get_softc(dev);
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */
uint16_t n_setup;
uint32_t data;
@ -807,6 +806,7 @@ urtw_attach(device_t dev)
TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc);
TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc);
callout_init(&sc->sc_watchdog_ch, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
if (sc->sc_flags & URTW_RTL8187B) {
setup_start = urtw_8187b_usbconfig;
@ -861,26 +861,6 @@ urtw_attach(device_t dev)
sc->sc_currate = 3;
sc->sc_preamble_mode = urtw_preamble_mode;
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not allocate ifnet\n");
ret = ENOMEM;
goto fail1;
}
ifp->if_softc = sc;
if_initname(ifp, "urtw", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = urtw_init;
ifp->if_ioctl = urtw_ioctl;
ifp->if_start = urtw_start;
/* XXX URTW_TX_DATA_LIST_COUNT */
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -901,7 +881,7 @@ urtw_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = urtw_raw_xmit;
ic->ic_scan_start = urtw_scan_start;
ic->ic_scan_end = urtw_scan_end;
@ -910,6 +890,8 @@ urtw_attach(device_t dev)
ic->ic_vap_create = urtw_vap_create;
ic->ic_vap_delete = urtw_vap_delete;
ic->ic_update_mcast = urtw_update_mcast;
ic->ic_parent = urtw_parent;
ic->ic_transmit = urtw_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -923,8 +905,9 @@ urtw_attach(device_t dev)
ieee80211_announce(ic);
return (0);
fail: URTW_UNLOCK(sc);
fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
fail:
URTW_UNLOCK(sc);
usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
fail0:
return (ret);
@ -934,18 +917,16 @@ static int
urtw_detach(device_t dev)
{
struct urtw_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
unsigned int n_xfers;
/* Prevent further ioctls */
URTW_LOCK(sc);
sc->sc_flags |= URTW_DETACHED;
urtw_stop(sc);
URTW_UNLOCK(sc);
urtw_stop(ifp);
ieee80211_draintask(ic, &sc->sc_updateslot_task);
ieee80211_draintask(ic, &sc->sc_led_task);
@ -979,7 +960,7 @@ urtw_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
ieee80211_ifdetach(ic);
if_free(ifp);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@ -1032,15 +1013,12 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (uvp == NULL)
return (NULL);
uvp = malloc(sizeof(struct urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -1052,7 +1030,7 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@ -1067,15 +1045,15 @@ urtw_vap_delete(struct ieee80211vap *vap)
}
static void
urtw_init_locked(void *arg)
urtw_init(struct urtw_softc *sc)
{
int ret;
struct urtw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
usb_error_t error;
int ret;
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
urtw_stop_locked(ifp);
URTW_ASSERT_LOCKED(sc);
if (sc->sc_flags & URTW_RUNNING)
urtw_stop(sc);
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
urtw_adapter_start(sc);
@ -1105,24 +1083,13 @@ urtw_init_locked(void *arg)
if (sc->sc_flags & URTW_RTL8187B)
usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= URTW_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
fail:
return;
}
static void
urtw_init(void *arg)
{
struct urtw_softc *sc = arg;
URTW_LOCK(sc);
urtw_init_locked(arg);
URTW_UNLOCK(sc);
}
static usb_error_t
urtw_adapter_start_b(struct urtw_softc *sc)
{
@ -1215,6 +1182,7 @@ urtw_adapter_start_b(struct urtw_softc *sc)
static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
usb_error_t error;
error = urtw_reset(sc);
@ -1234,8 +1202,8 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@ -1338,13 +1306,14 @@ urtw_do_request(struct urtw_softc *sc,
}
static void
urtw_stop_locked(struct ifnet *ifp)
urtw_stop(struct urtw_softc *sc)
{
struct urtw_softc *sc = ifp->if_softc;
uint8_t data8;
usb_error_t error;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
URTW_ASSERT_LOCKED(sc);
sc->sc_flags &= ~URTW_RUNNING;
error = urtw_intr_disable(sc);
if (error)
@ -1376,16 +1345,6 @@ urtw_stop_locked(struct ifnet *ifp)
urtw_abort_xfers(sc);
}
static void
urtw_stop(struct ifnet *ifp)
{
struct urtw_softc *sc = ifp->if_softc;
URTW_LOCK(sc);
urtw_stop_locked(ifp);
URTW_UNLOCK(sc);
}
static void
urtw_abort_xfers(struct urtw_softc *sc)
{
@ -1401,72 +1360,71 @@ urtw_abort_xfers(struct urtw_softc *sc)
usbd_transfer_stop(sc->sc_xfer[i]);
}
static int
urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
urtw_parent(struct ieee80211com *ic)
{
struct urtw_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error;
struct urtw_softc *sc = ic->ic_softc;
int startall = 0;
URTW_LOCK(sc);
error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
URTW_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if ((ifp->if_flags ^ sc->sc_if_flags) &
(IFF_ALLMULTI | IFF_PROMISC))
urtw_set_multi(sc);
} else {
urtw_init(ifp->if_softc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
urtw_stop(ifp);
}
sc->sc_if_flags = ifp->if_flags;
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
if (sc->sc_flags & URTW_DETACHED) {
URTW_UNLOCK(sc);
return;
}
return (error);
if (ic->ic_nrunning > 0) {
if (sc->sc_flags & URTW_RUNNING) {
if (ic->ic_promisc > 0 || ic->ic_allmulti > 0)
urtw_set_multi(sc);
} else {
urtw_init(sc);
startall = 1;
}
} else if (sc->sc_flags & URTW_RUNNING)
urtw_stop(sc);
URTW_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static int
urtw_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct urtw_softc *sc = ic->ic_softc;
int error;
URTW_LOCK(sc);
if ((sc->sc_flags & URTW_RUNNING) == 0) {
URTW_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
URTW_UNLOCK(sc);
return (error);
}
urtw_start(sc);
URTW_UNLOCK(sc);
return (0);
}
static void
urtw_start(struct ifnet *ifp)
urtw_start(struct urtw_softc *sc)
{
struct urtw_data *bf;
struct urtw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
URTW_ASSERT_LOCKED(sc);
if ((sc->sc_flags & URTW_RUNNING) == 0)
return;
URTW_LOCK(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = urtw_getbuf(sc);
if (bf == NULL) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
mbufq_prepend(&sc->sc_snd, m);
break;
}
@ -1474,7 +1432,8 @@ urtw_start(struct ifnet *ifp)
m->m_pkthdr.rcvif = NULL;
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
@ -1483,7 +1442,6 @@ urtw_start(struct ifnet *ifp)
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
}
URTW_UNLOCK(sc);
}
static int
@ -1565,12 +1523,11 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct urtw_softc *sc = ic->ic_softc;
struct urtw_data *bf;
struct urtw_softc *sc = ifp->if_softc;
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & URTW_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
@ -1584,10 +1541,8 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS); /* XXX */
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTW_UNLOCK(sc);
return (EIO);
@ -1615,8 +1570,7 @@ urtw_scan_end(struct ieee80211com *ic)
static void
urtw_set_channel(struct ieee80211com *ic)
{
struct urtw_softc *sc = ic->ic_ifp->if_softc;
struct ifnet *ifp = sc->sc_ifp;
struct urtw_softc *sc = ic->ic_softc;
uint32_t data, orig;
usb_error_t error;
@ -1626,7 +1580,7 @@ urtw_set_channel(struct ieee80211com *ic)
* initialization would be failed if setting a channel is called before
* the init have done.
*/
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
if (!(sc->sc_flags & URTW_RUNNING))
return;
if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan)
@ -1673,11 +1627,10 @@ static int
urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
struct urtw_data *data, int prior)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *);
struct ieee80211_key *k;
const struct ieee80211_txparam *tp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = {
sc->sc_xfer[URTW_8187B_BULK_TX_BE],
@ -1862,7 +1815,7 @@ static int
urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
struct urtw_softc *sc = ic->ic_ifp->if_softc;
struct urtw_softc *sc = ic->ic_softc;
struct urtw_vap *uvp = URTW_VAP(vap);
struct ieee80211_node *ni;
usb_error_t error = 0;
@ -1915,12 +1868,11 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@ -1930,17 +1882,7 @@ urtw_watchdog(void *arg)
static void
urtw_set_multi(void *arg)
{
struct urtw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
if (!(ifp->if_flags & IFF_UP))
return;
/*
* XXX don't know how to set a device. Lack of docs. Just try to set
* IFF_ALLMULTI flag here.
*/
ifp->if_flags |= IFF_ALLMULTI;
/* XXX don't know how to set a device. Lack of docs. */
}
static usb_error_t
@ -2002,8 +1944,7 @@ urtw_rtl2rate(uint32_t rate)
static usb_error_t
urtw_update_msr(struct urtw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t data;
usb_error_t error;
@ -2144,24 +2085,25 @@ urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
static usb_error_t
urtw_get_macaddr(struct urtw_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
usb_error_t error;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data);
if (error != 0)
goto fail;
sc->sc_bssid[0] = data & 0xff;
sc->sc_bssid[1] = (data & 0xff00) >> 8;
ic->ic_macaddr[0] = data & 0xff;
ic->ic_macaddr[1] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data);
if (error != 0)
goto fail;
sc->sc_bssid[2] = data & 0xff;
sc->sc_bssid[3] = (data & 0xff00) >> 8;
ic->ic_macaddr[2] = data & 0xff;
ic->ic_macaddr[3] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data);
if (error != 0)
goto fail;
sc->sc_bssid[4] = data & 0xff;
sc->sc_bssid[5] = (data & 0xff00) >> 8;
ic->ic_macaddr[4] = data & 0xff;
ic->ic_macaddr[5] = (data & 0xff00) >> 8;
fail:
return (error);
}
@ -3233,7 +3175,7 @@ urtw_8225_isv2(struct urtw_softc *sc, int *ret)
static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
struct ieee80211com *ic = &sc->sc_ic;
int i;
uint8_t data8;
usb_error_t error;
@ -3281,8 +3223,8 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@ -3293,7 +3235,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
/*
* MAC configuration
*/
for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg,
urtw_8225v2b_rf_part1[i].val);
urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50);
@ -3326,7 +3268,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff);
usb_pause_mtx(&sc->sc_mtx, 1100);
for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) {
for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) {
urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg,
urtw_8225v2b_rf_part0[i].val);
usb_pause_mtx(&sc->sc_mtx, 1);
@ -3372,7 +3314,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
}
urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c);
@ -3787,8 +3729,7 @@ static void
urtw_led_ch(void *arg)
{
struct urtw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
ieee80211_runtask(ic, &sc->sc_led_task);
}
@ -3935,8 +3876,7 @@ urtw_tx_enable(struct urtw_softc *sc)
static usb_error_t
urtw_rx_setconf(struct urtw_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
usb_error_t error;
@ -3961,7 +3901,7 @@ urtw_rx_setconf(struct urtw_softc *sc)
data = data | URTW_RX_FILTER_CRCERR;
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
data = data | URTW_RX_FILTER_ALLMAC;
} else {
data = data | URTW_RX_FILTER_NICMAC;
@ -3988,14 +3928,13 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct ieee80211_frame *wh;
struct mbuf *m, *mnew;
struct urtw_softc *sc = data->sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t noise = 0, rate;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
if (actlen < (int)URTW_MIN_RXBUFSZ) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@ -4006,7 +3945,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
@ -4020,7 +3959,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@ -4032,7 +3971,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@ -4041,7 +3980,6 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
data->buf = mtod(mnew, uint8_t *);
/* finalize mbuf */
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN;
if (ieee80211_radiotap_active(ic)) {
@ -4067,8 +4005,7 @@ static void
urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@ -4129,7 +4066,7 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@ -4143,7 +4080,7 @@ static void
urtw_txstatus_eof(struct usb_xfer *xfer)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
int actlen, type, pktretry, seq;
uint64_t val;
@ -4158,7 +4095,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer)
pktretry = val & 0xff;
seq = (val >> 16) & 0xff;
if (pktretry == URTW_TX_MAXRETRY)
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(ic->ic_oerrors, 1);
DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n",
pktretry, seq);
}
@ -4168,7 +4105,7 @@ static void
urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
URTW_ASSERT_LOCKED(sc);
@ -4186,7 +4123,7 @@ urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
default:
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@ -4197,38 +4134,22 @@ static void
urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
URTW_ASSERT_LOCKED(sc);
/*
* Do any tx complete callback. Note this must be done before releasing
* the node reference.
*/
if (data->m) {
m = data->m;
if (m->m_flags & M_TXCB) {
/* XXX status? */
ieee80211_process_callback(data->ni, m, 0);
}
m_freem(m);
/* XXX status? */
ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
}
if (data->ni) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_txtimer = 0;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct urtw_data *data;
URTW_ASSERT_LOCKED(sc);
@ -4256,18 +4177,17 @@ urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
URTW_UNLOCK(sc);
urtw_start(ifp);
URTW_LOCK(sc);
urtw_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
if_inc_counter(data->ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@ -4301,12 +4221,8 @@ urtw_getbuf(struct urtw_softc *sc)
URTW_ASSERT_LOCKED(sc);
bf = _urtw_getbuf(sc);
if (bf == NULL) {
struct ifnet *ifp = sc->sc_ifp;
if (bf == NULL)
DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
}
return (bf);
}
@ -4378,14 +4294,14 @@ static void
urtw_updateslottask(void *arg, int pending)
{
struct urtw_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
int error;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
URTW_LOCK(sc);
if ((sc->sc_flags & URTW_RUNNING) == 0) {
URTW_UNLOCK(sc);
return;
}
if (sc->sc_flags & URTW_RTL8187B) {
urtw_write8_m(sc, URTW_SIFS, 0x22);
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))

View File

@ -169,8 +169,8 @@ static device_detach_t urtwn_detach;
static usb_callback_t urtwn_bulk_tx_callback;
static usb_callback_t urtwn_bulk_rx_callback;
static usb_error_t urtwn_do_request(struct urtwn_softc *sc,
struct usb_device_request *req, void *data);
static usb_error_t urtwn_do_request(struct urtwn_softc *,
struct usb_device_request *, void *);
static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
const uint8_t [IEEE80211_ADDR_LEN],
@ -228,10 +228,9 @@ static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *);
static int urtwn_tx_start(struct urtwn_softc *,
struct ieee80211_node *, struct mbuf *,
struct urtwn_data *);
static void urtwn_start(struct ifnet *);
static void urtwn_start_locked(struct ifnet *,
struct urtwn_softc *);
static int urtwn_ioctl(struct ifnet *, u_long, caddr_t);
static int urtwn_transmit(struct ieee80211com *, struct mbuf *);
static void urtwn_start(struct urtwn_softc *);
static void urtwn_parent(struct ieee80211com *);
static int urtwn_r92c_power_on(struct urtwn_softc *);
static int urtwn_r88e_power_on(struct urtwn_softc *);
static int urtwn_llt_init(struct urtwn_softc *);
@ -269,10 +268,8 @@ static void urtwn_set_chan(struct urtwn_softc *,
static void urtwn_update_mcast(struct ieee80211com *);
static void urtwn_iq_calib(struct urtwn_softc *);
static void urtwn_lc_calib(struct urtwn_softc *);
static void urtwn_init(void *);
static void urtwn_init_locked(void *);
static void urtwn_stop(struct ifnet *);
static void urtwn_stop_locked(struct ifnet *);
static void urtwn_init(struct urtwn_softc *);
static void urtwn_stop(struct urtwn_softc *);
static void urtwn_abort_xfers(struct urtwn_softc *);
static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@ -368,8 +365,7 @@ urtwn_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct urtwn_softc *sc = device_get_softc(self);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@ -382,6 +378,7 @@ urtwn_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
callout_init(&sc->sc_watchdog_ch, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = URTWN_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
@ -424,24 +421,6 @@ urtwn_attach(device_t self)
URTWN_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto detach;
}
ic = ifp->if_l2com;
ifp->if_softc = sc;
if_initname(ifp, "urtwn", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = urtwn_init;
ifp->if_ioctl = urtwn_ioctl;
ifp->if_start = urtwn_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -462,12 +441,13 @@ urtwn_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = urtwn_raw_xmit;
ic->ic_scan_start = urtwn_scan_start;
ic->ic_scan_end = urtwn_scan_end;
ic->ic_set_channel = urtwn_set_channel;
ic->ic_transmit = urtwn_transmit;
ic->ic_parent = urtwn_parent;
ic->ic_vap_create = urtwn_vap_create;
ic->ic_vap_delete = urtwn_vap_delete;
ic->ic_update_mcast = urtwn_update_mcast;
@ -491,17 +471,15 @@ static int
urtwn_detach(device_t self)
{
struct urtwn_softc *sc = device_get_softc(self);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/* Prevent further ioctls. */
URTWN_LOCK(sc);
sc->sc_flags |= URTWN_DETACHED;
urtwn_stop(sc);
URTWN_UNLOCK(sc);
urtwn_stop(ifp);
callout_drain(&sc->sc_watchdog_ch);
/* Prevent further allocations from RX/TX data lists. */
@ -527,8 +505,7 @@ urtwn_detach(device_t self)
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
ieee80211_ifdetach(ic);
if_free(ifp);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -599,15 +576,12 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
uvp = (struct urtwn_vap *) malloc(sizeof(struct urtwn_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (uvp == NULL)
return (NULL);
uvp = malloc(sizeof(struct urtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@ -619,7 +593,7 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@ -636,8 +610,7 @@ urtwn_vap_delete(struct ieee80211vap *vap)
static struct mbuf *
urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct mbuf *m;
struct r92c_rx_stat *stat;
@ -650,7 +623,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
if (!(sc->sc_flags & URTWN_RUNNING))
return (NULL);
stat = (struct r92c_rx_stat *)buf;
@ -662,11 +635,11 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* This should not happen since we setup our Rx filter
* to not receive these frames.
*/
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@ -695,7 +668,6 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
}
/* Finalize mbuf. */
m->m_pkthdr.rcvif = ifp;
wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
memcpy(mtod(m, uint8_t *), wh, pktlen);
m->m_pkthdr.len = m->m_len = pktlen;
@ -741,7 +713,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
int8_t *nf)
{
struct urtwn_softc *sc = data->sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct r92c_rx_stat *stat;
struct mbuf *m, *m0 = NULL, *prevm = NULL;
uint32_t rxdw0;
@ -751,7 +723,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
if (len < sizeof(*stat)) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@ -802,8 +774,7 @@ static void
urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL, *next;
@ -866,7 +837,7 @@ urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
break;
@ -877,38 +848,19 @@ static void
urtwn_txeof(struct usb_xfer *xfer, struct urtwn_data *data)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
URTWN_ASSERT_LOCKED(sc);
/*
* Do any tx complete callback. Note this must be done before releasing
* the node reference.
*/
if (data->m) {
m = data->m;
if (m->m_flags & M_TXCB) {
/* XXX status? */
ieee80211_process_callback(data->ni, m, 0);
}
m_freem(m);
data->m = NULL;
}
if (data->ni) {
ieee80211_free_node(data->ni);
data->ni = NULL;
}
/* XXX status? */
ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
data->m = NULL;
sc->sc_txtimer = 0;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct urtwn_data *data;
URTWN_ASSERT_LOCKED(sc);
@ -933,16 +885,17 @@ urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
urtwn_start_locked(ifp, sc);
urtwn_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto tr_setup;
if (data->ni != NULL) {
if_inc_counter(data->ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@ -975,11 +928,8 @@ urtwn_getbuf(struct urtwn_softc *sc)
URTWN_ASSERT_LOCKED(sc);
bf = _urtwn_getbuf(sc);
if (bf == NULL) {
struct ifnet *ifp = sc->sc_ifp;
if (bf == NULL)
DPRINTF("%s: stop queue\n", __func__);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
}
return (bf);
}
@ -1302,7 +1252,7 @@ urtwn_read_rom(struct urtwn_softc *sc)
sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
DPRINTF("regulatory type=%d\n", sc->regulatory);
IEEE80211_ADDR_COPY(sc->sc_bssid, rom->macaddr);
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
sc->sc_rf_write = urtwn_r92c_rf_write;
sc->sc_power_on = urtwn_r92c_power_on;
@ -1363,7 +1313,7 @@ urtwn_r88e_read_rom(struct urtwn_softc *sc)
if (sc->ofdm_tx_pwr_diff & 0x08)
sc->ofdm_tx_pwr_diff |= 0xf0;
sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->r88e_rom[0xd7]);
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
sc->sc_rf_write = urtwn_r88e_rf_write;
sc->sc_power_on = urtwn_r88e_power_on;
@ -1378,7 +1328,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
{
static const uint8_t map[] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct ieee80211_rateset *rs;
@ -1455,8 +1405,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
void
urtwn_tsf_sync_enable(struct urtwn_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@ -1513,7 +1462,7 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct urtwn_vap *uvp = URTWN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct urtwn_softc *sc = ic->ic_ifp->if_softc;
struct urtwn_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
enum ieee80211_state ostate;
uint32_t reg;
@ -1669,12 +1618,11 @@ static void
urtwn_watchdog(void *arg)
{
struct urtwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
@ -1800,10 +1748,9 @@ static int
urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct urtwn_data *data)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *xfer;
struct r92c_tx_desc *txd;
@ -1942,89 +1889,78 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
return (0);
}
static void
urtwn_start(struct ifnet *ifp)
static int
urtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct urtwn_softc *sc = ifp->if_softc;
struct urtwn_softc *sc = ic->ic_softc;
int error;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
URTWN_LOCK(sc);
urtwn_start_locked(ifp, sc);
if ((sc->sc_flags & URTWN_RUNNING) == 0) {
URTWN_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
URTWN_UNLOCK(sc);
return (error);
}
urtwn_start(sc);
URTWN_UNLOCK(sc);
return (0);
}
static void
urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc)
urtwn_start(struct urtwn_softc *sc)
{
struct ieee80211_node *ni;
struct mbuf *m;
struct urtwn_data *bf;
URTWN_ASSERT_LOCKED(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = urtwn_getbuf(sc);
if (bf == NULL) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
}
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
}
}
static int
urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
urtwn_parent(struct ieee80211com *ic)
{
struct urtwn_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct urtwn_softc *sc = ic->ic_softc;
int startall = 0;
URTWN_LOCK(sc);
error = (sc->sc_flags & URTWN_DETACHED) ? ENXIO : 0;
URTWN_UNLOCK(sc);
if (error != 0)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
urtwn_init(ifp->if_softc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
urtwn_stop(ifp);
}
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
if (sc->sc_flags & URTWN_DETACHED) {
URTWN_UNLOCK(sc);
return;
}
return (error);
if (ic->ic_nrunning > 0) {
if ((sc->sc_flags & URTWN_RUNNING) == 0) {
urtwn_init(sc);
startall = 1;
}
} else if (sc->sc_flags & URTWN_RUNNING)
urtwn_stop(sc);
URTWN_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static int
@ -2938,7 +2874,7 @@ urtwn_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct r92c_rom *rom = &sc->rom;
uint16_t cckpow, ofdmpow, htpow, diff, max;
const struct urtwn_txpwr *base;
@ -3037,7 +2973,7 @@ urtwn_r88e_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint16_t cckpow, ofdmpow, bw20pow, htpow;
const struct urtwn_r88e_txpwr *base;
int ridx, chan, group;
@ -3134,7 +3070,7 @@ urtwn_scan_end(struct ieee80211com *ic)
static void
urtwn_set_channel(struct ieee80211com *ic)
{
struct urtwn_softc *sc = ic->ic_ifp->if_softc;
struct urtwn_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
URTWN_LOCK(sc);
@ -3156,7 +3092,7 @@ static void
urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c,
struct ieee80211_channel *extc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t reg;
u_int chan;
int i;
@ -3287,17 +3223,18 @@ urtwn_lc_calib(struct urtwn_softc *sc)
}
static void
urtwn_init_locked(void *arg)
urtwn_init(struct urtwn_softc *sc)
{
struct urtwn_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint8_t macaddr[IEEE80211_ADDR_LEN];
uint32_t reg;
int error;
URTWN_ASSERT_LOCKED(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
urtwn_stop_locked(ifp);
if (sc->sc_flags & URTWN_RUNNING)
urtwn_stop(sc);
/* Init firmware commands ring. */
sc->fwcur = 0;
@ -3340,8 +3277,8 @@ urtwn_init_locked(void *arg)
}
/* Set MAC address. */
urtwn_write_region_1(sc, R92C_MACID, IF_LLADDR(ifp),
IEEE80211_ADDR_LEN);
IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN);
/* Set initial network type. */
reg = urtwn_read_4(sc, R92C_CR);
@ -3465,8 +3402,7 @@ urtwn_init_locked(void *arg)
usbd_transfer_start(sc->sc_xfer[URTWN_BULK_RX]);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= URTWN_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
fail:
@ -3474,38 +3410,15 @@ urtwn_init_locked(void *arg)
}
static void
urtwn_init(void *arg)
urtwn_stop(struct urtwn_softc *sc)
{
struct urtwn_softc *sc = arg;
URTWN_LOCK(sc);
urtwn_init_locked(arg);
URTWN_UNLOCK(sc);
}
static void
urtwn_stop_locked(struct ifnet *ifp)
{
struct urtwn_softc *sc = ifp->if_softc;
URTWN_ASSERT_LOCKED(sc);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~URTWN_RUNNING;
callout_stop(&sc->sc_watchdog_ch);
urtwn_abort_xfers(sc);
}
static void
urtwn_stop(struct ifnet *ifp)
{
struct urtwn_softc *sc = ifp->if_softc;
URTWN_LOCK(sc);
urtwn_stop_locked(ifp);
URTWN_UNLOCK(sc);
}
static void
urtwn_abort_xfers(struct urtwn_softc *sc)
{
@ -3523,12 +3436,11 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct urtwn_softc *sc = ifp->if_softc;
struct urtwn_softc *sc = ic->ic_softc;
struct urtwn_data *bf;
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & URTWN_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@ -3542,10 +3454,8 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS);
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTWN_UNLOCK(sc);
return (EIO);

View File

@ -1172,7 +1172,8 @@ enum {
#define URTWN_EP_QUEUES URTWN_BULK_RX
struct urtwn_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@ -1180,6 +1181,7 @@ struct urtwn_softc {
u_int sc_flags;
#define URTWN_FLAG_CCK_HIPWR 0x01
#define URTWN_DETACHED 0x02
#define URTWN_RUNNING 0x04
u_int chip;
#define URTWN_CHIP_92C 0x01
@ -1224,7 +1226,6 @@ struct urtwn_softc {
uint8_t ht40_tx_pwr[5];
int8_t bw20_tx_pwr_diff;
int8_t ofdm_tx_pwr_diff;
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct callout sc_watchdog_ch;
struct mtx sc_mtx;

View File

@ -93,14 +93,14 @@ struct urtw_vap {
#define URTW_VAP(vap) ((struct urtw_vap *)(vap))
struct urtw_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
void *sc_tx_dma_buf;
int sc_debug;
int sc_if_flags;
int sc_flags;
#define URTW_INIT_ONCE (1 << 1)
#define URTW_RTL8187B (1 << 2)
@ -108,13 +108,13 @@ struct urtw_softc {
#define URTW_RTL8187B_REV_D (1 << 4)
#define URTW_RTL8187B_REV_E (1 << 5)
#define URTW_DETACHED (1 << 6)
#define URTW_RUNNING (1 << 7)
enum ieee80211_state sc_state;
int sc_epromtype;
#define URTW_EEPROM_93C46 0
#define URTW_EEPROM_93C56 1
uint8_t sc_crcmon;
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct ieee80211_channel *sc_curchan;

View File

@ -154,12 +154,12 @@ static int zyd_set_beacon_interval(struct zyd_softc *, int);
static void zyd_rx_data(struct usb_xfer *, int, uint16_t);
static int zyd_tx_start(struct zyd_softc *, struct mbuf *,
struct ieee80211_node *);
static void zyd_start(struct ifnet *);
static int zyd_transmit(struct ieee80211com *, struct mbuf *);
static void zyd_start(struct zyd_softc *);
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
static void zyd_parent(struct ieee80211com *);
static void zyd_init_locked(struct zyd_softc *);
static void zyd_init(void *);
static void zyd_stop(struct zyd_softc *);
static int zyd_loadfirmware(struct zyd_softc *);
static void zyd_scan_start(struct ieee80211com *);
@ -333,8 +333,7 @@ zyd_attach(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct zyd_softc *sc = device_get_softc(dev);
struct ifnet *ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@ -353,6 +352,7 @@ zyd_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
STAILQ_INIT(&sc->sc_rqh);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = ZYD_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@ -372,22 +372,6 @@ zyd_attach(device_t dev)
}
ZYD_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
goto detach;
}
ifp->if_softc = sc;
if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = zyd_init;
ifp->if_ioctl = zyd_ioctl;
ifp->if_start = zyd_start;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
IFQ_SET_READY(&ifp->if_snd);
ic = ifp->if_l2com;
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -408,16 +392,17 @@ zyd_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
ieee80211_ifattach(ic, sc->sc_bssid);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = zyd_raw_xmit;
ic->ic_scan_start = zyd_scan_start;
ic->ic_scan_end = zyd_scan_end;
ic->ic_set_channel = zyd_set_channel;
ic->ic_vap_create = zyd_vap_create;
ic->ic_vap_delete = zyd_vap_delete;
ic->ic_update_mcast = zyd_update_mcast;
ic->ic_update_promisc = zyd_update_mcast;
ic->ic_parent = zyd_parent;
ic->ic_transmit = zyd_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@ -439,8 +424,7 @@ static int
zyd_detach(device_t dev)
{
struct zyd_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@ -465,11 +449,9 @@ zyd_detach(device_t dev)
/* free USB transfers and some data buffers */
usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
if (ifp) {
ic = ifp->if_l2com;
if (ic->ic_softc == sc)
ieee80211_ifdetach(ic);
if_free(ifp);
}
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@ -486,15 +468,12 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (zvp == NULL)
return (NULL);
zvp = malloc(sizeof(struct zyd_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &zvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(zvp, M_80211_VAP);
return (NULL);
@ -509,7 +488,7 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
ieee80211_media_status);
ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@ -530,13 +509,8 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr)
struct zyd_softc *sc = data->sc;
if (data->m != NULL) {
if (data->m->m_flags & M_TXCB)
ieee80211_process_callback(data->ni, data->m,
txerr ? ETIMEDOUT : 0);
m_freem(data->m);
ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@ -593,7 +567,7 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct zyd_vap *zvp = ZYD_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
struct zyd_softc *sc = ic->ic_ifp->if_softc;
struct zyd_softc *sc = ic->ic_softc;
int error;
DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
@ -618,8 +592,8 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* make data LED blink upon Tx */
zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid);
zyd_set_bssid(sc, sc->sc_bssid);
IEEE80211_ADDR_COPY(ic->ic_macaddr, vap->iv_bss->ni_bssid);
zyd_set_bssid(sc, ic->ic_macaddr);
break;
default:
break;
@ -637,8 +611,7 @@ static void
zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct zyd_cmd *cmd = &sc->sc_ibuf;
@ -681,7 +654,9 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
ieee80211_free_node(ni);
}
if (le16toh(retry->count) & 0x100)
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */
/* too many retries */
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
1);
break;
}
case ZYD_NOTIF_IORD:
@ -1243,8 +1218,7 @@ zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c)
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
int error = 0, i;
struct zyd_softc *sc = rf->rf_sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
int chan = ieee80211_chan2ieee(ic, c);
@ -1932,7 +1906,7 @@ zyd_get_macaddr(struct zyd_softc *sc)
USETW(req.wIndex, 0);
USETW(req.wLength, IEEE80211_ADDR_LEN);
error = zyd_do_request(sc, &req, sc->sc_bssid);
error = zyd_do_request(sc, &req, sc->sc_ic.ic_macaddr);
if (error != 0) {
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
usbd_errstr(error));
@ -2004,36 +1978,41 @@ zyd_set_led(struct zyd_softc *sc, int which, int on)
static void
zyd_set_multi(struct zyd_softc *sc)
{
int error;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ifmultiaddr *ifma;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t low, high;
uint8_t v;
int error;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0)
return;
low = 0x00000000;
high = 0x80000000;
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
ic->ic_promisc > 0) {
low = 0xffffffff;
high = 0xffffffff;
} else {
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
ifma->ifma_addr))[5] >> 2;
if (v < 32)
low |= 1 << v;
else
high |= 1 << (v - 32);
struct ieee80211vap *vap;
struct ifnet *ifp;
struct ifmultiaddr *ifma;
uint8_t v;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
ifp = vap->iv_ifp;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
ifma->ifma_addr))[5] >> 2;
if (v < 32)
low |= 1 << v;
else
high |= 1 << (v - 32);
}
if_maddr_runlock(ifp);
}
if_maddr_runlock(ifp);
}
/* reprogram multicast global hash table */
@ -2050,9 +2029,6 @@ zyd_update_mcast(struct ieee80211com *ic)
{
struct zyd_softc *sc = ic->ic_softc;
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
ZYD_LOCK(sc);
zyd_set_multi(sc);
ZYD_UNLOCK(sc);
@ -2061,8 +2037,7 @@ zyd_update_mcast(struct ieee80211com *ic)
static int
zyd_set_rxfilter(struct zyd_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
uint32_t rxfilter;
switch (ic->ic_opmode) {
@ -2087,8 +2062,7 @@ static void
zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
{
int error;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct zyd_rf *rf = &sc->sc_rf;
uint32_t tmp;
int chan;
@ -2179,8 +2153,7 @@ static void
zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct zyd_plcphdr plcp;
struct zyd_rx_stat stat;
struct usb_page_cache *pc;
@ -2190,7 +2163,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (len < ZYD_MIN_FRAGSZ) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n",
device_get_nameunit(sc->sc_dev), len);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
pc = usbd_xfer_get_frame(xfer, 0);
@ -2201,7 +2174,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
DPRINTF(sc, ZYD_DEBUG_RECV,
"%s: RX status indicated error (%x)\n",
device_get_nameunit(sc->sc_dev), stat.flags);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
@ -2213,7 +2186,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (rlen > (int)MCLBYTES) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n",
device_get_nameunit(sc->sc_dev), rlen);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
} else if (rlen > (int)MHLEN)
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
@ -2222,10 +2195,9 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (m == NULL) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n",
device_get_nameunit(sc->sc_dev));
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
return;
}
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = rlen;
usbd_copy_out(pc, offset + sizeof(plcp), mtod(m, uint8_t *), rlen);
@ -2255,8 +2227,7 @@ static void
zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct zyd_rx_desc desc;
struct mbuf *m;
@ -2328,10 +2299,8 @@ zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
} else
(void)ieee80211_input_all(ic, m, rssi, nf);
}
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_IS_EMPTY(&ifp->if_snd))
zyd_start(ifp);
ZYD_LOCK(sc);
zyd_start(sc);
break;
default: /* Error */
@ -2386,7 +2355,6 @@ static void
zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct zyd_tx_data *data;
struct mbuf *m;
@ -2405,9 +2373,6 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
zyd_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@ -2440,16 +2405,14 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_xfer_set_priv(xfer, data);
usbd_transfer_submit(xfer);
}
ZYD_UNLOCK(sc);
zyd_start(ifp);
ZYD_LOCK(sc);
zyd_start(sc);
break;
default: /* Error */
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n",
usbd_errstr(error));
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
data = usbd_xfer_get_priv(xfer);
usbd_xfer_set_priv(xfer, NULL);
if (data != NULL)
@ -2590,31 +2553,45 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return (0);
}
static void
zyd_start(struct ifnet *ifp)
static int
zyd_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct zyd_softc *sc = ic->ic_softc;
int error;
ZYD_LOCK(sc);
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
ZYD_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
ZYD_UNLOCK(sc);
return (error);
}
zyd_start(sc);
ZYD_UNLOCK(sc);
return (0);
}
static void
zyd_start(struct zyd_softc *sc)
{
struct zyd_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
ZYD_LOCK(sc);
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (sc->tx_nfree == 0) {
IFQ_DRV_PREPEND(&ifp->if_snd, m);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
ZYD_LOCK_ASSERT(sc, MA_LOCKED);
while (sc->tx_nfree > 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (zyd_tx_start(sc, m, ni) != 0) {
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
break;
}
}
ZYD_UNLOCK(sc);
}
static int
@ -2622,19 +2599,17 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct zyd_softc *sc = ifp->if_softc;
struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
if (!(sc->sc_flags & ZYD_FLAG_RUNNING)) {
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
}
if (sc->tx_nfree == 0) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
@ -2648,7 +2623,6 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
*/
if (zyd_tx_start(sc, m, ni) != 0) {
ZYD_UNLOCK(sc);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
return (EIO);
}
@ -2656,56 +2630,35 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (0);
}
static int
zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
zyd_parent(struct ieee80211com *ic)
{
struct zyd_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error;
struct zyd_softc *sc = ic->ic_softc;
int startall = 0;
ZYD_LOCK(sc);
error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
ZYD_UNLOCK(sc);
if (error)
return (error);
switch (cmd) {
case SIOCSIFFLAGS:
ZYD_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
zyd_init_locked(sc);
startall = 1;
} else
zyd_set_multi(sc);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
zyd_stop(sc);
}
if (sc->sc_flags & ZYD_FLAG_DETACHED) {
ZYD_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
return;
}
return (error);
if (ic->ic_nrunning > 0) {
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
zyd_init_locked(sc);
startall = 1;
} else
zyd_set_multi(sc);
} else if (sc->sc_flags & ZYD_FLAG_RUNNING)
zyd_stop(sc);
ZYD_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
zyd_init_locked(struct zyd_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct usb_config_descriptor *cd;
int error;
uint32_t val;
@ -2757,12 +2710,12 @@ zyd_init_locked(struct zyd_softc *sc)
sc->sc_flags |= ZYD_FLAG_INITONCE;
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (sc->sc_flags & ZYD_FLAG_RUNNING)
zyd_stop(sc);
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
IF_LLADDR(ifp), ":");
error = zyd_set_macaddr(sc, IF_LLADDR(ifp));
vap ? vap->iv_myaddr : ic->ic_macaddr, ":");
error = zyd_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
if (error != 0)
return;
@ -2798,8 +2751,7 @@ zyd_init_locked(struct zyd_softc *sc)
/* enable interrupts */
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= ZYD_FLAG_RUNNING;
usbd_xfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[ZYD_BULK_RD]);
usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]);
@ -2810,30 +2762,14 @@ fail: zyd_stop(sc);
return;
}
static void
zyd_init(void *priv)
{
struct zyd_softc *sc = priv;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
ZYD_LOCK(sc);
zyd_init_locked(sc);
ZYD_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
zyd_stop(struct zyd_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int error;
ZYD_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~ZYD_FLAG_RUNNING;
/*
* Drain all the transfers, if not already drained:
@ -2925,30 +2861,29 @@ zyd_loadfirmware(struct zyd_softc *sc)
static void
zyd_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct zyd_softc *sc = ifp->if_softc;
struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* want broadcast address while scanning */
zyd_set_bssid(sc, ifp->if_broadcastaddr);
zyd_set_bssid(sc, ieee80211broadcastaddr);
ZYD_UNLOCK(sc);
}
static void
zyd_scan_end(struct ieee80211com *ic)
{
struct zyd_softc *sc = ic->ic_ifp->if_softc;
struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* restore previous bssid */
zyd_set_bssid(sc, sc->sc_bssid);
zyd_set_bssid(sc, ic->ic_macaddr);
ZYD_UNLOCK(sc);
}
static void
zyd_set_channel(struct ieee80211com *ic)
{
struct zyd_softc *sc = ic->ic_ifp->if_softc;
struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
zyd_set_chan(sc, ic->ic_curchan);

View File

@ -1249,7 +1249,8 @@ enum {
};
struct zyd_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@ -1260,13 +1261,13 @@ struct zyd_softc {
#define ZYD_FLAG_INITONCE (1 << 1)
#define ZYD_FLAG_INITDONE (1 << 2)
#define ZYD_FLAG_DETACHED (1 << 3)
#define ZYD_FLAG_RUNNING (1 << 4)
struct zyd_rf sc_rf;
STAILQ_HEAD(, zyd_rq) sc_rtx;
STAILQ_HEAD(, zyd_rq) sc_rqh;
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
uint16_t sc_fwbase;
uint8_t sc_regdomain;
uint8_t sc_macrev;

View File

@ -116,11 +116,9 @@ static struct ieee80211vap *wi_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void wi_vap_delete(struct ieee80211vap *vap);
static void wi_stop_locked(struct wi_softc *sc, int disable);
static void wi_start_locked(struct ifnet *);
static void wi_start(struct ifnet *);
static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
struct mbuf *m0);
static int wi_transmit(struct ieee80211com *, struct mbuf *);
static void wi_start(struct wi_softc *);
static int wi_start_tx(struct wi_softc *, struct wi_frame *, struct mbuf *);
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
@ -131,10 +129,8 @@ static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int rssi, int nf);
static int wi_reset(struct wi_softc *);
static void wi_watchdog(void *);
static int wi_ioctl(struct ifnet *, u_long, caddr_t);
static void wi_parent(struct ieee80211com *);
static void wi_media_status(struct ifnet *, struct ifmediareq *);
static uint64_t wi_get_counter(struct ifnet *, ift_counter);
static void wi_rx_intr(struct wi_softc *);
static void wi_tx_intr(struct wi_softc *);
static void wi_tx_ex_intr(struct wi_softc *);
@ -153,10 +149,10 @@ static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
static int wi_cmd(struct wi_softc *, int, int, int, int);
static int wi_seek_bap(struct wi_softc *, int, int);
static int wi_read_bap(struct wi_softc *, int, int, void *, int);
static int wi_write_bap(struct wi_softc *, int, int, void *, int);
static int wi_write_bap(struct wi_softc *, int, int, const void *, int);
static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
static int wi_read_rid(struct wi_softc *, int, void *, int *);
static int wi_write_rid(struct wi_softc *, int, void *, int);
static int wi_write_rid(struct wi_softc *, int, const void *, int);
static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *);
static void wi_scan_start(struct ieee80211com *);
@ -237,8 +233,7 @@ int
wi_attach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
struct ieee80211com *ic;
struct ifnet *ifp;
struct ieee80211com *ic = &sc->sc_ic;
int i, nrates, buflen;
u_int16_t val;
u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
@ -249,15 +244,6 @@ wi_attach(device_t dev)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int error;
uint8_t macaddr[IEEE80211_ADDR_LEN];
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc\n");
wi_free(dev);
return ENOSPC;
}
ic = ifp->if_l2com;
sc->sc_firmware_type = WI_NOTYPE;
sc->wi_cmd_count = 500;
@ -309,6 +295,7 @@ wi_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
/*
* Read the station address.
@ -317,12 +304,13 @@ wi_attach(device_t dev)
* the probe to fail.
*/
buflen = IEEE80211_ADDR_LEN;
error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen);
if (error != 0) {
buflen = IEEE80211_ADDR_LEN;
error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr,
&buflen);
}
if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) {
if (error != 0)
device_printf(dev, "mac read failed %d\n", error);
else {
@ -333,18 +321,6 @@ wi_attach(device_t dev)
return (error);
}
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = wi_ioctl;
ifp->if_start = wi_start;
ifp->if_init = wi_init;
ifp->if_get_counter = wi_get_counter;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_DS;
@ -458,16 +434,17 @@ wi_attach(device_t dev)
sc->sc_portnum = WI_DEFAULT_PORT;
ieee80211_ifattach(ic, macaddr);
ieee80211_ifattach(ic);
ic->ic_raw_xmit = wi_raw_xmit;
ic->ic_scan_start = wi_scan_start;
ic->ic_scan_end = wi_scan_end;
ic->ic_set_channel = wi_set_channel;
ic->ic_vap_create = wi_vap_create;
ic->ic_vap_delete = wi_vap_delete;
ic->ic_update_mcast = wi_update_mcast;
ic->ic_update_promisc = wi_update_promisc;
ic->ic_transmit = wi_transmit;
ic->ic_parent = wi_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
@ -483,7 +460,6 @@ wi_attach(device_t dev)
if (error) {
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
ieee80211_ifdetach(ic);
if_free(sc->sc_ifp);
wi_free(dev);
return error;
}
@ -495,21 +471,20 @@ int
wi_detach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
WI_LOCK(sc);
/* check if device was removed */
sc->wi_gone |= !bus_child_present(dev);
wi_stop_locked(sc, 0);
wi_stop(sc, 0);
WI_UNLOCK(sc);
ieee80211_ifdetach(ic);
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
if_free(sc->sc_ifp);
wi_free(dev);
mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@ -520,19 +495,16 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct wi_softc *sc = ic->ic_ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
struct wi_vap *wvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
M_80211_VAP, M_NOWAIT | M_ZERO);
if (wvp == NULL)
return NULL;
wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &wvp->wv_vap;
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
vap->iv_max_aid = WI_MAX_AID;
@ -566,7 +538,7 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
}
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@ -585,7 +557,9 @@ wi_shutdown(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
WI_LOCK(sc);
wi_stop(sc, 1);
WI_UNLOCK(sc);
return (0);
}
@ -593,12 +567,12 @@ void
wi_intr(void *arg)
{
struct wi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
u_int16_t status;
WI_LOCK(sc);
if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
if (sc->wi_gone || !sc->sc_enabled ||
(sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
WI_UNLOCK(sc);
@ -617,9 +591,8 @@ wi_intr(void *arg)
wi_tx_ex_intr(sc);
if (status & WI_EV_INFO)
wi_info_intr(sc);
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
wi_start_locked(ifp);
if (mbufq_first(&sc->sc_snd) != NULL)
wi_start(sc);
/* Re-enable interrupts. */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
@ -642,7 +615,7 @@ wi_enable(struct wi_softc *sc)
static int
wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
uint8_t mac[IEEE80211_ADDR_LEN])
const uint8_t mac[IEEE80211_ADDR_LEN])
{
int i;
@ -676,26 +649,25 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
return 0;
}
static void
wi_init_locked(struct wi_softc *sc)
void
wi_init(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int wasenabled;
WI_LOCK_ASSERT(sc);
wasenabled = sc->sc_enabled;
if (wasenabled)
wi_stop_locked(sc, 1);
wi_stop(sc, 1);
if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) {
if_printf(ifp, "interface not running\n");
wi_stop_locked(sc, 1);
if (wi_setup_locked(sc, sc->sc_porttype, 3,
sc->sc_ic.ic_macaddr) != 0) {
device_printf(sc->sc_dev, "interface not running\n");
wi_stop(sc, 1);
return;
}
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->sc_flags |= WI_FLAGS_RUNNING;
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
@ -703,24 +675,8 @@ wi_init_locked(struct wi_softc *sc)
}
void
wi_init(void *arg)
wi_stop(struct wi_softc *sc, int disable)
{
struct wi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
WI_LOCK(sc);
wi_init_locked(sc);
WI_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
wi_stop_locked(struct wi_softc *sc, int disable)
{
struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@ -736,22 +692,13 @@ wi_stop_locked(struct wi_softc *sc, int disable)
sc->sc_tx_timer = 0;
sc->sc_false_syns = 0;
ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
}
void
wi_stop(struct wi_softc *sc, int disable)
{
WI_LOCK(sc);
wi_stop_locked(sc, disable);
WI_UNLOCK(sc);
sc->sc_flags &= ~WI_FLAGS_RUNNING;
}
static void
wi_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: channel %d, %sscanning\n", __func__,
ieee80211_chan2ieee(ic, ic->ic_curchan),
@ -766,8 +713,7 @@ wi_set_channel(struct ieee80211com *ic)
static void
wi_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
struct ieee80211_scan_state *ss = ic->ic_scan;
DPRINTF(("%s\n", __func__));
@ -790,8 +736,7 @@ wi_scan_start(struct ieee80211com *ic)
static void
wi_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype));
@ -824,9 +769,8 @@ static int
wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state],
@ -894,9 +838,8 @@ static int
wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
int error;
DPRINTF(("%s: %s -> %s\n", __func__,
@ -953,10 +896,30 @@ wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int ar
return error;
}
static void
wi_start_locked(struct ifnet *ifp)
static int
wi_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct wi_softc *sc = ic->ic_softc;
int error;
WI_LOCK(sc);
if ((sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
WI_UNLOCK(sc);
return (ENXIO);
}
error = mbufq_enqueue(&sc->sc_snd, m);
if (error) {
WI_UNLOCK(sc);
return (error);
}
wi_start(sc);
WI_UNLOCK(sc);
return (0);
}
static void
wi_start(struct wi_softc *sc)
{
struct wi_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct ieee80211_frame *wh;
struct mbuf *m0;
@ -972,15 +935,8 @@ wi_start_locked(struct ifnet *ifp)
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
for (;;) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
if (m0 == NULL)
break;
if (sc->sc_txd[cur].d_len != 0) {
IFQ_DRV_PREPEND(&ifp->if_snd, m0);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
while (sc->sc_txd[cur].d_len == 0 &&
(m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
/* reconstruct 802.3 header */
@ -1029,28 +985,16 @@ wi_start_locked(struct ifnet *ifp)
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
ieee80211_free_node(ni);
if (wi_start_tx(ifp, &frmhdr, m0))
if (wi_start_tx(sc, &frmhdr, m0))
continue;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
}
static void
wi_start(struct ifnet *ifp)
{
struct wi_softc *sc = ifp->if_softc;
WI_LOCK(sc);
wi_start_locked(ifp);
WI_UNLOCK(sc);
}
static int
wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
{
struct wi_softc *sc = ifp->if_softc;
int cur = sc->sc_txnext;
int fid, off, error;
@ -1060,13 +1004,13 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
m_freem(m0);
if (error) {
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return -1;
}
sc->sc_txd[cur].d_len = off;
if (sc->sc_txcur == cur) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
if_printf(ifp, "xmit failed\n");
device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
return -1;
}
@ -1080,9 +1024,8 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap = ni->ni_vap;
struct wi_softc *sc = ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
struct wi_frame frmhdr;
@ -1098,7 +1041,6 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
if (sc->sc_txd[cur].d_len != 0) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
rc = ENOBUFS;
goto out;
}
@ -1129,7 +1071,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
(caddr_t)&frmhdr.wi_whdr);
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
if (wi_start_tx(sc, &frmhdr, m0) < 0) {
m0 = NULL;
rc = EIO;
goto out;
@ -1160,7 +1102,7 @@ wi_reset(struct wi_softc *sc)
}
sc->sc_reset = 1;
if (i == WI_INIT_TRIES) {
if_printf(sc->sc_ifp, "reset failed\n");
device_printf(sc->sc_dev, "reset failed\n");
return error;
}
@ -1178,7 +1120,6 @@ static void
wi_watchdog(void *arg)
{
struct wi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@ -1186,65 +1127,52 @@ wi_watchdog(void *arg)
return;
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
wi_init_locked(ifp->if_softc);
device_printf(sc->sc_dev, "device timeout\n");
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
wi_init(sc);
return;
}
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
}
static int
wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static void
wi_parent(struct ieee80211com *ic)
{
struct wi_softc *sc = ifp->if_softc;
struct ieee80211com *ic = ifp->if_l2com;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0, startall = 0;
struct wi_softc *sc = ic->ic_softc;
int startall = 0;
switch (cmd) {
case SIOCSIFFLAGS:
WI_LOCK(sc);
/*
* Can't do promisc and hostap at the same time. If all that's
* changing is the promisc flag, try to short-circuit a call to
* wi_init() by just setting PROMISC in the hardware.
*/
if (ifp->if_flags & IFF_UP) {
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
ifp->if_drv_flags & IFF_DRV_RUNNING) {
if ((ifp->if_flags ^ sc->sc_if_flags) & IFF_PROMISC) {
wi_write_val(sc, WI_RID_PROMISC,
(ifp->if_flags & IFF_PROMISC) != 0);
} else {
wi_init_locked(sc);
startall = 1;
}
WI_LOCK(sc);
/*
* Can't do promisc and hostap at the same time. If all that's
* changing is the promisc flag, try to short-circuit a call to
* wi_init() by just setting PROMISC in the hardware.
*/
if (ic->ic_nrunning > 0) {
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
sc->sc_flags & WI_FLAGS_RUNNING) {
if (ic->ic_promisc > 0 &&
(sc->sc_flags & WI_FLAGS_PROMISC) == 0) {
wi_write_val(sc, WI_RID_PROMISC, 1);
sc->sc_flags |= WI_FLAGS_PROMISC;
} else if (ic->ic_promisc == 0 &&
(sc->sc_flags & WI_FLAGS_PROMISC) != 0) {
wi_write_val(sc, WI_RID_PROMISC, 0);
sc->sc_flags &= ~WI_FLAGS_PROMISC;
} else {
wi_init_locked(sc);
wi_init(sc);
startall = 1;
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
wi_stop_locked(sc, 1);
sc->wi_gone = 0;
wi_init(sc);
startall = 1;
}
sc->sc_if_flags = ifp->if_flags;
WI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
break;
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
} else if (sc->sc_flags & WI_FLAGS_RUNNING) {
wi_stop(sc, 1);
sc->wi_gone = 0;
}
return error;
WI_UNLOCK(sc);
if (startall)
ieee80211_start_all(ic);
}
static void
@ -1252,7 +1180,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
struct wi_softc *sc = ic->ic_ifp->if_softc;
struct wi_softc *sc = ic->ic_softc;
u_int16_t val;
int rate, len;
@ -1280,8 +1208,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
static void
wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@ -1295,7 +1222,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
* indicator of the firmware's BSSID. Damp spurious
* change-of-BSSID indications.
*/
if ((ifp->if_flags & IFF_PROMISC) != 0 &&
if (ic->ic_promisc > 0 &&
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
WI_MAX_FALSE_SYNS))
return;
@ -1316,8 +1243,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
static __noinline void
wi_rx_intr(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct wi_frame frmhdr;
struct mbuf *m;
struct ieee80211_frame *wh;
@ -1332,7 +1258,7 @@ wi_rx_intr(struct wi_softc *sc)
/* First read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
}
@ -1343,7 +1269,7 @@ wi_rx_intr(struct wi_softc *sc)
status = le16toh(frmhdr.wi_status);
if (status & WI_STAT_ERRSTAT) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
@ -1358,7 +1284,7 @@ wi_rx_intr(struct wi_softc *sc)
if (off + len > MCLBYTES) {
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
} else
@ -1371,7 +1297,7 @@ wi_rx_intr(struct wi_softc *sc)
m = m_gethdr(M_NOWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
}
@ -1380,7 +1306,6 @@ wi_rx_intr(struct wi_softc *sc)
wi_read_bap(sc, fid, sizeof(frmhdr),
m->m_data + sizeof(struct ieee80211_frame), len);
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
m->m_pkthdr.rcvif = ifp;
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
@ -1425,7 +1350,6 @@ wi_rx_intr(struct wi_softc *sc)
static __noinline void
wi_tx_ex_intr(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct wi_frame frmhdr;
int fid;
@ -1440,7 +1364,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
*/
if ((status & WI_TXSTAT_DISCONNECT) == 0) {
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
if_printf(ifp, "tx failed");
device_printf(sc->sc_dev, "tx failed");
if (status & WI_TXSTAT_RET_ERR)
printf(", retry limit exceeded");
if (status & WI_TXSTAT_AGED_ERR)
@ -1455,7 +1379,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
printf(", status=0x%x", status);
printf("\n");
}
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
} else
DPRINTF(("port disconnected\n"));
} else
@ -1466,7 +1390,6 @@ wi_tx_ex_intr(struct wi_softc *sc)
static __noinline void
wi_tx_intr(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int fid, cur;
if (sc->wi_gone)
@ -1477,19 +1400,17 @@ wi_tx_intr(struct wi_softc *sc)
cur = sc->sc_txcur;
if (sc->sc_txd[cur].d_fid != fid) {
if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n",
fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
return;
}
sc->sc_tx_timer = 0;
sc->sc_txd[cur].d_len = 0;
sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
if (sc->sc_txd[cur].d_len == 0)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
else {
if (sc->sc_txd[cur].d_len != 0) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
0, 0)) {
if_printf(ifp, "xmit failed\n");
device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
} else {
sc->sc_tx_timer = 5;
@ -1500,7 +1421,7 @@ wi_tx_intr(struct wi_softc *sc)
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int i, fid, len, off;
u_int16_t ltbuf[2];
@ -1574,32 +1495,15 @@ wi_info_intr(struct wi_softc *sc)
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
}
static uint64_t
wi_get_counter(struct ifnet *ifp, ift_counter cnt)
{
struct wi_softc *sc;
sc = if_getsoftc(ifp);
switch (cnt) {
case IFCOUNTER_COLLISIONS:
return (sc->sc_stats.wi_tx_single_retries +
sc->sc_stats.wi_tx_multi_retries +
sc->sc_stats.wi_tx_retry_limit);
default:
return (if_get_counter_default(ifp, cnt));
}
}
static int
wi_write_multi(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
int n;
struct ifmultiaddr *ifma;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap;
struct wi_mcast mlist;
int n;
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
allmulti:
memset(&mlist, 0, sizeof(mlist));
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
@ -1607,17 +1511,23 @@ wi_write_multi(struct wi_softc *sc)
}
n = 0;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (n >= 16)
goto allmulti;
IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
n++;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
struct ifnet *ifp;
struct ifmultiaddr *ifma;
ifp = vap->iv_ifp;
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (n >= 16)
goto allmulti;
IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
n++;
}
if_maddr_runlock(ifp);
}
if_maddr_runlock(ifp);
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
IEEE80211_ADDR_LEN * n);
}
@ -1638,7 +1548,7 @@ wi_update_promisc(struct ieee80211com *ic)
/* XXX handle WEP special case handling? */
wi_write_val(sc, WI_RID_PROMISC,
(ic->ic_opmode == IEEE80211_M_MONITOR ||
(ic->ic_ifp->if_flags & IFF_PROMISC)));
(ic->ic_promisc > 0)));
WI_UNLOCK(sc);
}
@ -1937,7 +1847,7 @@ wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
}
static int
wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
{
int error, cnt;
@ -1949,7 +1859,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
return error;
}
cnt = (buflen + 1) / 2;
CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt);
sc->sc_bap_off += cnt * 2;
return 0;
@ -2039,7 +1949,7 @@ wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
}
static int
wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
wi_write_rid(struct wi_softc *sc, int rid, const void *buf, int buflen)
{
int error;
u_int16_t ltbuf[2];

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/bus.h>

View File

@ -238,7 +238,9 @@ wi_pci_suspend(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
WI_LOCK(sc);
wi_stop(sc, 1);
WI_UNLOCK(sc);
return (0);
}
@ -247,16 +249,15 @@ static int
wi_pci_resume(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = &sc->sc_ic;
if (sc->wi_bus_type != WI_BUS_PCI_NATIVE)
WI_LOCK(sc);
if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
return (0);
if (ifp->if_flags & IFF_UP) {
ifp->if_init(ifp->if_softc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
ifp->if_start(ifp);
WI_UNLOCK(sc);
}
if (ic->ic_nrunning > 0)
wi_init(sc);
WI_UNLOCK(sc);
return (0);
}

View File

@ -68,7 +68,8 @@ struct wi_vap {
#define WI_VAP(vap) ((struct wi_vap *)(vap))
struct wi_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
struct mbufq sc_snd;
device_t sc_dev;
struct mtx sc_mtx;
struct callout sc_watchdog;
@ -107,7 +108,6 @@ struct wi_softc {
int wi_cmd_count;
int sc_flags;
int sc_if_flags;
int sc_bap_id;
int sc_bap_off;
@ -152,6 +152,8 @@ struct wi_softc {
#define WI_FLAGS_HAS_ROAMING 0x0020
#define WI_FLAGS_HAS_FRAGTHR 0x0200
#define WI_FLAGS_HAS_DBMADJUST 0x0400
#define WI_FLAGS_RUNNING 0x0800
#define WI_FLAGS_PROMISC 0x1000
struct wi_card_ident {
u_int16_t card_id;
@ -180,7 +182,7 @@ int wi_shutdown(device_t);
int wi_alloc(device_t, int);
void wi_free(device_t);
extern devclass_t wi_devclass;
void wi_init(void *);
void wi_intr(void *);
int wi_mgmt_xmit(struct wi_softc *, caddr_t, int);
void wi_stop(struct wi_softc *, int);
void wi_init(struct wi_softc *);

File diff suppressed because it is too large Load Diff

View File

@ -72,6 +72,7 @@ struct wpi_tx_ring {
struct wpi_tx_cmd *cmd;
struct wpi_tx_data data[WPI_TX_RING_COUNT];
bus_dma_tag_t data_dmat;
struct mbufq snd;
int qid;
int queued;
int cur;
@ -164,14 +165,15 @@ struct wpi_fw_info {
struct wpi_softc {
device_t sc_dev;
struct ifnet *sc_ifp;
int sc_debug;
int sc_flags;
#define WPI_PS_PATH (1 << 0)
int sc_running;
struct mtx sc_mtx;
struct ieee80211com sc_ic;
struct mtx tx_mtx;
/* Shared area. */
@ -181,7 +183,6 @@ struct wpi_softc {
struct wpi_tx_ring txq[WPI_NTXQUEUES];
struct mtx txq_mtx;
struct mtx txq_state_mtx;
uint32_t txq_active;
struct wpi_rx_ring rxq;
uint64_t rx_tstamp;

View File

@ -261,7 +261,7 @@ static int
wtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
struct wtap_softc *sc = ic->ic_ifp->if_softc;
struct wtap_softc *sc = ic->ic_softc;
struct wtap_vap *avp = WTAP_VAP(vap);
struct ieee80211_node *ni = NULL;
int error;
@ -318,7 +318,7 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct wtap_softc *sc = ic->ic_ifp->if_softc;
struct wtap_softc *sc = ic->ic_softc;
struct ieee80211vap *vap;
struct wtap_vap *avp;
int error;
@ -326,15 +326,13 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
DWTAP_PRINTF("%s\n", __func__);
avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_NOWAIT | M_ZERO);
if (avp == NULL)
return (NULL);
avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_WAITOK | M_ZERO);
avp->id = sc->id;
avp->av_md = sc->sc_md;
avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id);
vap = (struct ieee80211vap *) avp;
error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS,
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
flags | IEEE80211_CLONE_NOBEACONS, bssid);
if (error) {
free(avp, M_80211_VAP);
return (NULL);
@ -351,9 +349,10 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
vap->iv_bmiss = wtap_bmiss;
/* complete setup */
ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status);
ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status,
mac);
avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"%s", (const char *)ic->ic_ifp->if_xname);
"%s", (const char *)sc->name);
/* TODO this is a hack to force it to choose the rate we want */
ni = ieee80211_ref_node(vap->iv_bss);
@ -374,148 +373,16 @@ wtap_vap_delete(struct ieee80211vap *vap)
free((struct wtap_vap*) vap, M_80211_VAP);
}
/* NB: This function is not used.
* I had the problem of the queue
* being empty all the time.
* Maybe I am setting the queue wrong?
*/
static void
wtap_start(struct ifnet *ifp)
wtap_parent(struct ieee80211com *ic)
{
struct ieee80211com *ic = ifp->if_l2com;
struct ifnet *icifp = ic->ic_ifp;
struct wtap_softc *sc = icifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
struct wtap_softc *sc = ic->ic_softc;
DWTAP_PRINTF("my_start, with id=%u\n", sc->id);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->up == 0)
return;
for (;;) {
if(IFQ_IS_EMPTY(&ifp->if_snd)){
printf("queue empty, just trying to see "
"if the other queue is empty\n");
#if 0
printf("queue for id=1, %u\n",
IFQ_IS_EMPTY(&global_mscs[1]->ifp->if_snd));
printf("queue for id=0, %u\n",
IFQ_IS_EMPTY(&global_mscs[0]->ifp->if_snd));
#endif
break;
}
IFQ_DEQUEUE(&ifp->if_snd, m);
if (m == NULL) {
printf("error dequeueing from ifp->snd\n");
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
/*
* Check for fragmentation. If this frame
* has been broken up verify we have enough
* buffers to send all the fragments so all
* go out or none...
*/
#if 0
STAILQ_INIT(&frags);
#endif
if ((m->m_flags & M_FRAG)){
printf("dont support frags\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return;
}
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if(wtap_raw_xmit(ni, m, NULL) < 0){
printf("error raw_xmiting\n");
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return;
}
}
}
static int
wtap_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
#if 0
DWTAP_PRINTF("%s\n", __func__);
uprintf("%s, command %lu\n", __func__, cmd);
#endif
#define IS_RUNNING(ifp) \
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
struct ieee80211com *ic = ifp->if_l2com;
struct wtap_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
int error = 0;
switch (cmd) {
case SIOCSIFFLAGS:
//printf("%s: %s\n", __func__, "SIOCSIFFLAGS");
if (IS_RUNNING(ifp)) {
DWTAP_PRINTF("running\n");
#if 0
/*
* To avoid rescanning another access point,
* do not call ath_init() here. Instead,
* only reflect promisc mode settings.
*/
//ath_mode_init(sc);
#endif
} else if (ifp->if_flags & IFF_UP) {
DWTAP_PRINTF("up\n");
sc->up = 1;
#if 0
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
* will still be marked UP but not RUNNING.
* However trying to re-init the interface
* is the wrong thing to do as we've already
* torn down much of our state. There's
* probably a better way to deal with this.
*/
//if (!sc->sc_invalid)
// ath_init(sc); /* XXX lose error */
#endif
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ieee80211_start_all(ic);
} else {
DWTAP_PRINTF("stoping\n");
#if 0
ath_stop_locked(ifp);
#ifdef notyet
/* XXX must wakeup in places like ath_vap_delete */
if (!sc->sc_invalid)
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
#endif
#endif
}
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
#if 0
DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFMEDIA|SIOCSIFMEDIA");
#endif
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
break;
case SIOCGIFADDR:
#if 0
DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFADDR");
#endif
error = ether_ioctl(ifp, cmd, data);
break;
default:
DWTAP_PRINTF("%s: %s [%lu]\n", __func__, "EINVAL", cmd);
error = EINVAL;
break;
}
return error;
#undef IS_RUNNING
}
static void
wtap_init(void *arg){
DWTAP_PRINTF("%s\n", __func__);
if (ic->ic_nrunning > 0) {
sc->up = 1;
ieee80211_start_all(ic);
} else
sc->up = 0;
}
static void
@ -581,8 +448,7 @@ wtap_inject(struct wtap_softc *sc, struct mbuf *m)
void
wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
int type;
#if 0
@ -591,11 +457,9 @@ wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, m);
if (m == NULL) { /* NB: shouldn't happen */
if_printf(ifp, "%s: no mbuf!\n", __func__);
ic_printf(ic, "%s: no mbuf!\n", __func__);
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
/*
@ -620,8 +484,7 @@ static void
wtap_rx_proc(void *arg, int npending)
{
struct wtap_softc *sc = (struct wtap_softc *)arg;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m;
struct ieee80211_node *ni;
int type;
@ -644,12 +507,10 @@ wtap_rx_proc(void *arg, int npending)
m = bf->m;
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m);
if (m == NULL) { /* NB: shouldn't happen */
if_printf(ifp, "%s: no mbuf!\n", __func__);
ic_printf(ic, "%s: no mbuf!\n", __func__);
free(bf, M_WTAP_RXBUF);
return;
}
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
#if 0
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
#endif
@ -716,7 +577,7 @@ wtap_update_promisc(struct ieee80211com *ic)
}
static int
wtap_if_transmit(struct ifnet *ifp, struct mbuf *m)
wtap_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct ieee80211_node *ni =
(struct ieee80211_node *) m->m_pkthdr.rcvif;
@ -753,7 +614,7 @@ static void
wtap_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
struct wtap_softc *sc = ic->ic_ifp->if_softc;
struct wtap_softc *sc = ic->ic_softc;
DWTAP_PRINTF("%s\n", __func__);
sc->sc_node_free(ni);
@ -762,41 +623,17 @@ wtap_node_free(struct ieee80211_node *ni)
int32_t
wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
{
struct ifnet *ifp;
struct ieee80211com *ic;
char wtap_name[] = {'w','T','a','p',sc->id,
'_','t','a','s','k','q','\0'};
struct ieee80211com *ic = &sc->sc_ic;
DWTAP_PRINTF("%s\n", __func__);
ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
printf("can not if_alloc()\n");
return -1;
}
ic = ifp->if_l2com;
if_initname(ifp, "wtap", sc->id);
sc->sc_ifp = ifp;
sc->up = 0;
STAILQ_INIT(&sc->sc_rxbuf);
sc->sc_tq = taskqueue_create(wtap_name, M_NOWAIT | M_ZERO,
sc->sc_tq = taskqueue_create("wtap_taskq", M_NOWAIT | M_ZERO,
taskqueue_thread_enqueue, &sc->sc_tq);
taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ",
ifp->if_xname);
taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", sc->name);
TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc);
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
ifp->if_start = wtap_start;
ifp->if_ioctl = wtap_ioctl;
ifp->if_init = wtap_init;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = sc->name;
ic->ic_phytype = IEEE80211_T_DS;
@ -815,17 +652,8 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B;
ic->ic_channels[0].ic_freq = 2412;
ieee80211_ifattach(ic, macaddr);
#if 0
/* new prototype hook-ups */
msc->if_input = ifp->if_input;
ifp->if_input = myath_if_input;
msc->if_output = ifp->if_output;
ifp->if_output = myath_if_output;
#endif
sc->if_transmit = ifp->if_transmit;
ifp->if_transmit = wtap_if_transmit;
IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
ieee80211_ifattach(ic);
/* override default methods */
ic->ic_newassoc = wtap_newassoc;
@ -835,15 +663,14 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
ic->ic_raw_xmit = wtap_raw_xmit;
ic->ic_update_mcast = wtap_update_mcast;
ic->ic_update_promisc = wtap_update_promisc;
ic->ic_transmit = wtap_transmit;
ic->ic_parent = wtap_parent;
sc->sc_node_alloc = ic->ic_node_alloc;
ic->ic_node_alloc = wtap_node_alloc;
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = wtap_node_free;
#if 0
ic->ic_node_getsignal = myath_node_getsignal;
#endif
ic->ic_scan_start = wtap_scan_start;
ic->ic_scan_end = wtap_scan_end;
ic->ic_set_channel = wtap_set_channel;
@ -882,13 +709,11 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
int32_t
wtap_detach(struct wtap_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211com *ic = &sc->sc_ic;
DWTAP_PRINTF("%s\n", __func__);
ieee80211_ageq_drain(&ic->ic_stageq);
ieee80211_ifdetach(ic);
if_free(ifp);
return 0;
}

View File

@ -130,18 +130,14 @@ struct wtap_vap {
struct taskqueue;
struct wtap_softc {
struct ieee80211com sc_ic;
char name[7]; /* wtapXX\0 */
int32_t id;
int32_t up;
struct ifnet *sc_ifp; /* interface common */
struct wtap_medium *sc_md; /* interface medium */
struct ieee80211_node* (* sc_node_alloc)
(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);
void (*sc_node_free)(struct ieee80211_node *);
int (*if_output) /* output routine (enqueue) */
(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *);
void (*if_input) (struct ifnet *, struct mbuf *);/* from h/w driver */
int (*if_transmit)(struct ifnet *, struct mbuf *);/* output routine */
struct mtx sc_mtx; /* master lock (recursive) */
struct taskqueue *sc_tq; /* private task queue */
wtap_bufhead sc_rxbuf; /* receive buffer */

View File

@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/sbuf.h>
#include <machine/stdarg.h>
@ -91,8 +92,6 @@ static void ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag);
static int ieee80211_media_setup(struct ieee80211com *ic,
struct ifmedia *media, int caps, int addsta,
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat);
static void ieee80211com_media_status(struct ifnet *, struct ifmediareq *);
static int ieee80211com_media_change(struct ifnet *);
static int media_status(enum ieee80211_opmode,
const struct ieee80211_channel *);
static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter);
@ -121,7 +120,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g =
* all available channels as active, and pick
* a default channel if not already specified.
*/
static void
void
ieee80211_chan_init(struct ieee80211com *ic)
{
#define DEFAULTRATES(m, def) do { \
@ -238,29 +237,6 @@ null_update_promisc(struct ieee80211com *ic)
ic_printf(ic, "need promiscuous mode update callback\n");
}
static int
null_transmit(struct ifnet *ifp, struct mbuf *m)
{
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return EACCES; /* XXX EIO/EPERM? */
}
static int
null_output(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr *dst, struct route *ro)
{
if_printf(ifp, "discard raw packet\n");
return null_transmit(ifp, m);
}
static void
null_input(struct ifnet *ifp, struct mbuf *m)
{
if_printf(ifp, "if_input should not be called\n");
m_freem(m);
}
static void
null_update_chw(struct ieee80211com *ic)
{
@ -281,19 +257,43 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...)
return (retval);
}
static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head);
static struct mtx ic_list_mtx;
MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF);
static int
sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS)
{
struct ieee80211com *ic;
struct sbuf *sb;
char *sp;
int error;
sb = sbuf_new_auto();
sp = "";
mtx_lock(&ic_list_mtx);
LIST_FOREACH(ic, &ic_head, ic_next) {
sbuf_printf(sb, "%s%s", sp, ic->ic_name);
sp = " ";
}
mtx_unlock(&ic_list_mtx);
sbuf_finish(sb);
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
sbuf_delete(sb);
return (error);
}
SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
sysctl_ieee80211coms, "A", "names of available 802.11 devices");
/*
* Attach/setup the common net80211 state. Called by
* the driver on attach to prior to creating any vap's.
*/
void
ieee80211_ifattach(struct ieee80211com *ic,
const uint8_t macaddr[IEEE80211_ADDR_LEN])
ieee80211_ifattach(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct sockaddr_dl *sdl;
struct ifaddr *ifa;
KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
IEEE80211_LOCK_INIT(ic, ic->ic_name);
IEEE80211_TX_LOCK_INIT(ic, ic->ic_name);
@ -311,7 +311,7 @@ ieee80211_ifattach(struct ieee80211com *ic,
* available channels as active, and pick a default
* channel if not already specified.
*/
ieee80211_media_init(ic);
ieee80211_chan_init(ic);
ic->ic_update_mcast = null_update_mcast;
ic->ic_update_promisc = null_update_promisc;
@ -336,28 +336,9 @@ ieee80211_ifattach(struct ieee80211com *ic,
ieee80211_sysctl_attach(ic);
ifp->if_addrlen = IEEE80211_ADDR_LEN;
ifp->if_hdrlen = 0;
CURVNET_SET(vnet0);
if_attach(ifp);
ifp->if_mtu = IEEE80211_MTU_MAX;
ifp->if_broadcastaddr = ieee80211broadcastaddr;
ifp->if_output = null_output;
ifp->if_input = null_input; /* just in case */
ifp->if_resolvemulti = NULL; /* NB: callers check */
ifa = ifaddr_byindex(ifp->if_index);
KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */
sdl->sdl_alen = IEEE80211_ADDR_LEN;
IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr);
ifa_free(ifa);
CURVNET_RESTORE();
mtx_lock(&ic_list_mtx);
LIST_INSERT_HEAD(&ic_head, ic, ic_next);
mtx_unlock(&ic_list_mtx);
}
/*
@ -369,16 +350,11 @@ ieee80211_ifattach(struct ieee80211com *ic,
void
ieee80211_ifdetach(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap;
/*
* This detaches the main interface, but not the vaps.
* Each VAP may be in a separate VIMAGE.
*/
CURVNET_SET(ifp->if_vnet);
if_detach(ifp);
CURVNET_RESTORE();
mtx_lock(&ic_list_mtx);
LIST_REMOVE(ic, ic_next);
mtx_unlock(&ic_list_mtx);
/*
* The VAP is responsible for setting and clearing
@ -402,8 +378,6 @@ ieee80211_ifdetach(struct ieee80211com *ic)
ieee80211_power_detach(ic);
ieee80211_node_detach(ic);
/* XXX VNET needed? */
ifmedia_removeall(&ic->ic_media);
counter_u64_free(ic->ic_ierrors);
counter_u64_free(ic->ic_oerrors);
@ -412,6 +386,20 @@ ieee80211_ifdetach(struct ieee80211com *ic)
IEEE80211_LOCK_DESTROY(ic);
}
struct ieee80211com *
ieee80211_find_com(const char *name)
{
struct ieee80211com *ic;
mtx_lock(&ic_list_mtx);
LIST_FOREACH(ic, &ic_head, ic_next)
if (strcmp(ic->ic_name, name) == 0)
break;
mtx_unlock(&ic_list_mtx);
return (ic);
}
/*
* Default reset method for use with the ioctl support. This
* method is invoked after any state change in the 802.11
@ -460,8 +448,7 @@ ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt)
int
ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode,
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t macaddr[IEEE80211_ADDR_LEN])
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp;
@ -490,6 +477,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
vap->iv_htextcaps = ic->ic_htextcaps;
vap->iv_opmode = opmode;
vap->iv_caps |= ieee80211_opcap[opmode];
vap->iv_myaddr = ic->ic_macaddr;
switch (opmode) {
case IEEE80211_M_WDS:
/*
@ -556,8 +544,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
*/
vap->iv_reset = default_reset;
IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr);
ieee80211_sysctl_vattach(vap);
ieee80211_crypto_vattach(vap);
ieee80211_node_vattach(vap);
@ -581,8 +567,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
* from this call the vap is ready for use.
*/
int
ieee80211_vap_attach(struct ieee80211vap *vap,
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
@ -610,7 +596,8 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
if (maxrate)
ifp->if_baudrate = IF_Mbps(maxrate);
ether_ifattach(ifp, vap->iv_myaddr);
ether_ifattach(ifp, macaddr);
vap->iv_myaddr = IF_LLADDR(ifp);
/* hook output method setup by ether_ifattach */
vap->iv_output = ifp->if_output;
ifp->if_output = ieee80211_output;
@ -626,8 +613,6 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
IEEE80211_UNLOCK(ic);
return 1;
@ -677,8 +662,10 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
/* NB: this handles the bpfdetach done below */
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
if (vap->iv_ifflags & IFF_PROMISC)
ieee80211_promisc(vap, false);
if (vap->iv_ifflags & IFF_ALLMULTI)
ieee80211_allmulti(vap, false);
IEEE80211_UNLOCK(ic);
ifmedia_removeall(&vap->iv_media);
@ -703,49 +690,57 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
}
/*
* Synchronize flag bit state in the parent ifnet structure
* according to the state of all vap ifnet's. This is used,
* for example, to handle IFF_PROMISC and IFF_ALLMULTI.
* Count number of vaps in promisc, and issue promisc on
* parent respectively.
*/
void
ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
ieee80211_promisc(struct ieee80211vap *vap, bool on)
{
struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap;
int bit, oflags;
struct ieee80211com *ic = vap->iv_ic;
IEEE80211_LOCK_ASSERT(ic);
/*
* XXX the bridge sets PROMISC but we don't want to
* enable it on the device, discard here so all the
* drivers don't need to special-case it
*/
if (!(vap->iv_opmode == IEEE80211_M_MONITOR ||
(vap->iv_opmode == IEEE80211_M_AHDEMO &&
(vap->iv_caps & IEEE80211_C_TDMA) == 0)))
return;
bit = 0;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
if (vap->iv_ifp->if_flags & flag) {
/*
* XXX the bridge sets PROMISC but we don't want to
* enable it on the device, discard here so all the
* drivers don't need to special-case it
*/
if (flag == IFF_PROMISC &&
!(vap->iv_opmode == IEEE80211_M_MONITOR ||
(vap->iv_opmode == IEEE80211_M_AHDEMO &&
(vap->iv_caps & IEEE80211_C_TDMA) == 0)))
continue;
bit = 1;
break;
}
oflags = ifp->if_flags;
if (bit)
ifp->if_flags |= flag;
else
ifp->if_flags &= ~flag;
if ((ifp->if_flags ^ oflags) & flag) {
/* XXX should we return 1/0 and let caller do this? */
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (flag == IFF_PROMISC)
ieee80211_runtask(ic, &ic->ic_promisc_task);
else if (flag == IFF_ALLMULTI)
ieee80211_runtask(ic, &ic->ic_mcast_task);
}
IEEE80211_LOCK(ic);
if (on) {
if (++ic->ic_promisc == 1)
ieee80211_runtask(ic, &ic->ic_promisc_task);
} else {
KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc",
__func__, ic));
if (--ic->ic_promisc == 0)
ieee80211_runtask(ic, &ic->ic_promisc_task);
}
IEEE80211_UNLOCK(ic);
}
/*
* Count number of vaps in allmulti, and issue allmulti on
* parent respectively.
*/
void
ieee80211_allmulti(struct ieee80211vap *vap, bool on)
{
struct ieee80211com *ic = vap->iv_ic;
IEEE80211_LOCK(ic);
if (on) {
if (++ic->ic_allmulti == 1)
ieee80211_runtask(ic, &ic->ic_mcast_task);
} else {
KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti",
__func__, ic));
if (--ic->ic_allmulti == 0)
ieee80211_runtask(ic, &ic->ic_mcast_task);
}
IEEE80211_UNLOCK(ic);
}
/*
@ -1234,39 +1229,6 @@ ieee80211_media_setup(struct ieee80211com *ic,
return maxrate;
}
void
ieee80211_media_init(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
int maxrate;
/* NB: this works because the structure is initialized to zero */
if (!LIST_EMPTY(&ic->ic_media.ifm_list)) {
/*
* We are re-initializing the channel list; clear
* the existing media state as the media routines
* don't suppress duplicates.
*/
ifmedia_removeall(&ic->ic_media);
}
ieee80211_chan_init(ic);
/*
* Recalculate media settings in case new channel list changes
* the set of available modes.
*/
maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1,
ieee80211com_media_change, ieee80211com_media_status);
/* NB: strip explicit mode; we're actually in autoselect */
ifmedia_set(&ic->ic_media,
media_status(ic->ic_opmode, ic->ic_curchan) &~
(IFM_MMASK | IFM_IEEE80211_TURBO));
if (maxrate)
ifp->if_baudrate = IF_Mbps(maxrate);
/* XXX need to propagate new media settings to vap's */
}
/* XXX inline or eliminate? */
const struct ieee80211_rateset *
ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
@ -1394,15 +1356,6 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode)
return 1;
}
/*
* Handle a media change request on the underlying interface.
*/
int
ieee80211com_media_change(struct ifnet *ifp)
{
return EINVAL;
}
/*
* Handle a media change request on the vap interface.
*/
@ -1480,23 +1433,6 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan)
return status;
}
static void
ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap;
imr->ifm_status = IFM_AVALID;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
if (vap->iv_ifp->if_flags & IFF_UP) {
imr->ifm_status |= IFM_ACTIVE;
break;
}
imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
if (imr->ifm_status & IFM_ACTIVE)
imr->ifm_current = imr->ifm_active;
}
void
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{

View File

@ -520,7 +520,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap);
db_printf("\n");
db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname);
db_printf("\tsoftc %p", ic->ic_softc);
db_printf("\tname %s", ic->ic_name);
db_printf(" comlock %p", &ic->ic_comlock);
db_printf("\n");
@ -528,7 +528,6 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
db_printf(" phytype %d", ic->ic_phytype);
db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
db_printf("\n");
db_printf("\tmedia %p", &ic->ic_media);
db_printf(" inact %p", &ic->ic_inact);
db_printf("\n");

View File

@ -69,58 +69,27 @@ static MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state");
static const char wlanname[] = "wlan";
static struct if_clone *wlan_cloner;
/*
* Allocate/free com structure in conjunction with ifnet;
* these routines are registered with if_register_com_alloc
* below and are called automatically by the ifnet code
* when the ifnet of the parent device is created.
*/
static void *
wlan_alloc(u_char type, struct ifnet *ifp)
{
struct ieee80211com *ic;
ic = IEEE80211_MALLOC(sizeof(struct ieee80211com), M_80211_COM,
IEEE80211_M_WAITOK | IEEE80211_M_ZERO);
ic->ic_ifp = ifp;
return (ic);
}
static void
wlan_free(void *ic, u_char type)
{
IEEE80211_FREE(ic, M_80211_COM);
}
static int
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct ieee80211_clone_params cp;
struct ieee80211vap *vap;
struct ieee80211com *ic;
struct ifnet *ifp;
int error;
error = copyin(params, &cp, sizeof(cp));
if (error)
return error;
ifp = ifunit(cp.icp_parent);
if (ifp == NULL)
ic = ieee80211_find_com(cp.icp_parent);
if (ic == NULL)
return ENXIO;
/* XXX move printfs to DIAGNOSTIC before release */
if (ifp->if_type != IFT_IEEE80211) {
if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
return ENXIO;
}
if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
if_printf(ifp, "%s: invalid opmode %d\n",
__func__, cp.icp_opmode);
ic_printf(ic, "%s: invalid opmode %d\n", __func__,
cp.icp_opmode);
return EINVAL;
}
ic = ifp->if_l2com;
if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
if_printf(ifp, "%s mode not supported\n",
ic_printf(ic, "%s mode not supported\n",
ieee80211_opmode_name[cp.icp_opmode]);
return EOPNOTSUPP;
}
@ -131,13 +100,13 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
(1)
#endif
) {
if_printf(ifp, "TDMA not supported\n");
ic_printf(ic, "TDMA not supported\n");
return EOPNOTSUPP;
}
vap = ic->ic_vap_create(ic, wlanname, unit,
cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
cp.icp_flags & IEEE80211_CLONE_MACADDR ?
cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
cp.icp_macaddr : ic->ic_macaddr);
return (vap == NULL ? EIO : 0);
}
@ -528,17 +497,19 @@ ieee80211_process_callback(struct ieee80211_node *ni,
* (the callers will first need modifying.)
*/
int
ieee80211_parent_xmitpkt(struct ieee80211com *ic,
struct mbuf *m)
ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
{
struct ifnet *parent = ic->ic_ifp;
int error;
/*
* Assert the IC TX lock is held - this enforces the
* processing -> queuing order is maintained
*/
IEEE80211_TX_LOCK_ASSERT(ic);
return (parent->if_transmit(parent, m));
error = ic->ic_transmit(ic, m);
if (error)
m_freem(m);
return (error);
}
/*
@ -836,7 +807,6 @@ ieee80211_load_module(const char *modname)
}
static eventhandler_tag wlan_bpfevent;
static eventhandler_tag wlan_ifllevent;
static void
bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
@ -864,33 +834,6 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
}
}
static void
wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
{
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap, *next;
if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
return;
IEEE80211_LOCK(ic);
TAILQ_FOREACH_SAFE(vap, &ic->ic_vaps, iv_next, next) {
/*
* If the MAC address has changed on the parent and it was
* copied to the vap on creation then re-sync.
*/
if (vap->iv_ic == ic &&
(vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
IEEE80211_UNLOCK(ic);
if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
IEEE80211_ADDR_LEN);
IEEE80211_LOCK(ic);
}
}
IEEE80211_UNLOCK(ic);
}
/*
* Module glue.
*
@ -905,17 +848,12 @@ wlan_modevent(module_t mod, int type, void *unused)
printf("wlan: <802.11 Link Layer>\n");
wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
bpf_track, 0, EVENTHANDLER_PRI_ANY);
wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
wlan_cloner = if_clone_simple(wlanname, wlan_clone_create,
wlan_clone_destroy, 0);
if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
return 0;
case MOD_UNLOAD:
if_deregister_com_alloc(IFT_IEEE80211);
if_clone_detach(wlan_cloner);
EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
return 0;
}
return EINVAL;

View File

@ -1329,13 +1329,12 @@ static int
setmlme_dropsta(struct ieee80211vap *vap,
const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node_table *nt = &ic->ic_sta;
struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
struct ieee80211_node *ni;
int error = 0;
/* NB: the broadcast address means do 'em all */
if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
IEEE80211_NODE_LOCK(nt);
ni = ieee80211_find_node_locked(nt, mac);
IEEE80211_NODE_UNLOCK(nt);
@ -2529,14 +2528,9 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
static __noinline int
ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_req sr; /* XXX off stack? */
int error;
/* NB: parent must be running */
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return ENXIO;
if (ireq->i_len != sizeof(sr))
return EINVAL;
error = copyin(ireq->i_data, &sr, sizeof(sr));
@ -3300,41 +3294,6 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
return error;
}
/*
* Rebuild the parent's multicast address list after an add/del
* of a multicast address for a vap. We have no way to tell
* what happened above to optimize the work so we purge the entire
* list and rebuild from scratch. This is way expensive.
* Note also the half-baked workaround for if_addmulti calling
* back to the parent device; there's no way to insert mcast
* entries quietly and/or cheaply.
*/
static void
ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
{
struct ifnet *parent = ic->ic_ifp;
struct ieee80211vap *vap;
void *ioctl;
IEEE80211_LOCK(ic);
if_delallmulti(parent);
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
parent->if_ioctl = NULL;
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
struct ifnet *ifp = vap->iv_ifp;
struct ifmultiaddr *ifma;
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
(void) if_addmulti(parent, ifma->ifma_addr, NULL);
}
}
parent->if_ioctl = ioctl;
ieee80211_runtask(ic, &ic->ic_mcast_task);
IEEE80211_UNLOCK(ic);
}
int
ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@ -3347,8 +3306,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFFLAGS:
IEEE80211_LOCK(ic);
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC)
ieee80211_promisc(vap, ifp->if_flags & IFF_PROMISC);
if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI)
ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
vap->iv_ifflags = ifp->if_flags;
if (ifp->if_flags & IFF_UP) {
/*
* Bring ourself up unless we're already operational.
@ -3371,7 +3333,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
ieee80211_ioctl_updatemulti(ic);
ieee80211_runtask(ic, &ic->ic_mcast_task);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@ -3427,17 +3389,16 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
break;
/* Pass NDIS ioctls up to the driver */
case SIOCGDRVSPEC:
case SIOCSDRVSPEC:
case SIOCGPRIVATE_0: {
struct ifnet *parent = vap->iv_ic->ic_ifp;
error = parent->if_ioctl(parent, cmd, data);
break;
}
default:
/*
* Pass unknown ioctls first to the driver, and if it
* returns ENOTTY, then to the generic Ethernet handler.
*/
if (ic->ic_ioctl != NULL &&
(error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
break;
error = ether_ioctl(ifp, cmd, data);
break;
}
return error;
return (error);
}

View File

@ -254,10 +254,6 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m,
/* NB: IFQ_HANDOFF reclaims mbuf */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
}
ic->ic_lastdata = ticks;
@ -430,17 +426,6 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *parent = ic->ic_ifp;
/* NB: parent must be up and running */
if (!IFNET_IS_UP_RUNNING(parent)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
"%s: ignore queue, parent %s not up+running\n",
__func__, parent->if_xname);
m_freem(m);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return (ENETDOWN);
}
/*
* No data frames go out unless we're running.
@ -507,6 +492,7 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct mbuf *m, const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = vap->iv_ic;
int error;
/*
* Set node - the caller has taken a reference, so ensure
@ -528,7 +514,10 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (params)
(void) ieee80211_add_xmit_params(m, params);
return (ic->ic_raw_xmit(ni, m, params));
error = ic->ic_raw_xmit(ni, m, params);
if (error)
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
return (error);
}
/*
@ -3457,6 +3446,15 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status)
{
if (ni != NULL) {
struct ifnet *ifp = ni->ni_vap->iv_ifp;
if (status == 0) {
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (m->m_flags & M_MCAST)
if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
} else
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, status);
ieee80211_free_node(ni);

View File

@ -418,7 +418,6 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
struct ifnet *parent, *ifp;
struct mbuf *parent_q = NULL, *ifp_q = NULL;
struct mbuf *m;
@ -429,59 +428,51 @@ pwrsave_flushq(struct ieee80211_node *ni)
qhead = &psq->psq_head[0]; /* 802.11 frames */
if (qhead->head != NULL) {
/* XXX could dispatch through vap and check M_ENCAP */
parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
parent = NULL;
}
qhead = &psq->psq_head[1]; /* 802.3 frames */
if (qhead->head != NULL) {
ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
} else
ifp = NULL;
}
psq->psq_len = 0;
IEEE80211_PSQ_UNLOCK(psq);
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
/* parent frames, should be encapsulated */
if (parent != NULL) {
while (parent_q != NULL) {
m = parent_q;
parent_q = m->m_nextpkt;
m->m_nextpkt = NULL;
/* must be encapsulated */
KASSERT((m->m_flags & M_ENCAP),
("%s: parentq with non-M_ENCAP frame!\n",
__func__));
/*
* For encaped frames, we need to free the node
* reference upon failure.
*/
if (ieee80211_parent_xmitpkt(ic, m) != 0)
ieee80211_free_node(ni);
}
while (parent_q != NULL) {
m = parent_q;
parent_q = m->m_nextpkt;
m->m_nextpkt = NULL;
/* must be encapsulated */
KASSERT((m->m_flags & M_ENCAP),
("%s: parentq with non-M_ENCAP frame!\n",
__func__));
/*
* For encaped frames, we need to free the node
* reference upon failure.
*/
if (ieee80211_parent_xmitpkt(ic, m) != 0)
ieee80211_free_node(ni);
}
/* VAP frames, aren't encapsulated */
if (ifp != NULL) {
while (ifp_q != NULL) {
m = ifp_q;
ifp_q = m->m_nextpkt;
m->m_nextpkt = NULL;
KASSERT((!(m->m_flags & M_ENCAP)),
("%s: vapq with M_ENCAP frame!\n", __func__));
(void) ieee80211_vap_xmitpkt(vap, m);
}
while (ifp_q != NULL) {
m = ifp_q;
ifp_q = m->m_nextpkt;
m->m_nextpkt = NULL;
KASSERT((!(m->m_flags & M_ENCAP)),
("%s: vapq with M_ENCAP frame!\n", __func__));
(void) ieee80211_vap_xmitpkt(vap, m);
}
}

View File

@ -122,23 +122,23 @@ null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
void
ieee80211_proto_attach(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
uint8_t hdrlen;
/* override the 802.3 setting */
ifp->if_hdrlen = ic->ic_headroom
hdrlen = ic->ic_headroom
+ sizeof(struct ieee80211_qosframe_addr4)
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_EXTIVLEN;
/* XXX no way to recalculate on ifdetach */
if (ALIGN(ifp->if_hdrlen) > max_linkhdr) {
if (ALIGN(hdrlen) > max_linkhdr) {
/* XXX sanity check... */
max_linkhdr = ALIGN(ifp->if_hdrlen);
max_linkhdr = ALIGN(hdrlen);
max_hdr = max_linkhdr + max_protohdr;
max_datalen = MHLEN - max_hdr;
}
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic);
TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
@ -188,7 +188,10 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
int i;
/* override the 802.3 setting */
ifp->if_hdrlen = ic->ic_ifp->if_hdrlen;
ifp->if_hdrlen = ic->ic_headroom
+ sizeof(struct ieee80211_qosframe_addr4)
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_EXTIVLEN;
vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT;
vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT;
@ -1155,9 +1158,9 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap)
static void
parent_updown(void *arg, int npending)
{
struct ifnet *parent = arg;
struct ieee80211com *ic = arg;
parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
ic->ic_parent(ic);
}
static void
@ -1224,7 +1227,6 @@ ieee80211_start_locked(struct ieee80211vap *vap)
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@ -1246,12 +1248,10 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* We are not running; if this we are the first vap
* to be brought up auto-up the parent if necessary.
*/
if (ic->ic_nrunning++ == 0 &&
(parent->if_drv_flags & IFF_DRV_RUNNING) == 0) {
if (ic->ic_nrunning++ == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"%s: up parent %s\n", __func__, parent->if_xname);
parent->if_flags |= IFF_UP;
"%s: up parent %s\n", __func__, ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
return;
}
@ -1260,8 +1260,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* If the parent is up and running, then kick the
* 802.11 state machine as appropriate.
*/
if ((parent->if_drv_flags & IFF_DRV_RUNNING) &&
vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
if (vap->iv_opmode == IEEE80211_M_STA) {
#if 0
/* XXX bypasses scan too easily; disable for now */
@ -1344,7 +1343,6 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@ -1354,12 +1352,10 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */
if (--ic->ic_nrunning == 0 &&
(parent->if_drv_flags & IFF_DRV_RUNNING)) {
if (--ic->ic_nrunning == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"down parent %s\n", parent->if_xname);
parent->if_flags &= ~IFF_UP;
"down parent %s\n", ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
}
}

View File

@ -56,7 +56,8 @@ void ieee80211_proto_detach(struct ieee80211com *);
void ieee80211_proto_vattach(struct ieee80211vap *);
void ieee80211_proto_vdetach(struct ieee80211vap *);
void ieee80211_syncifflag_locked(struct ieee80211com *, int flag);
void ieee80211_promisc(struct ieee80211vap *, bool);
void ieee80211_allmulti(struct ieee80211vap *, bool);
void ieee80211_syncflag(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ht(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ext(struct ieee80211vap *, int flag);

View File

@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <net/if.h>
@ -487,7 +486,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
memset(&ic->ic_channels[ic->ic_nchans], 0,
(IEEE80211_CHAN_MAX - ic->ic_nchans) *
sizeof(struct ieee80211_channel));
ieee80211_media_init(ic);
ieee80211_chan_init(ic);
/*
* Invalidate channel-related state.

View File

@ -1706,26 +1706,6 @@ static const struct ieee80211_scanner adhoc_default = {
IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
static void
ap_force_promisc(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
IEEE80211_LOCK(ic);
/* set interface into promiscuous mode */
ifp->if_flags |= IFF_PROMISC;
ieee80211_runtask(ic, &ic->ic_promisc_task);
IEEE80211_UNLOCK(ic);
}
static void
ap_reset_promisc(struct ieee80211com *ic)
{
IEEE80211_LOCK(ic);
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
IEEE80211_UNLOCK(ic);
}
static int
ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
@ -1741,7 +1721,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
st->st_scangen++;
st->st_newscan = 1;
ap_force_promisc(vap->iv_ic);
ieee80211_promisc(vap, true);
return 0;
}
@ -1751,7 +1731,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
static int
ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
ap_reset_promisc(vap->iv_ic);
ieee80211_promisc(vap, false);
return 0;
}
@ -1825,7 +1805,7 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
return 0;
}
}
ap_reset_promisc(ic);
ieee80211_promisc(vap, false);
if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) {
/*
* Manual/background scan, don't select+join the

View File

@ -116,16 +116,15 @@ struct ieee80211_superg;
struct ieee80211_frame;
struct ieee80211com {
struct ifnet *ic_ifp; /* associated device */
void *ic_softc; /* driver softc */
const char *ic_name; /* usually device name */
ieee80211_com_lock_t ic_comlock; /* state update lock */
ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */
LIST_ENTRY(ieee80211com) ic_next; /* on global list */
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
int ic_headroom; /* driver tx headroom needs */
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
enum ieee80211_opmode ic_opmode; /* operation mode */
struct ifmedia ic_media; /* interface media config */
struct callout ic_inact; /* inactivity processing */
struct taskqueue *ic_tq; /* deferred state thread */
struct task ic_parent_task; /* deferred parent processing */
@ -151,6 +150,7 @@ struct ieee80211com {
uint8_t ic_allmulti; /* vap's needing all multicast*/
uint8_t ic_nrunning; /* vap's marked running */
uint8_t ic_curmode; /* current mode */
uint8_t ic_macaddr[IEEE80211_ADDR_LEN];
uint16_t ic_bintval; /* beacon interval */
uint16_t ic_lintval; /* listen interval */
uint16_t ic_holdover; /* PM hold over duration */
@ -241,6 +241,11 @@ struct ieee80211com {
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
void (*ic_vap_delete)(struct ieee80211vap *);
/* device specific ioctls */
int (*ic_ioctl)(struct ieee80211com *,
u_long, void *);
/* start/stop device */
void (*ic_parent)(struct ieee80211com *);
/* operating mode attachment */
ieee80211vap_attach ic_vattach[IEEE80211_OPMODE_MAX];
/* return hardware/radio capabilities */
@ -254,6 +259,9 @@ struct ieee80211com {
int (*ic_set_quiet)(struct ieee80211_node *,
u_int8_t *quiet_elm);
/* regular transmit */
int (*ic_transmit)(struct ieee80211com *,
struct mbuf *);
/* send/recv 802.11 management frame */
int (*ic_send_mgmt)(struct ieee80211_node *,
int, int);
@ -351,14 +359,15 @@ struct ieee80211vap {
TAILQ_ENTRY(ieee80211vap) iv_next; /* list of vap instances */
struct ieee80211com *iv_ic; /* back ptr to common state */
const uint8_t *iv_myaddr; /* MAC address: ifp or ic */
uint32_t iv_debug; /* debug msg flags */
struct ieee80211_stats iv_stats; /* statistics */
uint8_t iv_myaddr[IEEE80211_ADDR_LEN];
uint32_t iv_flags; /* state flags */
uint32_t iv_flags_ext; /* extended state flags */
uint32_t iv_flags_ht; /* HT state flags */
uint32_t iv_flags_ven; /* vendor state flags */
uint32_t iv_ifflags; /* ifnet flags */
uint32_t iv_caps; /* capabilities */
uint32_t iv_htcaps; /* HT capabilities */
uint32_t iv_htextcaps; /* HT extended capabilities */
@ -681,24 +690,24 @@ MALLOC_DECLARE(M_80211_VAP);
"\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
void ieee80211_ifattach(struct ieee80211com *,
const uint8_t macaddr[IEEE80211_ADDR_LEN]);
void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);
int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
const char name[IFNAMSIZ], int unit,
enum ieee80211_opmode opmode, int flags,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t macaddr[IEEE80211_ADDR_LEN]);
const uint8_t bssid[IEEE80211_ADDR_LEN]);
int ieee80211_vap_attach(struct ieee80211vap *,
ifm_change_cb_t, ifm_stat_cb_t);
ifm_change_cb_t, ifm_stat_cb_t,
const uint8_t macaddr[IEEE80211_ADDR_LEN]);
void ieee80211_vap_detach(struct ieee80211vap *);
const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic,
const struct ieee80211_channel *);
void ieee80211_announce(struct ieee80211com *);
void ieee80211_announce_channels(struct ieee80211com *);
void ieee80211_drain(struct ieee80211com *);
void ieee80211_media_init(struct ieee80211com *);
void ieee80211_chan_init(struct ieee80211com *);
struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
struct ieee80211com *ieee80211_find_com(const char *name);
int ieee80211_media_change(struct ifnet *);
void ieee80211_media_status(struct ifnet *, struct ifmediareq *);
int ieee80211_ioctl(struct ifnet *, u_long, caddr_t);

View File

@ -50,7 +50,7 @@
#include "iwnstats.h"
#include "iwn_ioctl.h"
#define IWN_DEFAULT_IF "iwn0"
#define IWN_DEFAULT_IF "wlan0"
static struct iwnstats *
iwnstats_new(const char *ifname)
@ -290,19 +290,6 @@ main(int argc, char *argv[])
if (ifname)
free(ifname);
ifname = strdup(optarg);
if (strncmp(ifname, "wlan", 4) == 0) {
free(ifname);
len = 0;
asprintf(&sysctlname, "net.wlan.%s.%%parent", ifname + 4);
ret = sysctlbyname(sysctlname, NULL, &len, NULL, 0);
if (ret != 0)
err(1, "sysctl failed");
ifname = calloc(len, 1);
ret = sysctlbyname(sysctlname, ifname, &len, NULL, 0);
if (ret != 0)
err(1, "sysctl failed");
free(sysctlname);
}
break;
default:
case '?':