cfg80211: add flags for off-channel capabilities
authorJohannes Berg <johannes.berg@intel.com>
Fri, 18 Nov 2011 14:33:48 +0000 (15:33 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 21 Nov 2011 21:20:49 +0000 (16:20 -0500)
Currently mac80211 implements these for all devices,
but given restrictions of some devices that isn't
really true, so prepare for being able to remove the
capability for some mac80211 devices.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath6kl/init.c
include/net/cfg80211.h
net/mac80211/main.c
net/wireless/nl80211.c

index 57529acb9144ace752020f0cd75f16fc8d663dd2..30050af9d4c67a4bb1a774e040ea045d5e3c1d7f 100644 (file)
@@ -1602,7 +1602,8 @@ int ath6kl_core_init(struct ath6kl *ar)
                ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER;
 
        ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
-                           WIPHY_FLAG_HAVE_AP_SME;
+                           WIPHY_FLAG_HAVE_AP_SME |
+                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 
        set_bit(FIRST_BOOT, &ar->flag);
 
index 8d7ba0961d3e694115f60b7c17dbaadc396b93b0..26890045dbd68e5adbc3e26cf8175a97db522ade 100644 (file)
@@ -1700,6 +1700,8 @@ struct cfg80211_ops {
  *     cfg80211_report_obss_beacon().
  * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
  *     responds to probe-requests in hardware.
+ * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
+ * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
  */
 enum wiphy_flags {
        WIPHY_FLAG_CUSTOM_REGULATORY            = BIT(0),
@@ -1721,6 +1723,8 @@ enum wiphy_flags {
        WIPHY_FLAG_HAVE_AP_SME                  = BIT(17),
        WIPHY_FLAG_REPORTS_OBSS                 = BIT(18),
        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD        = BIT(19),
+       WIPHY_FLAG_OFFCHAN_TX                   = BIT(20),
+       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL        = BIT(21),
 };
 
 /**
index 3df4482bb1d964e1a9d5ddc88664fd6d9b111477..f0106d331938028882a362773fed12f4c7f01355 100644 (file)
@@ -594,7 +594,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
        wiphy->flags |= WIPHY_FLAG_NETNS_OK |
                        WIPHY_FLAG_4ADDR_AP |
                        WIPHY_FLAG_4ADDR_STATION |
-                       WIPHY_FLAG_REPORTS_OBSS;
+                       WIPHY_FLAG_REPORTS_OBSS |
+                       WIPHY_FLAG_OFFCHAN_TX |
+                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 
        wiphy->features = NL80211_FEATURE_SK_TX_STATUS;
 
index ae8ea3827acdc4414337efda769e5e6f3de2909d..9755b3f04dd74a40812287060e6b7b1057b8dcd7 100644 (file)
@@ -882,7 +882,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
        CMD(set_pmksa, SET_PMKSA);
        CMD(del_pmksa, DEL_PMKSA);
        CMD(flush_pmksa, FLUSH_PMKSA);
-       CMD(remain_on_channel, REMAIN_ON_CHANNEL);
+       if (dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
+               CMD(remain_on_channel, REMAIN_ON_CHANNEL);
        CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
        CMD(mgmt_tx, FRAME);
        CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
@@ -922,11 +923,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
        nla_nest_end(msg, nl_cmds);
 
-       if (dev->ops->remain_on_channel)
+       if (dev->ops->remain_on_channel &&
+           dev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL)
                NLA_PUT_U32(msg, NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION,
                            dev->wiphy.max_remain_on_channel_duration);
 
-       if (dev->ops->mgmt_tx_cancel_wait)
+       if (dev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX)
                NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
 
        if (mgmt_stypes) {
@@ -5127,7 +5129,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
            duration > rdev->wiphy.max_remain_on_channel_duration)
                return -EINVAL;
 
-       if (!rdev->ops->remain_on_channel)
+       if (!rdev->ops->remain_on_channel ||
+           !(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL))
                return -EOPNOTSUPP;
 
        if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -5340,7 +5343,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                return -EOPNOTSUPP;
 
        if (info->attrs[NL80211_ATTR_DURATION]) {
-               if (!rdev->ops->mgmt_tx_cancel_wait)
+               if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                        return -EINVAL;
                wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
        }
@@ -5358,6 +5361,9 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
 
        offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
 
+       if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
+               return -EINVAL;
+
        no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
        freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);