From owner-p4-projects@FreeBSD.ORG Thu Jan 15 13:56:26 2004 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CE87316A4D1; Thu, 15 Jan 2004 13:56:25 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8ABA716A4CF for ; Thu, 15 Jan 2004 13:56:25 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5F83843D6D for ; Thu, 15 Jan 2004 13:56:20 -0800 (PST) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.10/8.12.10) with ESMTP id i0FLuJ0B086501 for ; Thu, 15 Jan 2004 13:56:20 -0800 (PST) (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.10/8.12.10/Submit) id i0FLuJAP086498 for perforce@freebsd.org; Thu, 15 Jan 2004 13:56:19 -0800 (PST) (envelope-from sam@freebsd.org) Date: Thu, 15 Jan 2004 13:56:19 -0800 (PST) Message-Id: <200401152156.i0FLuJAP086498@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Subject: PERFORCE change 45412 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Jan 2004 21:56:26 -0000 http://perforce.freebsd.org/chv.cgi?CH=45412 Change 45412 by sam@sam_ebb on 2004/01/15 13:55:51 Add an ic_reset callback method to notify drivers a hardware reset (as opposed to full reset) is needed. Drivers may implement this directly or return ENETRESET to cause a full reset to be done after unwinding the stack. Use this mechanism in the ath driver to reload the h/w state w/o kicking the 802.11 state machine. Other drivers just return ENETRESET for now. Affected files ... .. //depot/projects/netperf+sockets/sys/dev/ath/if_ath.c#16 edit .. //depot/projects/netperf+sockets/sys/dev/awi/awi.c#4 edit .. //depot/projects/netperf+sockets/sys/dev/wi/if_wi.c#6 edit .. //depot/projects/netperf+sockets/sys/net80211/ieee80211_ioctl.c#8 edit .. //depot/projects/netperf+sockets/sys/net80211/ieee80211_var.h#5 edit Differences ... ==== //depot/projects/netperf+sockets/sys/dev/ath/if_ath.c#16 (text+ko) ==== @@ -95,7 +95,7 @@ static void ath_init(void *); static void ath_stop(struct ifnet *); static void ath_start(struct ifnet *); -static void ath_reset(struct ath_softc *, int); +static int ath_reset(struct ieee80211com *); static int ath_media_change(struct ifnet *); static void ath_watchdog(struct ifnet *); static int ath_ioctl(struct ifnet *, u_long, caddr_t); @@ -328,6 +328,7 @@ ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; ic->ic_softc = sc; + ic->ic_reset = ath_reset; ic->ic_newassoc = ath_newassoc; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; @@ -508,7 +509,7 @@ struct ath_softc *sc = arg; device_printf(sc->sc_dev, "hardware error; resetting\n"); - ath_reset(sc, 0); + ath_reset(&sc->sc_ic); } static void @@ -517,7 +518,7 @@ struct ath_softc *sc = arg; device_printf(sc->sc_dev, "rx FIFO overrun; resetting\n"); - ath_reset(sc, 0); + ath_reset(&sc->sc_ic); } static void @@ -684,11 +685,11 @@ * operational state. Used to recover from errors rx overrun * and to reset the hardware when rf gain settings must be reset. */ -static void -ath_reset(struct ath_softc *sc, int full) +static int +ath_reset(struct ieee80211com *ic) { - struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; + struct ath_softc *sc = ifp->if_softc; struct ath_hal *ah = sc->sc_ah; struct ieee80211_channel *c; HAL_STATUS status; @@ -709,15 +710,19 @@ if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status)) if_printf(ifp, "%s: unable to reset hardware; hal status %u\n", __func__, status); - /* NB: only needed when called from ath_ioctl */ - if (full && (ic->ic_flags & IEEE80211_F_WEPON)) - ath_initkeytable(sc); + /* + * NB: key state is preserved across resets but since we + * may be called after an ioctl call to update the + * hardware state we do this regardless. + */ + ath_initkeytable(sc); ath_hal_intrset(ah, sc->sc_imask); if (ath_startrecv(sc) != 0) /* restart recv */ if_printf(ifp, "%s: unable to start recv logic\n", __func__); ath_start(ifp); /* restart xmit */ if (ic->ic_state == IEEE80211_S_RUN) ath_beacon_config(sc); /* restart beacons */ + return 0; } static void @@ -866,7 +871,7 @@ if (ath_debug & ATH_DEBUG_WATCHDOG) ath_hal_dumpstate(sc->sc_ah); #endif /* AR_DEBUG */ - ath_reset(sc, 0); + ath_reset(ic); ifp->if_oerrors++; sc->sc_stats.ast_watchdog++; return; @@ -956,20 +961,8 @@ default: error = ieee80211_ioctl(ifp, cmd, data); if (error == ENETRESET) { - /* - * If the interface is up and running then we - * want the parameter changes to take effect - * immediately, so reset hardware state to - * reflect parameter change(s). We don't try to - * intuit exactly what changed here; we just - * bludgeon state which can have unfortunate - * side effects. - * - * XXX doesn't recognize when a rescan is needed; - * e.g. for ssid or channel change - */ if (UP_RUNNING(ifp)) - ath_reset(sc, 1); + ath_init(sc); error = 0; } break; @@ -2547,7 +2540,7 @@ * to load new gain values. */ sc->sc_stats.ast_per_rfgain++; - ath_reset(sc, 0); + ath_reset(ic); } if (!ath_hal_calibrate(ah, &hchan)) { DPRINTF(ATH_DEBUG_ANY, ==== //depot/projects/netperf+sockets/sys/dev/awi/awi.c#4 (text+ko) ==== @@ -157,6 +157,7 @@ #ifdef __FreeBSD__ static void awi_init0(void *); #endif +static int awi_reset(struct ieee80211com *); static int awi_init(struct ifnet *); static void awi_stop(struct ifnet *, int); static void awi_start(struct ifnet *); @@ -313,6 +314,7 @@ sc->sc_mib_phy.aSuprt_Data_Rates + 2, nrate); ic->ic_sup_rates[mode].rs_nrates = nrate; IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_mib_addr.aMAC_Address); + ic->ic_reset = awi_reset; printf("%s: IEEE802.11 %s (firmware %s)\n", ifp->if_xname, (ic->ic_phytype == IEEE80211_T_FH) ? "FH" : "DS", sc->sc_banner); @@ -544,6 +546,12 @@ #endif static int +awi_reset(struct ieee80211com *ic) +{ + return ENETRESET; /* XXX force delayed call to awi_init */ +} + +static int awi_init(struct ifnet *ifp) { struct awi_softc *sc = ifp->if_softc; @@ -2155,7 +2163,7 @@ } /* NB: EAPOL frames have their own encryption policy */ if (ic->ic_flags & IEEE80211_F_WEPON && - eh.ether_type != ETHERTYPE_EAPOL) + eh->ether_type != ETHERTYPE_EAPOL) wh->i_fc[1] |= IEEE80211_FC1_WEP; return m; } ==== //depot/projects/netperf+sockets/sys/dev/wi/if_wi.c#6 (text+ko) ==== @@ -118,6 +118,7 @@ #define IFQ_POLL(ifq, m) IF_POLL((ifq), (m)) #define IFQ_DEQUEUE(ifq, m) IF_DEQUEUE((ifq), (m)) +static int wi_hwreset(struct ieee80211com *); static void wi_start(struct ifnet *); static int wi_reset(struct wi_softc *); static void wi_watchdog(struct ifnet *); @@ -313,6 +314,7 @@ ic->ic_opmode = IEEE80211_M_STA; ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO; ic->ic_state = IEEE80211_S_INIT; + ic->ic_reset = wi_hwreset; /* * Query the card for available channels and setup the @@ -621,6 +623,12 @@ return; } +static int +wi_hwreset(struct ieee80211com *arg) +{ + return ENETRESET; /* force delayed call to wi_init */ +} + void wi_init(void *arg) { ==== //depot/projects/netperf+sockets/sys/net80211/ieee80211_ioctl.c#8 (text+ko) ==== @@ -564,7 +564,7 @@ return EINVAL; setrate: ic->ic_fixed_rate = i; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case WI_RID_CUR_TX_RATE: return EPERM; @@ -622,12 +622,12 @@ return EINVAL; if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { ic->ic_flags |= IEEE80211_F_PMGTON; - error = ENETRESET; + error = (*ic->ic_reset)(ic); } } else { if (ic->ic_flags & IEEE80211_F_PMGTON) { ic->ic_flags &= ~IEEE80211_F_PMGTON; - error = ENETRESET; + error = (*ic->ic_reset)(ic); } } break; @@ -636,7 +636,7 @@ return EINVAL; ic->ic_lintval = le16toh(wreq.wi_val[0]); if (ic->ic_flags & IEEE80211_F_PMGTON) - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case WI_RID_CUR_BEACON_INT: return EPERM; @@ -678,6 +678,7 @@ if (i >= IEEE80211_WEP_NKID) return EINVAL; ic->ic_wep_txkey = i; + error = (*ic->ic_reset)(ic); break; case WI_RID_DEFLT_CRYPT_KEYS: if (len != sizeof(struct wi_ltv_keys)) @@ -697,7 +698,7 @@ memcpy(ic->ic_nw_keys[i].wk_key, keys->wi_keys[i].wi_keydat, len); } - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case WI_RID_MAX_DATALEN: if (len != 2) @@ -708,7 +709,7 @@ if (len != IEEE80211_MAX_LEN) return EINVAL; /* TODO: fragment */ ic->ic_fragthreshold = len; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case WI_RID_IFACE_STATS: error = EPERM; @@ -910,11 +911,16 @@ * passed in is not OFF. */ if (ireq->i_val == IEEE80211_WEP_OFF) { - ic->ic_flags &= ~IEEE80211_F_WEPON; + if (ic->ic_flags & IEEE80211_F_WEPON) { + ic->ic_flags &= ~IEEE80211_F_WEPON; + error = ENETRESET; + } } else { - ic->ic_flags |= IEEE80211_F_WEPON; + if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) { + ic->ic_flags |= IEEE80211_F_WEPON; + error = ENETRESET; + } } - error = ENETRESET; break; case IEEE80211_IOC_WEPKEY: if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { @@ -937,7 +943,7 @@ memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey, sizeof(tmpkey)); ic->ic_nw_keys[kid].wk_len = ireq->i_len; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case IEEE80211_IOC_WEPTXKEY: kid = (u_int) ireq->i_val; @@ -946,7 +952,7 @@ break; } ic->ic_wep_txkey = kid; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case IEEE80211_IOC_AUTHMODE: if (!(IEEE80211_AUTH_NONE <= ireq->i_val && @@ -999,7 +1005,7 @@ case IEEE80211_POWERSAVE_OFF: if (ic->ic_flags & IEEE80211_F_PMGTON) { ic->ic_flags &= ~IEEE80211_F_PMGTON; - error = ENETRESET; + error = (*ic->ic_reset)(ic); } break; case IEEE80211_POWERSAVE_ON: @@ -1007,7 +1013,7 @@ error = EINVAL; else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { ic->ic_flags |= IEEE80211_F_PMGTON; - error = ENETRESET; + error = (*ic->ic_reset)(ic); } break; default: @@ -1021,7 +1027,7 @@ break; } ic->ic_lintval = ireq->i_val; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; case IEEE80211_IOC_RTSTHRESHOLD: if (!(IEEE80211_RTS_MIN < ireq->i_val && @@ -1030,7 +1036,7 @@ break; } ic->ic_rtsthreshold = ireq->i_val; - error = ENETRESET; + error = (*ic->ic_reset)(ic); break; default: error = EINVAL; ==== //depot/projects/netperf+sockets/sys/net80211/ieee80211_var.h#5 (text+ko) ==== @@ -150,6 +150,7 @@ struct ieee80211com { struct arpcom ic_ac; + int (*ic_reset)(struct ieee80211com *); void (*ic_recv_mgmt)(struct ieee80211com *, struct mbuf *, struct ieee80211_node *, int, int, u_int32_t);