|
@@ -77,8 +77,7 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
|
|
|
* NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
|
|
|
* Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE
|
|
|
*/
|
|
|
-static u8
|
|
|
-mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
|
|
|
+u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
|
|
|
{
|
|
|
switch (chan_type) {
|
|
|
case NL80211_CHAN_NO_HT:
|
|
@@ -247,6 +246,79 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
|
|
|
wiphy_dbg(wiphy, "info: mgmt frame registered\n");
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * CFG802.11 operation handler to remain on channel.
|
|
|
+ */
|
|
|
+static int
|
|
|
+mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ struct ieee80211_channel *chan,
|
|
|
+ enum nl80211_channel_type channel_type,
|
|
|
+ unsigned int duration, u64 *cookie)
|
|
|
+{
|
|
|
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (!chan || !cookie) {
|
|
|
+ wiphy_err(wiphy, "Invalid parameter for ROC\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (priv->roc_cfg.cookie) {
|
|
|
+ wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llu\n",
|
|
|
+ priv->roc_cfg.cookie);
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
|
|
|
+ &channel_type, duration);
|
|
|
+
|
|
|
+ if (!ret) {
|
|
|
+ *cookie = random32() | 1;
|
|
|
+ priv->roc_cfg.cookie = *cookie;
|
|
|
+ priv->roc_cfg.chan = *chan;
|
|
|
+ priv->roc_cfg.chan_type = channel_type;
|
|
|
+
|
|
|
+ cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type,
|
|
|
+ duration, GFP_ATOMIC);
|
|
|
+
|
|
|
+ wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * CFG802.11 operation handler to cancel remain on channel.
|
|
|
+ */
|
|
|
+static int
|
|
|
+mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev, u64 cookie)
|
|
|
+{
|
|
|
+ struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (cookie != priv->roc_cfg.cookie)
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
|
|
|
+ &priv->roc_cfg.chan,
|
|
|
+ &priv->roc_cfg.chan_type, 0);
|
|
|
+
|
|
|
+ if (!ret) {
|
|
|
+ cfg80211_remain_on_channel_expired(wdev, cookie,
|
|
|
+ &priv->roc_cfg.chan,
|
|
|
+ priv->roc_cfg.chan_type,
|
|
|
+ GFP_ATOMIC);
|
|
|
+
|
|
|
+ memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
|
|
|
+
|
|
|
+ wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* CFG802.11 operation handler to set Tx power.
|
|
|
*/
|
|
@@ -1950,6 +2022,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
|
|
|
.del_key = mwifiex_cfg80211_del_key,
|
|
|
.mgmt_tx = mwifiex_cfg80211_mgmt_tx,
|
|
|
.mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
|
|
|
+ .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
|
|
|
+ .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
|
|
|
.set_default_key = mwifiex_cfg80211_set_default_key,
|
|
|
.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
|
|
|
.set_tx_power = mwifiex_cfg80211_set_tx_power,
|
|
@@ -1987,6 +2061,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|
|
wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
|
|
|
wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
|
|
|
wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
|
|
|
+ wiphy->max_remain_on_channel_duration = 5000;
|
|
|
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
|
|
BIT(NL80211_IFTYPE_ADHOC) |
|
|
|
BIT(NL80211_IFTYPE_AP);
|
|
@@ -2008,7 +2083,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|
|
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
|
|
|
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
|
|
|
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
|
|
|
- WIPHY_FLAG_CUSTOM_REGULATORY;
|
|
|
+ WIPHY_FLAG_CUSTOM_REGULATORY |
|
|
|
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
|
|
|
|
|
wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
|
|
|
|