Beispiel #1
0
static struct mbuf *
rtwn_report_intr(struct rtwn_usb_softc *uc, struct usb_xfer *xfer,
    struct rtwn_data *data)
{
	struct rtwn_softc *sc = &uc->uc_sc;
	struct ieee80211com *ic = &sc->sc_ic;
	uint8_t *buf;
	int len;

	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);

	if (__predict_false(len < sizeof(struct r92c_rx_stat))) {
		counter_u64_add(ic->ic_ierrors, 1);
		return (NULL);
	}

	buf = data->buf;
	switch (rtwn_classify_intr(sc, buf, len)) {
	case RTWN_RX_DATA:
		return (rtwn_rxeof(sc, buf, len));
	case RTWN_RX_TX_REPORT:
		if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
			/* shouldn't happen */
			device_printf(sc->sc_dev,
			    "%s called while ratectl = %d!\n",
			    __func__, sc->sc_ratectl);
			break;
		}

		RTWN_NT_LOCK(sc);
		rtwn_handle_tx_report(sc, buf, len);
		RTWN_NT_UNLOCK(sc);

#ifdef IEEE80211_SUPPORT_SUPERG
		/*
		 * NB: this will executed only when 'report' bit is set.
		 */
		if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1)
			rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
#endif
		break;
	case RTWN_RX_OTHER:
		rtwn_handle_c2h_report(sc, buf, len);
		break;
	default:
		/* NOTREACHED */
		KASSERT(0, ("unknown Rx classification code"));
		break;
	}

	return (NULL);
}
Beispiel #2
0
static void
r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
{
#if __FreeBSD_version >= 1200012
	struct ieee80211_ratectl_tx_status txs;
#endif
	struct r92c_c2h_tx_rpt *rpt;
	struct ieee80211_node *ni;
	uint8_t macid;
	int ntries;

	if (sc->sc_ratectl != RTWN_RATECTL_NET80211) {
		/* shouldn't happen */
		device_printf(sc->sc_dev, "%s called while ratectl = %d!\n",
		    __func__, sc->sc_ratectl);
		return;
	}

	rpt = (struct r92c_c2h_tx_rpt *)buf;
	if (len != sizeof(*rpt)) {
		device_printf(sc->sc_dev,
		    "%s: wrong report size (%d, must be %zu)\n",
		    __func__, len, sizeof(*rpt));
		return;
	}

	RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
	    "%s: ccx report dump: 0: %02X, 1: %02X, queue time: "
	    "low %02X, high %02X, 4: %02X, 5: %02X, 6: %02X, 7: %02X\n",
	    __func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low,
	    rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6,
	    rpt->rptb7);

	macid = MS(rpt->rptb5, R92C_RPTB5_MACID);
	if (macid > sc->macid_limit) {
		device_printf(sc->sc_dev,
		    "macid %u is too big; increase MACID_MAX limit\n",
		    macid);
		return;
	}

	ntries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT);

	RTWN_NT_LOCK(sc);
	ni = sc->node_list[macid];
	if (ni != NULL) {
		RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
		    "%s sent (%d retries)\n", __func__, macid,
		    (rpt->rptb7 & R92C_RPTB7_PKT_OK) ? "" : " not",
		    ntries);

#if __FreeBSD_version >= 1200012
		txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY;
		txs.long_retries = ntries;
		if (rpt->rptb7 & R92C_RPTB7_PKT_OK)
			txs.status = IEEE80211_RATECTL_TX_SUCCESS;
		else if (rpt->rptb6 & R92C_RPTB6_RETRY_OVER)
			txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; /* XXX */
		else if (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE)
			txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
		else
			txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED;
		ieee80211_ratectl_tx_complete(ni, &txs);
#else
		struct ieee80211vap *vap = ni->ni_vap;
		if (rpt->rptb7 & R92C_RPTB7_PKT_OK) {
			ieee80211_ratectl_tx_complete(vap, ni,
			    IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
		} else {
			ieee80211_ratectl_tx_complete(vap, ni,
			    IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
		}
#endif
	} else {
		RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n",
		    __func__, macid);
	}
	RTWN_NT_UNLOCK(sc);

#ifdef IEEE80211_SUPPORT_SUPERG
	if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1)
		rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
#endif
}