qtnfmac: implement cfg80211 channel_switch handler

This patch implements cfg80211 channel_switch handler enabling CSA
channel-switch procedure.

Driver performs only basic validation of the requested new channel
and then sends command to firmware. Beacon IEs are not sent since
beacon update is handled by firmware.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Signed-off-by: Avinash Patil <avinashp@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Sergey Matyukevich
2017-07-28 02:06:50 +03:00
committed by Kalle Valo
parent 34f1145b2c
commit 97883695d5
6 changed files with 210 additions and 2 deletions

View File

@@ -350,6 +350,63 @@ qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
return 0;
}
static int
qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
const struct qlink_event_freq_change *data,
u16 len)
{
struct wiphy *wiphy = priv_to_wiphy(mac);
struct cfg80211_chan_def chandef;
struct ieee80211_channel *chan;
struct qtnf_vif *vif;
int freq;
int i;
if (len < sizeof(*data)) {
pr_err("payload is too short\n");
return -EINVAL;
}
freq = le32_to_cpu(data->freq);
chan = ieee80211_get_channel(wiphy, freq);
if (!chan) {
pr_err("channel at %d MHz not found\n", freq);
return -EINVAL;
}
pr_debug("MAC%d switch to new channel %u MHz\n", mac->macid, freq);
if (mac->status & QTNF_MAC_CSA_ACTIVE) {
mac->status &= ~QTNF_MAC_CSA_ACTIVE;
if (chan->hw_value != mac->csa_chandef.chan->hw_value)
pr_warn("unexpected switch to %u during CSA to %u\n",
chan->hw_value,
mac->csa_chandef.chan->hw_value);
}
/* FIXME: need to figure out proper nl80211_channel_type value */
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
/* fall-back to minimal safe chandef description */
if (!cfg80211_chandef_valid(&chandef))
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
memcpy(&mac->chandef, &chandef, sizeof(mac->chandef));
for (i = 0; i < QTNF_MAX_INTF; i++) {
vif = &mac->iflist[i];
if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
continue;
if (vif->netdev) {
mutex_lock(&vif->wdev.mtx);
cfg80211_ch_switch_notify(vif->netdev, &chandef);
mutex_unlock(&vif->wdev.mtx);
}
}
return 0;
}
static int qtnf_event_parse(struct qtnf_wmac *mac,
const struct sk_buff *event_skb)
{
@@ -400,6 +457,10 @@ static int qtnf_event_parse(struct qtnf_wmac *mac,
ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
event_len);
break;
case QLINK_EVENT_FREQ_CHANGE:
ret = qtnf_event_handle_freq_change(mac, (const void *)event,
event_len);
break;
default:
pr_warn("unknown event type: %x\n", event_id);
break;