2013-10-26 20:40:24

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 00/16] wl1251 patches from linux-n900 tree

Hello, I'm sending wl1251 patches from linux-n900 tree [1] for comments. More
patches come from David's monitor & packet injection work. Patches are tested
with 3.12 rc5 kernel on Nokia N900.

[1] - https://gitorious.org/linux-n900/linux-n900

David Gnedt (13):
mac80211: fix TX device statistics for monitor interfaces
wl1251: fix scan behaviour while not associated
wl1251: add sysfs interface for bluetooth coexistence mode
configuration
wl1251: retry power save entry
wl1251: implement hardware ARP filtering
wl1251: split RX and TX data path initialisation
wl1251: configure hardware en-/decryption for monitor mode
wl1251: implement multicast address filtering
wl1251: disable power saving in monitor mode
wl1251: fix channel switching in monitor mode
wl1251: enable tx path in monitor mode if necessary for packet
injection
wl1251: disable retry and ACK policy for injected packets
wl1251: enforce changed hw encryption support on monitor state change

Pali Rohár (3):
wl1251: add nvs file name to module firmware list
wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate
wl1251: Add sysfs file address for setting permanent mac address

drivers/net/wireless/ti/wl1251/acx.c | 97 ++++++-
drivers/net/wireless/ti/wl1251/acx.h | 34 ++-
drivers/net/wireless/ti/wl1251/boot.c | 3 +-
drivers/net/wireless/ti/wl1251/cmd.c | 50 +++-
drivers/net/wireless/ti/wl1251/cmd.h | 8 +-
drivers/net/wireless/ti/wl1251/event.c | 44 +++
drivers/net/wireless/ti/wl1251/event.h | 7 +
drivers/net/wireless/ti/wl1251/init.c | 19 +-
drivers/net/wireless/ti/wl1251/main.c | 460 ++++++++++++++++++++++++++++++-
drivers/net/wireless/ti/wl1251/rx.c | 2 +-
drivers/net/wireless/ti/wl1251/tx.c | 27 +-
drivers/net/wireless/ti/wl1251/wl1251.h | 14 +
net/mac80211/tx.c | 3 +
13 files changed, 715 insertions(+), 53 deletions(-)

--
1.7.10.4



2013-10-28 23:39:54

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> From: David Gnedt <[email protected]>
>
> Port the bt_coex_mode sysfs interface from wl1251 driver version included
> in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
> This enables userspace applications to set one of the modes
> WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
> The default mode is WL1251_BT_COEX_OFF.
> It should be noted that this driver always enabled bt-coexistence before
> and enabled bt-coexistence directly affects the receiving performance,
> rendering it unusable in some low-signal situations. Especially monitor
> mode is affected very badly with bt-coexistence enabled.
[...]

This should be implemented consistently with other drivers:

drivers/net/wireless/ath/ath9k/htc_drv_init.c:module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
drivers/net/wireless/ath/ath9k/init.c:module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
drivers/net/wireless/b43/main.c:module_param_named(btcoex, modparam_btcoex, int, 0444);
drivers/net/wireless/ipw2x00/ipw2200.c:module_param(bt_coexist, int, 0444);
drivers/net/wireless/iwlegacy/common.c:module_param(bt_coex_active, bool, S_IRUGO);
drivers/net/wireless/iwlwifi/iwl-drv.c:module_param_named(bt_coex_active, iwlwifi_mod_params.bt_coex_active,
drivers/net/wireless/ti/wlcore/sysfs.c:static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,

Oh, hmm, I see a problem here.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-10-28 14:57:09

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Mon, 2013-10-28 at 09:46 -0500, Dan Williams wrote:

> If the device doesn't actually *have* a permanent MAC address, then it
> shouldn't be returning one via ethtool, and should return an error for
> ETHTOOL_GPERMADDR.

There's currently no provision for that, but I agree it would be better
to do so.

johannes


2013-10-26 20:40:35

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 10/16] wl1251: fix channel switching in monitor mode

From: David Gnedt <[email protected]>

Use the ENABLE_RX command for channel switching when no interface is present
(monitor mode only).
The advantage of ENABLE_RX is that it leaves the tx data path disabled in
firmware, whereas the usual JOIN command seems to transmit some frames at
firmware level.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 62cb374..7e6b6d1 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -611,8 +611,19 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
if (channel != wl->channel) {
wl->channel = channel;

- ret = wl1251_join(wl, wl->bss_type, wl->channel,
- wl->beacon_int, wl->dtim_period);
+ /*
+ * Use ENABLE_RX command for channel switching when no
+ * interface is present (monitor mode only).
+ * This leaves the tx path disabled in firmware, whereas
+ * the usual JOIN command seems to transmit some frames
+ * at firmware level.
+ */
+ if (wl->vif == NULL) {
+ ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+ } else {
+ ret = wl1251_join(wl, wl->bss_type, wl->channel,
+ wl->beacon_int, wl->dtim_period);
+ }
if (ret < 0)
goto out_sleep;
}
--
1.7.10.4


2013-10-30 11:55:06

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 13/16] wl1251: enforce changed hw encryption support on monitor state change

On Sat 2013-10-26 22:34:12, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> The firmware doesn't support per packet encryption selection, so disable hw
> encryption support completly while a monitor interface is present to support

"completely".

> injection of packets (which shouldn't get encrypted by hw).
> To enforce the changed hw encryption support force a disassociation on
> non-monitor interfaces.
> For disassociation a workaround using hw connection monitor is employed,
> which temporary enables hw connection manager flag.
>
> Signed-off-by: David Gnedt <[email protected]>

Missing sign-off.

> index 174f403..f054741 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -685,6 +685,16 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
> wl->power_level = conf->power_level;
> }
>
> + /*
> + * Tell stack that connection is lost because hw encryption isn't
> + * supported in monitor mode.
> + * XXX This requires temporary enabling the hw connection monitor flag
> + */

"of the" and I guess you can remove the XXX? This way it looks like
workaround is not complete.

Thanks,
Pavel

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

2013-10-28 23:50:15

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> Driver wl1251 generating mac address randomly at startup and there is no way to
> set permanent mac address via SET_IEEE80211_PERM_ADDR. This patch export sysfs
> file which can set permanent mac address by userspace helper program. Patch is
> needed for devices which do not store mac address in internal wl1251 eeprom.
[...]

This belongs in struct wl12xx_platform_data or (better) Device Tree
properties. It definitely should not be settable once the device is
registered.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-10-26 20:40:28

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 04/16] wl1251: retry power save entry

From: David Gnedt <[email protected]>

Port of the power save entry retry code from wl1251 driver version included
in the Maemo Fremantle kernel.
This tries to enable power save mode up to 3 times before failing.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/boot.c | 3 ++-
drivers/net/wireless/ti/wl1251/event.c | 44 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/event.h | 7 +++++
drivers/net/wireless/ti/wl1251/main.c | 2 ++
drivers/net/wireless/ti/wl1251/wl1251.h | 3 +++
5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/boot.c b/drivers/net/wireless/ti/wl1251/boot.c
index a2e5241..2000cd5 100644
--- a/drivers/net/wireless/ti/wl1251/boot.c
+++ b/drivers/net/wireless/ti/wl1251/boot.c
@@ -299,7 +299,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
- BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
+ BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID |
+ PS_REPORT_EVENT_ID;

ret = wl1251_event_unmask(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index 74ae8e1..192cebd 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -46,6 +46,43 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
return ret;
}

+#define WL1251_PSM_ENTRY_RETRIES 3
+static int wl1251_event_ps_report(struct wl1251 *wl,
+ struct event_mailbox *mbox)
+{
+ int ret = 0;
+
+ wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
+
+ switch (mbox->ps_status) {
+ case EVENT_ENTER_POWER_SAVE_FAIL:
+ wl1251_debug(DEBUG_PSM, "PSM entry failed");
+
+ if (wl->station_mode != STATION_POWER_SAVE_MODE) {
+ /* remain in active mode */
+ wl->psm_entry_retry = 0;
+ break;
+ }
+
+ if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
+ wl->psm_entry_retry++;
+ ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ } else {
+ wl1251_error("Power save entry failed, giving up");
+ wl->psm_entry_retry = 0;
+ }
+ break;
+ case EVENT_ENTER_POWER_SAVE_SUCCESS:
+ case EVENT_EXIT_POWER_SAVE_FAIL:
+ case EVENT_EXIT_POWER_SAVE_SUCCESS:
+ default:
+ wl->psm_entry_retry = 0;
+ break;
+ }
+
+ return 0;
+}
+
static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
{
wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -80,6 +117,13 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
}
}

+ if (vector & PS_REPORT_EVENT_ID) {
+ wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
+ ret = wl1251_event_ps_report(wl, mbox);
+ if (ret < 0)
+ return ret;
+ }
+
if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");

diff --git a/drivers/net/wireless/ti/wl1251/event.h b/drivers/net/wireless/ti/wl1251/event.h
index 30eb5d1..88570a5 100644
--- a/drivers/net/wireless/ti/wl1251/event.h
+++ b/drivers/net/wireless/ti/wl1251/event.h
@@ -112,6 +112,13 @@ struct event_mailbox {
u8 padding[19];
} __packed;

+enum {
+ EVENT_ENTER_POWER_SAVE_FAIL = 0,
+ EVENT_ENTER_POWER_SAVE_SUCCESS,
+ EVENT_EXIT_POWER_SAVE_FAIL,
+ EVENT_EXIT_POWER_SAVE_SUCCESS,
+};
+
int wl1251_event_unmask(struct wl1251 *wl);
void wl1251_event_mbox_config(struct wl1251 *wl);
int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index ad2fd18..46a2494 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -480,6 +480,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->next_tx_complete = 0;
wl->elp = false;
wl->station_mode = STATION_ACTIVE_MODE;
+ wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
@@ -1519,6 +1520,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
wl->elp = false;
wl->station_mode = STATION_ACTIVE_MODE;
wl->psm_requested = false;
+ wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 724c9f9..7cd1bac 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -374,6 +374,9 @@ struct wl1251 {
/* PSM mode requested */
bool psm_requested;

+ /* retry counter for PSM entries */
+ u8 psm_entry_retry;
+
u16 beacon_int;
u8 dtim_period;

--
1.7.10.4


2013-10-29 07:10:22

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

On Mon, 2013-10-28 at 23:39 +0000, Ben Hutchings wrote:
> On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > From: David Gnedt <[email protected]>
> >
> > Port the bt_coex_mode sysfs interface from wl1251 driver version included
> > in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
> > This enables userspace applications to set one of the modes
> > WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
> > The default mode is WL1251_BT_COEX_OFF.
> > It should be noted that this driver always enabled bt-coexistence before
> > and enabled bt-coexistence directly affects the receiving performance,
> > rendering it unusable in some low-signal situations. Especially monitor
> > mode is affected very badly with bt-coexistence enabled.
> [...]
>
> This should be implemented consistently with other drivers:
>
> drivers/net/wireless/ath/ath9k/htc_drv_init.c:module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
> drivers/net/wireless/ath/ath9k/init.c:module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
> drivers/net/wireless/b43/main.c:module_param_named(btcoex, modparam_btcoex, int, 0444);
> drivers/net/wireless/ipw2x00/ipw2200.c:module_param(bt_coexist, int, 0444);
> drivers/net/wireless/iwlegacy/common.c:module_param(bt_coex_active, bool, S_IRUGO);
> drivers/net/wireless/iwlwifi/iwl-drv.c:module_param_named(bt_coex_active, iwlwifi_mod_params.bt_coex_active,
> drivers/net/wireless/ti/wlcore/sysfs.c:static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,
>
> Oh, hmm, I see a problem here.

With so many drivers doing the same thing, isn't it about time to add
this to nl80211?

--
Luca.


2013-10-30 11:46:29

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 09/16] wl1251: disable power saving in monitor mode

On Sat 2013-10-26 22:34:08, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Force power saving off while monitor interface is present.
>
> Signed-off-by: David Gnedt <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/main.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 727f2ee..62cb374 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -617,7 +617,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
> goto out_sleep;
> }
>
> - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
> + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested &&
> + !wl->monitor_present) {
> wl1251_debug(DEBUG_PSM, "psm enabled");
>
> wl->psm_requested = true;
> @@ -633,8 +634,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
> ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
> if (ret < 0)
> goto out_sleep;
> - } else if (!(conf->flags & IEEE80211_CONF_PS) &&
> - wl->psm_requested) {
> + } else if ((!(conf->flags & IEEE80211_CONF_PS) || wl->monitor_present)
> + && wl->psm_requested) {
> wl1251_debug(DEBUG_PSM, "psm disabled");
>

These boolean expressions make my head spin. Introduce helper function

can_do_pm()... return (conf->flags & IEEE80211_CONF_PS) &&
!wl->monitor_present

?

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

2013-10-26 20:40:31

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 06/16] wl1251: split RX and TX data path initialisation

From: David Gnedt <[email protected]>

Split up data path initialisation into RX and TX data path initialisation
functions. This change is required for channel switching in monitor mode.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/cmd.c | 37 ++++++++++++++++++++++++++-------
drivers/net/wireless/ti/wl1251/cmd.h | 3 ++-
drivers/net/wireless/ti/wl1251/init.c | 9 ++++++--
3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 16b6479..055924c 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -204,11 +204,11 @@ out:
return ret;
}

-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable)
{
struct cmd_enabledisable_path *cmd;
int ret;
- u16 cmd_rx, cmd_tx;
+ u16 cmd_rx;

wl1251_debug(DEBUG_CMD, "cmd data path");

@@ -220,13 +220,10 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)

cmd->channel = channel;

- if (enable) {
+ if (enable)
cmd_rx = CMD_ENABLE_RX;
- cmd_tx = CMD_ENABLE_TX;
- } else {
+ else
cmd_rx = CMD_DISABLE_RX;
- cmd_tx = CMD_DISABLE_TX;
- }

ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
if (ret < 0) {
@@ -238,6 +235,32 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
enable ? "start" : "stop", channel);

+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
+{
+ struct cmd_enabledisable_path *cmd;
+ int ret;
+ u16 cmd_tx;
+
+ wl1251_debug(DEBUG_CMD, "cmd data path");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->channel = channel;
+
+ if (enable)
+ cmd_tx = CMD_ENABLE_TX;
+ else
+ cmd_tx = CMD_DISABLE_TX;
+
ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
if (ret < 0) {
wl1251_error("tx %s cmd for channel %d failed",
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h
index 126f273..d824ff9 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.h
+++ b/drivers/net/wireless/ti/wl1251/cmd.h
@@ -35,7 +35,8 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
void *bitmap, u16 bitmap_len, u8 bitmap_control);
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable);
int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
u16 beacon_interval, u8 dtim_interval);
int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index a6ad223..424ce01 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -390,8 +390,13 @@ int wl1251_hw_init(struct wl1251 *wl)
if (ret < 0)
goto out_free_data_path;

- /* Enable data path */
- ret = wl1251_cmd_data_path(wl, wl->channel, 1);
+ /* Enable rx data path */
+ ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Enable tx data path */
+ ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1);
if (ret < 0)
goto out_free_data_path;

--
1.7.10.4


2013-10-26 20:40:34

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 09/16] wl1251: disable power saving in monitor mode

From: David Gnedt <[email protected]>

Force power saving off while monitor interface is present.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 727f2ee..62cb374 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -617,7 +617,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
goto out_sleep;
}

- if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+ if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested &&
+ !wl->monitor_present) {
wl1251_debug(DEBUG_PSM, "psm enabled");

wl->psm_requested = true;
@@ -633,8 +634,8 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
if (ret < 0)
goto out_sleep;
- } else if (!(conf->flags & IEEE80211_CONF_PS) &&
- wl->psm_requested) {
+ } else if ((!(conf->flags & IEEE80211_CONF_PS) || wl->monitor_present)
+ && wl->psm_requested) {
wl1251_debug(DEBUG_PSM, "psm disabled");

wl->psm_requested = false;
--
1.7.10.4


2013-10-30 11:47:40

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 10/16] wl1251: fix channel switching in monitor mode

On Sat 2013-10-26 22:34:09, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Use the ENABLE_RX command for channel switching when no interface is present
> (monitor mode only).
> The advantage of ENABLE_RX is that it leaves the tx data path disabled in
> firmware, whereas the usual JOIN command seems to transmit some frames at
> firmware level.
>
> Signed-off-by: David Gnedt <[email protected]>

Missing signoff, otherwise

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

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

2013-10-28 13:50:02

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Monday 28 October 2013 14:45:05 Johannes Berg wrote:
> On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > Driver wl1251 generating mac address randomly at startup and
> > there is no way to set permanent mac address via
> > SET_IEEE80211_PERM_ADDR. This patch export sysfs file which
> > can set permanent mac address by userspace helper program.
> > Patch is needed for devices which do not store mac address
> > in internal wl1251 eeprom.
>
> This doesn't really seem like a good idea since you can also
> just use 'ip' or whatever to set the MAC address.
>
> johannes

AFAIK you cannot set permanent address (show by ethtool -P wlan0)
via ip/ifconfig.

--
Pali Rohár
[email protected]


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

2013-10-26 20:40:39

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 14/16] wl1251: add nvs file name to module firmware list

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index f054741..7b9efc8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1709,3 +1709,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kalle Valo <[email protected]>");
MODULE_FIRMWARE(WL1251_FW_NAME);
+MODULE_FIRMWARE(WL1251_NVS_NAME);
--
1.7.10.4


2013-10-26 20:40:38

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 13/16] wl1251: enforce changed hw encryption support on monitor state change

From: David Gnedt <[email protected]>

The firmware doesn't support per packet encryption selection, so disable hw
encryption support completly while a monitor interface is present to support
injection of packets (which shouldn't get encrypted by hw).
To enforce the changed hw encryption support force a disassociation on
non-monitor interfaces.
For disassociation a workaround using hw connection monitor is employed,
which temporary enables hw connection manager flag.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 174f403..f054741 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -685,6 +685,16 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
wl->power_level = conf->power_level;
}

+ /*
+ * Tell stack that connection is lost because hw encryption isn't
+ * supported in monitor mode.
+ * XXX This requires temporary enabling the hw connection monitor flag
+ */
+ if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) {
+ wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;
+ ieee80211_connection_loss(wl->vif);
+ }
+
out_sleep:
wl1251_ps_elp_sleep(wl);

@@ -1116,6 +1126,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}

if (changed & BSS_CHANGED_ASSOC) {
+ /* XXX Disable temporary enabled hw connection monitor flag */
+ wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR;
+
if (bss_conf->assoc) {
wl->beacon_int = bss_conf->beacon_int;

--
1.7.10.4


2013-10-26 20:40:36

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 11/16] wl1251: enable tx path in monitor mode if necessary for packet injection

From: David Gnedt <[email protected]>

If necessary enable the tx path in monitor mode for packet injection using
the JOIN command with BSS_TYPE_STA_BSS and zero BSSID.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 5 +++++
drivers/net/wireless/ti/wl1251/tx.c | 17 +++++++++++++++++
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
3 files changed, 23 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 7e6b6d1..174f403 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -487,6 +487,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->rssi_thold = 0;
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->monitor_present = false;
+ wl->joined = false;

wl1251_debugfs_reset(wl);

@@ -546,6 +547,7 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
wl->vif = NULL;
+ memset(wl->bssid, 0, ETH_ALEN);
mutex_unlock(&wl->mutex);
}

@@ -619,6 +621,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
* at firmware level.
*/
if (wl->vif == NULL) {
+ wl->joined = false;
ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
} else {
ret = wl1251_join(wl, wl->bss_type, wl->channel,
@@ -1610,7 +1613,9 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->monitor_present = false;
+ wl->joined = false;
wl->scanning = false;
+ wl->bss_type = MAX_BSS_TYPE;
wl->default_key = 0;
wl->listen_int = 1;
wl->rx_counter = 0;
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 3cc82fd..1de4ccb 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -28,6 +28,7 @@
#include "tx.h"
#include "ps.h"
#include "io.h"
+#include "event.h"

static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
{
@@ -298,6 +299,22 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
}
}

+ /* Enable tx path in monitor mode for packet injection */
+ if ((wl->vif == NULL) && !wl->joined) {
+ ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel,
+ wl->beacon_int, wl->dtim_period);
+ if (ret < 0)
+ wl1251_warning("join failed");
+ else {
+ ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID,
+ 100);
+ if (ret < 0)
+ wl1251_warning("join timeout");
+ else
+ wl->joined = true;
+ }
+ }
+
ret = wl1251_tx_path_status(wl);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index e478e61..1bdf779 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -311,6 +311,7 @@ struct wl1251 {
u8 listen_int;
int channel;
bool monitor_present;
+ bool joined;

void *target_mem_map;
struct acx_data_path_params_resp *data_path;
--
1.7.10.4


2013-10-26 20:40:40

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 15/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate

This patch was extracted from Maemo 2.6.28 kernel

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 7b9efc8..29625c2 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1375,6 +1375,147 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_tx_mgmt_frm_rate(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+ int val;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ switch (wl->tx_mgmt_frm_rate) {
+ /* skip 1 and 12 Mbps because they have same value 0x0a */
+ case RATE_2MBPS:
+ val = 20;
+ break;
+ case RATE_5_5MBPS:
+ val = 55;
+ break;
+ case RATE_11MBPS:
+ val = 110;
+ break;
+ case RATE_6MBPS:
+ val = 60;
+ break;
+ case RATE_9MBPS:
+ val = 90;
+ break;
+ case RATE_12MBPS:
+ val = 120;
+ break;
+ case RATE_18MBPS:
+ val = 180;
+ break;
+ case RATE_24MBPS:
+ val = 240;
+ break;
+ case RATE_36MBPS:
+ val = 360;
+ break;
+ case RATE_48MBPS:
+ val = 480;
+ break;
+ case RATE_54MBPS:
+ val = 540;
+ break;
+ default:
+ val = 10;
+ }
+
+ /* for 1 and 12 Mbps we have to check the modulation */
+ if (wl->tx_mgmt_frm_rate == RATE_1MBPS) {
+ switch (wl->tx_mgmt_frm_rate) {
+ case CCK_LONG:
+ val = 10;
+ break;
+ case OFDM:
+ val = 120;
+ break;
+ default:
+ val = 10;
+ break;
+ }
+ }
+ len = snprintf(buf, len, "%d", val);
+
+ return len;
+}
+
+static ssize_t wl1251_sysfs_store_tx_mgmt_frm_rate(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned long res;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &res);
+
+ if (ret < 0) {
+ wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
+ return 0;
+ }
+
+ switch (res) {
+ case 10:
+ wl->tx_mgmt_frm_rate = RATE_1MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 20:
+ wl->tx_mgmt_frm_rate = RATE_2MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 55:
+ wl->tx_mgmt_frm_rate = RATE_5_5MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 110:
+ wl->tx_mgmt_frm_rate = RATE_11MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 60:
+ wl->tx_mgmt_frm_rate = RATE_6MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 90:
+ wl->tx_mgmt_frm_rate = RATE_9MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 120:
+ wl->tx_mgmt_frm_rate = RATE_12MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 180:
+ wl->tx_mgmt_frm_rate = RATE_18MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 240:
+ wl->tx_mgmt_frm_rate = RATE_24MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 360:
+ wl->tx_mgmt_frm_rate = RATE_36MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 480:
+ wl->tx_mgmt_frm_rate = RATE_48MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 540:
+ wl->tx_mgmt_frm_rate = RATE_54MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ default:
+ wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
+ return 0;
+ }
+
+ return count;
+}
+
static ssize_t wl1251_sysfs_show_bt_coex_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1443,6 +1584,10 @@ out:
return count;
}

+static DEVICE_ATTR(tx_mgmt_frm_rate, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_tx_mgmt_frm_rate,
+ wl1251_sysfs_store_tx_mgmt_frm_rate);
+
static DEVICE_ATTR(bt_coex_mode, S_IRUGO | S_IWUSR,
wl1251_sysfs_show_bt_coex_mode,
wl1251_sysfs_store_bt_coex_mode);
@@ -1583,6 +1728,13 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
}
dev_set_drvdata(&wl1251_device.dev, wl);

+ /* Create sysfs file tx_mgmt_frm_rate */
+ ret = device_create_file(&wl1251_device.dev,
+ &dev_attr_tx_mgmt_frm_rate);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file tx_mgmt_frm_rate");
+ goto out;
+ }

/* Create sysfs file to control bt coex state */
ret = device_create_file(&wl1251_device.dev, &dev_attr_bt_coex_mode);
--
1.7.10.4


2013-10-26 20:40:27

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

From: David Gnedt <[email protected]>

Port the bt_coex_mode sysfs interface from wl1251 driver version included
in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
This enables userspace applications to set one of the modes
WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
The default mode is WL1251_BT_COEX_OFF.
It should be noted that this driver always enabled bt-coexistence before
and enabled bt-coexistence directly affects the receiving performance,
rendering it unusable in some low-signal situations. Especially monitor
mode is affected very badly with bt-coexistence enabled.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 43 ++++++++++--
drivers/net/wireless/ti/wl1251/acx.h | 8 ++-
drivers/net/wireless/ti/wl1251/init.c | 6 +-
drivers/net/wireless/ti/wl1251/main.c | 108 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/wl1251.h | 8 +++
5 files changed, 161 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index db6430c..cce50e2 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -581,7 +581,7 @@ out:
return ret;
}

-int wl1251_acx_sg_enable(struct wl1251 *wl)
+int wl1251_acx_sg_enable(struct wl1251 *wl, u8 mode)
{
struct acx_bt_wlan_coex *pta;
int ret;
@@ -594,7 +594,7 @@ int wl1251_acx_sg_enable(struct wl1251 *wl)
goto out;
}

- pta->enable = SG_ENABLE;
+ pta->enable = mode;

ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
if (ret < 0) {
@@ -607,7 +607,7 @@ out:
return ret;
}

-int wl1251_acx_sg_cfg(struct wl1251 *wl)
+int wl1251_acx_sg_cfg(struct wl1251 *wl, u16 wake_up_beacon)
{
struct acx_bt_wlan_coex_param *param;
int ret;
@@ -632,7 +632,7 @@ int wl1251_acx_sg_cfg(struct wl1251 *wl)
param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
- param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+ param->wake_up_beacon = wake_up_beacon;
param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
param->antenna_type = PTA_ANTENNA_TYPE_DEF;
@@ -661,6 +661,41 @@ out:
return ret;
}

+int wl1251_acx_sg_configure(struct wl1251 *wl, bool force)
+{
+ int ret;
+
+ if (wl->state == WL1251_STATE_OFF && !force)
+ return 0;
+
+ switch (wl->bt_coex_mode) {
+ case WL1251_BT_COEX_OFF:
+ ret = wl1251_acx_sg_enable(wl, SG_DISABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, 0);
+ break;
+ case WL1251_BT_COEX_ENABLE:
+ ret = wl1251_acx_sg_enable(wl, SG_ENABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, PTA_TIME_BEFORE_BEACON_DEF);
+ break;
+ case WL1251_BT_COEX_MONOAUDIO:
+ ret = wl1251_acx_sg_enable(wl, SG_ENABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, PTA_TIME_BEFORE_BEACON_MONO_AUDIO);
+ break;
+ default:
+ wl1251_error("Invalid BT co-ex mode!");
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
int wl1251_acx_cca_threshold(struct wl1251 *wl)
{
struct acx_energy_detection *detection;
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index c2ba100..99ea80e 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -558,7 +558,8 @@ struct acx_bt_wlan_coex {
#define PTA_ANTI_STARVE_PERIOD_DEF (500)
#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4)
#define PTA_ALLOW_PA_SD_DEF (1)
-#define PTA_TIME_BEFORE_BEACON_DEF (6300)
+#define PTA_TIME_BEFORE_BEACON_DEF (500)
+#define PTA_TIME_BEFORE_BEACON_MONO_AUDIO (6300)
#define PTA_HPDM_MAX_TIME_DEF (1600)
#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550)
#define PTA_AUTO_MODE_NO_CTS_DEF (0)
@@ -1455,8 +1456,9 @@ int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
int wl1251_acx_conn_monit_params(struct wl1251 *wl);
-int wl1251_acx_sg_enable(struct wl1251 *wl);
-int wl1251_acx_sg_cfg(struct wl1251 *wl);
+int wl1251_acx_sg_enable(struct wl1251 *wl, u8 mode);
+int wl1251_acx_sg_cfg(struct wl1251 *wl, u16 wake_up_beacon);
+int wl1251_acx_sg_configure(struct wl1251 *wl, bool force);
int wl1251_acx_cca_threshold(struct wl1251 *wl);
int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 89b43d3..a6ad223 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -162,11 +162,7 @@ int wl1251_hw_init_pta(struct wl1251 *wl)
{
int ret;

- ret = wl1251_acx_sg_enable(wl);
- if (ret < 0)
- return ret;
-
- ret = wl1251_acx_sg_cfg(wl);
+ ret = wl1251_acx_sg_configure(wl, true);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 4d89ac8..ad2fd18 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -27,6 +27,7 @@
#include <linux/crc32.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>

#include "wl1251.h"
@@ -1256,6 +1257,94 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_bt_coex_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ mutex_lock(&wl->mutex);
+ len = snprintf(buf, len, "%d\n\n%d - off\n%d - on\n%d - monoaudio\n",
+ wl->bt_coex_mode,
+ WL1251_BT_COEX_OFF,
+ WL1251_BT_COEX_ENABLE,
+ WL1251_BT_COEX_MONOAUDIO);
+ mutex_unlock(&wl->mutex);
+
+ return len;
+
+}
+
+static ssize_t wl1251_sysfs_store_bt_coex_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned long res;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &res);
+
+ if (ret < 0) {
+ wl1251_warning("incorrect value written to bt_coex_mode");
+ return count;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ if (res == wl->bt_coex_mode)
+ goto out;
+
+ switch (res) {
+ case WL1251_BT_COEX_OFF:
+ case WL1251_BT_COEX_ENABLE:
+ case WL1251_BT_COEX_MONOAUDIO:
+ wl->bt_coex_mode = res;
+ break;
+ default:
+ wl1251_warning("incorrect value written to bt_coex_mode");
+ goto out;
+ }
+
+ if (wl->state == WL1251_STATE_OFF)
+ goto out;
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1251_acx_sg_configure(wl, false);
+ wl1251_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static DEVICE_ATTR(bt_coex_mode, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_bt_coex_mode,
+ wl1251_sysfs_store_bt_coex_mode);
+
+static void wl1251_device_release(struct device *dev)
+{
+
+}
+
+static struct platform_device wl1251_device = {
+ /* FIXME: use wl12xx name to not break the user space */
+ .name = "wl12xx",
+ .id = -1,
+
+ /* device model insists to have a release function */
+ .dev = {
+ .release = wl1251_device_release,
+ },
+};
+
static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
{
unsigned long timeout;
@@ -1368,6 +1457,22 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
if (ret)
goto out;

+ /* Register platform device */
+ ret = platform_device_register(&wl1251_device);
+ if (ret) {
+ wl1251_error("couldn't register platform device");
+ goto out;
+ }
+ dev_set_drvdata(&wl1251_device.dev, wl);
+
+
+ /* Create sysfs file to control bt coex state */
+ ret = device_create_file(&wl1251_device.dev, &dev_attr_bt_coex_mode);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file bt_coex_mode");
+ goto out;
+ }
+
wl1251_debugfs_init(wl);
wl1251_notice("initialized");

@@ -1420,6 +1525,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
wl->vif = NULL;
+ wl->bt_coex_mode = WL1251_BT_COEX_OFF;

for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
wl->tx_frames[i] = NULL;
@@ -1459,6 +1565,8 @@ int wl1251_free_hw(struct wl1251 *wl)

wl1251_debugfs_exit(wl);

+ platform_device_unregister(&wl1251_device);
+
kfree(wl->target_mem_map);
kfree(wl->data_path);
vfree(wl->fw);
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index fd02060..724c9f9 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -257,6 +257,12 @@ struct wl1251_debugfs {
struct dentry *excessive_retries;
};

+enum wl1251_bt_coex_mode {
+ WL1251_BT_COEX_OFF,
+ WL1251_BT_COEX_ENABLE,
+ WL1251_BT_COEX_MONOAUDIO
+};
+
struct wl1251_if_operations {
void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
@@ -386,6 +392,8 @@ struct wl1251 {

struct ieee80211_vif *vif;

+ enum wl1251_bt_coex_mode bt_coex_mode;
+
u32 chip_id;
char fw_ver[21];

--
1.7.10.4


2013-10-30 11:24:07

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 02/16] wl1251: fix scan behaviour while not associated

On Sat 2013-10-26 22:34:01, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> With a dissacociated card I often encoutered very long scan delays.
>
> My guess is that it has something to do with the cards DTIM handling and
> another firmware bug mentioned in the TI WLAN driver, which is described as
> the card may never end scanning if the channel is overloaded because it
> can't send probe requests. I think the firmware somehow also tries to
> receive DTIM messages when the BSSID is not set. Therefore most of the time
> it waits for DTIM messages and can't do scanning work.
>
> Anyway we can workaround this misbehaviour by setting the HIGH_PRIORITY
> bit for scans in disassociated state.
>
> Signed-off-by: David Gnedt <[email protected]>

I guess you should add your Signed-off-by: here (as you are sending
the patch forward).

Other than that:

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

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

2013-10-30 11:52:53

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 12/16] wl1251: disable retry and ACK policy for injected packets

On Sat 2013-10-26 22:34:11, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Set the retry limit to 0 and disable the ACK policy for injected packets.
>
> Signed-off-by: David Gnedt <[email protected]>

Missing sign-off, otherwise ok:

Reviewed-by: Pavel Machek <[email protected]>
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2013-10-28 15:33:28

by Stephen Hemminger

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Mon, 28 Oct 2013 15:56:55 +0100
Johannes Berg <[email protected]> wrote:

> On Mon, 2013-10-28 at 09:46 -0500, Dan Williams wrote:
>
> > If the device doesn't actually *have* a permanent MAC address, then it
> > shouldn't be returning one via ethtool, and should return an error for
> > ETHTOOL_GPERMADDR.
>
> There's currently no provision for that, but I agree it would be better
> to do so.
>
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

The current netdevice API handle the case of a device without a permanent
MAC address, slightly differently.

If device does not have a permanent address,
then:
1. dev->addr_assign_type should not be NET_ADDR_PERM
2. when device is registered dev->perm_addr will not be set
and retain all zeros value
4. when ethtool gets address it will return all zeros which
is not a valid address.

This case doesn't seem to be handled threo mac80211 API's




2013-10-28 15:04:52

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Monday 28 October 2013 15:56:55 Johannes Berg wrote:
> On Mon, 2013-10-28 at 09:46 -0500, Dan Williams wrote:
> > If the device doesn't actually *have* a permanent MAC
> > address, then it shouldn't be returning one via ethtool,
> > and should return an error for ETHTOOL_GPERMADDR.
>
> There's currently no provision for that, but I agree it would
> be better to do so.
>
> johannes

So what to do with devices which has MAC address stored in some
obscure place and there is userspace binary which can read it?

I think that there should be some way to tell kernel that *this*
is the permanent address and it should use it.

This is reason why I proposed patch which adding sysfs entry for
setting permanent address from userspace in wl1251 driver.

--
Pali Rohár
[email protected]


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

2013-10-28 13:47:47

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 01/16] mac80211: fix TX device statistics for monitor interfaces

On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:

> + dev->stats.tx_packets++;
> + dev->stats.tx_bytes += skb->len;

We can still easily drop the packet after this - we can't guarantee
it'll go out but maybe we shouldn't do it here?

johannes


2013-10-26 20:40:29

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 05/16] wl1251: implement hardware ARP filtering

From: David Gnedt <[email protected]>

Update hardware ARP filter configuration on BSS_CHANGED_ARP_FILTER
notification from mac80211.
Ported from wl1271 driver.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 31 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/acx.h | 15 +++++++++++++++
drivers/net/wireless/ti/wl1251/main.c | 13 +++++++++++++
3 files changed, 59 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index cce50e2..9295090 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -1062,6 +1062,37 @@ out:
return ret;
}

+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
+{
+ struct wl1251_acx_arp_filter *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->version = ACX_IPV4_VERSION;
+ acx->enable = enable;
+
+ if (enable == true)
+ memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
+
+ ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
+ acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1251_warning("failed to set arp ip filter: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
u8 aifs, u16 txop)
{
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 99ea80e..4444cd0 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -1233,6 +1233,20 @@ struct wl1251_acx_bet_enable {
u8 padding[2];
} __packed;

+#define ACX_IPV4_VERSION 4
+#define ACX_IPV6_VERSION 6
+#define ACX_IPV4_ADDR_SIZE 4
+struct wl1251_acx_arp_filter {
+ struct acx_header header;
+ u8 version; /* The IP version: 4 - IPv4, 6 - IPv6.*/
+ u8 enable; /* 1 - ARP filtering is enabled, 0 - disabled */
+ u8 padding[2];
+ u8 address[16]; /* The IP address used to filter ARP packets.
+ ARP packets that do not match this address are
+ dropped. When the IP Version is 4, the last 12
+ bytes of the the address are ignored. */
+} __attribute__((packed));
+
struct wl1251_acx_ac_cfg {
struct acx_header header;

@@ -1475,6 +1489,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl);
int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
u8 max_consecutive);
+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address);
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
u8 aifs, u16 txop);
int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 46a2494..9752745 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1078,6 +1078,19 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}
}

+ if (changed & BSS_CHANGED_ARP_FILTER) {
+ __be32 addr = bss_conf->arp_addr_list[0];
+ WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
+
+ if (bss_conf->arp_addr_cnt == 1 && bss_conf->assoc)
+ ret = wl1251_acx_arp_ip_filter(wl, true, addr);
+ else
+ ret = wl1251_acx_arp_ip_filter(wl, false, addr);
+
+ if (ret < 0)
+ goto out_sleep;
+ }
+
if (changed & BSS_CHANGED_BEACON) {
beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
--
1.7.10.4


2013-10-28 13:46:01

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 15/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate

On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> This patch was extracted from Maemo 2.6.28 kernel

That's not a description or justification for the patch ....

but again, it seems like a bad idea to use sysfs.

johannes


2013-10-28 05:53:53

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 01/16] mac80211: fix TX device statistics for monitor interfaces

Pali Rohár <[email protected]> writes:

> From: David Gnedt <[email protected]>
>
> Count TX packets and bytes also for monitor interfaces.
>
> Signed-of-by: David Gnedt <[email protected]>

You should send mac80211 patches separately, not inside a wl1251 patchset.

--
Kalle Valo

2013-10-28 13:55:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Mon, 2013-10-28 at 14:49 +0100, Pali Rohár wrote:
> On Monday 28 October 2013 14:45:05 Johannes Berg wrote:
> > On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > > Driver wl1251 generating mac address randomly at startup and
> > > there is no way to set permanent mac address via
> > > SET_IEEE80211_PERM_ADDR. This patch export sysfs file which
> > > can set permanent mac address by userspace helper program.
> > > Patch is needed for devices which do not store mac address
> > > in internal wl1251 eeprom.
> >
> > This doesn't really seem like a good idea since you can also
> > just use 'ip' or whatever to set the MAC address.
> >
> > johannes
>
> AFAIK you cannot set permanent address (show by ethtool -P wlan0)
> via ip/ifconfig.

You probably can't, but that address also doesn't matter at all and
isn't really used anywhere.

johannes



2013-10-28 13:45:18

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> Driver wl1251 generating mac address randomly at startup and there is no way to
> set permanent mac address via SET_IEEE80211_PERM_ADDR. This patch export sysfs
> file which can set permanent mac address by userspace helper program. Patch is
> needed for devices which do not store mac address in internal wl1251 eeprom.

This doesn't really seem like a good idea since you can also just use
'ip' or whatever to set the MAC address.

johannes


2013-10-26 20:40:26

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 02/16] wl1251: fix scan behaviour while not associated

From: David Gnedt <[email protected]>

With a dissacociated card I often encoutered very long scan delays.

My guess is that it has something to do with the cards DTIM handling and
another firmware bug mentioned in the TI WLAN driver, which is described as
the card may never end scanning if the channel is overloaded because it
can't send probe requests. I think the firmware somehow also tries to
receive DTIM messages when the BSSID is not set. Therefore most of the time
it waits for DTIM messages and can't do scanning work.

Anyway we can workaround this misbehaviour by setting the HIGH_PRIORITY
bit for scans in disassociated state.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/cmd.c | 13 ++++++++++++-
drivers/net/wireless/ti/wl1251/cmd.h | 5 +++++
drivers/net/wireless/ti/wl1251/main.c | 1 +
3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 6822b84..16b6479 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/crc7.h>
+#include <linux/etherdevice.h>

#include "wl1251.h"
#include "reg.h"
@@ -410,7 +411,10 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
struct wl1251_cmd_scan *cmd;
int i, ret = 0;

- wl1251_debug(DEBUG_CMD, "cmd scan");
+ wl1251_debug(DEBUG_CMD, "cmd scan channels %d ssid(%d) '%s'",
+ n_channels, ssid_len, ssid);
+
+ WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
@@ -421,6 +425,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
CFG_RX_MGMT_EN |
CFG_RX_BCN_EN);
cmd->params.scan_options = 0;
+ /*
+ * Use high priority scan when not associated to prevent fw issue
+ * causing never-ending scans (sometimes 20+ minutes).
+ * Note: This bug may be caused by the fw's DTIM handling.
+ */
+ if (is_zero_ether_addr(wl->bssid))
+ cmd->params.scan_options |= WL1251_SCAN_OPT_PRIORITY_HIGH;
cmd->params.num_channels = n_channels;
cmd->params.num_probe_requests = n_probes;
cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h
index ee4f2b3..126f273 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.h
+++ b/drivers/net/wireless/ti/wl1251/cmd.h
@@ -167,6 +167,11 @@ struct cmd_read_write_memory {
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4

+#define WL1251_SCAN_OPT_PASSIVE 1
+#define WL1251_SCAN_OPT_5GHZ_BAND 2
+#define WL1251_SCAN_OPT_TRIGGERD_SCAN 4
+#define WL1251_SCAN_OPT_PRIORITY_HIGH 8
+
#define WL1251_SCAN_MIN_DURATION 30000
#define WL1251_SCAN_MAX_DURATION 60000

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 3291ffa..4d89ac8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -930,6 +930,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
req->n_channels, WL1251_SCAN_NUM_PROBES);
if (ret < 0) {
+ wl1251_debug(DEBUG_SCAN, "scan failed %d", ret);
wl->scanning = false;
goto out_idle;
}
--
1.7.10.4


2013-10-29 13:35:32

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

Luca Coelho <[email protected]> writes:

> On Mon, 2013-10-28 at 23:39 +0000, Ben Hutchings wrote:
>> On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
>> > From: David Gnedt <[email protected]>
>> >
>> > Port the bt_coex_mode sysfs interface from wl1251 driver version included
>> > in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
>> > This enables userspace applications to set one of the modes
>> > WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
>> > The default mode is WL1251_BT_COEX_OFF.
>> > It should be noted that this driver always enabled bt-coexistence before
>> > and enabled bt-coexistence directly affects the receiving performance,
>> > rendering it unusable in some low-signal situations. Especially monitor
>> > mode is affected very badly with bt-coexistence enabled.
>> [...]
>>
>> This should be implemented consistently with other drivers:
>>
>> drivers/net/wireless/ath/ath9k/htc_drv_init.c:module_param_named(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
>> drivers/net/wireless/ath/ath9k/init.c:module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
>> drivers/net/wireless/b43/main.c:module_param_named(btcoex, modparam_btcoex, int, 0444);
>> drivers/net/wireless/ipw2x00/ipw2200.c:module_param(bt_coexist, int, 0444);
>> drivers/net/wireless/iwlegacy/common.c:module_param(bt_coex_active, bool, S_IRUGO);
>> drivers/net/wireless/iwlwifi/iwl-drv.c:module_param_named(bt_coex_active, iwlwifi_mod_params.bt_coex_active,
>> drivers/net/wireless/ti/wlcore/sysfs.c:static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,
>>
>> Oh, hmm, I see a problem here.
>
> With so many drivers doing the same thing, isn't it about time to add
> this to nl80211?

Yes, this really needs to be in nl80211. I even suggested this years ago
but was turned down at the time. Can't remember the reason anymore.

--
Kalle Valo

2013-10-26 20:40:32

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 07/16] wl1251: configure hardware en-/decryption for monitor mode

From: David Gnedt <[email protected]>

Disable hardware encryption (DF_ENCRYPTION_DISABLE) and decryption
(DF_SNIFF_MODE_ENABLE) via wl1251_acx_feature_cfg while monitor interface is
present.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 6 +++---
drivers/net/wireless/ti/wl1251/acx.h | 2 +-
drivers/net/wireless/ti/wl1251/init.c | 2 +-
drivers/net/wireless/ti/wl1251/main.c | 34 ++++++++++++++++++++++++++-----
drivers/net/wireless/ti/wl1251/rx.c | 2 +-
drivers/net/wireless/ti/wl1251/tx.c | 3 +++
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
7 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 9295090..e79636f 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -209,7 +209,7 @@ out:
return ret;
}

-int wl1251_acx_feature_cfg(struct wl1251 *wl)
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
{
struct acx_feature_config *feature;
int ret;
@@ -222,8 +222,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl)
goto out;
}

- /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
- feature->data_flow_options = 0;
+ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
+ feature->data_flow_options = data_flow_options;
feature->options = 0;

ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 4444cd0..bea2e67 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -1455,7 +1455,7 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
int wl1251_acx_tx_power(struct wl1251 *wl, int power);
-int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options);
int wl1251_acx_mem_map(struct wl1251 *wl,
struct acx_header *mem_map, size_t len);
int wl1251_acx_data_path_params(struct wl1251 *wl,
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 424ce01..92de289 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -33,7 +33,7 @@ int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
{
int ret;

- ret = wl1251_acx_feature_cfg(wl);
+ ret = wl1251_acx_feature_cfg(wl, 0);
if (ret < 0) {
wl1251_warning("couldn't set feature config");
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 9752745..c6e2591 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -485,6 +485,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;

wl1251_debugfs_reset(wl);

@@ -577,8 +578,10 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
channel = ieee80211_frequency_to_channel(
conf->chandef.chan->center_freq);

- wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+ wl1251_debug(DEBUG_MAC80211,
+ "mac80211 config ch %d monitor %s psm %s power %d",
channel,
+ conf->flags & IEEE80211_CONF_MONITOR ? "on" : "off",
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
conf->power_level);

@@ -588,6 +591,22 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
if (ret < 0)
goto out;

+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ u32 mode;
+
+ if (conf->flags & IEEE80211_CONF_MONITOR) {
+ wl->monitor_present = true;
+ mode = DF_SNIFF_MODE_ENABLE | DF_ENCRYPTION_DISABLE;
+ } else {
+ wl->monitor_present = false;
+ mode = 0;
+ }
+
+ ret = wl1251_acx_feature_cfg(wl, mode);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
if (channel != wl->channel) {
wl->channel = channel;

@@ -804,12 +823,12 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

mutex_lock(&wl->mutex);

- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out_unlock;
-
switch (cmd) {
case SET_KEY:
+ if (wl->monitor_present) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
wl_cmd->key_action = KEY_ADD_OR_REPLACE;
break;
case DISABLE_KEY:
@@ -820,6 +839,10 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
}

+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
if (ret < 0) {
wl1251_error("Set KEY type failed");
@@ -1521,6 +1544,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)

INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;
wl->scanning = false;
wl->default_key = 0;
wl->listen_int = 1;
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c
index 23289d4..123c4bb 100644
--- a/drivers/net/wireless/ti/wl1251/rx.c
+++ b/drivers/net/wireless/ti/wl1251/rx.c
@@ -83,7 +83,7 @@ static void wl1251_rx_status(struct wl1251 *wl,

status->flag |= RX_FLAG_MACTIME_START;

- if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
+ if (!wl->monitor_present && (desc->flags & RX_DESC_ENCRYPTION_MASK)) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;

if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 28121c5..3cc82fd 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -287,6 +287,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);

if (info->control.hw_key) {
+ if (unlikely(wl->monitor_present))
+ return -1;
+
idx = info->control.hw_key->hw_key_idx;
if (unlikely(wl->default_key != idx)) {
ret = wl1251_acx_default_key(wl, idx);
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 7cd1bac..750e510 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -309,6 +309,7 @@ struct wl1251 {
u8 bss_type;
u8 listen_int;
int channel;
+ bool monitor_present;

void *target_mem_map;
struct acx_data_path_params_resp *data_path;
--
1.7.10.4


2013-10-30 11:31:30

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 06/16] wl1251: split RX and TX data path initialisation

Hi!

> Split up data path initialisation into RX and TX data path initialisation
> functions. This change is required for channel switching in monitor mode.
>
> Signed-off-by: David Gnedt <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/cmd.c | 37 ++++++++++++++++++++++++++-------
> drivers/net/wireless/ti/wl1251/cmd.h | 3 ++-
> drivers/net/wireless/ti/wl1251/init.c | 9 ++++++--
> 3 files changed, 39 insertions(+), 10 deletions(-)
>
> @@ -238,6 +235,32 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
> wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
> enable ? "start" : "stop", channel);
>
> +out:
> + kfree(cmd);
> + return ret;
> +}
> +
> +int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
> +{
> + struct cmd_enabledisable_path *cmd;
> + int ret;
> + u16 cmd_tx;
> +
> + wl1251_debug(DEBUG_CMD, "cmd data path");
> +
> + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
> + if (!cmd) {
> + ret = -ENOMEM;
> + goto out;
> + }

Again, doing jump just to kfree(NULL)... is probably not worth
it.

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

2013-10-28 14:46:54

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Mon, 2013-10-28 at 15:00 +0100, Pali Rohár wrote:
> On Monday 28 October 2013 14:55:22 Johannes Berg wrote:
> > On Mon, 2013-10-28 at 14:49 +0100, Pali Rohár wrote:
> > > On Monday 28 October 2013 14:45:05 Johannes Berg wrote:
> > > > On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > > > > Driver wl1251 generating mac address randomly at startup
> > > > > and there is no way to set permanent mac address via
> > > > > SET_IEEE80211_PERM_ADDR. This patch export sysfs file
> > > > > which can set permanent mac address by userspace helper
> > > > > program. Patch is needed for devices which do not store
> > > > > mac address in internal wl1251 eeprom.
> > > >
> > > > This doesn't really seem like a good idea since you can
> > > > also just use 'ip' or whatever to set the MAC address.
> > > >
> > > > johannes
> > >
> > > AFAIK you cannot set permanent address (show by ethtool -P
> > > wlan0) via ip/ifconfig.
> >
> > You probably can't, but that address also doesn't matter at
> > all and isn't really used anywhere.
> >
> > johannes
>
> There are some (proprietary) applications which using permanent
> address for something...
>
> And also more important: some network managing tools using it.
> NetworkManager resetting current MAC address to permanent one
> before starting configuring interface.
>
> So this will lead to never use correct MAC address (but random
> permanent one) assigned for that wl1251 wireless card...

If the device doesn't actually *have* a permanent MAC address, then it
shouldn't be returning one via ethtool, and should return an error for
ETHTOOL_GPERMADDR. Setting the permanent MAC address shouldn't ever be
allowed except by the driver inspecting EEPROM, and certainly not via
sysfs.

mac80211 does have to do some special stuff due to virtual interfaces
and such, but in general, if the MAC address is randomly generated,
neither the driver nor mac80211 should be reporting that address as the
permanent address, only as the current one.

Dan



2013-10-30 11:41:45

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 08/16] wl1251: implement multicast address filtering

Hi!

> Port multicast address filtering from wl1271 driver.
> It sets up the hardware multicast address filter in configure_filter() with
> addresses supplied through prepare_multicast().

> +static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
> + struct netdev_hw_addr_list *mc_list)
> +{
> + struct wl1251_filter_params *fp;
> + struct netdev_hw_addr *ha;
> + struct wl1251 *wl = hw->priv;
> +
> + if (unlikely(wl->state == WL1251_STATE_OFF))
> + return 0;
> +
> + fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
> + if (!fp) {
> + wl1251_error("Out of memory setting filters.");
> + return 0;
> + }

So if there's not enough memory, we return 0.

> + /* update multicast filtering parameters */
> + fp->mc_list_length = 0;
> + if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
> + fp->enabled = false;
> + } else {
> + fp->enabled = true;
> + netdev_hw_addr_list_for_each(ha, mc_list) {
> + memcpy(fp->mc_list[fp->mc_list_length],
> + ha->addr, ETH_ALEN);
> + fp->mc_list_length++;
> + }
> + }
> +
> + return (u64)(unsigned long)fp;
> +}

Hiding pointers into u64 is not exactly nice, but I guess that's how
interface is designed? :-(.

> @@ -737,6 +779,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
> if (ret < 0)
> goto out;
>
> + if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
> + ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
> + else if (fp)
> + ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
> + fp->mc_list,
> + fp->mc_list_length);

Is it correct not to call anything in !fp case (for example because we
were out of memory?)

> + if (ret < 0)
> + goto out;
> +
> /* send filters to firmware */
> wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
>
> @@ -744,6 +795,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
>
> out:
> mutex_unlock(&wl->mutex);
> + kfree(fp);
> }

Umm, this is interesting. Who frees the memory in the success case?

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

2013-10-26 20:40:33

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 08/16] wl1251: implement multicast address filtering

From: David Gnedt <[email protected]>

Port multicast address filtering from wl1271 driver.
It sets up the hardware multicast address filter in configure_filter() with
addresses supplied through prepare_multicast().

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 9 ++---
drivers/net/wireless/ti/wl1251/acx.h | 9 ++---
drivers/net/wireless/ti/wl1251/init.c | 2 +-
drivers/net/wireless/ti/wl1251/main.c | 57 +++++++++++++++++++++++++++++--
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
5 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index e79636f..14da6de 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -408,7 +408,8 @@ out:
return ret;
}

-int wl1251_acx_group_address_tbl(struct wl1251 *wl)
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+ void *mc_list, u32 mc_list_len)
{
struct acx_dot11_grp_addr_tbl *acx;
int ret;
@@ -422,9 +423,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
}

/* MAC filtering */
- acx->enabled = 0;
- acx->num_groups = 0;
- memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+ acx->enabled = enable;
+ acx->num_groups = mc_list_len;
+ memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);

ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
acx, sizeof(*acx));
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index bea2e67..820573c 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -350,8 +350,8 @@ struct acx_slot {
} __packed;


-#define ADDRESS_GROUP_MAX (8)
-#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
+#define ACX_MC_ADDRESS_GROUP_MAX (8)
+#define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)

struct acx_dot11_grp_addr_tbl {
struct acx_header header;
@@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
u8 enabled;
u8 num_groups;
u8 pad[2];
- u8 mac_table[ADDRESS_GROUP_MAX_LEN];
+ u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
} __packed;


@@ -1464,7 +1464,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
int wl1251_acx_pd_threshold(struct wl1251 *wl);
int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
-int wl1251_acx_group_address_tbl(struct wl1251 *wl);
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+ void *mc_list, u32 mc_list_len);
int wl1251_acx_service_period_timeout(struct wl1251 *wl);
int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 92de289..f8a2ea9 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
if (ret < 0)
return ret;

- ret = wl1251_acx_group_address_tbl(wl);
+ ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index c6e2591..727f2ee 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -29,6 +29,7 @@
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/netdevice.h>

#include "wl1251.h"
#include "wl12xx_80211.h"
@@ -678,6 +679,44 @@ out:
return ret;
}

+struct wl1251_filter_params {
+ bool enabled;
+ int mc_list_length;
+ u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
+static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list)
+{
+ struct wl1251_filter_params *fp;
+ struct netdev_hw_addr *ha;
+ struct wl1251 *wl = hw->priv;
+
+ if (unlikely(wl->state == WL1251_STATE_OFF))
+ return 0;
+
+ fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
+ if (!fp) {
+ wl1251_error("Out of memory setting filters.");
+ return 0;
+ }
+
+ /* update multicast filtering parameters */
+ fp->mc_list_length = 0;
+ if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
+ fp->enabled = false;
+ } else {
+ fp->enabled = true;
+ netdev_hw_addr_list_for_each(ha, mc_list) {
+ memcpy(fp->mc_list[fp->mc_list_length],
+ ha->addr, ETH_ALEN);
+ fp->mc_list_length++;
+ }
+ }
+
+ return (u64)(unsigned long)fp;
+}
+
#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_FCSFAIL | \
@@ -688,8 +727,9 @@ out:

static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
- unsigned int *total,u64 multicast)
+ unsigned int *total, u64 multicast)
{
+ struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
struct wl1251 *wl = hw->priv;
int ret;

@@ -698,9 +738,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
*total &= WL1251_SUPPORTED_FILTERS;
changed &= WL1251_SUPPORTED_FILTERS;

- if (changed == 0)
+ if (changed == 0) {
/* no filters which we support changed */
+ kfree(fp);
return;
+ }

mutex_lock(&wl->mutex);

@@ -737,6 +779,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
if (ret < 0)
goto out;

+ if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
+ ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
+ else if (fp)
+ ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
+ fp->mc_list,
+ fp->mc_list_length);
+ if (ret < 0)
+ goto out;
+
/* send filters to firmware */
wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);

@@ -744,6 +795,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,

out:
mutex_unlock(&wl->mutex);
+ kfree(fp);
}

/* HW encryption */
@@ -1284,6 +1336,7 @@ static const struct ieee80211_ops wl1251_ops = {
.add_interface = wl1251_op_add_interface,
.remove_interface = wl1251_op_remove_interface,
.config = wl1251_op_config,
+ .prepare_multicast = wl1251_op_prepare_multicast,
.configure_filter = wl1251_op_configure_filter,
.tx = wl1251_op_tx,
.set_key = wl1251_op_set_key,
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 750e510..e478e61 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -93,6 +93,7 @@ enum {
} while (0)

#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
+ CFG_MC_FILTER_EN | \
CFG_BSSID_FILTER_EN)

#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \
--
1.7.10.4


2013-10-28 14:00:27

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Monday 28 October 2013 14:55:22 Johannes Berg wrote:
> On Mon, 2013-10-28 at 14:49 +0100, Pali Rohár wrote:
> > On Monday 28 October 2013 14:45:05 Johannes Berg wrote:
> > > On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > > > Driver wl1251 generating mac address randomly at startup
> > > > and there is no way to set permanent mac address via
> > > > SET_IEEE80211_PERM_ADDR. This patch export sysfs file
> > > > which can set permanent mac address by userspace helper
> > > > program. Patch is needed for devices which do not store
> > > > mac address in internal wl1251 eeprom.
> > >
> > > This doesn't really seem like a good idea since you can
> > > also just use 'ip' or whatever to set the MAC address.
> > >
> > > johannes
> >
> > AFAIK you cannot set permanent address (show by ethtool -P
> > wlan0) via ip/ifconfig.
>
> You probably can't, but that address also doesn't matter at
> all and isn't really used anywhere.
>
> johannes

There are some (proprietary) applications which using permanent
address for something...

And also more important: some network managing tools using it.
NetworkManager resetting current MAC address to permanent one
before starting configuring interface.

So this will lead to never use correct MAC address (but random
permanent one) assigned for that wl1251 wireless card...

--
Pali Rohár
[email protected]


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

2013-10-30 11:55:43

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 14/16] wl1251: add nvs file name to module firmware list

On Sat 2013-10-26 22:34:13, Pali Roh?r wrote:
> Signed-off-by: Pali Roh?r <[email protected]>

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

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

2013-10-28 15:30:25

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Mon, 2013-10-28 at 16:04 +0100, Pali Rohár wrote:
> On Monday 28 October 2013 15:56:55 Johannes Berg wrote:
> > On Mon, 2013-10-28 at 09:46 -0500, Dan Williams wrote:
> > > If the device doesn't actually *have* a permanent MAC
> > > address, then it shouldn't be returning one via ethtool,
> > > and should return an error for ETHTOOL_GPERMADDR.
> >
> > There's currently no provision for that, but I agree it would
> > be better to do so.
> >
> > johannes
>
> So what to do with devices which has MAC address stored in some
> obscure place and there is userspace binary which can read it?
>
> I think that there should be some way to tell kernel that *this*
> is the permanent address and it should use it.
>
> This is reason why I proposed patch which adding sysfs entry for
> setting permanent address from userspace in wl1251 driver.

Ok, so the N900's MAC is stored in the "cal partition", which is a
region of flash exposed to the OS as /dev/mtd1. That also stores the
regulatory domain. Typically userspace binaries are used to pull out
this and other data (see
https://dev.openwrt.org/browser/packages/utils/calvaria/files/src/calvaria.c ) which is then used to initialize the device.

Any idea what kernel driver is used to expose the CAL partition
as /dev/mtd1? If it's nothing special maybe a small EEPROM-style driver
could be written to read the relevant areas (and since they don't ever
change, don't need to worry about something else writing at the same
time).

Dan



2013-10-26 20:40:25

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 01/16] mac80211: fix TX device statistics for monitor interfaces

From: David Gnedt <[email protected]>

Count TX packets and bytes also for monitor interfaces.

Signed-of-by: David Gnedt <[email protected]>
---
net/mac80211/tx.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3456c04..674db8e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1593,6 +1593,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (unlikely(skb->len < len_rthdr))
goto fail; /* skb too short for claimed rt header extent */

+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
--
1.7.10.4


2013-10-28 16:21:29

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

On Monday 28 October 2013 16:29:21 Dan Williams wrote:
> On Mon, 2013-10-28 at 16:04 +0100, Pali Rohár wrote:
> > On Monday 28 October 2013 15:56:55 Johannes Berg wrote:
> > > On Mon, 2013-10-28 at 09:46 -0500, Dan Williams wrote:
> > > > If the device doesn't actually *have* a permanent MAC
> > > > address, then it shouldn't be returning one via ethtool,
> > > > and should return an error for ETHTOOL_GPERMADDR.
> > >
> > > There's currently no provision for that, but I agree it
> > > would be better to do so.
> > >
> > > johannes
> >
> > So what to do with devices which has MAC address stored in
> > some obscure place and there is userspace binary which can
> > read it?
> >
> > I think that there should be some way to tell kernel that
> > *this* is the permanent address and it should use it.
> >
> > This is reason why I proposed patch which adding sysfs entry
> > for setting permanent address from userspace in wl1251
> > driver.
>
> Ok, so the N900's MAC is stored in the "cal partition", which
> is a region of flash exposed to the OS as /dev/mtd1. That
> also stores the regulatory domain. Typically userspace
> binaries are used to pull out this and other data (see
> https://dev.openwrt.org/browser/packages/utils/calvaria/files/
> src/calvaria.c ) which is then used to initialize the device.
>
> Any idea what kernel driver is used to expose the CAL
> partition as /dev/mtd1? If it's nothing special maybe a
> small EEPROM-style driver could be written to read the
> relevant areas (and since they don't ever change, don't need
> to worry about something else writing at the same time).
>
> Dan

/dev/mtd1 is second (0 is first) OneNand partition. Nothing
special. Kernel driver for OnaNand is already in mainline kernel.

That partition also has NVS device data for wl1251 chip.

And you are right calvaria has GPL v2 code for parsing data in
that partition.

--
Pali Rohár
[email protected]


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

2013-10-30 11:51:50

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 11/16] wl1251: enable tx path in monitor mode if necessary for packet injection

Hi!
>
> If necessary enable the tx path in monitor mode for packet injection using
> the JOIN command with BSS_TYPE_STA_BSS and zero BSSID.
>
> Signed-off-by: David Gnedt <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/main.c | 5 +++++
> drivers/net/wireless/ti/wl1251/tx.c | 17 +++++++++++++++++
> drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
> 3 files changed, 23 insertions(+)
>
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
> index 3cc82fd..1de4ccb 100644
> --- a/drivers/net/wireless/ti/wl1251/tx.c
> +++ b/drivers/net/wireless/ti/wl1251/tx.c
> @@ -28,6 +28,7 @@
> #include "tx.h"
> #include "ps.h"
> #include "io.h"
> +#include "event.h"
>
> static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
> {
> @@ -298,6 +299,22 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
> }
> }
>
> + /* Enable tx path in monitor mode for packet injection */
> + if ((wl->vif == NULL) && !wl->joined) {
> + ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel,
> + wl->beacon_int, wl->dtim_period);
> + if (ret < 0)
> + wl1251_warning("join failed");
> + else {
> + ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID,
> + 100);
> + if (ret < 0)
> + wl1251_warning("join timeout");
> + else
> + wl->joined = true;
> + }
> + }

Create function enable_tx_for_packet_injection() and then just return
so that you don't have to nest ifs?

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

2013-10-26 20:40:37

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 12/16] wl1251: disable retry and ACK policy for injected packets

From: David Gnedt <[email protected]>

Set the retry limit to 0 and disable the ACK policy for injected packets.

Signed-off-by: David Gnedt <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 8 +++++++-
drivers/net/wireless/ti/wl1251/tx.c | 7 ++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 14da6de..f98d46f 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -943,12 +943,18 @@ int wl1251_acx_rate_policies(struct wl1251 *wl)
}

/* configure one default (one-size-fits-all) rate class */
- acx->rate_class_cnt = 1;
+ acx->rate_class_cnt = 2;
acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
acx->rate_class[0].aflags = 0;

+ /* no-retry rate class */
+ acx->rate_class[1].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+ acx->rate_class[1].short_retry_limit = 0;
+ acx->rate_class[1].long_retry_limit = 0;
+ acx->rate_class[1].aflags = 0;
+
ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
wl1251_warning("Setting of rate policies failed: %d", ret);
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 1de4ccb..e559bc4 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -90,8 +90,12 @@ static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
/* 802.11 packets */
tx_hdr->control.packet_type = 0;

- if (control->flags & IEEE80211_TX_CTL_NO_ACK)
+ /* Also disable retry and ACK policy for injected packets */
+ if ((control->flags & IEEE80211_TX_CTL_NO_ACK) ||
+ (control->flags & IEEE80211_TX_CTL_INJECTED)) {
+ tx_hdr->control.rate_policy = 1;
tx_hdr->control.ack_policy = 1;
+ }

tx_hdr->control.tx_complete = 1;

@@ -414,6 +418,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
info = IEEE80211_SKB_CB(skb);

if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
(result->status == TX_SUCCESS))
info->flags |= IEEE80211_TX_STAT_ACK;

--
1.7.10.4


2013-10-30 11:35:04

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 07/16] wl1251: configure hardware en-/decryption for monitor mode

On Sat 2013-10-26 22:34:06, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Disable hardware encryption (DF_ENCRYPTION_DISABLE) and decryption
> (DF_SNIFF_MODE_ENABLE) via wl1251_acx_feature_cfg while monitor interface is
> present.
>
> Signed-off-by: David Gnedt <[email protected]>

You need to sign off the patch, otherwise looks ok.

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

Thanks,
Pavel

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

2013-10-26 20:40:41

by Pali Rohár

[permalink] [raw]
Subject: [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address

Driver wl1251 generating mac address randomly at startup and there is no way to
set permanent mac address via SET_IEEE80211_PERM_ADDR. This patch export sysfs
file which can set permanent mac address by userspace helper program. Patch is
needed for devices which do not store mac address in internal wl1251 eeprom.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 29625c2..91a009c 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1375,6 +1375,46 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_address(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ len = snprintf(buf, len, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ wl->mac_addr[0], wl->mac_addr[1], wl->mac_addr[2],
+ wl->mac_addr[3], wl->mac_addr[4], wl->mac_addr[5]);
+
+ return len;
+}
+
+static ssize_t wl1251_sysfs_store_address(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned int addr[6];
+ int ret, i;
+
+ ret = sscanf(buf, "%2x:%2x:%2x:%2x:%2x:%2x\n",
+ &addr[0], &addr[1], &addr[2],
+ &addr[3], &addr[4], &addr[5]);
+
+ if (ret != 6)
+ return -EINVAL;
+
+ for (i = 0; i < 6; i++)
+ wl->mac_addr[i] = addr[i] & 0xff;
+
+ SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+
+ return count;
+}
+
static ssize_t wl1251_sysfs_show_tx_mgmt_frm_rate(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1584,6 +1624,10 @@ out:
return count;
}

+static DEVICE_ATTR(address, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_address,
+ wl1251_sysfs_store_address);
+
static DEVICE_ATTR(tx_mgmt_frm_rate, S_IRUGO | S_IWUSR,
wl1251_sysfs_show_tx_mgmt_frm_rate,
wl1251_sysfs_store_tx_mgmt_frm_rate);
@@ -1728,6 +1772,14 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
}
dev_set_drvdata(&wl1251_device.dev, wl);

+ /* Create sysfs file address */
+ ret = device_create_file(&wl1251_device.dev,
+ &dev_attr_address);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file address");
+ goto out;
+ }
+
/* Create sysfs file tx_mgmt_frm_rate */
ret = device_create_file(&wl1251_device.dev,
&dev_attr_tx_mgmt_frm_rate);
--
1.7.10.4


2013-10-30 11:28:56

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH 05/16] wl1251: implement hardware ARP filtering

Hi!

> Update hardware ARP filter configuration on BSS_CHANGED_ARP_FILTER
> notification from mac80211.
> Ported from wl1271 driver.
>
> Signed-off-by: David Gnedt <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/acx.c | 31 +++++++++++++++++++++++++++++++
> drivers/net/wireless/ti/wl1251/acx.h | 15 +++++++++++++++
> drivers/net/wireless/ti/wl1251/main.c | 13 +++++++++++++
> 3 files changed, 59 insertions(+)
>
> diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
> index cce50e2..9295090 100644
> --- a/drivers/net/wireless/ti/wl1251/acx.c
> +++ b/drivers/net/wireless/ti/wl1251/acx.c
> @@ -1062,6 +1062,37 @@ out:
> return ret;
> }
>
> +int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
> +{
> + struct wl1251_acx_arp_filter *acx;
> + int ret;
> +
> + wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
> +
> + acx = kzalloc(sizeof(*acx), GFP_KERNEL);
> + if (!acx) {
> + ret = -ENOMEM;
> + goto out;
> + }

I'd do "return -ENOMEM;" here. Trying to free NULL pointer is
unneccessary complication.

> + acx->version = ACX_IPV4_VERSION;
> + acx->enable = enable;
> +
> + if (enable == true)

if (enable) would be C way of writing stuff.

> + memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
> +
> + ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
> + acx, sizeof(*acx));
> + if (ret < 0) {
> + wl1251_warning("failed to set arp ip filter: %d", ret);
> + goto out;
> + }
> +
> +out:

No need for the out label now.

> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 46a2494..9752745 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -1078,6 +1078,19 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
> }
> }
>
> + if (changed & BSS_CHANGED_ARP_FILTER) {
> + __be32 addr = bss_conf->arp_addr_list[0];
> + WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
> +
> + if (bss_conf->arp_addr_cnt == 1 && bss_conf->assoc)
> + ret = wl1251_acx_arp_ip_filter(wl, true, addr);
> + else
> + ret = wl1251_acx_arp_ip_filter(wl, false, addr);


enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc;
ret = wl1251_acx_arp_ip_filter(wl, enable, addr);

?

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

2013-11-25 19:54:44

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 00/16] wl1251 patches from linux-n900 tree

On Friday 08 November 2013 15:20:07 Felipe Contreras wrote:
> On Sat, Oct 26, 2013 at 3:33 PM, Pali Rohár <[email protected]> wrote:
> > Hello, I'm sending wl1251 patches from linux-n900 tree [1]
> > for comments. More patches come from David's monitor &
> > packet injection work. Patches are tested with 3.12 rc5
> > kernel on Nokia N900.
> >
> > [1] - https://gitorious.org/linux-n900/linux-n900
>
> How did you test these patches? I get a panic loop immediately
> after I bring the interface loop in monitor mode (v3.12).

Hi!

now I can reproduce this crash with 3.12-rc5 kernel. Problem
looks like irrelevant to this patch series and is present in 3.12
kernel. There is possible NULL pointer dereference.

With this patch I'm not able to reproduce this bug:

diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index 192cebd..db01053 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -124,7 +124,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
return ret;
}

- if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
+ if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");

/* indicate to the stack, that beacons have been lost */


--
Pali Rohár
[email protected]


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

2013-11-08 14:20:09

by Felipe Contreras

[permalink] [raw]
Subject: Re: [PATCH 00/16] wl1251 patches from linux-n900 tree

On Sat, Oct 26, 2013 at 3:33 PM, Pali Rohár <[email protected]> wrote:
> Hello, I'm sending wl1251 patches from linux-n900 tree [1] for comments. More
> patches come from David's monitor & packet injection work. Patches are tested
> with 3.12 rc5 kernel on Nokia N900.
>
> [1] - https://gitorious.org/linux-n900/linux-n900

How did you test these patches? I get a panic loop immediately after I
bring the interface loop in monitor mode (v3.12).

--
Felipe Contreras

2013-12-12 19:56:05

by Ben Hutchings

[permalink] [raw]
Subject: Re: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Wed, 2013-12-11 at 16:53 -0600, Dan Williams wrote:
> On Wed, 2013-12-11 at 22:15 +0000, Ben Hutchings wrote:
> > On Wed, 2013-12-11 at 23:35 +0200, Ivajlo Dimitrov wrote:
> > > On 11.12.2013 23:17, Ben Hutchings wrote:
> > > > I think that's an even worse idea. This is not firmware and it already
> > > > exists in separate storage.
> > > >
> > > > I think that rx51_init_wl1251() in
> > > > arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
> > > > address out of NVRAM, or if it's too early to do that, then schedule a
> > > > function to run later and only then set up wl1251 platform data.
> > > >
> > > > Ben.
> > > >
> > >
> > > And how will that work with DT when board files will be in the history?
> >
> > 1. Boot loader reads the MAC address from NVRAM and puts it in the DT
> > node.
> > or
> > 2. NVRAM reading is done by a tiny driver that is loaded based on the
> > platform name and updates the DT node in memory. (But I don't know how
> > wl1251 should decide to defer probing if it's probed before that other
> > driver.)
>
> I'm uncomfortable with it too, and yes the permanent MAC should really
> be known before the interface is even registered, but...
>
> Imagine if the MAC address for your ethernet device was stored
> in /etc/my-mac-addr.txt, except that /etc was a read-only protected
> partition from a very small SSD. That's essentially the N900; it's
> stored in a file in a normal ext2/ext3 (?) filesystem on a partition of
> the internal flash.

Oh, from my quick look I got the impression that this 'CAL' was stored
directly in a specific flash partition.

> It seems like overkill to write a small driver that
> duplicates the ext3 + MTD drivers just to read the MAC.
[...]

I don't see that anything would need to be duplicated. But reading
files from the kernel is really ugly, and deciding when to read the file
would be another problem (as you noted).

Ben

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-08 09:27:29

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 10/16] wl1251: enable tx path in monitor mode if necessary for packet injection

From: David Gnedt <[email protected]>

If necessary enable the tx path in monitor mode for packet injection using
the JOIN command with BSS_TYPE_STA_BSS and zero BSSID.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/main.c | 5 +++++
drivers/net/wireless/ti/wl1251/tx.c | 25 +++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
3 files changed, 31 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index b6f11b8..bb6e873 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -487,6 +487,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->rssi_thold = 0;
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->monitor_present = false;
+ wl->joined = false;

wl1251_debugfs_reset(wl);

@@ -546,6 +547,7 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface");
wl->vif = NULL;
+ memset(wl->bssid, 0, ETH_ALEN);
mutex_unlock(&wl->mutex);
}

@@ -624,6 +626,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
* at firmware level.
*/
if (wl->vif == NULL) {
+ wl->joined = false;
ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
} else {
ret = wl1251_join(wl, wl->bss_type, wl->channel,
@@ -1612,7 +1615,9 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
wl->monitor_present = false;
+ wl->joined = false;
wl->scanning = false;
+ wl->bss_type = MAX_BSS_TYPE;
wl->default_key = 0;
wl->listen_int = 1;
wl->rx_counter = 0;
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 3cc82fd..216334d 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -28,6 +28,7 @@
#include "tx.h"
#include "ps.h"
#include "io.h"
+#include "event.h"

static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
{
@@ -277,6 +278,26 @@ static void wl1251_tx_trigger(struct wl1251 *wl)
TX_STATUS_DATA_OUT_COUNT_MASK;
}

+static void enable_tx_for_packet_injection(struct wl1251 *wl)
+{
+ int ret;
+
+ ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel,
+ wl->beacon_int, wl->dtim_period);
+ if (ret < 0) {
+ wl1251_warning("join failed");
+ return;
+ }
+
+ ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100);
+ if (ret < 0) {
+ wl1251_warning("join timeout");
+ return;
+ }
+
+ wl->joined = true;
+}
+
/* caller must hold wl->mutex */
static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
{
@@ -298,6 +319,10 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
}
}

+ /* Enable tx path in monitor mode for packet injection */
+ if ((wl->vif == NULL) && !wl->joined)
+ enable_tx_for_packet_injection(wl);
+
ret = wl1251_tx_path_status(wl);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 93c18d2..89f07f6 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -311,6 +311,7 @@ struct wl1251 {
u8 listen_int;
int channel;
bool monitor_present;
+ bool joined;

void *target_mem_map;
struct acx_data_path_params_resp *data_path;
--
1.7.9.5


2013-12-10 09:21:16

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

Hi!

> diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
> index 6822b84..16b6479 100644
> --- a/drivers/net/wireless/ti/wl1251/cmd.c
> +++ b/drivers/net/wireless/ti/wl1251/cmd.c
> @@ -410,7 +411,10 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
> struct wl1251_cmd_scan *cmd;
> int i, ret = 0;
>
> - wl1251_debug(DEBUG_CMD, "cmd scan");
> + wl1251_debug(DEBUG_CMD, "cmd scan channels %d ssid(%d) '%s'",
> + n_channels, (int)ssid_len, ssid);
> +
> + WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);
>

ssids can have \0s in them... and what is worse, they may not be 0
terminated AFAICT.

Potential solution is at
http://www.spinics.net/lists/linux-wireless/msg98640.html .

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

2013-12-10 17:14:39

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > Pali Rohár <[email protected]> writes:
> > > Driver wl1251 generating mac address randomly at startup
> > > and there is no way to set permanent mac address via
> > > SET_IEEE80211_PERM_ADDR. This patch export sysfs file
> > > which can set permanent mac address by userspace helper
> > > program. Patch is needed for devices which do not store
> > > mac address in internal wl1251 eeprom.
> > >
> > > Signed-off-by: Pali Rohár <[email protected]>
> >
> > We have ioctl() command for setting the mac address.
>
> Really? Is there ioctl for setting permanent mac address?
> Can you show me it?

Now I looked at it again and I did not found any ioctl for it.
There is only ioctl cmd for getting address, not setting it.

#define SIOCETHTOOL 0x8946

/* Get permanent hardware address */
#define ETHTOOL_GPERMADDR 0x00000020

--
Pali Rohár
[email protected]


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

2013-12-08 09:27:32

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 12/16] wl1251: enforce changed hw encryption support on monitor state change

From: David Gnedt <[email protected]>

The firmware doesn't support per packet encryption selection, so disable hw
encryption support completely while a monitor interface is present to support
injection of packets (which shouldn't get encrypted by hw).
To enforce the changed hw encryption support force a disassociation on
non-monitor interfaces.
For disassociation a workaround using hw connection monitor is employed,
which temporary enables hw connection manager flag.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index bb6e873..1ef264c 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -688,6 +688,16 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
wl->power_level = conf->power_level;
}

+ /*
+ * Tell stack that connection is lost because hw encryption isn't
+ * supported in monitor mode.
+ * This requires temporary enabling of the hw connection monitor flag
+ */
+ if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) {
+ wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;
+ ieee80211_connection_loss(wl->vif);
+ }
+
out_sleep:
wl1251_ps_elp_sleep(wl);

@@ -1120,6 +1130,9 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}

if (changed & BSS_CHANGED_ASSOC) {
+ /* Disable temporary enabled hw connection monitor flag */
+ wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR;
+
if (bss_conf->assoc) {
wl->beacon_int = bss_conf->beacon_int;

--
1.7.9.5


2013-12-08 16:36:08

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

On Sun, 2013-12-08 at 08:55 +0100, Pali Rohár wrote:
> On Tuesday 29 October 2013 00:39:47 Ben Hutchings wrote:
> > On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > > From: David Gnedt <[email protected]>
> > >
> > > Port the bt_coex_mode sysfs interface from wl1251 driver
> > > version included in the Maemo Fremantle kernel to allow
> > > bt-coexistence mode configuration. This enables userspace
> > > applications to set one of the modes WL1251_BT_COEX_OFF,
> > > WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO. The
> > > default mode is WL1251_BT_COEX_OFF.
> > > It should be noted that this driver always enabled
> > > bt-coexistence before and enabled bt-coexistence directly
> > > affects the receiving performance, rendering it unusable in
> > > some low-signal situations. Especially monitor mode is
> > > affected very badly with bt-coexistence enabled.
> >
> > [...]
> >
> > This should be implemented consistently with other drivers:
> >
> > drivers/net/wireless/ath/ath9k/htc_drv_init.c:module_param_nam
> > ed(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
> > drivers/net/wireless/ath/ath9k/init.c:module_param_named(btco
> > ex_enable, ath9k_btcoex_enable, int, 0444);
> > drivers/net/wireless/b43/main.c:module_param_named(btcoex,
> > modparam_btcoex, int, 0444);
> > drivers/net/wireless/ipw2x00/ipw2200.c:module_param(bt_coexis
> > t, int, 0444);
> > drivers/net/wireless/iwlegacy/common.c:module_param(bt_coex_a
> > ctive, bool, S_IRUGO);
> > drivers/net/wireless/iwlwifi/iwl-drv.c:module_param_named(bt_
> > coex_active, iwlwifi_mod_params.bt_coex_active,
> > drivers/net/wireless/ti/wlcore/sysfs.c:static
> > DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,
> >
> > Oh, hmm, I see a problem here.
> >
> > Ben.
>
> So where is consitency? Each driver doing this in different way:
> btcoex_enable, btcoex, bt_coexist, bt_coex_active

Indeed, it's a bigger problem than one driver and this isn't really an
objection to your patch. I suppose there should be an nl80211 attribute
to control this behaviour per-interface. You or any other wireless
networking developer could work on that.

Ben.

> Reason for this usage in wl1251 is to not break existing
> userspace applications.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-11 22:15:41

by Ben Hutchings

[permalink] [raw]
Subject: Re: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Wed, 2013-12-11 at 23:35 +0200, Ivajlo Dimitrov wrote:
> On 11.12.2013 23:17, Ben Hutchings wrote:
> > I think that's an even worse idea. This is not firmware and it already
> > exists in separate storage.
> >
> > I think that rx51_init_wl1251() in
> > arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
> > address out of NVRAM, or if it's too early to do that, then schedule a
> > function to run later and only then set up wl1251 platform data.
> >
> > Ben.
> >
>
> And how will that work with DT when board files will be in the history?

1. Boot loader reads the MAC address from NVRAM and puts it in the DT
node.
or
2. NVRAM reading is done by a tiny driver that is loaded based on the
platform name and updates the DT node in memory. (But I don't know how
wl1251 should decide to defer probing if it's probed before that other
driver.)

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-10 19:21:54

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tue, 2013-12-10 at 18:52 +0100, Pali Rohár wrote:
> On Tuesday 10 December 2013 18:49:22 Dan Williams wrote:
> > On Tue, 2013-12-10 at 18:14 +0100, Pali Rohár wrote:
> > > On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> > > > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > > > Pali Rohár <[email protected]> writes:
> > > > > > Driver wl1251 generating mac address randomly at
> > > > > > startup and there is no way to set permanent mac
> > > > > > address via SET_IEEE80211_PERM_ADDR. This patch
> > > > > > export sysfs file which can set permanent mac address
> > > > > > by userspace helper program. Patch is needed for
> > > > > > devices which do not store mac address in internal
> > > > > > wl1251 eeprom.
> > > > > >
> > > > > > Signed-off-by: Pali Rohár <[email protected]>
> > > > >
> > > > > We have ioctl() command for setting the mac address.
> > > >
> > > > Really? Is there ioctl for setting permanent mac address?
> > > > Can you show me it?
> > >
> > > Now I looked at it again and I did not found any ioctl for
> > > it. There is only ioctl cmd for getting address, not
> > > setting it.
> > >
> > > #define SIOCETHTOOL 0x8946
> > >
> > > /* Get permanent hardware address */
> > > #define ETHTOOL_GPERMADDR 0x00000020
> >
> > Yeah, because it's supposed to be permanent and unchanging.
> > Which means if there was an ioctl for it, that would be
> > contrary to the purpose of a permanent MAC address.
> >
> > I realize the N900 stores the WiFi MAC address completely
> > differently than many other systems, and that's why this
> > sysfs file was created. I don't really have a great
> > converged solution for that, other than what you've currently
> > got, or perhaps adding SPERMADDR to ethtool. One thing I
> > *would* like though, is a restriction on the sysfs file such
> > that if the permanent MAC is already set, it cannot be set
> > again. Otherwise the permanent MAC address isn't permanent
> > at all.
> >
> > Dan
>
> Maybe another way could be to use request_firmware to load address
> from userspace... Or what do you think?

That sounds like a great idea to try. A number of devices either need
stub firmware to read the MAC from EEPROM, or do use request_firmware()
to load firmware before they read the MAC. You may have to use
request_firmware() synchronously though to ensure that the MAC is read
before registering with mac80211.

Dan



2013-12-08 07:55:31

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

On Tuesday 29 October 2013 00:39:47 Ben Hutchings wrote:
> On Sat, 2013-10-26 at 22:34 +0200, Pali Rohár wrote:
> > From: David Gnedt <[email protected]>
> >
> > Port the bt_coex_mode sysfs interface from wl1251 driver
> > version included in the Maemo Fremantle kernel to allow
> > bt-coexistence mode configuration. This enables userspace
> > applications to set one of the modes WL1251_BT_COEX_OFF,
> > WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO. The
> > default mode is WL1251_BT_COEX_OFF.
> > It should be noted that this driver always enabled
> > bt-coexistence before and enabled bt-coexistence directly
> > affects the receiving performance, rendering it unusable in
> > some low-signal situations. Especially monitor mode is
> > affected very badly with bt-coexistence enabled.
>
> [...]
>
> This should be implemented consistently with other drivers:
>
> drivers/net/wireless/ath/ath9k/htc_drv_init.c:module_param_nam
> ed(btcoex_enable, ath9k_htc_btcoex_enable, int, 0444);
> drivers/net/wireless/ath/ath9k/init.c:module_param_named(btco
> ex_enable, ath9k_btcoex_enable, int, 0444);
> drivers/net/wireless/b43/main.c:module_param_named(btcoex,
> modparam_btcoex, int, 0444);
> drivers/net/wireless/ipw2x00/ipw2200.c:module_param(bt_coexis
> t, int, 0444);
> drivers/net/wireless/iwlegacy/common.c:module_param(bt_coex_a
> ctive, bool, S_IRUGO);
> drivers/net/wireless/iwlwifi/iwl-drv.c:module_param_named(bt_
> coex_active, iwlwifi_mod_params.bt_coex_active,
> drivers/net/wireless/ti/wlcore/sysfs.c:static
> DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,
>
> Oh, hmm, I see a problem here.
>
> Ben.

So where is consitency? Each driver doing this in different way:
btcoex_enable, btcoex, bt_coexist, bt_coex_active

Reason for this usage in wl1251 is to not break existing
userspace applications.

--
Pali Rohár
[email protected]


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

2013-12-31 09:31:59

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 06/16] wl1251: configure hardware en-/decryption for monitor mode

On Tuesday 10 December 2013 10:35:18 Pavel Machek wrote:
> Hi!
>
> > --- a/drivers/net/wireless/ti/wl1251/tx.c
> > +++ b/drivers/net/wireless/ti/wl1251/tx.c
> > @@ -287,6 +287,9 @@ static int wl1251_tx_frame(struct wl1251
> > *wl, struct sk_buff *skb)
> >
> > info = IEEE80211_SKB_CB(skb);
> >
> > if (info->control.hw_key) {
> >
> > + if (unlikely(wl->monitor_present))
> > + return -1;
> > +
>
> This function seems to use 0/-errno convention. So probably
> "return -EINVAL"?
>
> With that fixed:
>
> Reviewed-by: Pavel Machek <[email protected]>
>
> Thanks,
> Pavel

Here is new version with above fix:

From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]>
Subject: [PATCH v2 06/16] wl1251: configure hardware en-/decryption for monitor mode
Date: Sun, 8 Dec 2013 10:25:04 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 8bit

From: David Gnedt <[email protected]>

Disable hardware encryption (DF_ENCRYPTION_DISABLE) and decryption
(DF_SNIFF_MODE_ENABLE) via wl1251_acx_feature_cfg while monitor interface is
present.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 6 +++---
drivers/net/wireless/ti/wl1251/acx.h | 2 +-
drivers/net/wireless/ti/wl1251/init.c | 2 +-
drivers/net/wireless/ti/wl1251/main.c | 34 ++++++++++++++++++++++++++-----
drivers/net/wireless/ti/wl1251/rx.c | 2 +-
drivers/net/wireless/ti/wl1251/tx.c | 3 +++
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
7 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 5f4a552..1ec98e9 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -209,7 +209,7 @@ out:
return ret;
}

-int wl1251_acx_feature_cfg(struct wl1251 *wl)
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
{
struct acx_feature_config *feature;
int ret;
@@ -222,8 +222,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl)
goto out;
}

- /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
- feature->data_flow_options = 0;
+ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
+ feature->data_flow_options = data_flow_options;
feature->options = 0;

ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 4444cd0..bea2e67 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -1455,7 +1455,7 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
int wl1251_acx_tx_power(struct wl1251 *wl, int power);
-int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options);
int wl1251_acx_mem_map(struct wl1251 *wl,
struct acx_header *mem_map, size_t len);
int wl1251_acx_data_path_params(struct wl1251 *wl,
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 424ce01..92de289 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -33,7 +33,7 @@ int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
{
int ret;

- ret = wl1251_acx_feature_cfg(wl);
+ ret = wl1251_acx_feature_cfg(wl, 0);
if (ret < 0) {
wl1251_warning("couldn't set feature config");
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 0e27f1f..39a6105 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -485,6 +485,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;

wl1251_debugfs_reset(wl);

@@ -577,8 +578,10 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
channel = ieee80211_frequency_to_channel(
conf->chandef.chan->center_freq);

- wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+ wl1251_debug(DEBUG_MAC80211,
+ "mac80211 config ch %d monitor %s psm %s power %d",
channel,
+ conf->flags & IEEE80211_CONF_MONITOR ? "on" : "off",
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
conf->power_level);

@@ -588,6 +591,22 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
if (ret < 0)
goto out;

+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ u32 mode;
+
+ if (conf->flags & IEEE80211_CONF_MONITOR) {
+ wl->monitor_present = true;
+ mode = DF_SNIFF_MODE_ENABLE | DF_ENCRYPTION_DISABLE;
+ } else {
+ wl->monitor_present = false;
+ mode = 0;
+ }
+
+ ret = wl1251_acx_feature_cfg(wl, mode);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
if (channel != wl->channel) {
wl->channel = channel;

@@ -804,12 +823,12 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

mutex_lock(&wl->mutex);

- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out_unlock;
-
switch (cmd) {
case SET_KEY:
+ if (wl->monitor_present) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
wl_cmd->key_action = KEY_ADD_OR_REPLACE;
break;
case DISABLE_KEY:
@@ -820,6 +839,10 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
}

+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
if (ret < 0) {
wl1251_error("Set KEY type failed");
@@ -1520,6 +1543,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)

INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;
wl->scanning = false;
wl->default_key = 0;
wl->listen_int = 1;
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c
index 23289d4..123c4bb 100644
--- a/drivers/net/wireless/ti/wl1251/rx.c
+++ b/drivers/net/wireless/ti/wl1251/rx.c
@@ -83,7 +83,7 @@ static void wl1251_rx_status(struct wl1251 *wl,

status->flag |= RX_FLAG_MACTIME_START;

- if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
+ if (!wl->monitor_present && (desc->flags & RX_DESC_ENCRYPTION_MASK)) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;

if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 28121c5..3cc82fd 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -287,6 +287,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);

if (info->control.hw_key) {
+ if (unlikely(wl->monitor_present))
+ return -EINVAL;
+
idx = info->control.hw_key->hw_key_idx;
if (unlikely(wl->default_key != idx)) {
ret = wl1251_acx_default_key(wl, idx);
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index de9e418..45df03a 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -309,6 +309,7 @@ struct wl1251 {
u8 bss_type;
u8 listen_int;
int channel;
+ bool monitor_present;

void *target_mem_map;
struct acx_data_path_params_resp *data_path;
--
1.7.9.5

--
Pali Rohár
[email protected]


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

2013-12-10 09:46:11

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 11/16] wl1251: disable retry and ACK policy for injected packets

On Sun 2013-12-08 10:25:09, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Set the retry limit to 0 and disable the ACK policy for injected packets.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel

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

2013-12-08 09:27:18

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 02/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

From: David Gnedt <[email protected]>

Port the bt_coex_mode sysfs interface from wl1251 driver version included
in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
This enables userspace applications to set one of the modes
WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
The default mode is WL1251_BT_COEX_OFF.
It should be noted that this driver always enabled bt-coexistence before
and enabled bt-coexistence directly affects the receiving performance,
rendering it unusable in some low-signal situations. Especially monitor
mode is affected very badly with bt-coexistence enabled.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 43 ++++++++++--
drivers/net/wireless/ti/wl1251/acx.h | 8 ++-
drivers/net/wireless/ti/wl1251/init.c | 6 +-
drivers/net/wireless/ti/wl1251/main.c | 108 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/wl1251.h | 8 +++
5 files changed, 161 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index db6430c..cce50e2 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -581,7 +581,7 @@ out:
return ret;
}

-int wl1251_acx_sg_enable(struct wl1251 *wl)
+int wl1251_acx_sg_enable(struct wl1251 *wl, u8 mode)
{
struct acx_bt_wlan_coex *pta;
int ret;
@@ -594,7 +594,7 @@ int wl1251_acx_sg_enable(struct wl1251 *wl)
goto out;
}

- pta->enable = SG_ENABLE;
+ pta->enable = mode;

ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
if (ret < 0) {
@@ -607,7 +607,7 @@ out:
return ret;
}

-int wl1251_acx_sg_cfg(struct wl1251 *wl)
+int wl1251_acx_sg_cfg(struct wl1251 *wl, u16 wake_up_beacon)
{
struct acx_bt_wlan_coex_param *param;
int ret;
@@ -632,7 +632,7 @@ int wl1251_acx_sg_cfg(struct wl1251 *wl)
param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
- param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
+ param->wake_up_beacon = wake_up_beacon;
param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
param->antenna_type = PTA_ANTENNA_TYPE_DEF;
@@ -661,6 +661,41 @@ out:
return ret;
}

+int wl1251_acx_sg_configure(struct wl1251 *wl, bool force)
+{
+ int ret;
+
+ if (wl->state == WL1251_STATE_OFF && !force)
+ return 0;
+
+ switch (wl->bt_coex_mode) {
+ case WL1251_BT_COEX_OFF:
+ ret = wl1251_acx_sg_enable(wl, SG_DISABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, 0);
+ break;
+ case WL1251_BT_COEX_ENABLE:
+ ret = wl1251_acx_sg_enable(wl, SG_ENABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, PTA_TIME_BEFORE_BEACON_DEF);
+ break;
+ case WL1251_BT_COEX_MONOAUDIO:
+ ret = wl1251_acx_sg_enable(wl, SG_ENABLE);
+ if (ret)
+ break;
+ ret = wl1251_acx_sg_cfg(wl, PTA_TIME_BEFORE_BEACON_MONO_AUDIO);
+ break;
+ default:
+ wl1251_error("Invalid BT co-ex mode!");
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+
int wl1251_acx_cca_threshold(struct wl1251 *wl)
{
struct acx_energy_detection *detection;
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index c2ba100..99ea80e 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -558,7 +558,8 @@ struct acx_bt_wlan_coex {
#define PTA_ANTI_STARVE_PERIOD_DEF (500)
#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4)
#define PTA_ALLOW_PA_SD_DEF (1)
-#define PTA_TIME_BEFORE_BEACON_DEF (6300)
+#define PTA_TIME_BEFORE_BEACON_DEF (500)
+#define PTA_TIME_BEFORE_BEACON_MONO_AUDIO (6300)
#define PTA_HPDM_MAX_TIME_DEF (1600)
#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550)
#define PTA_AUTO_MODE_NO_CTS_DEF (0)
@@ -1455,8 +1456,9 @@ int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
int wl1251_acx_beacon_filter_table(struct wl1251 *wl);
int wl1251_acx_conn_monit_params(struct wl1251 *wl);
-int wl1251_acx_sg_enable(struct wl1251 *wl);
-int wl1251_acx_sg_cfg(struct wl1251 *wl);
+int wl1251_acx_sg_enable(struct wl1251 *wl, u8 mode);
+int wl1251_acx_sg_cfg(struct wl1251 *wl, u16 wake_up_beacon);
+int wl1251_acx_sg_configure(struct wl1251 *wl, bool force);
int wl1251_acx_cca_threshold(struct wl1251 *wl);
int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 89b43d3..a6ad223 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -162,11 +162,7 @@ int wl1251_hw_init_pta(struct wl1251 *wl)
{
int ret;

- ret = wl1251_acx_sg_enable(wl);
- if (ret < 0)
- return ret;
-
- ret = wl1251_acx_sg_cfg(wl);
+ ret = wl1251_acx_sg_configure(wl, true);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 4d89ac8..ad2fd18 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -27,6 +27,7 @@
#include <linux/crc32.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>

#include "wl1251.h"
@@ -1256,6 +1257,94 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_bt_coex_mode(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ mutex_lock(&wl->mutex);
+ len = snprintf(buf, len, "%d\n\n%d - off\n%d - on\n%d - monoaudio\n",
+ wl->bt_coex_mode,
+ WL1251_BT_COEX_OFF,
+ WL1251_BT_COEX_ENABLE,
+ WL1251_BT_COEX_MONOAUDIO);
+ mutex_unlock(&wl->mutex);
+
+ return len;
+
+}
+
+static ssize_t wl1251_sysfs_store_bt_coex_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned long res;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &res);
+
+ if (ret < 0) {
+ wl1251_warning("incorrect value written to bt_coex_mode");
+ return count;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ if (res == wl->bt_coex_mode)
+ goto out;
+
+ switch (res) {
+ case WL1251_BT_COEX_OFF:
+ case WL1251_BT_COEX_ENABLE:
+ case WL1251_BT_COEX_MONOAUDIO:
+ wl->bt_coex_mode = res;
+ break;
+ default:
+ wl1251_warning("incorrect value written to bt_coex_mode");
+ goto out;
+ }
+
+ if (wl->state == WL1251_STATE_OFF)
+ goto out;
+
+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out;
+
+ wl1251_acx_sg_configure(wl, false);
+ wl1251_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static DEVICE_ATTR(bt_coex_mode, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_bt_coex_mode,
+ wl1251_sysfs_store_bt_coex_mode);
+
+static void wl1251_device_release(struct device *dev)
+{
+
+}
+
+static struct platform_device wl1251_device = {
+ /* FIXME: use wl12xx name to not break the user space */
+ .name = "wl12xx",
+ .id = -1,
+
+ /* device model insists to have a release function */
+ .dev = {
+ .release = wl1251_device_release,
+ },
+};
+
static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data)
{
unsigned long timeout;
@@ -1368,6 +1457,22 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
if (ret)
goto out;

+ /* Register platform device */
+ ret = platform_device_register(&wl1251_device);
+ if (ret) {
+ wl1251_error("couldn't register platform device");
+ goto out;
+ }
+ dev_set_drvdata(&wl1251_device.dev, wl);
+
+
+ /* Create sysfs file to control bt coex state */
+ ret = device_create_file(&wl1251_device.dev, &dev_attr_bt_coex_mode);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file bt_coex_mode");
+ goto out;
+ }
+
wl1251_debugfs_init(wl);
wl1251_notice("initialized");

@@ -1420,6 +1525,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
wl->vif = NULL;
+ wl->bt_coex_mode = WL1251_BT_COEX_OFF;

for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
wl->tx_frames[i] = NULL;
@@ -1459,6 +1565,8 @@ int wl1251_free_hw(struct wl1251 *wl)

wl1251_debugfs_exit(wl);

+ platform_device_unregister(&wl1251_device);
+
kfree(wl->target_mem_map);
kfree(wl->data_path);
vfree(wl->fw);
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 2c3bd1b..50bae8b 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -257,6 +257,12 @@ struct wl1251_debugfs {
struct dentry *excessive_retries;
};

+enum wl1251_bt_coex_mode {
+ WL1251_BT_COEX_OFF,
+ WL1251_BT_COEX_ENABLE,
+ WL1251_BT_COEX_MONOAUDIO
+};
+
struct wl1251_if_operations {
void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
@@ -386,6 +392,8 @@ struct wl1251 {

struct ieee80211_vif *vif;

+ enum wl1251_bt_coex_mode bt_coex_mode;
+
u32 chip_id;
char fw_ver[21];

--
1.7.9.5


2013-12-16 12:38:24

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] mac80211: fix TX device statistics for monitor interfaces

On Sun, 2013-12-08 at 09:45 +0100, Pali Rohár wrote:
> From: David Gnedt <[email protected]>
>
> Count TX packets and bytes also for monitor interfaces.

> + dev->stats.tx_packets++;
> + dev->stats.tx_bytes += skb->len;
> +
> /*
> * fix up the pointers accounting for the radiotap
> * header still being in there. We are being given

Should we really count the machine-local radiotap management stuff?

johannes


2013-12-08 09:27:33

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 13/16] wl1251: add nvs file name to module firmware list

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 1ef264c..382dedf 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1711,3 +1711,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kalle Valo <[email protected]>");
MODULE_FIRMWARE(WL1251_FW_NAME);
+MODULE_FIRMWARE(WL1251_NVS_NAME);
--
1.7.9.5


2013-12-11 21:35:27

by Ivaylo Dimitrov

[permalink] [raw]
Subject: Re: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address


On 11.12.2013 23:17, Ben Hutchings wrote:
> I think that's an even worse idea. This is not firmware and it already
> exists in separate storage.
>
> I think that rx51_init_wl1251() in
> arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
> address out of NVRAM, or if it's too early to do that, then schedule a
> function to run later and only then set up wl1251 platform data.
>
> Ben.
>

And how will that work with DT when board files will be in the history?

Ivo

2013-12-08 09:27:22

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 05/16] wl1251: split RX and TX data path initialisation

From: David Gnedt <[email protected]>

Split up data path initialisation into RX and TX data path initialisation
functions. This change is required for channel switching in monitor mode.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/cmd.c | 46 +++++++++++++++++++++++----------
drivers/net/wireless/ti/wl1251/cmd.h | 3 ++-
drivers/net/wireless/ti/wl1251/init.c | 9 +++++--
3 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 16b6479..381b3fe 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -204,11 +204,11 @@ out:
return ret;
}

-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable)
{
struct cmd_enabledisable_path *cmd;
int ret;
- u16 cmd_rx, cmd_tx;
+ u16 cmd_rx;

wl1251_debug(DEBUG_CMD, "cmd data path");

@@ -220,13 +220,10 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)

cmd->channel = channel;

- if (enable) {
+ if (enable)
cmd_rx = CMD_ENABLE_RX;
- cmd_tx = CMD_ENABLE_TX;
- } else {
+ else
cmd_rx = CMD_DISABLE_RX;
- cmd_tx = CMD_DISABLE_TX;
- }

ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
if (ret < 0) {
@@ -238,17 +235,38 @@ int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
enable ? "start" : "stop", channel);

+out:
+ kfree(cmd);
+ return ret;
+}
+
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
+{
+ struct cmd_enabledisable_path *cmd;
+ int ret;
+ u16 cmd_tx;
+
+ wl1251_debug(DEBUG_CMD, "cmd data path");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ cmd->channel = channel;
+
+ if (enable)
+ cmd_tx = CMD_ENABLE_TX;
+ else
+ cmd_tx = CMD_DISABLE_TX;
+
ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
- if (ret < 0) {
+ if (ret < 0)
wl1251_error("tx %s cmd for channel %d failed",
enable ? "start" : "stop", channel);
- goto out;
- }
-
- wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
- enable ? "start" : "stop", channel);
+ else
+ wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
+ enable ? "start" : "stop", channel);

-out:
kfree(cmd);
return ret;
}
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h
index 126f273..d824ff9 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.h
+++ b/drivers/net/wireless/ti/wl1251/cmd.h
@@ -35,7 +35,8 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len);
int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
void *bitmap, u16 bitmap_len, u8 bitmap_control);
-int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable);
+int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable);
int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
u16 beacon_interval, u8 dtim_interval);
int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index a6ad223..424ce01 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -390,8 +390,13 @@ int wl1251_hw_init(struct wl1251 *wl)
if (ret < 0)
goto out_free_data_path;

- /* Enable data path */
- ret = wl1251_cmd_data_path(wl, wl->channel, 1);
+ /* Enable rx data path */
+ ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+ if (ret < 0)
+ goto out_free_data_path;
+
+ /* Enable tx data path */
+ ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1);
if (ret < 0)
goto out_free_data_path;

--
1.7.9.5


2013-12-10 09:35:20

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 06/16] wl1251: configure hardware en-/decryption for monitor mode

Hi!


> --- a/drivers/net/wireless/ti/wl1251/tx.c
> +++ b/drivers/net/wireless/ti/wl1251/tx.c
> @@ -287,6 +287,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
> info = IEEE80211_SKB_CB(skb);
>
> if (info->control.hw_key) {
> + if (unlikely(wl->monitor_present))
> + return -1;
> +


This function seems to use 0/-errno convention. So probably "return
-EINVAL"?

With that fixed:

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

Thanks,
Pavel

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

2013-12-10 15:36:58

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 14/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate

Pali Rohár <[email protected]> writes:

> This patch adds support for configuring reg domains.
> Patch was extracted from Maemo 2.6.28 kernel.
>
> Signed-off-by: Pali Rohár <[email protected]>

[...]

> + /* FIXME: what's the maximum length of buf? page size?*/
> + len = 500;

Based on the comment here I'm guessing that I wrote this horrible hack :)

I can't recall anymore why it was needed, maybe something for BT coex?
But this code should never go upstream.

--
Kalle Valo

2013-12-10 15:41:09

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

Pavel Machek <[email protected]> writes:

> ssids can have \0s in them... and what is worse, they may not be 0
> terminated AFAICT.
>
> Potential solution is at
> http://www.spinics.net/lists/linux-wireless/msg98640.html .

I just use print_hex_dump_bytes() to print SSIDs.

--
Kalle Valo

2013-12-08 09:27:20

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 04/16] wl1251: implement hardware ARP filtering

From: David Gnedt <[email protected]>

Update hardware ARP filter configuration on BSS_CHANGED_ARP_FILTER
notification from mac80211.
Ported from wl1271 driver.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 26 ++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/acx.h | 15 +++++++++++++++
drivers/net/wireless/ti/wl1251/main.c | 12 ++++++++++++
3 files changed, 53 insertions(+)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index cce50e2..5f4a552 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -1062,6 +1062,32 @@ out:
return ret;
}

+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
+{
+ struct wl1251_acx_arp_filter *acx;
+ int ret;
+
+ wl1251_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx)
+ return -ENOMEM;
+
+ acx->version = ACX_IPV4_VERSION;
+ acx->enable = enable;
+
+ if (enable)
+ memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
+
+ ret = wl1251_cmd_configure(wl, ACX_ARP_IP_FILTER,
+ acx, sizeof(*acx));
+ if (ret < 0)
+ wl1251_warning("failed to set arp ip filter: %d", ret);
+
+ kfree(acx);
+ return ret;
+}
+
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
u8 aifs, u16 txop)
{
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 99ea80e..4444cd0 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -1233,6 +1233,20 @@ struct wl1251_acx_bet_enable {
u8 padding[2];
} __packed;

+#define ACX_IPV4_VERSION 4
+#define ACX_IPV6_VERSION 6
+#define ACX_IPV4_ADDR_SIZE 4
+struct wl1251_acx_arp_filter {
+ struct acx_header header;
+ u8 version; /* The IP version: 4 - IPv4, 6 - IPv6.*/
+ u8 enable; /* 1 - ARP filtering is enabled, 0 - disabled */
+ u8 padding[2];
+ u8 address[16]; /* The IP address used to filter ARP packets.
+ ARP packets that do not match this address are
+ dropped. When the IP Version is 4, the last 12
+ bytes of the the address are ignored. */
+} __attribute__((packed));
+
struct wl1251_acx_ac_cfg {
struct acx_header header;

@@ -1475,6 +1489,7 @@ int wl1251_acx_mem_cfg(struct wl1251 *wl);
int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
u8 max_consecutive);
+int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address);
int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
u8 aifs, u16 txop);
int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 46a2494..0e27f1f 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -980,6 +980,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
{
struct wl1251 *wl = hw->priv;
struct sk_buff *beacon, *skb;
+ bool enable;
int ret;

wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1078,6 +1079,17 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}
}

+ if (changed & BSS_CHANGED_ARP_FILTER) {
+ __be32 addr = bss_conf->arp_addr_list[0];
+ WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
+
+ enable = bss_conf->arp_addr_cnt == 1 && bss_conf->assoc;
+ wl1251_acx_arp_ip_filter(wl, enable, addr);
+
+ if (ret < 0)
+ goto out_sleep;
+ }
+
if (changed & BSS_CHANGED_BEACON) {
beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
--
1.7.9.5


2013-12-08 09:27:19

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 03/16] wl1251: retry power save entry

From: David Gnedt <[email protected]>

Port of the power save entry retry code from wl1251 driver version included
in the Maemo Fremantle kernel.
This tries to enable power save mode up to 3 times before failing.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/boot.c | 3 ++-
drivers/net/wireless/ti/wl1251/event.c | 44 +++++++++++++++++++++++++++++++
drivers/net/wireless/ti/wl1251/event.h | 7 +++++
drivers/net/wireless/ti/wl1251/main.c | 2 ++
drivers/net/wireless/ti/wl1251/wl1251.h | 3 +++
5 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/boot.c b/drivers/net/wireless/ti/wl1251/boot.c
index a2e5241..2000cd5 100644
--- a/drivers/net/wireless/ti/wl1251/boot.c
+++ b/drivers/net/wireless/ti/wl1251/boot.c
@@ -299,7 +299,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
ROAMING_TRIGGER_LOW_RSSI_EVENT_ID |
ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID |
REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID |
- BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID;
+ BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID |
+ PS_REPORT_EVENT_ID;

ret = wl1251_event_unmask(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index 74ae8e1..192cebd 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -46,6 +46,43 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
return ret;
}

+#define WL1251_PSM_ENTRY_RETRIES 3
+static int wl1251_event_ps_report(struct wl1251 *wl,
+ struct event_mailbox *mbox)
+{
+ int ret = 0;
+
+ wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);
+
+ switch (mbox->ps_status) {
+ case EVENT_ENTER_POWER_SAVE_FAIL:
+ wl1251_debug(DEBUG_PSM, "PSM entry failed");
+
+ if (wl->station_mode != STATION_POWER_SAVE_MODE) {
+ /* remain in active mode */
+ wl->psm_entry_retry = 0;
+ break;
+ }
+
+ if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
+ wl->psm_entry_retry++;
+ ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
+ } else {
+ wl1251_error("Power save entry failed, giving up");
+ wl->psm_entry_retry = 0;
+ }
+ break;
+ case EVENT_ENTER_POWER_SAVE_SUCCESS:
+ case EVENT_EXIT_POWER_SAVE_FAIL:
+ case EVENT_EXIT_POWER_SAVE_SUCCESS:
+ default:
+ wl->psm_entry_retry = 0;
+ break;
+ }
+
+ return 0;
+}
+
static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
{
wl1251_debug(DEBUG_EVENT, "MBOX DUMP:");
@@ -80,6 +117,13 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
}
}

+ if (vector & PS_REPORT_EVENT_ID) {
+ wl1251_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
+ ret = wl1251_event_ps_report(wl, mbox);
+ if (ret < 0)
+ return ret;
+ }
+
if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");

diff --git a/drivers/net/wireless/ti/wl1251/event.h b/drivers/net/wireless/ti/wl1251/event.h
index 30eb5d1..88570a5 100644
--- a/drivers/net/wireless/ti/wl1251/event.h
+++ b/drivers/net/wireless/ti/wl1251/event.h
@@ -112,6 +112,13 @@ struct event_mailbox {
u8 padding[19];
} __packed;

+enum {
+ EVENT_ENTER_POWER_SAVE_FAIL = 0,
+ EVENT_ENTER_POWER_SAVE_SUCCESS,
+ EVENT_EXIT_POWER_SAVE_FAIL,
+ EVENT_EXIT_POWER_SAVE_SUCCESS,
+};
+
int wl1251_event_unmask(struct wl1251 *wl);
void wl1251_event_mbox_config(struct wl1251 *wl);
int wl1251_event_handle(struct wl1251 *wl, u8 mbox);
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index ad2fd18..46a2494 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -480,6 +480,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->next_tx_complete = 0;
wl->elp = false;
wl->station_mode = STATION_ACTIVE_MODE;
+ wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
@@ -1519,6 +1520,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
wl->elp = false;
wl->station_mode = STATION_ACTIVE_MODE;
wl->psm_requested = false;
+ wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 50bae8b..de9e418 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -374,6 +374,9 @@ struct wl1251 {
/* PSM mode requested */
bool psm_requested;

+ /* retry counter for PSM entries */
+ u8 psm_entry_retry;
+
u16 beacon_int;
u8 dtim_period;

--
1.7.9.5


2013-12-11 21:28:51

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Wed, 2013-12-11 at 21:17 +0000, Ben Hutchings wrote:
> On Tue, 2013-12-10 at 18:52 +0100, Pali Rohár wrote:
[...]
> > Maybe another way could be to use request_firmware to load address
> > from userspace... Or what do you think?
>
> I think that's an even worse idea. This is not firmware and it already
> exists in separate storage.
[...]

Actually, as it seems you meant to do some kind of dynamic conversion, I
think it's not so bad. Unfortunately I don't think it can work as I
explained in my other email.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-08 09:27:30

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 11/16] wl1251: disable retry and ACK policy for injected packets

From: David Gnedt <[email protected]>

Set the retry limit to 0 and disable the ACK policy for injected packets.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 8 +++++++-
drivers/net/wireless/ti/wl1251/tx.c | 7 ++++++-
2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index f772e62..8f420d0 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -943,12 +943,18 @@ int wl1251_acx_rate_policies(struct wl1251 *wl)
}

/* configure one default (one-size-fits-all) rate class */
- acx->rate_class_cnt = 1;
+ acx->rate_class_cnt = 2;
acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
acx->rate_class[0].aflags = 0;

+ /* no-retry rate class */
+ acx->rate_class[1].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
+ acx->rate_class[1].short_retry_limit = 0;
+ acx->rate_class[1].long_retry_limit = 0;
+ acx->rate_class[1].aflags = 0;
+
ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
if (ret < 0) {
wl1251_warning("Setting of rate policies failed: %d", ret);
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 216334d..4516180 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -90,8 +90,12 @@ static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr,
/* 802.11 packets */
tx_hdr->control.packet_type = 0;

- if (control->flags & IEEE80211_TX_CTL_NO_ACK)
+ /* Also disable retry and ACK policy for injected packets */
+ if ((control->flags & IEEE80211_TX_CTL_NO_ACK) ||
+ (control->flags & IEEE80211_TX_CTL_INJECTED)) {
+ tx_hdr->control.rate_policy = 1;
tx_hdr->control.ack_policy = 1;
+ }

tx_hdr->control.tx_complete = 1;

@@ -422,6 +426,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
info = IEEE80211_SKB_CB(skb);

if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
(result->status == TX_SUCCESS))
info->flags |= IEEE80211_TX_STAT_ACK;

--
1.7.9.5


2013-12-08 09:27:16

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

From: David Gnedt <[email protected]>

With a dissacociated card I often encoutered very long scan delays.

My guess is that it has something to do with the cards DTIM handling and
another firmware bug mentioned in the TI WLAN driver, which is described as
the card may never end scanning if the channel is overloaded because it
can't send probe requests. I think the firmware somehow also tries to
receive DTIM messages when the BSSID is not set. Therefore most of the time
it waits for DTIM messages and can't do scanning work.

Anyway we can workaround this misbehaviour by setting the HIGH_PRIORITY
bit for scans in disassociated state.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/cmd.c | 13 ++++++++++++-
drivers/net/wireless/ti/wl1251/cmd.h | 5 +++++
drivers/net/wireless/ti/wl1251/main.c | 1 +
3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 6822b84..16b6479 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/crc7.h>
+#include <linux/etherdevice.h>

#include "wl1251.h"
#include "reg.h"
@@ -410,7 +411,10 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
struct wl1251_cmd_scan *cmd;
int i, ret = 0;

- wl1251_debug(DEBUG_CMD, "cmd scan");
+ wl1251_debug(DEBUG_CMD, "cmd scan channels %d ssid(%d) '%s'",
+ n_channels, (int)ssid_len, ssid);
+
+ WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
@@ -421,6 +425,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
CFG_RX_MGMT_EN |
CFG_RX_BCN_EN);
cmd->params.scan_options = 0;
+ /*
+ * Use high priority scan when not associated to prevent fw issue
+ * causing never-ending scans (sometimes 20+ minutes).
+ * Note: This bug may be caused by the fw's DTIM handling.
+ */
+ if (is_zero_ether_addr(wl->bssid))
+ cmd->params.scan_options |= WL1251_SCAN_OPT_PRIORITY_HIGH;
cmd->params.num_channels = n_channels;
cmd->params.num_probe_requests = n_probes;
cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h
index ee4f2b3..126f273 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.h
+++ b/drivers/net/wireless/ti/wl1251/cmd.h
@@ -167,6 +167,11 @@ struct cmd_read_write_memory {
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4

+#define WL1251_SCAN_OPT_PASSIVE 1
+#define WL1251_SCAN_OPT_5GHZ_BAND 2
+#define WL1251_SCAN_OPT_TRIGGERD_SCAN 4
+#define WL1251_SCAN_OPT_PRIORITY_HIGH 8
+
#define WL1251_SCAN_MIN_DURATION 30000
#define WL1251_SCAN_MAX_DURATION 60000

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 3291ffa..4d89ac8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -930,6 +930,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
req->n_channels, WL1251_SCAN_NUM_PROBES);
if (ret < 0) {
+ wl1251_debug(DEBUG_SCAN, "scan failed %d", ret);
wl->scanning = false;
goto out_idle;
}
--
1.7.9.5


2013-12-10 09:42:14

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 16/16] wl1251: fix NULL pointer dereference

On Sun 2013-12-08 10:25:14, Pali Roh?r wrote:
> Signed-off-by: Pali Roh?r <[email protected]>
> Reported-by: Felipe Contreras <[email protected]>

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

Thanks,
Pavel


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

2013-12-10 09:41:05

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 08/16] wl1251: disable power saving in monitor mode

On Sun 2013-12-08 10:25:06, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Force power saving off while monitor interface is present.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel

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

2013-12-10 09:31:16

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 05/16] wl1251: split RX and TX data path initialisation

On Sun 2013-12-08 10:25:03, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Split up data path initialisation into RX and TX data path initialisation
> functions. This change is required for channel switching in monitor mode.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

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

2013-12-10 15:46:58

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 02/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

Pali Rohár <[email protected]> writes:

> From: David Gnedt <[email protected]>
>
> Port the bt_coex_mode sysfs interface from wl1251 driver version included
> in the Maemo Fremantle kernel to allow bt-coexistence mode configuration.
> This enables userspace applications to set one of the modes
> WL1251_BT_COEX_OFF, WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO.
> The default mode is WL1251_BT_COEX_OFF.
> It should be noted that this driver always enabled bt-coexistence before
> and enabled bt-coexistence directly affects the receiving performance,
> rendering it unusable in some low-signal situations. Especially monitor
> mode is affected very badly with bt-coexistence enabled.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Rohár <[email protected]>

I think this is also what I wrote a long time. And also this sysfs hack
should not go to upstream.

Over the years there has been some talk about solving the BT coex
properly, but I haven't seen any patches. I guess the proper solution
would be that BT subsystem in kernel would notify wireless drivers about
BT use?

--
Kalle Valo

2013-12-08 09:27:15

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

Hello, I'm sending wl1251 patches from linux-n900 tree [1] for comments. More
patches come from David's monitor & packet injection work. Patches are tested
with 3.12 rc5 kernel on Nokia N900.

Second version contains new patch for fixing NULL pointer dereference which
sometimes cause kernel panic and fixes code suggested by Pavel Machek.

[1] - https://gitorious.org/linux-n900/linux-n900

David Gnedt (12):
wl1251: fix scan behaviour while not associated
wl1251: add sysfs interface for bluetooth coexistence mode
configuration
wl1251: retry power save entry
wl1251: implement hardware ARP filtering
wl1251: split RX and TX data path initialisation
wl1251: configure hardware en-/decryption for monitor mode
wl1251: implement multicast address filtering
wl1251: disable power saving in monitor mode
wl1251: fix channel switching in monitor mode
wl1251: enable tx path in monitor mode if necessary for packet
injection
wl1251: disable retry and ACK policy for injected packets
wl1251: enforce changed hw encryption support on monitor state change

Pali Rohár (4):
wl1251: add nvs file name to module firmware list
wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate
wl1251: Add sysfs file address for setting permanent mac address
wl1251: fix NULL pointer dereference

drivers/net/wireless/ti/wl1251/acx.c | 92 +++++-
drivers/net/wireless/ti/wl1251/acx.h | 34 ++-
drivers/net/wireless/ti/wl1251/boot.c | 3 +-
drivers/net/wireless/ti/wl1251/cmd.c | 59 +++-
drivers/net/wireless/ti/wl1251/cmd.h | 8 +-
drivers/net/wireless/ti/wl1251/event.c | 46 ++-
drivers/net/wireless/ti/wl1251/event.h | 7 +
drivers/net/wireless/ti/wl1251/init.c | 19 +-
drivers/net/wireless/ti/wl1251/main.c | 462 ++++++++++++++++++++++++++++++-
drivers/net/wireless/ti/wl1251/rx.c | 2 +-
drivers/net/wireless/ti/wl1251/tx.c | 35 ++-
drivers/net/wireless/ti/wl1251/wl1251.h | 14 +
12 files changed, 720 insertions(+), 61 deletions(-)

--
1.7.9.5


2013-12-10 17:52:21

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tuesday 10 December 2013 18:49:22 Dan Williams wrote:
> On Tue, 2013-12-10 at 18:14 +0100, Pali Rohár wrote:
> > On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> > > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > > Pali Rohár <[email protected]> writes:
> > > > > Driver wl1251 generating mac address randomly at
> > > > > startup and there is no way to set permanent mac
> > > > > address via SET_IEEE80211_PERM_ADDR. This patch
> > > > > export sysfs file which can set permanent mac address
> > > > > by userspace helper program. Patch is needed for
> > > > > devices which do not store mac address in internal
> > > > > wl1251 eeprom.
> > > > >
> > > > > Signed-off-by: Pali Rohár <[email protected]>
> > > >
> > > > We have ioctl() command for setting the mac address.
> > >
> > > Really? Is there ioctl for setting permanent mac address?
> > > Can you show me it?
> >
> > Now I looked at it again and I did not found any ioctl for
> > it. There is only ioctl cmd for getting address, not
> > setting it.
> >
> > #define SIOCETHTOOL 0x8946
> >
> > /* Get permanent hardware address */
> > #define ETHTOOL_GPERMADDR 0x00000020
>
> Yeah, because it's supposed to be permanent and unchanging.
> Which means if there was an ioctl for it, that would be
> contrary to the purpose of a permanent MAC address.
>
> I realize the N900 stores the WiFi MAC address completely
> differently than many other systems, and that's why this
> sysfs file was created. I don't really have a great
> converged solution for that, other than what you've currently
> got, or perhaps adding SPERMADDR to ethtool. One thing I
> *would* like though, is a restriction on the sysfs file such
> that if the permanent MAC is already set, it cannot be set
> again. Otherwise the permanent MAC address isn't permanent
> at all.
>
> Dan

Maybe another way could be to use request_firmware to load address
from userspace... Or what do you think?

--
Pali Rohár
[email protected]


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

2013-12-08 09:27:26

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 08/16] wl1251: disable power saving in monitor mode

From: David Gnedt <[email protected]>

Force power saving off while monitor interface is present.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index ee318c8..1223bc6 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -570,6 +570,11 @@ static int wl1251_build_qos_null_data(struct wl1251 *wl)
sizeof(template));
}

+static bool wl1251_can_do_pm(struct ieee80211_conf *conf, struct wl1251 *wl)
+{
+ return (conf->flags & IEEE80211_CONF_PS) && !wl->monitor_present;
+}
+
static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct wl1251 *wl = hw->priv;
@@ -617,7 +622,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
goto out_sleep;
}

- if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
+ if (wl1251_can_do_pm(conf, wl) && !wl->psm_requested) {
wl1251_debug(DEBUG_PSM, "psm enabled");

wl->psm_requested = true;
@@ -633,8 +638,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
if (ret < 0)
goto out_sleep;
- } else if (!(conf->flags & IEEE80211_CONF_PS) &&
- wl->psm_requested) {
+ } else if (!wl1251_can_do_pm(conf, wl) && wl->psm_requested) {
wl1251_debug(DEBUG_PSM, "psm disabled");

wl->psm_requested = false;
--
1.7.9.5


2013-12-10 17:08:49

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

On Tuesday 10 December 2013 16:41:04 Kalle Valo wrote:
> Pavel Machek <[email protected]> writes:
> > ssids can have \0s in them... and what is worse, they may
> > not be 0 terminated AFAICT.
> >
> > Potential solution is at
> > http://www.spinics.net/lists/linux-wireless/msg98640.html .
>
> I just use print_hex_dump_bytes() to print SSIDs.

Ok and has kernel printf modifier for size_t?

--
Pali Rohár
[email protected]


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

2013-12-10 09:39:07

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 07/16] wl1251: implement multicast address filtering

On Sun 2013-12-08 10:25:05, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Port multicast address filtering from wl1271 driver.
> It sets up the hardware multicast address filter in configure_filter() with
> addresses supplied through prepare_multicast().
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel
> ---
> drivers/net/wireless/ti/wl1251/acx.c | 9 ++---
> drivers/net/wireless/ti/wl1251/acx.h | 9 ++---
> drivers/net/wireless/ti/wl1251/init.c | 2 +-
> drivers/net/wireless/ti/wl1251/main.c | 57 +++++++++++++++++++++++++++++--
> drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
> 5 files changed, 67 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
> index 1ec98e9..f772e62 100644
> --- a/drivers/net/wireless/ti/wl1251/acx.c
> +++ b/drivers/net/wireless/ti/wl1251/acx.c
> @@ -408,7 +408,8 @@ out:
> return ret;
> }
>
> -int wl1251_acx_group_address_tbl(struct wl1251 *wl)
> +int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
> + void *mc_list, u32 mc_list_len)
> {
> struct acx_dot11_grp_addr_tbl *acx;
> int ret;
> @@ -422,9 +423,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
> }
>
> /* MAC filtering */
> - acx->enabled = 0;
> - acx->num_groups = 0;
> - memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
> + acx->enabled = enable;
> + acx->num_groups = mc_list_len;
> + memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
>
> ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
> acx, sizeof(*acx));
> diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
> index bea2e67..820573c 100644
> --- a/drivers/net/wireless/ti/wl1251/acx.h
> +++ b/drivers/net/wireless/ti/wl1251/acx.h
> @@ -350,8 +350,8 @@ struct acx_slot {
> } __packed;
>
>
> -#define ADDRESS_GROUP_MAX (8)
> -#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
> +#define ACX_MC_ADDRESS_GROUP_MAX (8)
> +#define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
>
> struct acx_dot11_grp_addr_tbl {
> struct acx_header header;
> @@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
> u8 enabled;
> u8 num_groups;
> u8 pad[2];
> - u8 mac_table[ADDRESS_GROUP_MAX_LEN];
> + u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
> } __packed;
>
>
> @@ -1464,7 +1464,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
> int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
> int wl1251_acx_pd_threshold(struct wl1251 *wl);
> int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
> -int wl1251_acx_group_address_tbl(struct wl1251 *wl);
> +int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
> + void *mc_list, u32 mc_list_len);
> int wl1251_acx_service_period_timeout(struct wl1251 *wl);
> int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
> int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
> diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
> index 92de289..f8a2ea9 100644
> --- a/drivers/net/wireless/ti/wl1251/init.c
> +++ b/drivers/net/wireless/ti/wl1251/init.c
> @@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
> if (ret < 0)
> return ret;
>
> - ret = wl1251_acx_group_address_tbl(wl);
> + ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
> if (ret < 0)
> return ret;
>
> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 39a6105..ee318c8 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -29,6 +29,7 @@
> #include <linux/vmalloc.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> +#include <linux/netdevice.h>
>
> #include "wl1251.h"
> #include "wl12xx_80211.h"
> @@ -678,6 +679,44 @@ out:
> return ret;
> }
>
> +struct wl1251_filter_params {
> + bool enabled;
> + int mc_list_length;
> + u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
> +};
> +
> +static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
> + struct netdev_hw_addr_list *mc_list)
> +{
> + struct wl1251_filter_params *fp;
> + struct netdev_hw_addr *ha;
> + struct wl1251 *wl = hw->priv;
> +
> + if (unlikely(wl->state == WL1251_STATE_OFF))
> + return 0;
> +
> + fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
> + if (!fp) {
> + wl1251_error("Out of memory setting filters.");
> + return 0;
> + }
> +
> + /* update multicast filtering parameters */
> + fp->mc_list_length = 0;
> + if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
> + fp->enabled = false;
> + } else {
> + fp->enabled = true;
> + netdev_hw_addr_list_for_each(ha, mc_list) {
> + memcpy(fp->mc_list[fp->mc_list_length],
> + ha->addr, ETH_ALEN);
> + fp->mc_list_length++;
> + }
> + }
> +
> + return (u64)(unsigned long)fp;
> +}
> +
> #define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
> FIF_ALLMULTI | \
> FIF_FCSFAIL | \
> @@ -688,8 +727,9 @@ out:
>
> static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
> unsigned int changed,
> - unsigned int *total,u64 multicast)
> + unsigned int *total, u64 multicast)
> {
> + struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
> struct wl1251 *wl = hw->priv;
> int ret;
>
> @@ -698,9 +738,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
> *total &= WL1251_SUPPORTED_FILTERS;
> changed &= WL1251_SUPPORTED_FILTERS;
>
> - if (changed == 0)
> + if (changed == 0) {
> /* no filters which we support changed */
> + kfree(fp);
> return;
> + }
>
> mutex_lock(&wl->mutex);
>
> @@ -737,6 +779,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
> if (ret < 0)
> goto out;
>
> + if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
> + ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
> + else if (fp)
> + ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
> + fp->mc_list,
> + fp->mc_list_length);
> + if (ret < 0)
> + goto out;
> +
> /* send filters to firmware */
> wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
>
> @@ -744,6 +795,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
>
> out:
> mutex_unlock(&wl->mutex);
> + kfree(fp);
> }
>
> /* HW encryption */
> @@ -1283,6 +1335,7 @@ static const struct ieee80211_ops wl1251_ops = {
> .add_interface = wl1251_op_add_interface,
> .remove_interface = wl1251_op_remove_interface,
> .config = wl1251_op_config,
> + .prepare_multicast = wl1251_op_prepare_multicast,
> .configure_filter = wl1251_op_configure_filter,
> .tx = wl1251_op_tx,
> .set_key = wl1251_op_set_key,
> diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
> index 45df03a..93c18d2 100644
> --- a/drivers/net/wireless/ti/wl1251/wl1251.h
> +++ b/drivers/net/wireless/ti/wl1251/wl1251.h
> @@ -93,6 +93,7 @@ enum {
> } while (0)
>
> #define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
> + CFG_MC_FILTER_EN | \
> CFG_BSSID_FILTER_EN)
>
> #define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \

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

2013-12-11 21:17:40

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tue, 2013-12-10 at 18:52 +0100, Pali Rohár wrote:
> On Tuesday 10 December 2013 18:49:22 Dan Williams wrote:
> > On Tue, 2013-12-10 at 18:14 +0100, Pali Rohár wrote:
> > > On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> > > > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > > > Pali Rohár <[email protected]> writes:
> > > > > > Driver wl1251 generating mac address randomly at
> > > > > > startup and there is no way to set permanent mac
> > > > > > address via SET_IEEE80211_PERM_ADDR. This patch
> > > > > > export sysfs file which can set permanent mac address
> > > > > > by userspace helper program. Patch is needed for
> > > > > > devices which do not store mac address in internal
> > > > > > wl1251 eeprom.
> > > > > >
> > > > > > Signed-off-by: Pali Rohár <[email protected]>
> > > > >
> > > > > We have ioctl() command for setting the mac address.
> > > >
> > > > Really? Is there ioctl for setting permanent mac address?
> > > > Can you show me it?
> > >
> > > Now I looked at it again and I did not found any ioctl for
> > > it. There is only ioctl cmd for getting address, not
> > > setting it.
> > >
> > > #define SIOCETHTOOL 0x8946
> > >
> > > /* Get permanent hardware address */
> > > #define ETHTOOL_GPERMADDR 0x00000020
> >
> > Yeah, because it's supposed to be permanent and unchanging.
> > Which means if there was an ioctl for it, that would be
> > contrary to the purpose of a permanent MAC address.
> >
> > I realize the N900 stores the WiFi MAC address completely
> > differently than many other systems, and that's why this
> > sysfs file was created. I don't really have a great
> > converged solution for that, other than what you've currently
> > got, or perhaps adding SPERMADDR to ethtool. One thing I
> > *would* like though, is a restriction on the sysfs file such
> > that if the permanent MAC is already set, it cannot be set
> > again. Otherwise the permanent MAC address isn't permanent
> > at all.

I'm really uncomfortable with the idea of involving userland in
establishing the 'permanent' MAC address. (And from what I gather, the
Nokia software never did that but only used SIOCSIFHWADDR.) It ought to
be set before the interface is ever registered.

> > Dan
>
> Maybe another way could be to use request_firmware to load address
> from userspace... Or what do you think?

I think that's an even worse idea. This is not firmware and it already
exists in separate storage.

I think that rx51_init_wl1251() in
arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
address out of NVRAM, or if it's too early to do that, then schedule a
function to run later and only then set up wl1251 platform data.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-10 19:31:29

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tuesday 10 December 2013 20:22:19 Dan Williams wrote:
> On Tue, 2013-12-10 at 18:52 +0100, Pali Rohár wrote:
> > On Tuesday 10 December 2013 18:49:22 Dan Williams wrote:
> > > On Tue, 2013-12-10 at 18:14 +0100, Pali Rohár wrote:
> > > > On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> > > > > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > > > > Pali Rohár <[email protected]> writes:
> > > > > > > Driver wl1251 generating mac address randomly at
> > > > > > > startup and there is no way to set permanent mac
> > > > > > > address via SET_IEEE80211_PERM_ADDR. This patch
> > > > > > > export sysfs file which can set permanent mac
> > > > > > > address by userspace helper program. Patch is
> > > > > > > needed for devices which do not store mac address
> > > > > > > in internal wl1251 eeprom.
> > > > > > >
> > > > > > > Signed-off-by: Pali Rohár <[email protected]>
> > > > > >
> > > > > > We have ioctl() command for setting the mac address.
> > > > >
> > > > > Really? Is there ioctl for setting permanent mac
> > > > > address? Can you show me it?
> > > >
> > > > Now I looked at it again and I did not found any ioctl
> > > > for it. There is only ioctl cmd for getting address,
> > > > not setting it.
> > > >
> > > > #define SIOCETHTOOL 0x8946
> > > >
> > > > /* Get permanent hardware address */
> > > > #define ETHTOOL_GPERMADDR 0x00000020
> > >
> > > Yeah, because it's supposed to be permanent and
> > > unchanging. Which means if there was an ioctl for it,
> > > that would be contrary to the purpose of a permanent MAC
> > > address.
> > >
> > > I realize the N900 stores the WiFi MAC address completely
> > > differently than many other systems, and that's why this
> > > sysfs file was created. I don't really have a great
> > > converged solution for that, other than what you've
> > > currently got, or perhaps adding SPERMADDR to ethtool.
> > > One thing I *would* like though, is a restriction on the
> > > sysfs file such that if the permanent MAC is already set,
> > > it cannot be set again. Otherwise the permanent MAC
> > > address isn't permanent at all.
> > >
> > > Dan
> >
> > Maybe another way could be to use request_firmware to load
> > address from userspace... Or what do you think?
>
> That sounds like a great idea to try. A number of devices
> either need stub firmware to read the MAC from EEPROM, or do
> use request_firmware() to load firmware before they read the
> MAC. You may have to use request_firmware() synchronously
> though to ensure that the MAC is read before registering with
> mac80211.
>
> Dan

So, if you like this idea, can you help me how to write udev rule
which will run my own program (it print mac address) and send mac
address when driver ask for mac address in request_firmware?
Problem is that default udev rule for firmware trying to load data
from /lib/firmware/... but in this case mac address first must be
read from special location and converted to correct format.

--
Pali Rohár
[email protected]


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

2013-12-11 22:52:52

by Dan Williams

[permalink] [raw]
Subject: Re: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Wed, 2013-12-11 at 22:15 +0000, Ben Hutchings wrote:
> On Wed, 2013-12-11 at 23:35 +0200, Ivajlo Dimitrov wrote:
> > On 11.12.2013 23:17, Ben Hutchings wrote:
> > > I think that's an even worse idea. This is not firmware and it already
> > > exists in separate storage.
> > >
> > > I think that rx51_init_wl1251() in
> > > arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
> > > address out of NVRAM, or if it's too early to do that, then schedule a
> > > function to run later and only then set up wl1251 platform data.
> > >
> > > Ben.
> > >
> >
> > And how will that work with DT when board files will be in the history?
>
> 1. Boot loader reads the MAC address from NVRAM and puts it in the DT
> node.
> or
> 2. NVRAM reading is done by a tiny driver that is loaded based on the
> platform name and updates the DT node in memory. (But I don't know how
> wl1251 should decide to defer probing if it's probed before that other
> driver.)

I'm uncomfortable with it too, and yes the permanent MAC should really
be known before the interface is even registered, but...

Imagine if the MAC address for your ethernet device was stored
in /etc/my-mac-addr.txt, except that /etc was a read-only protected
partition from a very small SSD. That's essentially the N900; it's
stored in a file in a normal ext2/ext3 (?) filesystem on a partition of
the internal flash. It seems like overkill to write a small driver that
duplicates the ext3 + MTD drivers just to read the MAC.

There's got to be a better way to do this than having it set from
userspace though, but I don't know what that is. The request_firmware()
method would probably run into race conditions, since who knows if the
partition gets mounted before the WiFi gets initialized? I suppose the
firmware helper could block until it did, and while that's ugly, it's
the best approach I've seen yet that doesn't violate the "permanent"
idea here.

Dan


2013-12-08 09:27:37

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 16/16] wl1251: fix NULL pointer dereference

Signed-off-by: Pali Rohár <[email protected]>
Reported-by: Felipe Contreras <[email protected]>
---
drivers/net/wireless/ti/wl1251/event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index 192cebd..db01053 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -124,7 +124,7 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
return ret;
}

- if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
+ if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");

/* indicate to the stack, that beacons have been lost */
--
1.7.9.5


2013-12-10 09:43:17

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 09/16] wl1251: fix channel switching in monitor mode

On Sun 2013-12-08 10:25:07, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Use the ENABLE_RX command for channel switching when no interface is present
> (monitor mode only).
> The advantage of ENABLE_RX is that it leaves the tx data path disabled in
> firmware, whereas the usual JOIN command seems to transmit some frames at
> firmware level.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel

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

2013-12-31 09:44:14

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

On Tuesday 10 December 2013 10:21:14 Pavel Machek wrote:
> Hi!
>
> > diff --git a/drivers/net/wireless/ti/wl1251/cmd.c
> > b/drivers/net/wireless/ti/wl1251/cmd.c index
> > 6822b84..16b6479 100644
> > --- a/drivers/net/wireless/ti/wl1251/cmd.c
> > +++ b/drivers/net/wireless/ti/wl1251/cmd.c
> > @@ -410,7 +411,10 @@ int wl1251_cmd_scan(struct wl1251 *wl,
> > u8 *ssid, size_t ssid_len,
> >
> > struct wl1251_cmd_scan *cmd;
> > int i, ret = 0;
> >
> > - wl1251_debug(DEBUG_CMD, "cmd scan");
> > + wl1251_debug(DEBUG_CMD, "cmd scan channels %d ssid(%d)
> > '%s'", + n_channels, (int)ssid_len, ssid);
> > +
> > + WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);
>
> ssids can have \0s in them... and what is worse, they may not
> be 0 terminated AFAICT.
>
> Potential solution is at
> http://www.spinics.net/lists/linux-wireless/msg98640.html .
>
> Thanks,
> Pavel

Ok. To prevent other problems in future, I removed printing ssid
and len params from debug output. I think it is not needed...

Here is updated patch:

From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <[email protected]>
Subject: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated
Date: Sun, 8 Dec 2013 10:24:59 +0100
MIME-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 8bit

From: David Gnedt <[email protected]>

With a dissacociated card I often encoutered very long scan delays.

My guess is that it has something to do with the cards DTIM handling and
another firmware bug mentioned in the TI WLAN driver, which is described as
the card may never end scanning if the channel is overloaded because it
can't send probe requests. I think the firmware somehow also tries to
receive DTIM messages when the BSSID is not set. Therefore most of the time
it waits for DTIM messages and can't do scanning work.

Anyway we can workaround this misbehaviour by setting the HIGH_PRIORITY
bit for scans in disassociated state.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/cmd.c | 13 ++++++++++++-
drivers/net/wireless/ti/wl1251/cmd.h | 5 +++++
drivers/net/wireless/ti/wl1251/main.c | 1 +
3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index 6822b84..16b6479 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -3,6 +3,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/crc7.h>
+#include <linux/etherdevice.h>

#include "wl1251.h"
#include "reg.h"
@@ -410,7 +411,9 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
struct wl1251_cmd_scan *cmd;
int i, ret = 0;

- wl1251_debug(DEBUG_CMD, "cmd scan");
+ wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels);
+
+ WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);

cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
@@ -421,6 +425,13 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
CFG_RX_MGMT_EN |
CFG_RX_BCN_EN);
cmd->params.scan_options = 0;
+ /*
+ * Use high priority scan when not associated to prevent fw issue
+ * causing never-ending scans (sometimes 20+ minutes).
+ * Note: This bug may be caused by the fw's DTIM handling.
+ */
+ if (is_zero_ether_addr(wl->bssid))
+ cmd->params.scan_options |= WL1251_SCAN_OPT_PRIORITY_HIGH;
cmd->params.num_channels = n_channels;
cmd->params.num_probe_requests = n_probes;
cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
diff --git a/drivers/net/wireless/ti/wl1251/cmd.h b/drivers/net/wireless/ti/wl1251/cmd.h
index ee4f2b3..126f273 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.h
+++ b/drivers/net/wireless/ti/wl1251/cmd.h
@@ -167,6 +167,11 @@ struct cmd_read_write_memory {
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4

+#define WL1251_SCAN_OPT_PASSIVE 1
+#define WL1251_SCAN_OPT_5GHZ_BAND 2
+#define WL1251_SCAN_OPT_TRIGGERD_SCAN 4
+#define WL1251_SCAN_OPT_PRIORITY_HIGH 8
+
#define WL1251_SCAN_MIN_DURATION 30000
#define WL1251_SCAN_MAX_DURATION 60000

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 3291ffa..4d89ac8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -930,6 +930,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
ret = wl1251_cmd_scan(wl, ssid, ssid_len, req->channels,
req->n_channels, WL1251_SCAN_NUM_PROBES);
if (ret < 0) {
+ wl1251_debug(DEBUG_SCAN, "scan failed %d", ret);
wl->scanning = false;
goto out_idle;
}
--
1.7.9.5

--
Pali Rohár
[email protected]


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

2013-12-10 09:59:42

by Michal Kubecek

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] wl1251: implement hardware ARP filtering

On Tue, Dec 10, 2013 at 10:29:16AM +0100, Pavel Machek wrote:
> >
> > +int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
> > +{
> > + struct wl1251_acx_arp_filter *acx;
> > + int ret;
>
> Is it good idea to use be32 for IP address? AFAICT IPv4 addresses
> really don't have edianity. Perhaps u32 is better?

If they are known to be in network byte ordering, they do (as NBO is the
same as BE).

Michal Kubecek


2013-12-12 10:56:51

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Wed 2013-12-11 21:17:34, Ben Hutchings wrote:
> On Tue, 2013-12-10 at 18:52 +0100, Pali Roh?r wrote:
> > On Tuesday 10 December 2013 18:49:22 Dan Williams wrote:
> > > On Tue, 2013-12-10 at 18:14 +0100, Pali Roh?r wrote:
> > > > On Tuesday 10 December 2013 17:10:50 Pali Roh?r wrote:
> > > > > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > > > > Pali Roh?r <[email protected]> writes:
> > > > > > > Driver wl1251 generating mac address randomly at
> > > > > > > startup and there is no way to set permanent mac
> > > > > > > address via SET_IEEE80211_PERM_ADDR. This patch
> > > > > > > export sysfs file which can set permanent mac address
> > > > > > > by userspace helper program. Patch is needed for
> > > > > > > devices which do not store mac address in internal
> > > > > > > wl1251 eeprom.
> > > > > > >
> > > > > > > Signed-off-by: Pali Roh?r <[email protected]>
> > > > > >
> > > > > > We have ioctl() command for setting the mac address.
> > > > >
> > > > > Really? Is there ioctl for setting permanent mac address?
> > > > > Can you show me it?
> > > >
> > > > Now I looked at it again and I did not found any ioctl for
> > > > it. There is only ioctl cmd for getting address, not
> > > > setting it.
> > > >
> > > > #define SIOCETHTOOL 0x8946
> > > >
> > > > /* Get permanent hardware address */
> > > > #define ETHTOOL_GPERMADDR 0x00000020
> > >
> > > Yeah, because it's supposed to be permanent and unchanging.
> > > Which means if there was an ioctl for it, that would be
> > > contrary to the purpose of a permanent MAC address.
> > >
> > > I realize the N900 stores the WiFi MAC address completely
> > > differently than many other systems, and that's why this
> > > sysfs file was created. I don't really have a great
> > > converged solution for that, other than what you've currently
> > > got, or perhaps adding SPERMADDR to ethtool. One thing I
> > > *would* like though, is a restriction on the sysfs file such
> > > that if the permanent MAC is already set, it cannot be set
> > > again. Otherwise the permanent MAC address isn't permanent
> > > at all.
>
> I'm really uncomfortable with the idea of involving userland in
> establishing the 'permanent' MAC address. (And from what I gather, the
> Nokia software never did that but only used SIOCSIFHWADDR.) It ought to
> be set before the interface is ever registered.

Which is hard to do on n900. What is the problem with userland setting
permanent mac address?

It is not used for security or anything...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2013-12-09 16:55:12

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH v2 14/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate

On Sun, 2013-12-08 at 10:25 +0100, Pali Rohár wrote:
> This patch adds support for configuring reg domains.
> Patch was extracted from Maemo 2.6.28 kernel.
>
> Signed-off-by: Pali Rohár <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/main.c | 152 +++++++++++++++++++++++++++++++++
> 1 file changed, 152 insertions(+)

Isn't this supposed to be done automatically by the rate control
modules? Seems pretty wrong to have it done via a sysfs file. If the
maemo code was twiddling the TX rate for management frames so that it
could get more reliable DHCP or 802.1x, we have better nl80211
mechanisms for that now.

Also, the patch description is wrong. This doesn't really add support
for "configuring reg domains" at all.

Dan

> diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
> index 382dedf..42730b7 100644
> --- a/drivers/net/wireless/ti/wl1251/main.c
> +++ b/drivers/net/wireless/ti/wl1251/main.c
> @@ -1377,6 +1377,147 @@ static const struct ieee80211_ops wl1251_ops = {
> .get_survey = wl1251_op_get_survey,
> };
>
> +static ssize_t wl1251_sysfs_show_tx_mgmt_frm_rate(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct wl1251 *wl = dev_get_drvdata(dev);
> + ssize_t len;
> + int val;
> +
> + /* FIXME: what's the maximum length of buf? page size?*/
> + len = 500;
> +
> + switch (wl->tx_mgmt_frm_rate) {
> + /* skip 1 and 12 Mbps because they have same value 0x0a */
> + case RATE_2MBPS:
> + val = 20;
> + break;
> + case RATE_5_5MBPS:
> + val = 55;
> + break;
> + case RATE_11MBPS:
> + val = 110;
> + break;
> + case RATE_6MBPS:
> + val = 60;
> + break;
> + case RATE_9MBPS:
> + val = 90;
> + break;
> + case RATE_12MBPS:
> + val = 120;
> + break;
> + case RATE_18MBPS:
> + val = 180;
> + break;
> + case RATE_24MBPS:
> + val = 240;
> + break;
> + case RATE_36MBPS:
> + val = 360;
> + break;
> + case RATE_48MBPS:
> + val = 480;
> + break;
> + case RATE_54MBPS:
> + val = 540;
> + break;
> + default:
> + val = 10;
> + }
> +
> + /* for 1 and 12 Mbps we have to check the modulation */
> + if (wl->tx_mgmt_frm_rate == RATE_1MBPS) {
> + switch (wl->tx_mgmt_frm_rate) {
> + case CCK_LONG:
> + val = 10;
> + break;
> + case OFDM:
> + val = 120;
> + break;
> + default:
> + val = 10;
> + break;
> + }
> + }
> + len = snprintf(buf, len, "%d", val);
> +
> + return len;
> +}
> +
> +static ssize_t wl1251_sysfs_store_tx_mgmt_frm_rate(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct wl1251 *wl = dev_get_drvdata(dev);
> + unsigned long res;
> + int ret;
> +
> + ret = strict_strtoul(buf, 10, &res);
> +
> + if (ret < 0) {
> + wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
> + return 0;
> + }
> +
> + switch (res) {
> + case 10:
> + wl->tx_mgmt_frm_rate = RATE_1MBPS;
> + wl->tx_mgmt_frm_mod = CCK_LONG;
> + break;
> + case 20:
> + wl->tx_mgmt_frm_rate = RATE_2MBPS;
> + wl->tx_mgmt_frm_mod = CCK_LONG;
> + break;
> + case 55:
> + wl->tx_mgmt_frm_rate = RATE_5_5MBPS;
> + wl->tx_mgmt_frm_mod = CCK_LONG;
> + break;
> + case 110:
> + wl->tx_mgmt_frm_rate = RATE_11MBPS;
> + wl->tx_mgmt_frm_mod = CCK_LONG;
> + break;
> + case 60:
> + wl->tx_mgmt_frm_rate = RATE_6MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 90:
> + wl->tx_mgmt_frm_rate = RATE_9MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 120:
> + wl->tx_mgmt_frm_rate = RATE_12MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 180:
> + wl->tx_mgmt_frm_rate = RATE_18MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 240:
> + wl->tx_mgmt_frm_rate = RATE_24MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 360:
> + wl->tx_mgmt_frm_rate = RATE_36MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 480:
> + wl->tx_mgmt_frm_rate = RATE_48MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + case 540:
> + wl->tx_mgmt_frm_rate = RATE_54MBPS;
> + wl->tx_mgmt_frm_mod = OFDM;
> + break;
> + default:
> + wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
> + return 0;
> + }
> +
> + return count;
> +}
> +
> static ssize_t wl1251_sysfs_show_bt_coex_mode(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -1445,6 +1586,10 @@ out:
> return count;
> }
>
> +static DEVICE_ATTR(tx_mgmt_frm_rate, S_IRUGO | S_IWUSR,
> + wl1251_sysfs_show_tx_mgmt_frm_rate,
> + wl1251_sysfs_store_tx_mgmt_frm_rate);
> +
> static DEVICE_ATTR(bt_coex_mode, S_IRUGO | S_IWUSR,
> wl1251_sysfs_show_bt_coex_mode,
> wl1251_sysfs_store_bt_coex_mode);
> @@ -1585,6 +1730,13 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
> }
> dev_set_drvdata(&wl1251_device.dev, wl);
>
> + /* Create sysfs file tx_mgmt_frm_rate */
> + ret = device_create_file(&wl1251_device.dev,
> + &dev_attr_tx_mgmt_frm_rate);
> + if (ret < 0) {
> + wl1251_error("failed to create sysfs file tx_mgmt_frm_rate");
> + goto out;
> + }
>
> /* Create sysfs file to control bt coex state */
> ret = device_create_file(&wl1251_device.dev, &dev_attr_bt_coex_mode);



2013-12-08 09:27:24

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 06/16] wl1251: configure hardware en-/decryption for monitor mode

From: David Gnedt <[email protected]>

Disable hardware encryption (DF_ENCRYPTION_DISABLE) and decryption
(DF_SNIFF_MODE_ENABLE) via wl1251_acx_feature_cfg while monitor interface is
present.

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 6 +++---
drivers/net/wireless/ti/wl1251/acx.h | 2 +-
drivers/net/wireless/ti/wl1251/init.c | 2 +-
drivers/net/wireless/ti/wl1251/main.c | 34 ++++++++++++++++++++++++++-----
drivers/net/wireless/ti/wl1251/rx.c | 2 +-
drivers/net/wireless/ti/wl1251/tx.c | 3 +++
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
7 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 5f4a552..1ec98e9 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -209,7 +209,7 @@ out:
return ret;
}

-int wl1251_acx_feature_cfg(struct wl1251 *wl)
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options)
{
struct acx_feature_config *feature;
int ret;
@@ -222,8 +222,8 @@ int wl1251_acx_feature_cfg(struct wl1251 *wl)
goto out;
}

- /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
- feature->data_flow_options = 0;
+ /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE can be set */
+ feature->data_flow_options = data_flow_options;
feature->options = 0;

ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index 4444cd0..bea2e67 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -1455,7 +1455,7 @@ int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event,
int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth);
int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len);
int wl1251_acx_tx_power(struct wl1251 *wl, int power);
-int wl1251_acx_feature_cfg(struct wl1251 *wl);
+int wl1251_acx_feature_cfg(struct wl1251 *wl, u32 data_flow_options);
int wl1251_acx_mem_map(struct wl1251 *wl,
struct acx_header *mem_map, size_t len);
int wl1251_acx_data_path_params(struct wl1251 *wl,
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 424ce01..92de289 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -33,7 +33,7 @@ int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
{
int ret;

- ret = wl1251_acx_feature_cfg(wl);
+ ret = wl1251_acx_feature_cfg(wl, 0);
if (ret < 0) {
wl1251_warning("couldn't set feature config");
return ret;
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 0e27f1f..39a6105 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -485,6 +485,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
wl->rssi_thold = 0;
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;

wl1251_debugfs_reset(wl);

@@ -577,8 +578,10 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
channel = ieee80211_frequency_to_channel(
conf->chandef.chan->center_freq);

- wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
+ wl1251_debug(DEBUG_MAC80211,
+ "mac80211 config ch %d monitor %s psm %s power %d",
channel,
+ conf->flags & IEEE80211_CONF_MONITOR ? "on" : "off",
conf->flags & IEEE80211_CONF_PS ? "on" : "off",
conf->power_level);

@@ -588,6 +591,22 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
if (ret < 0)
goto out;

+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ u32 mode;
+
+ if (conf->flags & IEEE80211_CONF_MONITOR) {
+ wl->monitor_present = true;
+ mode = DF_SNIFF_MODE_ENABLE | DF_ENCRYPTION_DISABLE;
+ } else {
+ wl->monitor_present = false;
+ mode = 0;
+ }
+
+ ret = wl1251_acx_feature_cfg(wl, mode);
+ if (ret < 0)
+ goto out_sleep;
+ }
+
if (channel != wl->channel) {
wl->channel = channel;

@@ -804,12 +823,12 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

mutex_lock(&wl->mutex);

- ret = wl1251_ps_elp_wakeup(wl);
- if (ret < 0)
- goto out_unlock;
-
switch (cmd) {
case SET_KEY:
+ if (wl->monitor_present) {
+ ret = -EOPNOTSUPP;
+ goto out_unlock;
+ }
wl_cmd->key_action = KEY_ADD_OR_REPLACE;
break;
case DISABLE_KEY:
@@ -820,6 +839,10 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
}

+ ret = wl1251_ps_elp_wakeup(wl);
+ if (ret < 0)
+ goto out_unlock;
+
ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr);
if (ret < 0) {
wl1251_error("Set KEY type failed");
@@ -1520,6 +1543,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)

INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work);
wl->channel = WL1251_DEFAULT_CHANNEL;
+ wl->monitor_present = false;
wl->scanning = false;
wl->default_key = 0;
wl->listen_int = 1;
diff --git a/drivers/net/wireless/ti/wl1251/rx.c b/drivers/net/wireless/ti/wl1251/rx.c
index 23289d4..123c4bb 100644
--- a/drivers/net/wireless/ti/wl1251/rx.c
+++ b/drivers/net/wireless/ti/wl1251/rx.c
@@ -83,7 +83,7 @@ static void wl1251_rx_status(struct wl1251 *wl,

status->flag |= RX_FLAG_MACTIME_START;

- if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
+ if (!wl->monitor_present && (desc->flags & RX_DESC_ENCRYPTION_MASK)) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;

if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL)))
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c
index 28121c5..3cc82fd 100644
--- a/drivers/net/wireless/ti/wl1251/tx.c
+++ b/drivers/net/wireless/ti/wl1251/tx.c
@@ -287,6 +287,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb)
info = IEEE80211_SKB_CB(skb);

if (info->control.hw_key) {
+ if (unlikely(wl->monitor_present))
+ return -1;
+
idx = info->control.hw_key->hw_key_idx;
if (unlikely(wl->default_key != idx)) {
ret = wl1251_acx_default_key(wl, idx);
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index de9e418..45df03a 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -309,6 +309,7 @@ struct wl1251 {
u8 bss_type;
u8 listen_int;
int channel;
+ bool monitor_present;

void *target_mem_map;
struct acx_data_path_params_resp *data_path;
--
1.7.9.5


2013-12-12 20:24:44

by Ivaylo Dimitrov

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address


On 12.12.2013 21:55, Ben Hutchings wrote:
> On Wed, 2013-12-11 at 16:53 -0600, Dan Williams wrote:
>> On Wed, 2013-12-11 at 22:15 +0000, Ben Hutchings wrote:
>>> On Wed, 2013-12-11 at 23:35 +0200, Ivajlo Dimitrov wrote:
>>>> On 11.12.2013 23:17, Ben Hutchings wrote:
>>>>> I think that's an even worse idea. This is not firmware and it already
>>>>> exists in separate storage.
>>>>>
>>>>> I think that rx51_init_wl1251() in
>>>>> arch/arm/mach-omap2/board-rx51-peripherals.c should either copy the MAC
>>>>> address out of NVRAM, or if it's too early to do that, then schedule a
>>>>> function to run later and only then set up wl1251 platform data.
>>>>>
>>>>> Ben.
>>>>>
>>>> And how will that work with DT when board files will be in the history?
>>> 1. Boot loader reads the MAC address from NVRAM and puts it in the DT
>>> node.
>>> or
>>> 2. NVRAM reading is done by a tiny driver that is loaded based on the
>>> platform name and updates the DT node in memory. (But I don't know how
>>> wl1251 should decide to defer probing if it's probed before that other
>>> driver.)
>> I'm uncomfortable with it too, and yes the permanent MAC should really
>> be known before the interface is even registered, but...
>>
>> Imagine if the MAC address for your ethernet device was stored
>> in /etc/my-mac-addr.txt, except that /etc was a read-only protected
>> partition from a very small SSD. That's essentially the N900; it's
>> stored in a file in a normal ext2/ext3 (?) filesystem on a partition of
>> the internal flash.
> Oh, from my quick look I got the impression that this 'CAL' was stored
> directly in a specific flash partition.
>
>> It seems like overkill to write a small driver that
>> duplicates the ext3 + MTD drivers just to read the MAC.
> [...]
>
> I don't see that anything would need to be duplicated. But reading
> files from the kernel is really ugly, and deciding when to read the file
> would be another problem (as you noted).
>
> Ben
>
Yes, CAL is stored in /dev/mtd1, a dedicated partition in the NAND
flash. But reading the data stored in it from the kernel is not a
trivial task, as it uses its own pseudo-fs format etc. Not impossible (I
RE-ed libcal a while ago [0], so there is a code that could be reused,
calvaria works too afaik), but still doesn't sound like a very good idea.

[0]
https://gitorious.org/community-ssu/libcal/source/d4c5fd9293ddb693c9b032b4c084cd0343b3ea26:

Ivo

2013-12-10 09:48:48

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 12/16] wl1251: enforce changed hw encryption support on monitor state change

On Sun 2013-12-08 10:25:10, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> The firmware doesn't support per packet encryption selection, so disable hw
> encryption support completely while a monitor interface is present to support
> injection of packets (which shouldn't get encrypted by hw).
> To enforce the changed hw encryption support force a disassociation on
> non-monitor interfaces.
> For disassociation a workaround using hw connection monitor is employed,
> which temporary enables hw connection manager flag.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel

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

2013-12-10 16:09:43

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 02/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration

On Tuesday 10 December 2013 16:46:54 Kalle Valo wrote:
> Pali Rohár <[email protected]> writes:
> > From: David Gnedt <[email protected]>
> >
> > Port the bt_coex_mode sysfs interface from wl1251 driver
> > version included in the Maemo Fremantle kernel to allow
> > bt-coexistence mode configuration. This enables userspace
> > applications to set one of the modes WL1251_BT_COEX_OFF,
> > WL1251_BT_COEX_ENABLE and WL1251_BT_COEX_MONOAUDIO. The
> > default mode is WL1251_BT_COEX_OFF.
> > It should be noted that this driver always enabled
> > bt-coexistence before and enabled bt-coexistence directly
> > affects the receiving performance, rendering it unusable in
> > some low-signal situations. Especially monitor mode is
> > affected very badly with bt-coexistence enabled.
> >
> > Signed-off-by: David Gnedt <[email protected]>
> > Signed-off-by: Pali Rohár <[email protected]>
>
> I think this is also what I wrote a long time. And also this
> sysfs hack should not go to upstream.
>
> Over the years there has been some talk about solving the BT
> coex properly, but I haven't seen any patches. I guess the
> proper solution would be that BT subsystem in kernel would
> notify wireless drivers about BT use?

See other drivers in upstream, they doing something similar...

--
Pali Rohár
[email protected]


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

2013-12-08 08:46:34

by Pali Rohár

[permalink] [raw]
Subject: [PATCH] mac80211: fix TX device statistics for monitor interfaces

From: David Gnedt <[email protected]>

Count TX packets and bytes also for monitor interfaces.

Signed-off-by: David Gnedt <[email protected]>
---
net/mac80211/tx.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c558b24..37b38fb 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1623,6 +1623,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
if (unlikely(skb->len < len_rthdr))
goto fail; /* skb too short for claimed rt header extent */

+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
/*
* fix up the pointers accounting for the radiotap
* header still being in there. We are being given
--
1.7.9.5


2013-12-08 09:27:36

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

Driver wl1251 generating mac address randomly at startup and there is no way to
set permanent mac address via SET_IEEE80211_PERM_ADDR. This patch export sysfs
file which can set permanent mac address by userspace helper program. Patch is
needed for devices which do not store mac address in internal wl1251 eeprom.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 42730b7..a69b741 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1377,6 +1377,46 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_address(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ len = snprintf(buf, len, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ wl->mac_addr[0], wl->mac_addr[1], wl->mac_addr[2],
+ wl->mac_addr[3], wl->mac_addr[4], wl->mac_addr[5]);
+
+ return len;
+}
+
+static ssize_t wl1251_sysfs_store_address(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned int addr[6];
+ int ret, i;
+
+ ret = sscanf(buf, "%2x:%2x:%2x:%2x:%2x:%2x\n",
+ &addr[0], &addr[1], &addr[2],
+ &addr[3], &addr[4], &addr[5]);
+
+ if (ret != 6)
+ return -EINVAL;
+
+ for (i = 0; i < 6; i++)
+ wl->mac_addr[i] = addr[i] & 0xff;
+
+ SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
+
+ return count;
+}
+
static ssize_t wl1251_sysfs_show_tx_mgmt_frm_rate(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1586,6 +1626,10 @@ out:
return count;
}

+static DEVICE_ATTR(address, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_address,
+ wl1251_sysfs_store_address);
+
static DEVICE_ATTR(tx_mgmt_frm_rate, S_IRUGO | S_IWUSR,
wl1251_sysfs_show_tx_mgmt_frm_rate,
wl1251_sysfs_store_tx_mgmt_frm_rate);
@@ -1730,6 +1774,14 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
}
dev_set_drvdata(&wl1251_device.dev, wl);

+ /* Create sysfs file address */
+ ret = device_create_file(&wl1251_device.dev,
+ &dev_attr_address);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file address");
+ goto out;
+ }
+
/* Create sysfs file tx_mgmt_frm_rate */
ret = device_create_file(&wl1251_device.dev,
&dev_attr_tx_mgmt_frm_rate);
--
1.7.9.5


2013-12-10 17:48:41

by Dan Williams

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tue, 2013-12-10 at 18:14 +0100, Pali Rohár wrote:
> On Tuesday 10 December 2013 17:10:50 Pali Rohár wrote:
> > On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> > > Pali Rohár <[email protected]> writes:
> > > > Driver wl1251 generating mac address randomly at startup
> > > > and there is no way to set permanent mac address via
> > > > SET_IEEE80211_PERM_ADDR. This patch export sysfs file
> > > > which can set permanent mac address by userspace helper
> > > > program. Patch is needed for devices which do not store
> > > > mac address in internal wl1251 eeprom.
> > > >
> > > > Signed-off-by: Pali Rohár <[email protected]>
> > >
> > > We have ioctl() command for setting the mac address.
> >
> > Really? Is there ioctl for setting permanent mac address?
> > Can you show me it?
>
> Now I looked at it again and I did not found any ioctl for it.
> There is only ioctl cmd for getting address, not setting it.
>
> #define SIOCETHTOOL 0x8946
>
> /* Get permanent hardware address */
> #define ETHTOOL_GPERMADDR 0x00000020

Yeah, because it's supposed to be permanent and unchanging. Which means
if there was an ioctl for it, that would be contrary to the purpose of a
permanent MAC address.

I realize the N900 stores the WiFi MAC address completely differently
than many other systems, and that's why this sysfs file was created. I
don't really have a great converged solution for that, other than what
you've currently got, or perhaps adding SPERMADDR to ethtool. One thing
I *would* like though, is a restriction on the sysfs file such that if
the permanent MAC is already set, it cannot be set again. Otherwise the
permanent MAC address isn't permanent at all.

Dan



2013-12-08 09:27:25

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 07/16] wl1251: implement multicast address filtering

From: David Gnedt <[email protected]>

Port multicast address filtering from wl1271 driver.
It sets up the hardware multicast address filter in configure_filter() with
addresses supplied through prepare_multicast().

Signed-off-by: David Gnedt <[email protected]>
Signed-off-by: Pali Rohár <[email protected]>
---
drivers/net/wireless/ti/wl1251/acx.c | 9 ++---
drivers/net/wireless/ti/wl1251/acx.h | 9 ++---
drivers/net/wireless/ti/wl1251/init.c | 2 +-
drivers/net/wireless/ti/wl1251/main.c | 57 +++++++++++++++++++++++++++++--
drivers/net/wireless/ti/wl1251/wl1251.h | 1 +
5 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 1ec98e9..f772e62 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -408,7 +408,8 @@ out:
return ret;
}

-int wl1251_acx_group_address_tbl(struct wl1251 *wl)
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+ void *mc_list, u32 mc_list_len)
{
struct acx_dot11_grp_addr_tbl *acx;
int ret;
@@ -422,9 +423,9 @@ int wl1251_acx_group_address_tbl(struct wl1251 *wl)
}

/* MAC filtering */
- acx->enabled = 0;
- acx->num_groups = 0;
- memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+ acx->enabled = enable;
+ acx->num_groups = mc_list_len;
+ memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);

ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
acx, sizeof(*acx));
diff --git a/drivers/net/wireless/ti/wl1251/acx.h b/drivers/net/wireless/ti/wl1251/acx.h
index bea2e67..820573c 100644
--- a/drivers/net/wireless/ti/wl1251/acx.h
+++ b/drivers/net/wireless/ti/wl1251/acx.h
@@ -350,8 +350,8 @@ struct acx_slot {
} __packed;


-#define ADDRESS_GROUP_MAX (8)
-#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
+#define ACX_MC_ADDRESS_GROUP_MAX (8)
+#define ACX_MC_ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)

struct acx_dot11_grp_addr_tbl {
struct acx_header header;
@@ -359,7 +359,7 @@ struct acx_dot11_grp_addr_tbl {
u8 enabled;
u8 num_groups;
u8 pad[2];
- u8 mac_table[ADDRESS_GROUP_MAX_LEN];
+ u8 mac_table[ACX_MC_ADDRESS_GROUP_MAX_LEN];
} __packed;


@@ -1464,7 +1464,8 @@ int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time);
int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter);
int wl1251_acx_pd_threshold(struct wl1251 *wl);
int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time);
-int wl1251_acx_group_address_tbl(struct wl1251 *wl);
+int wl1251_acx_group_address_tbl(struct wl1251 *wl, bool enable,
+ void *mc_list, u32 mc_list_len);
int wl1251_acx_service_period_timeout(struct wl1251 *wl);
int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold);
int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter);
diff --git a/drivers/net/wireless/ti/wl1251/init.c b/drivers/net/wireless/ti/wl1251/init.c
index 92de289..f8a2ea9 100644
--- a/drivers/net/wireless/ti/wl1251/init.c
+++ b/drivers/net/wireless/ti/wl1251/init.c
@@ -127,7 +127,7 @@ int wl1251_hw_init_phy_config(struct wl1251 *wl)
if (ret < 0)
return ret;

- ret = wl1251_acx_group_address_tbl(wl);
+ ret = wl1251_acx_group_address_tbl(wl, true, NULL, 0);
if (ret < 0)
return ret;

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 39a6105..ee318c8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -29,6 +29,7 @@
#include <linux/vmalloc.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/netdevice.h>

#include "wl1251.h"
#include "wl12xx_80211.h"
@@ -678,6 +679,44 @@ out:
return ret;
}

+struct wl1251_filter_params {
+ bool enabled;
+ int mc_list_length;
+ u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
+static u64 wl1251_op_prepare_multicast(struct ieee80211_hw *hw,
+ struct netdev_hw_addr_list *mc_list)
+{
+ struct wl1251_filter_params *fp;
+ struct netdev_hw_addr *ha;
+ struct wl1251 *wl = hw->priv;
+
+ if (unlikely(wl->state == WL1251_STATE_OFF))
+ return 0;
+
+ fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
+ if (!fp) {
+ wl1251_error("Out of memory setting filters.");
+ return 0;
+ }
+
+ /* update multicast filtering parameters */
+ fp->mc_list_length = 0;
+ if (netdev_hw_addr_list_count(mc_list) > ACX_MC_ADDRESS_GROUP_MAX) {
+ fp->enabled = false;
+ } else {
+ fp->enabled = true;
+ netdev_hw_addr_list_for_each(ha, mc_list) {
+ memcpy(fp->mc_list[fp->mc_list_length],
+ ha->addr, ETH_ALEN);
+ fp->mc_list_length++;
+ }
+ }
+
+ return (u64)(unsigned long)fp;
+}
+
#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | \
FIF_FCSFAIL | \
@@ -688,8 +727,9 @@ out:

static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
- unsigned int *total,u64 multicast)
+ unsigned int *total, u64 multicast)
{
+ struct wl1251_filter_params *fp = (void *)(unsigned long)multicast;
struct wl1251 *wl = hw->priv;
int ret;

@@ -698,9 +738,11 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
*total &= WL1251_SUPPORTED_FILTERS;
changed &= WL1251_SUPPORTED_FILTERS;

- if (changed == 0)
+ if (changed == 0) {
/* no filters which we support changed */
+ kfree(fp);
return;
+ }

mutex_lock(&wl->mutex);

@@ -737,6 +779,15 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,
if (ret < 0)
goto out;

+ if (*total & FIF_ALLMULTI || *total & FIF_PROMISC_IN_BSS)
+ ret = wl1251_acx_group_address_tbl(wl, false, NULL, 0);
+ else if (fp)
+ ret = wl1251_acx_group_address_tbl(wl, fp->enabled,
+ fp->mc_list,
+ fp->mc_list_length);
+ if (ret < 0)
+ goto out;
+
/* send filters to firmware */
wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter);

@@ -744,6 +795,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw,

out:
mutex_unlock(&wl->mutex);
+ kfree(fp);
}

/* HW encryption */
@@ -1283,6 +1335,7 @@ static const struct ieee80211_ops wl1251_ops = {
.add_interface = wl1251_op_add_interface,
.remove_interface = wl1251_op_remove_interface,
.config = wl1251_op_config,
+ .prepare_multicast = wl1251_op_prepare_multicast,
.configure_filter = wl1251_op_configure_filter,
.tx = wl1251_op_tx,
.set_key = wl1251_op_set_key,
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h
index 45df03a..93c18d2 100644
--- a/drivers/net/wireless/ti/wl1251/wl1251.h
+++ b/drivers/net/wireless/ti/wl1251/wl1251.h
@@ -93,6 +93,7 @@ enum {
} while (0)

#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
+ CFG_MC_FILTER_EN | \
CFG_BSSID_FILTER_EN)

#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \
--
1.7.9.5


2013-12-10 09:24:40

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 03/16] wl1251: retry power save entry

On Sun 2013-12-08 10:25:01, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> Port of the power save entry retry code from wl1251 driver version included
> in the Maemo Fremantle kernel.
> This tries to enable power save mode up to 3 times before failing.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

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

2013-12-10 09:44:03

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 10/16] wl1251: enable tx path in monitor mode if necessary for packet injection

On Sun 2013-12-08 10:25:08, Pali Roh?r wrote:
> From: David Gnedt <[email protected]>
>
> If necessary enable the tx path in monitor mode for packet injection using
> the JOIN command with BSS_TYPE_STA_BSS and zero BSSID.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel


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

2013-12-10 09:29:18

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 04/16] wl1251: implement hardware ARP filtering

Hi!

> Update hardware ARP filter configuration on BSS_CHANGED_ARP_FILTER
> notification from mac80211.
> Ported from wl1271 driver.
>
> Signed-off-by: David Gnedt <[email protected]>
> Signed-off-by: Pali Roh?r <[email protected]>
> ---
> drivers/net/wireless/ti/wl1251/acx.c | 26 ++++++++++++++++++++++++++
> drivers/net/wireless/ti/wl1251/acx.h | 15 +++++++++++++++
> drivers/net/wireless/ti/wl1251/main.c | 12 ++++++++++++
> 3 files changed, 53 insertions(+)
>
> diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
> index cce50e2..5f4a552 100644
> --- a/drivers/net/wireless/ti/wl1251/acx.c
> +++ b/drivers/net/wireless/ti/wl1251/acx.c
> @@ -1062,6 +1062,32 @@ out:
> return ret;
> }
>
> +int wl1251_acx_arp_ip_filter(struct wl1251 *wl, bool enable, __be32 address)
> +{
> + struct wl1251_acx_arp_filter *acx;
> + int ret;

Is it good idea to use be32 for IP address? AFAICT IPv4 addresses
really don't have edianity. Perhaps u32 is better?

> + if (enable)
> + memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);

acx->address is an array of u8, so no endianity there, either.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2013-12-10 09:49:24

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 13/16] wl1251: add nvs file name to module firmware list

On Sun 2013-12-08 10:25:11, Pali Roh?r wrote:
> Signed-off-by: Pali Roh?r <[email protected]>

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

Thanks,
Pavel

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

2013-12-31 09:47:35

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

On Sunday 08 December 2013 10:24:58 Pali Rohár wrote:
> Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> comments. More patches come from David's monitor & packet
> injection work. Patches are tested with 3.12 rc5 kernel on
> Nokia N900.
>
> Second version contains new patch for fixing NULL pointer
> dereference which sometimes cause kernel panic and fixes code
> suggested by Pavel Machek.
>
> [1] - https://gitorious.org/linux-n900/linux-n900
>
> David Gnedt (12):
> wl1251: fix scan behaviour while not associated
> wl1251: add sysfs interface for bluetooth coexistence mode
> configuration
> wl1251: retry power save entry
> wl1251: implement hardware ARP filtering
> wl1251: split RX and TX data path initialisation
> wl1251: configure hardware en-/decryption for monitor mode
> wl1251: implement multicast address filtering
> wl1251: disable power saving in monitor mode
> wl1251: fix channel switching in monitor mode
> wl1251: enable tx path in monitor mode if necessary for
> packet injection
> wl1251: disable retry and ACK policy for injected packets
> wl1251: enforce changed hw encryption support on monitor
> state change
>
> Pali Rohár (4):
> wl1251: add nvs file name to module firmware list
> wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate
> wl1251: Add sysfs file address for setting permanent mac
> address wl1251: fix NULL pointer dereference
>
> drivers/net/wireless/ti/wl1251/acx.c | 92 +++++-
> drivers/net/wireless/ti/wl1251/acx.h | 34 ++-
> drivers/net/wireless/ti/wl1251/boot.c | 3 +-
> drivers/net/wireless/ti/wl1251/cmd.c | 59 +++-
> drivers/net/wireless/ti/wl1251/cmd.h | 8 +-
> drivers/net/wireless/ti/wl1251/event.c | 46 ++-
> drivers/net/wireless/ti/wl1251/event.h | 7 +
> drivers/net/wireless/ti/wl1251/init.c | 19 +-
> drivers/net/wireless/ti/wl1251/main.c | 462
> ++++++++++++++++++++++++++++++-
> drivers/net/wireless/ti/wl1251/rx.c | 2 +-
> drivers/net/wireless/ti/wl1251/tx.c | 35 ++-
> drivers/net/wireless/ti/wl1251/wl1251.h | 14 +
> 12 files changed, 720 insertions(+), 61 deletions(-)

So far, there are no new comments for patches 01, 03-13 and 16.
Are there any other problems with that patches or can be accepted
for upstream?

--
Pali Rohár
[email protected]


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

2013-12-10 16:10:55

by Pali Rohár

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tuesday 10 December 2013 16:49:23 Kalle Valo wrote:
> Pali Rohár <[email protected]> writes:
> > Driver wl1251 generating mac address randomly at startup and
> > there is no way to set permanent mac address via
> > SET_IEEE80211_PERM_ADDR. This patch export sysfs file which
> > can set permanent mac address by userspace helper program.
> > Patch is needed for devices which do not store mac address
> > in internal wl1251 eeprom.
> >
> > Signed-off-by: Pali Rohár <[email protected]>
>
> We have ioctl() command for setting the mac address.

Really? Is there ioctl for setting permanent mac address?
Can you show me it?

--
Pali Rohár
[email protected]


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

2013-12-12 12:45:48

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

Hello.

On 12-12-2013 2:36, Ivajlo Dimitrov wrote:

>> 2. NVRAM reading is done by a tiny driver that is loaded based on the
>> platform name and updates the DT node in memory. (But I don't know how
>> wl1251 should decide to defer probing if it's probed before that other
>> driver.)

>> Ben.


> Maybe a "hwmac" property with a value of XX:XX:XX:XX:XX:XX (or some other
> invalid value) set in DT could be used to tell the driver to defer until that
> value changes to something sane?

The standard property name for that is "local-mac-address". There's also
non-standard "mac-address" variation.

> Ivo

WBR, Sergei


2013-12-11 20:44:47

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

On Tue, 2013-12-10 at 18:08 +0100, Pali Rohár wrote:
> On Tuesday 10 December 2013 16:41:04 Kalle Valo wrote:
> > Pavel Machek <[email protected]> writes:
> > > ssids can have \0s in them... and what is worse, they may
> > > not be 0 terminated AFAICT.
> > >
> > > Potential solution is at
> > > http://www.spinics.net/lists/linux-wireless/msg98640.html .
> >
> > I just use print_hex_dump_bytes() to print SSIDs.
>
> Ok and has kernel printf modifier for size_t?

It is 'z', same as in userland.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-08 09:27:35

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 14/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate

This patch adds support for configuring reg domains.
Patch was extracted from Maemo 2.6.28 kernel.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 382dedf..42730b7 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1377,6 +1377,147 @@ static const struct ieee80211_ops wl1251_ops = {
.get_survey = wl1251_op_get_survey,
};

+static ssize_t wl1251_sysfs_show_tx_mgmt_frm_rate(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+ int val;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ switch (wl->tx_mgmt_frm_rate) {
+ /* skip 1 and 12 Mbps because they have same value 0x0a */
+ case RATE_2MBPS:
+ val = 20;
+ break;
+ case RATE_5_5MBPS:
+ val = 55;
+ break;
+ case RATE_11MBPS:
+ val = 110;
+ break;
+ case RATE_6MBPS:
+ val = 60;
+ break;
+ case RATE_9MBPS:
+ val = 90;
+ break;
+ case RATE_12MBPS:
+ val = 120;
+ break;
+ case RATE_18MBPS:
+ val = 180;
+ break;
+ case RATE_24MBPS:
+ val = 240;
+ break;
+ case RATE_36MBPS:
+ val = 360;
+ break;
+ case RATE_48MBPS:
+ val = 480;
+ break;
+ case RATE_54MBPS:
+ val = 540;
+ break;
+ default:
+ val = 10;
+ }
+
+ /* for 1 and 12 Mbps we have to check the modulation */
+ if (wl->tx_mgmt_frm_rate == RATE_1MBPS) {
+ switch (wl->tx_mgmt_frm_rate) {
+ case CCK_LONG:
+ val = 10;
+ break;
+ case OFDM:
+ val = 120;
+ break;
+ default:
+ val = 10;
+ break;
+ }
+ }
+ len = snprintf(buf, len, "%d", val);
+
+ return len;
+}
+
+static ssize_t wl1251_sysfs_store_tx_mgmt_frm_rate(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1251 *wl = dev_get_drvdata(dev);
+ unsigned long res;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &res);
+
+ if (ret < 0) {
+ wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
+ return 0;
+ }
+
+ switch (res) {
+ case 10:
+ wl->tx_mgmt_frm_rate = RATE_1MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 20:
+ wl->tx_mgmt_frm_rate = RATE_2MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 55:
+ wl->tx_mgmt_frm_rate = RATE_5_5MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 110:
+ wl->tx_mgmt_frm_rate = RATE_11MBPS;
+ wl->tx_mgmt_frm_mod = CCK_LONG;
+ break;
+ case 60:
+ wl->tx_mgmt_frm_rate = RATE_6MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 90:
+ wl->tx_mgmt_frm_rate = RATE_9MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 120:
+ wl->tx_mgmt_frm_rate = RATE_12MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 180:
+ wl->tx_mgmt_frm_rate = RATE_18MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 240:
+ wl->tx_mgmt_frm_rate = RATE_24MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 360:
+ wl->tx_mgmt_frm_rate = RATE_36MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 480:
+ wl->tx_mgmt_frm_rate = RATE_48MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ case 540:
+ wl->tx_mgmt_frm_rate = RATE_54MBPS;
+ wl->tx_mgmt_frm_mod = OFDM;
+ break;
+ default:
+ wl1251_warning("incorrect value written to tx_mgmt_frm_rate");
+ return 0;
+ }
+
+ return count;
+}
+
static ssize_t wl1251_sysfs_show_bt_coex_mode(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1445,6 +1586,10 @@ out:
return count;
}

+static DEVICE_ATTR(tx_mgmt_frm_rate, S_IRUGO | S_IWUSR,
+ wl1251_sysfs_show_tx_mgmt_frm_rate,
+ wl1251_sysfs_store_tx_mgmt_frm_rate);
+
static DEVICE_ATTR(bt_coex_mode, S_IRUGO | S_IWUSR,
wl1251_sysfs_show_bt_coex_mode,
wl1251_sysfs_store_bt_coex_mode);
@@ -1585,6 +1730,13 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
}
dev_set_drvdata(&wl1251_device.dev, wl);

+ /* Create sysfs file tx_mgmt_frm_rate */
+ ret = device_create_file(&wl1251_device.dev,
+ &dev_attr_tx_mgmt_frm_rate);
+ if (ret < 0) {
+ wl1251_error("failed to create sysfs file tx_mgmt_frm_rate");
+ goto out;
+ }

/* Create sysfs file to control bt coex state */
ret = device_create_file(&wl1251_device.dev, &dev_attr_bt_coex_mode);
--
1.7.9.5


2013-12-08 09:27:28

by Pali Rohár

[permalink] [raw]
Subject: [PATCH v2 09/16] wl1251: fix channel switching in monitor mode

From: David Gnedt <[email protected]>

Use the ENABLE_RX command for channel switching when no interface is present
(monitor mode only).
The advantage of ENABLE_RX is that it leaves the tx data path disabled in
firmware, whereas the usual JOIN command seems to transmit some frames at
firmware level.

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

diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 1223bc6..b6f11b8 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -616,8 +616,19 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
if (channel != wl->channel) {
wl->channel = channel;

- ret = wl1251_join(wl, wl->bss_type, wl->channel,
- wl->beacon_int, wl->dtim_period);
+ /*
+ * Use ENABLE_RX command for channel switching when no
+ * interface is present (monitor mode only).
+ * This leaves the tx path disabled in firmware, whereas
+ * the usual JOIN command seems to transmit some frames
+ * at firmware level.
+ */
+ if (wl->vif == NULL) {
+ ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1);
+ } else {
+ ret = wl1251_join(wl, wl->bss_type, wl->channel,
+ wl->beacon_int, wl->dtim_period);
+ }
if (ret < 0)
goto out_sleep;
}
--
1.7.9.5


2013-12-10 15:49:33

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

Pali Rohár <[email protected]> writes:

> Driver wl1251 generating mac address randomly at startup and there is no way to
> set permanent mac address via SET_IEEE80211_PERM_ADDR. This patch export sysfs
> file which can set permanent mac address by userspace helper program. Patch is
> needed for devices which do not store mac address in internal wl1251 eeprom.
>
> Signed-off-by: Pali Rohár <[email protected]>

We have ioctl() command for setting the mac address.

--
Kalle Valo

2013-12-11 21:26:20

by Ben Hutchings

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address

On Tue, 2013-12-10 at 20:31 +0100, Pali Rohár wrote:
[...]
> So, if you like this idea, can you help me how to write udev rule
> which will run my own program (it print mac address) and send mac
> address when driver ask for mac address in request_firmware?
> Problem is that default udev rule for firmware trying to load data
> from /lib/firmware/... but in this case mac address first must be
> read from special location and converted to correct format.

Unfortunately, udev no longer supports firmware loading during module
loading (unless that was fixed - I don't think it has been). Loading
firmware *files* still works because the kernel can read those directly
rather than requesting them from udev.

Ben.

--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.


2013-12-11 22:36:47

by Ivaylo Dimitrov

[permalink] [raw]
Subject: Re: [PATCH v2 15/16] wl1251: Add sysfs file address for setting permanent mac address


On 12.12.2013 00:15, Ben Hutchings wrote:
> 2. NVRAM reading is done by a tiny driver that is loaded based on the
> platform name and updates the DT node in memory. (But I don't know how
> wl1251 should decide to defer probing if it's probed before that other
> driver.)
>
> Ben.
>

Maybe a "hwmac" property with a value of XX:XX:XX:XX:XX:XX (or some
other invalid value) set in DT could be used to tell the driver to defer
until that value changes to something sane?

Ivo

Subject: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated

>-------- Оригинално писмо --------
>От: Pali Rohár
>Относно: Re: [PATCH v2 01/16] wl1251: fix scan behaviour while not associated
>До: Kalle Valo ,
Pavel Machek
>Изпратено на: Вторник, 2013, Декември 10 19:08:44 EET
>
>
>On Tuesday 10 December 2013 16:41:04 Kalle Valo wrote:
>> Pavel Machek writes:
>> > ssids can have &#92;0s in them... and what is worse, they may
>> > not be 0 terminated AFAICT.
>> >
>> > Potential solution is at
>> > http://www.spinics.net/lists/linux-wireless/msg98640.html .
>>
>> I just use print_hex_dump_bytes() to print SSIDs.
>
>Ok and has kernel printf modifier for size_t?
>
>--
>Pali Rohár
>[email protected]
>

If I read lib/vsprintf.c correctly, you can use 'z'

Regards,
Ivo

PS: Please use my gmail address when cc-ing me, LKML really hates my abv dot bg account :)

2014-01-06 20:26:13

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

On Mon, 2014-01-06 at 15:00 -0500, John W. Linville wrote:
> On Tue, Dec 31, 2013 at 10:47:29AM +0100, Pali Rohár wrote:
> > On Sunday 08 December 2013 10:24:58 Pali Rohár wrote:
> > > Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> > > comments. More patches come from David's monitor & packet
> > > injection work. Patches are tested with 3.12 rc5 kernel on
> > > Nokia N900.
> > >
> > > Second version contains new patch for fixing NULL pointer
> > > dereference which sometimes cause kernel panic and fixes code
> > > suggested by Pavel Machek.
>
> > So far, there are no new comments for patches 01, 03-13 and 16.
> > Are there any other problems with that patches or can be accepted
> > for upstream?
>
> They are probably fine to merge now. Of course, I was still deleting
> wl12xx patches when they were originally posted, so I'll need someone
> to resend the patches to me...

But please please don't CC half the world again!

johannes


2014-01-16 00:21:22

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

On Mon 2014-01-06 15:00:50, John W. Linville wrote:
> On Tue, Dec 31, 2013 at 10:47:29AM +0100, Pali Roh?r wrote:
> > On Sunday 08 December 2013 10:24:58 Pali Roh?r wrote:
> > > Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> > > comments. More patches come from David's monitor & packet
> > > injection work. Patches are tested with 3.12 rc5 kernel on
> > > Nokia N900.
> > >
> > > Second version contains new patch for fixing NULL pointer
> > > dereference which sometimes cause kernel panic and fixes code
> > > suggested by Pavel Machek.
>
> > So far, there are no new comments for patches 01, 03-13 and 16.
> > Are there any other problems with that patches or can be accepted
> > for upstream?
>
> They are probably fine to merge now. Of course, I was still deleting
> wl12xx patches when they were originally posted, so I'll need someone
> to resend the patches to me...

Ping? Did they get merged? Did you receive the patches?

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

2014-01-16 20:30:29

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

On Thu, Jan 16, 2014 at 01:21:21AM +0100, Pavel Machek wrote:
> On Mon 2014-01-06 15:00:50, John W. Linville wrote:
> > On Tue, Dec 31, 2013 at 10:47:29AM +0100, Pali Roh?r wrote:
> > > On Sunday 08 December 2013 10:24:58 Pali Roh?r wrote:
> > > > Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> > > > comments. More patches come from David's monitor & packet
> > > > injection work. Patches are tested with 3.12 rc5 kernel on
> > > > Nokia N900.
> > > >
> > > > Second version contains new patch for fixing NULL pointer
> > > > dereference which sometimes cause kernel panic and fixes code
> > > > suggested by Pavel Machek.
> >
> > > So far, there are no new comments for patches 01, 03-13 and 16.
> > > Are there any other problems with that patches or can be accepted
> > > for upstream?
> >
> > They are probably fine to merge now. Of course, I was still deleting
> > wl12xx patches when they were originally posted, so I'll need someone
> > to resend the patches to me...
>
> Ping? Did they get merged? Did you receive the patches?

They are already available in wireless-next.

--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2014-01-06 20:15:35

by John W. Linville

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

On Tue, Dec 31, 2013 at 10:47:29AM +0100, Pali Roh?r wrote:
> On Sunday 08 December 2013 10:24:58 Pali Roh?r wrote:
> > Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> > comments. More patches come from David's monitor & packet
> > injection work. Patches are tested with 3.12 rc5 kernel on
> > Nokia N900.
> >
> > Second version contains new patch for fixing NULL pointer
> > dereference which sometimes cause kernel panic and fixes code
> > suggested by Pavel Machek.

> So far, there are no new comments for patches 01, 03-13 and 16.
> Are there any other problems with that patches or can be accepted
> for upstream?

They are probably fine to merge now. Of course, I was still deleting
wl12xx patches when they were originally posted, so I'll need someone
to resend the patches to me...

John
--
John W. Linville Someday the world will need a hero, and you
[email protected] might be all we have. Be ready.

2014-01-07 12:15:05

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

Hi!

> > > Second version contains new patch for fixing NULL pointer
> > > dereference which sometimes cause kernel panic and fixes code
> > > suggested by Pavel Machek.
>
> > So far, there are no new comments for patches 01, 03-13 and 16.
> > Are there any other problems with that patches or can be accepted
> > for upstream?
>
> They are probably fine to merge now. Of course, I was still deleting
> wl12xx patches when they were originally posted, so I'll need someone
> to resend the patches to me...

Patches should be in your inbox now, with subjects "[PATCH v3 13/13]
wl1251:". I hand selected patches 01, 03-13 and 16. I was doing
forwarding by hand, sorry for extra (fwd) in 06/13.

Best regards,
Pavel

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

2014-01-06 22:03:08

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v2 00/16] wl1251 patches from linux-n900 tree

Hi!

> > > Hello, I'm sending wl1251 patches from linux-n900 tree [1] for
> > > comments. More patches come from David's monitor & packet
> > > injection work. Patches are tested with 3.12 rc5 kernel on
> > > Nokia N900.
> > >
> > > Second version contains new patch for fixing NULL pointer
> > > dereference which sometimes cause kernel panic and fixes code
> > > suggested by Pavel Machek.
>
> > So far, there are no new comments for patches 01, 03-13 and 16.
> > Are there any other problems with that patches or can be accepted
> > for upstream?
>
> They are probably fine to merge now. Of course, I was still deleting
> wl12xx patches when they were originally posted, so I'll need someone
> to resend the patches to me...

I'll try to help with that (Pali has his development machine under
repairs), but I'll have to hunt it in archives, too...

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