diff mbox series

[13/13] wifi: ath12k: Advertise multi hardware iface combination

Message ID 20240328072916.1164195-14-quic_periyasa@quicinc.com (mailing list archive)
State RFC
Delegated to: Kalle Valo
Headers show
Series wifi: Add multi physical hardware iface combination support | expand

Commit Message

Karthikeyan Periyasamy March 28, 2024, 7:29 a.m. UTC
From: Harshitha Prem <quic_hprem@quicinc.com>

The prerequisite for MLO support in cfg80211/mac80211 requires that all
the links participating in MLO belong to the same wiphy/ieee80211_hw.
The driver needs to group multiple discrete hardware each acting as a
link in MLO, under one wiphy. Consequently, the driver advertises multi
hardware interface combination capabilities with a list of supported
frequencies.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00188-QCAHKSWPL_SILICONZ-1

Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Co-developed-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
---
 drivers/net/wireless/ath/ath12k/mac.c | 128 +++++++++++++++++++++++++-
 1 file changed, 127 insertions(+), 1 deletion(-)

Comments

kernel test robot March 28, 2024, 11:42 p.m. UTC | #1
Hi Karthikeyan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on d69aef8084cc72df7b0f2583096d9b037c647ec8]

url:    https://github.com/intel-lab-lkp/linux/commits/Karthikeyan-Periyasamy/wifi-cfg80211-Add-provision-to-advertise-multiple-radio-in-one-wiphy/20240328-153303
base:   d69aef8084cc72df7b0f2583096d9b037c647ec8
patch link:    https://lore.kernel.org/r/20240328072916.1164195-14-quic_periyasa%40quicinc.com
patch subject: [PATCH 13/13] wifi: ath12k: Advertise multi hardware iface combination
config: arm64-allyesconfig (https://download.01.org/0day-ci/archive/20240329/202403290724.p8vSV474-lkp@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 79ba323bdd0843275019e16b6e9b35133677c514)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240329/202403290724.p8vSV474-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202403290724.p8vSV474-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/net/wireless/ath/ath12k/mac.c:7:
   In file included from include/net/mac80211.h:18:
   In file included from include/linux/if_ether.h:19:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:8:
   In file included from include/linux/cacheflush.h:5:
   In file included from arch/arm64/include/asm/cacheflush.h:11:
   In file included from include/linux/kgdb.h:19:
   In file included from include/linux/kprobes.h:28:
   In file included from include/linux/ftrace.h:13:
   In file included from include/linux/kallsyms.h:13:
   In file included from include/linux/mm.h:2188:
   include/linux/vmstat.h:508:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     508 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     509 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:515:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     515 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     516 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:522:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     522 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:527:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     527 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     528 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:536:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     536 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     537 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
>> drivers/net/wireless/ath/ath12k/mac.c:7795:11: warning: variable 'band' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
    7795 |         else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
         |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    7796 |                  ar->supports_6ghz)
         |                  ~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/ath12k/mac.c:7799:44: note: uninitialized use occurs here
    7799 |         chans = kzalloc(struct_size(chans, chans, band->n_channels),
         |                                                   ^~~~
   include/linux/overflow.h:294:53: note: expanded from macro 'struct_size'
     294 |                 size_add(sizeof(*(p)), flex_array_size(p, member, count)))
         |                                                                   ^~~~~
   include/linux/overflow.h:278:12: note: expanded from macro 'flex_array_size'
     278 |                 size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member)))
         |                          ^~~~~
   drivers/net/wireless/ath/ath12k/mac.c:7795:7: note: remove the 'if' if its condition is always true
    7795 |         else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
         |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    7796 |                  ar->supports_6ghz)
         |                  ~~~~~~~~~~~~~~~~~~
    7797 |                 band = &ar->mac.sbands[NL80211_BAND_6GHZ];
>> drivers/net/wireless/ath/ath12k/mac.c:7795:11: warning: variable 'band' is used uninitialized whenever '&&' condition is false [-Wsometimes-uninitialized]
    7795 |         else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
         |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/ath12k/mac.c:7799:44: note: uninitialized use occurs here
    7799 |         chans = kzalloc(struct_size(chans, chans, band->n_channels),
         |                                                   ^~~~
   include/linux/overflow.h:294:53: note: expanded from macro 'struct_size'
     294 |                 size_add(sizeof(*(p)), flex_array_size(p, member, count)))
         |                                                                   ^~~~~
   include/linux/overflow.h:278:12: note: expanded from macro 'flex_array_size'
     278 |                 size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member)))
         |                          ^~~~~
   drivers/net/wireless/ath/ath12k/mac.c:7795:11: note: remove the '&&' if its condition is always true
    7795 |         else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
         |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/ath12k/mac.c:7788:39: note: initialize the variable 'band' to silence this warning
    7788 |         struct ieee80211_supported_band *band;
         |                                              ^
         |                                               = NULL
   7 warnings generated.


vim +7795 drivers/net/wireless/ath/ath12k/mac.c

  7783	
  7784	static
  7785	struct ieee80211_chans_per_hw *ath12k_setup_per_hw_chan(struct ath12k *ar)
  7786	{
  7787		struct ieee80211_chans_per_hw *chans;
  7788		struct ieee80211_supported_band *band;
  7789	
  7790		if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
  7791			band = &ar->mac.sbands[NL80211_BAND_2GHZ];
  7792		else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
  7793			 !ar->supports_6ghz)
  7794			band = &ar->mac.sbands[NL80211_BAND_5GHZ];
> 7795		else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
  7796			 ar->supports_6ghz)
  7797			band = &ar->mac.sbands[NL80211_BAND_6GHZ];
  7798	
  7799		chans = kzalloc(struct_size(chans, chans, band->n_channels),
  7800				GFP_KERNEL);
  7801		if (!chans)
  7802			return NULL;
  7803	
  7804		memcpy(chans->chans, band->channels,
  7805		       sizeof(*band->channels) * band->n_channels);
  7806		chans->n_chans = band->n_channels;
  7807	
  7808		return chans;
  7809	}
  7810
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 44c8bf6eb6ae..3d0cae8d883a 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -7781,10 +7781,126 @@  static bool ath12k_mac_is_iface_mode_enable(struct ath12k_hw *ah,
 	return is_enable;
 }
 
+static
+struct ieee80211_chans_per_hw *ath12k_setup_per_hw_chan(struct ath12k *ar)
+{
+	struct ieee80211_chans_per_hw *chans;
+	struct ieee80211_supported_band *band;
+
+	if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP)
+		band = &ar->mac.sbands[NL80211_BAND_2GHZ];
+	else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
+		 !ar->supports_6ghz)
+		band = &ar->mac.sbands[NL80211_BAND_5GHZ];
+	else if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP &&
+		 ar->supports_6ghz)
+		band = &ar->mac.sbands[NL80211_BAND_6GHZ];
+
+	chans = kzalloc(struct_size(chans, chans, band->n_channels),
+			GFP_KERNEL);
+	if (!chans)
+		return NULL;
+
+	memcpy(chans->chans, band->channels,
+	       sizeof(*band->channels) * band->n_channels);
+	chans->n_chans = band->n_channels;
+
+	return chans;
+}
+
+static void ath12k_mac_cleanup_hw_channels(struct ath12k_hw *ah)
+{
+	struct wiphy *wiphy = ah->hw->wiphy;
+	int i;
+
+	for (i = 0; i < ah->num_radio; i++)
+		kfree(wiphy->hw_chans[i]);
+
+	kfree(wiphy->hw_chans);
+}
+
+static int
+ath12k_mac_setup_hw_channels(struct ath12k_hw *ah)
+{
+	struct wiphy *wiphy = ah->hw->wiphy;
+	int i, ret;
+
+	wiphy->hw_chans = kcalloc(ah->num_radio, sizeof(*wiphy->hw_chans),
+				  GFP_KERNEL);
+	if (!wiphy->hw_chans)
+		return -ENOMEM;
+
+	for (i = 0; i < ah->num_radio; i++) {
+		wiphy->hw_chans[i] = ath12k_setup_per_hw_chan(&ah->radio[i]);
+		if (!wiphy->hw_chans[i]) {
+			ret = -ENOMEM;
+			goto cleanup_hw_chan;
+		}
+	}
+
+	wiphy->num_hw = ah->num_radio;
+
+	return 0;
+
+cleanup_hw_chan:
+	for (i = i - 1; i >= 0; i--)
+		kfree(wiphy->hw_chans[i]);
+
+	kfree(wiphy->hw_chans);
+
+	return ret;
+}
+
+static void
+ath12k_mac_cleanup_per_hw_iface_comb(struct ath12k_hw *ah)
+{
+	struct wiphy *wiphy = ah->hw->wiphy;
+
+	ath12k_mac_cleanup_hw_channels(ah);
+
+	kfree(wiphy->iface_combinations[0].iface_hw_list);
+}
+
+static int
+ath12k_mac_setup_per_hw_iface_comb(struct ath12k_hw *ah,
+				   struct ieee80211_iface_combination *comb)
+{
+	struct ieee80211_iface_per_hw *iface_hw;
+	struct ieee80211_hw *hw = ah->hw;
+	int i, ret;
+
+	ret = ath12k_mac_setup_hw_channels(ah);
+	if (ret)
+		return ret;
+
+	iface_hw  = kcalloc(ah->num_radio, sizeof(*iface_hw), GFP_KERNEL);
+	if (!iface_hw) {
+		ath12k_mac_cleanup_hw_channels(ah);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ah->num_radio; i++) {
+		iface_hw[i].hw_chans_idx = i;
+		iface_hw[i].num_different_channels =
+					comb->num_different_channels;
+		iface_hw[i].max_interfaces = comb->max_interfaces;
+		iface_hw[i].limits = comb->limits;
+		iface_hw[i].n_limits = comb->n_limits;
+	}
+
+	comb->iface_hw_list = iface_hw;
+	comb->n_hw_list = hw->wiphy->num_hw;
+
+	return 0;
+}
+
 static void ath12k_mac_cleanup_iface_combinations(struct ath12k_hw *ah)
 {
 	struct wiphy *wiphy = ah->hw->wiphy;
 
+	if (ah->num_radio > 1)
+		ath12k_mac_cleanup_per_hw_iface_comb(ah);
+
 	kfree(wiphy->iface_combinations[0].limits);
 	kfree(wiphy->iface_combinations);
 }
@@ -7794,7 +7910,7 @@  static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 	struct wiphy *wiphy = ah->hw->wiphy;
 	struct ieee80211_iface_combination *combinations;
 	struct ieee80211_iface_limit *limits;
-	int n_limits, max_interfaces;
+	int n_limits, max_interfaces, ret;
 	bool ap, mesh, p2p;
 
 	ap = ath12k_mac_is_iface_mode_enable(ah, NL80211_IFTYPE_AP);
@@ -7857,6 +7973,16 @@  static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 						BIT(NL80211_CHAN_WIDTH_40) |
 						BIT(NL80211_CHAN_WIDTH_80);
 
+	if (ah->num_radio > 1) {
+		ret = ath12k_mac_setup_per_hw_iface_comb(ah, combinations);
+		if (ret) {
+			kfree(limits);
+			kfree(combinations);
+
+			return ret;
+		}
+	}
+
 	wiphy->iface_combinations = combinations;
 	wiphy->n_iface_combinations = 1;