Date: Mon, 19 Jul 2010 19:18:33 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 181189 for review Message-ID: <201007191918.o6JJIX8x094501@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181189?ac=10 Change 181189 by hselasky@hselasky_laptop001 on 2010/07/19 19:17:47 USB WLAN (RUN-driver update): * Because hostapd calls iv_key_set() before if_init(), made sure key_set callback function will be executed, and the key won't be deleted during init process. * txmic and rxmic are written into the chip the same place regardless of opmode. * Made hardware generate 802.11 sequence numbers. * make command queuing atomic by adding another mutex * some minor whitespace/tab styling * remove errornous semicolon. - patch by Akinori Reviewed by: hselasky @ Affected files ... .. //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#15 edit .. //depot/projects/usb/src/sys/dev/usb/wlan/if_runvar.h#9 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#15 (text+ko) ==== @@ -90,12 +90,6 @@ #define IEEE80211_HAS_ADDR4(wh) \ (((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) -/* - * Because of LOR in run_key_delete(), use atomic instead. - * '& RUN_CMDQ_MASQ' is to loop cmdq[]. - */ -#define RUN_CMDQ_GET(c) (atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ) - static const struct usb_device_id run_devs[] = { { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2770) }, { USB_VP(USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2870) }, @@ -554,6 +548,8 @@ mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, MTX_DEF); + mtx_init(&sc->sc_cmdq_mtx, device_get_nameunit(sc->sc_dev), + MTX_NETWORK_LOCK, MTX_DEF); iface_index = RT2860_IFACE_INDEX; @@ -719,7 +715,10 @@ RUN_LOCK(sc); sc->ratectl_run = RUN_RATECTL_OFF; + + RUN_CMDQ_LOCK(sc); sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT; + RUN_CMDQ_UNLOCK(sc); /* free TX list, if any */ for (i = 0; i != RUN_EP_QUEUES; i++) @@ -737,6 +736,7 @@ } mtx_destroy(&sc->sc_mtx); + mtx_destroy(&sc->sc_cmdq_mtx); return (0); } @@ -830,9 +830,6 @@ if(sc->rvp_cnt++ == 0) ic->ic_opmode = opmode; - if(opmode == IEEE80211_M_HOSTAP) - sc->cmdq_run = RUN_CMDQ_GO; - DPRINTF("rvp_id=%d bmap=%x rvp_cnt=%d\n", rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt); @@ -889,27 +886,53 @@ struct run_softc *sc = arg; uint8_t i; - /* call cmdq[].func locked */ - RUN_LOCK(sc); - for(i = sc->cmdq_exec; sc->cmdq[i].func && pending; - i = sc->cmdq_exec, pending--){ + RUN_CMDQ_LOCK(sc); + for (i = sc->cmdq_exec; sc->cmdq[i].func; i = sc->cmdq_exec){ DPRINTFN(6, "cmdq_exec=%d pending=%d\n", i, pending); - if(sc->cmdq_run == RUN_CMDQ_GO){ + if ((sc->cmdq_run == RUN_CMDQ_GO) || + ((sc->cmdq_key_set == RUN_CMDQ_GO) && + (sc->cmdq[i].func == run_key_set_cb))) { + RUN_CMDQ_UNLOCK(sc); + RUN_LOCK(sc); /* * If arg0 is NULL, callback func needs more * than one arg. So, pass ptr to cmdq struct. */ - if(sc->cmdq[i].arg0) + if (sc->cmdq[i].arg0) sc->cmdq[i].func(sc->cmdq[i].arg0); else sc->cmdq[i].func(&sc->cmdq[i]); + RUN_UNLOCK(sc); + RUN_CMDQ_LOCK(sc); } sc->cmdq[i].arg0 = NULL; sc->cmdq[i].func = NULL; sc->cmdq_exec++; sc->cmdq_exec &= RUN_CMDQ_MASQ; } - RUN_UNLOCK(sc); + RUN_CMDQ_UNLOCK(sc); +} + +static uint8_t +run_cmdq_append(struct run_softc *sc) +{ + uint8_t i; + + RUN_CMDQ_LOCK_ASSERT(sc, MA_OWNED); + + i = sc->cmdq_store; + + DPRINTF("cmdq_store=%d\n", i); + + if (sc->cmdq[i].func != NULL) { + DPRINTF("cmdq is full\n"); + return (RUN_CMDQ_MAX); + } + + sc->cmdq_store++; + sc->cmdq_store &= RUN_CMDQ_MASQ; + + return (i); } static void @@ -1771,6 +1794,19 @@ case IEEE80211_S_INIT: restart_ratectl = 1; + /* + * When hostapd has set a key, don't clear it. But, + * when the device is being brought down, clear it. + */ + if ((sc->cmdq_key_set != RUN_CMDQ_GO) || + (ostate == IEEE80211_S_RUN)) { + /* clear shared key table */ + run_set_region_4(sc, + RT2860_SKEY(rvp->rvp_id, 0), 0, 4 * 32); + /* clear shared key mode */ + run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); + } + if (ostate != IEEE80211_S_RUN) break; @@ -1921,12 +1957,20 @@ { struct run_softc *sc = ic->ic_ifp->if_softc; - /* sometime called wothout lock */ - if(mtx_owned(&ic->ic_comlock.mtx)){ - uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", i); + /* sometime called without lock */ + if (mtx_owned(&ic->ic_comlock.mtx)){ + uint8_t i; + + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i >= RUN_CMDQ_MAX) { + RUN_CMDQ_UNLOCK(sc); + return (-1); + } sc->cmdq[i].func = run_wme_update_cb; sc->cmdq[i].arg0 = ic; + RUN_CMDQ_UNLOCK(sc); + ieee80211_runtask(ic, &sc->cmdq_task); return (0); } @@ -1970,7 +2014,7 @@ RUN_LOCK_ASSERT(sc, MA_OWNED); - if(vap->iv_opmode == IEEE80211_M_HOSTAP) + if (vap->iv_opmode == IEEE80211_M_HOSTAP) ni = ieee80211_find_vap_node(&ic->ic_sta, vap, cmdq->mac); else ni = vap->iv_bss; @@ -2085,28 +2129,32 @@ { struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; - uint32_t i; + uint8_t i; - i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", i); + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i >= RUN_CMDQ_MAX) { + RUN_CMDQ_UNLOCK(sc); + return (0); + } sc->cmdq[i].func = run_key_set_cb; sc->cmdq[i].arg0 = NULL; sc->cmdq[i].arg1 = vap; sc->cmdq[i].k = k; IEEE80211_ADDR_COPY(sc->cmdq[i].mac, mac); - ieee80211_runtask(ic, &sc->cmdq_task); /* - * To make sure key will be set when hostapd - * calls iv_key_set() before if_init(). + * To make sure key will be set when hostapd calls + * iv_key_set() before if_init(). */ - if(vap->iv_opmode == IEEE80211_M_HOSTAP){ - RUN_LOCK(sc); + if (vap->iv_opmode == IEEE80211_M_HOSTAP) sc->cmdq_key_set = RUN_CMDQ_GO; - RUN_UNLOCK(sc); - } + + RUN_CMDQ_UNLOCK(sc); + + ieee80211_runtask(ic, &sc->cmdq_task); - return(1); + return (1); } /* @@ -2154,16 +2202,18 @@ struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; struct ieee80211_key *k0; - uint32_t i; + uint8_t i; /* * When called back, key might be gone. So, make a copy * of some values need to delete keys before deferring. - * But, because of LOR with node lock, cannot use lock here. - * So, use atomic instead. */ - i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", i); + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i >= RUN_CMDQ_MAX) { + RUN_CMDQ_UNLOCK(sc); + return (0); + } sc->cmdq[i].func = run_key_delete_cb; sc->cmdq[i].arg0 = NULL; sc->cmdq[i].arg1 = sc; @@ -2172,9 +2222,11 @@ k0->wk_keyix = k->wk_keyix; /* matching wcid was written to wk_pad in run_key_set() */ k0->wk_pad = k->wk_pad; + RUN_CMDQ_UNLOCK(sc); + ieee80211_runtask(ic, &sc->cmdq_task); + return (1); /* return fake success */ - } static void @@ -2362,18 +2414,25 @@ } /* only interested in true associations */ - if (isnew && ni->ni_associd != 0){ - + if (isnew && ni->ni_associd != 0) { /* - * This function could is called though timeout function. - * Need to defer. + * This function could be called through timeout + * callback. Need to defer. */ - uint32_t cnt = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", cnt); + uint8_t cnt; + + RUN_CMDQ_LOCK(sc); + cnt = run_cmdq_append(sc); + if (cnt >= RUN_CMDQ_MAX) { + RUN_CMDQ_UNLOCK(sc); + return; + } sc->cmdq[cnt].func = run_newassoc_cb; sc->cmdq[cnt].arg0 = NULL; sc->cmdq[cnt].arg1 = ni; sc->cmdq[cnt].wcid = wcid; + RUN_CMDQ_UNLOCK(sc); + ieee80211_runtask(ic, &sc->cmdq_task); } @@ -2803,13 +2862,18 @@ vap = TAILQ_FIRST(&ic->ic_vaps); if (error != USB_ERR_CANCELLED) { - if (error == USB_ERR_TIMEOUT) { + if ((error == USB_ERR_TIMEOUT) && (vap != NULL)) { + uint8_t i; device_printf(sc->sc_dev, "device timeout\n"); - uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", i); - sc->cmdq[i].func = run_usb_timeout_cb; - sc->cmdq[i].arg0 = vap; - ieee80211_runtask(ic, &sc->cmdq_task); + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i < RUN_CMDQ_MAX) { + sc->cmdq[i].func = run_usb_timeout_cb; + sc->cmdq[i].arg0 = vap; + } + RUN_CMDQ_UNLOCK(sc); + if (i < RUN_CMDQ_MAX) + ieee80211_runtask(ic, &sc->cmdq_task); } /* @@ -3064,14 +3128,22 @@ */ if(sc->fifo_cnt++ == 10){ /* - * With multiple vaps or if_bridge, if_start() is called - * with a non-sleepable lock, tcpinp. So, need to defer. + * With multiple vaps or if_bridge, if_start() + * is called with a non-sleepable lock, + * tcpinp. So, need to defer. */ - uint32_t i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTFN(6, "cmdq_store=%d\n", i); - sc->cmdq[i].func = run_drain_fifo; - sc->cmdq[i].arg0 = sc; - ieee80211_runtask(ic, &sc->cmdq_task); + uint8_t i; + + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i < RUN_CMDQ_MAX) { + sc->cmdq[i].func = run_drain_fifo; + sc->cmdq[i].arg0 = sc; + } + RUN_CMDQ_UNLOCK(sc); + if (i < RUN_CMDQ_MAX) + ieee80211_runtask(ic, &sc->cmdq_task); + } } @@ -3188,7 +3260,7 @@ ackrate = ieee80211_ack_rate(ic->ic_rt, rate); isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; - dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort); + dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) + ieee80211_ack_duration(ic->ic_rt, rate, isshort); wflags = RT2860_TX_FRAG; @@ -3906,15 +3978,18 @@ { struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; - uint32_t i; + uint8_t i; - i = RUN_CMDQ_GET(&sc->cmdq_store); - DPRINTF("cmdq_store=%d\n", i); - sc->cmdq[i].func = run_update_beacon_cb; - sc->cmdq[i].arg0 = vap; - ieee80211_runtask(ic, &sc->cmdq_task); + RUN_CMDQ_LOCK(sc); + i = run_cmdq_append(sc); + if (i < RUN_CMDQ_MAX) { + sc->cmdq[i].func = run_update_beacon_cb; + sc->cmdq[i].arg0 = vap; + } + RUN_CMDQ_UNLOCK(sc); + if (i < RUN_CMDQ_MAX) + ieee80211_runtask(ic, &sc->cmdq_task); - return; } static void @@ -4693,14 +4768,6 @@ /* clear WCID attribute table */ run_set_region_4(sc, RT2860_WCID_ATTR(0), 0, 8 * 32); - /* hostapd sets a key before init. So, don't clear it. */ - if(sc->cmdq_key_set != RUN_CMDQ_GO){ - /* clear shared key table */ - run_set_region_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); - /* clear shared key mode */ - run_set_region_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); - } - run_read(sc, RT2860_US_CYC_CNT, &tmp); tmp = (tmp & ~0xff) | 0x1e; run_write(sc, RT2860_US_CYC_CNT, tmp); @@ -4759,7 +4826,10 @@ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; ifp->if_drv_flags |= IFF_DRV_RUNNING; + + RUN_CMDQ_LOCK(sc); sc->cmdq_run = RUN_CMDQ_GO; + RUN_CMDQ_UNLOCK(sc); for(i = 0; i != RUN_N_XFER; i++) usbd_xfer_set_stall(sc->sc_xfer[i]); @@ -4807,7 +4877,10 @@ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); sc->ratectl_run = RUN_RATECTL_OFF; - sc->cmdq_run = sc->cmdq_key_set; + + RUN_CMDQ_LOCK(sc); + sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT; + RUN_CMDQ_UNLOCK(sc); RUN_UNLOCK(sc); ==== //depot/projects/usb/src/sys/dev/usb/wlan/if_runvar.h#9 (text+ko) ==== @@ -23,7 +23,7 @@ #ifndef _IF_RUNVAR_H_ #define _IF_RUNVAR_H_ -#define RUN_MAX_RXSZ \ +#define RUN_MAX_RXSZ \ MIN(4096, MJUMPAGESIZE) #if 0 (sizeof (uint32_t) + \ @@ -33,21 +33,21 @@ sizeof (struct rt2870_rxd)) #endif /* NB: "11" is the maximum number of padding bytes needed for Tx */ -#define RUN_MAX_TXSZ \ +#define RUN_MAX_TXSZ \ (sizeof (struct rt2870_txd) + \ sizeof (struct rt2860_rxwi) + \ MCLBYTES + 11) -#define RUN_TX_TIMEOUT 5000 /* ms */ +#define RUN_TX_TIMEOUT 5000 /* ms */ /* Tx ring count was 8/endpoint, now 32 for all 4 (or 6) endpoints. */ -#define RUN_TX_RING_COUNT 32 -#define RUN_RX_RING_COUNT 1 +#define RUN_TX_RING_COUNT 32 +#define RUN_RX_RING_COUNT 1 -#define RT2870_WCID_MAX 64 -#define RUN_AID2WCID(aid) ((aid) & 0xff) +#define RT2870_WCID_MAX 64 +#define RUN_AID2WCID(aid) ((aid) & 0xff) -#define RUN_VAP_MAX 8 +#define RUN_VAP_MAX 8 struct run_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; @@ -60,7 +60,7 @@ uint8_t wr_antsignal; } __packed; -#define RUN_RX_RADIOTAP_PRESENT \ +#define RUN_RX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL | \ @@ -77,9 +77,9 @@ uint8_t wt_hwqueue; } __packed; -#define IEEE80211_RADIOTAP_HWQUEUE 15 +#define IEEE80211_RADIOTAP_HWQUEUE 15 -#define RUN_TX_RADIOTAP_PRESENT \ +#define RUN_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ 1 << IEEE80211_RADIOTAP_RATE | \ 1 << IEEE80211_RADIOTAP_CHANNEL | \ @@ -127,7 +127,7 @@ uint8_t rvp_id; }; -#define RUN_VAP(vap) ((struct run_vap *)(vap)) +#define RUN_VAP(vap) ((struct run_vap *)(vap)) /* * There are 7 bulk endpoints: 1 for RX @@ -202,25 +202,26 @@ uint8_t sc_bssid[6]; struct mtx sc_mtx; + struct mtx sc_cmdq_mtx; struct run_endpoint_queue sc_epq[RUN_EP_QUEUES]; struct task ratectl_task; struct usb_callout ratectl_ch; uint8_t ratectl_run; -#define RUN_RATECTL_OFF 0 +#define RUN_RATECTL_OFF 0 -/* need to be power of 2, otherwise RUN_CMDQ_GET fails */ -#define RUN_CMDQ_MAX 16 -#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1) +/* need to be power of 2, otherwise modulo assumptions fail */ +#define RUN_CMDQ_MAX 16 +#define RUN_CMDQ_MASQ (RUN_CMDQ_MAX - 1) struct run_cmdq cmdq[RUN_CMDQ_MAX]; struct task cmdq_task; - uint32_t cmdq_store; + uint8_t cmdq_store; uint8_t cmdq_exec; uint8_t cmdq_run; uint8_t cmdq_key_set; -#define RUN_CMDQ_ABORT 0 -#define RUN_CMDQ_GO 1 +#define RUN_CMDQ_ABORT 0 +#define RUN_CMDQ_GO 1 struct usb_xfer *sc_xfer[RUN_N_XFER]; @@ -240,19 +241,23 @@ struct run_rx_radiotap_header th; uint8_t pad[64]; } sc_rxtapu; -#define sc_rxtap sc_rxtapu.th +#define sc_rxtap sc_rxtapu.th int sc_rxtap_len; union { struct run_tx_radiotap_header th; uint8_t pad[64]; } sc_txtapu; -#define sc_txtap sc_txtapu.th +#define sc_txtap sc_txtapu.th int sc_txtap_len; }; -#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) -#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) +#define RUN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) +#define RUN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) +#define RUN_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t) + +#define RUN_CMDQ_LOCK(sc) mtx_lock(&(sc)->sc_cmdq_mtx) +#define RUN_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->sc_cmdq_mtx) +#define RUN_CMDQ_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_cmdq_mtx, t) #endif /* _IF_RUNVAR_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007191918.o6JJIX8x094501>