PERFORCE change 181189 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Jul 19 19:18:34 UTC 2010
http://p4web.freebsd.org/@@181189?ac=10
Change 181189 by hselasky at 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_ */
More information about the p4-projects
mailing list