mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2025-01-03 02:02:33 +01:00
netdev: Retry IF_OPER_UP
Some drivers ignore the initial IF_OPER_UP setting that was sent during netdev_connect_ok(). Attempt to work around this by parsing New Link events. If OperState setting is still not correct in a subsequent event, retry setting OperState to IF_OPER_UP.
This commit is contained in:
parent
47ebd81393
commit
a75126af39
26
src/netdev.c
26
src/netdev.c
@ -5589,6 +5589,8 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes)
|
|||||||
char old_name[IFNAMSIZ];
|
char old_name[IFNAMSIZ];
|
||||||
uint8_t old_addr[ETH_ALEN];
|
uint8_t old_addr[ETH_ALEN];
|
||||||
struct rtattr *attr;
|
struct rtattr *attr;
|
||||||
|
uint8_t *operstate = NULL;
|
||||||
|
uint8_t *linkmode = NULL;
|
||||||
|
|
||||||
if (ifi->ifi_family == AF_BRIDGE) {
|
if (ifi->ifi_family == AF_BRIDGE) {
|
||||||
netdev_bridge_port_event(ifi, bytes, true);
|
netdev_bridge_port_event(ifi, bytes, true);
|
||||||
@ -5617,12 +5619,36 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes)
|
|||||||
|
|
||||||
memcpy(netdev->addr, RTA_DATA(attr), ETH_ALEN);
|
memcpy(netdev->addr, RTA_DATA(attr), ETH_ALEN);
|
||||||
break;
|
break;
|
||||||
|
case IFLA_OPERSTATE:
|
||||||
|
operstate = RTA_DATA(attr);
|
||||||
|
break;
|
||||||
|
case IFLA_LINKMODE:
|
||||||
|
linkmode = RTA_DATA(attr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!netdev->events_ready) /* Did we send NETDEV_WATCH_EVENT_NEW yet? */
|
if (!netdev->events_ready) /* Did we send NETDEV_WATCH_EVENT_NEW yet? */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sometimes the driver sends the Association / Connect event on the
|
||||||
|
* nl80211 interface before the driver is ready to accept IF_OPER_UP
|
||||||
|
* setting on the rtnl interface. This results in our initial
|
||||||
|
* IF_OPER_UP setting being ignored. In this case the driver will
|
||||||
|
* send a New Link event with a stale OperState. Detect this case and
|
||||||
|
* try to re-set IF_OPER_UP.
|
||||||
|
*/
|
||||||
|
if (linkmode && *linkmode == 1 &&
|
||||||
|
operstate && *operstate == IF_OPER_DORMANT &&
|
||||||
|
netdev->operational) {
|
||||||
|
l_debug("Retrying setting OperState to IF_OPER_UP");
|
||||||
|
l_rtnl_set_linkmode_and_operstate(rtnl, netdev->index,
|
||||||
|
IF_LINK_MODE_DORMANT, IF_OPER_UP,
|
||||||
|
netdev_operstate_cb,
|
||||||
|
L_UINT_TO_PTR(netdev->index), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
new_up = netdev_get_is_up(netdev);
|
new_up = netdev_get_is_up(netdev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user