svn commit: r236052 - stable/9/sys/net

Andrew Thompson thompsa at FreeBSD.org
Sat May 26 07:43:17 UTC 2012


Author: thompsa
Date: Sat May 26 07:43:17 2012
New Revision: 236052
URL: http://svn.freebsd.org/changeset/base/236052

Log:
  MFC r234488
  
   Move the interface media check to a taskqueue, some interfaces (usb) sleep
   during SIOCGIFMEDIA and we were holding locks.

Modified:
  stable/9/sys/net/bridgestp.c
  stable/9/sys/net/bridgestp.h
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/amd64/include/xen/   (props changed)
  stable/9/sys/boot/   (props changed)
  stable/9/sys/boot/i386/efi/   (props changed)
  stable/9/sys/boot/ia64/efi/   (props changed)
  stable/9/sys/boot/ia64/ski/   (props changed)
  stable/9/sys/boot/powerpc/boot1.chrp/   (props changed)
  stable/9/sys/boot/powerpc/ofw/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)
  stable/9/sys/conf/   (props changed)
  stable/9/sys/contrib/dev/acpica/   (props changed)
  stable/9/sys/contrib/octeon-sdk/   (props changed)
  stable/9/sys/contrib/pf/   (props changed)
  stable/9/sys/contrib/x86emu/   (props changed)
  stable/9/sys/dev/   (props changed)
  stable/9/sys/dev/e1000/   (props changed)
  stable/9/sys/dev/ixgbe/   (props changed)
  stable/9/sys/fs/   (props changed)
  stable/9/sys/fs/ntfs/   (props changed)
  stable/9/sys/modules/   (props changed)

Modified: stable/9/sys/net/bridgestp.c
==============================================================================
--- stable/9/sys/net/bridgestp.c	Sat May 26 07:42:32 2012	(r236051)
+++ stable/9/sys/net/bridgestp.c	Sat May 26 07:43:17 2012	(r236052)
@@ -127,7 +127,7 @@ static int	bstp_rerooted(struct bstp_sta
 static uint32_t	bstp_calc_path_cost(struct bstp_port *);
 static void	bstp_notify_state(void *, int);
 static void	bstp_notify_rtage(void *, int);
-static void	bstp_ifupdstatus(struct bstp_state *, struct bstp_port *);
+static void	bstp_ifupdstatus(void *, int);
 static void	bstp_enable_port(struct bstp_state *, struct bstp_port *);
 static void	bstp_disable_port(struct bstp_state *, struct bstp_port *);
 static void	bstp_tick(void *);
@@ -1677,7 +1677,7 @@ bstp_set_autoptp(struct bstp_port *bp, i
 	if (set) {
 		bp->bp_flags |= BSTP_PORT_AUTOPTP;
 		if (bp->bp_role != BSTP_ROLE_DISABLED)
-			bstp_ifupdstatus(bs, bp);
+			taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
 	} else
 		bp->bp_flags &= ~BSTP_PORT_AUTOPTP;
 	BSTP_UNLOCK(bs);
@@ -1771,69 +1771,89 @@ bstp_linkstate(struct bstp_port *bp)
 {
 	struct bstp_state *bs = bp->bp_bs;
 
+	if (!bp->bp_active)
+		return;
+
+	bstp_ifupdstatus(bp, 0);
 	BSTP_LOCK(bs);
-	if (bp->bp_active) {
-		bstp_ifupdstatus(bs, bp);
-		bstp_update_state(bs, bp);
-	}
+	bstp_update_state(bs, bp);
 	BSTP_UNLOCK(bs);
 }
 
 static void
-bstp_ifupdstatus(struct bstp_state *bs, struct bstp_port *bp)
+bstp_ifupdstatus(void *arg, int pending)
 {
+	struct bstp_port *bp = (struct bstp_port *)arg;
+	struct bstp_state *bs = bp->bp_bs;
 	struct ifnet *ifp = bp->bp_ifp;
 	struct ifmediareq ifmr;
-	int error = 0;
+	int error, changed;
 
-	BSTP_LOCK_ASSERT(bs);
+	if (!bp->bp_active)
+		return;
 
 	bzero((char *)&ifmr, sizeof(ifmr));
 	error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr);
 
+	BSTP_LOCK(bs);
+	changed = 0;
 	if ((error == 0) && (ifp->if_flags & IFF_UP)) {
 		if (ifmr.ifm_status & IFM_ACTIVE) {
 			/* A full-duplex link is assumed to be point to point */
 			if (bp->bp_flags & BSTP_PORT_AUTOPTP) {
-				bp->bp_ptp_link =
-				    ifmr.ifm_active & IFM_FDX ? 1 : 0;
+				int fdx;
+
+				fdx = ifmr.ifm_active & IFM_FDX ? 1 : 0;
+				if (bp->bp_ptp_link ^ fdx) {
+					bp->bp_ptp_link = fdx;
+					changed = 1;
+				}
 			}
 
 			/* Calc the cost if the link was down previously */
 			if (bp->bp_flags & BSTP_PORT_PNDCOST) {
-				bp->bp_path_cost = bstp_calc_path_cost(bp);
+				uint32_t cost;
+
+				cost = bstp_calc_path_cost(bp);
+				if (bp->bp_path_cost != cost) {
+					bp->bp_path_cost = cost;
+					changed = 1;
+				}
 				bp->bp_flags &= ~BSTP_PORT_PNDCOST;
 			}
 
-			if (bp->bp_role == BSTP_ROLE_DISABLED)
+			if (bp->bp_role == BSTP_ROLE_DISABLED) {
 				bstp_enable_port(bs, bp);
+				changed = 1;
+			}
 		} else {
 			if (bp->bp_role != BSTP_ROLE_DISABLED) {
 				bstp_disable_port(bs, bp);
+				changed = 1;
 				if ((bp->bp_flags & BSTP_PORT_ADMEDGE) &&
 				    bp->bp_protover == BSTP_PROTO_RSTP)
 					bp->bp_operedge = 1;
 			}
 		}
-		return;
-	}
-
-	if (bp->bp_infois != BSTP_INFO_DISABLED)
+	} else if (bp->bp_infois != BSTP_INFO_DISABLED) {
 		bstp_disable_port(bs, bp);
+		changed = 1;
+	}
+	if (changed)
+		bstp_assign_roles(bs);
+	BSTP_UNLOCK(bs);
 }
 
 static void
 bstp_enable_port(struct bstp_state *bs, struct bstp_port *bp)
 {
 	bp->bp_infois = BSTP_INFO_AGED;
-	bstp_assign_roles(bs);
 }
 
 static void
 bstp_disable_port(struct bstp_state *bs, struct bstp_port *bp)
 {
 	bp->bp_infois = BSTP_INFO_DISABLED;
-	bstp_assign_roles(bs);
 }
 
 static void
@@ -1853,7 +1873,7 @@ bstp_tick(void *arg)
 	if (bstp_timer_dectest(&bs->bs_link_timer)) {
 		LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
 			if (!(bp->bp_ifp->if_capabilities & IFCAP_LINKSTATE))
-				bstp_ifupdstatus(bs, bp);
+				taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
 		}
 		bstp_timer_start(&bs->bs_link_timer, BSTP_LINK_TIMER);
 	}
@@ -2063,7 +2083,7 @@ bstp_reinit(struct bstp_state *bs)
 	LIST_FOREACH(bp, &bs->bs_bplist, bp_next) {
 		bp->bp_port_id = (bp->bp_priority << 8) |
 		    (bp->bp_ifp->if_index  & 0xfff);
-		bstp_ifupdstatus(bs, bp);
+		taskqueue_enqueue(taskqueue_swi, &bp->bp_mediatask);
 	}
 
 	bstp_assign_roles(bs);
@@ -2184,6 +2204,7 @@ bstp_create(struct bstp_state *bs, struc
 	bp->bp_priority = BSTP_DEFAULT_PORT_PRIORITY;
 	TASK_INIT(&bp->bp_statetask, 0, bstp_notify_state, bp);
 	TASK_INIT(&bp->bp_rtagetask, 0, bstp_notify_rtage, bp);
+	TASK_INIT(&bp->bp_mediatask, 0, bstp_ifupdstatus, bp);
 
 	/* Init state */
 	bp->bp_infois = BSTP_INFO_DISABLED;
@@ -2247,4 +2268,5 @@ bstp_destroy(struct bstp_port *bp)
 	KASSERT(bp->bp_active == 0, ("port is still attached"));
 	taskqueue_drain(taskqueue_swi, &bp->bp_statetask);
 	taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask);
+	taskqueue_drain(taskqueue_swi, &bp->bp_mediatask);
 }

Modified: stable/9/sys/net/bridgestp.h
==============================================================================
--- stable/9/sys/net/bridgestp.h	Sat May 26 07:42:32 2012	(r236051)
+++ stable/9/sys/net/bridgestp.h	Sat May 26 07:43:17 2012	(r236052)
@@ -326,6 +326,7 @@ struct bstp_port {
 	uint8_t			bp_txcount;
 	struct task		bp_statetask;
 	struct task		bp_rtagetask;
+	struct task		bp_mediatask;
 };
 
 /*


More information about the svn-src-stable-9 mailing list