MFp4 //depot/projects/usb; 157429, 157433, 157443
Various changes wrt. usb procs and tasks. Submitted by: Hans Petter Selasky
This commit is contained in:
parent
1b216d3626
commit
41f3098786
@ -54,6 +54,9 @@ SYSCTL_INT(_hw_usb2_rum, OID_AUTO, debug, CTLFLAG_RW, &rum_debug, 0,
|
||||
"Debug level");
|
||||
#endif
|
||||
|
||||
#define rum_do_request(sc,req,data) \
|
||||
usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000)
|
||||
|
||||
static const struct usb2_device_id rum_devs[] = {
|
||||
{ USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM) },
|
||||
{ USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2) },
|
||||
@ -116,10 +119,13 @@ static device_detach_t rum_detach;
|
||||
static usb2_callback_t rum_bulk_read_callback;
|
||||
static usb2_callback_t rum_bulk_write_callback;
|
||||
|
||||
static usb2_proc_callback_t rum_attach_post;
|
||||
static usb2_proc_callback_t rum_task;
|
||||
static usb2_proc_callback_t rum_scantask;
|
||||
static usb2_proc_callback_t rum_promisctask;
|
||||
static usb2_proc_callback_t rum_amrr_task;
|
||||
static usb2_proc_callback_t rum_init_task;
|
||||
static usb2_proc_callback_t rum_stop_task;
|
||||
|
||||
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
|
||||
const char name[IFNAMSIZ], int unit, int opmode,
|
||||
@ -127,8 +133,8 @@ static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
static void rum_vap_delete(struct ieee80211vap *);
|
||||
static void rum_tx_free(struct rum_tx_data *, int);
|
||||
static int rum_alloc_tx_list(struct rum_softc *);
|
||||
static void rum_free_tx_list(struct rum_softc *);
|
||||
static void rum_setup_tx_list(struct rum_softc *);
|
||||
static void rum_unsetup_tx_list(struct rum_softc *);
|
||||
static int rum_newstate(struct ieee80211vap *,
|
||||
enum ieee80211_state, int);
|
||||
static void rum_setup_tx_desc(struct rum_softc *,
|
||||
@ -169,9 +175,7 @@ static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
|
||||
static const char *rum_get_rf(int);
|
||||
static void rum_read_eeprom(struct rum_softc *);
|
||||
static int rum_bbp_init(struct rum_softc *);
|
||||
static void rum_init_locked(struct rum_softc *);
|
||||
static void rum_init(void *);
|
||||
static void rum_stop(void *);
|
||||
static int rum_load_microcode(struct rum_softc *, const u_char *,
|
||||
size_t);
|
||||
static int rum_prepare_beacon(struct rum_softc *,
|
||||
@ -391,12 +395,8 @@ rum_attach(device_t self)
|
||||
{
|
||||
struct usb2_attach_arg *uaa = device_get_ivars(self);
|
||||
struct rum_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
const uint8_t *ucode = NULL;
|
||||
uint8_t bands, iface_index;
|
||||
uint32_t tmp;
|
||||
int error, ntries, size;
|
||||
uint8_t iface_index;
|
||||
int error;
|
||||
|
||||
device_set_usb2_desc(self);
|
||||
sc->sc_udev = uaa->device;
|
||||
@ -420,42 +420,64 @@ rum_attach(device_t self)
|
||||
goto detach;
|
||||
}
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
/* fork rest of the attach code */
|
||||
RUM_LOCK(sc);
|
||||
rum_queue_command(sc, rum_attach_post,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
RUM_UNLOCK(sc);
|
||||
return (0);
|
||||
|
||||
detach:
|
||||
rum_detach(self);
|
||||
return (ENXIO); /* failure */
|
||||
}
|
||||
|
||||
static void
|
||||
rum_attach_post(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct rum_task *task = (struct rum_task *)pm;
|
||||
struct rum_softc *sc = task->sc;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
unsigned int ntries;
|
||||
int error;
|
||||
uint32_t tmp;
|
||||
uint8_t bands;
|
||||
|
||||
/* retrieve RT2573 rev. no */
|
||||
for (ntries = 0; ntries < 1000; ntries++) {
|
||||
for (ntries = 0; ntries != 1000; ntries++) {
|
||||
if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
usb2_pause_mtx(&sc->sc_mtx, hz / 1000);
|
||||
}
|
||||
if (ntries == 1000) {
|
||||
device_printf(self, "timeout waiting for chip to settle\n");
|
||||
RUM_UNLOCK(sc);
|
||||
goto detach;
|
||||
device_printf(sc->sc_dev, "timeout waiting for chip to settle\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* retrieve MAC address and various other things from EEPROM */
|
||||
rum_read_eeprom(sc);
|
||||
|
||||
device_printf(self, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n",
|
||||
device_printf(sc->sc_dev, "MAC/BBP RT2573 (rev 0x%05x), RF %s\n",
|
||||
tmp, rum_get_rf(sc->rf_rev));
|
||||
|
||||
ucode = rt2573_ucode;
|
||||
size = sizeof rt2573_ucode;
|
||||
error = rum_load_microcode(sc, ucode, size);
|
||||
error = rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
|
||||
if (error != 0) {
|
||||
device_printf(self, "could not load 8051 microcode\n");
|
||||
RUM_UNLOCK(sc);
|
||||
goto detach;
|
||||
device_printf(sc->sc_dev, "could not load 8051 microcode\n");
|
||||
return;
|
||||
}
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
RUM_LOCK(sc);
|
||||
return;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
@ -468,6 +490,7 @@ rum_attach(device_t self)
|
||||
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid);
|
||||
|
||||
/* set device capabilities */
|
||||
ic->ic_caps =
|
||||
@ -516,10 +539,7 @@ rum_attach(device_t self)
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
return 0;
|
||||
detach:
|
||||
rum_detach(self);
|
||||
return (ENXIO); /* failure */
|
||||
RUM_LOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -529,20 +549,24 @@ rum_detach(device_t self)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
sc->sc_flags |= RUM_FLAG_DETACH;
|
||||
rum_stop(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
/* wait for any post attach or other command to complete */
|
||||
usb2_proc_drain(&sc->sc_tq);
|
||||
|
||||
/* stop all USB transfers first */
|
||||
/* stop all USB transfers */
|
||||
usb2_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
|
||||
usb2_proc_free(&sc->sc_tq);
|
||||
|
||||
/* free TX list, if any */
|
||||
RUM_LOCK(sc);
|
||||
rum_unsetup_tx_list(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
if (ifp) {
|
||||
bpfdetach(ifp);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
}
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -590,11 +614,8 @@ static void
|
||||
rum_vap_delete(struct ieee80211vap *vap)
|
||||
{
|
||||
struct rum_vap *rvp = RUM_VAP(vap);
|
||||
struct rum_softc *sc = rvp->sc;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
usb2_callout_stop(&rvp->amrr_ch);
|
||||
RUM_UNLOCK(sc);
|
||||
usb2_callout_drain(&rvp->amrr_ch);
|
||||
ieee80211_amrr_cleanup(&rvp->amrr);
|
||||
ieee80211_vap_detach(vap);
|
||||
free(rvp, M_80211_VAP);
|
||||
@ -619,17 +640,12 @@ rum_tx_free(struct rum_tx_data *data, int txerr)
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
|
||||
static int
|
||||
rum_alloc_tx_list(struct rum_softc *sc)
|
||||
static void
|
||||
rum_setup_tx_list(struct rum_softc *sc)
|
||||
{
|
||||
struct rum_tx_data *data;
|
||||
int i;
|
||||
|
||||
sc->tx_data = malloc(sizeof(struct rum_tx_data) * RUM_TX_LIST_COUNT,
|
||||
M_USB, M_NOWAIT|M_ZERO);
|
||||
if (sc->tx_data == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
@ -641,18 +657,20 @@ rum_alloc_tx_list(struct rum_softc *sc)
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rum_free_tx_list(struct rum_softc *sc)
|
||||
rum_unsetup_tx_list(struct rum_softc *sc)
|
||||
{
|
||||
struct rum_tx_data *data;
|
||||
int i;
|
||||
|
||||
if (sc->tx_data == NULL)
|
||||
return;
|
||||
/* make sure any subsequent use of the queues will fail */
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
|
||||
/* free up all node references and mbufs */
|
||||
for (i = 0; i < RUM_TX_LIST_COUNT; i++) {
|
||||
data = &sc->tx_data[i];
|
||||
|
||||
@ -665,8 +683,6 @@ rum_free_tx_list(struct rum_softc *sc)
|
||||
data->ni = NULL;
|
||||
}
|
||||
}
|
||||
free(sc->tx_data, M_USB);
|
||||
sc->tx_data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -683,9 +699,6 @@ rum_task(struct usb2_proc_msg *pm)
|
||||
struct ieee80211_node *ni;
|
||||
uint32_t tmp;
|
||||
|
||||
if (sc->sc_flags & RUM_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
ostate = vap->iv_state;
|
||||
|
||||
switch (sc->sc_state) {
|
||||
@ -705,7 +718,8 @@ rum_task(struct usb2_proc_msg *pm)
|
||||
rum_enable_mrr(sc);
|
||||
rum_set_txpreamble(sc);
|
||||
rum_set_basicrates(sc);
|
||||
rum_set_bssid(sc, ni->ni_bssid);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
|
||||
rum_set_bssid(sc, sc->sc_bssid);
|
||||
}
|
||||
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||
@ -773,7 +787,7 @@ rum_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
struct ieee80211_channel *c = ic->ic_curchan;
|
||||
struct rum_tx_data *data;
|
||||
struct mbuf *m;
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
@ -790,15 +804,6 @@ rum_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
#if 0
|
||||
if (sc->sc_flags & RUM_FLAG_WAIT_COMMAND) {
|
||||
/*
|
||||
* don't send anything while a command is pending !
|
||||
*/
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
data = STAILQ_FIRST(&sc->tx_q);
|
||||
if (data) {
|
||||
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
|
||||
@ -845,6 +850,13 @@ tr_setup:
|
||||
DPRINTFN(11, "transfer error, %s\n",
|
||||
usb2_errstr(xfer->error));
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
if (data != NULL) {
|
||||
rum_tx_free(data, xfer->error);
|
||||
xfer->priv_fifo = NULL;
|
||||
}
|
||||
|
||||
if (xfer->error == USB_ERR_STALLED) {
|
||||
/* try to clear stall first */
|
||||
xfer->flags.stall_pipe = 1;
|
||||
@ -852,13 +864,6 @@ tr_setup:
|
||||
}
|
||||
if (xfer->error == USB_ERR_TIMEOUT)
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
if (data != NULL) {
|
||||
rum_tx_free(data, xfer->error);
|
||||
xfer->priv_fifo = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -873,7 +878,7 @@ rum_bulk_read_callback(struct usb2_xfer *xfer)
|
||||
struct mbuf *m = NULL;
|
||||
uint32_t flags;
|
||||
uint8_t rssi = 0;
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
@ -965,7 +970,6 @@ tr_setup:
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1333,15 +1337,20 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
RUM_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
rum_init_locked(sc);
|
||||
rum_queue_command(sc, rum_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
startall = 1;
|
||||
} else
|
||||
rum_queue_command(sc, rum_promisctask,
|
||||
&sc->sc_promisctask[0].hdr,
|
||||
&sc->sc_promisctask[1].hdr);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rum_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
rum_queue_command(sc, rum_stop_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
}
|
||||
}
|
||||
RUM_UNLOCK(sc);
|
||||
if (startall)
|
||||
@ -1372,7 +1381,7 @@ rum_eeprom_read(struct rum_softc *sc, uint16_t addr, void *buf, int len)
|
||||
USETW(req.wIndex, addr);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = rum_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1401,7 +1410,7 @@ rum_read_multi(struct rum_softc *sc, uint16_t reg, void *buf, int len)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = rum_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not multi read MAC register: %s\n",
|
||||
@ -1429,7 +1438,7 @@ rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = rum_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not multi write MAC register: %s\n",
|
||||
@ -1787,9 +1796,6 @@ rum_promisctask(struct usb2_proc_msg *pm)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
if (sc->sc_flags & RUM_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR0);
|
||||
|
||||
tmp &= ~RT2573_DROP_NOT_TO_ME;
|
||||
@ -1817,15 +1823,13 @@ rum_get_rf(int rev)
|
||||
static void
|
||||
rum_read_eeprom(struct rum_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t val;
|
||||
#ifdef RUM_DEBUG
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* read MAC address */
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, ic->ic_myaddr, 6);
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6);
|
||||
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
|
||||
val = le16toh(val);
|
||||
@ -1933,9 +1937,11 @@ rum_bbp_init(struct rum_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
rum_init_locked(struct rum_softc *sc)
|
||||
rum_init_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
#define N(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
struct rum_task *task = (struct rum_task *)pm;
|
||||
struct rum_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
@ -1944,10 +1950,7 @@ rum_init_locked(struct rum_softc *sc)
|
||||
|
||||
RUM_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & RUM_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
rum_stop(sc);
|
||||
rum_stop_task(pm);
|
||||
|
||||
/* initialize MAC registers to default values */
|
||||
for (i = 0; i < N(rum_def_mac); i++)
|
||||
@ -1990,11 +1993,7 @@ rum_init_locked(struct rum_softc *sc)
|
||||
/*
|
||||
* Allocate Tx and Rx xfer queues.
|
||||
*/
|
||||
error = rum_alloc_tx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx list\n");
|
||||
goto fail;
|
||||
}
|
||||
rum_setup_tx_list(sc);
|
||||
|
||||
/* update Rx filter */
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR0) & 0xffff;
|
||||
@ -2015,7 +2014,7 @@ rum_init_locked(struct rum_softc *sc)
|
||||
usb2_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
|
||||
return;
|
||||
|
||||
fail: rum_stop(sc);
|
||||
fail: rum_stop_task(pm);
|
||||
#undef N
|
||||
}
|
||||
|
||||
@ -2027,7 +2026,9 @@ rum_init(void *priv)
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rum_init_locked(sc);
|
||||
rum_queue_command(sc, rum_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
@ -2035,9 +2036,10 @@ rum_init(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
rum_stop(void *priv)
|
||||
rum_stop_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct rum_softc *sc = priv;
|
||||
struct rum_task *task = (struct rum_task *)pm;
|
||||
struct rum_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
@ -2045,17 +2047,17 @@ rum_stop(void *priv)
|
||||
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
/*
|
||||
* stop all the transfers, if not already stopped:
|
||||
* Drain the USB transfers, if not already drained:
|
||||
*/
|
||||
usb2_transfer_stop(sc->sc_xfer[RUM_BULK_WR]);
|
||||
usb2_transfer_stop(sc->sc_xfer[RUM_BULK_RD]);
|
||||
usb2_transfer_drain(sc->sc_xfer[RUM_BULK_WR]);
|
||||
usb2_transfer_drain(sc->sc_xfer[RUM_BULK_RD]);
|
||||
|
||||
rum_free_tx_list(sc);
|
||||
RUM_LOCK(sc);
|
||||
|
||||
/* Stop now if the device has vanished */
|
||||
if (sc->sc_flags & RUM_FLAG_DETACH)
|
||||
return;
|
||||
rum_unsetup_tx_list(sc);
|
||||
|
||||
/* disable Rx */
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR0);
|
||||
@ -2083,7 +2085,7 @@ rum_load_microcode(struct rum_softc *sc, const u_char *ucode, size_t size)
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
|
||||
error = rum_do_request(sc, &req, NULL);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not run firmware: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -2291,14 +2293,10 @@ rum_scantask(struct usb2_proc_msg *pm)
|
||||
struct rum_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
uint32_t tmp;
|
||||
|
||||
RUM_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & RUM_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
switch (sc->sc_scan_action) {
|
||||
case RUM_SCAN_START:
|
||||
/* abort TSF synchronization */
|
||||
@ -2307,19 +2305,13 @@ rum_scantask(struct usb2_proc_msg *pm)
|
||||
rum_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
break;
|
||||
|
||||
case RUM_SCAN_END:
|
||||
rum_enable_tsf_sync(sc);
|
||||
/* XXX keep local copy */
|
||||
rum_set_bssid(sc, vap->iv_bss->ni_bssid);
|
||||
break;
|
||||
|
||||
case RUM_SET_CHANNEL:
|
||||
rum_set_chan(sc, ic->ic_curchan);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("unknown scan action %d\n", sc->sc_scan_action);
|
||||
/* NEVER REACHED */
|
||||
default: /* RUM_SCAN_END */
|
||||
rum_enable_tsf_sync(sc);
|
||||
rum_set_bssid(sc, sc->sc_bssid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2395,6 +2387,11 @@ rum_queue_command(struct rum_softc *sc, usb2_proc_callback_t *fn,
|
||||
task->hdr.pm_callback = fn;
|
||||
task->sc = sc;
|
||||
|
||||
/*
|
||||
* Init and stop must be synchronous!
|
||||
*/
|
||||
if ((fn == rum_init_task) || (fn == rum_stop_task))
|
||||
usb2_proc_mwait(&sc->sc_tq, t0, t1);
|
||||
}
|
||||
|
||||
static device_method_t rum_methods[] = {
|
||||
|
@ -100,14 +100,14 @@ struct rum_softc {
|
||||
struct usb2_process sc_tq;
|
||||
|
||||
const struct ieee80211_rate_table *sc_rates;
|
||||
struct usb2_xfer *sc_xfer[RUM_N_TRANSFER];
|
||||
|
||||
uint8_t rf_rev;
|
||||
uint8_t rffreq;
|
||||
|
||||
struct usb2_xfer *sc_xfer[RUM_N_TRANSFER];
|
||||
|
||||
enum ieee80211_state sc_state;
|
||||
int sc_arg;
|
||||
struct rum_task sc_synctask[2];
|
||||
struct rum_task sc_task[2];
|
||||
struct rum_task sc_promisctask[2];
|
||||
struct rum_task sc_scantask[2];
|
||||
@ -116,7 +116,7 @@ struct rum_softc {
|
||||
#define RUM_SCAN_END 1
|
||||
#define RUM_SET_CHANNEL 2
|
||||
|
||||
struct rum_tx_data *tx_data;
|
||||
struct rum_tx_data tx_data[RUM_TX_LIST_COUNT];
|
||||
rum_txdhead tx_q;
|
||||
rum_txdhead tx_free;
|
||||
int tx_nfree;
|
||||
@ -124,12 +124,10 @@ struct rum_softc {
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
int sc_flags;
|
||||
#define RUM_FLAG_DETACH 0x0001
|
||||
|
||||
uint32_t sta[6];
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[44];
|
||||
uint8_t sc_bssid[6];
|
||||
|
||||
struct {
|
||||
uint8_t val;
|
||||
|
@ -55,6 +55,9 @@ SYSCTL_INT(_hw_usb2_ural, OID_AUTO, debug, CTLFLAG_RW, &ural_debug, 0,
|
||||
"Debug level");
|
||||
#endif
|
||||
|
||||
#define ural_do_request(sc,req,data) \
|
||||
usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000)
|
||||
|
||||
#define URAL_RSSI(rssi) \
|
||||
((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ? \
|
||||
((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0)
|
||||
@ -95,10 +98,13 @@ static const struct usb2_device_id ural_devs[] = {
|
||||
static usb2_callback_t ural_bulk_read_callback;
|
||||
static usb2_callback_t ural_bulk_write_callback;
|
||||
|
||||
static usb2_proc_callback_t ural_attach_post;
|
||||
static usb2_proc_callback_t ural_task;
|
||||
static usb2_proc_callback_t ural_scantask;
|
||||
static usb2_proc_callback_t ural_promisctask;
|
||||
static usb2_proc_callback_t ural_amrr_task;
|
||||
static usb2_proc_callback_t ural_init_task;
|
||||
static usb2_proc_callback_t ural_stop_task;
|
||||
|
||||
static struct ieee80211vap *ural_vap_create(struct ieee80211com *,
|
||||
const char name[IFNAMSIZ], int unit, int opmode,
|
||||
@ -106,8 +112,8 @@ static struct ieee80211vap *ural_vap_create(struct ieee80211com *,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
static void ural_vap_delete(struct ieee80211vap *);
|
||||
static void ural_tx_free(struct ural_tx_data *, int);
|
||||
static int ural_alloc_tx_list(struct ural_softc *);
|
||||
static void ural_free_tx_list(struct ural_softc *);
|
||||
static void ural_setup_tx_list(struct ural_softc *);
|
||||
static void ural_unsetup_tx_list(struct ural_softc *);
|
||||
static int ural_newstate(struct ieee80211vap *,
|
||||
enum ieee80211_state, int);
|
||||
static void ural_setup_tx_desc(struct ural_softc *,
|
||||
@ -153,9 +159,7 @@ static void ural_read_eeprom(struct ural_softc *);
|
||||
static int ural_bbp_init(struct ural_softc *);
|
||||
static void ural_set_txantenna(struct ural_softc *, int);
|
||||
static void ural_set_rxantenna(struct ural_softc *, int);
|
||||
static void ural_init_locked(struct ural_softc *);
|
||||
static void ural_init(void *);
|
||||
static void ural_stop(void *);
|
||||
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void ural_amrr_start(struct ural_softc *,
|
||||
@ -394,10 +398,8 @@ ural_attach(device_t self)
|
||||
{
|
||||
struct usb2_attach_arg *uaa = device_get_ivars(self);
|
||||
struct ural_softc *sc = device_get_softc(self);
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
int error;
|
||||
uint8_t bands, iface_index;
|
||||
uint8_t iface_index;
|
||||
|
||||
device_set_usb2_desc(self);
|
||||
sc->sc_udev = uaa->device;
|
||||
@ -422,14 +424,28 @@ ural_attach(device_t self)
|
||||
goto detach;
|
||||
}
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
/* fork rest of the attach code */
|
||||
RAL_LOCK(sc);
|
||||
ural_queue_command(sc, ural_attach_post,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
RAL_UNLOCK(sc);
|
||||
return (0);
|
||||
|
||||
detach:
|
||||
ural_detach(self);
|
||||
return (ENXIO); /* failure */
|
||||
}
|
||||
|
||||
static void
|
||||
ural_attach_post(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct ural_task *task = (struct ural_task *)pm;
|
||||
struct ural_softc *sc = task->sc;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
uint8_t bands;
|
||||
|
||||
/* retrieve RT2570 rev. no */
|
||||
sc->asic_rev = ural_read(sc, RAL_MAC_CSR0);
|
||||
|
||||
@ -440,6 +456,14 @@ ural_attach(device_t self)
|
||||
device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
|
||||
sc->asic_rev, ural_get_rf(sc->rf_rev));
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
RAL_LOCK(sc);
|
||||
return;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
@ -452,6 +476,7 @@ ural_attach(device_t self)
|
||||
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid);
|
||||
|
||||
/* set device capabilities */
|
||||
ic->ic_caps =
|
||||
@ -500,11 +525,7 @@ ural_attach(device_t self)
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
return (0); /* success */
|
||||
|
||||
detach:
|
||||
ural_detach(self);
|
||||
return (ENXIO); /* failure */
|
||||
RAL_LOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -514,20 +535,24 @@ ural_detach(device_t self)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
sc->sc_flags |= URAL_FLAG_DETACH;
|
||||
ural_stop(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
/* wait for any post attach or other command to complete */
|
||||
usb2_proc_drain(&sc->sc_tq);
|
||||
|
||||
/* stop all USB transfers first */
|
||||
/* stop all USB transfers */
|
||||
usb2_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
|
||||
usb2_proc_free(&sc->sc_tq);
|
||||
|
||||
/* free TX list, if any */
|
||||
RAL_LOCK(sc);
|
||||
ural_unsetup_tx_list(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (ifp) {
|
||||
bpfdetach(ifp);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
}
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -575,11 +600,8 @@ static void
|
||||
ural_vap_delete(struct ieee80211vap *vap)
|
||||
{
|
||||
struct ural_vap *uvp = URAL_VAP(vap);
|
||||
struct ural_softc *sc = uvp->sc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
usb2_callout_stop(&uvp->amrr_ch);
|
||||
RAL_UNLOCK(sc);
|
||||
usb2_callout_drain(&uvp->amrr_ch);
|
||||
ieee80211_amrr_cleanup(&uvp->amrr);
|
||||
ieee80211_vap_detach(vap);
|
||||
free(uvp, M_80211_VAP);
|
||||
@ -604,17 +626,12 @@ ural_tx_free(struct ural_tx_data *data, int txerr)
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
|
||||
static int
|
||||
ural_alloc_tx_list(struct ural_softc *sc)
|
||||
static void
|
||||
ural_setup_tx_list(struct ural_softc *sc)
|
||||
{
|
||||
struct ural_tx_data *data;
|
||||
int i;
|
||||
|
||||
sc->tx_data = malloc(sizeof(struct ural_tx_data) * RAL_TX_LIST_COUNT,
|
||||
M_USB, M_NOWAIT|M_ZERO);
|
||||
if (sc->tx_data == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
@ -626,18 +643,20 @@ ural_alloc_tx_list(struct ural_softc *sc)
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ural_free_tx_list(struct ural_softc *sc)
|
||||
ural_unsetup_tx_list(struct ural_softc *sc)
|
||||
{
|
||||
struct ural_tx_data *data;
|
||||
int i;
|
||||
|
||||
if (sc->tx_data == NULL)
|
||||
return;
|
||||
/* make sure any subsequent use of the queues will fail */
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
|
||||
/* free up all node references and mbufs */
|
||||
for (i = 0; i < RAL_TX_LIST_COUNT; i++) {
|
||||
data = &sc->tx_data[i];
|
||||
|
||||
@ -650,8 +669,6 @@ ural_free_tx_list(struct ural_softc *sc)
|
||||
data->ni = NULL;
|
||||
}
|
||||
}
|
||||
free(sc->tx_data, M_USB);
|
||||
sc->tx_data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -668,9 +685,6 @@ ural_task(struct usb2_proc_msg *pm)
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
if (sc->sc_flags & URAL_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
ostate = vap->iv_state;
|
||||
|
||||
switch (sc->sc_state) {
|
||||
@ -691,7 +705,8 @@ ural_task(struct usb2_proc_msg *pm)
|
||||
ural_update_slot(ic->ic_ifp);
|
||||
ural_set_txpreamble(sc);
|
||||
ural_set_basicrates(sc, ic->ic_bsschan);
|
||||
ural_set_bssid(sc, ni->ni_bssid);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
|
||||
ural_set_bssid(sc, sc->sc_bssid);
|
||||
}
|
||||
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||
@ -743,26 +758,27 @@ ural_scantask(struct usb2_proc_msg *pm)
|
||||
struct ural_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
RAL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & URAL_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
if (sc->sc_scan_action == URAL_SCAN_START) {
|
||||
switch (sc->sc_scan_action) {
|
||||
case URAL_SCAN_START:
|
||||
/* abort TSF synchronization */
|
||||
DPRINTF("starting scan\n");
|
||||
ural_write(sc, RAL_TXRX_CSR19, 0);
|
||||
ural_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
} else if (sc->sc_scan_action == URAL_SET_CHANNEL) {
|
||||
break;
|
||||
|
||||
case URAL_SET_CHANNEL:
|
||||
ural_set_chan(sc, ic->ic_curchan);
|
||||
} else {
|
||||
break;
|
||||
|
||||
default: /* URAL_SCAN_END */
|
||||
DPRINTF("stopping scan\n");
|
||||
ural_enable_tsf_sync(sc);
|
||||
/* XXX keep local copy */
|
||||
ural_set_bssid(sc, vap->iv_bss->ni_bssid);
|
||||
}
|
||||
ural_set_bssid(sc, sc->sc_bssid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -806,7 +822,7 @@ ural_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
struct ieee80211_channel *c = ic->ic_curchan;
|
||||
struct ural_tx_data *data;
|
||||
struct mbuf *m;
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
@ -823,15 +839,6 @@ ural_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
#if 0
|
||||
if (sc->sc_flags & URAL_FLAG_WAIT_COMMAND) {
|
||||
/*
|
||||
* don't send anything while a command is pending !
|
||||
*/
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
data = STAILQ_FIRST(&sc->tx_q);
|
||||
if (data) {
|
||||
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
|
||||
@ -878,6 +885,13 @@ tr_setup:
|
||||
DPRINTFN(11, "transfer error, %s\n",
|
||||
usb2_errstr(xfer->error));
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
if (data != NULL) {
|
||||
ural_tx_free(data, xfer->error);
|
||||
xfer->priv_fifo = NULL;
|
||||
}
|
||||
|
||||
if (xfer->error == USB_ERR_STALLED) {
|
||||
/* try to clear stall first */
|
||||
xfer->flags.stall_pipe = 1;
|
||||
@ -885,13 +899,6 @@ tr_setup:
|
||||
}
|
||||
if (xfer->error == USB_ERR_TIMEOUT)
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
if (data != NULL) {
|
||||
ural_tx_free(data, xfer->error);
|
||||
xfer->priv_fifo = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -906,7 +913,7 @@ ural_bulk_read_callback(struct usb2_xfer *xfer)
|
||||
struct mbuf *m = NULL;
|
||||
uint32_t flags;
|
||||
uint8_t rssi = 0;
|
||||
int len;
|
||||
unsigned int len;
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
@ -1001,7 +1008,6 @@ tr_setup:
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1406,15 +1412,20 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
RAL_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
ural_init_locked(sc);
|
||||
ural_queue_command(sc, ural_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
startall = 1;
|
||||
} else
|
||||
ural_queue_command(sc, ural_promisctask,
|
||||
&sc->sc_promisctask[0].hdr,
|
||||
&sc->sc_promisctask[1].hdr);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ural_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
ural_queue_command(sc, ural_stop_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
}
|
||||
}
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
@ -1443,7 +1454,7 @@ ural_set_testmode(struct ural_softc *sc)
|
||||
USETW(req.wIndex, 1);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
|
||||
error = ural_do_request(sc, &req, NULL);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not set test mode: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1462,7 +1473,7 @@ ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len)
|
||||
USETW(req.wIndex, addr);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = ural_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1482,7 +1493,7 @@ ural_read(struct ural_softc *sc, uint16_t reg)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, sizeof (uint16_t));
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, &val);
|
||||
error = ural_do_request(sc, &req, &val);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read MAC register: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1504,7 +1515,7 @@ ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = ural_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read MAC register: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1523,7 +1534,7 @@ ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, 0);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
|
||||
error = ural_do_request(sc, &req, NULL);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not write MAC register: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1542,7 +1553,7 @@ ural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
|
||||
USETW(req.wIndex, reg);
|
||||
USETW(req.wLength, len);
|
||||
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, buf);
|
||||
error = ural_do_request(sc, &req, buf);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not write MAC register: %s\n",
|
||||
usb2_errstr(error));
|
||||
@ -1937,9 +1948,6 @@ ural_promisctask(struct usb2_proc_msg *pm)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
if (sc->sc_flags & URAL_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
tmp = ural_read(sc, RAL_TXRX_CSR2);
|
||||
|
||||
tmp &= ~RAL_DROP_NOT_TO_ME;
|
||||
@ -1970,8 +1978,6 @@ ural_get_rf(int rev)
|
||||
static void
|
||||
ural_read_eeprom(struct ural_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t val;
|
||||
|
||||
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
|
||||
@ -1984,7 +1990,7 @@ ural_read_eeprom(struct ural_softc *sc)
|
||||
sc->nb_ant = val & 0x3;
|
||||
|
||||
/* read MAC address */
|
||||
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_myaddr, 6);
|
||||
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
|
||||
|
||||
/* read default values for BBP registers */
|
||||
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
|
||||
@ -2077,24 +2083,22 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
|
||||
}
|
||||
|
||||
static void
|
||||
ural_init_locked(struct ural_softc *sc)
|
||||
ural_init_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
#define N(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
struct ural_task *task = (struct ural_task *)pm;
|
||||
struct ural_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t tmp;
|
||||
usb2_error_t error;
|
||||
int i, ntries;
|
||||
|
||||
RAL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & URAL_FLAG_DETACH)
|
||||
return;
|
||||
|
||||
ural_set_testmode(sc);
|
||||
ural_write(sc, 0x308, 0x00f0); /* XXX magic */
|
||||
|
||||
ural_stop(sc);
|
||||
ural_stop_task(pm);
|
||||
|
||||
/* initialize MAC registers to default values */
|
||||
for (i = 0; i < N(ural_def_mac); i++)
|
||||
@ -2137,11 +2141,7 @@ ural_init_locked(struct ural_softc *sc)
|
||||
/*
|
||||
* Allocate Tx and Rx xfer queues.
|
||||
*/
|
||||
error = ural_alloc_tx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx list\n");
|
||||
goto fail;
|
||||
}
|
||||
ural_setup_tx_list(sc);
|
||||
|
||||
/* kick Rx */
|
||||
tmp = RAL_DROP_PHY | RAL_DROP_CRC;
|
||||
@ -2159,7 +2159,7 @@ ural_init_locked(struct ural_softc *sc)
|
||||
usb2_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
|
||||
return;
|
||||
|
||||
fail: ural_stop(sc);
|
||||
fail: ural_stop_task(pm);
|
||||
#undef N
|
||||
}
|
||||
|
||||
@ -2171,7 +2171,9 @@ ural_init(void *priv)
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
ural_init_locked(sc);
|
||||
ural_queue_command(sc, ural_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
@ -2179,9 +2181,10 @@ ural_init(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
ural_stop(void *priv)
|
||||
ural_stop_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct ural_softc *sc = priv;
|
||||
struct ural_task *task = (struct ural_task *)pm;
|
||||
struct ural_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
RAL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
@ -2189,16 +2192,14 @@ ural_stop(void *priv)
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/*
|
||||
* stop all the transfers, if not already stopped:
|
||||
* Drain all the transfers, if not already drained:
|
||||
*/
|
||||
usb2_transfer_stop(sc->sc_xfer[URAL_BULK_WR]);
|
||||
usb2_transfer_stop(sc->sc_xfer[URAL_BULK_RD]);
|
||||
RAL_UNLOCK(sc);
|
||||
usb2_transfer_drain(sc->sc_xfer[URAL_BULK_WR]);
|
||||
usb2_transfer_drain(sc->sc_xfer[URAL_BULK_RD]);
|
||||
RAL_LOCK(sc);
|
||||
|
||||
ural_free_tx_list(sc);
|
||||
|
||||
/* Stop now if the device has vanished */
|
||||
if (sc->sc_flags & URAL_FLAG_DETACH)
|
||||
return;
|
||||
ural_unsetup_tx_list(sc);
|
||||
|
||||
/* disable Rx */
|
||||
ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
|
||||
@ -2333,5 +2334,10 @@ ural_queue_command(struct ural_softc *sc, usb2_proc_callback_t *fn,
|
||||
task->hdr.pm_callback = fn;
|
||||
task->sc = sc;
|
||||
|
||||
/*
|
||||
* Init and stop must be synchronous!
|
||||
*/
|
||||
if ((fn == ural_init_task) || (fn == ural_stop_task))
|
||||
usb2_proc_mwait(&sc->sc_tq, t0, t1);
|
||||
}
|
||||
|
||||
|
@ -114,11 +114,12 @@ struct ural_softc {
|
||||
enum ieee80211_state sc_state;
|
||||
int sc_arg;
|
||||
int sc_scan_action; /* should be an enum */
|
||||
struct ural_task sc_synctask[2];
|
||||
struct ural_task sc_task[2];
|
||||
struct ural_task sc_promisctask[2];
|
||||
struct ural_task sc_scantask[2];
|
||||
|
||||
struct ural_tx_data *tx_data;
|
||||
struct ural_tx_data tx_data[RAL_TX_LIST_COUNT];
|
||||
ural_txdhead tx_q;
|
||||
ural_txdhead tx_free;
|
||||
int tx_nfree;
|
||||
@ -126,12 +127,10 @@ struct ural_softc {
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
int sc_flags;
|
||||
#define URAL_FLAG_DETACH 0x0001
|
||||
|
||||
uint16_t sta[11];
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[14];
|
||||
uint8_t sc_bssid[6];
|
||||
|
||||
struct {
|
||||
uint8_t val;
|
||||
|
@ -64,7 +64,7 @@ enum {
|
||||
ZYD_DEBUG_ANY = 0xffffffff
|
||||
};
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
if (sc->sc_debug & (m)) \
|
||||
if (zyd_debug & (m)) \
|
||||
printf("%s: " fmt, __func__, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
@ -73,6 +73,9 @@ enum {
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define zyd_do_request(sc,req,data) \
|
||||
usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000)
|
||||
|
||||
static device_probe_t zyd_match;
|
||||
static device_attach_t zyd_attach;
|
||||
static device_detach_t zyd_detach;
|
||||
@ -82,9 +85,12 @@ static usb2_callback_t zyd_intr_write_callback;
|
||||
static usb2_callback_t zyd_bulk_read_callback;
|
||||
static usb2_callback_t zyd_bulk_write_callback;
|
||||
|
||||
static usb2_proc_callback_t zyd_attach_post;
|
||||
static usb2_proc_callback_t zyd_task;
|
||||
static usb2_proc_callback_t zyd_scantask;
|
||||
static usb2_proc_callback_t zyd_multitask;
|
||||
static usb2_proc_callback_t zyd_init_task;
|
||||
static usb2_proc_callback_t zyd_stop_task;
|
||||
|
||||
static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
|
||||
const char name[IFNAMSIZ], int unit, int opmode,
|
||||
@ -92,8 +98,8 @@ static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
static void zyd_vap_delete(struct ieee80211vap *);
|
||||
static void zyd_tx_free(struct zyd_tx_data *, int);
|
||||
static int zyd_alloc_tx_list(struct zyd_softc *);
|
||||
static void zyd_free_tx_list(struct zyd_softc *);
|
||||
static void zyd_setup_tx_list(struct zyd_softc *);
|
||||
static void zyd_unsetup_tx_list(struct zyd_softc *);
|
||||
static struct ieee80211_node *zyd_node_alloc(struct ieee80211vap *,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
static int zyd_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
||||
@ -130,15 +136,12 @@ static void zyd_start(struct ifnet *);
|
||||
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void zyd_init_locked(struct zyd_softc *);
|
||||
static void zyd_init(void *);
|
||||
static void zyd_stop(struct zyd_softc *);
|
||||
static int zyd_loadfirmware(struct zyd_softc *);
|
||||
static void zyd_newassoc(struct ieee80211_node *, int);
|
||||
static void zyd_scan_start(struct ieee80211com *);
|
||||
static void zyd_scan_end(struct ieee80211com *);
|
||||
static void zyd_set_channel(struct ieee80211com *);
|
||||
static void zyd_wakeup(struct zyd_softc *);
|
||||
static int zyd_rfmd_init(struct zyd_rf *);
|
||||
static int zyd_rfmd_switch_radio(struct zyd_rf *, int);
|
||||
static int zyd_rfmd_set_channel(struct zyd_rf *, uint8_t);
|
||||
@ -290,7 +293,7 @@ zyd_match(device_t dev)
|
||||
|
||||
if (uaa->usb2_mode != USB_MODE_HOST)
|
||||
return (ENXIO);
|
||||
if (uaa->info.bConfigIndex != 0)
|
||||
if (uaa->info.bConfigIndex != ZYD_CONFIG_INDEX)
|
||||
return (ENXIO);
|
||||
if (uaa->info.bIfaceIndex != ZYD_IFACE_INDEX)
|
||||
return (ENXIO);
|
||||
@ -301,12 +304,10 @@ zyd_match(device_t dev)
|
||||
static int
|
||||
zyd_attach(device_t dev)
|
||||
{
|
||||
int error = ENXIO;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
struct usb2_attach_arg *uaa = device_get_ivars(dev);
|
||||
struct zyd_softc *sc = device_get_softc(dev);
|
||||
uint8_t bands, iface_index;
|
||||
int error;
|
||||
uint8_t iface_index;
|
||||
|
||||
if (uaa->info.bcdDevice < 0x4330) {
|
||||
device_printf(dev, "device version mismatch: 0x%X "
|
||||
@ -319,9 +320,7 @@ zyd_attach(device_t dev)
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_udev = uaa->device;
|
||||
sc->sc_macrev = USB_GET_DRIVER_INFO(uaa);
|
||||
#ifdef USB_DEBUG
|
||||
sc->sc_debug = zyd_debug;
|
||||
#endif
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
|
||||
@ -334,26 +333,50 @@ zyd_attach(device_t dev)
|
||||
if (error) {
|
||||
device_printf(dev, "could not allocate USB transfers, "
|
||||
"err=%s\n", usb2_errstr(error));
|
||||
goto fail0;
|
||||
goto detach;
|
||||
}
|
||||
error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx,
|
||||
device_get_nameunit(dev), USB_PRI_MED);
|
||||
if (error) {
|
||||
device_printf(dev, "could not setup config thread!\n");
|
||||
goto fail0;
|
||||
goto detach;
|
||||
}
|
||||
|
||||
/* fork rest of the attach code */
|
||||
ZYD_LOCK(sc);
|
||||
zyd_queue_command(sc, zyd_attach_post,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
ZYD_UNLOCK(sc);
|
||||
return (0);
|
||||
|
||||
detach:
|
||||
zyd_detach(dev);
|
||||
return (ENXIO); /* failure */
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_attach_post(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct zyd_task *task = (struct zyd_task *)pm;
|
||||
struct zyd_softc *sc = task->sc;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
int error;
|
||||
uint8_t bands;
|
||||
|
||||
if ((error = zyd_get_macaddr(sc)) != 0) {
|
||||
device_printf(sc->sc_dev, "could not read EEPROM\n");
|
||||
error = ENXIO;
|
||||
goto fail0;
|
||||
return;
|
||||
}
|
||||
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
error = ENXIO;
|
||||
goto fail0;
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
ZYD_LOCK(sc);
|
||||
return;
|
||||
}
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
|
||||
@ -409,10 +432,7 @@ zyd_attach(device_t dev)
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
return (0);
|
||||
|
||||
fail0: mtx_destroy(&sc->sc_mtx);
|
||||
return (error);
|
||||
ZYD_LOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -422,21 +442,22 @@ zyd_detach(device_t dev)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
sc->sc_flags |= ZYD_FLAG_DETACHING;
|
||||
zyd_stop(sc);
|
||||
zyd_wakeup(sc);
|
||||
ZYD_UNLOCK(sc);
|
||||
/* wait for any post attach or other command to complete */
|
||||
usb2_proc_drain(&sc->sc_tq);
|
||||
|
||||
/* stop all USB transfers first */
|
||||
/* stop all USB transfers */
|
||||
usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
|
||||
usb2_proc_free(&sc->sc_tq);
|
||||
|
||||
/* free TX list, if any */
|
||||
zyd_unsetup_tx_list(sc);
|
||||
|
||||
if (ifp) {
|
||||
bpfdetach(ifp);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
}
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -507,17 +528,12 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr)
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
|
||||
static int
|
||||
zyd_alloc_tx_list(struct zyd_softc *sc)
|
||||
static void
|
||||
zyd_setup_tx_list(struct zyd_softc *sc)
|
||||
{
|
||||
struct zyd_tx_data *data;
|
||||
int i;
|
||||
|
||||
sc->tx_data = malloc(sizeof(struct zyd_tx_data) * ZYD_TX_LIST_CNT,
|
||||
M_USB, M_NOWAIT|M_ZERO);
|
||||
if (sc->tx_data == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
@ -529,18 +545,20 @@ zyd_alloc_tx_list(struct zyd_softc *sc)
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
sc->tx_nfree++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_free_tx_list(struct zyd_softc *sc)
|
||||
zyd_unsetup_tx_list(struct zyd_softc *sc)
|
||||
{
|
||||
struct zyd_tx_data *data;
|
||||
int i;
|
||||
|
||||
if (sc->tx_data == NULL)
|
||||
return;
|
||||
/* make sure any subsequent use of the queues will fail */
|
||||
sc->tx_nfree = 0;
|
||||
STAILQ_INIT(&sc->tx_q);
|
||||
STAILQ_INIT(&sc->tx_free);
|
||||
|
||||
/* free up all node references and mbufs */
|
||||
for (i = 0; i < ZYD_TX_LIST_CNT; i++) {
|
||||
data = &sc->tx_data[i];
|
||||
|
||||
@ -553,8 +571,6 @@ zyd_free_tx_list(struct zyd_softc *sc)
|
||||
data->ni = NULL;
|
||||
}
|
||||
}
|
||||
free(sc->tx_data, M_USB);
|
||||
sc->tx_data = NULL;
|
||||
}
|
||||
|
||||
/* ARGUSED */
|
||||
@ -802,7 +818,8 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
|
||||
|
||||
if (ilen > sizeof(cmd.data))
|
||||
return (EINVAL);
|
||||
if (sc->sc_flags & ZYD_FLAG_DETACHING)
|
||||
|
||||
if (usb2_proc_is_gone(&sc->sc_tq))
|
||||
return (ENXIO);
|
||||
|
||||
cmd.code = htole16(code);
|
||||
@ -1899,13 +1916,11 @@ zyd_get_macaddr(struct zyd_softc *sc)
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, IEEE80211_ADDR_LEN);
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
error = usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, sc->sc_bssid);
|
||||
error = zyd_do_request(sc, &req, sc->sc_bssid);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
|
||||
usb2_errstr(error));
|
||||
}
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
}
|
||||
@ -2477,16 +2492,6 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer)
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
#if 0
|
||||
if (sc->sc_flags & ZYD_FLAG_WAIT_COMMAND) {
|
||||
/*
|
||||
* don't send anything while a command is pending !
|
||||
*/
|
||||
DPRINTF(sc, ZYD_DEBUG_ANY, "wait command\n");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
data = STAILQ_FIRST(&sc->tx_q);
|
||||
if (data) {
|
||||
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
|
||||
@ -2523,6 +2528,12 @@ tr_setup:
|
||||
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n",
|
||||
usb2_errstr(xfer->error));
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
xfer->priv_fifo = NULL;
|
||||
if (data != NULL)
|
||||
zyd_tx_free(data, xfer->error);
|
||||
|
||||
if (xfer->error == USB_ERR_STALLED) {
|
||||
/* try to clear stall first */
|
||||
xfer->flags.stall_pipe = 1;
|
||||
@ -2530,12 +2541,6 @@ tr_setup:
|
||||
}
|
||||
if (xfer->error == USB_ERR_TIMEOUT)
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
|
||||
ifp->if_oerrors++;
|
||||
data = xfer->priv_fifo;
|
||||
xfer->priv_fifo = NULL;
|
||||
if (data != NULL && ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
zyd_tx_free(data, xfer->error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2729,12 +2734,17 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
(IFF_ALLMULTI | IFF_PROMISC))
|
||||
zyd_set_multi(sc);
|
||||
} else {
|
||||
zyd_init_locked(sc);
|
||||
zyd_queue_command(sc, zyd_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
zyd_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
zyd_queue_command(sc, zyd_stop_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
}
|
||||
}
|
||||
sc->sc_if_flags = ifp->if_flags;
|
||||
ZYD_UNLOCK(sc);
|
||||
@ -2755,19 +2765,18 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_init_locked(struct zyd_softc *sc)
|
||||
zyd_init_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
int error;
|
||||
struct zyd_task *task = (struct zyd_task *)pm;
|
||||
struct zyd_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct usb2_config_descriptor *cd;
|
||||
int error;
|
||||
uint32_t val;
|
||||
|
||||
ZYD_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & ZYD_FLAG_DETACHING)
|
||||
return;
|
||||
|
||||
if (!(sc->sc_flags & ZYD_FLAG_INITONCE)) {
|
||||
error = zyd_loadfirmware(sc);
|
||||
if (error != 0) {
|
||||
@ -2814,7 +2823,7 @@ zyd_init_locked(struct zyd_softc *sc)
|
||||
}
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
zyd_stop(sc);
|
||||
zyd_stop_task(pm);
|
||||
|
||||
IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
|
||||
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %s\n",
|
||||
@ -2850,10 +2859,7 @@ zyd_init_locked(struct zyd_softc *sc)
|
||||
/*
|
||||
* Allocate Tx and Rx xfer queues.
|
||||
*/
|
||||
if ((error = zyd_alloc_tx_list(sc)) != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx list\n");
|
||||
goto fail;
|
||||
}
|
||||
zyd_setup_tx_list(sc);
|
||||
|
||||
/* enable interrupts */
|
||||
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
|
||||
@ -2865,7 +2871,7 @@ zyd_init_locked(struct zyd_softc *sc)
|
||||
|
||||
return;
|
||||
|
||||
fail: zyd_stop(sc);
|
||||
fail: zyd_stop_task(pm);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2877,7 +2883,9 @@ zyd_init(void *priv)
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
zyd_init_locked(sc);
|
||||
zyd_queue_command(sc, zyd_init_task,
|
||||
&sc->sc_synctask[0].hdr,
|
||||
&sc->sc_synctask[1].hdr);
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
@ -2885,8 +2893,10 @@ zyd_init(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_stop(struct zyd_softc *sc)
|
||||
zyd_stop_task(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct zyd_task *task = (struct zyd_task *)pm;
|
||||
struct zyd_softc *sc = task->sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int error;
|
||||
|
||||
@ -2895,16 +2905,17 @@ zyd_stop(struct zyd_softc *sc)
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/*
|
||||
* stop all the transfers, if not already stopped:
|
||||
* Drain all the transfers, if not already drained:
|
||||
*/
|
||||
usb2_transfer_stop(sc->sc_xfer[ZYD_BULK_WR]);
|
||||
usb2_transfer_stop(sc->sc_xfer[ZYD_BULK_RD]);
|
||||
ZYD_UNLOCK(sc);
|
||||
usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_WR]);
|
||||
usb2_transfer_drain(sc->sc_xfer[ZYD_BULK_RD]);
|
||||
ZYD_LOCK(sc);
|
||||
|
||||
zyd_free_tx_list(sc);
|
||||
zyd_unsetup_tx_list(sc);
|
||||
|
||||
/* Stop now if the device has vanished or was never set up */
|
||||
if (sc->sc_flags & ZYD_FLAG_DETACHING ||
|
||||
(sc->sc_flags & ZYD_FLAG_INITONCE) == 0)
|
||||
/* Stop now if the device was never set up */
|
||||
if (!(sc->sc_flags & ZYD_FLAG_INITONCE))
|
||||
return;
|
||||
|
||||
/* switch radio transmitter OFF */
|
||||
@ -2958,7 +2969,7 @@ zyd_loadfirmware(struct zyd_softc *sc)
|
||||
|
||||
USETW(req.wValue, addr);
|
||||
USETW(req.wLength, mlen);
|
||||
if (usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, fw) != 0)
|
||||
if (zyd_do_request(sc, &req, fw) != 0)
|
||||
return (EIO);
|
||||
|
||||
addr += mlen / 2;
|
||||
@ -2972,7 +2983,7 @@ zyd_loadfirmware(struct zyd_softc *sc)
|
||||
USETW(req.wValue, 0);
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, sizeof(stat));
|
||||
if (usb2_do_request(sc->sc_udev, &sc->sc_mtx, &req, &stat) != 0)
|
||||
if (zyd_do_request(sc, &req, &stat) != 0)
|
||||
return (EIO);
|
||||
|
||||
sc->sc_flags |= ZYD_FLAG_FWLOADED;
|
||||
@ -3042,27 +3053,16 @@ zyd_scantask(struct usb2_proc_msg *pm)
|
||||
/* want broadcast address while scanning */
|
||||
zyd_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
break;
|
||||
case ZYD_SCAN_END:
|
||||
/* restore previous bssid */
|
||||
zyd_set_bssid(sc, sc->sc_bssid);
|
||||
break;
|
||||
|
||||
case ZYD_SET_CHANNEL:
|
||||
zyd_set_chan(sc, ic->ic_curchan);
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown scan action %d\n",
|
||||
sc->sc_scan_action);
|
||||
|
||||
default: /* ZYD_SCAN_END */
|
||||
/* restore previous bssid */
|
||||
zyd_set_bssid(sc, sc->sc_bssid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_wakeup(struct zyd_softc *sc)
|
||||
{
|
||||
struct zyd_rq *rqp;
|
||||
|
||||
STAILQ_FOREACH(rqp, &sc->sc_rqh, rq)
|
||||
wakeup(rqp); /* wakeup sleeping caller */
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3089,6 +3089,11 @@ zyd_queue_command(struct zyd_softc *sc, usb2_proc_callback_t *fn,
|
||||
task->hdr.pm_callback = fn;
|
||||
task->sc = sc;
|
||||
|
||||
/*
|
||||
* Init and stop must be synchronous!
|
||||
*/
|
||||
if ((fn == zyd_init_task) || (fn == zyd_stop_task))
|
||||
usb2_proc_mwait(&sc->sc_tq, t0, t1);
|
||||
}
|
||||
|
||||
static device_method_t zyd_methods[] = {
|
||||
|
@ -1127,7 +1127,7 @@ struct zyd_notif_retry {
|
||||
uint16_t count;
|
||||
} __packed;
|
||||
|
||||
#define ZYD_CONFIG_NO 1
|
||||
#define ZYD_CONFIG_INDEX 0
|
||||
#define ZYD_IFACE_INDEX 0
|
||||
|
||||
#define ZYD_INTR_TIMEOUT 1000
|
||||
@ -1270,13 +1270,12 @@ struct zyd_softc {
|
||||
enum ieee80211_state sc_state;
|
||||
int sc_arg;
|
||||
int sc_flags;
|
||||
#define ZYD_FLAG_FWLOADED (1 << 0)
|
||||
#define ZYD_FLAG_DETACHING (1 << 1)
|
||||
#define ZYD_FLAG_INITONCE (1 << 2)
|
||||
#define ZYD_FLAG_INITDONE (1 << 3)
|
||||
#define ZYD_FLAG_FWLOADED (1 << 0)
|
||||
#define ZYD_FLAG_INITONCE (1 << 1)
|
||||
#define ZYD_FLAG_INITDONE (1 << 2)
|
||||
int sc_if_flags;
|
||||
uint32_t sc_debug;
|
||||
|
||||
struct zyd_task sc_synctask[2];
|
||||
struct zyd_task sc_mcasttask[2];
|
||||
struct zyd_task sc_scantask[2];
|
||||
int sc_scan_action;
|
||||
@ -1317,7 +1316,7 @@ struct zyd_softc {
|
||||
|
||||
struct mtx sc_mtx;
|
||||
struct cv sc_intr_cv;
|
||||
struct zyd_tx_data *tx_data;
|
||||
struct zyd_tx_data tx_data[ZYD_TX_LIST_CNT];
|
||||
zyd_txdhead tx_q;
|
||||
zyd_txdhead tx_free;
|
||||
int tx_nfree;
|
||||
|
Loading…
x
Reference in New Issue
Block a user