svn commit: r308389 - in head/sys/dev/rtwn: . pci rtl8192c rtl8192c/pci usb

Andriy Voskoboinyk avos at FreeBSD.org
Sun Nov 6 23:13:15 UTC 2016


Author: avos
Date: Sun Nov  6 23:13:13 2016
New Revision: 308389
URL: https://svnweb.freebsd.org/changeset/base/308389

Log:
  rtwn: add HOSTAP / IBSS mode support for RTL8188CE.
  
  NOTE: some multi-vap configurations (e.g., STA+IBSS) are not stable;
  that will be fixed later.
  
  Tested with:
   - RTL8188CE, STA + AP mode;
   - RTL8188CE, IBSS mode;
   - RTL8188CUS, IBSS mode;
   - RTL8188EU, IBSS mode.
  
  Relnotes:	yes

Modified:
  head/sys/dev/rtwn/if_rtwn.c
  head/sys/dev/rtwn/if_rtwn_beacon.c
  head/sys/dev/rtwn/if_rtwnvar.h
  head/sys/dev/rtwn/pci/rtwn_pci_attach.c
  head/sys/dev/rtwn/pci/rtwn_pci_tx.c
  head/sys/dev/rtwn/pci/rtwn_pci_var.h
  head/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
  head/sys/dev/rtwn/rtl8192c/r92c_beacon.c
  head/sys/dev/rtwn/usb/rtwn_usb_attach.c

Modified: head/sys/dev/rtwn/if_rtwn.c
==============================================================================
--- head/sys/dev/rtwn/if_rtwn.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/if_rtwn.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -628,10 +628,10 @@ rtwn_vap_delete(struct ieee80211vap *vap
 	ieee80211_draintask(ic, &ic->ic_parent_task);
 
 	RTWN_LOCK(sc);
-	if (uvp->bcn_mbuf != NULL)
-		m_freem(uvp->bcn_mbuf);
 	/* Cancel any unfinished Tx. */
 	rtwn_reset_lists(sc, vap);
+	if (uvp->bcn_mbuf != NULL)
+		m_freem(uvp->bcn_mbuf);
 	rtwn_vap_decrement_counters(sc, vap->iv_opmode, uvp->id);
 	rtwn_set_ic_opmode(sc);
 	if (sc->sc_flags & RTWN_RUNNING)
@@ -822,8 +822,10 @@ rtwn_push_nulldata(struct rtwn_softc *sc
 	rtwn_setbits_1_shift(sc, R92C_FWHW_TXQ_CTRL,
 	    R92C_FWHW_TXQ_CTRL_REAL_BEACON, 0, 2);
 
-	if (uvp->bcn_mbuf != NULL)
+	if (uvp->bcn_mbuf != NULL) {
+		rtwn_beacon_unload(sc, uvp->id);
 		m_freem(uvp->bcn_mbuf);
+	}
 
 	m->m_pkthdr.len = m->m_len = required_size - sc->txdesc_len;
 	uvp->bcn_mbuf = m;
@@ -1268,6 +1270,9 @@ rtwn_run(struct rtwn_softc *sc, struct i
 	}
 #endif
 
+	/* Enable TSF synchronization. */
+	rtwn_tsf_sync_enable(sc, vap);
+
 	if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
 	    vap->iv_opmode == IEEE80211_M_IBSS) {
 		error = rtwn_setup_beacon(sc, ni);
@@ -1282,9 +1287,6 @@ rtwn_run(struct rtwn_softc *sc, struct i
 	/* Set ACK preamble type. */
 	rtwn_set_ack_preamble(sc);
 
-	/* Enable TSF synchronization. */
-	rtwn_tsf_sync_enable(sc, vap);
-
 	/* Set basic rates mask. */
 	rtwn_calc_basicrates(sc);
 

Modified: head/sys/dev/rtwn/if_rtwn_beacon.c
==============================================================================
--- head/sys/dev/rtwn/if_rtwn_beacon.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/if_rtwn_beacon.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -54,6 +54,7 @@ rtwn_reset_beacon_valid(struct rtwn_soft
 
 	KASSERT (id == 0 || id == 1, ("wrong port id %d\n", id));
 
+	/* XXX cannot be cleared on RTL8188CE */
 	rtwn_setbits_1_shift(sc, sc->bcn_status_reg[id],
 	    R92C_TDECTRL_BCN_VALID, 0, 2);
 
@@ -79,7 +80,7 @@ rtwn_check_beacon_valid(struct rtwn_soft
 			    __func__, id);
 			break;
 		}
-		rtwn_delay(sc, 100);
+		rtwn_delay(sc, sc->bcn_check_interval);
 	}
 	if (ntries == 10)
 		return (ETIMEDOUT);
@@ -123,8 +124,10 @@ rtwn_setup_beacon(struct rtwn_softc *sc,
 		return (ENOMEM);
 	}
 
-	if (uvp->bcn_mbuf != NULL)
+	if (uvp->bcn_mbuf != NULL) {
+		rtwn_beacon_unload(sc, uvp->id);
 		m_freem(uvp->bcn_mbuf);
+	}
 
 	uvp->bcn_mbuf = m;
 
@@ -173,6 +176,7 @@ rtwn_update_beacon(struct ieee80211vap *
 			return;
 		}
 	}
+	rtwn_beacon_update_begin(sc, vap);
 	RTWN_UNLOCK(sc);
 
 	if (item == IEEE80211_BEACON_TIM)
@@ -183,6 +187,7 @@ rtwn_update_beacon(struct ieee80211vap *
 
 	RTWN_LOCK(sc);
 	rtwn_tx_beacon(sc, uvp);
+	rtwn_beacon_update_end(sc, vap);
 	RTWN_UNLOCK(sc);
 }
 

Modified: head/sys/dev/rtwn/if_rtwnvar.h
==============================================================================
--- head/sys/dev/rtwn/if_rtwnvar.h	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/if_rtwnvar.h	Sun Nov  6 23:13:13 2016	(r308389)
@@ -277,6 +277,14 @@ struct rtwn_softc {
 	uint16_t	(*sc_get_qmap)(struct rtwn_softc *);
 	void		(*sc_set_desc_addr)(struct rtwn_softc *);
 	void		(*sc_drop_incorrect_tx)(struct rtwn_softc *);
+	void		(*sc_beacon_update_begin)(struct rtwn_softc *,
+			    struct ieee80211vap *);
+	void		(*sc_beacon_update_end)(struct rtwn_softc *,
+			    struct ieee80211vap *);
+	void		(*sc_beacon_unload)(struct rtwn_softc *, int);
+
+	/* XXX drop checks for PCIe? */
+	int		bcn_check_interval;
 
 	/* Device-specific. */
 	uint32_t	(*sc_rf_read)(struct rtwn_softc *, int, uint8_t);
@@ -445,6 +453,12 @@ void	rtwn_suspend(struct rtwn_softc *);
 	(((_sc)->sc_set_desc_addr)((_sc)))
 #define rtwn_drop_incorrect_tx(_sc) \
 	(((_sc)->sc_drop_incorrect_tx)((_sc)))
+#define rtwn_beacon_update_begin(_sc, _vap) \
+	(((_sc)->sc_beacon_update_begin)((_sc), (_vap)))
+#define rtwn_beacon_update_end(_sc, _vap) \
+	(((_sc)->sc_beacon_update_end)((_sc), (_vap)))
+#define rtwn_beacon_unload(_sc, _id) \
+	(((_sc)->sc_beacon_unload)((_sc), (_id)))
 
 /* Aliases. */
 #define	rtwn_bb_write		rtwn_write_4

Modified: head/sys/dev/rtwn/pci/rtwn_pci_attach.c
==============================================================================
--- head/sys/dev/rtwn/pci/rtwn_pci_attach.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/pci/rtwn_pci_attach.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -87,6 +87,10 @@ static int	rtwn_pci_fw_write_block(struc
 		    const uint8_t *, uint16_t, int);
 static uint16_t	rtwn_pci_get_qmap(struct rtwn_softc *);
 static void	rtwn_pci_set_desc_addr(struct rtwn_softc *);
+static void	rtwn_pci_beacon_update_begin(struct rtwn_softc *,
+		    struct ieee80211vap *);
+static void	rtwn_pci_beacon_update_end(struct rtwn_softc *,
+		    struct ieee80211vap *);
 static void	rtwn_pci_attach_methods(struct rtwn_softc *);
 
 
@@ -539,6 +543,27 @@ rtwn_pci_set_desc_addr(struct rtwn_softc
 }
 
 static void
+rtwn_pci_beacon_update_begin(struct rtwn_softc *sc, struct ieee80211vap *vap)
+{
+	struct rtwn_vap *rvp = RTWN_VAP(vap);
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	rtwn_beacon_enable(sc, rvp->id, 0);
+}
+
+static void
+rtwn_pci_beacon_update_end(struct rtwn_softc *sc, struct ieee80211vap *vap)
+{
+	struct rtwn_vap *rvp = RTWN_VAP(vap);
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	if (rvp->curr_mode != R92C_MSR_NOLINK)
+		rtwn_beacon_enable(sc, rvp->id, 1);
+}
+
+static void
 rtwn_pci_attach_methods(struct rtwn_softc *sc)
 {
 	sc->sc_write_1		= rtwn_pci_write_1;
@@ -555,6 +580,11 @@ rtwn_pci_attach_methods(struct rtwn_soft
 	sc->sc_get_qmap		= rtwn_pci_get_qmap;
 	sc->sc_set_desc_addr	= rtwn_pci_set_desc_addr;
 	sc->sc_drop_incorrect_tx = rtwn_nop_softc;
+	sc->sc_beacon_update_begin = rtwn_pci_beacon_update_begin;
+	sc->sc_beacon_update_end = rtwn_pci_beacon_update_end;
+	sc->sc_beacon_unload	= rtwn_pci_reset_beacon_ring;
+
+	sc->bcn_check_interval	= 25000;
 }
 
 static int

Modified: head/sys/dev/rtwn/pci/rtwn_pci_tx.c
==============================================================================
--- head/sys/dev/rtwn/pci/rtwn_pci_tx.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/pci/rtwn_pci_tx.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$");
 
 
 static int
-rtwn_pci_tx_start_common(struct rtwn_softc *sc, struct ieee80211_node *ni,
-    struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
+rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
+    struct mbuf *m, uint8_t *tx_desc, uint8_t type)
 {
 	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
 	struct rtwn_tx_ring *ring;
@@ -75,16 +75,13 @@ rtwn_pci_tx_start_common(struct rtwn_sof
 	switch (type) {
 	case IEEE80211_FC0_TYPE_CTL:
 	case IEEE80211_FC0_TYPE_MGT:
-		qid = RTWN_PCI_VO_QUEUE;
+		qid = RTWN_PCI_MGNT_QUEUE;
 		break;
 	default:
 		qid = M_WME_GETAC(m);
 		break;
 	}
 
-	if (ni == NULL)		/* beacon frame */
-		qid = RTWN_PCI_BEACON_QUEUE;
-
 	ring = &pc->tx_ring[qid];
 	data = &ring->tx_data[ring->cur];
 	if (data->m != NULL) {
@@ -151,19 +148,16 @@ rtwn_pci_tx_start_common(struct rtwn_sof
 
 	data->m = m;
 	data->ni = ni;
-	data->id = id;
 
 	ring->cur = (ring->cur + 1) % RTWN_PCI_TX_LIST_COUNT;
 
-	if (qid != RTWN_PCI_BEACON_QUEUE) {
-		ring->queued++;
-		if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
-			sc->qfullmsk |= (1 << qid);
+	ring->queued++;
+	if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1))
+		sc->qfullmsk |= (1 << qid);
 
 #ifndef D4054
-		sc->sc_tx_timer = 5;
+	sc->sc_tx_timer = 5;
 #endif
-	}
 
 	/* Kick TX. */
 	rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid));
@@ -171,25 +165,77 @@ rtwn_pci_tx_start_common(struct rtwn_sof
 	return (0);
 }
 
+static int
+rtwn_pci_tx_start_beacon(struct rtwn_softc *sc, struct mbuf *m,
+    uint8_t *tx_desc, int id)
+{
+	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+	struct rtwn_tx_ring *ring;
+	struct rtwn_tx_data *data;
+	struct rtwn_tx_desc_common *txd;
+	bus_dma_segment_t segs[1];
+	int nsegs, error, own;
+
+	RTWN_ASSERT_LOCKED(sc);
+
+	KASSERT(id == 0 || id == 1, ("bogus vap id %d\n", id));
+
+	ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
+	data = &ring->tx_data[id];
+	txd = (struct rtwn_tx_desc_common *)
+	    ((uint8_t *)ring->desc + id * sc->txdesc_len);
+
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+	    BUS_DMASYNC_POSTREAD);
+	own = !!(txd->flags0 & RTWN_FLAGS0_OWN);
+	error = 0;
+	if (!own || txd->pktlen != htole16(m->m_pkthdr.len)) {
+		if (!own) {
+			/* Copy Tx descriptor. */
+			rtwn_pci_copy_tx_desc(pc, txd, tx_desc);
+			txd->offset = sc->txdesc_len;
+		} else {
+			/* Reload mbuf. */
+			bus_dmamap_unload(ring->data_dmat, data->map);
+		}
+
+		error = bus_dmamap_load_mbuf_sg(ring->data_dmat,
+		    data->map, m, segs, &nsegs, BUS_DMA_NOWAIT);
+		if (error != 0) {
+			device_printf(sc->sc_dev,
+			    "can't map beacon (error %d)\n", error);
+			txd->flags0 &= ~RTWN_FLAGS0_OWN;
+			goto end;
+		}
+
+		txd->pktlen = htole16(m->m_pkthdr.len);
+		rtwn_pci_tx_postsetup(pc, txd, segs);
+		txd->flags0 |= RTWN_FLAGS0_OWN;
+end:
+		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+		    BUS_DMASYNC_PREWRITE);
+	}
+
+	/* Dump Tx descriptor. */
+	rtwn_dump_tx_desc(sc, txd);
+
+	bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE);
+
+	return (0);
+}
+
 int
 rtwn_pci_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
     struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id)
 {
 	int error = 0;
 
-	if (ni == NULL) {	/* beacon frame */
-		m = m_dup(m, M_NOWAIT);
-		if (__predict_false(m == NULL)) {
-			device_printf(sc->sc_dev,
-			    "%s: could not copy beacon frame\n", __func__);
-			return (ENOMEM);
-		}
+	RTWN_ASSERT_LOCKED(sc);
 
-		error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
-		if (error != 0)
-			m_freem(m);
-	} else
-		error = rtwn_pci_tx_start_common(sc, ni, m, tx_desc, type, id);
+	if (ni == NULL)		/* beacon frame */
+		error = rtwn_pci_tx_start_beacon(sc, m, tx_desc, id);
+	else
+		error = rtwn_pci_tx_start_frame(sc, ni, m, tx_desc, type);
 
 	return (error);
 }

Modified: head/sys/dev/rtwn/pci/rtwn_pci_var.h
==============================================================================
--- head/sys/dev/rtwn/pci/rtwn_pci_var.h	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/pci/rtwn_pci_var.h	Sun Nov  6 23:13:13 2016	(r308389)
@@ -50,7 +50,6 @@ struct rtwn_tx_data {
 	bus_dmamap_t		map;
 	struct mbuf		*m;
 	struct ieee80211_node	*ni;
-	uint8_t			id;
 };
 
 struct rtwn_tx_ring {

Modified: head/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c
==============================================================================
--- head/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -141,9 +141,7 @@ r92ce_adj_devcaps(struct rtwn_softc *sc)
 	/* XXX TODO: test everything that removed here before enabling. */
 	/* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */
 	ic->ic_caps &= ~(
-		  IEEE80211_C_IBSS	/* check beaconing / tsf */
-		| IEEE80211_C_HOSTAP	/* the same */
-		| IEEE80211_C_PMGT	/* check null frame / device usability */
+		  IEEE80211_C_PMGT	/* check null frame / device usability */
 		| IEEE80211_C_SWAMSDUTX
 		| IEEE80211_C_FF
 	);
@@ -256,6 +254,12 @@ r92ce_attach(struct rtwn_pci_softc *pc)
 	sc->temp_delta			= R92C_CALIB_THRESHOLD;
 
 	sc->bcn_status_reg[0]		= R92C_TDECTRL;
+	/*
+	 * TODO: some additional setup is required
+	 * to maintain few beacons at the same time.
+	 *
+	 * XXX BCNQ1 mechanism is not needed here; move it to the USB module.
+	 */
 	sc->bcn_status_reg[1]		= R92C_TDECTRL;
 	sc->rcr				= 0;
 

Modified: head/sys/dev/rtwn/rtl8192c/r92c_beacon.c
==============================================================================
--- head/sys/dev/rtwn/rtl8192c/r92c_beacon.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/rtl8192c/r92c_beacon.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -68,6 +68,7 @@ r92c_beacon_init(struct rtwn_softc *sc, 
 	rtwn_r92c_tx_setup_macid(sc, buf, id);
 	txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
 	txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id));
+	txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id));
 	txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1));
 }
 

Modified: head/sys/dev/rtwn/usb/rtwn_usb_attach.c
==============================================================================
--- head/sys/dev/rtwn/usb/rtwn_usb_attach.c	Sun Nov  6 21:41:26 2016	(r308388)
+++ head/sys/dev/rtwn/usb/rtwn_usb_attach.c	Sun Nov  6 23:13:13 2016	(r308389)
@@ -81,6 +81,7 @@ static void	rtwn_usb_start_xfers(struct 
 static void	rtwn_usb_abort_xfers(struct rtwn_softc *);
 static int	rtwn_usb_fw_write_block(struct rtwn_softc *,
 		    const uint8_t *, uint16_t, int);
+static void	rtwn_usb_drop_incorrect_tx(struct rtwn_softc *);
 static void	rtwn_usb_attach_methods(struct rtwn_softc *);
 
 #define RTWN_CONFIG_INDEX	0
@@ -318,6 +319,11 @@ rtwn_usb_attach_methods(struct rtwn_soft
 	sc->sc_get_qmap		= rtwn_usb_get_qmap;
 	sc->sc_set_desc_addr	= rtwn_nop_softc;
 	sc->sc_drop_incorrect_tx = rtwn_usb_drop_incorrect_tx;
+	sc->sc_beacon_update_begin = rtwn_nop_softc_vap;
+	sc->sc_beacon_update_end = rtwn_nop_softc_vap;
+	sc->sc_beacon_unload	= rtwn_nop_softc_int;
+
+	sc->bcn_check_interval	= 100;
 }
 
 static int


More information about the svn-src-all mailing list