ソースを参照

qcacld-3.0: send nl80211_chan_width instead of bw value

Currently, host sends bw value to upper layer in response
of GET_USABLE_CHAN command. but upper layer requires bw
value in form of nl80211_chan_width enum and considering
bw value as invalid and resulting into 0 bw.

Fix is to convert bw value to nl80211_chan_width enum
and send to upper layer.

Change-Id: I6ae523c35561120c28b08f3aa9782bb749337c8c
CRs-Fixed: 2957062
sheenam monga 3 年 前
コミット
26e8085d7e
1 ファイル変更107 行追加26 行削除
  1. 107 26
      core/hdd/src/wlan_hdd_cfg80211.c

+ 107 - 26
core/hdd/src/wlan_hdd_cfg80211.c

@@ -169,7 +169,6 @@
 #include "wlan_hdd_bootup_marker.h"
 #include "wlan_hdd_cm_api.h"
 #include "wlan_roam_debug.h"
-
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
 
@@ -15283,6 +15282,32 @@ get_usable_channel_policy[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1] = {
 };
 
 #ifdef WLAN_FEATURE_GET_USABLE_CHAN_LIST
+static enum nl80211_chan_width
+hdd_convert_phy_bw_to_nl_bw(enum phy_ch_width bw)
+{
+	switch (bw) {
+	case CH_WIDTH_20MHZ:
+		return NL80211_CHAN_WIDTH_20;
+	case CH_WIDTH_40MHZ:
+		return NL80211_CHAN_WIDTH_40;
+	case CH_WIDTH_160MHZ:
+		return NL80211_CHAN_WIDTH_160;
+	case CH_WIDTH_80MHZ:
+		return NL80211_CHAN_WIDTH_80;
+	case CH_WIDTH_80P80MHZ:
+		return NL80211_CHAN_WIDTH_80P80;
+	case CH_WIDTH_5MHZ:
+		return NL80211_CHAN_WIDTH_5;
+	case CH_WIDTH_10MHZ:
+		return NL80211_CHAN_WIDTH_10;
+	case CH_WIDTH_INVALID:
+	case CH_WIDTH_MAX:
+		return NL80211_CHAN_WIDTH_20;
+	}
+
+	return NL80211_CHAN_WIDTH_20;
+}
+
 /**
  * hdd_fill_usable_channels_data() - Fill the data requested by userspace
  * @skb: SK buffer
@@ -15300,8 +15325,8 @@ hdd_fill_usable_channels_data(struct sk_buff *skb, struct nlattr **tb,
 			      struct get_usable_chan_res_params *res_msg,
 			      int count)
 {
-	struct nlattr *config;
-	uint8_t i = 0;
+	struct nlattr *config, *chan_params;
+	uint8_t i, bw, j = 0;
 
 	config = nla_nest_start(skb,
 				QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO);
@@ -15312,16 +15337,31 @@ hdd_fill_usable_channels_data(struct sk_buff *skb, struct nlattr **tb,
 	for (i = 0; i < count ; i++) {
 		if (!res_msg[i].freq)
 			continue;
-		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ,
-			    res_msg[i].freq);
-		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ,
-			    res_msg[i].seg0_freq);
-		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ,
-			    res_msg[i].seg1_freq);
-		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH,
-			    res_msg[i].bw);
-		nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK,
-			    res_msg[i].iface_mode_mask);
+		chan_params = nla_nest_start(skb, j);
+		if (!chan_params)
+			return -EINVAL;
+		j++;
+		bw = hdd_convert_phy_bw_to_nl_bw(res_msg[i].bw);
+		hdd_debug("populating chan_params freq %d bw %d iface mode %d, seg0 %d",
+			  res_msg[i].freq, bw, res_msg[i].iface_mode_mask,
+			  res_msg[i].seg0_freq);
+		if (nla_put_u32(skb,
+				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ,
+				res_msg[i].freq) ||
+		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ,
+				res_msg[i].seg0_freq) ||
+		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ,
+				res_msg[i].seg1_freq) ||
+		    nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH,
+				bw) ||
+		    nla_put_u32(skb,
+				QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK,
+				res_msg[i].iface_mode_mask)) {
+			hdd_err("nla put failre");
+			return -EINVAL;
+		}
+
+		nla_nest_end(skb, chan_params);
 	}
 	nla_nest_end(skb, config);
 	return 0;
@@ -15396,6 +15436,43 @@ fail:
 	return status;
 }
 
+/**
+ * hdd_get_all_band_mask() - get supported nl80211 bands
+ *
+ * Return: supported band mask
+ */
+static uint32_t
+hdd_get_all_band_mask(void)
+{
+	uint32_t band_mask = 0;
+
+	band_mask = (1 << NL80211_BAND_2GHZ) |
+			(1 << NL80211_BAND_5GHZ) |
+			(1 << NL80211_BAND_6GHZ);
+
+	return band_mask;
+}
+
+/**
+ * hdd_get_all_iface_mode_mask() - get supported nl80211 iface mode
+ *
+ * Return: supported iface mode mask
+ */
+static uint32_t
+hdd_get_all_iface_mode_mask(void)
+{
+	uint32_t mode_mask = 0;
+
+	mode_mask = (1 << NL80211_IFTYPE_STATION) |
+			(1 << NL80211_IFTYPE_AP) |
+			(1 << NL80211_IFTYPE_P2P_GO) |
+			(1 << NL80211_IFTYPE_P2P_CLIENT) |
+			(1 << NL80211_IFTYPE_P2P_DEVICE) |
+			(1 << NL80211_IFTYPE_NAN);
+
+	return mode_mask;
+}
+
 /**
  * __wlan_hdd_cfg80211_get_usable_channel() - get chain rssi
  * @wiphy: wiphy pointer
@@ -15440,27 +15517,31 @@ static int __wlan_hdd_cfg80211_get_usable_channel(struct wiphy *wiphy,
 
 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]) {
 		hdd_err("band mask not present");
-		ret = -EINVAL;
-		goto err;
-	}
-	req_msg.band_mask =
+		req_msg.band_mask = hdd_get_all_band_mask();
+	} else {
+		req_msg.band_mask =
 		nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK]);
-
+		if (!req_msg.band_mask)
+			req_msg.band_mask = hdd_get_all_band_mask();
+	}
 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]) {
 		hdd_err("iface mode mask not present");
-		ret = -EINVAL;
-		goto err;
-	}
-	req_msg.iface_mode_mask = nla_get_u32(
+		req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
+	} else {
+		req_msg.iface_mode_mask = nla_get_u32(
 		tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK]);
+		if (!req_msg.iface_mode_mask)
+			req_msg.iface_mode_mask = hdd_get_all_iface_mode_mask();
+	}
 
 	if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]) {
 		hdd_err("usable channels filter mask not present");
-		ret = -EINVAL;
-		goto err;
+		req_msg.filter_mask = 0;
+	} else {
+		req_msg.filter_mask =
+			nla_get_u32(
+			tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
 	}
-	req_msg.filter_mask =
-	   nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK]);
 
 	hdd_debug("get usable channel list for band %d mode %d filter %d",
 		  req_msg.band_mask, req_msg.iface_mode_mask,