- Fix Tx queues to USB endpoints mapping

- Merge urtwn_r92c_dma_init() and urtwn_r88e_dma_init() into one

Reviewed by:	adrian, avos
Differential Revision:	https://reviews.freebsd.org/D4381
This commit is contained in:
kevlo 2015-12-06 14:07:57 +00:00
parent b6356a57e1
commit 070b607d88
2 changed files with 93 additions and 128 deletions

View File

@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/socket.h>
@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_device.h>
#include "usbdevs.h"
#define USB_DEBUG_VAR urtwn_debug
@ -265,8 +267,7 @@ static void urtwn_r88e_fw_reset(struct urtwn_softc *);
static int urtwn_fw_loadpage(struct urtwn_softc *, int,
const uint8_t *, int);
static int urtwn_load_firmware(struct urtwn_softc *);
static int urtwn_r92c_dma_init(struct urtwn_softc *);
static int urtwn_r88e_dma_init(struct urtwn_softc *);
static int urtwn_dma_init(struct urtwn_softc *);
static int urtwn_mac_init(struct urtwn_softc *);
static void urtwn_bb_init(struct urtwn_softc *);
static void urtwn_rf_init(struct urtwn_softc *);
@ -396,7 +397,7 @@ urtwn_attach(device_t self)
struct usb_attach_arg *uaa = device_get_ivars(self);
struct urtwn_softc *sc = device_get_softc(self);
struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
uint8_t bands;
int error;
device_set_usb_desc(self);
@ -410,9 +411,9 @@ urtwn_attach(device_t self)
callout_init(&sc->sc_watchdog_ch, 0);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = URTWN_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
urtwn_config, URTWN_N_TRANSFER, sc, &sc->sc_mtx);
sc->sc_iface_index = URTWN_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &sc->sc_iface_index,
sc->sc_xfer, urtwn_config, URTWN_N_TRANSFER, sc, &sc->sc_mtx);
if (error) {
device_printf(self, "could not allocate USB transfers, "
"err=%s\n", usbd_errstr(error));
@ -1471,7 +1472,6 @@ urtwn_read_rom(struct urtwn_softc *sc)
sc->sc_rf_write = urtwn_r92c_rf_write;
sc->sc_power_on = urtwn_r92c_power_on;
sc->sc_dma_init = urtwn_r92c_dma_init;
return (0);
}
@ -1503,7 +1503,6 @@ urtwn_r88e_read_rom(struct urtwn_softc *sc)
sc->sc_rf_write = urtwn_r88e_rf_write;
sc->sc_power_on = urtwn_r88e_power_on;
sc->sc_dma_init = urtwn_r88e_dma_init;
return (0);
}
@ -2811,86 +2810,103 @@ urtwn_load_firmware(struct urtwn_softc *sc)
return (error);
}
static __inline int
static int
urtwn_dma_init(struct urtwn_softc *sc)
{
struct usb_endpoint *ep, *ep_end;
usb_error_t usb_err;
int error;
uint32_t reg;
int hashq, hasnq, haslq, nqueues, ntx;
int error, pagecount, npubqpages, nqpages, nrempages, tx_boundary;
/* Initialize LLT table. */
error = urtwn_llt_init(sc);
if (error != 0)
return (error);
error = sc->sc_dma_init(sc);
if (error != 0)
return (error);
/* Set Tx/Rx transfer page size. */
usb_err = urtwn_write_1(sc, R92C_PBP,
SM(R92C_PBP_PSRX, R92C_PBP_128) |
SM(R92C_PBP_PSTX, R92C_PBP_128));
if (usb_err != USB_ERR_NORMAL_COMPLETION)
/* Determine the number of bulk-out pipes. */
ntx = 0;
ep = sc->sc_udev->endpoints;
ep_end = sc->sc_udev->endpoints + sc->sc_udev->endpoints_max;
for (; ep != ep_end; ep++) {
if ((ep->edesc == NULL) ||
(ep->iface_index != sc->sc_iface_index))
continue;
if (UE_GET_DIR(ep->edesc->bEndpointAddress) == UE_DIR_OUT)
ntx++;
}
if (ntx == 0) {
device_printf(sc->sc_dev,
"%d: invalid number of Tx bulk pipes\n", ntx);
return (EIO);
return (0);
}
static int
urtwn_r92c_dma_init(struct urtwn_softc *sc)
{
int hashq, hasnq, haslq, nqueues, nqpages, nrempages;
usb_error_t error;
uint32_t reg;
}
/* Get Tx queues to USB endpoints mapping. */
hashq = hasnq = haslq = 0;
reg = urtwn_read_2(sc, R92C_USB_EP + 1);
DPRINTFN(2, "USB endpoints mapping 0x%x\n", reg);
if (MS(reg, R92C_USB_EP_HQ) != 0)
hashq = 1;
if (MS(reg, R92C_USB_EP_NQ) != 0)
hasnq = 1;
if (MS(reg, R92C_USB_EP_LQ) != 0)
haslq = 1;
hashq = hasnq = haslq = nqueues = 0;
switch (ntx) {
case 1: hashq = 1; break;
case 2: hashq = hasnq = 1; break;
case 3: case 4: hashq = hasnq = haslq = 1; break;
}
nqueues = hashq + hasnq + haslq;
if (nqueues == 0)
return (EIO);
/* Get the number of pages for each queue. */
nqpages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) / nqueues;
/* The remaining pages are assigned to the high priority queue. */
nrempages = (R92C_TX_PAGE_COUNT - R92C_PUBQ_NPAGES) % nqueues;
npubqpages = nqpages = nrempages = pagecount = 0;
if (sc->chip & URTWN_CHIP_88E)
tx_boundary = R88E_TX_PAGE_BOUNDARY;
else {
pagecount = R92C_TX_PAGE_COUNT;
npubqpages = R92C_PUBQ_NPAGES;
tx_boundary = R92C_TX_PAGE_BOUNDARY;
}
/* Set number of pages for normal priority queue. */
error = urtwn_write_1(sc, R92C_RQPN_NPQ, hasnq ? nqpages : 0);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_4(sc, R92C_RQPN,
/* Set number of pages for public queue. */
SM(R92C_RQPN_PUBQ, R92C_PUBQ_NPAGES) |
/* Set number of pages for high priority queue. */
SM(R92C_RQPN_HPQ, hashq ? nqpages + nrempages : 0) |
/* Set number of pages for low priority queue. */
SM(R92C_RQPN_LPQ, haslq ? nqpages : 0) |
/* Load values. */
R92C_RQPN_LD);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
if (sc->chip & URTWN_CHIP_88E) {
usb_err = urtwn_write_2(sc, R92C_RQPN_NPQ, 0xd);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
usb_err = urtwn_write_4(sc, R92C_RQPN, 0x808e000d);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
} else {
/* Get the number of pages for each queue. */
nqpages = (pagecount - npubqpages) / nqueues;
/*
* The remaining pages are assigned to the high priority
* queue.
*/
nrempages = (pagecount - npubqpages) % nqueues;
usb_err = urtwn_write_1(sc, R92C_RQPN_NPQ, hasnq ? nqpages : 0);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
usb_err = urtwn_write_4(sc, R92C_RQPN,
/* Set number of pages for public queue. */
SM(R92C_RQPN_PUBQ, npubqpages) |
/* Set number of pages for high priority queue. */
SM(R92C_RQPN_HPQ, hashq ? nqpages + nrempages : 0) |
/* Set number of pages for low priority queue. */
SM(R92C_RQPN_LPQ, haslq ? nqpages : 0) |
/* Load values. */
R92C_RQPN_LD);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
}
error = urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, tx_boundary);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, tx_boundary);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, tx_boundary);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_1(sc, R92C_TRXFF_BNDY, tx_boundary);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_1(sc, R92C_TDECTRL + 1, tx_boundary);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
/* Set queue to USB pipe mapping. */
@ -2913,72 +2929,21 @@ urtwn_r92c_dma_init(struct urtwn_softc *sc)
reg |= R92C_TRXDMA_CTRL_QMAP_HQ_LQ;
} else
reg |= R92C_TRXDMA_CTRL_QMAP_3EP;
error = urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
/* Set Tx/Rx transfer page boundary. */
error = urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff);
if (error != USB_ERR_NORMAL_COMPLETION)
usb_err = urtwn_write_2(sc, R92C_TRXFF_BNDY + 2,
(sc->chip & URTWN_CHIP_88E) ? 0x23ff : 0x27ff);
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
return (0);
}
static int
urtwn_r88e_dma_init(struct urtwn_softc *sc)
{
struct usb_interface *iface;
uint32_t reg;
usb_error_t error;
int nqueues;
/* Get Tx queues to USB endpoints mapping. */
iface = usbd_get_iface(sc->sc_udev, 0);
nqueues = iface->idesc->bNumEndpoints - 1;
if (nqueues == 0)
return (EIO);
/* Set number of pages for normal priority queue. */
error = urtwn_write_2(sc, R92C_RQPN_NPQ, 0x000d);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_4(sc, R92C_RQPN, 0x808e000d);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R88E_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R88E_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R88E_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TRXFF_BNDY, R88E_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
error = urtwn_write_1(sc, R92C_TDECTRL + 1, R88E_TX_PAGE_BOUNDARY);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
/* Set queue to USB pipe mapping. */
reg = urtwn_read_2(sc, R92C_TRXDMA_CTRL);
reg &= ~R92C_TRXDMA_CTRL_QMAP_M;
if (nqueues == 1)
reg |= R92C_TRXDMA_CTRL_QMAP_LQ;
else if (nqueues == 2)
reg |= R92C_TRXDMA_CTRL_QMAP_HQ_NQ;
else
reg |= R92C_TRXDMA_CTRL_QMAP_3EP;
error = urtwn_write_2(sc, R92C_TRXDMA_CTRL, reg);
if (error != USB_ERR_NORMAL_COMPLETION)
return (EIO);
/* Set Tx/Rx transfer page boundary. */
error = urtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x23ff);
if (error != USB_ERR_NORMAL_COMPLETION)
/* Set Tx/Rx transfer page size. */
usb_err = urtwn_write_1(sc, R92C_PBP,
SM(R92C_PBP_PSRX, R92C_PBP_128) |
SM(R92C_PBP_PSTX, R92C_PBP_128));
if (usb_err != USB_ERR_NORMAL_COMPLETION)
return (EIO);
return (0);

View File

@ -139,6 +139,7 @@ struct urtwn_softc {
device_t sc_dev;
struct usb_device *sc_udev;
uint8_t sc_iface_index;
int ac2idx[WME_NUM_AC];
u_int sc_flags;
#define URTWN_FLAG_CCK_HIPWR 0x01
@ -155,7 +156,6 @@ struct urtwn_softc {
void (*sc_rf_write)(struct urtwn_softc *,
int, uint8_t, uint32_t);
int (*sc_power_on)(struct urtwn_softc *);
int (*sc_dma_init)(struct urtwn_softc *);
uint8_t board_type;
uint8_t regulatory;