1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

Move the interface media check to a taskqueue, some interfaces (usb) sleep

during SIOCGIFMEDIA and we were holding locks.
This commit is contained in:
Andrew Thompson 2012-04-20 10:06:28 +00:00
parent 7702d4013b
commit 2885c19ebd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234488
2 changed files with 44 additions and 21 deletions

View File

@ -127,7 +127,7 @@ static int bstp_rerooted(struct bstp_state *, struct bstp_port *);
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, int set)
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, struct bstp_port *bp, struct ifnet *ifp)
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);
}

View File

@ -326,6 +326,7 @@ struct bstp_port {
uint8_t bp_txcount;
struct task bp_statetask;
struct task bp_rtagetask;
struct task bp_mediatask;
};
/*