Handle a reference counted flag that should be set on the parent as well */
| 1620 | |
| 1621 | /* Handle a reference counted flag that should be set on the parent as well */ |
| 1622 | static int |
| 1623 | vlan_setflag(struct ifnet *ifp, int flag, int status, |
| 1624 | int (*func)(struct ifnet *, int)) |
| 1625 | { |
| 1626 | struct ifvlan *ifv; |
| 1627 | int error; |
| 1628 | |
| 1629 | VLAN_SXLOCK_ASSERT(); |
| 1630 | |
| 1631 | ifv = ifp->if_softc; |
| 1632 | status = status ? (ifp->if_flags & flag) : 0; |
| 1633 | /* Now "status" contains the flag value or 0 */ |
| 1634 | |
| 1635 | /* |
| 1636 | * See if recorded parent's status is different from what |
| 1637 | * we want it to be. If it is, flip it. We record parent's |
| 1638 | * status in ifv_pflags so that we won't clear parent's flag |
| 1639 | * we haven't set. In fact, we don't clear or set parent's |
| 1640 | * flags directly, but get or release references to them. |
| 1641 | * That's why we can be sure that recorded flags still are |
| 1642 | * in accord with actual parent's flags. |
| 1643 | */ |
| 1644 | if (status != (ifv->ifv_pflags & flag)) { |
| 1645 | error = (*func)(PARENT(ifv), status); |
| 1646 | if (error) |
| 1647 | return (error); |
| 1648 | ifv->ifv_pflags &= ~flag; |
| 1649 | ifv->ifv_pflags |= status; |
| 1650 | } |
| 1651 | return (0); |
| 1652 | } |
| 1653 | |
| 1654 | /* |
| 1655 | * Handle IFF_* flags that require certain changes on the parent: |