Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Jan 2004 13:56:19 -0800 (PST)
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 45412 for review
Message-ID:  <200401152156.i0FLuJAP086498@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200401152156.i0FLuJAP086498>