Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/malo/if_malo.c
Context not available. | |||||
(IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)) | (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)) | ||||
#define IFF_DUMPPKTS_RECV(sc, wh) \ | #define IFF_DUMPPKTS_RECV(sc, wh) \ | ||||
(((sc->malo_debug & MALO_DEBUG_RECV) && \ | (((sc->malo_debug & MALO_DEBUG_RECV) && \ | ||||
((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \ | ((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh)))) | ||||
(sc->malo_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == \ | |||||
(IFF_DEBUG|IFF_LINK2)) | |||||
#define IFF_DUMPPKTS_XMIT(sc) \ | #define IFF_DUMPPKTS_XMIT(sc) \ | ||||
((sc->malo_debug & MALO_DEBUG_XMIT) || \ | (sc->malo_debug & MALO_DEBUG_XMIT) | ||||
(sc->malo_ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == \ | |||||
(IFF_DEBUG | IFF_LINK2)) | |||||
#define DPRINTF(sc, m, fmt, ...) do { \ | #define DPRINTF(sc, m, fmt, ...) do { \ | ||||
if (sc->malo_debug & (m)) \ | if (sc->malo_debug & (m)) \ | ||||
printf(fmt, __VA_ARGS__); \ | printf(fmt, __VA_ARGS__); \ | ||||
Context not available. | |||||
static int malo_setup_hwdma(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_txq_init(struct malo_softc *, struct malo_txq *, int); | ||||
static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *); | 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 void malo_watchdog(void *); | ||||
static int malo_ioctl(struct ifnet *, u_long, caddr_t); | |||||
static void malo_updateslot(struct ieee80211com *); | static void malo_updateslot(struct ieee80211com *); | ||||
static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int); | static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int); | ||||
static void malo_scan_start(struct ieee80211com *); | static void malo_scan_start(struct ieee80211com *); | ||||
Context not available. | |||||
static void malo_sysctlattach(struct malo_softc *); | static void malo_sysctlattach(struct malo_softc *); | ||||
static void malo_announce(struct malo_softc *); | static void malo_announce(struct malo_softc *); | ||||
static void malo_dma_cleanup(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_chan_set(struct malo_softc *, struct ieee80211_channel *); | ||||
static int malo_mode_init(struct malo_softc *); | static int malo_mode_init(struct malo_softc *); | ||||
static void malo_tx_proc(void *, int); | static void malo_tx_proc(void *, int); | ||||
Context not available. | |||||
int | int | ||||
malo_attach(uint16_t devid, struct malo_softc *sc) | malo_attach(uint16_t devid, struct malo_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = &sc->malo_ic; | |||||
struct malo_hal *mh; | |||||
int error; | int error; | ||||
struct ieee80211com *ic; | |||||
struct ifnet *ifp; | |||||
struct malo_hal *mh; | |||||
uint8_t bands; | 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); | MALO_LOCK_INIT(sc); | ||||
callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0); | callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0); | ||||
mbufq_init(&sc->malo_snd, ifqmaxlen); | |||||
/* set these up early for if_printf use */ | |||||
if_initname(ifp, device_get_name(sc->malo_dev), | |||||
device_get_unit(sc->malo_dev)); | |||||
mh = malo_hal_attach(sc->malo_dev, devid, | mh = malo_hal_attach(sc->malo_dev, devid, | ||||
sc->malo_io1h, sc->malo_io1t, sc->malo_dmat); | sc->malo_io1h, sc->malo_io1t, sc->malo_dmat); | ||||
if (mh == NULL) { | if (mh == NULL) { | ||||
if_printf(ifp, "unable to attach HAL\n"); | device_printf(sc->malo_dev, "unable to attach HAL\n"); | ||||
error = EIO; | error = EIO; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m"); | error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m"); | ||||
if (error != 0) { | if (error != 0) { | ||||
if_printf(ifp, "unable to setup firmware\n"); | device_printf(sc->malo_dev, "unable to setup firmware\n"); | ||||
goto bad1; | goto bad1; | ||||
} | } | ||||
/* XXX gethwspecs() extracts correct informations? not maybe! */ | /* XXX gethwspecs() extracts correct informations? not maybe! */ | ||||
error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs); | error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs); | ||||
if (error != 0) { | 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; | goto bad1; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
error = malo_dma_setup(sc); | error = malo_dma_setup(sc); | ||||
if (error != 0) { | 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; | goto bad1; | ||||
} | } | ||||
error = malo_setup_hwdma(sc); /* push to firmware */ | error = malo_setup_hwdma(sc); /* push to firmware */ | ||||
Context not available. | |||||
sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT, | sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT, | ||||
taskqueue_thread_enqueue, &sc->malo_tq); | taskqueue_thread_enqueue, &sc->malo_tq); | ||||
taskqueue_start_threads(&sc->malo_tq, 1, PI_NET, | 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_rxtask, 0, malo_rx_proc, sc); | ||||
TASK_INIT(&sc->malo_txtask, 0, malo_tx_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_softc = sc; | ||||
ic->ic_name = device_get_nameunit(sc->malo_dev); | ic->ic_name = device_get_nameunit(sc->malo_dev); | ||||
/* XXX not right but it's not used anywhere important */ | /* XXX not right but it's not used anywhere important */ | ||||
Context not available. | |||||
| IEEE80211_C_TXPMGT /* capable of txpow mgt */ | | IEEE80211_C_TXPMGT /* capable of txpow mgt */ | ||||
| IEEE80211_C_WPA /* capable of WPA1+WPA2 */ | | 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 | * Transmit requires space in the packet for a special format transmit | ||||
Context not available. | |||||
sizeof(struct ieee80211_frame); | sizeof(struct ieee80211_frame); | ||||
/* call MI attach routine. */ | /* call MI attach routine. */ | ||||
ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr); | ieee80211_ifattach(ic); | ||||
/* override default methods */ | /* override default methods */ | ||||
ic->ic_vap_create = malo_vap_create; | ic->ic_vap_create = malo_vap_create; | ||||
ic->ic_vap_delete = malo_vap_delete; | ic->ic_vap_delete = malo_vap_delete; | ||||
ic->ic_raw_xmit = malo_raw_xmit; | ic->ic_raw_xmit = malo_raw_xmit; | ||||
ic->ic_updateslot = malo_updateslot; | ic->ic_updateslot = malo_updateslot; | ||||
ic->ic_scan_start = malo_scan_start; | ic->ic_scan_start = malo_scan_start; | ||||
ic->ic_scan_end = malo_scan_end; | ic->ic_scan_end = malo_scan_end; | ||||
ic->ic_set_channel = malo_set_channel; | 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 */ | sc->malo_invalid = 0; /* ready to go, enable int handling */ | ||||
Context not available. | |||||
bad1: | bad1: | ||||
malo_hal_detach(mh); | malo_hal_detach(mh); | ||||
bad: | bad: | ||||
if_free(ifp); | |||||
sc->malo_invalid = 1; | sc->malo_invalid = 1; | ||||
return error; | return error; | ||||
Context not available. | |||||
const uint8_t bssid[IEEE80211_ADDR_LEN], | const uint8_t bssid[IEEE80211_ADDR_LEN], | ||||
const uint8_t mac[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 malo_vap *mvp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) { | 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; | return NULL; | ||||
} | } | ||||
switch (opmode) { | switch (opmode) { | ||||
Context not available. | |||||
case IEEE80211_M_MONITOR: | case IEEE80211_M_MONITOR: | ||||
break; | break; | ||||
default: | default: | ||||
if_printf(ifp, "%s mode not supported\n", | device_printf(sc->malo_dev, "%s mode not supported\n", | ||||
ieee80211_opmode_name[opmode]); | ieee80211_opmode_name[opmode]); | ||||
return NULL; /* unsupported */ | return NULL; /* unsupported */ | ||||
} | } | ||||
mvp = (struct malo_vap *) malloc(sizeof(struct malo_vap), | mvp = malloc(sizeof(struct malo_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_NOWAIT | M_ZERO); | |||||
if (mvp == NULL) { | |||||
if_printf(ifp, "cannot allocate vap state block\n"); | |||||
return NULL; | |||||
} | |||||
vap = &mvp->malo_vap; | 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 */ | /* override state transition machine */ | ||||
mvp->malo_newstate = vap->iv_newstate; | mvp->malo_newstate = vap->iv_newstate; | ||||
Context not available. | |||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, | ieee80211_vap_attach(vap, | ||||
ieee80211_media_change, ieee80211_media_status); | ieee80211_media_change, ieee80211_media_status, mac); | ||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
return vap; | return vap; | ||||
} | } | ||||
Context not available. | |||||
int nbuf, size_t bufsize, int ndesc, size_t descsize) | int nbuf, size_t bufsize, int ndesc, size_t descsize) | ||||
{ | { | ||||
int error; | int error; | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
uint8_t *ds; | uint8_t *ds; | ||||
DPRINTF(sc, MALO_DEBUG_RESET, | DPRINTF(sc, MALO_DEBUG_RESET, | ||||
Context not available. | |||||
NULL, /* lockarg */ | NULL, /* lockarg */ | ||||
&dd->dd_dmat); | &dd->dd_dmat); | ||||
if (error != 0) { | 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; | return error; | ||||
} | } | ||||
Context not available. | |||||
error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc, | error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc, | ||||
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap); | BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap); | ||||
if (error != 0) { | 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); | "error %u\n", nbuf * ndesc, dd->dd_name, error); | ||||
goto fail1; | goto fail1; | ||||
} | } | ||||
Context not available. | |||||
dd->dd_desc, dd->dd_desc_len, | dd->dd_desc, dd->dd_desc_len, | ||||
malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT); | malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT); | ||||
if (error != 0) { | 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); | dd->dd_name, error); | ||||
goto fail2; | goto fail2; | ||||
} | } | ||||
Context not available. | |||||
static int | static int | ||||
malo_rxdma_setup(struct malo_softc *sc) | malo_rxdma_setup(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
int error, bsize, i; | int error, bsize, i; | ||||
struct malo_rxbuf *bf; | struct malo_rxbuf *bf; | ||||
struct malo_rxdesc *ds; | struct malo_rxdesc *ds; | ||||
Context not available. | |||||
bsize = malo_rxbuf * sizeof(struct malo_rxbuf); | bsize = malo_rxbuf * sizeof(struct malo_rxbuf); | ||||
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); | bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); | ||||
if (bf == NULL) { | 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; | return error; | ||||
} | } | ||||
sc->malo_rxdma.dd_bufptr = bf; | sc->malo_rxdma.dd_bufptr = bf; | ||||
Context not available. | |||||
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, | error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, | ||||
&bf->bf_dmamap); | &bf->bf_dmamap); | ||||
if (error != 0) { | if (error != 0) { | ||||
if_printf(ifp, "%s: unable to dmamap for rx buffer, " | device_printf(sc->malo_dev, | ||||
"error %d\n", __func__, error); | "%s: unable to dmamap for rx buffer, error %d\n", | ||||
__func__, error); | |||||
return error; | return error; | ||||
} | } | ||||
/* NB: tail is intentional to preserve descriptor order */ | /* NB: tail is intentional to preserve descriptor order */ | ||||
Context not available. | |||||
static int | static int | ||||
malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq) | malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
int error, bsize, i; | int error, bsize, i; | ||||
struct malo_txbuf *bf; | struct malo_txbuf *bf; | ||||
struct malo_txdesc *ds; | struct malo_txdesc *ds; | ||||
Context not available. | |||||
bsize = malo_txbuf * sizeof(struct malo_txbuf); | bsize = malo_txbuf * sizeof(struct malo_txbuf); | ||||
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); | bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); | ||||
if (bf == NULL) { | 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); | malo_txbuf); | ||||
return ENOMEM; | return ENOMEM; | ||||
} | } | ||||
Context not available. | |||||
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, | error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, | ||||
&bf->bf_dmamap); | &bf->bf_dmamap); | ||||
if (error != 0) { | 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); | "buffer %u, error %u\n", i, error); | ||||
return error; | return error; | ||||
} | } | ||||
Context not available. | |||||
if (status & MALO_TXD_STATUS_FAILED_AGING) | if (status & MALO_TXD_STATUS_FAILED_AGING) | ||||
sc->malo_stats.mst_tx_aging++; | sc->malo_stats.mst_tx_aging++; | ||||
} | } | ||||
/* | /* XXX strip fw len in case header inspected */ | ||||
* Do any tx complete callback. Note this must | m_adj(bf->bf_m, sizeof(uint16_t)); | ||||
* be done before releasing the node reference. | ieee80211_tx_complete(ni, bf->bf_m, | ||||
* XXX no way to figure out if frame was ACK'd | (status & MALO_TXD_STATUS_OK) == 0); | ||||
*/ | } else | ||||
if (bf->bf_m->m_flags & M_TXCB) { | m_freem(bf->bf_m); | ||||
/* 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); | |||||
} | |||||
ds->status = htole32(MALO_TXD_STATUS_IDLE); | ds->status = htole32(MALO_TXD_STATUS_IDLE); | ||||
ds->pktlen = htole32(0); | ds->pktlen = htole32(0); | ||||
Context not available. | |||||
bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap, | bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap, | ||||
BUS_DMASYNC_POSTWRITE); | BUS_DMASYNC_POSTWRITE); | ||||
bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap); | bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap); | ||||
m_freem(bf->bf_m); | |||||
bf->bf_m = NULL; | bf->bf_m = NULL; | ||||
bf->bf_node = NULL; | bf->bf_node = NULL; | ||||
Context not available. | |||||
malo_tx_proc(void *arg, int npending) | malo_tx_proc(void *arg, int npending) | ||||
{ | { | ||||
struct malo_softc *sc = arg; | struct malo_softc *sc = arg; | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
int i, nreaped; | int i, nreaped; | ||||
/* | /* | ||||
Context not available. | |||||
* Process each active queue. | * Process each active queue. | ||||
*/ | */ | ||||
nreaped = 0; | nreaped = 0; | ||||
MALO_LOCK(sc); | |||||
for (i = 0; i < MALO_NUM_TX_QUEUES; i++) { | for (i = 0; i < MALO_NUM_TX_QUEUES; i++) { | ||||
if (!STAILQ_EMPTY(&sc->malo_txq[i].active)) | if (!STAILQ_EMPTY(&sc->malo_txq[i].active)) | ||||
nreaped += malo_tx_processq(sc, &sc->malo_txq[i]); | nreaped += malo_tx_processq(sc, &sc->malo_txq[i]); | ||||
Context not available. | |||||
} | } | ||||
if (nreaped != 0) { | if (nreaped != 0) { | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
sc->malo_timer = 0; | sc->malo_timer = 0; | ||||
malo_start(ifp); | malo_start(sc); | ||||
} | } | ||||
MALO_UNLOCK(sc); | |||||
} | } | ||||
static int | static int | ||||
Context not available. | |||||
int error, ismcast, iswep; | int error, ismcast, iswep; | ||||
int copyhdrlen, hdrlen, pktlen; | int copyhdrlen, hdrlen, pktlen; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct malo_txdesc *ds; | struct malo_txdesc *ds; | ||||
struct malo_txrec *tr; | struct malo_txrec *tr; | ||||
Context not available. | |||||
ds->txpriority = txq->qnum; | ds->txpriority = txq->qnum; | ||||
break; | break; | ||||
default: | 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__); | wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); | ||||
/* XXX statistic */ | /* XXX statistic */ | ||||
m_freem(m0); | m_freem(m0); | ||||
Context not available. | |||||
STAILQ_INSERT_TAIL(&txq->active, bf, bf_list); | STAILQ_INSERT_TAIL(&txq->active, bf, bf_list); | ||||
MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
sc->malo_timer = 5; | sc->malo_timer = 5; | ||||
MALO_TXQ_UNLOCK(txq); | MALO_TXQ_UNLOCK(txq); | ||||
return 0; | return 0; | ||||
Context not available. | |||||
#undef IEEE80211_DIR_DSTODS | #undef IEEE80211_DIR_DSTODS | ||||
} | } | ||||
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 | static void | ||||
malo_start(struct ifnet *ifp) | malo_start(struct malo_softc *sc) | ||||
{ | { | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct malo_txq *txq = &sc->malo_txq[0]; | struct malo_txq *txq = &sc->malo_txq[0]; | ||||
struct malo_txbuf *bf = NULL; | struct malo_txbuf *bf = NULL; | ||||
Context not available. | |||||
struct mbuf *m; | struct mbuf *m; | ||||
int nqueued = 0; | 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; | return; | ||||
for (;;) { | while ((m = mbufq_dequeue(&sc->malo_snd)) != NULL) { | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | |||||
if (m == NULL) | |||||
break; | |||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ||||
bf = malo_getbuf(sc, txq); | bf = malo_getbuf(sc, txq); | ||||
if (bf == NULL) { | if (bf == NULL) { | ||||
IFQ_DRV_PREPEND(&ifp->if_snd, m); | mbufq_prepend(&sc->malo_snd, m); | ||||
/* XXX blocks other traffic */ | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
sc->malo_stats.mst_tx_qstop++; | sc->malo_stats.mst_tx_qstop++; | ||||
break; | break; | ||||
} | } | ||||
Context not available. | |||||
* Pass the frame to the h/w for transmission. | * Pass the frame to the h/w for transmission. | ||||
*/ | */ | ||||
if (malo_tx_start(sc, ni, bf, m)) { | 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) { | if (bf != NULL) { | ||||
bf->bf_m = NULL; | bf->bf_m = NULL; | ||||
bf->bf_node = NULL; | bf->bf_node = NULL; | ||||
Context not available. | |||||
static void | static void | ||||
malo_watchdog(void *arg) | malo_watchdog(void *arg) | ||||
{ | { | ||||
struct malo_softc *sc; | struct malo_softc *sc = arg; | ||||
struct ifnet *ifp; | |||||
sc = arg; | |||||
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); | callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); | ||||
if (sc->malo_timer == 0 || --sc->malo_timer > 0) | if (sc->malo_timer == 0 || --sc->malo_timer > 0) | ||||
return; | return; | ||||
ifp = sc->malo_ifp; | if (sc->malo_running && !sc->malo_invalid) { | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) { | device_printf(sc->malo_dev, "watchdog timeout\n"); | ||||
if_printf(ifp, "watchdog timeout\n"); | |||||
/* XXX no way to reset h/w. now */ | /* 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++; | sc->malo_stats.mst_watchdog++; | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
malo_hal_reset(struct malo_softc *sc) | malo_hal_reset(struct malo_softc *sc) | ||||
{ | { | ||||
static int first = 0; | static int first = 0; | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct malo_hal *mh = sc->malo_mh; | struct malo_hal *mh = sc->malo_mh; | ||||
if (first == 0) { | if (first == 0) { | ||||
Context not available. | |||||
mtod(m, caddr_t), MJUMPAGESIZE, | mtod(m, caddr_t), MJUMPAGESIZE, | ||||
malo_load_cb, &paddr, BUS_DMA_NOWAIT); | malo_load_cb, &paddr, BUS_DMA_NOWAIT); | ||||
if (error != 0) { | if (error != 0) { | ||||
if_printf(sc->malo_ifp, | device_printf(sc->malo_dev, | ||||
"%s: bus_dmamap_load failed, error %d\n", __func__, error); | "%s: bus_dmamap_load failed, error %d\n", __func__, error); | ||||
m_freem(m); | m_freem(m); | ||||
return NULL; | return NULL; | ||||
Context not available. | |||||
static void | static void | ||||
malo_init_locked(struct malo_softc *sc) | malo_init_locked(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
struct malo_hal *mh = sc->malo_mh; | struct malo_hal *mh = sc->malo_mh; | ||||
int error; | int error; | ||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n", | |||||
__func__, ifp->if_flags); | |||||
MALO_LOCK_ASSERT(sc); | MALO_LOCK_ASSERT(sc); | ||||
/* | /* | ||||
Context not available. | |||||
* Stop anything previously setup. This is safe whether this is | * Stop anything previously setup. This is safe whether this is | ||||
* the first time through or not. | * the first time through or not. | ||||
*/ | */ | ||||
malo_stop_locked(ifp, 0); | malo_stop(sc); | ||||
/* | /* | ||||
* Push state to the firmware. | * Push state to the firmware. | ||||
*/ | */ | ||||
if (!malo_hal_reset(sc)) { | 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; | return; | ||||
} | } | ||||
Context not available. | |||||
*/ | */ | ||||
error = malo_startrecv(sc); | error = malo_startrecv(sc); | ||||
if (error != 0) { | 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); | __func__, error); | ||||
return; | return; | ||||
} | } | ||||
Context not available. | |||||
| MALO_A2HRIC_BIT_RADAR_DETECT | | MALO_A2HRIC_BIT_RADAR_DETECT | ||||
| MALO_A2HRIC_BIT_CHAN_SWITCH; | | MALO_A2HRIC_BIT_CHAN_SWITCH; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | sc->malo_running = 1; | ||||
malo_hal_intrset(mh, sc->malo_imask); | malo_hal_intrset(mh, sc->malo_imask); | ||||
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); | callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); | ||||
} | } | ||||
Context not available. | |||||
malo_init(void *arg) | malo_init(void *arg) | ||||
{ | { | ||||
struct malo_softc *sc = (struct malo_softc *) arg; | struct malo_softc *sc = (struct malo_softc *) arg; | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n", | |||||
__func__, ifp->if_flags); | |||||
MALO_LOCK(sc); | MALO_LOCK(sc); | ||||
malo_init_locked(sc); | malo_init_locked(sc); | ||||
MALO_UNLOCK(sc); | MALO_UNLOCK(sc); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->malo_running) | ||||
ieee80211_start_all(ic); /* start all vap's */ | ieee80211_start_all(ic); /* start all vap's */ | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
malo_setmcastfilter(struct malo_softc *sc) | malo_setmcastfilter(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ieee80211vap *vap; | ||||
struct ifmultiaddr *ifma; | |||||
uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX]; | uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX]; | ||||
uint8_t *mp; | uint8_t *mp; | ||||
int nmc; | int nmc; | ||||
Context not available. | |||||
mp = macs; | mp = macs; | ||||
nmc = 0; | nmc = 0; | ||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || | if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 || | ||||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) | ic->ic_promisc > 0) | ||||
goto all; | 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) { | TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { | ||||
ifp->if_flags |= IFF_ALLMULTI; | struct ifnet *ifp; | ||||
if_maddr_runlock(ifp); | struct ifmultiaddr *ifma; | ||||
goto all; | |||||
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, | if_maddr_runlock(ifp); | ||||
LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); | |||||
mp += IEEE80211_ADDR_LEN, nmc++; | |||||
} | } | ||||
if_maddr_runlock(ifp); | |||||
malo_hal_setmcast(sc->malo_mh, nmc, macs); | malo_hal_setmcast(sc->malo_mh, nmc, macs); | ||||
Context not available. | |||||
static int | static int | ||||
malo_mode_init(struct malo_softc *sc) | malo_mode_init(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct malo_hal *mh = sc->malo_mh; | struct malo_hal *mh = sc->malo_mh; | ||||
/* | /* | ||||
Context not available. | |||||
* identify internal requests (from the bridge) | * identify internal requests (from the bridge) | ||||
* versus external requests such as for tcpdump. | * 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); | ic->ic_opmode != IEEE80211_M_HOSTAP); | ||||
malo_setmcastfilter(sc); | malo_setmcastfilter(sc); | ||||
Context not available. | |||||
MALO_TXQ_UNLOCK(txq); | MALO_TXQ_UNLOCK(txq); | ||||
#ifdef MALO_DEBUG | #ifdef MALO_DEBUG | ||||
if (sc->malo_debug & MALO_DEBUG_RESET) { | if (sc->malo_debug & MALO_DEBUG_RESET) { | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
const struct malo_txrec *tr = | const struct malo_txrec *tr = | ||||
mtod(bf->bf_m, const struct malo_txrec *); | mtod(bf->bf_m, const struct malo_txrec *); | ||||
malo_printtxbuf(bf, txq->qnum, ix); | malo_printtxbuf(bf, txq->qnum, ix); | ||||
Context not available. | |||||
} | } | ||||
static void | 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; | struct malo_hal *mh = sc->malo_mh; | ||||
int i; | int i; | ||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n", | DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u running %u\n", | ||||
__func__, sc->malo_invalid, ifp->if_flags); | __func__, sc->malo_invalid, sc->malo_running); | ||||
MALO_LOCK_ASSERT(sc); | MALO_LOCK_ASSERT(sc); | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) | if (!sc->malo_running) | ||||
return; | return; | ||||
/* | /* | ||||
Context not available. | |||||
* Note that some of this work is not possible if the hardware | * Note that some of this work is not possible if the hardware | ||||
* is gone (invalid). | * is gone (invalid). | ||||
*/ | */ | ||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; | sc->malo_running = 0; | ||||
callout_stop(&sc->malo_watchdog_timer); | callout_stop(&sc->malo_watchdog_timer); | ||||
sc->malo_timer = 0; | sc->malo_timer = 0; | ||||
/* diable interrupt. */ | /* disable interrupt. */ | ||||
malo_hal_intrset(mh, 0); | malo_hal_intrset(mh, 0); | ||||
/* turn off the radio. */ | /* turn off the radio. */ | ||||
malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE); | malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE); | ||||
Context not available. | |||||
malo_tx_draintxq(sc, &sc->malo_txq[i]); | malo_tx_draintxq(sc, &sc->malo_txq[i]); | ||||
} | } | ||||
static int | static void | ||||
malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | malo_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
#define MALO_IS_RUNNING(ifp) \ | struct malo_softc *sc = ic->ic_softc; | ||||
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) | int startall = 0; | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ifreq *ifr = (struct ifreq *) data; | |||||
int error = 0, startall = 0; | |||||
MALO_LOCK(sc); | MALO_LOCK(sc); | ||||
switch (cmd) { | if (ic->ic_nrunning > 0) { | ||||
case SIOCSIFFLAGS: | /* | ||||
if (MALO_IS_RUNNING(ifp)) { | * Beware of being called during attach/detach | ||||
/* | * to reset promiscuous mode. In that case we | ||||
* To avoid rescanning another access point, | * will still be marked UP but not RUNNING. | ||||
* do not call malo_init() here. Instead, | * However trying to re-init the interface | ||||
* only reflect promisc mode settings. | * is the wrong thing to do as we've already | ||||
*/ | * torn down much of our state. There's | ||||
malo_mode_init(sc); | * probably a better way to deal with this. | ||||
} else if (ifp->if_flags & IFF_UP) { | */ | ||||
/* | if (!sc->malo_running && !sc->malo_invalid) { | ||||
* Beware of being called during attach/detach | malo_init(sc); | ||||
* to reset promiscuous mode. In that case we | startall = 1; | ||||
* 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 | * To avoid rescanning another access point, | ||||
* torn down much of our state. There's | * do not call malo_init() here. Instead, | ||||
* probably a better way to deal with this. | * only reflect promisc mode settings. | ||||
*/ | */ | ||||
if (!sc->malo_invalid) { | malo_mode_init(sc); | ||||
malo_init_locked(sc); | } else if (sc->malo_running) | ||||
startall = 1; | malo_stop(sc); | ||||
} | |||||
} 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; | |||||
} | |||||
MALO_UNLOCK(sc); | MALO_UNLOCK(sc); | ||||
if (startall) | if (startall) | ||||
ieee80211_start_all(ic); | ieee80211_start_all(ic); | ||||
return error; | |||||
#undef MALO_IS_RUNNING | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
int error; | int error; | ||||
/* NB: can be called early; suppress needless cmds */ | /* NB: can be called early; suppress needless cmds */ | ||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | if (!sc->malo_running) | ||||
return; | return; | ||||
DPRINTF(sc, MALO_DEBUG_RESET, | DPRINTF(sc, MALO_DEBUG_RESET, | ||||
Context not available. | |||||
malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) | ||||
{ | { | ||||
struct ieee80211com *ic = vap->iv_ic; | 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; | struct malo_hal *mh = sc->malo_mh; | ||||
int error; | int error; | ||||
Context not available. | |||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct malo_softc *sc = ic->ic_softc; | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
struct malo_txbuf *bf; | struct malo_txbuf *bf; | ||||
struct malo_txq *txq; | 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); | ieee80211_free_node(ni); | ||||
m_freem(m); | m_freem(m); | ||||
return ENETDOWN; | return ENETDOWN; | ||||
Context not available. | |||||
txq = &sc->malo_txq[0]; | txq = &sc->malo_txq[0]; | ||||
bf = malo_getbuf(sc, txq); | bf = malo_getbuf(sc, txq); | ||||
if (bf == NULL) { | if (bf == NULL) { | ||||
/* XXX blocks other traffic */ | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
m_freem(m); | m_freem(m); | ||||
return ENOBUFS; | return ENOBUFS; | ||||
Context not available. | |||||
* Pass the frame to the h/w for transmission. | * Pass the frame to the h/w for transmission. | ||||
*/ | */ | ||||
if (malo_tx_start(sc, ni, bf, m) != 0) { | if (malo_tx_start(sc, ni, bf, m) != 0) { | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
bf->bf_m = NULL; | bf->bf_m = NULL; | ||||
bf->bf_node = NULL; | bf->bf_node = NULL; | ||||
MALO_TXQ_LOCK(txq); | MALO_TXQ_LOCK(txq); | ||||
Context not available. | |||||
static void | static void | ||||
malo_announce(struct malo_softc *sc) | 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.hwversion, | ||||
(sc->malo_hwspecs.fw_releasenum >> 24) & 0xff, | (sc->malo_hwspecs.fw_releasenum >> 24) & 0xff, | ||||
(sc->malo_hwspecs.fw_releasenum >> 16) & 0xff, | (sc->malo_hwspecs.fw_releasenum >> 16) & 0xff, | ||||
Context not available. | |||||
sc->malo_hwspecs.regioncode); | sc->malo_hwspecs.regioncode); | ||||
if (bootverbose || malo_rxbuf != MALO_RXBUF) | 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 (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); | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
static void | static void | ||||
malo_scan_start(struct ieee80211com *ic) | malo_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct malo_softc *sc = ic->ic_softc; | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); | DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
malo_scan_end(struct ieee80211com *ic) | malo_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct malo_softc *sc = ic->ic_softc; | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); | DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
malo_set_channel(struct ieee80211com *ic) | malo_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct malo_softc *sc = ic->ic_softc; | ||||
struct malo_softc *sc = ifp->if_softc; | |||||
(void) malo_chan_set(sc, ic->ic_curchan); | (void) malo_chan_set(sc, ic->ic_curchan); | ||||
} | } | ||||
Context not available. | |||||
((((const struct ieee80211_frame *)wh)->i_fc[1] & \ | ((((const struct ieee80211_frame *)wh)->i_fc[1] & \ | ||||
IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) | IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) | ||||
struct malo_softc *sc = arg; | struct malo_softc *sc = arg; | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct malo_rxbuf *bf; | struct malo_rxbuf *bf; | ||||
struct malo_rxdesc *ds; | struct malo_rxdesc *ds; | ||||
struct mbuf *m, *mnew; | struct mbuf *m, *mnew; | ||||
Context not available. | |||||
#endif | #endif | ||||
status = ds->status; | status = ds->status; | ||||
if (status & MALO_RXD_STATUS_DECRYPT_ERR_MASK) { | 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; | goto rx_next; | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
/* XXX don't need mbuf, just dma buffer */ | /* XXX don't need mbuf, just dma buffer */ | ||||
mnew = malo_getrxmbuf(sc, bf); | mnew = malo_getrxmbuf(sc, bf); | ||||
if (mnew == NULL) { | if (mnew == NULL) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto rx_next; | goto rx_next; | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
bf->bf_m = mnew; | bf->bf_m = mnew; | ||||
m->m_data += off - hdrlen; | m->m_data += off - hdrlen; | ||||
m->m_pkthdr.len = m->m_len = pktlen; | m->m_pkthdr.len = m->m_len = pktlen; | ||||
m->m_pkthdr.rcvif = ifp; | |||||
/* | /* | ||||
* Piece 802.11 header together. | * Piece 802.11 header together. | ||||
Context not available. | |||||
len, ds->rate, rssi); | len, ds->rate, rssi); | ||||
} | } | ||||
#endif | #endif | ||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | |||||
/* dispatch */ | /* dispatch */ | ||||
ni = ieee80211_find_rxnode(ic, | ni = ieee80211_find_rxnode(ic, | ||||
(struct ieee80211_frame_min *)wh); | (struct ieee80211_frame_min *)wh); | ||||
Context not available. | |||||
malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr); | malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr); | ||||
sc->malo_rxnext = bf; | sc->malo_rxnext = bf; | ||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && | if (mbufq_first(&sc->malo_snd) != NULL) | ||||
!IFQ_IS_EMPTY(&ifp->if_snd)) | malo_start(sc); | ||||
malo_start(ifp); | |||||
#undef IEEE80211_DIR_DSTODS | #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. | * Reclaim all tx queue resources. | ||||
*/ | */ | ||||
Context not available. | |||||
int | int | ||||
malo_detach(struct malo_softc *sc) | malo_detach(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | struct ieee80211com *ic = &sc->malo_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", | malo_stop(sc); | ||||
__func__, ifp->if_flags); | |||||
malo_stop(ifp, 1); | |||||
if (sc->malo_tq != NULL) { | if (sc->malo_tq != NULL) { | ||||
taskqueue_drain(sc->malo_tq, &sc->malo_rxtask); | taskqueue_drain(sc->malo_tq, &sc->malo_rxtask); | ||||
taskqueue_drain(sc->malo_tq, &sc->malo_txtask); | taskqueue_drain(sc->malo_tq, &sc->malo_txtask); | ||||
Context not available. | |||||
malo_dma_cleanup(sc); | malo_dma_cleanup(sc); | ||||
malo_tx_cleanup(sc); | malo_tx_cleanup(sc); | ||||
malo_hal_detach(sc->malo_mh); | malo_hal_detach(sc->malo_mh); | ||||
if_free(ifp); | mbufq_drain(&sc->malo_snd); | ||||
MALO_LOCK_DESTROY(sc); | MALO_LOCK_DESTROY(sc); | ||||
return 0; | return 0; | ||||
Context not available. | |||||
void | void | ||||
malo_shutdown(struct malo_softc *sc) | malo_shutdown(struct malo_softc *sc) | ||||
{ | { | ||||
malo_stop(sc->malo_ifp, 1); | |||||
malo_stop(sc); | |||||
} | } | ||||
void | void | ||||
malo_suspend(struct malo_softc *sc) | malo_suspend(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", | malo_stop(sc); | ||||
__func__, ifp->if_flags); | |||||
malo_stop(ifp, 1); | |||||
} | } | ||||
void | void | ||||
malo_resume(struct malo_softc *sc) | malo_resume(struct malo_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->malo_ifp; | |||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", | if (sc->malo_ic.ic_nrunning > 0) | ||||
__func__, ifp->if_flags); | |||||
if (ifp->if_flags & IFF_UP) | |||||
malo_init(sc); | malo_init(sc); | ||||
} | } | ||||
Context not available. |