static void rtwn_cmdq_cb(void *arg, int pending) { struct rtwn_softc *sc = arg; struct rtwn_cmdq *item; /* * Device must be powered on (via rtwn_power_on()) * before any command may be sent. */ RTWN_LOCK(sc); if (!(sc->sc_flags & RTWN_RUNNING)) { RTWN_UNLOCK(sc); return; } RTWN_CMDQ_LOCK(sc); while (sc->cmdq[sc->cmdq_first].func != NULL) { item = &sc->cmdq[sc->cmdq_first]; sc->cmdq_first = (sc->cmdq_first + 1) % RTWN_CMDQ_SIZE; RTWN_CMDQ_UNLOCK(sc); item->func(sc, &item->data); RTWN_CMDQ_LOCK(sc); memset(item, 0, sizeof (*item)); } RTWN_CMDQ_UNLOCK(sc); RTWN_UNLOCK(sc); }
void r21a_parse_rom(struct rtwn_softc *sc, uint8_t *buf) { struct r12a_softc *rs = sc->sc_priv; struct r12a_rom *rom = (struct r12a_rom *)buf; uint8_t pa_type, lna_type_2g, lna_type_5g; /* Read PA/LNA types. */ pa_type = RTWN_GET_ROM_VAR(rom->pa_type, 0); lna_type_2g = RTWN_GET_ROM_VAR(rom->lna_type_2g, 0); lna_type_5g = RTWN_GET_ROM_VAR(rom->lna_type_5g, 0); rs->ext_pa_2g = R21A_ROM_IS_PA_EXT_2GHZ(pa_type); rs->ext_pa_5g = R21A_ROM_IS_PA_EXT_5GHZ(pa_type); rs->ext_lna_2g = R21A_ROM_IS_LNA_EXT(lna_type_2g); rs->ext_lna_5g = R21A_ROM_IS_LNA_EXT(lna_type_5g); RTWN_LOCK(sc); rs->bt_coex = !!(rtwn_read_4(sc, R92C_MULTI_FUNC_CTRL) & R92C_MULTI_BT_FUNC_EN); RTWN_UNLOCK(sc); rs->bt_ant_num = (rom->rf_bt_opt & R12A_RF_BT_OPT_ANT_NUM); /* Read MAC address. */ IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr_21a); /* Execute common part of initialization. */ r12a_parse_rom_common(sc, buf); }
void rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data) { struct ieee80211com *ic = &sc->sc_ic; RTWN_UNLOCK(sc); ieee80211_ff_flush_all(ic); RTWN_LOCK(sc); }
void r92c_scan_end(struct ieee80211com *ic) { struct rtwn_softc *sc = ic->ic_softc; struct r92c_softc *rs = sc->sc_priv; RTWN_LOCK(sc); /* Set gain under link. */ rtwn_r92c_set_gain(sc, 0x32); RTWN_UNLOCK(sc); rs->rs_scan_end(ic); }
void r92c_scan_start(struct ieee80211com *ic) { struct rtwn_softc *sc = ic->ic_softc; struct r92c_softc *rs = sc->sc_priv; RTWN_LOCK(sc); /* Set gain for scanning. */ rtwn_r92c_set_gain(sc, 0x20); RTWN_UNLOCK(sc); rs->rs_scan_start(ic); }
void r12a_vap_preattach(struct rtwn_softc *sc, struct ieee80211vap *vap) { struct r12a_softc *rs = sc->sc_priv; struct ifnet *ifp = vap->iv_ifp; ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6; RTWN_LOCK(sc); if (rs->rs_flags & R12A_RXCKSUM_EN) ifp->if_capenable |= IFCAP_RXCSUM; if (rs->rs_flags & R12A_RXCKSUM6_EN) ifp->if_capenable |= IFCAP_RXCSUM_IPV6; RTWN_UNLOCK(sc); }
static void rtwn_usb_abort_xfers(struct rtwn_softc *sc) { struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); int i; RTWN_ASSERT_LOCKED(sc); /* abort any pending transfers */ RTWN_UNLOCK(sc); for (i = 0; i < RTWN_N_TRANSFER; i++) usbd_transfer_drain(uc->uc_xfer[i]); RTWN_LOCK(sc); }
void rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct rtwn_usb_softc *uc = usbd_xfer_softc(xfer); struct rtwn_softc *sc = &uc->uc_sc; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct mbuf *m = NULL, *next; struct rtwn_data *data; int8_t nf, rssi; RTWN_ASSERT_LOCKED(sc); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: data = STAILQ_FIRST(&uc->uc_rx_active); if (data == NULL) goto tr_setup; STAILQ_REMOVE_HEAD(&uc->uc_rx_active, next); m = rtwn_report_intr(uc, xfer, data); STAILQ_INSERT_TAIL(&uc->uc_rx_inactive, data, next); /* FALLTHROUGH */ case USB_ST_SETUP: tr_setup: data = STAILQ_FIRST(&uc->uc_rx_inactive); if (data == NULL) { KASSERT(m == NULL, ("mbuf isn't NULL")); goto finish; } STAILQ_REMOVE_HEAD(&uc->uc_rx_inactive, next); STAILQ_INSERT_TAIL(&uc->uc_rx_active, data, next); usbd_xfer_set_frame_data(xfer, 0, data->buf, usbd_xfer_max_len(xfer)); usbd_transfer_submit(xfer); /* * To avoid LOR we should unlock our private mutex here to call * ieee80211_input() because here is at the end of a USB * callback and safe to unlock. */ while (m != NULL) { next = m->m_next; m->m_next = NULL; ni = rtwn_rx_frame(sc, m, &rssi); RTWN_UNLOCK(sc); nf = RTWN_NOISE_FLOOR; if (ni != NULL) { if (ni->ni_flags & IEEE80211_NODE_HT) m->m_flags |= M_AMPDU; (void)ieee80211_input(ni, m, rssi - nf, nf); ieee80211_free_node(ni); } else { (void)ieee80211_input_all(ic, m, rssi - nf, nf); } RTWN_LOCK(sc); m = next; } break; default: /* needs it to the inactive queue due to a error. */ data = STAILQ_FIRST(&uc->uc_rx_active); if (data != NULL) { STAILQ_REMOVE_HEAD(&uc->uc_rx_active, next); STAILQ_INSERT_TAIL(&uc->uc_rx_inactive, data, next); } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } break; } finish: /* Finished receive; age anything left on the FF queue by a little bump */ /* * XXX TODO: just make this a callout timer schedule so we can * flush the FF staging queue if we're approaching idle. */ #ifdef IEEE80211_SUPPORT_SUPERG if (!(sc->sc_flags & RTWN_FW_LOADED) || sc->sc_ratectl != RTWN_RATECTL_NET80211) rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); #endif /* Kick-start more transmit in case we stalled */ rtwn_start(sc); }