mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
manager: Fallback to old logic for some drivers
If we get an error during DEL_INTERFACE or NEW_INTERFACE we may be dealing with a driver that doesn't implement virtual interfaces or doesn't implement deleting the default interface. In this case fall back to using the first usable interface that we've detected on this wiphy. There's at least one full-mac driver that doesn't implement the cfg80211 .del_virtual_intf and .add_virtual_intf methods and at least one that only allows P2P interfaces to be manipulated. mac80211 drivers seem to at least implement those methods but I didn't check to see if there are driver where they'd eventually return EOPNOTSUPP.
This commit is contained in:
parent
2ea9db9cae
commit
9e079ba4fc
@ -48,6 +48,14 @@ struct wiphy_setup_state {
|
||||
struct l_timeout *setup_timeout;
|
||||
unsigned int pending_cmd_count;
|
||||
bool aborted;
|
||||
|
||||
/*
|
||||
* Data we may need if the driver does not seem to support interface
|
||||
* manipulation and we fall back to using the driver-created default
|
||||
* interface.
|
||||
*/
|
||||
bool use_default;
|
||||
struct l_genl_msg *default_if_msg;
|
||||
};
|
||||
|
||||
static struct l_queue *pending_wiphys;
|
||||
@ -61,10 +69,29 @@ static void wiphy_setup_state_free(void *data)
|
||||
if (state->setup_timeout)
|
||||
l_timeout_remove(state->setup_timeout);
|
||||
|
||||
if (state->default_if_msg)
|
||||
l_genl_msg_unref(state->default_if_msg);
|
||||
|
||||
L_WARN_ON(state->pending_cmd_count);
|
||||
l_free(state);
|
||||
}
|
||||
|
||||
static bool manager_use_default(struct wiphy_setup_state *state)
|
||||
{
|
||||
l_debug("");
|
||||
|
||||
if (!state->default_if_msg) {
|
||||
l_error("No default interface for wiphy %u",
|
||||
(unsigned int) state->id);
|
||||
wiphy_setup_state_free(state);
|
||||
return false;
|
||||
}
|
||||
|
||||
netdev_create_from_genl(state->default_if_msg);
|
||||
wiphy_setup_state_free(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void manager_new_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||
{
|
||||
struct wiphy_setup_state *state = user_data;
|
||||
@ -108,6 +135,11 @@ static void manager_create_interfaces(struct wiphy_setup_state *state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->use_default) {
|
||||
manager_use_default(state);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Current policy: we maintain one netdev per wiphy for station,
|
||||
* AP and Ad-Hoc modes, one optional p2p-device and zero or more
|
||||
@ -158,9 +190,11 @@ static void manager_del_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||
if (state->aborted)
|
||||
return;
|
||||
|
||||
if (l_genl_msg_get_error(msg) < 0)
|
||||
if (l_genl_msg_get_error(msg) < 0) {
|
||||
l_error("DEL_INTERFACE failed: %s",
|
||||
strerror(-l_genl_msg_get_error(msg)));
|
||||
state->use_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||
@ -236,6 +270,21 @@ static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||
if (!ifindex || !wdev_idx || !iftype || !ifname)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this interface is usable as our default netdev in case the
|
||||
* driver does not support interface manipulation, save the message
|
||||
* just in case.
|
||||
*/
|
||||
if ((*iftype == NL80211_IFTYPE_ADHOC ||
|
||||
*iftype == NL80211_IFTYPE_STATION ||
|
||||
*iftype == NL80211_IFTYPE_AP) &&
|
||||
ifindex && *ifindex != 0 &&
|
||||
!state->default_if_msg)
|
||||
state->default_if_msg = l_genl_msg_ref(msg);
|
||||
|
||||
if (state->use_default)
|
||||
return;
|
||||
|
||||
del_msg = l_genl_msg_new(NL80211_CMD_DEL_INTERFACE);
|
||||
l_genl_msg_append_attr(del_msg, NL80211_ATTR_IFINDEX, 4, ifindex);
|
||||
l_genl_msg_append_attr(del_msg, NL80211_ATTR_WDEV, 8, wdev_idx);
|
||||
@ -246,6 +295,7 @@ static void manager_get_interface_cb(struct l_genl_msg *msg, void *user_data)
|
||||
|
||||
if (!cmd_id) {
|
||||
l_error("Sending DEL_INTERFACE for %s failed", ifname);
|
||||
state->use_default = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user