From owner-p4-projects@FreeBSD.ORG Wed May 5 19:56:36 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 617C51065672; Wed, 5 May 2010 19:56:36 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 0D2B1106566B for ; Wed, 5 May 2010 19:56:36 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id EE54C8FC08 for ; Wed, 5 May 2010 19:56:35 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o45JuZvJ060762 for ; Wed, 5 May 2010 19:56:35 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o45JuZRt060760 for perforce@freebsd.org; Wed, 5 May 2010 19:56:35 GMT (envelope-from hselasky@FreeBSD.org) Date: Wed, 5 May 2010 19:56:35 GMT Message-Id: <201005051956.o45JuZRt060760@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 177777 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 May 2010 19:56:36 -0000 http://p4web.freebsd.org/@@177777?ac=10 Change 177777 by hselasky@hselasky_laptop001 on 2010/05/05 19:55:35 USB WLAN: - integrate latest version of RUN driver from: http://gitorious.org/run/run/trees/master/dev/usb/wlan Affected files ... .. //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#9 edit .. //depot/projects/usb/src/sys/dev/usb/wlan/if_runreg.h#4 edit .. //depot/projects/usb/src/sys/dev/usb/wlan/if_runvar.h#6 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/wlan/if_run.c#9 (text+ko) ==== @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -66,20 +65,22 @@ #include #include #include +#include #include #include #include "usbdevs.h" #define USB_DEBUG_VAR run_debug +#define USB_DEBUG /*XXX remove this before commit */ #include -#include "if_runreg.h" /* shared with ral(4) */ +#include "if_runreg.h" #include "if_runvar.h" #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) -#if USB_DEBUG +#ifdef USB_DEBUG #define RUN_DEBUG #endif @@ -93,6 +94,12 @@ #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) }, @@ -290,7 +297,6 @@ }; MODULE_DEPEND(run, wlan, 1, 1, 1); -MODULE_DEPEND(run, wlan_amrr, 1, 1, 1); MODULE_DEPEND(run, usb, 1, 1, 1); MODULE_DEPEND(run, firmware, 1, 1, 1); @@ -313,6 +319,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]); static void run_vap_delete(struct ieee80211vap *); +static void run_cmdq_cb(void *, int); static void run_setup_tx_list(struct run_softc *, struct run_endpoint_queue *); static void run_unsetup_tx_list(struct run_softc *, @@ -343,23 +350,24 @@ static int run_media_change(struct ifnet *); static int run_newstate(struct ieee80211vap *, enum ieee80211_state, int); static int run_wme_update(struct ieee80211com *); -static void run_wme_update_cb(void *, int); +static void run_wme_update_cb(void *); static void run_key_update_begin(struct ieee80211vap *); static void run_key_update_end(struct ieee80211vap *); -static int run_key_set(struct ieee80211vap *, const struct ieee80211_key *, +static void run_key_set_cb(void *); +static int run_key_set(struct ieee80211vap *, struct ieee80211_key *, const uint8_t mac[IEEE80211_ADDR_LEN]); -static int run_key_delete(struct ieee80211vap *, - const struct ieee80211_key *); -static void run_amrr_start(struct run_softc *, struct ieee80211_node *); -static void run_amrr_to(void *); -static void run_amrr_cb(void *, int); +static void run_key_delete_cb(void *); +static int run_key_delete(struct ieee80211vap *, struct ieee80211_key *); +static void run_ratectl_to(void *); +static void run_ratectl_cb(void *, int); +static void run_drain_fifo(void *); static void run_iter_func(void *, struct ieee80211_node *); +static void run_newassoc_cb(void *); static void run_newassoc(struct ieee80211_node *, int); static void run_rx_frame(struct run_softc *, struct mbuf *, uint32_t); static void run_tx_free(struct run_endpoint_queue *pq, struct run_tx_data *, int); -static void run_set_tx_desc(struct run_softc *, struct run_tx_data *, - uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); +static void run_set_tx_desc(struct run_softc *, struct run_tx_data *); static int run_tx(struct run_softc *, struct mbuf *, struct ieee80211_node *); static int run_tx_mgt(struct run_softc *, struct mbuf *, @@ -383,11 +391,10 @@ static void run_set_channel(struct ieee80211com *); static void run_scan_start(struct ieee80211com *); static void run_scan_end(struct ieee80211com *); -static uint8_t run_rate2mcs(uint8_t); static void run_update_beacon(struct ieee80211vap *, int); -static void run_update_beacon_locked(struct ieee80211vap *, int); +static void run_update_beacon_cb(void *); static void run_updateprot(struct ieee80211com *); -static void run_usb_timeout_cb(void *, int); +static void run_usb_timeout_cb(void *); static void run_reset_livelock(struct run_softc *); static void run_enable_tsf_sync(struct run_softc *); static void run_enable_mrr(struct run_softc *); @@ -397,6 +404,7 @@ static void run_set_bssid(struct run_softc *, const uint8_t *); static void run_set_macaddr(struct run_softc *, const uint8_t *); static void run_updateslot(struct ifnet *); +static void run_update_mcast(struct ifnet *); static int8_t run_rssi2dbm(struct run_softc *, uint8_t, uint8_t); static void run_update_promisc_locked(struct ifnet *); static void run_update_promisc(struct ifnet *); @@ -412,7 +420,7 @@ static void run_delay(struct run_softc *, unsigned int); static const struct { - uint32_t reg; + uint16_t reg; uint32_t val; } rt2870_def_mac[] = { RT2870_DEF_MAC @@ -552,6 +560,7 @@ MTX_NETWORK_LOCK, MTX_DEF); iface_index = RT2860_IFACE_INDEX; + error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer, run_config, RUN_N_XFER, sc, &sc->sc_mtx); if (error) { @@ -617,15 +626,15 @@ ic->ic_ifp = ifp; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ -#if 0 - ic->ic_state = IEEE80211_S_INIT; -#endif + /* set device capabilities */ ic->ic_caps = IEEE80211_C_STA | /* station mode supported */ IEEE80211_C_MONITOR | /* monitor mode supported */ IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | + IEEE80211_C_WDS | /* 4-address traffic works */ + IEEE80211_C_MBSS | IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_SHSLOT | /* short slot time supported */ IEEE80211_C_WME | /* WME */ @@ -672,6 +681,7 @@ ic->ic_node_alloc = run_node_alloc; ic->ic_newassoc = run_newassoc; //ic->ic_updateslot = run_updateslot; + ic->ic_update_mcast = run_update_mcast; ic->ic_wme.wme_update = run_wme_update; ic->ic_raw_xmit = run_raw_xmit; ic->ic_update_promisc = run_update_promisc; @@ -685,6 +695,10 @@ &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), RUN_RX_RADIOTAP_PRESENT); + TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc); + TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc); + callout_init((struct callout *)&sc->ratectl_ch, 1); + if (bootverbose) ieee80211_announce(ic); @@ -703,6 +717,8 @@ struct ieee80211com *ic; int i; + DPRINTF("called\n"); + /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER); @@ -710,16 +726,23 @@ /* free TX list, if any */ for (i = 0; i != RUN_EP_QUEUES; i++) run_unsetup_tx_list(sc, &sc->sc_epq[i]); + RUN_UNLOCK(sc); if (ifp) { ic = ifp->if_l2com; + /* drain tasks */ + usb_callout_drain(&sc->ratectl_ch); + ieee80211_draintask(ic, &sc->cmdq_task); + ieee80211_draintask(ic, &sc->ratectl_task); ieee80211_ifdetach(ic); if_free(ifp); } mtx_destroy(&sc->sc_mtx); + DPRINTF("done\n"); + return (0); } @@ -729,43 +752,92 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct ifnet *ifp = ic->ic_ifp; + struct run_softc *sc = ifp->if_softc; struct run_vap *rvp; struct ieee80211vap *vap; + int i; - if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ + if(sc->rvp_cnt >= RUN_VAP_MAX){ + if_printf(ifp, "number of VAPs maxed out\n"); + return NULL; + } + + switch (opmode) { + case IEEE80211_M_STA: + /* enable s/w bmiss handling for sta mode */ + flags |= IEEE80211_CLONE_NOBEACONS; + /* fall though */ + case IEEE80211_M_IBSS: + case IEEE80211_M_MONITOR: + case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: + /* other than WDS vaps, only one at a time */ + if (!TAILQ_EMPTY(&ic->ic_vaps)) + return NULL; + break; + case IEEE80211_M_WDS: + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next){ + if(vap->iv_opmode != IEEE80211_M_HOSTAP) + continue; + /* WDS vap's always share the local mac address. */ + flags &= ~IEEE80211_CLONE_BSSID; + break; + } + if(vap == NULL){ + if_printf(ifp, "wds only supported in ap mode\n"); + return NULL; + } + break; + default: + if_printf(ifp, "unknown opmode %d\n", opmode); return NULL; - sc->sc_rvp = rvp = (struct run_vap *) malloc(sizeof(struct run_vap), + } + + rvp = (struct run_vap *) malloc(sizeof(struct run_vap), M_80211_VAP, M_NOWAIT | M_ZERO); if (rvp == NULL) return NULL; vap = &rvp->vap; - /* enable s/w bmiss handling for sta mode */ - ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); vap->iv_key_update_begin = run_key_update_begin; vap->iv_key_update_end = run_key_update_end; - vap->iv_key_delete = run_key_delete; - vap->iv_key_set = run_key_set; vap->iv_update_beacon = run_update_beacon; + vap->iv_max_aid = RT2870_WCID_MAX; + /* + * To delete the right key from h/w, we need wcid. + * Luckily, there is unused space in ieee80211_key{}, wk_pad, + * and matching wcid will be written into there. So, cast + * some spells to remove 'const' from ieee80211_key{} + */ + vap->iv_key_delete = (void *)run_key_delete; + vap->iv_key_set = (void *)run_key_set; /* override state transition machine */ rvp->newstate = vap->iv_newstate; vap->iv_newstate = run_newstate; - TASK_INIT(&rvp->amrr_task, 0, run_amrr_cb, rvp); - TASK_INIT(&sc->wme_task, 0, run_wme_update_cb, ic); - TASK_INIT(&sc->usb_timeout_task, 0, run_usb_timeout_cb, sc); - callout_init((struct callout *)&rvp->amrr_ch, 1); - ieee80211_amrr_init(&rvp->amrr, vap, - IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, - IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, - 1000 /* 1 sec */); + ieee80211_ratectl_init(vap); + ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status); - ic->ic_opmode = opmode; + + /* make sure id is always unique */ + for(i = 0; i < RUN_VAP_MAX; i++){ + if((sc->rvp_bmap & 1 << i) == 0){ + sc->rvp_bmap |= 1 << i; + rvp->rvp_id = i; + break; + } + } + if(sc->rvp_cnt++ == 0) + ic->ic_opmode = opmode; + + DPRINTF("rvp_id=%d bmap=%x rvp_cnt=%d\n", + rvp->rvp_id, sc->rvp_bmap, sc->rvp_cnt); + return vap; } @@ -776,6 +848,7 @@ struct ifnet *ifp; struct ieee80211com *ic; struct run_softc *sc; + uint8_t rvp_id; if(vap == NULL) return; @@ -786,19 +859,59 @@ sc = ifp->if_softc; RUN_LOCK(sc); - sc->sc_rvp->amrr_run = RUN_AMRR_OFF; + + rvp_id = rvp->rvp_id; + sc->ratectl_run &= ~(1 << rvp_id); + sc->rvp_bmap &= ~(1 << rvp_id); + run_set_region_4(sc, RT2860_SKEY(rvp_id, 0), 0, 128); + run_set_region_4(sc, RT2860_BCN_BASE(rvp_id), 0, 512); + --sc->rvp_cnt; + + DPRINTF("vap=%p rvp_id=%d bmap=%x rvp_cnt=%d\n", + vap, rvp_id, sc->rvp_bmap, sc->rvp_cnt); + RUN_UNLOCK(sc); - /* drain them all */ - usb_callout_drain(&sc->sc_rvp->amrr_ch); - ieee80211_draintask(ic, &sc->sc_rvp->amrr_task); - ieee80211_draintask(ic, &sc->wme_task); - ieee80211_draintask(ic, &sc->usb_timeout_task); - - ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); - sc->sc_rvp = NULL; +} + +/* + * There are numbers of functions need to be called in context thread. + * Rather than creating taskqueue event for each of those functions, + * here is all-for-one taskqueue callback function. This function + * gurantees deferred functions are executed in the same order they + * were enqueued. + * '& RUN_CMDQ_MASQ' is to loop cmdq[]. + */ +static void +run_cmdq_cb(void *arg, int pending) +{ + 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--){ + DPRINTFN(6, "cmdq_exec=%d pending=%d\n", i, pending); + if(sc->cmdq_run == RUN_CMDQ_GO){ + /* + * If arg0 is NULL, callback func needs more + * than one arg. So, pass ptr to cmdq struct. + */ + if(sc->cmdq[i].arg0) + sc->cmdq[i].func(sc->cmdq[i].arg0); + else + sc->cmdq[i].func(&sc->cmdq[i]); + } + sc->cmdq[i].arg0 = NULL; + sc->cmdq[i].func = NULL; + sc->cmdq_exec++; + sc->cmdq_exec &= RUN_CMDQ_MASQ; + } + RUN_UNLOCK(sc); } static void @@ -1331,14 +1444,14 @@ sc->sc_srom_read = run_eeprom_read_2; if (sc->mac_ver >= 0x3070) { run_read(sc, RT3070_EFUSE_CTRL, &tmp); - DPRINTF("EFUSE_CTRL=0x%08x\n", tmp); + DPRINTFN(2, "EFUSE_CTRL=0x%08x\n", tmp); if (tmp & RT3070_SEL_EFUSE) sc->sc_srom_read = run_efuse_read_2; } /* read ROM version */ run_srom_read(sc, RT2860_EEPROM_VERSION, &val); - DPRINTF("EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8); + DPRINTFN(2, "EEPROM rev=%d, FAE=%d\n", val & 0xff, val >> 8); /* read MAC address */ run_srom_read(sc, RT2860_EEPROM_MAC01, &val); @@ -1356,7 +1469,7 @@ run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val); sc->bbp[i].val = val & 0xff; sc->bbp[i].reg = val >> 8; - DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val); + DPRINTFN(2, "BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val); } if (sc->mac_ver >= 0x3071) { /* read vendor RF settings */ @@ -1364,7 +1477,7 @@ run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val); sc->rf[i].val = val & 0xff; sc->rf[i].reg = val >> 8; - DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg, + DPRINTFN(2, "RF%d=0x%02x\n", sc->rf[i].reg, sc->rf[i].val); } } @@ -1372,7 +1485,7 @@ /* read RF frequency offset from EEPROM */ run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val); sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; - DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff); + DPRINTFN(2, "EEPROM freq offset %d\n", sc->freq & 0xff); if (val >> 8 != 0xff) { /* read LEDs operating mode */ @@ -1387,7 +1500,7 @@ sc->led[1] = 0x2221; sc->led[2] = 0x5627; /* differs from RT2860 */ } - DPRINTF("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", + DPRINTFN(2, "EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", sc->leds, sc->led[0], sc->led[1], sc->led[2]); /* read RF information */ @@ -1418,8 +1531,9 @@ DPRINTF("EEPROM RF rev=0x%02x chains=%dT%dR\n", sc->rf_rev, sc->ntxchains, sc->nrxchains); + /* check if RF supports automatic Tx access gain control */ run_srom_read(sc, RT2860_EEPROM_CONFIG, &val); - DPRINTF("EEPROM CFG 0x%04x\n", val); + DPRINTFN(2, "EEPROM CFG 0x%04x\n", val); /* check if driver should patch the DAC issue */ if ((val >> 8) != 0xff) sc->patch_dac = (val >> 15) & 1; @@ -1448,7 +1562,7 @@ sc->txpow1[i] = 5; if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31) sc->txpow2[i] = 5; - DPRINTF("chan %d: power1=%d, power2=%d\n", + DPRINTFN(2, "chan %d: power1=%d, power2=%d\n", rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]); } /* read power settings for 5GHz channels */ @@ -1467,7 +1581,7 @@ sc->txpow1[14 + i] = 5; if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) sc->txpow2[14 + i] = 5; - DPRINTF("chan %d: power1=%d, power2=%d\n", + DPRINTFN(2, "chan %d: power1=%d, power2=%d\n", rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], sc->txpow2[14 + i]); } @@ -1486,22 +1600,22 @@ if (!(val & 0x40)) /* negative number */ delta_5ghz = -delta_5ghz; } - DPRINTF("power compensation=%d (2GHz), %d (5GHz)\n", + DPRINTFN(2, "power compensation=%d (2GHz), %d (5GHz)\n", delta_2ghz, delta_5ghz); for (ridx = 0; ridx < 5; ridx++) { uint32_t reg; - run_srom_read(sc, RT2860_EEPROM_RPWR + ridx, &val); - reg = (uint32_t)val << 16; - run_srom_read(sc, RT2860_EEPROM_RPWR + ridx + 1, &val); - reg |= val; + run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2, &val); + reg = val; + run_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1, &val); + reg |= (uint32_t)val << 16; sc->txpow20mhz[ridx] = reg; sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); - DPRINTF("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " + DPRINTFN(2, "ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]); } @@ -1518,7 +1632,7 @@ */ if ((val & 0xff) != 0xff) sc->txmixgain_2ghz = val & 0x7; - DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz); + DPRINTFN(2, "tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz); } else sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ sc->lna[2] = val >> 8; /* channel group 2 */ @@ -1534,7 +1648,7 @@ */ if ((val & 0xff) != 0xff) sc->txmixgain_5ghz = val & 0x7; - DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz); + DPRINTFN(2, "tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz); } else sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ sc->lna[3] = val >> 8; /* channel group 3 */ @@ -1578,19 +1692,23 @@ static int run_media_change(struct ifnet *ifp) { + struct ieee80211vap *vap = ifp->if_softc; + struct ieee80211com *ic = vap->iv_ic; const struct ieee80211_txparam *tp; - struct run_softc *sc = ifp->if_softc; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ieee80211vap *vap = &sc->sc_rvp->vap; + struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_node *rn = (void *)vap->iv_bss; uint8_t rate, ridx; int error; + DPRINTF("called\n"); + RUN_LOCK(sc); error = ieee80211_media_change(ifp); - if (error != ENETRESET) + if (error != ENETRESET){ RUN_UNLOCK(sc); return error; + } tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { @@ -1599,13 +1717,16 @@ for (ridx = 0; ridx < RT2860_RIDX_MAX; ridx++) if (rt2860_rates[ridx].rate == rate) break; - sc->fixed_ridx = ridx; + rn->fix_ridx = ridx; + DPRINTF("rate=%d, fix_ridx=%d\n", rate, rn->fix_ridx); } +#if 0 if ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)){ run_init_locked(sc); } +#endif RUN_UNLOCK(sc); @@ -1621,8 +1742,11 @@ struct run_vap *rvp = RUN_VAP(vap); enum ieee80211_state ostate; struct ieee80211_node *ni; + uint32_t sta[3]; uint32_t tmp; - uint8_t wcid; + uint8_t ratectl; + uint8_t restart_ratectl = 0; + uint8_t bid = 1 << rvp->rvp_id; ostate = vap->iv_state; DPRINTF("%s -> %s\n", @@ -1632,8 +1756,9 @@ IEEE80211_UNLOCK(ic); RUN_LOCK(sc); - sc->sc_rvp->amrr_run = RUN_AMRR_OFF; - usb_callout_stop(&rvp->amrr_ch); + ratectl = sc->ratectl_run; /* remember current state */ + sc->ratectl_run = RUN_RATECTL_OFF; + usb_callout_stop(&sc->ratectl_ch); if (ostate == IEEE80211_S_RUN) { /* turn link LED off */ @@ -1642,8 +1767,16 @@ switch (nstate) { case IEEE80211_S_INIT: - if (ostate == IEEE80211_S_RUN) { - /* abort TSF synchronization */ + restart_ratectl = 1; + + if (ostate != IEEE80211_S_RUN) + break; + + ratectl &= ~bid; + sc->runbmap &= ~bid; + + /* abort TSF synchronization if there is no vap running */ + if(--sc->running == 0){ run_read(sc, RT2860_BCN_TIME_CFG, &tmp); run_write(sc, RT2860_BCN_TIME_CFG, tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | @@ -1651,9 +1784,43 @@ } break; + case IEEE80211_S_RUN: ni = vap->iv_bss; + if(!(sc->runbmap & bid)){ + if(sc->running++) + restart_ratectl = 1; + sc->runbmap |= bid; + } + + switch(vap->iv_opmode){ + case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: + sc->ap_running |= bid; + ic->ic_opmode = vap->iv_opmode; + run_update_beacon_cb(vap); + break; + case IEEE80211_M_IBSS: + sc->adhoc_running |= bid; + if(!sc->ap_running) + ic->ic_opmode = vap->iv_opmode; + run_update_beacon_cb(vap); + break; + case IEEE80211_M_STA: + sc->sta_running |= bid; + if(!sc->ap_running && !sc->adhoc_running) + ic->ic_opmode = vap->iv_opmode; + + /* read statistic counters (clear on read) */ + run_read_region_1(sc, RT2860_TX_STA_CNT0, + (uint8_t *)sta, sizeof sta); + break; + default: + ic->ic_opmode = vap->iv_opmode; + break; + } + if (vap->iv_opmode != IEEE80211_M_MONITOR) { run_updateslot(ic->ic_ifp); run_enable_mrr(sc); @@ -1661,31 +1828,17 @@ run_set_basicrates(sc); IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); run_set_bssid(sc, ni->ni_bssid); - } + run_enable_tsf_sync(sc); - if (vap->iv_opmode == IEEE80211_M_STA) { - /* add BSS entry to the WCID table */ - wcid = RUN_AID2WCID(ni->ni_associd); - run_write_region_1(sc, RT2860_WCID_ENTRY(wcid), - ni->ni_macaddr, IEEE80211_ADDR_LEN); + /* enable automatic rate adaptation */ + tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; + if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) + ratectl |= bid; } - if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) - run_update_beacon_locked(vap, 0); - - if (vap->iv_opmode != IEEE80211_M_MONITOR) { - run_enable_tsf_sync(sc); - } /* else tsf */ - - /* enable automatic rate adaptation */ - tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)]; - if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) - run_amrr_start(sc, ni); - /* turn link LED on */ run_set_leds(sc, RT2860_LED_RADIO | - (IEEE80211_IS_CHAN_2GHZ(vap->iv_bss->ni_chan) ? + (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); break; @@ -1694,34 +1847,28 @@ break; } + /* restart amrr for running VAPs */ + if((sc->ratectl_run = ratectl) && restart_ratectl) + usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc); + RUN_UNLOCK(sc); IEEE80211_LOCK(ic); return(rvp->newstate(vap, nstate, arg)); } -/* another taskqueue, so usbd_do_request() can go sleep */ -static int -run_wme_update(struct ieee80211com *ic) -{ - struct run_softc *sc = ic->ic_ifp->if_softc; - - ieee80211_runtask(ic, &sc->wme_task); - - /* return whatever, upper layer desn't care anyway */ - return 0; -} - /* ARGSUSED */ static void -run_wme_update_cb(void *arg, int pending) +run_wme_update_cb(void *arg) { struct ieee80211com *ic = arg; struct run_softc *sc = ic->ic_ifp->if_softc; struct ieee80211_wme_state *wmesp = &ic->ic_wme; int aci, error = 0; - RUN_LOCK(sc); + DPRINTF("called\n"); + + RUN_LOCK_ASSERT(sc, MA_OWNED); /* update MAC TX configuration registers */ for (aci = 0; aci < WME_NUM_AC; aci++) { @@ -1764,19 +1911,41 @@ if(error) DPRINTF("WME update failed\n"); + return; +} + +static int +run_wme_update(struct ieee80211com *ic) +{ + struct run_softc *sc = ic->ic_ifp->if_softc; + + DPRINTF("called\n"); + + /* 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); + sc->cmdq[i].func = run_wme_update_cb; + sc->cmdq[i].arg0 = ic; + ieee80211_runtask(ic, &sc->cmdq_task); + return (0); + } + + RUN_LOCK(sc); + run_wme_update_cb(ic); RUN_UNLOCK(sc); - return; + + /* return whatever, upper layer desn't care anyway */ + return (0); } static void run_key_update_begin(struct ieee80211vap *vap) { /* - * Because run_key_delete() needs special attention - * on lock related operation, lock handling is being done - * differently in run_key_set and _delete. - * - * So, we don't use key_update_begin and _end. + * To avoid out-of-order events, both run_key_set() and + * _delete() are deferred and handled by run_cmdq_cb(). + * So, there is nothing we need to do here. */ } @@ -1786,37 +1955,31 @@ /* null */ } -/* - * return 0 on error - */ -static int -run_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, - const uint8_t mac[IEEE80211_ADDR_LEN]) +static void +run_key_set_cb(void *arg) { + struct run_cmdq *cmdq = arg; + struct ieee80211vap *vap = cmdq->arg1; + struct ieee80211_key *k = cmdq->k; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct run_softc *sc = ifp->if_softc; + struct run_softc *sc = ic->ic_ifp->if_softc; struct ieee80211_node *ni; uint32_t attr; uint16_t base, associd; uint8_t mode, wcid, txmic, rxmic, iv[8]; - int error = 0; - RUN_LOCK(sc); + RUN_LOCK_ASSERT(sc, MA_OWNED); if(vap->iv_opmode == IEEE80211_M_HOSTAP){ - ni = ieee80211_find_vap_node(&ic->ic_sta, vap, mac); - associd = (ni != NULL) ? ni->ni_associd : 0; - if(ni != NULL) - ieee80211_free_node(ni); + ni = ieee80211_find_vap_node(&ic->ic_sta, vap, cmdq->mac); txmic = 24; rxmic = 16; } else { ni = vap->iv_bss; - associd = (ni != NULL) ? ni->ni_associd : 0; txmic = 16; rxmic = 24; } + associd = (ni != NULL) ? ni->ni_associd : 0; /* map net80211 cipher to RT2860 security mode */ switch (k->wk_cipher->ic_cipher) { @@ -1834,16 +1997,18 @@ break; default: DPRINTF("undefined case\n"); - goto fail; + return; } - DPRINTFN(1, "associd=%x, keyix=%d, mode=%x, type=%s\n", + DPRINTFN(1, "associd=%x, keyix=%d, mode=%x, type=%s, tx=%s, rx=%s\n", associd, k->wk_keyix, mode, - (k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise"); + (k->wk_flags & IEEE80211_KEY_GROUP) ? "group" : "pairwise", + (k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off", + (k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off"); if (k->wk_flags & IEEE80211_KEY_GROUP) { wcid = 0; /* NB: update WCID0 for group keys */ - base = RT2860_SKEY(0, k->wk_keyix); + base = RT2860_SKEY(RUN_VAP(vap)->rvp_id, k->wk_keyix); } else { wcid = RUN_AID2WCID(associd); base = RT2860_PKEY(wcid); @@ -1851,15 +2016,15 @@ if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { if(run_write_region_1(sc, base, k->wk_key, 16)) - goto fail; + return; if(run_write_region_1(sc, base + 16, &k->wk_key[txmic], 8)) /* wk_txmic */ - goto fail; + return; if(run_write_region_1(sc, base + 24, &k->wk_key[rxmic], 8)) /* wk_rxmic */ - goto fail; + return; } else { /* roundup len to 16-bit: XXX fix write_region_1() instead */ if(run_write_region_1(sc, base, k->wk_key, (k->wk_keylen + 1) & ~1)) - goto fail; + return; } if (!(k->wk_flags & IEEE80211_KEY_GROUP) || @@ -1867,7 +2032,7 @@ /* set initial packet number in IV+EIV */ if (k->wk_cipher == IEEE80211_CIPHER_WEP){ memset(iv, 0, sizeof iv); - iv[3] = sc->sc_rvp->vap.iv_def_txkey << 6; + iv[3] = vap->iv_def_txkey << 6; } else { if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { iv[0] = k->wk_keytsc >> 8; @@ -1885,127 +2050,150 @@ iv[7] = k->wk_keytsc >> 40; } if(run_write_region_1(sc, RT2860_IVEIV(wcid), iv, 8)) - goto fail; + return; } if (k->wk_flags & IEEE80211_KEY_GROUP) { /* install group key */ if(run_read(sc, RT2860_SKEY_MODE_0_7, &attr)) - goto fail; + return; attr &= ~(0xf << (k->wk_keyix * 4)); attr |= mode << (k->wk_keyix * 4); if(run_write(sc, RT2860_SKEY_MODE_0_7, attr)) - goto fail; + return; } else { /* install pairwise key */ if(run_read(sc, RT2860_WCID_ATTR(wcid), &attr)) - goto fail; + return; attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN; if(run_write(sc, RT2860_WCID_ATTR(wcid), attr)) - goto fail; + return; } /* TODO create a pass-thru key entry? */ -fail: - RUN_UNLOCK(sc); - return (error? 0 : 1); + /* need wcid to delete the right key later */ + k->wk_pad = wcid; } /* + * Don't have to be deferred, but in order to keep order of + * execution, i.e. with run_key_delete(), defer this and let + * run_cmdq_cb() maintain the order. + * * return 0 on error */ static int -run_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) +run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k, + const uint8_t mac[IEEE80211_ADDR_LEN]) { struct ieee80211com *ic = vap->iv_ic; struct run_softc *sc = ic->ic_ifp->if_softc; - struct ieee80211_node *ni = vap->iv_bss; - struct ieee80211_node_table *nt = &ic->ic_sta; + uint32_t i; + + i = RUN_CMDQ_GET(&sc->cmdq_store); + DPRINTF("cmdq_store=%d\n", i); + 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); + + return(1); +} + +/* + * If wlan is destroyed without being brought down i.e. without + * wlan down or wpa_cli terminate, this function is called after + * vap is gone. Don't refer it. + */ +static void +run_key_delete_cb(void *arg) +{ + struct run_cmdq *cmdq = arg; + struct run_softc *sc = cmdq->arg1; + struct ieee80211_key *k = &cmdq->key; uint32_t attr; uint8_t wcid; - int error = 0; - uint8_t nislocked, cislocked; - if((nislocked = IEEE80211_NODE_IS_LOCKED(nt))) - IEEE80211_NODE_UNLOCK(nt); - if((cislocked = mtx_owned(&ic->ic_comlock.mtx))) - IEEE80211_UNLOCK(ic); - RUN_LOCK(sc); + RUN_LOCK_ASSERT(sc, MA_OWNED); if (k->wk_flags & IEEE80211_KEY_GROUP) { /* remove group key */ - if(run_read(sc, RT2860_SKEY_MODE_0_7, &attr)) - goto fail; + DPRINTF("removing group key\n"); + run_read(sc, RT2860_SKEY_MODE_0_7, &attr); attr &= ~(0xf << (k->wk_keyix * 4)); >>> TRUNCATED FOR MAIL (1000 lines) <<<