diff mbox series

[v2,1/2] UBUNTU: SAUCE: wcn36xx: read MAC from file or randomly generate one

Message ID 1528970937-26879-2-git-send-email-paolo.pisati@canonical.com
State New
Headers show
Series UBUNTU: SAUCE: arm64: snapdragon: wcn36xx MAC | expand

Commit Message

Paolo Pisati June 14, 2018, 10:08 a.m. UTC
BugLink: http://bugs.launchpad.net/bugs/1776491

By default, wcn36xx initializes itself with a dummy 00:00:00:00:00:00 MAC
address, preventing the interface from working until a valid MAC address was set.

While not an issue on Ubuntu Classic (where the user can always set it
later on the command line or via /etc/network/interfaces), it became a problem
on Ubuntu Core where the wifi interface is probed during installation,
before the user has any chance to set a new MAC address.

To overcome this scenario, the wcn36xx driver in Xenial had a couple of features:

1) during probe, if /lib/firmware/wlan/macaddr0 was present, its content was
used as the new MAC address

2) if that failed, a pseudo-random MAC addres was generated and set

and this is a port of a the corresponding Xenial code to Bionic:
see xenial/snapdragon tree, 
drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c::wcn36xx_msm_get_hw_mac().

Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 drivers/net/wireless/ath/wcn36xx/Kconfig |  9 ++++++++
 drivers/net/wireless/ath/wcn36xx/main.c  | 38 +++++++++++++++++++++++++++++++-
 2 files changed, 46 insertions(+), 1 deletion(-)

Comments

Khalid Elmously June 17, 2018, 6:18 a.m. UTC | #1
On 2018-06-14 12:08:56 , Paolo Pisati wrote:
> BugLink: http://bugs.launchpad.net/bugs/1776491
> 
> By default, wcn36xx initializes itself with a dummy 00:00:00:00:00:00 MAC
> address, preventing the interface from working until a valid MAC address was set.
> 
> While not an issue on Ubuntu Classic (where the user can always set it
> later on the command line or via /etc/network/interfaces), it became a problem
> on Ubuntu Core where the wifi interface is probed during installation,
> before the user has any chance to set a new MAC address.
> 
> To overcome this scenario, the wcn36xx driver in Xenial had a couple of features:
> 
> 1) during probe, if /lib/firmware/wlan/macaddr0 was present, its content was
> used as the new MAC address
> 
> 2) if that failed, a pseudo-random MAC addres was generated and set
> 
> and this is a port of a the corresponding Xenial code to Bionic:
> see xenial/snapdragon tree, 
> drivers/net/wireless/ath/wcn36xx/wcn36xx-msm.c::wcn36xx_msm_get_hw_mac().
> 
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---
>  drivers/net/wireless/ath/wcn36xx/Kconfig |  9 ++++++++
>  drivers/net/wireless/ath/wcn36xx/main.c  | 38 +++++++++++++++++++++++++++++++-
>  2 files changed, 46 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig
> index 20bf967..44d34a80 100644
> --- a/drivers/net/wireless/ath/wcn36xx/Kconfig
> +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
> @@ -16,3 +16,12 @@ config WCN36XX_DEBUGFS
>  	  Enabled debugfs support
>  
>  	  If unsure, say Y to make it easier to debug problems.
> +
> +config WCN36XX_SNAPDRAGON_HACKS
> +	bool "Dragonboard 410c WCN36XX MAC address generation hacks"
> +	default n
> +	depends on WCN36XX
> +	---help---
> +	  Upon probe, WCN36XX will try to read its MAC address from
> +	  a file located at /lib/firmware/wlan/macaddr0. If the file
> +	  is not present, it will randomly generate a new MAC address.
> diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
> index fcc98d4..ed0b973 100644
> --- a/drivers/net/wireless/ath/wcn36xx/main.c
> +++ b/drivers/net/wireless/ath/wcn36xx/main.c
> @@ -1265,6 +1265,14 @@ static int wcn36xx_probe(struct platform_device *pdev)
>  	void *wcnss;
>  	int ret;
>  	const u8 *addr;
> +#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
> +	int status;
> +	const struct firmware *addr_file = NULL;
> +	u8 tmp[18], _addr[ETH_ALEN];
> +	static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
> +	static const char *files = {"wlan/macaddr0"};
> +#endif
> +
>  
>  	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
>  
> @@ -1298,7 +1306,35 @@ static int wcn36xx_probe(struct platform_device *pdev)
>  		wcn36xx_err("invalid local-mac-address\n");
>  		ret = -EINVAL;
>  		goto out_wq;
> -	} else if (addr) {
> +	}
> +#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
> +	else if (addr == NULL) {
> +		addr = _addr;
> +		status = request_firmware(&addr_file, files, &pdev->dev);
> +
> +		if (status < 0) {
> +			/* Assign a random mac with Qualcomm oui */
> +			dev_err(&pdev->dev, "Failed (%d) to read macaddress"
> +			"file %s, using a random address instead", status, files);
> +			memcpy(addr, qcom_oui, 3);
> +			get_random_bytes(addr + 3, 3);
> +		} else {
> +			memset(tmp, 0, sizeof(tmp));
> +			memcpy(tmp, addr_file->data, sizeof(tmp) - 1);
> +			sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
> +			&addr[0],
> +			&addr[1],
> +			&addr[2],
> +			&addr[3],
> +			&addr[4],
> +			&addr[5]);
> +
> +			release_firmware(addr_file);

Not sure of the details of release_firmware(), but seems like calling it right after the memcpy() would be better. Probably not important though.


> +		}
> +	}
> +#endif
> +
> +	if (addr) {
>  		wcn36xx_info("mac address: %pM\n", addr);
>  		SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
>  	}
> -- 
> 2.7.4
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff mbox series

Patch

diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 20bf967..44d34a80 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -16,3 +16,12 @@  config WCN36XX_DEBUGFS
 	  Enabled debugfs support
 
 	  If unsure, say Y to make it easier to debug problems.
+
+config WCN36XX_SNAPDRAGON_HACKS
+	bool "Dragonboard 410c WCN36XX MAC address generation hacks"
+	default n
+	depends on WCN36XX
+	---help---
+	  Upon probe, WCN36XX will try to read its MAC address from
+	  a file located at /lib/firmware/wlan/macaddr0. If the file
+	  is not present, it will randomly generate a new MAC address.
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index fcc98d4..ed0b973 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1265,6 +1265,14 @@  static int wcn36xx_probe(struct platform_device *pdev)
 	void *wcnss;
 	int ret;
 	const u8 *addr;
+#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
+	int status;
+	const struct firmware *addr_file = NULL;
+	u8 tmp[18], _addr[ETH_ALEN];
+	static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
+	static const char *files = {"wlan/macaddr0"};
+#endif
+
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
 
@@ -1298,7 +1306,35 @@  static int wcn36xx_probe(struct platform_device *pdev)
 		wcn36xx_err("invalid local-mac-address\n");
 		ret = -EINVAL;
 		goto out_wq;
-	} else if (addr) {
+	}
+#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
+	else if (addr == NULL) {
+		addr = _addr;
+		status = request_firmware(&addr_file, files, &pdev->dev);
+
+		if (status < 0) {
+			/* Assign a random mac with Qualcomm oui */
+			dev_err(&pdev->dev, "Failed (%d) to read macaddress"
+			"file %s, using a random address instead", status, files);
+			memcpy(addr, qcom_oui, 3);
+			get_random_bytes(addr + 3, 3);
+		} else {
+			memset(tmp, 0, sizeof(tmp));
+			memcpy(tmp, addr_file->data, sizeof(tmp) - 1);
+			sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+			&addr[0],
+			&addr[1],
+			&addr[2],
+			&addr[3],
+			&addr[4],
+			&addr[5]);
+
+			release_firmware(addr_file);
+		}
+	}
+#endif
+
+	if (addr) {
 		wcn36xx_info("mac address: %pM\n", addr);
 		SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
 	}