Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Aug 2005 21:56:54 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 81315 for review
Message-ID:  <200508012156.j71LusCV029648@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=81315

Change 81315 by sam@sam_ebb on 2005/08/01 21:56:24

	Use a private callout to timeout mgt frames instead of using
	the watchdog timer; this eliminates another incestuous tie
	between the driver and net80211.
	
	Also bring in proper handling of tx timeout on auth frames:
	notify the scan module so the entry is ignored; this fixes
	problems with ap's moving channel.

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#94 edit
.. //depot/projects/wifi/sys/net80211/ieee80211.c#26 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_output.c#51 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_proto.c#33 edit
.. //depot/projects/wifi/sys/net80211/ieee80211_var.h#32 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#94 (text+ko) ====

@@ -4370,8 +4370,6 @@
 				ath_hal_txprocdesc(ah, bf->bf_desc) == HAL_OK);
 #endif /* AR_DEBUG */
 		bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
-		m_freem(bf->bf_m);
-		bf->bf_m = NULL;
 		ni = bf->bf_node;
 		bf->bf_node = NULL;
 		if (ni != NULL) {
@@ -4380,6 +4378,8 @@
 			 */
 			ieee80211_free_node(ni);
 		}
+		m_freem(bf->bf_m);
+		bf->bf_m = NULL;
 		ATH_TXBUF_LOCK(sc);
 		STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
 		ATH_TXBUF_UNLOCK(sc);
@@ -5198,7 +5198,6 @@
 ath_watchdog(struct ifnet *ifp)
 {
 	struct ath_softc *sc = ifp->if_softc;
-	struct ieee80211com *ic = &sc->sc_ic;
 
 	ifp->if_timer = 0;
 	if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid)
@@ -5212,7 +5211,6 @@
 		} else
 			ifp->if_timer = 1;
 	}
-	ieee80211_watchdog(ic);
 }
 
 /*

==== //depot/projects/wifi/sys/net80211/ieee80211.c#26 (text+ko) ====

@@ -795,18 +795,6 @@
 		imr->ifm_active |= IFM_AUTO;
 }
 
-void
-ieee80211_watchdog(struct ieee80211com *ic)
-{
-
-	if (ic->ic_state != IEEE80211_S_INIT) {
-		if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0)
-			ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
-	}
-	if (ic->ic_mgt_timer != 0)
-		ic->ic_ifp->if_timer = 1;
-}
-
 /*
  * Set the current phy mode and recalculate the active channel
  * set based on the available channels for this mode.  Also

==== //depot/projects/wifi/sys/net80211/ieee80211_output.c#51 (text+ko) ====

@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.32 2005/07/31 06:12:32 sam Exp $");
+__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.31 2005/07/22 21:11:26 sam Exp $");
 
 #include "opt_inet.h"
 
@@ -64,6 +64,7 @@
 	struct mbuf *m2, const struct ether_header *eh2);
 static int ieee80211_fragment(struct ieee80211com *, struct mbuf *,
 	u_int hdrsize, u_int ciphdrsize, u_int mtu);
+static	void ieee80211_tx_timeout(void *);
 
 #ifdef IEEE80211_DEBUG
 /*
@@ -213,10 +214,6 @@
 
 /*
  * Send a null data frame to the specified node.
- *
- * NB: the caller is assumed to have setup a node reference
- *     for use; this is necessary to deal with a race condition
- *     when probing for inactive stations.
  */
 int
 ieee80211_send_nulldata(struct ieee80211_node *ni)
@@ -230,10 +227,9 @@
 	if (m == NULL) {
 		/* XXX debug msg */
 		ic->ic_stats.is_tx_nobuf++;
-		ieee80211_unref_node(&ni);
 		return ENOMEM;
 	}
-	m->m_pkthdr.rcvif = (void *) ni;
+	m->m_pkthdr.rcvif = (void *) ieee80211_ref_node(ni);
 
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ic, ni, wh,
@@ -1703,17 +1699,34 @@
 	}
 
 	ret = ieee80211_mgmt_output(ic, ni, m, type);
-	if (ret == 0) {
-		if (timer)
-			ic->ic_mgt_timer = timer;
-	} else {
+	if (ret != 0)
+		goto bad;
+	if (timer)
+		callout_reset(&ic->ic_mgtsend, timer*hz,
+			ieee80211_tx_timeout, ic);
+	return 0;
 bad:
-		ieee80211_free_node(ni);
-	}
+	ieee80211_free_node(ni);
 	return ret;
 #undef senderr
 }
 
+static void
+ieee80211_tx_timeout(void *arg)
+{
+	struct ieee80211com *ic	= arg;
+
+	if (ic->ic_state != IEEE80211_S_INIT &&
+	    (ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+		/*
+		 * NB: it's safe to specify a timeout as the reason here;
+		 *     it'll only be used in the right state.
+		 */
+		ieee80211_new_state(ic, IEEE80211_S_SCAN,
+			IEEE80211_SCAN_FAIL_TIMEOUT);
+	}
+}
+
 /*
  * Allocate a beacon frame and fillin the appropriate bits.
  */

==== //depot/projects/wifi/sys/net80211/ieee80211_proto.c#33 (text+ko) ====

@@ -97,6 +97,7 @@
 	ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
 	ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
 	ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
+	callout_init(&ic->ic_mgtsend, CALLOUT_MPSAFE);
 	ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
 	ic->ic_protmode = IEEE80211_PROT_CTSONLY;
 	ic->ic_roaming = IEEE80211_ROAMING_AUTO;
@@ -919,6 +920,7 @@
 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
 		ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
 	ic->ic_state = nstate;			/* state transition */
+	callout_drain(&ic->ic_mgtsend);
 	if (ostate != IEEE80211_S_SCAN)
 		ieee80211_cancel_scan(ic);	/* background scan */
 	ni = ic->ic_bss;			/* NB: no reference held */
@@ -963,7 +965,6 @@
 			goto reset;
 		case IEEE80211_S_AUTH:
 		reset:
-			ic->ic_mgt_timer = 0;
 			IF_DRAIN(&ic->ic_mgtq);
 			ieee80211_reset_bss(ic);
 			break;
@@ -1144,7 +1145,6 @@
 					IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
 			}
 #endif
-			ic->ic_mgt_timer = 0;
 			if (ic->ic_opmode == IEEE80211_M_STA)
 				ieee80211_scan_assoc_success(ic,
 					ni->ni_macaddr);

==== //depot/projects/wifi/sys/net80211/ieee80211_var.h#32 (text+ko) ====

@@ -175,6 +175,7 @@
 
 	struct ifqueue		ic_mgtq;
 	enum ieee80211_state	ic_state;	/* 802.11 state */
+	struct callout		ic_mgtsend;	/* mgmt frame response timer */
 	u_int32_t		*ic_aid_bitmap;	/* association id map */
 	u_int16_t		ic_max_aid;
 	u_int16_t		ic_ps_sta;	/* stations in power save */
@@ -193,7 +194,6 @@
 	u_int16_t		ic_txmin;	/* min tx retry count */
 	u_int16_t		ic_txmax;	/* max tx retry count */
 	u_int16_t		ic_txlifetime;	/* tx lifetime */
-	int			ic_mgt_timer;	/* mgmt timeout */
 	struct callout		ic_inact;	/* inactivity timer wait */
 	void			*ic_opt_ie;	/* user-specified IE's */
 	u_int16_t		ic_opt_ie_len;	/* length of ni_opt_ie */
@@ -327,7 +327,6 @@
 int	ieee80211_ioctl(struct ieee80211com *, u_long, caddr_t);
 int	ieee80211_cfgget(struct ieee80211com *, u_long, caddr_t);
 int	ieee80211_cfgset(struct ieee80211com *, u_long, caddr_t);
-void	ieee80211_watchdog(struct ieee80211com *);
 int	ieee80211_rate2media(struct ieee80211com *, int,
 		enum ieee80211_phymode);
 int	ieee80211_media2rate(int);



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