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:
parent
7702d4013b
commit
2885c19ebd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234488
@ -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);
|
||||
}
|
||||
|
@ -326,6 +326,7 @@ struct bstp_port {
|
||||
uint8_t bp_txcount;
|
||||
struct task bp_statetask;
|
||||
struct task bp_rtagetask;
|
||||
struct task bp_mediatask;
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user