aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c105
1 files changed, 77 insertions, 28 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index c80c4490351c..fd8345c20051 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -93,23 +93,21 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
93 ieee80211_configure_filter(local); 93 ieee80211_configure_filter(local);
94} 94}
95 95
96int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 96static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local)
97{ 97{
98 struct ieee80211_channel *chan; 98 struct ieee80211_channel *chan;
99 int ret = 0; 99 u32 changed = 0;
100 int power; 100 int power;
101 enum nl80211_channel_type channel_type; 101 enum nl80211_channel_type channel_type;
102 u32 offchannel_flag; 102 u32 offchannel_flag;
103 103
104 might_sleep();
105
106 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 104 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
107 if (local->scan_channel) { 105 if (local->scan_channel) {
108 chan = local->scan_channel; 106 chan = local->scan_channel;
109 /* If scanning on oper channel, use whatever channel-type 107 /* If scanning on oper channel, use whatever channel-type
110 * is currently in use. 108 * is currently in use.
111 */ 109 */
112 if (chan == local->oper_channel) 110 if (chan == local->_oper_channel)
113 channel_type = local->_oper_channel_type; 111 channel_type = local->_oper_channel_type;
114 else 112 else
115 channel_type = NL80211_CHAN_NO_HT; 113 channel_type = NL80211_CHAN_NO_HT;
@@ -117,11 +115,11 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
117 chan = local->tmp_channel; 115 chan = local->tmp_channel;
118 channel_type = local->tmp_channel_type; 116 channel_type = local->tmp_channel_type;
119 } else { 117 } else {
120 chan = local->oper_channel; 118 chan = local->_oper_channel;
121 channel_type = local->_oper_channel_type; 119 channel_type = local->_oper_channel_type;
122 } 120 }
123 121
124 if (chan != local->oper_channel || 122 if (chan != local->_oper_channel ||
125 channel_type != local->_oper_channel_type) 123 channel_type != local->_oper_channel_type)
126 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 124 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
127 else 125 else
@@ -164,6 +162,21 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
164 local->hw.conf.power_level = power; 162 local->hw.conf.power_level = power;
165 } 163 }
166 164
165 return changed;
166}
167
168int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
169{
170 int ret = 0;
171
172 might_sleep();
173
174 if (!local->use_chanctx)
175 changed |= ieee80211_hw_conf_chan(local);
176 else
177 changed &= ~(IEEE80211_CONF_CHANGE_CHANNEL |
178 IEEE80211_CONF_CHANGE_POWER);
179
167 if (changed && local->open_count) { 180 if (changed && local->open_count) {
168 ret = drv_config(local, changed); 181 ret = drv_config(local, changed);
169 /* 182 /*
@@ -359,14 +372,6 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
359} 372}
360EXPORT_SYMBOL(ieee80211_restart_hw); 373EXPORT_SYMBOL(ieee80211_restart_hw);
361 374
362static void ieee80211_recalc_smps_work(struct work_struct *work)
363{
364 struct ieee80211_local *local =
365 container_of(work, struct ieee80211_local, recalc_smps);
366
367 ieee80211_recalc_smps(local);
368}
369
370#ifdef CONFIG_INET 375#ifdef CONFIG_INET
371static int ieee80211_ifa_changed(struct notifier_block *nb, 376static int ieee80211_ifa_changed(struct notifier_block *nb,
372 unsigned long data, void *arg) 377 unsigned long data, void *arg)
@@ -540,6 +545,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
540 struct ieee80211_local *local; 545 struct ieee80211_local *local;
541 int priv_size, i; 546 int priv_size, i;
542 struct wiphy *wiphy; 547 struct wiphy *wiphy;
548 bool use_chanctx;
543 549
544 if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config || 550 if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config ||
545 !ops->add_interface || !ops->remove_interface || 551 !ops->add_interface || !ops->remove_interface ||
@@ -549,6 +555,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
549 if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) 555 if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
550 return NULL; 556 return NULL;
551 557
558 /* check all or no channel context operations exist */
559 i = !!ops->add_chanctx + !!ops->remove_chanctx +
560 !!ops->change_chanctx + !!ops->assign_vif_chanctx +
561 !!ops->unassign_vif_chanctx;
562 if (WARN_ON(i != 0 && i != 5))
563 return NULL;
564 use_chanctx = i == 5;
565
552 /* Ensure 32-byte alignment of our private data and hw private data. 566 /* Ensure 32-byte alignment of our private data and hw private data.
553 * We use the wiphy priv data for both our ieee80211_local and for 567 * We use the wiphy priv data for both our ieee80211_local and for
554 * the driver's private data 568 * the driver's private data
@@ -584,8 +598,14 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
584 if (ops->remain_on_channel) 598 if (ops->remain_on_channel)
585 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 599 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
586 600
587 wiphy->features = NL80211_FEATURE_SK_TX_STATUS | 601 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
588 NL80211_FEATURE_HT_IBSS; 602 NL80211_FEATURE_SAE |
603 NL80211_FEATURE_HT_IBSS;
604
605 if (!ops->hw_scan)
606 wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
607 NL80211_FEATURE_AP_SCAN;
608
589 609
590 if (!ops->set_key) 610 if (!ops->set_key)
591 wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 611 wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
@@ -599,6 +619,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
599 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); 619 local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
600 620
601 local->ops = ops; 621 local->ops = ops;
622 local->use_chanctx = use_chanctx;
602 623
603 /* set up some defaults */ 624 /* set up some defaults */
604 local->hw.queues = 1; 625 local->hw.queues = 1;
@@ -626,6 +647,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
626 spin_lock_init(&local->filter_lock); 647 spin_lock_init(&local->filter_lock);
627 spin_lock_init(&local->queue_stop_reason_lock); 648 spin_lock_init(&local->queue_stop_reason_lock);
628 649
650 INIT_LIST_HEAD(&local->chanctx_list);
651 mutex_init(&local->chanctx_mtx);
652
629 /* 653 /*
630 * The rx_skb_queue is only accessed from tasklets, 654 * The rx_skb_queue is only accessed from tasklets,
631 * but other SKB queues are used from within IRQ 655 * but other SKB queues are used from within IRQ
@@ -641,7 +665,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
641 INIT_WORK(&local->restart_work, ieee80211_restart_work); 665 INIT_WORK(&local->restart_work, ieee80211_restart_work);
642 666
643 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); 667 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
644 INIT_WORK(&local->recalc_smps, ieee80211_recalc_smps_work);
645 local->smps_mode = IEEE80211_SMPS_OFF; 668 local->smps_mode = IEEE80211_SMPS_OFF;
646 669
647 INIT_WORK(&local->dynamic_ps_enable_work, 670 INIT_WORK(&local->dynamic_ps_enable_work,
@@ -719,6 +742,25 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
719 if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) 742 if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan)
720 return -EINVAL; 743 return -EINVAL;
721 744
745 if (!local->use_chanctx) {
746 for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
747 const struct ieee80211_iface_combination *comb;
748
749 comb = &local->hw.wiphy->iface_combinations[i];
750
751 if (comb->num_different_channels > 1)
752 return -EINVAL;
753 }
754 } else {
755 /*
756 * WDS is currently prohibited when channel contexts are used
757 * because there's no clear definition of which channel WDS
758 * type interfaces use
759 */
760 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
761 return -EINVAL;
762 }
763
722 /* Only HW csum features are currently compatible with mac80211 */ 764 /* Only HW csum features are currently compatible with mac80211 */
723 feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 765 feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
724 NETIF_F_HW_CSUM; 766 NETIF_F_HW_CSUM;
@@ -728,6 +770,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
728 if (hw->max_report_rates == 0) 770 if (hw->max_report_rates == 0)
729 hw->max_report_rates = hw->max_rates; 771 hw->max_report_rates = hw->max_rates;
730 772
773 local->rx_chains = 1;
774
731 /* 775 /*
732 * generic code guarantees at least one band, 776 * generic code guarantees at least one band,
733 * set this very early because much code assumes 777 * set this very early because much code assumes
@@ -743,18 +787,29 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
743 sband = local->hw.wiphy->bands[band]; 787 sband = local->hw.wiphy->bands[band];
744 if (!sband) 788 if (!sband)
745 continue; 789 continue;
746 if (!local->oper_channel) { 790 if (!local->use_chanctx && !local->_oper_channel) {
747 /* init channel we're on */ 791 /* init channel we're on */
748 local->hw.conf.channel = 792 local->hw.conf.channel =
749 local->oper_channel = &sband->channels[0]; 793 local->_oper_channel = &sband->channels[0];
750 local->hw.conf.channel_type = NL80211_CHAN_NO_HT; 794 local->hw.conf.channel_type = NL80211_CHAN_NO_HT;
751 } 795 }
796 if (!local->monitor_channel) {
797 local->monitor_channel = &sband->channels[0];
798 local->monitor_channel_type = NL80211_CHAN_NO_HT;
799 }
752 channels += sband->n_channels; 800 channels += sband->n_channels;
753 801
754 if (max_bitrates < sband->n_bitrates) 802 if (max_bitrates < sband->n_bitrates)
755 max_bitrates = sband->n_bitrates; 803 max_bitrates = sband->n_bitrates;
756 supp_ht = supp_ht || sband->ht_cap.ht_supported; 804 supp_ht = supp_ht || sband->ht_cap.ht_supported;
757 supp_vht = supp_vht || sband->vht_cap.vht_supported; 805 supp_vht = supp_vht || sband->vht_cap.vht_supported;
806
807 if (sband->ht_cap.ht_supported)
808 local->rx_chains =
809 max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
810 local->rx_chains);
811
812 /* TODO: consider VHT for RX chains, hopefully it's the same */
758 } 813 }
759 814
760 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + 815 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -778,19 +833,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
778 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 833 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
779 hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); 834 hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
780 835
781 /* 836 /* mac80211 doesn't support more than one IBSS interface right now */
782 * mac80211 doesn't support more than 1 channel, and also not more
783 * than one IBSS interface
784 */
785 for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { 837 for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
786 const struct ieee80211_iface_combination *c; 838 const struct ieee80211_iface_combination *c;
787 int j; 839 int j;
788 840
789 c = &hw->wiphy->iface_combinations[i]; 841 c = &hw->wiphy->iface_combinations[i];
790 842
791 if (c->num_different_channels > 1)
792 return -EINVAL;
793
794 for (j = 0; j < c->n_limits; j++) 843 for (j = 0; j < c->n_limits; j++)
795 if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && 844 if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
796 c->limits[j].max > 1) 845 c->limits[j].max > 1)
@@ -832,7 +881,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
832 881
833 if (supp_vht) 882 if (supp_vht)
834 local->scan_ies_len += 883 local->scan_ies_len +=
835 2 + sizeof(struct ieee80211_vht_capabilities); 884 2 + sizeof(struct ieee80211_vht_cap);
836 885
837 if (!local->ops->hw_scan) { 886 if (!local->ops->hw_scan) {
838 /* For hw_scan, driver needs to set these up. */ 887 /* For hw_scan, driver needs to set these up. */