diff mbox series

wifi: cfg80211: allow reg update by driver even if wiphy->regd is set

Message ID 20230421061312.13722-1-quic_rajkbhag@quicinc.com
State New
Headers show
Series wifi: cfg80211: allow reg update by driver even if wiphy->regd is set | expand

Commit Message

Raj Kumar Bhagat April 21, 2023, 6:13 a.m. UTC
Currently regulatory update by driver is not allowed when the
wiphy->regd is already set and drivers_request->intersect is false.

During wiphy registration, some drivers (ath10k does this currently)
first register the world regulatory to cfg80211 using
wiphy_apply_custom_regulatory(). The driver then obtain the current
operating country and tries to update the correct regulatory to
cfg80211 using regulatory_hint().

But at this point, wiphy->regd is already set to world regulatory.
Also, since this is the first request from driver after the world
regulatory is set this will result in drivers_request->intersect
set to false. In this condition the driver request regulatory is not
allowed to update to cfg80211 in reg_set_rd_driver(). This restricts
the device operation to the world regulatory.

This driver request to update the requlatory with current operating
country is valid and should be updated to cfg80211. Hence allow
regulatory update by driver even if the wiphy->regd is already set
and driver_request->intersect is false.

Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
---
 net/wireless/reg.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

Comments

Jeff Johnson Aug. 16, 2023, 6:26 p.m. UTC | #1
On 4/20/2023 11:13 PM, Raj Kumar Bhagat wrote:
> Currently regulatory update by driver is not allowed when the
> wiphy->regd is already set and drivers_request->intersect is false.
> 
> During wiphy registration, some drivers (ath10k does this currently)
> first register the world regulatory to cfg80211 using
> wiphy_apply_custom_regulatory(). The driver then obtain the current
> operating country and tries to update the correct regulatory to
> cfg80211 using regulatory_hint().
> 
> But at this point, wiphy->regd is already set to world regulatory.
> Also, since this is the first request from driver after the world
> regulatory is set this will result in drivers_request->intersect
> set to false. In this condition the driver request regulatory is not
> allowed to update to cfg80211 in reg_set_rd_driver(). This restricts
> the device operation to the world regulatory.
> 
> This driver request to update the requlatory with current operating

nit: s/requlatory/regulatory/

> country is valid and should be updated to cfg80211. Hence allow
> regulatory update by driver even if the wiphy->regd is already set
> and driver_request->intersect is false.
> 
> Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>

Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>

> ---
>   net/wireless/reg.c | 9 ++++-----
>   1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
> index 0d40d6af7e10..6cf0bc386f94 100644
> --- a/net/wireless/reg.c
> +++ b/net/wireless/reg.c
> @@ -3833,7 +3833,7 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
>   {
>   	const struct ieee80211_regdomain *regd;
>   	const struct ieee80211_regdomain *intersected_rd = NULL;
> -	const struct ieee80211_regdomain *tmp;
> +	const struct ieee80211_regdomain *tmp = NULL;
>   	struct wiphy *request_wiphy;
>   
>   	if (is_world_regdom(rd->alpha2))
> @@ -3856,10 +3856,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
>   	if (!driver_request->intersect) {
>   		ASSERT_RTNL();
>   		wiphy_lock(request_wiphy);
> -		if (request_wiphy->regd) {
> -			wiphy_unlock(request_wiphy);
> -			return -EALREADY;
> -		}
> +		if (request_wiphy->regd)
> +			tmp = get_wiphy_regdom(request_wiphy);
>   
>   		regd = reg_copy_regd(rd);
>   		if (IS_ERR(regd)) {
> @@ -3868,6 +3866,7 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
>   		}
>   
>   		rcu_assign_pointer(request_wiphy->regd, regd);
> +		rcu_free_regdom(tmp);
>   		wiphy_unlock(request_wiphy);
>   		reset_regdomains(false, rd);
>   		return 0;
diff mbox series

Patch

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0d40d6af7e10..6cf0bc386f94 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3833,7 +3833,7 @@  static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
 {
 	const struct ieee80211_regdomain *regd;
 	const struct ieee80211_regdomain *intersected_rd = NULL;
-	const struct ieee80211_regdomain *tmp;
+	const struct ieee80211_regdomain *tmp = NULL;
 	struct wiphy *request_wiphy;
 
 	if (is_world_regdom(rd->alpha2))
@@ -3856,10 +3856,8 @@  static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
 	if (!driver_request->intersect) {
 		ASSERT_RTNL();
 		wiphy_lock(request_wiphy);
-		if (request_wiphy->regd) {
-			wiphy_unlock(request_wiphy);
-			return -EALREADY;
-		}
+		if (request_wiphy->regd)
+			tmp = get_wiphy_regdom(request_wiphy);
 
 		regd = reg_copy_regd(rd);
 		if (IS_ERR(regd)) {
@@ -3868,6 +3866,7 @@  static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
 		}
 
 		rcu_assign_pointer(request_wiphy->regd, regd);
+		rcu_free_regdom(tmp);
 		wiphy_unlock(request_wiphy);
 		reset_regdomains(false, rd);
 		return 0;