PERFORCE change 128855 for review

Tai-hwa Liang avatar at FreeBSD.org
Thu Nov 8 22:23:03 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=128855

Change 128855 by avatar at avatar_t40 on 2007/11/09 06:22:32

	- Trying to eliminate another racing by replacing the timeout(9)
	  with callout APIs.  In addition to that, the callout_drain() in
	  an_detach() help us to avoid a possible panic-on-free due to the
	  callout API tries to lock a destroyed mutex [1];
	
	- In an_stats_update(), check the return value of an_read_record().
	  This should reduce the device removal(PCCARD) panic [2].
	
	Submitted by:	jhb [1], ambrisko [2]
	Reviewed by:	jhb, ambrisko
	Tested by:	dhw
	MFP4 after:	3 days

Affected files ...

.. //depot/projects/wifi/sys/dev/an/if_an.c#20 edit
.. //depot/projects/wifi/sys/dev/an/if_anreg.h#4 edit

Differences ...

==== //depot/projects/wifi/sys/dev/an/if_an.c#20 (text+ko) ====

@@ -790,7 +790,7 @@
 	 */
 
 	ether_ifattach(ifp, sc->an_caps.an_oemaddr);
-	callout_handle_init(&sc->an_stat_ch);
+	callout_init_mtx(&sc->an_stat_ch, &sc->an_mtx, 0);
 
 	return(0);
 fail:;
@@ -818,6 +818,7 @@
 	AN_UNLOCK(sc);
 	ether_ifdetach(ifp);
 	bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+	callout_drain(&sc->an_stat_ch);
 	if_free(ifp);
 	an_release_resources(dev);
 	mtx_destroy(&sc->an_mtx);
@@ -1150,18 +1151,17 @@
 	struct ifnet		*ifp;
 
 	sc = xsc;
-	AN_LOCK(sc);
-
 	if (sc->an_gone) {
-		AN_UNLOCK(sc);
 		return;
 	}
 
+	AN_LOCK_ASSERT(sc);
 	ifp = sc->an_ifp;
 
 	sc->an_status.an_type = AN_RID_STATUS;
 	sc->an_status.an_len = sizeof(struct an_ltv_status);
-	an_read_record(sc, (struct an_ltv_gen *)&sc->an_status);
+	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_status))
+		return;
 
 	if (sc->an_status.an_opmode & AN_STATUS_OPMODE_IN_SYNC)
 		sc->an_associated = 1;
@@ -1170,17 +1170,16 @@
 
 	/* Don't do this while we're transmitting */
 	if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
-		sc->an_stat_ch = timeout(an_stats_update, sc, hz);
-		AN_UNLOCK(sc);
+		callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc);
 		return;
 	}
 
 	sc->an_stats.an_len = sizeof(struct an_ltv_stats);
 	sc->an_stats.an_type = AN_RID_32BITS_CUM;
-	an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len);
+	if (an_read_record(sc, (struct an_ltv_gen *)&sc->an_stats.an_len))
+		return;
 
-	sc->an_stat_ch = timeout(an_stats_update, sc, hz);
-	AN_UNLOCK(sc);
+	callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc);
 
 	return;
 }
@@ -2621,7 +2620,7 @@
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
-	sc->an_stat_ch = timeout(an_stats_update, sc, hz);
+	callout_reset(&sc->an_stat_ch, hz, an_stats_update, sc);
 	AN_UNLOCK(sc);
 
 	return;
@@ -2834,7 +2833,7 @@
 	for (i = 0; i < AN_TX_RING_CNT; i++)
 		an_cmd(sc, AN_CMD_DEALLOC_MEM, sc->an_rdata.an_tx_fids[i]);
 
-	untimeout(an_stats_update, sc, sc->an_stat_ch);
+	callout_stop(&sc->an_stat_ch);
 
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING|IFF_DRV_OACTIVE);
 

==== //depot/projects/wifi/sys/dev/an/if_anreg.h#4 (text+ko) ====

@@ -485,7 +485,7 @@
 	int			an_have_rssimap;
 	struct an_ltv_rssi_map	an_rssimap;
 #endif
-	struct callout_handle	an_stat_ch;
+	struct callout		an_stat_ch;
 	struct mtx		an_mtx;
 	device_t		an_dev;
 	struct ifmedia		an_ifmedia;


More information about the p4-projects mailing list