Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Dec 2015 21:00:21 +0000 (UTC)
From:      Andriy Voskoboinyk <avos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r292167 - head/sys/dev/usb/wlan
Message-ID:  <201512132100.tBDL0LIi078588@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avos
Date: Sun Dec 13 21:00:21 2015
New Revision: 292167
URL: https://svnweb.freebsd.org/changeset/base/292167

Log:
  urtwn: add rate control support for RTL8188EU.
  
  Tested with:
  - RTL8188EU, STA and HOSTAP modes.
  - RTL8188CUS, STA mode.
  
  Reviewed by:	kevlo
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D4402

Modified:
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnreg.h
  head/sys/dev/usb/wlan/if_urtwnvar.h

Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c	Sun Dec 13 20:53:51 2015	(r292166)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Sun Dec 13 21:00:21 2015	(r292167)
@@ -183,8 +183,12 @@ static struct ieee80211vap *urtwn_vap_cr
 static void		urtwn_vap_delete(struct ieee80211vap *);
 static struct mbuf *	urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int,
 			    int *);
-static struct mbuf *	urtwn_rxeof(struct usb_xfer *, struct urtwn_data *,
+static struct mbuf *	urtwn_report_intr(struct usb_xfer *, struct urtwn_data *,
 			    int *, int8_t *);
+static struct mbuf *	urtwn_rxeof(struct urtwn_softc *, uint8_t *, int,
+			    int *, int8_t *);
+static void		urtwn_r88e_ratectl_tx_complete(struct urtwn_softc *,
+			    void *);
 static void		urtwn_txeof(struct urtwn_softc *, struct urtwn_data *,
 			    int);
 static int		urtwn_alloc_list(struct urtwn_softc *,
@@ -295,6 +299,10 @@ static int		urtwn_wme_update(struct ieee
 static void		urtwn_set_promisc(struct urtwn_softc *);
 static void		urtwn_update_promisc(struct ieee80211com *);
 static void		urtwn_update_mcast(struct ieee80211com *);
+static struct ieee80211_node *urtwn_r88e_node_alloc(struct ieee80211vap *,
+			    const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void		urtwn_r88e_newassoc(struct ieee80211_node *, int);
+static void		urtwn_r88e_node_free(struct ieee80211_node *);
 static void		urtwn_set_chan(struct urtwn_softc *,
 		    	    struct ieee80211_channel *,
 			    struct ieee80211_channel *);
@@ -419,6 +427,7 @@ urtwn_attach(device_t self)
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(self),
 	    MTX_NETWORK_LOCK, MTX_DEF);
+	URTWN_NT_LOCK_INIT(sc);
 	callout_init(&sc->sc_watchdog_ch, 0);
 	mbufq_init(&sc->sc_snd, ifqmaxlen);
 
@@ -504,6 +513,12 @@ urtwn_attach(device_t self)
 	ic->ic_wme.wme_update = urtwn_wme_update;
 	ic->ic_update_promisc = urtwn_update_promisc;
 	ic->ic_update_mcast = urtwn_update_mcast;
+	if (sc->chip & URTWN_CHIP_88E) {
+		ic->ic_node_alloc = urtwn_r88e_node_alloc;
+		ic->ic_newassoc = urtwn_r88e_newassoc;
+		sc->sc_node_free = ic->ic_node_free;
+		ic->ic_node_free = urtwn_r88e_node_free;
+	}
 
 	ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
 	    sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT,
@@ -560,6 +575,7 @@ urtwn_detach(device_t self)
 	URTWN_UNLOCK(sc);
 
 	ieee80211_ifdetach(ic);
+	URTWN_NT_LOCK_DESTROY(sc);
 	mtx_destroy(&sc->sc_mtx);
 
 	return (0);
@@ -638,6 +654,8 @@ urtwn_vap_create(struct ieee80211com *ic
 		TASK_INIT(&uvp->tsf_task_adhoc, 0, urtwn_tsf_task_adhoc, vap);
 	}
 
+	if (URTWN_CHIP_HAS_RATECTL(sc))
+		ieee80211_ratectl_init(vap);
 	/* complete setup */
 	ieee80211_vap_attach(vap, ieee80211_media_change,
 	    ieee80211_media_status, mac);
@@ -649,12 +667,15 @@ static void
 urtwn_vap_delete(struct ieee80211vap *vap)
 {
 	struct ieee80211com *ic = vap->iv_ic;
+	struct urtwn_softc *sc = ic->ic_softc;
 	struct urtwn_vap *uvp = URTWN_VAP(vap);
 
 	if (uvp->bcn_mbuf != NULL)
 		m_freem(uvp->bcn_mbuf);
 	if (vap->iv_opmode == IEEE80211_M_IBSS)
 		ieee80211_draintask(ic, &uvp->tsf_task_adhoc);
+	if (URTWN_CHIP_HAS_RATECTL(sc))
+		ieee80211_ratectl_deinit(vap);
 	ieee80211_vap_detach(vap);
 	free(uvp, M_80211_VAP);
 }
@@ -743,16 +764,14 @@ urtwn_rx_frame(struct urtwn_softc *sc, u
 }
 
 static struct mbuf *
-urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
+urtwn_report_intr(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
     int8_t *nf)
 {
 	struct urtwn_softc *sc = data->sc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct r92c_rx_stat *stat;
-	struct mbuf *m, *m0 = NULL, *prevm = NULL;
-	uint32_t rxdw0;
 	uint8_t *buf;
-	int len, totlen, pktlen, infosz, npkts;
+	int len;
 
 	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
 
@@ -762,6 +781,36 @@ urtwn_rxeof(struct usb_xfer *xfer, struc
 	}
 
 	buf = data->buf;
+	stat = (struct r92c_rx_stat *)buf;
+
+	if (sc->chip & URTWN_CHIP_88E) {
+		int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT);
+
+		switch (report_sel) {
+		case R88E_RXDW3_RPT_RX:
+			return (urtwn_rxeof(sc, buf, len, rssi, nf));
+		case R88E_RXDW3_RPT_TX1:
+			urtwn_r88e_ratectl_tx_complete(sc, &stat[1]);
+			break;
+		default:
+			DPRINTFN(7, "case %d was not handled\n", report_sel);
+			break;
+		}
+	} else
+		return (urtwn_rxeof(sc, buf, len, rssi, nf));
+
+	return (NULL);
+}
+
+static struct mbuf *
+urtwn_rxeof(struct urtwn_softc *sc, uint8_t *buf, int len, int *rssi,
+    int8_t *nf)
+{
+	struct r92c_rx_stat *stat;
+	struct mbuf *m, *m0 = NULL, *prevm = NULL;
+	uint32_t rxdw0;
+	int totlen, pktlen, infosz, npkts;
+
 	/* Get the number of encapsulated frames. */
 	stat = (struct r92c_rx_stat *)buf;
 	npkts = MS(le32toh(stat->rxdw2), R92C_RXDW2_PKTCNT);
@@ -805,6 +854,35 @@ urtwn_rxeof(struct usb_xfer *xfer, struc
 }
 
 static void
+urtwn_r88e_ratectl_tx_complete(struct urtwn_softc *sc, void *arg)
+{
+	struct r88e_tx_rpt_ccx *rpt = arg;
+	struct ieee80211vap *vap;
+	struct ieee80211_node *ni;
+	uint8_t macid;
+	int ntries;
+
+	macid = MS(rpt->rptb1, R88E_RPTB1_MACID);
+	ntries = MS(rpt->rptb2, R88E_RPTB2_RETRY_CNT);
+
+	URTWN_NT_LOCK(sc);
+	ni = sc->node_list[macid];
+	if (ni != NULL) {
+		vap = ni->ni_vap;
+
+		if (rpt->rptb1 & R88E_RPTB1_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);
+		}
+	} else
+		DPRINTFN(8, "macid %d, ni is NULL\n", macid);
+	URTWN_NT_UNLOCK(sc);
+}
+
+static void
 urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
 {
 	struct urtwn_softc *sc = usbd_xfer_softc(xfer);
@@ -824,7 +902,7 @@ urtwn_bulk_rx_callback(struct usb_xfer *
 		if (data == NULL)
 			goto tr_setup;
 		STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
-		m = urtwn_rxeof(xfer, data, &rssi, &nf);
+		m = urtwn_report_intr(xfer, data, &rssi, &nf);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
@@ -2008,10 +2086,7 @@ urtwn_newstate(struct ieee80211vap *vap,
 		urtwn_write_1(sc, R92C_T2T_SIFS + 1, 10);
 
 		/* Intialize rate adaptation. */
-		if (sc->chip & URTWN_CHIP_88E)
-			ni->ni_txrate =
-			    ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1];
-		else
+		if (!(sc->chip & URTWN_CHIP_88E))
 			urtwn_ra_init(sc);
 		/* Turn link LED on. */
 		urtwn_set_led(sc, URTWN_LED_LINK, 1);
@@ -2162,16 +2237,38 @@ urtwn_r88e_get_rssi(struct urtwn_softc *
 	return (rssi);
 }
 
+static __inline uint8_t
+rate2ridx(uint8_t rate)
+{
+	switch (rate) {
+	case 12:	return 4;
+	case 18:	return 5;
+	case 24:	return 6;
+	case 36:	return 7;
+	case 48:	return 8;
+	case 72:	return 9;
+	case 96:	return 10;
+	case 108:	return 11;
+	case 2:		return 0;
+	case 4:		return 1;
+	case 11:	return 2;
+	case 22:	return 3;
+	default:	return 0;
+	}
+}
+
 static int
 urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
     struct mbuf *m, struct urtwn_data *data)
 {
-	struct ieee80211_frame *wh;
-	struct ieee80211_key *k = NULL;
+	const struct ieee80211_txparam *tp;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_key *k = NULL;
+	struct ieee80211_channel *chan;
+	struct ieee80211_frame *wh;
 	struct r92c_tx_desc *txd;
-	uint8_t macid, raid, ridx, subtype, type, tid, qsel;
+	uint8_t macid, raid, rate, ridx, subtype, type, tid, qsel;
 	int hasqos, ismcast;
 
 	URTWN_ASSERT_LOCKED(sc);
@@ -2192,6 +2289,38 @@ urtwn_tx_data(struct urtwn_softc *sc, st
 	} else
 		tid = 0;
 
+	chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ?
+		ni->ni_chan : ic->ic_curchan;
+	tp = &vap->iv_txparms[ieee80211_chan2mode(chan)];
+
+	/* Choose a TX rate index. */
+	if (type == IEEE80211_FC0_TYPE_MGT)
+		rate = tp->mgmtrate;
+	else if (ismcast)
+		rate = tp->mcastrate;
+	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
+		rate = tp->ucastrate;
+	else if (m->m_flags & M_EAPOL)
+		rate = tp->mgmtrate;
+	else {
+		if (URTWN_CHIP_HAS_RATECTL(sc)) {
+			/* XXX pass pktlen */
+			(void) ieee80211_ratectl_rate(ni, NULL, 0);
+			rate = ni->ni_txrate;
+		} else {
+			if (ic->ic_curmode != IEEE80211_MODE_11B)
+				rate = 108;
+			else
+				rate = 22;
+		}
+	}
+
+	ridx = rate2ridx(rate);
+	if (ic->ic_curmode != IEEE80211_MODE_11B)
+		raid = R92C_RAID_11BG;
+	else
+		raid = R92C_RAID_11B;
+
 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
 		k = ieee80211_crypto_encap(ni, m);
 		if (k == NULL) {
@@ -2214,25 +2343,21 @@ urtwn_tx_data(struct urtwn_softc *sc, st
 	if (ismcast)
 		txd->txdw0 |= htole32(R92C_TXDW0_BMCAST);
 
-	raid = R92C_RAID_11B;	/* by default */
-	ridx = URTWN_RIDX_CCK1;
 	if (!ismcast) {
-		macid = URTWN_MACID_BSS;
+		if (sc->chip & URTWN_CHIP_88E) {
+			struct urtwn_node *un = URTWN_NODE(ni);
+			macid = un->id;
+		} else
+			macid = URTWN_MACID_BSS;
 
 		if (type == IEEE80211_FC0_TYPE_DATA) {
 			qsel = tid % URTWN_MAX_TID;
 
-			if (!(m->m_flags & M_EAPOL)) {
-				if (ic->ic_curmode != IEEE80211_MODE_11B) {
-					raid = R92C_RAID_11BG;
-					ridx = URTWN_RIDX_OFDM54;
-				} else
-					ridx = URTWN_RIDX_CCK11;
-			}
-
-			if (sc->chip & URTWN_CHIP_88E)
-				txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
-			else
+			if (sc->chip & URTWN_CHIP_88E) {
+				txd->txdw2 |= htole32(
+				    R88E_TXDW2_AGGBK |
+				    R88E_TXDW2_CCX_RPT);
+			} else
 				txd->txdw1 |= htole32(R92C_TXDW1_AGGBK);
 
 			if (ic->ic_flags & IEEE80211_F_USEPROT) {
@@ -2272,8 +2397,8 @@ urtwn_tx_data(struct urtwn_softc *sc, st
 
 	txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx));
 	/* Force this rate if needed. */
-	if (ismcast || type != IEEE80211_FC0_TYPE_DATA ||
-	    (m->m_flags & M_EAPOL))
+	if (URTWN_CHIP_HAS_RATECTL(sc) || ismcast ||
+	    (m->m_flags & M_EAPOL) || type != IEEE80211_FC0_TYPE_DATA)
 		txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
 
 	if (!hasqos) {
@@ -3705,6 +3830,63 @@ urtwn_update_mcast(struct ieee80211com *
 	/* XXX do nothing?  */
 }
 
+static struct ieee80211_node *
+urtwn_r88e_node_alloc(struct ieee80211vap *vap,
+    const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+	struct urtwn_node *un;
+
+	un = malloc(sizeof (struct urtwn_node), M_80211_NODE,
+	    M_NOWAIT | M_ZERO);
+
+	if (un == NULL)
+		return NULL;
+
+	un->id = URTWN_MACID_UNDEFINED;
+
+	return &un->ni;
+}
+
+static void
+urtwn_r88e_newassoc(struct ieee80211_node *ni, int isnew)
+{
+	struct urtwn_softc *sc = ni->ni_ic->ic_softc;
+	struct urtwn_node *un = URTWN_NODE(ni);
+	uint8_t id;
+
+	if (!isnew)
+		return;
+
+	URTWN_NT_LOCK(sc);
+	for (id = 0; id <= URTWN_MACID_MAX(sc); id++) {
+		if (id != URTWN_MACID_BC && sc->node_list[id] == NULL) {
+			un->id = id;
+			sc->node_list[id] = ni;
+			break;
+		}
+	}
+	URTWN_NT_UNLOCK(sc);
+
+	if (id > URTWN_MACID_MAX(sc)) {
+		device_printf(sc->sc_dev, "%s: node table is full\n",
+		    __func__);
+	}
+}
+
+static void
+urtwn_r88e_node_free(struct ieee80211_node *ni)
+{
+	struct urtwn_softc *sc = ni->ni_ic->ic_softc;
+	struct urtwn_node *un = URTWN_NODE(ni);
+
+	URTWN_NT_LOCK(sc);
+	if (un->id != URTWN_MACID_UNDEFINED)
+		sc->node_list[un->id] = NULL;
+	URTWN_NT_UNLOCK(sc);
+
+	sc->sc_node_free(ni);
+}
+
 static void
 urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c,
     struct ieee80211_channel *extc)
@@ -4022,6 +4204,12 @@ urtwn_init(struct urtwn_softc *sc)
 	/* Enable hardware sequence numbering. */
 	urtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff);
 
+	/* Enable per-packet TX report. */
+	if (sc->chip & URTWN_CHIP_88E) {
+		urtwn_write_1(sc, R88E_TX_RPT_CTRL,
+		    urtwn_read_1(sc, R88E_TX_RPT_CTRL) | R88E_TX_RPT1_ENA);
+	}
+
 	/* Perform LO and IQ calibrations. */
 	urtwn_iq_calib(sc);
 	/* Perform LC calibration. */

Modified: head/sys/dev/usb/wlan/if_urtwnreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h	Sun Dec 13 20:53:51 2015	(r292166)
+++ head/sys/dev/usb/wlan/if_urtwnreg.h	Sun Dec 13 21:00:21 2015	(r292167)
@@ -158,6 +158,9 @@
 #define R92C_INIRTS_RATE_SEL		0x480
 #define R92C_INIDATA_RATE_SEL(macid)	(0x484 + (macid))
 #define R92C_MAX_AGGR_NUM		0x4ca
+#define R88E_TX_RPT_CTRL		0x4ec
+#define R88E_TX_RPT_MACID_MAX		0x4ed
+#define R88E_TX_RPT_TIME		0x4f0
 /* EDCA Configuration. */
 #define R92C_EDCA_VO_PARAM		0x500
 #define R92C_EDCA_VI_PARAM		0x504
@@ -479,6 +482,10 @@
 #define R92C_RRSR_RSC_UPSUBCHNL		0x00400000
 #define R92C_RRSR_SHORT			0x00800000
 
+/* Bits for R88E_TX_RPT_CTRL. */
+#define R88E_TX_RPT1_ENA		0x01
+#define R88E_TX_RPT2_ENA		0x02
+
 /* Bits for R92C_EDCA_XX_PARAM. */
 #define R92C_EDCA_PARAM_AIFS_M		0x000000ff
 #define R92C_EDCA_PARAM_AIFS_S		0
@@ -895,6 +902,11 @@ struct r92c_fw_cmd_macid_cfg {
 	uint8_t		macid;
 #define URTWN_MACID_BSS		0
 #define URTWN_MACID_BC		4	/* Broadcast. */
+#define R92C_MACID_MAX		31
+#define R88E_MACID_MAX		63
+#define URTWN_MACID_MAX(sc)	(((sc)->chip & URTWN_CHIP_88E) ? \
+				    R88E_MACID_MAX : R92C_MACID_MAX)
+#define URTWN_MACID_UNDEFINED	(uint8_t)-1
 #define URTWN_MACID_VALID	0x80
 } __packed;
 
@@ -972,6 +984,11 @@ struct r92c_rx_stat {
 #define R92C_RXDW3_RATE_S	0
 #define R92C_RXDW3_HT		0x00000040
 #define R92C_RXDW3_HTC		0x00000400
+#define R88E_RXDW3_RPT_M	0x0000c000
+#define R88E_RXDW3_RPT_S	14
+#define R88E_RXDW3_RPT_RX	0
+#define R88E_RXDW3_RPT_TX1	1
+#define R88E_RXDW3_RPT_TX2	2
 
 	uint32_t	rxdw4;
 	uint32_t	rxdw5;
@@ -1059,6 +1076,7 @@ struct r92c_tx_desc {
 
 	uint32_t	txdw2;
 #define R88E_TXDW2_AGGBK	0x00010000
+#define R88E_TXDW2_CCX_RPT	0x00080000
 
 	uint16_t	txdw3;
 	uint16_t	txdseq;
@@ -1091,6 +1109,30 @@ struct r92c_tx_desc {
 	uint16_t	pad;
 } __packed __attribute__((aligned(4)));
 
+struct r88e_tx_rpt_ccx {
+	uint8_t		rptb0;
+	uint8_t		rptb1;
+#define R88E_RPTB1_MACID_M	0x3f
+#define R88E_RPTB1_MACID_S	0
+#define R88E_RPTB1_PKT_OK	0x40
+#define R88E_RPTB1_BMC		0x80
+
+	uint8_t		rptb2;
+#define R88E_RPTB2_RETRY_CNT_M	0x3f
+#define R88E_RPTB2_RETRY_CNT_S	0
+#define R88E_RPTB2_LIFE_EXPIRE	0x40
+#define R88E_RPTB2_RETRY_OVER	0x80
+
+	uint8_t		rptb3;
+	uint8_t		rptb4;
+	uint8_t		rptb5;
+	uint8_t		rptb6;
+#define R88E_RPTB6_QSEL_M	0xf0
+#define R88E_RPTB6_QSEL_S	4
+
+	uint8_t		rptb7;
+} __packed;
+
 
 static const uint8_t ridx2rate[] =
 	{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };

Modified: head/sys/dev/usb/wlan/if_urtwnvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnvar.h	Sun Dec 13 20:53:51 2015	(r292166)
+++ head/sys/dev/usb/wlan/if_urtwnvar.h	Sun Dec 13 21:00:21 2015	(r292167)
@@ -86,6 +86,12 @@ struct urtwn_fw_info {
 	size_t			size;
 };
 
+struct urtwn_node {
+	struct ieee80211_node	ni;	/* must be the first */
+	uint8_t			id;
+};
+#define URTWN_NODE(ni)	((struct urtwn_node *)(ni))
+
 struct urtwn_vap {
 	struct ieee80211vap	vap;
 
@@ -152,10 +158,16 @@ struct urtwn_softc {
 #define	URTWN_CHIP_UMC_A_CUT	0x08
 #define	URTWN_CHIP_88E		0x10
 
+#define URTWN_CHIP_HAS_RATECTL(_sc)	(!!((_sc)->chip & URTWN_CHIP_88E))
+
+	void				(*sc_node_free)(struct ieee80211_node *);
 	void				(*sc_rf_write)(struct urtwn_softc *,
 					    int, uint8_t, uint32_t);
 	int				(*sc_power_on)(struct urtwn_softc *);
 
+	struct ieee80211_node		*node_list[R88E_MACID_MAX];
+	struct mtx			nt_mtx;
+
 	uint8_t				board_type;
 	uint8_t				regulatory;
 	uint8_t				pa_setting;
@@ -213,3 +225,9 @@ struct urtwn_softc {
 #define	URTWN_LOCK(sc)			mtx_lock(&(sc)->sc_mtx)
 #define	URTWN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
 #define	URTWN_ASSERT_LOCKED(sc)		mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+
+#define URTWN_NT_LOCK_INIT(sc) \
+	mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF)
+#define URTWN_NT_LOCK(sc)		mtx_lock(&(sc)->nt_mtx)
+#define URTWN_NT_UNLOCK(sc)		mtx_unlock(&(sc)->nt_mtx)
+#define URTWN_NT_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->nt_mtx)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512132100.tBDL0LIi078588>