Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] staging: vt6656: device.h  Remove typedef enum __device_init_type.
From: Greg KH @ 2013-10-27 13:49 UTC (permalink / raw)
  To: Malcolm Priestley; +Cc: linux-wireless
In-Reply-To: <1382469974.6738.8.camel@canaries64-MCP7A>

On Tue, Oct 22, 2013 at 08:26:14PM +0100, Malcolm Priestley wrote:
> Since typedef enum __device_init_type is only ever called
> in one state.

Then why not remove it entirely?

> Remove the typedef from main_usb.c:device_init_registers
> and if braces and just apply the enum value to sInitCmd.byInitClass.

You kind of did this, but things are still a bit messed up:

>      }
> -    if (InitType == DEVICE_INIT_COLD) {
>  
>          ntStatus = CONTROLnsRequestIn(pDevice,MESSAGE_TYPE_INIT_RSP,0,0,sizeof(RSP_CARD_INIT), (u8 *) &(sInitRsp));
>  
> @@ -574,7 +572,6 @@ static int device_init_registers(struct vnt_private *pDevice,
>  	/* if exist SW network address, use it */
>  	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Network address = %pM\n",
>  		pDevice->abyCurrentNetAddr);
> -    }

You remove this if, but the indentation is not fixed up.

Just remove the enum entirely if it's not used.

thanks,

greg k-h

^ permalink raw reply

* iwlegacy (4965) - what would 0x8000 as the completed TX rate indicate?
From: Adrian Chadd @ 2013-10-26 23:56 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org

Hi all,

I'm debugging some issues that i see with the 4965 driver on FreeBSD. I
figure maybe someone here with experience with the iwlegacy driver may know.

I've set it up to do non-aggregate 11abg only traffic in my tests and I do
occasionally see the TX rate control completion status show the rate is
0x8000. I don't know to interpret it. It typically happens with the retry
count being non-zero, but there are also completed frames with non-zero
retry and normal rate results. The returned status is OK.

Here's an example:

Oct 26 16:06:11 lucy kernel: iwn4965_tx_done: qid 0 idx 210 retries 0 nkill
0 rate 4003 duration 294 status 201
Oct 26 16:06:11 lucy kernel: iwn4965_tx_done: qid 0 idx 211 retries 0 nkill
0 rate 4003 duration 182 status 201
Oct 26 16:06:11 lucy kernel: iwn4965_tx_done: qid 0 idx 212 retries 1 nkill
0 rate 8000 duration 616 status 201
Oct 26 16:06:12 lucy kernel: iwn4965_tx_done: qid 0 idx 213 retries 0 nkill
0 rate 4003 duration 294 status 201
Oct 26 16:06:12 lucy kernel: iwn4965_tx_done: qid 0 idx 214 retries 1 nkill
0 rate 8000 duration 292 status 201
Oct 26 16:06:12 lucy kernel: iwn4965_tx_done: qid 0 idx 215 retries 0 nkill
0 rate 4003 duration 86 status 201
Oct 26 16:06:12 lucy kernel: iwn4965_tx_done: qid 0 idx 216 retries 0 nkill
0 rate 4003 duration 86 status 201

I definitely am programming the initial rate control fine and the flags
field doesn't have the linkq stuff set, so it should be transmitting only
at that rate.

The status indicates things are transmitting and completing fine.

So, any ideas what that 0x8000 rate in the rate completion means?

Thanks!


-adrian

^ permalink raw reply

* BRCM 4324 Help
From: Hiemanshu Sharma @ 2013-10-26 20:54 UTC (permalink / raw)
  To: linux-wireless

Hey,

Trying to follow the instructions at
http://wireless.kernel.org/en/users/Drivers/brcm80211 I need a
brcmfmac-sdio.txt with the nvram values but I am not able to find out
where to get the file from. I've tried google a lot but there doesn't
seem to be a lot of help out there.

dmesg says :

brcmfam: brcmf_sdbrcm_download_nvram : Fail to request nvram -2
brcmfmac: _brcmf_sdbrcm_download_firmware: dongle nvram file download failed


I've used firmware from the git, and the message for missing firmware
is not shown anymore.

Regards,

Hiemanshu Sharma.

^ permalink raw reply

* [PATCH 16/16] wl1251: Add sysfs file address for setting permanent mac address
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

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 <pali.rohar@gmail.com>
---
 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


^ permalink raw reply related

* [PATCH 15/16] wl1251: Add sysfs file tx_mgmt_frm_rate for setting rate
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

This patch was extracted from Maemo 2.6.28 kernel

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
 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


^ permalink raw reply related

* [PATCH 14/16] wl1251: add nvs file name to module firmware list
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
---
 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 <kvalo@adurom.com>");
 MODULE_FIRMWARE(WL1251_FW_NAME);
+MODULE_FIRMWARE(WL1251_NVS_NAME);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 13/16] wl1251: enforce changed hw encryption support on monitor state change
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 12/16] wl1251: disable retry and ACK policy for injected packets
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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

Signed-off-by: David Gnedt <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 11/16] wl1251: enable tx path in monitor mode if necessary for packet injection
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 10/16] wl1251: fix channel switching in monitor mode
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 09/16] wl1251: disable power saving in monitor mode
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

Force power saving off while monitor interface is present.

Signed-off-by: David Gnedt <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 08/16] wl1251: implement multicast address filtering
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 07/16] wl1251: configure hardware en-/decryption for monitor mode
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 06/16] wl1251: split RX and TX data path initialisation
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 05/16] wl1251: implement hardware ARP filtering
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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

Signed-off-by: David Gnedt <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 04/16] wl1251: retry power save entry
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 03/16] wl1251: add sysfs interface for bluetooth coexistence mode configuration
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 02/16] wl1251: fix scan behaviour while not associated
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

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 <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 01/16] mac80211: fix TX device statistics for monitor interfaces
From: Pali Rohár @ 2013-10-26 20:34 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar,
	David Gnedt
In-Reply-To: <1382819655-30430-1-git-send-email-pali.rohar@gmail.com>

From: David Gnedt <david.gnedt@davizone.at>

Count TX packets and bytes also for monitor interfaces.

Signed-of-by: David Gnedt <david.gnedt@davizone.at>
---
 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


^ permalink raw reply related

* [PATCH 00/16] wl1251 patches from linux-n900 tree
From: Pali Rohár @ 2013-10-26 20:33 UTC (permalink / raw)
  To: Luciano Coelho, John W. Linville, Johannes Berg, David S. Miller
  Cc: linux-wireless, netdev, linux-kernel, freemangordon,
	aaro.koskinen, pavel, sre, joni.lapilainen, pali.rohar

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


^ permalink raw reply

* [Patch v3 3/3] net: wireless: replace printk with pr_warn in adm8211.c
From: Georgiana Rodica Chelu @ 2013-10-26 19:50 UTC (permalink / raw)
  To: opw-kernel; +Cc: linux-wireless

WARNING: Prefer netdev_warn(netdev, ... then dev_warn(dev, ... then pr_warn(...
to printk(KERN_WARNING ...

Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com>
---
 drivers/net/wireless/adm8211.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 0392b52..00a1221 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1855,8 +1855,8 @@ static int adm8211_probe(struct pci_dev *pdev,
 		cpu_to_le16(ADM8211_CSR_READ(PAR1) & 0xFFFF);
 
 	if (!is_valid_ether_addr(perm_addr)) {
-		printk(KERN_WARNING "%s (adm8211): Invalid hwaddr in EEPROM!\n",
-		       pci_name(pdev));
+		pr_warn("%s (adm8211): Invalid hwaddr in EEPROM!\n",
+			pci_name(pdev));
 		eth_random_addr(perm_addr);
 	}
 	SET_IEEE80211_PERM_ADDR(dev, perm_addr);
-- 
1.8.1.2


^ permalink raw reply related

* [Patch v3 2/3] net: wireless: replace printk with pr_warn in adm8211.c
From: Georgiana Rodica Chelu @ 2013-10-26 19:44 UTC (permalink / raw)
  To: opw-kernel; +Cc: linux-wireless

WARNING: Prefer netdev_warn(netdev, ... then dev_warn(dev, ... then pr_warn(...
to printk(KERN_WARNING ...

Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com>
---
 drivers/net/wireless/adm8211.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index e36d54d..0392b52 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -169,13 +169,13 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
 		else
 			priv->bbp_type = ADM8211_TYPE_ADMTEK;
 
-		printk(KERN_WARNING "%s (adm8211): Unknown BBPtype: %d\n",
-		       pci_name(priv->pdev), cr49 >> 3);
+		pr_warn("%s (adm8211): Unknown BBPtype: %d\n",
+			pci_name(priv->pdev), cr49 >> 3);
 	}
 
 	if (priv->eeprom->country_code >= ARRAY_SIZE(cranges)) {
-		printk(KERN_WARNING "%s (adm8211): Invalid country code (%d)\n",
-		       pci_name(priv->pdev), priv->eeprom->country_code);
+		pr_warn("%s (adm8211): Invalid country code (%d)\n",
+			pci_name(priv->pdev), priv->eeprom->country_code);
 
 		chan_range = cranges[2];
 	} else
@@ -209,8 +209,8 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
 		else
 			priv->specific_bbptype = ADM8211_BBP_ADM8011;
 
-		printk(KERN_WARNING "%s (adm8211): Unknown specific BBP: %d\n",
-		       pci_name(priv->pdev), priv->eeprom->specific_bbptype);
+		pr_warn("%s (adm8211): Unknown specific BBP: %d\n",
+			pci_name(priv->pdev), priv->eeprom->specific_bbptype);
 	}
 
 	switch (priv->eeprom->specific_rftype) {
@@ -230,8 +230,8 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
 		else if (priv->pdev->revision == ADM8211_REV_AB)
 			priv->transceiver_type = ADM8211_RFMD2948;
 
-		printk(KERN_WARNING "%s (adm8211): Unknown transceiver: %d\n",
-		       pci_name(priv->pdev), priv->eeprom->specific_rftype);
+		pr_warn("%s (adm8211): Unknown transceiver: %d\n",
+			pci_name(priv->pdev), priv->eeprom->specific_rftype);
 
 		break;
 	}
-- 
1.8.1.2


^ permalink raw reply related

* [Patch v3 1/3] net: wireless: replace printk with pr_warn in adm8211.c
From: Georgiana Rodica Chelu @ 2013-10-26 19:20 UTC (permalink / raw)
  To: opw-kernel; +Cc: linux-wireless

WARNING: Prefer netdev_warn(netdev, ... then dev_warn(dev, ... then pr_warn(...
to printk(KERN_WARNING ...

Signed-off-by: Georgiana Rodica Chelu <georgiana.chelu93@gmail.com>
---
 drivers/net/wireless/adm8211.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index f9a24e5..e36d54d 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -151,7 +151,7 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
 		else
 			priv->rf_type = ADM8211_TYPE_AIROHA;
 
-		printk(KERN_WARNING "%s (adm8211): Unknown RFtype %d\n",
+		pr_warn("%s (adm8211): Unknown RFtype %d\n",
 		       pci_name(priv->pdev), (cr49 >> 3) & 0x7);
 	}
 
-- 
1.8.1.2


^ permalink raw reply related

* [RFC] carl9170: new firmware for linux-firmware.git
From: Christian Lamparter @ 2013-10-25 23:15 UTC (permalink / raw)
  To: Ben Hutchings; +Cc: linux-wireless

Hi Ben,

I'm currently updating the carl9170 firmware to the latest
version (1.9.9). I've already pushed out the sources and
updated the binaries over at our wiki (for the last time,
all future update will be via linux-firmware.git).

Now, the last item on my check off list is:
[ ]     new firmware for linux-firmware.git

Last time - when this topic came up - we had a short brainstorm
about how to handle updates in the future: 
<http://marc.info/?l=linux-wireless&m=136115736909708>

So, I've now prepared some options: 

1. Reorganize carl9170 by creating a new subdirectory "carl9170"
   and move everything in it.
   * A carl9170fw-x.y.z.tar.xz with the source is generated for
     each release and placed under carl9170/source/.

   * new firmware binaries are placed in carl9170/.
     (The firmware file name will include the version e.g. 
     carl9170-1.9.9.fw, it won't clash with a previous release.)

   * A symlink from the linux-firmware.git root to the latest 
     carl9170-1.fw in the carl9170 subfolder is added/updated for
     each release.

   For a preview see: [1]
   116 files changed, 3 insertions(+), 26313 deletions(-)
   
2. Simply replace code and firmware binary
   * The code is simply dumped from the carl9170 firmware repository
     into the existing carl9170fw directory.

   * The old firmware binary "carl9170-1.fw" file is replaced by the
     new version.

   For a preview see: [2]
   70 files changed, 2479 insertions(+), 4560 deletions(-)

I would prefer to go with option 1 and move everything into a carl9170
subdirectory. This way has the advantage that we can have multiple 
firmware binaries and sources coexisting in one place. However, I'm 
also aware of the additional "space and bandwidth" cost in this case. 

Please tell me which option you like best or if it should be done
differently. I've prepared a few RFCs (see links), but once we 
settled for the process, I'll make a proper announcement + patches.

Regards

Christian

[1] <https://drive.google.com/folderview?id=0BwOU1CguSZuBdGYxVVlTWnpXSm8>
[2] <https://drive.google.com/folderview?id=0BwOU1CguSZuBT1V2V0s2Smp0UmM>

^ permalink raw reply

* [PATCH -next 2/2] wireless: cw1200: Use consistent internal  locking conventions
From: Solomon Peachy @ 2013-10-25 22:15 UTC (permalink / raw)
  To: linux-wireless; +Cc: Solomon Peachy
In-Reply-To: <1382739343-5727-1-git-send-email-pizza@shaftnet.org>

The cw1200_irq_handler() function expects the hwbus lock to be held when
it is called.  On the SDIO platform, this lock is implemented in terms
of sdio_claim_host/sdio_release_host.

This trivial patch makes it explicit that we are performing the hwbus
lock rather than something SDIO-specific.

Signed-off-by: Solomon Peachy <pizza@shaftnet.org>
---
 drivers/net/wireless/cw1200/cw1200_sdio.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/cw1200/cw1200_sdio.c b/drivers/net/wireless/cw1200/cw1200_sdio.c
index ebdcdf4..d3acc85 100644
--- a/drivers/net/wireless/cw1200/cw1200_sdio.c
+++ b/drivers/net/wireless/cw1200/cw1200_sdio.c
@@ -108,9 +108,9 @@ static irqreturn_t cw1200_gpio_irq(int irq, void *dev_id)
 	struct hwbus_priv *self = dev_id;
 
 	if (self->core) {
-		sdio_claim_host(self->func);
+		cw1200_sdio_lock(self);
 		cw1200_irq_handler(self->core);
-		sdio_release_host(self->func);
+		cw1200_sdio_unlock(self);
 		return IRQ_HANDLED;
 	} else {
 		return IRQ_NONE;
-- 
1.8.3.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox