Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/dev/ic/bwfm.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/dev/ic/bwfm.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.14.6.3 retrieving revision 1.15 diff -u -p -r1.14.6.3 -r1.15 --- src/sys/dev/ic/bwfm.c 2020/08/17 11:22:45 1.14.6.3 +++ src/sys/dev/ic/bwfm.c 2019/09/01 05:40:39 1.15 @@ -1,4 +1,4 @@ -/* $NetBSD: bwfm.c,v 1.14.6.3 2020/08/17 11:22:45 martin Exp $ */ +/* $NetBSD: bwfm.c,v 1.15 2019/09/01 05:40:39 mlelstv Exp $ */ /* $OpenBSD: bwfm.c,v 1.5 2017/10/16 22:27:16 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -18,23 +18,21 @@ */ #include -#include - +#include #include -#include #include -#include -#include +#include #include #include -#include +#include #include +#include #include #include #include -#include #include +#include #include @@ -114,7 +112,6 @@ int bwfm_fwvar_var_set_int(struct bwfm_ struct ieee80211_channel *bwfm_bss2chan(struct bwfm_softc *, struct bwfm_bss_info *); void bwfm_scan(struct bwfm_softc *); void bwfm_connect(struct bwfm_softc *); -void bwfm_get_sta_info(struct bwfm_softc *, struct ifmediareq *); void bwfm_rx(struct bwfm_softc *, struct mbuf *); void bwfm_rx_event(struct bwfm_softc *, struct mbuf *); @@ -139,21 +136,24 @@ bwfm_attach(struct bwfm_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &sc->sc_if; + struct bwfm_task *t; char fw_version[BWFM_DCMD_SMLEN]; uint32_t bandlist[3]; uint32_t tmp; int i, j, error; error = workqueue_create(&sc->sc_taskq, DEVNAME(sc), - bwfm_task, sc, PRI_NONE, IPL_NET, 0); + bwfm_task, sc, PRI_NONE, IPL_NET, WQ_MPSAFE); if (error != 0) { printf("%s: could not create workqueue\n", DEVNAME(sc)); return; } - sc->sc_freetask = pool_cache_init(sizeof(struct bwfm_task), 0, 0, 0, - "bwfmtask", NULL, IPL_NET /* XXX IPL_SOFTNET? */, - NULL, NULL, NULL); - pool_prime(&sc->sc_freetask->pc_pool, BWFM_TASK_COUNT); + sc->sc_freetask = pcq_create(BWFM_TASK_COUNT, KM_SLEEP); + for (i = 0; i < BWFM_TASK_COUNT; i++) { + t = &sc->sc_task[i]; + t->t_sc = sc; + pcq_put(sc->sc_freetask, t); + } /* Stop the device in case it was previously initialized */ bwfm_fwvar_cmd_set_int(sc, BWFM_C_DOWN, 1); @@ -202,7 +202,7 @@ bwfm_attach(struct bwfm_softc *sc) sizeof(bandlist))) { printf("%s: couldn't get supported band list\n", DEVNAME(sc)); return; - } + } const u_int nbands = le32toh(bandlist[0]); for (i = 1; i <= MIN(nbands, __arraycount(bandlist) - 1); i++) { switch (le32toh(bandlist[i])) { @@ -246,13 +246,17 @@ bwfm_attach(struct bwfm_softc *sc) error = if_initialize(ifp); if (error != 0) { printf("%s: if_initialize failed(%d)\n", DEVNAME(sc), error); - pool_cache_destroy(sc->sc_freetask); + pcq_destroy(sc->sc_freetask); workqueue_destroy(sc->sc_taskq); return; /* Error */ } - + ieee80211_ifattach(ic); + ifp->if_percpuq = if_percpuq_create(ifp); + if_deferred_start_init(ifp, NULL); + if_register(ifp); + sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = bwfm_newstate; ic->ic_newassoc = bwfm_newassoc; @@ -260,10 +264,6 @@ bwfm_attach(struct bwfm_softc *sc) ic->ic_recv_mgmt = bwfm_recv_mgmt; ic->ic_crypto.cs_key_set = bwfm_key_set; ic->ic_crypto.cs_key_delete = bwfm_key_delete; - - ifp->if_percpuq = if_percpuq_create(ifp); - if_deferred_start_init(ifp, NULL); - if_register(ifp); ieee80211_media_init(ic, bwfm_media_change, ieee80211_media_status); ieee80211_announce(ic); @@ -286,7 +286,7 @@ bwfm_detach(struct bwfm_softc *sc, int f if (sc->sc_taskq) workqueue_destroy(sc->sc_taskq); if (sc->sc_freetask) - pool_cache_destroy(sc->sc_freetask); + pcq_destroy(sc->sc_freetask); return 0; } @@ -344,7 +344,6 @@ bwfm_init(struct ifnet *ifp) struct ieee80211com *ic = &sc->sc_ic; uint8_t evmask[BWFM_EVENT_MASK_LEN]; struct bwfm_join_pref_params join_pref[2]; - int pm; if (bwfm_fwvar_var_set_int(sc, "mpc", 1)) { printf("%s: could not set mpc\n", DEVNAME(sc)); @@ -370,37 +369,16 @@ bwfm_init(struct ifnet *ifp) #define ENABLE_EVENT(e) evmask[(e) / 8] |= 1 << ((e) % 8) /* Events used to drive the state machine */ - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - ENABLE_EVENT(BWFM_E_IF); - ENABLE_EVENT(BWFM_E_LINK); - ENABLE_EVENT(BWFM_E_AUTH); - ENABLE_EVENT(BWFM_E_ASSOC); - ENABLE_EVENT(BWFM_E_DEAUTH); - ENABLE_EVENT(BWFM_E_DISASSOC); - ENABLE_EVENT(BWFM_E_SET_SSID); - ENABLE_EVENT(BWFM_E_ESCAN_RESULT); - break; -#ifndef IEEE80211_STA_ONLY - case IEEE80211_M_HOSTAP: - ENABLE_EVENT(BWFM_E_AUTH_IND); - ENABLE_EVENT(BWFM_E_ASSOC_IND); - ENABLE_EVENT(BWFM_E_REASSOC_IND); - ENABLE_EVENT(BWFM_E_DEAUTH_IND); - ENABLE_EVENT(BWFM_E_DISASSOC_IND); - ENABLE_EVENT(BWFM_E_ESCAN_RESULT); - ENABLE_EVENT(BWFM_E_ESCAN_RESULT); - break; -#endif - default: - break; - } + ENABLE_EVENT(BWFM_E_ASSOC); + ENABLE_EVENT(BWFM_E_ESCAN_RESULT); + ENABLE_EVENT(BWFM_E_SET_SSID); + ENABLE_EVENT(BWFM_E_LINK); #undef ENABLE_EVENT #ifdef BWFM_DEBUG memset(evmask, 0xff, sizeof(evmask)); #endif - + if (bwfm_fwvar_var_set_data(sc, "event_msgs", evmask, sizeof(evmask))) { printf("%s: could not set event mask\n", DEVNAME(sc)); return EIO; @@ -422,16 +400,7 @@ bwfm_init(struct ifnet *ifp) return EIO; } - /* - * Use CAM (constantly awake) when we are running as AP - * otherwise use fast power saving. - */ - pm = BWFM_PM_FAST_PS; -#ifndef IEEE80211_STA_ONLY - if (ic->ic_opmode == IEEE80211_M_HOSTAP) - pm = BWFM_PM_CAM; -#endif - if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, pm)) { + if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, 2)) { printf("%s: could not set power\n", DEVNAME(sc)); return EIO; } @@ -478,25 +447,15 @@ bwfm_stop(struct ifnet *ifp, int disable { struct bwfm_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - struct bwfm_join_params join; sc->sc_tx_timer = 0; ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); - memset(&join, 0, sizeof(join)); - bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_SSID, &join, sizeof(join)); bwfm_fwvar_cmd_set_int(sc, BWFM_C_DOWN, 1); bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, 0); - bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_AP, 0); - bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_INFRA, 0); - bwfm_fwvar_cmd_set_int(sc, BWFM_C_UP, 1); - bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, BWFM_PM_FAST_PS); ieee80211_new_state(ic, IEEE80211_S_INIT, -1); - - if (sc->sc_bus_ops->bs_stop) - sc->sc_bus_ops->bs_stop(sc); } void @@ -553,12 +512,6 @@ bwfm_ioctl(struct ifnet *ifp, u_long cmd } break; - case SIOCGIFMEDIA: - error = ieee80211_ioctl(ic, cmd, data); - if (error == 0 && ic->ic_state == IEEE80211_S_RUN) - bwfm_get_sta_info(sc, (struct ifmediareq *)data); - break; - default: error = ieee80211_ioctl(ic, cmd, data); } @@ -597,13 +550,12 @@ bwfm_key_set(struct ieee80211com *ic, co struct bwfm_softc *sc = ic->ic_ifp->if_softc; struct bwfm_task *t; - t = pool_cache_get(sc->sc_freetask, PR_NOWAIT); + t = pcq_get(sc->sc_freetask); if (t == NULL) { printf("%s: no free tasks\n", DEVNAME(sc)); return 0; } - t->t_sc = sc; t->t_cmd = BWFM_TASK_KEY_SET; t->t_key.key = wk; memcpy(t->t_key.mac, mac, sizeof(t->t_key.mac)); @@ -647,7 +599,7 @@ bwfm_key_set_cb(struct bwfm_softc *sc, s wsec_key.len = htole32(wk->wk_keylen); memcpy(wsec_key.data, wk->wk_key, sizeof(wsec_key.data)); if (!ext_key) - wsec_key.flags = htole32(BWFM_WSEC_PRIMARY_KEY); + wsec_key.flags = htole32(BWFM_PRIMARY_KEY); switch (wk->wk_cipher->ic_cipher) { case IEEE80211_CIPHER_WEP: @@ -689,13 +641,12 @@ bwfm_key_delete(struct ieee80211com *ic, struct bwfm_softc *sc = ic->ic_ifp->if_softc; struct bwfm_task *t; - t = pool_cache_get(sc->sc_freetask, PR_NOWAIT); + t = pcq_get(sc->sc_freetask); if (t == NULL) { printf("%s: no free tasks\n", DEVNAME(sc)); return 0; } - t->t_sc = sc; t->t_cmd = BWFM_TASK_KEY_DELETE; t->t_key.key = wk; memset(t->t_key.mac, 0, sizeof(t->t_key.mac)); @@ -712,7 +663,7 @@ bwfm_key_delete_cb(struct bwfm_softc *sc memset(&wsec_key, 0, sizeof(wsec_key)); wsec_key.index = htole32(wk->wk_keyix); - wsec_key.flags = htole32(BWFM_WSEC_PRIMARY_KEY); + wsec_key.flags = htole32(BWFM_PRIMARY_KEY); if (bwfm_fwvar_var_set_data(sc, "wsec_key", &wsec_key, sizeof(wsec_key))) return; @@ -724,13 +675,12 @@ bwfm_newstate(struct ieee80211com *ic, e struct bwfm_softc *sc = ic->ic_ifp->if_softc; struct bwfm_task *t; - t = pool_cache_get(sc->sc_freetask, PR_NOWAIT); + t = pcq_get(sc->sc_freetask); if (t == NULL) { printf("%s: no free tasks\n", DEVNAME(sc)); return EIO; } - t->t_sc = sc; t->t_cmd = BWFM_TASK_NEWSTATE; t->t_newstate.state = nstate; t->t_newstate.arg = arg; @@ -808,7 +758,7 @@ bwfm_task(struct work *wk, void *arg) panic("bwfm: unknown task command %d", t->t_cmd); } - pool_cache_put(sc->sc_freetask, t); + pcq_put(sc->sc_freetask, t); } int @@ -1495,10 +1445,10 @@ bwfm_proto_bcdc_query_dcmd(struct bwfm_s { struct bwfm_proto_bcdc_dcmd *dcmd; size_t size = sizeof(dcmd->hdr) + *len; - int reqid; + static int reqid = 0; int ret = 1; - reqid = sc->sc_bcdc_reqid++; + reqid++; dcmd = kmem_zalloc(sizeof(*dcmd), KM_SLEEP); if (*len > sizeof(dcmd->buf)) @@ -1555,9 +1505,10 @@ bwfm_proto_bcdc_set_dcmd(struct bwfm_sof { struct bwfm_proto_bcdc_dcmd *dcmd; size_t size = sizeof(dcmd->hdr) + len; - int ret = 1, reqid; + int reqid = 0; + int ret = 1; - reqid = sc->sc_bcdc_reqid++; + reqid++; dcmd = kmem_zalloc(sizeof(*dcmd), KM_SLEEP); if (len > sizeof(dcmd->buf)) @@ -1838,55 +1789,12 @@ bwfm_connect(struct bwfm_softc *sc) } void -bwfm_get_sta_info(struct bwfm_softc *sc, struct ifmediareq *ifmr) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = ic->ic_bss; - struct bwfm_sta_info sta; - uint32_t flags, txrate; - - memset(&sta, 0, sizeof(sta)); - memcpy(&sta, ni->ni_macaddr, sizeof(ni->ni_macaddr)); - - if (bwfm_fwvar_var_get_data(sc, "sta_info", &sta, sizeof(sta))) - return; - - if (!IEEE80211_ADDR_EQ(ni->ni_macaddr, sta.ea)) - return; - - if (le16toh(sta.ver) < 4) - return; - - flags = le32toh(sta.flags); - if ((flags & BWFM_STA_SCBSTATS) == 0) - return; - - txrate = le32toh(sta.tx_rate); - if (txrate == 0xffffffff) - return; - - if ((flags & BWFM_STA_VHT_CAP) != 0) { - ifmr->ifm_active &= ~IFM_TMASK; - ifmr->ifm_active |= IFM_IEEE80211_VHT; - ifmr->ifm_active &= ~IFM_MMASK; - ifmr->ifm_active |= IFM_IEEE80211_11AC; - } else if ((flags & BWFM_STA_N_CAP) != 0) { - ifmr->ifm_active &= ~IFM_TMASK; - ifmr->ifm_active |= IFM_IEEE80211_MCS; - ifmr->ifm_active &= ~IFM_MMASK; - if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) - ifmr->ifm_active |= IFM_IEEE80211_11NG; - else - ifmr->ifm_active |= IFM_IEEE80211_11NA; - } -} - -void bwfm_rx(struct bwfm_softc *sc, struct mbuf *m) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = ic->ic_ifp; struct bwfm_event *e = mtod(m, struct bwfm_event *); + int s; if (m->m_len >= sizeof(e->ehdr) && ntohs(e->ehdr.ether_type) == BWFM_ETHERTYPE_LINK_CTL && @@ -1897,8 +1805,14 @@ bwfm_rx(struct bwfm_softc *sc, struct mb return; } - m_set_rcvif(m, ifp); - if_percpuq_enqueue(ifp->if_percpuq, m); + s = splnet(); + + //if ((ifp->if_flags & IFF_RUNNING) != 0) { + m_set_rcvif(m, ifp); + if_percpuq_enqueue(ifp->if_percpuq, m); + //} + + splx(s); } void @@ -1906,14 +1820,13 @@ bwfm_rx_event(struct bwfm_softc *sc, str { struct bwfm_task *t; - t = pool_cache_get(sc->sc_freetask, PR_NOWAIT); + t = pcq_get(sc->sc_freetask); if (t == NULL) { m_freem(m); printf("%s: no free tasks\n", DEVNAME(sc)); return; } - t->t_sc = sc; t->t_cmd = BWFM_TASK_RX_EVENT; t->t_mbuf = m; workqueue_enqueue(sc->sc_taskq, (struct work*)t, NULL);