P2P: Inform driver of the operating channel following group formation

Upon GO Negotiation completion, if the remote peer becomes GO, send a
hint event over QCA vendor specific interface to inform the driver of
the likely operating channel of the P2P GO.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Ahmad Kholaif 2015-07-23 17:07:55 -07:00 committed by Jouni Malinen
parent 079a28f7b8
commit 7c813acf9c
6 changed files with 76 additions and 0 deletions

View file

@ -3403,6 +3403,18 @@ struct wpa_driver_ops {
* Returns 0 on success, -1 on failure * Returns 0 on success, -1 on failure
*/ */
int (*set_band)(void *priv, enum set_band band); int (*set_band)(void *priv, enum set_band band);
/**
* set_prob_oper_freq - Indicate probable P2P operating channel
* @priv: Private driver interface data
* @freq: Channel frequency in MHz
* Returns 0 on success, -1 on failure
*
* This command can be used to inform the driver of the operating
* frequency that an ongoing P2P group formation is likely to come up
* on. Local device is assuming P2P Client role.
*/
int (*set_prob_oper_freq)(void *priv, unsigned int freq);
}; };

View file

@ -8509,6 +8509,52 @@ static int nl80211_set_band(void *priv, enum set_band band)
} }
static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
int ret;
struct nlattr *params;
if (!drv->set_prob_oper_freq)
return -1;
wpa_printf(MSG_DEBUG,
"nl80211: Set P2P probable operating freq %u for ifindex %d",
freq, bss->ifindex);
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_SET_PROBABLE_OPER_CHANNEL) ||
!(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) ||
nla_put_u32(msg,
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE,
QCA_IFACE_TYPE_P2P_CLIENT) ||
nla_put_u32(msg,
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ,
freq)) {
wpa_printf(MSG_ERROR,
"%s: err in adding vendor_cmd and vendor_data",
__func__);
nlmsg_free(msg);
return -1;
}
nla_nest_end(msg, params);
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
msg = NULL;
if (ret) {
wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs",
__func__);
return ret;
}
nlmsg_free(msg);
return 0;
}
const struct wpa_driver_ops wpa_driver_nl80211_ops = { const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211", .name = "nl80211",
.desc = "Linux nl80211/cfg80211", .desc = "Linux nl80211/cfg80211",
@ -8617,4 +8663,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.del_tx_ts = nl80211_del_ts, .del_tx_ts = nl80211_del_ts,
.do_acs = wpa_driver_do_acs, .do_acs = wpa_driver_do_acs,
.set_band = nl80211_set_band, .set_band = nl80211_set_band,
.set_prob_oper_freq = nl80211_set_prob_oper_freq,
}; };

View file

@ -146,6 +146,7 @@ struct wpa_driver_nl80211_data {
unsigned int set_rekey_offload:1; unsigned int set_rekey_offload:1;
unsigned int p2p_go_ctwindow_supported:1; unsigned int p2p_go_ctwindow_supported:1;
unsigned int setband_vendor_cmd_avail:1; unsigned int setband_vendor_cmd_avail:1;
unsigned int set_prob_oper_freq:1;
u64 remain_on_chan_cookie; u64 remain_on_chan_cookie;
u64 send_action_cookie; u64 send_action_cookie;

View file

@ -589,6 +589,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
drv->get_features_vendor_cmd_avail = 1; drv->get_features_vendor_cmd_avail = 1;
break; break;
case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL:
drv->set_prob_oper_freq = 1;
break;
case QCA_NL80211_VENDOR_SUBCMD_DO_ACS: case QCA_NL80211_VENDOR_SUBCMD_DO_ACS:
drv->capa.flags |= drv->capa.flags |=
WPA_DRIVER_FLAGS_ACS_OFFLOAD; WPA_DRIVER_FLAGS_ACS_OFFLOAD;

View file

@ -893,4 +893,12 @@ static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
return wpa_s->driver->set_band(wpa_s->drv_priv, band); return wpa_s->driver->set_band(wpa_s->drv_priv, band);
} }
static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s,
unsigned int freq)
{
if (!wpa_s->driver->set_prob_oper_freq)
return 0;
return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq);
}
#endif /* DRIVER_I_H */ #endif /* DRIVER_I_H */

View file

@ -2081,6 +2081,11 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
return; return;
} }
if (!res->role_go) {
/* Inform driver of the operating channel of GO. */
wpa_drv_set_prob_oper_freq(wpa_s, res->freq);
}
if (wpa_s->p2p_go_ht40) if (wpa_s->p2p_go_ht40)
res->ht40 = 1; res->ht40 = 1;
if (wpa_s->p2p_go_vht) if (wpa_s->p2p_go_vht)