From owner-svn-src-head@FreeBSD.ORG Fri Apr 20 10:06:29 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8D40C106566C; Fri, 20 Apr 2012 10:06:29 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6DF1D8FC14; Fri, 20 Apr 2012 10:06:29 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q3KA6TYx034504; Fri, 20 Apr 2012 10:06:29 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q3KA6T6B034501; Fri, 20 Apr 2012 10:06:29 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <201204201006.q3KA6T6B034501@svn.freebsd.org> From: Andrew Thompson Date: Fri, 20 Apr 2012 10:06:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r234488 - head/sys/net X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 20 Apr 2012 10:06:29 -0000 Author: thompsa Date: Fri Apr 20 10:06:28 2012 New Revision: 234488 URL: http://svn.freebsd.org/changeset/base/234488 Log: Move the interface media check to a taskqueue, some interfaces (usb) sleep during SIOCGIFMEDIA and we were holding locks. Modified: head/sys/net/bridgestp.c head/sys/net/bridgestp.h Modified: head/sys/net/bridgestp.c ============================================================================== --- head/sys/net/bridgestp.c Fri Apr 20 09:55:50 2012 (r234487) +++ head/sys/net/bridgestp.c Fri Apr 20 10:06:28 2012 (r234488) @@ -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: head/sys/net/bridgestp.h ============================================================================== --- head/sys/net/bridgestp.h Fri Apr 20 09:55:50 2012 (r234487) +++ head/sys/net/bridgestp.h Fri Apr 20 10:06:28 2012 (r234488) @@ -326,6 +326,7 @@ struct bstp_port { uint8_t bp_txcount; struct task bp_statetask; struct task bp_rtagetask; + struct task bp_mediatask; }; /*