QCA vendor command support to set band to driver
Add vendor command to pass SET setband command to the driver and read the updated channel list from driver when this notification succeeds. This allows the driver to update its internal channel lists based on setband configuration. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
06836013d3
commit
844dfeb804
9 changed files with 109 additions and 9 deletions
|
@ -328,4 +328,10 @@ enum mesh_plink_state {
|
|||
PLINK_BLOCKED,
|
||||
};
|
||||
|
||||
enum set_band {
|
||||
WPA_SETBAND_AUTO,
|
||||
WPA_SETBAND_5G,
|
||||
WPA_SETBAND_2G
|
||||
};
|
||||
|
||||
#endif /* DEFS_H */
|
||||
|
|
|
@ -155,6 +155,7 @@ enum qca_nl80211_vendor_subcmds {
|
|||
QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102,
|
||||
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
|
||||
QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
|
||||
QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
|
||||
};
|
||||
|
||||
|
||||
|
@ -182,6 +183,8 @@ enum qca_wlan_vendor_attr {
|
|||
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10,
|
||||
/* Unsigned 32-bit value */
|
||||
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
|
||||
/* Unsigned 32-bit value from enum qca_set_band. */
|
||||
QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
|
||||
/* keep last */
|
||||
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
|
||||
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
|
||||
|
@ -314,4 +317,10 @@ enum qca_iface_type {
|
|||
QCA_IFACE_TYPE_TDLS,
|
||||
};
|
||||
|
||||
enum qca_set_band {
|
||||
QCA_SETBAND_AUTO,
|
||||
QCA_SETBAND_5G,
|
||||
QCA_SETBAND_2G,
|
||||
};
|
||||
|
||||
#endif /* QCA_VENDOR_H */
|
||||
|
|
|
@ -3387,6 +3387,14 @@ struct wpa_driver_ops {
|
|||
* indicates support for such offloading (WPA_DRIVER_FLAGS_ACS_OFFLOAD).
|
||||
*/
|
||||
int (*do_acs)(void *priv, struct drv_acs_params *params);
|
||||
|
||||
/**
|
||||
* set_band - Notify driver of band selection
|
||||
* @priv: Private driver interface data
|
||||
* @band: The selected band(s)
|
||||
* Returns 0 on success, -1 on failure
|
||||
*/
|
||||
int (*set_band)(void *priv, enum set_band band);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8435,6 +8435,53 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params)
|
|||
}
|
||||
|
||||
|
||||
static int nl80211_set_band(void *priv, enum set_band band)
|
||||
{
|
||||
struct i802_bss *bss = priv;
|
||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||
struct nl_msg *msg;
|
||||
struct nlattr *data;
|
||||
int ret;
|
||||
enum qca_set_band qca_band;
|
||||
|
||||
if (!drv->setband_vendor_cmd_avail)
|
||||
return -1;
|
||||
|
||||
switch (band) {
|
||||
case WPA_SETBAND_AUTO:
|
||||
qca_band = QCA_SETBAND_AUTO;
|
||||
break;
|
||||
case WPA_SETBAND_5G:
|
||||
qca_band = QCA_SETBAND_5G;
|
||||
break;
|
||||
case WPA_SETBAND_2G:
|
||||
qca_band = QCA_SETBAND_2G;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
|
||||
QCA_NL80211_VENDOR_SUBCMD_SETBAND) ||
|
||||
!(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
|
||||
nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
nla_nest_end(msg, data);
|
||||
|
||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||
if (ret) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"nl80211: Driver setband function failed: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||
.name = "nl80211",
|
||||
.desc = "Linux nl80211/cfg80211",
|
||||
|
@ -8542,4 +8589,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
|||
.add_tx_ts = nl80211_add_ts,
|
||||
.del_tx_ts = nl80211_del_ts,
|
||||
.do_acs = wpa_driver_do_acs,
|
||||
.set_band = nl80211_set_band,
|
||||
};
|
||||
|
|
|
@ -145,6 +145,7 @@ struct wpa_driver_nl80211_data {
|
|||
unsigned int get_features_vendor_cmd_avail:1;
|
||||
unsigned int set_rekey_offload:1;
|
||||
unsigned int p2p_go_ctwindow_supported:1;
|
||||
unsigned int setband_vendor_cmd_avail:1;
|
||||
|
||||
u64 remain_on_chan_cookie;
|
||||
u64 send_action_cookie;
|
||||
|
|
|
@ -593,6 +593,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
|
|||
drv->capa.flags |=
|
||||
WPA_DRIVER_FLAGS_ACS_OFFLOAD;
|
||||
break;
|
||||
case QCA_NL80211_VENDOR_SUBCMD_SETBAND:
|
||||
drv->setband_vendor_cmd_avail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -286,6 +286,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
|
||||
{
|
||||
union wpa_event_data event;
|
||||
|
||||
if (os_strcmp(band, "AUTO") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_AUTO;
|
||||
else if (os_strcmp(band, "5G") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_5G;
|
||||
else if (os_strcmp(band, "2G") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_2G;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
|
||||
os_memset(&event, 0, sizeof(event));
|
||||
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
|
||||
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
|
||||
wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
||||
char *cmd)
|
||||
{
|
||||
|
@ -449,14 +473,7 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
|||
ret = wpas_ctrl_set_blob(wpa_s, value);
|
||||
#endif /* CONFIG_NO_CONFIG_BLOBS */
|
||||
} else if (os_strcasecmp(cmd, "setband") == 0) {
|
||||
if (os_strcmp(value, "AUTO") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_AUTO;
|
||||
else if (os_strcmp(value, "5G") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_5G;
|
||||
else if (os_strcmp(value, "2G") == 0)
|
||||
wpa_s->setband = WPA_SETBAND_2G;
|
||||
else
|
||||
ret = -1;
|
||||
ret = wpas_ctrl_set_band(wpa_s, value);
|
||||
} else {
|
||||
value[-1] = '=';
|
||||
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
|
||||
|
|
|
@ -885,4 +885,12 @@ static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
#endif /* CONFIG_MACSEC */
|
||||
|
||||
static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
|
||||
enum set_band band)
|
||||
{
|
||||
if (!wpa_s->driver->set_band)
|
||||
return -1;
|
||||
return wpa_s->driver->set_band(wpa_s->drv_priv, band);
|
||||
}
|
||||
|
||||
#endif /* DRIVER_I_H */
|
||||
|
|
|
@ -482,7 +482,7 @@ struct wpa_supplicant {
|
|||
struct wpa_ssid_value *disallow_aps_ssid;
|
||||
size_t disallow_aps_ssid_count;
|
||||
|
||||
enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband;
|
||||
enum set_band setband;
|
||||
|
||||
/* Preferred network for the next connection attempt */
|
||||
struct wpa_ssid *next_ssid;
|
||||
|
|
Loading…
Reference in a new issue