|
@@ -540,6 +540,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
|
|
struct ieee80211_local *local;
|
|
|
int priv_size, i;
|
|
|
struct wiphy *wiphy;
|
|
|
+ bool use_chanctx;
|
|
|
|
|
|
if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
|
|
|
!ops->add_interface || !ops->remove_interface ||
|
|
@@ -555,6 +556,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
|
|
!!ops->unassign_vif_chanctx;
|
|
|
if (WARN_ON(i != 0 && i != 5))
|
|
|
return NULL;
|
|
|
+ use_chanctx = i == 5;
|
|
|
|
|
|
/* Ensure 32-byte alignment of our private data and hw private data.
|
|
|
* We use the wiphy priv data for both our ieee80211_local and for
|
|
@@ -606,6 +608,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
|
|
local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
|
|
|
|
|
|
local->ops = ops;
|
|
|
+ local->use_chanctx = use_chanctx;
|
|
|
|
|
|
/* set up some defaults */
|
|
|
local->hw.queues = 1;
|
|
@@ -729,6 +732,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|
|
if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ if (!local->use_chanctx) {
|
|
|
+ for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
|
|
|
+ const struct ieee80211_iface_combination *comb;
|
|
|
+
|
|
|
+ comb = &local->hw.wiphy->iface_combinations[i];
|
|
|
+
|
|
|
+ if (comb->num_different_channels > 1)
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * WDS is currently prohibited when channel contexts are used
|
|
|
+ * because there's no clear definition of which channel WDS
|
|
|
+ * type interfaces use
|
|
|
+ */
|
|
|
+ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
/* Only HW csum features are currently compatible with mac80211 */
|
|
|
feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
|
|
|
NETIF_F_HW_CSUM;
|