Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nl80211: enable IBSS support for channel switch announcements

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Simon Wunderlich and committed by
Johannes Berg
ee4bc9e7 9449410f

+34 -15
+34 -15
net/wireless/nl80211.c
··· 5634 5634 static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; 5635 5635 u8 radar_detect_width = 0; 5636 5636 int err; 5637 + bool need_new_beacon = false; 5637 5638 5638 5639 if (!rdev->ops->channel_switch || 5639 5640 !(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)) 5640 5641 return -EOPNOTSUPP; 5641 5642 5642 - /* may add IBSS support later */ 5643 - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 5644 - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 5643 + switch (dev->ieee80211_ptr->iftype) { 5644 + case NL80211_IFTYPE_AP: 5645 + case NL80211_IFTYPE_P2P_GO: 5646 + need_new_beacon = true; 5647 + 5648 + /* useless if AP is not running */ 5649 + if (!wdev->beacon_interval) 5650 + return -EINVAL; 5651 + break; 5652 + case NL80211_IFTYPE_ADHOC: 5653 + break; 5654 + default: 5645 5655 return -EOPNOTSUPP; 5656 + } 5646 5657 5647 5658 memset(&params, 0, sizeof(params)); 5648 5659 ··· 5662 5651 return -EINVAL; 5663 5652 5664 5653 /* only important for AP, IBSS and mesh create IEs internally */ 5665 - if (!info->attrs[NL80211_ATTR_CSA_IES]) 5666 - return -EINVAL; 5667 - 5668 - /* useless if AP is not running */ 5669 - if (!wdev->beacon_interval) 5654 + if (need_new_beacon && 5655 + (!info->attrs[NL80211_ATTR_CSA_IES] || 5656 + !info->attrs[NL80211_ATTR_CSA_C_OFF_BEACON])) 5670 5657 return -EINVAL; 5671 5658 5672 5659 params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]); 5660 + 5661 + if (!need_new_beacon) 5662 + goto skip_beacons; 5673 5663 5674 5664 err = nl80211_parse_beacon(info->attrs, &params.beacon_after); 5675 5665 if (err) ··· 5711 5699 return -EINVAL; 5712 5700 } 5713 5701 5702 + skip_beacons: 5714 5703 err = nl80211_parse_chandef(rdev, info, &params.chandef); 5715 5704 if (err) 5716 5705 return err; ··· 5719 5706 if (!cfg80211_reg_can_beacon(&rdev->wiphy, &params.chandef)) 5720 5707 return -EINVAL; 5721 5708 5722 - err = cfg80211_chandef_dfs_required(wdev->wiphy, &params.chandef); 5723 - if (err < 0) { 5724 - return err; 5725 - } else if (err) { 5726 - radar_detect_width = BIT(params.chandef.width); 5727 - params.radar_required = true; 5709 + /* DFS channels are only supported for AP/P2P GO ... for now. */ 5710 + if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || 5711 + dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) { 5712 + err = cfg80211_chandef_dfs_required(wdev->wiphy, 5713 + &params.chandef); 5714 + if (err < 0) { 5715 + return err; 5716 + } else if (err) { 5717 + radar_detect_width = BIT(params.chandef.width); 5718 + params.radar_required = true; 5719 + } 5728 5720 } 5729 5721 5730 5722 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, ··· 10758 10740 wdev_lock(wdev); 10759 10741 10760 10742 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && 10761 - wdev->iftype != NL80211_IFTYPE_P2P_GO)) 10743 + wdev->iftype != NL80211_IFTYPE_P2P_GO && 10744 + wdev->iftype != NL80211_IFTYPE_ADHOC)) 10762 10745 goto out; 10763 10746 10764 10747 wdev->channel = chandef->chan;