2016-12-24 16:58:04

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 0/6] wl1251: Fix MAC address for Nokia N900

This patch series fix processing MAC address for wl1251 chip found in Nokia N900.

Pali Rohár (6):
firmware: Add request_firmware_prefer_user() function
wl1251: Use request_firmware_prefer_user() for loading NVS
calibration data
wl1251: Update wl->nvs_len after wl->nvs is valid
wl1251: Generate random MAC address only if driver does not have
valid
wl1251: Parse and use MAC address from supplied NVS data
wl1251: Set generated MAC address back to NVS data

drivers/base/firmware_class.c | 45 +++++++++++++++-
drivers/net/wireless/ti/wl1251/Kconfig | 1 +
drivers/net/wireless/ti/wl1251/main.c | 91 +++++++++++++++++++++++++-------
include/linux/firmware.h | 9 ++++
4 files changed, 125 insertions(+), 21 deletions(-)

--
1.7.9.5


2016-12-24 16:58:14

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 1/6] firmware: Add request_firmware_prefer_user() function

This function works pretty much like request_firmware(), but it prefer
usermode helper. If usermode helper fails then it fallback to direct
access. Useful for dynamic or model specific firmware data.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/base/firmware_class.c | 45 +++++++++++++++++++++++++++++++++++++++--
include/linux/firmware.h | 9 +++++++++
2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760..6a8c261 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -119,6 +119,11 @@ static inline long firmware_loading_timeout(void)
#endif
#define FW_OPT_NO_WARN (1U << 3)
#define FW_OPT_NOCACHE (1U << 4)
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+#define FW_OPT_PREFER_USER (1U << 5)
+#else
+#define FW_OPT_PREFER_USER 0
+#endif

struct firmware_cache {
/* firmware_buf instance will be added into the below list */
@@ -1169,13 +1174,26 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device,
}
}

- ret = fw_get_filesystem_firmware(device, fw->priv);
+ if (opt_flags & FW_OPT_PREFER_USER) {
+ ret = fw_load_from_user_helper(fw, name, device, opt_flags, timeout);
+ if (ret && !(opt_flags & FW_OPT_NO_WARN)) {
+ dev_warn(device,
+ "User helper firmware load for %s failed with error %d\n",
+ name, ret);
+ dev_warn(device, "Falling back to direct firmware load\n");
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+ if (ret)
+ ret = fw_get_filesystem_firmware(device, fw->priv);
if (ret) {
if (!(opt_flags & FW_OPT_NO_WARN))
dev_warn(device,
"Direct firmware load for %s failed with error %d\n",
name, ret);
- if (opt_flags & FW_OPT_USERHELPER) {
+ if ((opt_flags & FW_OPT_USERHELPER) && !(opt_flags & FW_OPT_PREFER_USER)) {
dev_warn(device, "Falling back to user helper\n");
ret = fw_load_from_user_helper(fw, name, device,
opt_flags, timeout);
@@ -1287,6 +1305,29 @@ int request_firmware_direct(const struct firmware **firmware_p,
EXPORT_SYMBOL(request_firmware_into_buf);

/**
+ * request_firmware_prefer_user: - prefer usermode helper for loading firmware
+ * @firmware_p: pointer to firmware image
+ * @name: name of firmware file
+ * @device: device for which firmware is being loaded
+ *
+ * This function works pretty much like request_firmware(), but it prefer
+ * usermode helper. If usermode helper fails then it fallback to direct access.
+ * Useful for dynamic or model specific firmware data.
+ **/
+int request_firmware_prefer_user(const struct firmware **firmware_p,
+ const char *name, struct device *device)
+{
+ int ret;
+
+ __module_get(THIS_MODULE);
+ ret = _request_firmware(firmware_p, name, device, NULL, 0,
+ FW_OPT_UEVENT | FW_OPT_PREFER_USER);
+ module_put(THIS_MODULE);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(request_firmware_prefer_user);
+
+/**
* release_firmware: - release the resource associated with a firmware image
* @fw: firmware resource to release
**/
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index b1f9f0c..01f7a85 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -47,6 +47,8 @@ int request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context));
int request_firmware_direct(const struct firmware **fw, const char *name,
struct device *device);
+int request_firmware_prefer_user(const struct firmware **fw, const char *name,
+ struct device *device);
int request_firmware_into_buf(const struct firmware **firmware_p,
const char *name, struct device *device, void *buf, size_t size);

@@ -77,6 +79,13 @@ static inline int request_firmware_direct(const struct firmware **fw,
return -EINVAL;
}

+static inline int request_firmware_prefer_user(const struct firmware **fw,
+ const char *name,
+ struct device *device)
+{
+ return -EINVAL;
+}
+
static inline int request_firmware_into_buf(const struct firmware **firmware_p,
const char *name, struct device *device, void *buf, size_t size)
{
--
1.7.9.5

2016-12-24 16:58:07

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 3/6] wl1251: Update wl->nvs_len after wl->nvs is valid

In case kmemdup fails thne wl->nvs_len will contains invalid non-zero size.
This patch fixes it.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 24f8866..8971b64 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -124,8 +124,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
goto out;
}

- wl->nvs_len = fw->size;
- wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL);
+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);

if (!wl->nvs) {
wl1251_error("could not allocate memory for the nvs file");
@@ -133,6 +132,8 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
goto out;
}

+ wl->nvs_len = fw->size;
+
ret = 0;

out:
--
1.7.9.5

2016-12-24 16:57:59

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

NVS calibration data for wl1251 are model specific. Every one device with
wl1251 chip has different and calibrated in factory.

Not all wl1251 chips have own EEPROM where are calibration data stored. And
in that case there is no "standard" place. Every device has stored them on
different place (some in rootfs file, some in dedicated nand partition,
some in another proprietary structure).

Kernel wl1251 driver cannot support every one different storage decided by
device manufacture so it will use request_firmware_prefer_user() call for
loading NVS calibration data and userspace helper will be responsible to
prepare correct data.

In case userspace helper fails request_firmware_prefer_user() still try to
load data file directly from VFS as fallback mechanism.

On Nokia N900 device which has wl1251 chip, NVS calibration data are stored
in CAL nand partition. CAL is proprietary Nokia key/value format for nand
devices.

With this patch it is finally possible to load correct model specific NVS
calibration data for Nokia N900.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/Kconfig | 1 +
drivers/net/wireless/ti/wl1251/main.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig
index 7142ccf..affe154 100644
--- a/drivers/net/wireless/ti/wl1251/Kconfig
+++ b/drivers/net/wireless/ti/wl1251/Kconfig
@@ -2,6 +2,7 @@ config WL1251
tristate "TI wl1251 driver support"
depends on MAC80211
select FW_LOADER
+ select FW_LOADER_USER_HELPER
select CRC7
---help---
This will enable TI wl1251 driver support. The drivers make
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 208f062..24f8866 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -110,7 +110,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
struct device *dev = wiphy_dev(wl->hw->wiphy);
int ret;

- ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
+ ret = request_firmware_prefer_user(&fw, WL1251_NVS_NAME, dev);

if (ret < 0) {
wl1251_error("could not get nvs file: %d", ret);
--
1.7.9.5

2016-12-24 17:01:50

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 5/6] wl1251: Parse and use MAC address from supplied NVS data

This patch implements parsing MAC address from NVS data which are sent to
wl1251 chip. Calibration NVS data could contain valid MAC address and it
will be used instead randomly generated.

This patch also move code for requesting NVS data from userspace to driver
initialization code to make sure that NVS data will be there at time when
permanent MAC address is needed.

Calibration NVS data for wl1251 are model specific. Every one device with
wl1251 chip should have been calibrated in factory and needs to provide own
calibration data.

Default example wl1251-nvs.bin data found in linux-firmware repository and
contains MAC address 00:00:20:07:03:09. So this MAC address is marked as
invalid as it is not real device specific address, just example one.

Format of calibration NVS data can be found at:
http://notaz.gp2x.de/misc/pnd/wl1251/nvs_map.txt

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 39 ++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index c3fa0b6..1454ba2 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -205,13 +205,6 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
goto out;
}

- if (wl->nvs == NULL && !wl->use_eeprom) {
- /* No NVS from netlink, try to get it from the filesystem */
- ret = wl1251_fetch_nvs(wl);
- if (ret < 0)
- goto out;
- }
-
out:
return ret;
}
@@ -1538,6 +1531,30 @@ static int wl1251_read_eeprom_mac(struct wl1251 *wl)
return 0;
}

+static int wl1251_read_nvs_mac(struct wl1251 *wl)
+{
+ u8 mac[ETH_ALEN];
+ int i;
+
+ if (wl->nvs_len < 0x24)
+ return -ENODATA;
+
+ /* length is 2 and data address is 0x546c (mask is 0xfffe) */
+ if (wl->nvs[0x19] != 2 || wl->nvs[0x1a] != 0x6d || wl->nvs[0x1b] != 0x54)
+ return -EINVAL;
+
+ /* MAC is stored in reverse order */
+ for (i = 0; i < ETH_ALEN; i++)
+ mac[i] = wl->nvs[0x1c + ETH_ALEN - i - 1];
+
+ /* 00:00:20:07:03:09 is in default example wl1251-nvs.bin, so invalid */
+ if (ether_addr_equal_unaligned(mac, "\x00\x00\x20\x07\x03\x09"))
+ return -EINVAL;
+
+ memcpy(wl->mac_addr, mac, ETH_ALEN);
+ return 0;
+}
+
static int wl1251_register_hw(struct wl1251 *wl)
{
int ret;
@@ -1581,10 +1598,16 @@ int wl1251_init_ieee80211(struct wl1251 *wl)

wl->hw->queues = 4;

+ if (wl->nvs == NULL && !wl->use_eeprom) {
+ ret = wl1251_fetch_nvs(wl);
+ if (ret < 0)
+ goto out;
+ }
+
if (wl->use_eeprom)
ret = wl1251_read_eeprom_mac(wl);
else
- ret = -EINVAL;
+ ret = wl1251_read_nvs_mac(wl);

if (ret == 0 && !is_valid_ether_addr(wl->mac_addr))
ret = -EINVAL;
--
1.7.9.5

2016-12-24 17:02:15

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 4/6] wl1251: Generate random MAC address only if driver does not have valid

Before this patch driver generated random MAC address every time when was
doing initialization. And after that random MAC address could be
overwritten with fixed one if provided.

This patch changes order. First it tries to read fixed MAC address and if
it fails then driver generates random MAC address.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 8971b64..c3fa0b6 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1582,7 +1582,24 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
wl->hw->queues = 4;

if (wl->use_eeprom)
- wl1251_read_eeprom_mac(wl);
+ ret = wl1251_read_eeprom_mac(wl);
+ else
+ ret = -EINVAL;
+
+ if (ret == 0 && !is_valid_ether_addr(wl->mac_addr))
+ ret = -EINVAL;
+
+ if (ret < 0) {
+ /*
+ * In case our MAC address is not correctly set,
+ * we use a random but Nokia MAC.
+ */
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
+ memcpy(wl->mac_addr, nokia_oui, 3);
+ get_random_bytes(wl->mac_addr + 3, 3);
+ wl1251_warning("MAC address in eeprom or nvs data is not valid");
+ wl1251_warning("Setting random MAC address: %pM", wl->mac_addr);
+ }

ret = wl1251_register_hw(wl);
if (ret)
@@ -1623,7 +1640,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
struct ieee80211_hw *hw;
struct wl1251 *wl;
int i;
- static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};

hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
if (!hw) {
@@ -1674,13 +1690,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
INIT_WORK(&wl->irq_work, wl1251_irq_work);
INIT_WORK(&wl->tx_work, wl1251_tx_work);

- /*
- * In case our MAC address is not correctly set,
- * we use a random but Nokia MAC.
- */
- memcpy(wl->mac_addr, nokia_oui, 3);
- get_random_bytes(wl->mac_addr + 3, 3);
-
wl->state = WL1251_STATE_OFF;
mutex_init(&wl->mutex);

--
1.7.9.5

2016-12-24 17:02:23

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 6/6] wl1251: Set generated MAC address back to NVS data

In case there is no valid MAC address kernel generates random one. This
patch propagate this generated MAC address back to NVS data which will be
uploaded to wl1251 chip. So HW would have same MAC address as linux kernel
uses.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 1454ba2..895ae05 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1555,6 +1555,24 @@ static int wl1251_read_nvs_mac(struct wl1251 *wl)
return 0;
}

+static int wl1251_write_nvs_mac(struct wl1251 *wl)
+{
+ int i;
+
+ if (wl->nvs_len < 0x24)
+ return -ENODATA;
+
+ /* length is 2 and data address is 0x546c (mask is 0xfffe) */
+ if (wl->nvs[0x19] != 2 || wl->nvs[0x1a] != 0x6d || wl->nvs[0x1b] != 0x54)
+ return -EINVAL;
+
+ /* MAC is stored in reverse order */
+ for (i = 0; i < ETH_ALEN; i++)
+ wl->nvs[0x1c + i] = wl->mac_addr[ETH_ALEN - i - 1];
+
+ return 0;
+}
+
static int wl1251_register_hw(struct wl1251 *wl)
{
int ret;
@@ -1620,6 +1638,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
memcpy(wl->mac_addr, nokia_oui, 3);
get_random_bytes(wl->mac_addr + 3, 3);
+ if (!wl->use_eeprom)
+ wl1251_write_nvs_mac(wl);
wl1251_warning("MAC address in eeprom or nvs data is not valid");
wl1251_warning("Setting random MAC address: %pM", wl->mac_addr);
}
--
1.7.9.5

2016-12-24 18:02:16

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 3/6] wl1251: Update wl->nvs_len after wl->nvs is valid

On Sat 2016-12-24 17:52:58, Pali Roh?r wrote:
> In case kmemdup fails thne wl->nvs_len will contains invalid non-zero size.
> This patch fixes it.

If kmemdup fails, then wl->nvs_len will contain invalid non-zero size.

?

This probably should go as first in series, as it is bugfix?

Pavel
Acked-by: Pavel Machek <[email protected]>


> Signed-off-by: Pali Roh?r <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/main.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 24f8866..8971b64 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -124,8 +124,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
> goto out;
> }
>
> - wl->nvs_len = fw->size;
> - wl->nvs = kmemdup(fw->data, wl->nvs_len, GFP_KERNEL);
> + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);
>
> if (!wl->nvs) {
> wl1251_error("could not allocate memory for the nvs file");
> @@ -133,6 +132,8 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
> goto out;
> }
>
> + wl->nvs_len = fw->size;
> +
> ret = 0;
>
> out:

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (1.30 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2016-12-24 18:08:58

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 4/6] wl1251: Generate random MAC address only if driver does not have valid

On Sat 2016-12-24 17:52:59, Pali Roh?r wrote:

> Before this patch driver generated random MAC address every time when was
> doing initialization. And after that random MAC address could be
> overwritten with fixed one if provided.

Before this patch, driver generated random MAC address every time it
was initialized. After that random MAC address could be overwritten
with fixed one, if provided.

> This patch changes order. First it tries to read fixed MAC address and if
> it fails then driver generates random MAC address.

I don't quite get where the advantage is supposed to be. Is it that
"use_eeprom" is set, but reading fails?

The only case where this helps is if wl1251_read_eeprom_mac() succeeds
but reads invalid address.

> Signed-off-by: Pali Roh?r <[email protected]>

Acked-by: Pavel Machek <[email protected]>

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (965.00 B)
signature.asc (181.00 B)
Digital signature
Download all attachments

2016-12-24 18:14:26

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 5/6] wl1251: Parse and use MAC address from supplied NVS data

On Sat 2016-12-24 17:53:00, Pali Roh?r wrote:
> This patch implements parsing MAC address from NVS data which are sent to
> wl1251 chip. Calibration NVS data could contain valid MAC address and it
> will be used instead randomly generated.

will be used instead of randomly generated one.

> This patch also move code for requesting NVS data from userspace to driver

"moves"

> initialization code to make sure that NVS data will be there at time when
> permanent MAC address is needed.

"at a time"

> Calibration NVS data for wl1251 are model specific. Every one device with

"device specific"? "Every device".

> wl1251 chip should have been calibrated in factory and needs to provide own
> calibration data.
>
> Default example wl1251-nvs.bin data found in linux-firmware repository and

"are found"

> contains MAC address 00:00:20:07:03:09. So this MAC address is marked as

"contain"

> invalid as it is not real device specific address, just example one.
>
> Format of calibration NVS data can be found at:
> http://notaz.gp2x.de/misc/pnd/wl1251/nvs_map.txt
>
> Signed-off-by: Pali Roh?r <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/main.c | 39 ++++++++++++++++++++++++++-------
> 1 file changed, 31 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index c3fa0b6..1454ba2 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -205,13 +205,6 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
> goto out;
> }
>
> - if (wl->nvs == NULL && !wl->use_eeprom) {
> - /* No NVS from netlink, try to get it from the filesystem */
> - ret = wl1251_fetch_nvs(wl);
> - if (ret < 0)
> - goto out;
> - }
> -
> out:
> return ret;
> }
> @@ -1538,6 +1531,30 @@ static int wl1251_read_eeprom_mac(struct wl1251 *wl)
> return 0;
> }
>
> +static int wl1251_read_nvs_mac(struct wl1251 *wl)
> +{
> + u8 mac[ETH_ALEN];
> + int i;
> +
> + if (wl->nvs_len < 0x24)
> + return -ENODATA;
> +
> + /* length is 2 and data address is 0x546c (mask is 0xfffe) */
> + if (wl->nvs[0x19] != 2 || wl->nvs[0x1a] != 0x6d || wl->nvs[0x1b] != 0x54)
> + return -EINVAL;
> +
> + /* MAC is stored in reverse order */
> + for (i = 0; i < ETH_ALEN; i++)
> + mac[i] = wl->nvs[0x1c + ETH_ALEN - i - 1];
> +
> + /* 00:00:20:07:03:09 is in default example wl1251-nvs.bin, so invalid */

remove "default".

> + if (ether_addr_equal_unaligned(mac, "\x00\x00\x20\x07\x03\x09"))
> + return -EINVAL;
> +
> + memcpy(wl->mac_addr, mac, ETH_ALEN);
> + return 0;
> +}
> +
> static int wl1251_register_hw(struct wl1251 *wl)
> {
> int ret;
> @@ -1581,10 +1598,16 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
>
> wl->hw->queues = 4;
>
> + if (wl->nvs == NULL && !wl->use_eeprom) {
> + ret = wl1251_fetch_nvs(wl);
> + if (ret < 0)
> + goto out;
> + }

Is goto out here good idea? IMNSHO it is copy&paste bug, it should
just proceed with generating random address.

> if (wl->use_eeprom)
> ret = wl1251_read_eeprom_mac(wl);
> else
> - ret = -EINVAL;
> + ret = wl1251_read_nvs_mac(wl);
>
> if (ret == 0 && !is_valid_ether_addr(wl->mac_addr))
> ret = -EINVAL;

Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (3.30 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2016-12-24 18:17:34

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 6/6] wl1251: Set generated MAC address back to NVS data

Hi!

> In case there is no valid MAC address kernel generates random one. This
> patch propagate this generated MAC address back to NVS data which will be
> uploaded to wl1251 chip. So HW would have same MAC address as linux kernel
> uses.

> return 0;
> }
>
> +static int wl1251_write_nvs_mac(struct wl1251 *wl)
> +{

The name is quite confusing, this sounds like writing into
non-volatile storage.

> + int i;
> +
> + if (wl->nvs_len < 0x24)
> + return -ENODATA;
> +
> + /* length is 2 and data address is 0x546c (mask is 0xfffe) */

You don't actually check for the mask.

> + if (wl->nvs[0x19] != 2 || wl->nvs[0x1a] != 0x6d || wl->nvs[0x1b] != 0x54)
> + return -EINVAL;

You have two copies of these. Does it make sense to move it to helper
function?

Thanks,
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (923.00 B)
signature.asc (181.00 B)
Digital signature
Download all attachments

2016-12-24 18:38:51

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 4/6] wl1251: Generate random MAC address only if driver does not have valid

On Saturday 24 December 2016 19:08:54 Pavel Machek wrote:
> On Sat 2016-12-24 17:52:59, Pali Rohár wrote:
> > Before this patch driver generated random MAC address every time
> > when was doing initialization. And after that random MAC address
> > could be overwritten with fixed one if provided.
>
> Before this patch, driver generated random MAC address every time it
> was initialized. After that random MAC address could be overwritten
> with fixed one, if provided.
>
> > This patch changes order. First it tries to read fixed MAC address
> > and if it fails then driver generates random MAC address.
>
> I don't quite get where the advantage is supposed to be. Is it that
> "use_eeprom" is set, but reading fails?

Random bytes are read from kernel only if random MAC address is needed.
And in wl->mac_addr is always either invalid address or permanenent mac
address which will be used. Without patch in wl->mac_addr can be random
temporary address for some time...

> The only case where this helps is if wl1251_read_eeprom_mac()
> succeeds but reads invalid address.
>
> > Signed-off-by: Pali Rohár <[email protected]>
>
> Acked-by: Pavel Machek <[email protected]>

--
Pali Rohár
[email protected]


Attachments:
signature.asc (198.00 B)
This is a digitally signed message part.

2016-12-24 18:40:29

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 5/6] wl1251: Parse and use MAC address from supplied NVS data

On Saturday 24 December 2016 19:14:21 Pavel Machek wrote:
> On Sat 2016-12-24 17:53:00, Pali Rohár wrote:
> > @@ -1581,10 +1598,16 @@ int wl1251_init_ieee80211(struct wl1251
> > *wl)
> >
> > wl->hw->queues = 4;
> >
> > + if (wl->nvs == NULL && !wl->use_eeprom) {
> > + ret = wl1251_fetch_nvs(wl);
> > + if (ret < 0)
> > + goto out;
> > + }
>
> Is goto out here good idea? IMNSHO it is copy&paste bug, it should
> just proceed with generating random address.

No, goto is correct here. wl1251 cannot be initialized without NVS data.
And when fetching (from userspace) fails it is fatal error.

--
Pali Rohár
[email protected]


Attachments:
signature.asc (198.00 B)
This is a digitally signed message part.

2016-12-24 18:44:38

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 6/6] wl1251: Set generated MAC address back to NVS data

On Saturday 24 December 2016 19:17:30 Pavel Machek wrote:
> Hi!
>
> > In case there is no valid MAC address kernel generates random one.
> > This patch propagate this generated MAC address back to NVS data
> > which will be uploaded to wl1251 chip. So HW would have same MAC
> > address as linux kernel uses.
> >
> > return 0;
> >
> > }
> >
> > +static int wl1251_write_nvs_mac(struct wl1251 *wl)
> > +{
>
> The name is quite confusing, this sounds like writing into
> non-volatile storage.
>
> > + int i;
> > +
> > + if (wl->nvs_len < 0x24)
> > + return -ENODATA;
> > +
> > + /* length is 2 and data address is 0x546c (mask is 0xfffe) */
>
> You don't actually check for the mask.

It is quite complicated. { 0x6d, 0x54 } (= 0x546d) in data represent
address 0x546c and content are data. You need to apply mask 0xfffe for
0x546d and you get address where data will be written (so 0x546c).

> > + if (wl->nvs[0x19] != 2 || wl->nvs[0x1a] != 0x6d || wl->nvs[0x1b]
> > != 0x54) + return -EINVAL;
>
> You have two copies of these. Does it make sense to move it to helper
> function?

I'm thinking if checks is really needed. But probably moving it to
separate function is good idea.

--
Pali Rohár
[email protected]


Attachments:
signature.asc (198.00 B)
This is a digitally signed message part.

2016-12-25 20:15:46

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On 24-12-2016 17:52, Pali Rohár wrote:
> NVS calibration data for wl1251 are model specific. Every one device with
> wl1251 chip has different and calibrated in factory.
>
> Not all wl1251 chips have own EEPROM where are calibration data stored. And
> in that case there is no "standard" place. Every device has stored them on
> different place (some in rootfs file, some in dedicated nand partition,
> some in another proprietary structure).
>
> Kernel wl1251 driver cannot support every one different storage decided by
> device manufacture so it will use request_firmware_prefer_user() call for
> loading NVS calibration data and userspace helper will be responsible to
> prepare correct data.

Responding to this patch as it provides a lot of context to discuss. As
you might have gathered from earlier discussions I am not a fan of using
user-space helper. I can agree that the kernel driver, wl1251 in this
case, should be agnostic to platform specific details regarding storage
solutions and the firmware api should hide that. However, it seems your
only solution is adding user-space to the mix and changing the api
towards that. Can we solve it without user-space help?

The firmware_class already supports a number of path prefixes it
traverses looking for the requested firmware. So I was thinking about
adding a hashtable in which a platform driver can add firmware which are
stored in the hashtable using the hashed firmware name. Upon a firmware
request from the driver we could check the hashtable before traversing
the path prefixes on VFS. The obvious problem is that the request may
come before the firmware is added to the hashtable. Just wanted to pitch
the idea first and hear what others think about it and maybe someone has
a nice solution for this problem. Fingers crossed :-p

> In case userspace helper fails request_firmware_prefer_user() still try to
> load data file directly from VFS as fallback mechanism.
>
> On Nokia N900 device which has wl1251 chip, NVS calibration data are stored
> in CAL nand partition. CAL is proprietary Nokia key/value format for nand
> devices.

With the firmware hashtable api on N900 a platform driver could
interpret the CAL data in the nand partition and provide it through the
firmware_class.

> With this patch it is finally possible to load correct model specific NVS
> calibration data for Nokia N900.

But on other devices that use wl1251, but for instance have no userspace
helper the request to userspace will fail (after 60 sec?) and try VFS
after that. Maybe not so nice. You should consider other device
configurations. Not just N900.

Regards,
Arend

> Signed-off-by: Pali Rohár <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/Kconfig | 1 +
> drivers/net/wireless/ti/wl1251/main.c | 2 +-
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig
> index 7142ccf..affe154 100644
> --- a/drivers/net/wireless/ti/wl1251/Kconfig
> +++ b/drivers/net/wireless/ti/wl1251/Kconfig
> @@ -2,6 +2,7 @@ config WL1251
> tristate "TI wl1251 driver support"
> depends on MAC80211
> select FW_LOADER
> + select FW_LOADER_USER_HELPER
> select CRC7
> ---help---
> This will enable TI wl1251 driver support. The drivers make
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 208f062..24f8866 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -110,7 +110,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
> struct device *dev = wiphy_dev(wl->hw->wiphy);
> int ret;
>
> - ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
> + ret = request_firmware_prefer_user(&fw, WL1251_NVS_NAME, dev);
>
> if (ret < 0) {
> wl1251_error("could not get nvs file: %d", ret);
>

2016-12-25 20:46:50

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On Sunday 25 December 2016 21:15:40 Arend Van Spriel wrote:
> On 24-12-2016 17:52, Pali Rohár wrote:
> > NVS calibration data for wl1251 are model specific. Every one
> > device with wl1251 chip has different and calibrated in factory.
> >
> > Not all wl1251 chips have own EEPROM where are calibration data
> > stored. And in that case there is no "standard" place. Every
> > device has stored them on different place (some in rootfs file,
> > some in dedicated nand partition, some in another proprietary
> > structure).
> >
> > Kernel wl1251 driver cannot support every one different storage
> > decided by device manufacture so it will use
> > request_firmware_prefer_user() call for loading NVS calibration
> > data and userspace helper will be responsible to prepare correct
> > data.
>
> Responding to this patch as it provides a lot of context to discuss.
> As you might have gathered from earlier discussions I am not a fan
> of using user-space helper. I can agree that the kernel driver,
> wl1251 in this case, should be agnostic to platform specific details
> regarding storage solutions and the firmware api should hide that.
> However, it seems your only solution is adding user-space to the mix
> and changing the api towards that. Can we solve it without
> user-space help?

Without userspace helper it means that userspace helper code must be
integrated into kernel.

So what is userspace helper doing?

1) Read MAC address from CAL
2) Read NVS data from CAL
3) Modify MAC address in memory NVS data (new for this patch series)
4) Modify in memory NVS data if we in FCC country

Checking for country is done via dbus call to either Maemo cellular
daemon or alternatively via REGDOMAIN in /etc/default/crda. I have plan
to use ofono (instead Maemo cellular daemon) too...

Currently we are using closed Nokia proprietary CAL library.

Steps 1) and 2) needs closed library, step 4) needs dbus call.

In current state I do not see way to integrate it into kernel. And
because wl1251 currently uses request_firmware() to load those nvs data
I think it is still the best way how to handle it...

And IIRC there was already discussion about Nokia CAL parser in kernel
and it was declined.

> The firmware_class already supports a number of path prefixes it
> traverses looking for the requested firmware. So I was thinking about
> adding a hashtable in which a platform driver can add firmware which
> are stored in the hashtable using the hashed firmware name. Upon a
> firmware request from the driver we could check the hashtable before
> traversing the path prefixes on VFS. The obvious problem is that the
> request may come before the firmware is added to the hashtable. Just
> wanted to pitch the idea first and hear what others think about it
> and maybe someone has a nice solution for this problem. Fingers
> crossed :-p
>
> > In case userspace helper fails request_firmware_prefer_user() still
> > try to load data file directly from VFS as fallback mechanism.
> >
> > On Nokia N900 device which has wl1251 chip, NVS calibration data
> > are stored in CAL nand partition. CAL is proprietary Nokia
> > key/value format for nand devices.
>
> With the firmware hashtable api on N900 a platform driver could
> interpret the CAL data in the nand partition and provide it through
> the firmware_class.
>
> > With this patch it is finally possible to load correct model
> > specific NVS calibration data for Nokia N900.
>
> But on other devices that use wl1251, but for instance have no
> userspace helper the request to userspace will fail (after 60 sec?)
> and try VFS after that. Maybe not so nice.

Currently support for those devices is broken (like for N900) as without
proper NVS data they do not work correctly...

> You should consider other device configurations. Not just N900.

I do not have any other wl1251 devices. I know that pandora has wl1251
too, but it has wl1251 with eeprom where is stored NVS. And in this case
request_firmware() is not used there.

> Regards,
> Arend
>
> > Signed-off-by: Pali Rohár <[email protected]>
> > ---
> >
> > drivers/net/wireless/ti/wl1251/Kconfig | 1 +
> > drivers/net/wireless/ti/wl1251/main.c | 2 +-
> > 2 files changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/wireless/ti/wl1251/Kconfig
> > b/drivers/net/wireless/ti/wl1251/Kconfig index 7142ccf..affe154
> > 100644
> > --- a/drivers/net/wireless/ti/wl1251/Kconfig
> > +++ b/drivers/net/wireless/ti/wl1251/Kconfig
> > @@ -2,6 +2,7 @@ config WL1251
> >
> > tristate "TI wl1251 driver support"
> > depends on MAC80211
> > select FW_LOADER
> >
> > + select FW_LOADER_USER_HELPER
> >
> > select CRC7
> > ---help---
> >
> > This will enable TI wl1251 driver support. The drivers make
> >
> > diff --git a/drivers/net/wireless/ti/wl1251/main.c
> > b/drivers/net/wireless/ti/wl1251/main.c index 208f062..24f8866
> > 100644
> > --- a/drivers/net/wireless/ti/wl1251/main.c
> > +++ b/drivers/net/wireless/ti/wl1251/main.c
> > @@ -110,7 +110,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl)
> >
> > struct device *dev = wiphy_dev(wl->hw->wiphy);
> > int ret;
> >
> > - ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
> > + ret = request_firmware_prefer_user(&fw, WL1251_NVS_NAME, dev);
> >
> > if (ret < 0) {
> >
> > wl1251_error("could not get nvs file: %d", ret);

--
Pali Rohár
[email protected]


Attachments:
signature.asc (198.00 B)
This is a digitally signed message part.

2016-12-26 15:44:29

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

Hi!

> > > NVS calibration data for wl1251 are model specific. Every one
> > > device with wl1251 chip has different and calibrated in factory.
> > >
> > > Not all wl1251 chips have own EEPROM where are calibration data
> > > stored. And in that case there is no "standard" place. Every
> > > device has stored them on different place (some in rootfs file,
> > > some in dedicated nand partition, some in another proprietary
> > > structure).
> > >
> > > Kernel wl1251 driver cannot support every one different storage
> > > decided by device manufacture so it will use
> > > request_firmware_prefer_user() call for loading NVS calibration
> > > data and userspace helper will be responsible to prepare correct
> > > data.
> >
> > Responding to this patch as it provides a lot of context to discuss.
> > As you might have gathered from earlier discussions I am not a fan
> > of using user-space helper. I can agree that the kernel driver,
> > wl1251 in this case, should be agnostic to platform specific details
> > regarding storage solutions and the firmware api should hide that.
> > However, it seems your only solution is adding user-space to the mix
> > and changing the api towards that. Can we solve it without
> > user-space help?
>
> Without userspace helper it means that userspace helper code must be
> integrated into kernel.
>
> So what is userspace helper doing?
>
> 1) Read MAC address from CAL
> 2) Read NVS data from CAL
> 3) Modify MAC address in memory NVS data (new for this patch series)
> 4) Modify in memory NVS data if we in FCC country
>
> Checking for country is done via dbus call to either Maemo cellular
> daemon or alternatively via REGDOMAIN in /etc/default/crda. I have plan
> to use ofono (instead Maemo cellular daemon) too...
>
> Currently we are using closed Nokia proprietary CAL library.
>
> Steps 1) and 2) needs closed library, step 4) needs dbus call.

I guess pointer to the source code implementing this would be welcome.

> > But on other devices that use wl1251, but for instance have no
> > userspace helper the request to userspace will fail (after 60 sec?)
> > and try VFS after that. Maybe not so nice.
>
> Currently support for those devices is broken (like for N900) as without
> proper NVS data they do not work correctly...

Is it expected to work at all, perhaps with degraded performance /
range? Because it seems to work for me.

Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (2.50 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2016-12-26 16:05:03

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On Monday 26 December 2016 16:43:53 Pavel Machek wrote:
> Hi!
>
> > > > NVS calibration data for wl1251 are model specific. Every one
> > > > device with wl1251 chip has different and calibrated in
> > > > factory.
> > > >
> > > > Not all wl1251 chips have own EEPROM where are calibration data
> > > > stored. And in that case there is no "standard" place. Every
> > > > device has stored them on different place (some in rootfs file,
> > > > some in dedicated nand partition, some in another proprietary
> > > > structure).
> > > >
> > > > Kernel wl1251 driver cannot support every one different storage
> > > > decided by device manufacture so it will use
> > > > request_firmware_prefer_user() call for loading NVS calibration
> > > > data and userspace helper will be responsible to prepare
> > > > correct data.
> > >
> > > Responding to this patch as it provides a lot of context to
> > > discuss. As you might have gathered from earlier discussions I
> > > am not a fan of using user-space helper. I can agree that the
> > > kernel driver, wl1251 in this case, should be agnostic to
> > > platform specific details regarding storage solutions and the
> > > firmware api should hide that. However, it seems your only
> > > solution is adding user-space to the mix and changing the api
> > > towards that. Can we solve it without user-space help?
> >
> > Without userspace helper it means that userspace helper code must
> > be integrated into kernel.
> >
> > So what is userspace helper doing?
> >
> > 1) Read MAC address from CAL
> > 2) Read NVS data from CAL
> > 3) Modify MAC address in memory NVS data (new for this patch
> > series) 4) Modify in memory NVS data if we in FCC country
> >
> > Checking for country is done via dbus call to either Maemo cellular
> > daemon or alternatively via REGDOMAIN in /etc/default/crda. I have
> > plan to use ofono (instead Maemo cellular daemon) too...
> >
> > Currently we are using closed Nokia proprietary CAL library.
> >
> > Steps 1) and 2) needs closed library, step 4) needs dbus call.
>
> I guess pointer to the source code implementing this would be
> welcome.

Here is current code: https://github.com/community-ssu/wl1251-cal

(there is implemented also Maemo netlink interface)

> > > But on other devices that use wl1251, but for instance have no
> > > userspace helper the request to userspace will fail (after 60
> > > sec?) and try VFS after that. Maybe not so nice.
> >
> > Currently support for those devices is broken (like for N900) as
> > without proper NVS data they do not work correctly...
>
> Is it expected to work at all, perhaps with degraded performance /
> range? Because it seems to work for me.

Yes, some degraded performance or problems with connecting is expected.
And random MAC address at every boot. Plus some regulatory problems in
FCC countries.

--
Pali Rohár
[email protected]


Attachments:
signature.asc (198.00 B)
This is a digitally signed message part.

2016-12-26 16:37:07

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On Sun 2016-12-25 21:15:40, Arend Van Spriel wrote:
> On 24-12-2016 17:52, Pali Roh?r wrote:
> > NVS calibration data for wl1251 are model specific. Every one device with
> > wl1251 chip has different and calibrated in factory.
> >
> > Not all wl1251 chips have own EEPROM where are calibration data stored. And
> > in that case there is no "standard" place. Every device has stored them on
> > different place (some in rootfs file, some in dedicated nand partition,
> > some in another proprietary structure).
> >
> > Kernel wl1251 driver cannot support every one different storage decided by
> > device manufacture so it will use request_firmware_prefer_user() call for
> > loading NVS calibration data and userspace helper will be responsible to
> > prepare correct data.
>
> Responding to this patch as it provides a lot of context to discuss. As
> you might have gathered from earlier discussions I am not a fan of using
> user-space helper. I can agree that the kernel driver, wl1251 in this
> case, should be agnostic to platform specific details regarding storage
> solutions and the firmware api should hide that. However, it seems your
> only solution is adding user-space to the mix and changing the api
> towards that. Can we solve it without user-space help?

Answer is no, due to licensing. But that's wrong question to ask.

Right question is "should we solve it without user-space help"?

Answer is no, too. Way too complex. Yes, it would be nice if hardware
was designed in such a way that getting calibration data from kernel
is easy, and if you design hardware, please design it like that. But
N900 is not designed like that and getting the calibration through
userspace looks like only reasonable solution.

Now... how exactly to do that is other question. (But this is looks
very reasonable. Maybe I'd add request_firmware_with_flags(, ...int
flags), but.. that's a tiny detail.). But userspace needs to be
involved.

Thanks,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html


Attachments:
(No filename) (2.05 kB)
signature.asc (181.00 B)
Digital signature
Download all attachments

2017-06-23 21:53:24

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On Tue, May 16, 2017 at 10:41:08AM +0200, Arend Van Spriel wrote:
> On 16-5-2017 1:13, Luis R. Rodriguez wrote:
> > Since no upstream delta is needed for firmwared I'd like to first encourage
> > evaluating the above. While distributions don't carry it yet that may be seen as
> > an issue but since what we are looking for are corner cases, only folks needing
> > to deploy a specific solution would need it or a custom proprietary solution.
>
> Ok. I will go try and run firmwared in OpenWrt on a router platform.
> Have to steal one from a colleague :-p Will study firmwared.

Arend, curious how this effort goes. Its important to me as we know then that
if this works its a good approach to recommend moving forward which should also
prove less complex than that soup we had with the custom fallback stuff.

Luis

2017-06-30 21:35:47

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data



On 23-06-17 23:53, Luis R. Rodriguez wrote:
> On Tue, May 16, 2017 at 10:41:08AM +0200, Arend Van Spriel wrote:
>> On 16-5-2017 1:13, Luis R. Rodriguez wrote:
>>> Since no upstream delta is needed for firmwared I'd like to first encourage
>>> evaluating the above. While distributions don't carry it yet that may be seen as
>>> an issue but since what we are looking for are corner cases, only folks needing
>>> to deploy a specific solution would need it or a custom proprietary solution.
>>
>> Ok. I will go try and run firmwared in OpenWrt on a router platform.
>> Have to steal one from a colleague :-p Will study firmwared.
>
> Arend, curious how this effort goes. Its important to me as we know then that
> if this works its a good approach to recommend moving forward which should also
> prove less complex than that soup we had with the custom fallback stuff.

Hi Luis,

So I looked at firmwared and we basically need to extend it. For our
router platform we need to obtain nvram calibration data from an MTD
partition which contains the raw data, ie. no file-system on it. So
firmwared would need some sort of configuration to map a particular
firmware file to some action obtaining the data like kicking off some
mtd-utils in my case.

Regards,
Arend

2017-08-10 19:43:07

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH 2/6] wl1251: Use request_firmware_prefer_user() for loading NVS calibration data

On Fri, Jun 30, 2017 at 11:35:41PM +0200, Arend van Spriel wrote:
> On 23-06-17 23:53, Luis R. Rodriguez wrote:
> > On Tue, May 16, 2017 at 10:41:08AM +0200, Arend Van Spriel wrote:
> >> On 16-5-2017 1:13, Luis R. Rodriguez wrote:
> >>> Since no upstream delta is needed for firmwared I'd like to first encourage
> >>> evaluating the above. While distributions don't carry it yet that may be seen as
> >>> an issue but since what we are looking for are corner cases, only folks needing
> >>> to deploy a specific solution would need it or a custom proprietary solution.
> >>
> >> Ok. I will go try and run firmwared in OpenWrt on a router platform.
> >> Have to steal one from a colleague :-p Will study firmwared.
> >
> > Arend, curious how this effort goes. Its important to me as we know then that
> > if this works its a good approach to recommend moving forward which should also
> > prove less complex than that soup we had with the custom fallback stuff.
>
> Hi Luis,
>
> So I looked at firmwared and we basically need to extend it.

And actually as me and Johannes spoke long ago at Plumbers, its rather
expected folks would need this or just fork it off completely. firmwared
would just be a reference codebase on how to do these custom loaders.

*How regular* Linux distributions embrace this is still up in the air then,
because as Lennart has pointed out there is no plan to merge firmwared
to systemd.

*If* this is a requirement only for non-upstream drivers or patches on
which will not be merged upstream then this will work long term. If you
need regular distros to do something custom then their respective upstream
tools would need to be evaluated for how something similar would be done.

As far as I can tell perhaps the remote-proc thing would count as one
possible use-case for upstream drivers -- but even then the systems
that use it seem likely to use Android and then some custom userspace.

> For our
> router platform we need to obtain nvram calibration data from an MTD
> partition which contains the raw data, ie. no file-system on it. So
> firmwared would need some sort of configuration to map a particular
> firmware file to some action obtaining the data like kicking off some
> mtd-utils in my case.

I see. So platform specific.

Thanks for the update!

Luis

2017-11-09 23:42:24

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 0/6] wl1251: Fix MAC address for Nokia N900

This patch series fix processing MAC address for wl1251 chip found in Nokia N900.

Changes since v1:
* Added Acked-by for Pavel Machek
* Fixed grammar
* Magic numbers for NVS offsets are replaced by defines
* Check for validity of mac address NVS data is moved into function
* Changed order of patches as Pavel requested

Pali Rohár (6):
wl1251: Update wl->nvs_len after wl->nvs is valid
wl1251: Generate random MAC address only if driver does not have
valid
wl1251: Parse and use MAC address from supplied NVS data
wl1251: Set generated MAC address back to NVS data
firmware: Add request_firmware_prefer_user() function
wl1251: Use request_firmware_prefer_user() for loading NVS
calibration data

drivers/base/firmware_class.c | 45 +++++++++++++-
drivers/net/wireless/ti/wl1251/Kconfig | 1 +
drivers/net/wireless/ti/wl1251/main.c | 104 ++++++++++++++++++++++++++------
include/linux/firmware.h | 9 +++
4 files changed, 138 insertions(+), 21 deletions(-)

--
1.7.9.5


From 1583615347071151294@xxx Thu Nov 09 18:48:03 +0000 2017
X-GM-THRID: 1583615347071151294
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-09 23:42:10

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 4/6] wl1251: Set generated MAC address back to NVS data

In case there is no valid MAC address kernel generates random one. This
patch propagate this generated MAC address back to NVS data which will be
uploaded to wl1251 chip. So HW would have same MAC address as linux kernel
uses.

This should not change any functionality, but it is better to tell wl1251
correct mac address since beginning of chip usage.

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index d497ba5..1f423be 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1481,6 +1481,21 @@ static int wl1251_read_nvs_mac(struct wl1251 *wl)
return 0;
}

+static int wl1251_write_nvs_mac(struct wl1251 *wl)
+{
+ int i, ret;
+
+ ret = wl1251_check_nvs_mac(wl);
+ if (ret)
+ return ret;
+
+ /* MAC is stored in reverse order */
+ for (i = 0; i < ETH_ALEN; i++)
+ wl->nvs[NVS_OFF_MAC_DATA + i] = wl->mac_addr[ETH_ALEN - i - 1];
+
+ return 0;
+}
+
static int wl1251_register_hw(struct wl1251 *wl)
{
int ret;
@@ -1546,6 +1561,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
memcpy(wl->mac_addr, nokia_oui, 3);
get_random_bytes(wl->mac_addr + 3, 3);
+ if (!wl->use_eeprom)
+ wl1251_write_nvs_mac(wl);
wl1251_warning("MAC address in eeprom or nvs data is not valid");
wl1251_warning("Setting random MAC address: %pM", wl->mac_addr);
}
--
1.7.9.5


From 1583671839625441555@xxx Fri Nov 10 09:45:59 +0000 2017
X-GM-THRID: 1583492295006962716
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread

2017-11-09 23:40:48

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 3/6] wl1251: Parse and use MAC address from supplied NVS data

This patch implements parsing MAC address from NVS data which are sent to
wl1251 chip. Calibration NVS data could contain valid MAC address and it
will be used instead of randomly generated one.

This patch also moves code for requesting NVS data from userspace to driver
initialization code to make sure that NVS data will be there at time when
permanent MAC address is needed.

Calibration NVS data for wl1251 are device specific. Every device with
wl1251 chip should have been calibrated in factory and needs to provide own
calibration data.

Default example file wl1251-nvs.bin, found in linux-firmware repository,
contains MAC address 00:00:20:07:03:09. So this MAC address is marked as
invalid as it is not real device specific address, just example one.

Format of calibration NVS data can be found at:
http://notaz.gp2x.de/misc/pnd/wl1251/nvs_map.txt

Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 55 ++++++++++++++++++++++++++++-----
1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 9106c20..d497ba5 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -203,13 +203,6 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
goto out;
}

- if (wl->nvs == NULL && !wl->use_eeprom) {
- /* No NVS from netlink, try to get it from the filesystem */
- ret = wl1251_fetch_nvs(wl);
- if (ret < 0)
- goto out;
- }
-
out:
return ret;
}
@@ -1448,6 +1441,46 @@ static int wl1251_read_eeprom_mac(struct wl1251 *wl)
return 0;
}

+#define NVS_OFF_MAC_LEN 0x19
+#define NVS_OFF_MAC_ADDR_LO 0x1a
+#define NVS_OFF_MAC_ADDR_HI 0x1b
+#define NVS_OFF_MAC_DATA 0x1c
+
+static int wl1251_check_nvs_mac(struct wl1251 *wl)
+{
+ if (wl->nvs_len < 0x24)
+ return -ENODATA;
+
+ /* length is 2 and data address is 0x546c (ANDed with 0xfffe) */
+ if (wl->nvs[NVS_OFF_MAC_LEN] != 2 ||
+ wl->nvs[NVS_OFF_MAC_ADDR_LO] != 0x6d ||
+ wl->nvs[NVS_OFF_MAC_ADDR_HI] != 0x54)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int wl1251_read_nvs_mac(struct wl1251 *wl)
+{
+ u8 mac[ETH_ALEN];
+ int i, ret;
+
+ ret = wl1251_check_nvs_mac(wl);
+ if (ret)
+ return ret;
+
+ /* MAC is stored in reverse order */
+ for (i = 0; i < ETH_ALEN; i++)
+ mac[i] = wl->nvs[NVS_OFF_MAC_DATA + ETH_ALEN - i - 1];
+
+ /* 00:00:20:07:03:09 is in example file wl1251-nvs.bin, so invalid */
+ if (ether_addr_equal_unaligned(mac, "\x00\x00\x20\x07\x03\x09"))
+ return -EINVAL;
+
+ memcpy(wl->mac_addr, mac, ETH_ALEN);
+ return 0;
+}
+
static int wl1251_register_hw(struct wl1251 *wl)
{
int ret;
@@ -1491,10 +1524,16 @@ int wl1251_init_ieee80211(struct wl1251 *wl)

wl->hw->queues = 4;

+ if (wl->nvs == NULL && !wl->use_eeprom) {
+ ret = wl1251_fetch_nvs(wl);
+ if (ret < 0)
+ goto out;
+ }
+
if (wl->use_eeprom)
ret = wl1251_read_eeprom_mac(wl);
else
- ret = -EINVAL;
+ ret = wl1251_read_nvs_mac(wl);

if (ret == 0 && !is_valid_ether_addr(wl->mac_addr))
ret = -EINVAL;
--
1.7.9.5


From 1585316890852053809@xxx Tue Nov 28 13:33:22 +0000 2017
X-GM-THRID: 1585267426933007486
X-Gmail-Labels: Inbox,Category Forums,HistoricalUnread