Ejemplo n.º 1
0
uint8_t
rtwn_pci_read_1(struct rtwn_softc *sc, uint16_t addr)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);

	return (bus_space_read_1(pc->pc_st, pc->pc_sh, addr));
}
Ejemplo n.º 2
0
static void
rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
	int i;

	for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
		struct rtwn_tx_data *data = &ring->tx_data[i];
		void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i;

		rtwn_pci_copy_tx_desc(pc, desc, NULL);

		if (data->m != NULL) {
			bus_dmamap_sync(ring->data_dmat, data->map,
			    BUS_DMASYNC_POSTWRITE);
			bus_dmamap_unload(ring->data_dmat, data->map);
			m_freem(data->m);
			data->m = NULL;
		}
		if (data->ni != NULL) {
			ieee80211_free_node(data->ni);
			data->ni = NULL;
		}
	}

	bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
	    BUS_DMASYNC_POSTWRITE);

	sc->qfullmsk &= ~(1 << qid);
	ring->queued = 0;
	ring->last = ring->cur = 0;
}
Ejemplo n.º 3
0
uint16_t
rtwn_pci_read_2(struct rtwn_softc *sc, uint16_t addr)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	uint16_t val;

	val = bus_space_read_2(pc->pc_st, pc->pc_sh, addr);
	return le16toh(val);
}
Ejemplo n.º 4
0
int
rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);

	bus_space_write_1(pc->pc_st, pc->pc_sh, addr, val);

	return (0);
}
Ejemplo n.º 5
0
static uint16_t
rtwn_pci_get_qmap(struct rtwn_softc *sc)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);

	KASSERT(pc->pc_qmap != 0, ("%s: qmap is not set!\n", __func__));

	return (pc->pc_qmap);
}
Ejemplo n.º 6
0
static void
rtwn_pci_reset_rx_list(struct rtwn_softc *sc)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
	struct rtwn_rx_data *rx_data;
	int i;

	for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
		rx_data = &rx_ring->rx_data[i];
		rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i],
		    rx_data->paddr, MJUMPAGESIZE, i);
	}
	rx_ring->cur = 0;
}
Ejemplo n.º 7
0
/*
 * Drop stale entries from Tx ring before the vap will be deleted.
 * In case if vap is NULL just free everything and reset cur / last pointers.
 */
static void
rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
    int qid)
{
	int i;

	if (vap == NULL) {
		if (qid != RTWN_PCI_BEACON_QUEUE) {
			/*
			 * Device was stopped; just clear all entries.
			 */
			rtwn_pci_reset_tx_ring_stopped(sc, qid);
		} else {
			for (i = 0; i < RTWN_PORT_COUNT; i++)
				rtwn_pci_reset_beacon_ring(sc, i);
		}
	} else if (qid == RTWN_PCI_BEACON_QUEUE &&
		   (vap->iv_opmode == IEEE80211_M_HOSTAP ||
		    vap->iv_opmode == IEEE80211_M_IBSS)) {
		struct rtwn_vap *uvp = RTWN_VAP(vap);

		rtwn_pci_reset_beacon_ring(sc, uvp->id);
	} else {
		struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
		struct rtwn_tx_ring *ring = &pc->tx_ring[qid];

		for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
			struct rtwn_tx_data *data = &ring->tx_data[i];
			if (data->ni != NULL && data->ni->ni_vap == vap) {
				/*
				 * NB: if some vap is still running
				 * rtwn_pci_tx_done() will free the mbuf;
				 * otherwise, rtwn_stop() will reset all rings
				 * after device shutdown.
				 */
				ieee80211_free_node(data->ni);
				data->ni = NULL;
			}
		}
	}
}
Ejemplo n.º 8
0
static void
rtwn_pci_free_rx_list(struct rtwn_softc *sc)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
	struct rtwn_rx_data *rx_data;
	int i;

	if (rx_ring->desc_dmat != NULL) {
		if (rx_ring->desc != NULL) {
			bus_dmamap_sync(rx_ring->desc_dmat,
			    rx_ring->desc_map,
			    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
			bus_dmamap_unload(rx_ring->desc_dmat,
			    rx_ring->desc_map);
			bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc,
			    rx_ring->desc_map);
			rx_ring->desc = NULL;
		}
		bus_dma_tag_destroy(rx_ring->desc_dmat);
		rx_ring->desc_dmat = NULL;
	}

	for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
		rx_data = &rx_ring->rx_data[i];

		if (rx_data->m != NULL) {
			bus_dmamap_sync(rx_ring->data_dmat,
			    rx_data->map, BUS_DMASYNC_POSTREAD);
			bus_dmamap_unload(rx_ring->data_dmat, rx_data->map);
			m_freem(rx_data->m);
			rx_data->m = NULL;
		}
		bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map);
		rx_data->map = NULL;
	}
	if (rx_ring->data_dmat != NULL) {
		bus_dma_tag_destroy(rx_ring->data_dmat);
		rx_ring->data_dmat = NULL;
	}
}
Ejemplo n.º 9
0
static void
rtwn_pci_free_tx_list(struct rtwn_softc *sc, int qid)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
	struct rtwn_tx_data *tx_data;
	int i;

	if (tx_ring->desc_dmat != NULL) {
		if (tx_ring->desc != NULL) {
			bus_dmamap_sync(tx_ring->desc_dmat,
			    tx_ring->desc_map, BUS_DMASYNC_POSTWRITE);
			bus_dmamap_unload(tx_ring->desc_dmat,
			    tx_ring->desc_map);
			bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc,
			    tx_ring->desc_map);
		}
		bus_dma_tag_destroy(tx_ring->desc_dmat);
	}

	for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
		tx_data = &tx_ring->tx_data[i];

		if (tx_data->m != NULL) {
			bus_dmamap_sync(tx_ring->data_dmat, tx_data->map,
			    BUS_DMASYNC_POSTWRITE);
			bus_dmamap_unload(tx_ring->data_dmat, tx_data->map);
			m_freem(tx_data->m);
			tx_data->m = NULL;
		}
	}
	if (tx_ring->data_dmat != NULL) {
		bus_dma_tag_destroy(tx_ring->data_dmat);
		tx_ring->data_dmat = NULL;
	}

	sc->qfullmsk &= ~(1 << qid);
	tx_ring->queued = 0;
	tx_ring->last = tx_ring->cur = 0;
}
Ejemplo n.º 10
0
static void
rtwn_pci_set_desc_addr(struct rtwn_softc *sc)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);

	RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: addresses:\n"
	    "bk: %08jX, be: %08jX, vi: %08jX, vo: %08jX\n"
	    "bcn: %08jX, mgt: %08jX, high: %08jX, rx: %08jX\n",
	    __func__, (uintmax_t)pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr,
	    (uintmax_t)pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr,
	    (uintmax_t)pc->rx_ring.paddr);

	/* Set Tx Configuration Register. */
	rtwn_pci_write_4(sc, R92C_TCR, pc->tcr);

	/* Configure Tx DMA. */
	rtwn_pci_write_4(sc, R92C_BKQ_DESA,
	    pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_BEQ_DESA,
	    pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_VIQ_DESA,
	    pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_VOQ_DESA,
	    pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_BCNQ_DESA,
	    pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_MGQ_DESA,
	    pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr);
	rtwn_pci_write_4(sc, R92C_HQ_DESA,
	    pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr);

	/* Configure Rx DMA. */
	rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr);
}
Ejemplo n.º 11
0
/*
 * Clear entry 0 (or 1) in the beacon queue (other are not used).
 */
static void
rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
	struct rtwn_tx_data *data = &ring->tx_data[id];
	struct rtwn_tx_desc_common *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);
	if (txd->flags0 & RTWN_FLAGS0_OWN) {
		/* Clear OWN bit. */
		txd->flags0 &= ~RTWN_FLAGS0_OWN;
		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
		    BUS_DMASYNC_PREWRITE);

		/* Unload mbuf. */
		bus_dmamap_sync(ring->data_dmat, data->map,
		    BUS_DMASYNC_POSTWRITE);
		bus_dmamap_unload(ring->data_dmat, data->map);
	}
}
Ejemplo n.º 12
0
static int
rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
	bus_size_t size;
	int i, error;

	size = sc->txdesc_len * RTWN_PCI_TX_LIST_COUNT;
	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not create tx ring DMA tag\n");
		goto fail;
	}

	error = bus_dmamem_alloc(tx_ring->desc_dmat, &tx_ring->desc,
	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map);
	if (error != 0) {
		device_printf(sc->sc_dev, "can't map tx ring DMA memory\n");
		goto fail;
	}
	error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map,
	    tx_ring->desc, size, rtwn_pci_dma_map_addr, &tx_ring->paddr,
	    BUS_DMA_NOWAIT);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not load desc DMA map\n");
		goto fail;
	}
	bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
	    BUS_DMASYNC_PREWRITE);

	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not create tx buf DMA tag\n");
		goto fail;
	}

	for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
		struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
		void *tx_desc = (uint8_t *)tx_ring->desc + sc->txdesc_len * i;
		uint32_t next_desc_addr = tx_ring->paddr +
		    sc->txdesc_len * ((i + 1) % RTWN_PCI_TX_LIST_COUNT);

		rtwn_pci_setup_tx_desc(pc, tx_desc, next_desc_addr);

		error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map);
		if (error != 0) {
			device_printf(sc->sc_dev,
			    "could not create tx buf DMA map\n");
			return (error);
		}
		tx_data->m = NULL;
		tx_data->ni = NULL;
	}
	return (0);

fail:
	rtwn_pci_free_tx_list(sc, qid);
	return (error);
}
Ejemplo n.º 13
0
static int
rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
{
	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
	struct rtwn_rx_ring *rx_ring = &pc->rx_ring;
	struct rtwn_rx_data *rx_data;
	bus_size_t size;
	int i, error;

	/* Allocate Rx descriptors. */
	size = sizeof(struct r92ce_rx_stat) * RTWN_PCI_RX_LIST_COUNT;
	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not create rx desc DMA tag\n");
		goto fail;
	}

	error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc,
	    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
	    &rx_ring->desc_map);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not allocate rx desc\n");
		goto fail;
	}
	error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map,
	    rx_ring->desc, size, rtwn_pci_dma_map_addr, &rx_ring->paddr, 0);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not load rx desc DMA map\n");
		goto fail;
	}
	bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map,
	    BUS_DMASYNC_PREWRITE);

	/* Create RX buffer DMA tag. */
	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat);
	if (error != 0) {
		device_printf(sc->sc_dev, "could not create rx buf DMA tag\n");
		goto fail;
	}

	/* Allocate Rx buffers. */
	for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
		rx_data = &rx_ring->rx_data[i];
		error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map);
		if (error != 0) {
			device_printf(sc->sc_dev,
			    "could not create rx buf DMA map\n");
			goto fail;
		}

		rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
		    MJUMPAGESIZE);
		if (rx_data->m == NULL) {
			device_printf(sc->sc_dev,
			    "could not allocate rx mbuf\n");
			error = ENOMEM;
			goto fail;
		}

		error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map,
		    mtod(rx_data->m, void *), MJUMPAGESIZE,
		    rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
		if (error != 0) {
			device_printf(sc->sc_dev,
			    "could not load rx buf DMA map");
			goto fail;
		}

		rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr,
		    MJUMPAGESIZE, i);
	}
	rx_ring->cur = 0;

	return (0);

fail:
	rtwn_pci_free_rx_list(sc);
	return (error);
}