From owner-svn-src-all@freebsd.org Sun Nov 6 23:13:15 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BEA3AC3319C; Sun, 6 Nov 2016 23:13:15 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8FCC4E15; Sun, 6 Nov 2016 23:13:15 +0000 (UTC) (envelope-from avos@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uA6NDEvP014257; Sun, 6 Nov 2016 23:13:14 GMT (envelope-from avos@FreeBSD.org) Received: (from avos@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uA6NDDdv014248; Sun, 6 Nov 2016 23:13:13 GMT (envelope-from avos@FreeBSD.org) Message-Id: <201611062313.uA6NDDdv014248@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: avos set sender to avos@FreeBSD.org using -f From: Andriy Voskoboinyk Date: Sun, 6 Nov 2016 23:13:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308389 - in head/sys/dev/rtwn: . pci rtl8192c rtl8192c/pci usb X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Nov 2016 23:13:15 -0000 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