Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [rt2x00-users] [PATCH] rt73usb.c : more ids
From: John W. Linville @ 2009-10-13 14:56 UTC (permalink / raw)
  To: rt2x00 Users List; +Cc: linux-wireless
In-Reply-To: <880c1630910130520p30c06846k8692634ec277340@mail.gmail.com>

On Tue, Oct 13, 2009 at 01:20:17PM +0100, Luis Correia wrote:
> Hi Xose,
> 
> 2009/10/13 Xose Vazquez Perez <xose.vazquez@gmail.com>
> 
> > hi,
> >
> > stolen from windows inf file(07/17/2009, 1.03.05.0000)
> > Ovislink 0x1b75, 0x7318
> > MSI 0x0db0, 0x4600
> > WideTell 0x7167, 0x3840
> >
> >
> > -thanks-
> >
> > regards,
> >
> 
> Are you absolutely sure that these devices are really rt73usb?
> 
> By being in the windows inf file doesn't mean they would work in Linux.
> 
> Luis Correia,
> rt2x00 project admin

Please also post patches in the correct format (especially including
the Signed-off-by):

	http://linux.yyz.us/patch-format.html

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* RE: [PATCH V3] iwlwifi: use paged Rx
From: Zhu, Yi @ 2009-10-13 12:44 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <20091013115110.GA2639@dhcp-lab-161.englab.brq.redhat.com>

> From: Stanislaw Gruszka [mailto:sgruszka@redhat.com]
> > Which case? The linear one is the same as the current implementation.
> 
> Considering swcrypt for example. This patch make things worse as we still
> need to do the same skb allocation as before, plus additional pages allocation,
> plus additional memcpy. No ?

Yes. But software encryption is only used for debugging purpose by iwlagn.

Thanks,
-yi

^ permalink raw reply

* Re: [PATCH] rt2800pci.c : more ids
From: Xose Vazquez Perez @ 2009-10-13 12:12 UTC (permalink / raw)
  Cc: linux-wireless, users, IvDoorn
In-Reply-To: <4AD434B6.3090903@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 498 bytes --]

On 10/13/2009 10:05 AM, Xose Vazquez Perez wrote:

> stolen from windows inf file(09/05/2009, 1.04.07.0000)
> 
> 0x1814, 0x3060

apply this one instead, 
got 0x1462,0x89a from linux driver(2009_0903_RT3090_Linux_STA_v2.2.0.1)

-thanks-

-- 
«Allá muevan feroz guerra, ciegos reyes por un palmo más de tierra;
que yo aquí tengo por mío cuanto abarca el mar bravío, a quien nadie
impuso leyes. Y no hay playa, sea cualquiera, ni bandera de esplendor,
que no sienta mi derecho y dé pecho a mi valor.»

[-- Attachment #2: new_id-2800pci-v2.diff --]
[-- Type: text/plain, Size: 1273 bytes --]

--- o/drivers/net/wireless/rt2800pci.c	2009-10-13 09:57:37.523379731 +0200
+++ n/drivers/net/wireless/rt2800pci.c	2009-10-13 14:10:12.785378782 +0200
@@ -3225,6 +3225,8 @@
  * RT2800pci module information.
  */
 static struct pci_device_id rt2800pci_device_table[] = {
+	/* ??? */
+	{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	/* Edimax */
 	{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
@@ -3233,10 +3235,12 @@
 	{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	/* Ralink */
 	{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
+	{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },

^ permalink raw reply

* Error Installing 'iw'
From: Pramono Tunggul @ 2009-10-13 18:53 UTC (permalink / raw)
  To: linux-wireless

Guyz, when I try to start airmon-ng, it said that I have to install iw,
so I download and install iw but I have never succeed to install iw,

PACKAGE_CONFIG_PATH=/usr/lib
export PACKAGE_CONFIG_PATH

make

CC iw.o
In file included from /usr/local/include/netlink/netlink.h:23,
from /usr/include/netlink/genl/genl.h:15,
from iw.c:17:
/usr/local/include/netlink/netlink-kernel.h:222: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/netlink-kernel.h:232: error: expected 
specifier-qualifier-list before ‘__u16’
In file included from /usr/local/include/netlink/netlink.h:24,
from /usr/include/netlink/genl/genl.h:15,
from iw.c:17:
/usr/local/include/netlink/rtnetlink-kernel.h:281: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:342: error: expected 
specifier-qualifier-list before ‘__u8’
/usr/local/include/netlink/rtnetlink-kernel.h:403: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:431: error: expected 
specifier-qualifier-list before ‘__u16’
/usr/local/include/netlink/rtnetlink-kernel.h:477: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:498: error: expected 
specifier-qualifier-list before ‘__u64’
/usr/local/include/netlink/rtnetlink-kernel.h:533: error: expected 
specifier-qualifier-list before ‘__u8’
/usr/local/include/netlink/rtnetlink-kernel.h:540: error: expected 
specifier-qualifier-list before ‘__u16’
/usr/local/include/netlink/rtnetlink-kernel.h:622: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:629: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:663: error: expected 
specifier-qualifier-list before ‘__u64’
/usr/local/include/netlink/rtnetlink-kernel.h:751: error: expected 
specifier-qualifier-list before ‘__u32’
/usr/local/include/netlink/rtnetlink-kernel.h:767: error: expected 
specifier-qualifier-list before ‘__u32’
iw.c: In function ‘error_handler’:
iw.c:237: error: ‘NL_STOP’ undeclared (first use in this function)
iw.c:237: error: (Each undeclared identifier is reported only once
iw.c:237: error: for each function it appears in.)
iw.c: In function ‘ack_handler’:
iw.c:251: error: ‘NL_STOP’ undeclared (first use in this function)
iw.c: In function ‘__handle_cmd’:
iw.c:367: error: implicit declaration of function ‘nlmsg_alloc’
iw.c:367: warning: assignment makes pointer from integer without a cast
iw.c:373: error: implicit declaration of function ‘nl_cb_alloc’
iw.c:373: warning: assignment makes pointer from integer without a cast
iw.c:411: error: implicit declaration of function ‘nl_cb_put’
make: *** [iw.o] Error 1

Would you mind telling me how to install iw??

Thank you


Regards,

Pramono Tunggul

^ permalink raw reply

* Re: [PATCH V3] iwlwifi: use paged Rx
From: Stanislaw Gruszka @ 2009-10-13 11:51 UTC (permalink / raw)
  To: Zhu Yi; +Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org
In-Reply-To: <1255421948.3719.363.camel@debian>

On Tue, Oct 13, 2009 at 04:19:08PM +0800, Zhu Yi wrote:
> > > Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb
> > > for all the management frames and software decryption or defragmentation
> > > required data frames before handed to mac80211. For all the other frames,
> > > we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211
> > > to handle them properly.
> > 
> > This seems to be big overhead, but since there is no way to avoid it ...
> 
> Which case? The linear one is the same as the current implementation.

Considering swcrypt for example. This patch make things worse as we still
need to do the same skb allocation as before, plus additional pages allocation,
plus additional memcpy. No ?

Cheers
Stanislaw

^ permalink raw reply

* [PATCH] rt73usb.c : more ids
From: Xose Vazquez Perez @ 2009-10-13 11:47 UTC (permalink / raw)
  To: linux-wireless, users, IvDoorn

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

hi,

stolen from windows inf file(07/17/2009, 1.03.05.0000)
Ovislink 0x1b75, 0x7318
MSI 0x0db0, 0x4600
WideTell 0x7167, 0x3840


-thanks-

regards,
-- 
«Allá muevan feroz guerra, ciegos reyes por un palmo más de tierra;
que yo aquí tengo por mío cuanto abarca el mar bravío, a quien nadie
impuso leyes. Y no hay playa, sea cualquiera, ni bandera de esplendor,
que no sienta mi derecho y dé pecho a mi valor.»


[-- Attachment #2: new_id-73usb.diff --]
[-- Type: text/plain, Size: 1205 bytes --]

--- o/drivers/net/wireless/rt73usb.c	2009-10-13 12:58:32.042380351 +0200
+++ n/drivers/net/wireless/rt73usb.c	2009-10-13 13:01:01.073379225 +0200
@@ -2389,10 +2389,13 @@
 	{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* MSI */
+	{ USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+	/* Ovislink */
+	{ USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* Ralink */
 	{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2420,6 +2423,8 @@
 	/* Planex */
 	{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
 	{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+	/* WideTell */
+	{ USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* Zcom */
 	{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
 	/* ZyXEL */

^ permalink raw reply

* [PATCH] cfg80211: remove warning in deauth case
From: Holger Schurig @ 2009-10-13 11:45 UTC (permalink / raw)
  To: linux-wireless, John W. Linville; +Cc: Johannes Berg

It might be the case that __cfg80211_disconnected() has already
cleaned up wdev->current_bss() for us. The old code didn't catch
that situation and didn't warn needlessly.

Signed-off-by: Holger Schurig <hs4233@mail.mn-solutions.de>

---

For more info, see mail "cfg80211 / libertas: an unusual race"
in the linux-wireless mailing list.


--- linux-wl.orig/net/wireless/mlme.c
+++ linux-wl/net/wireless/mlme.c
@@ -130,7 +130,6 @@
 	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf;
 	const u8 *bssid = mgmt->bssid;
 	int i;
-	bool done = false;
 
 	ASSERT_WDEV_LOCK(wdev);
 
@@ -138,7 +137,6 @@
 
 	if (wdev->current_bss &&
 	    memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
-		done = true;
 		cfg80211_unhold_bss(wdev->current_bss);
 		cfg80211_put_bss(&wdev->current_bss->pub);
 		wdev->current_bss = NULL;
@@ -148,7 +146,6 @@
 			cfg80211_unhold_bss(wdev->auth_bsses[i]);
 			cfg80211_put_bss(&wdev->auth_bsses[i]->pub);
 			wdev->auth_bsses[i] = NULL;
-			done = true;
 			break;
 		}
 		if (wdev->authtry_bsses[i] &&
@@ -156,13 +153,10 @@
 			cfg80211_unhold_bss(wdev->authtry_bsses[i]);
 			cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
 			wdev->authtry_bsses[i] = NULL;
-			done = true;
 			break;
 		}
 	}
 
-	WARN_ON(!done);
-
 	if (wdev->sme_state == CFG80211_SME_CONNECTED) {
 		u16 reason_code;
 		bool from_ap;

-- 
http://www.holgerschurig.de

^ permalink raw reply

* Current status of rt2800usb and staging/rt2870
From: Ozan Çağlayan @ 2009-10-13 11:24 UTC (permalink / raw)
  To: linux-wireless, linux-kernel

Hi,

In 2.6.31, there are USB device IDs common between both drivers. Should
a distribution enable both drivers? What do you suggest? Are there any
*known issues* stuff for one of them?

Regards, thanks
Ozan Caglayan

^ permalink raw reply

* [PATCH 15/22] wl1271: Checking of rx descriptor status fixed
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>

Fixed checking of status of the received packet. On wl1251 status is in the
flags field of the descriptor, on wl1271 there is a separate status field.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_rx.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 1dd8458..1ea3f41 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -142,15 +142,10 @@ static void wl1271_rx_status(struct wl1271 *wl,
 	if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
 
-		if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
+		if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL)))
 			status->flag |= RX_FLAG_DECRYPTED;
-		/* FIXME: Flag should be also set when using 5 GHz band.
-		 * At the moment chip reports MIC failed on all packets,
-		 * so flag is silently discarded.
-		 */
-		if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
-			if (status->band != IEEE80211_BAND_5GHZ)
-				status->flag |= RX_FLAG_MMIC_ERROR;
+		if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL))
+			status->flag |= RX_FLAG_MMIC_ERROR;
 	}
 }
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 20/22] wl1271: Correct memory handling for FW boot
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Several memory allocation related failure cases were not properly
handled by the driver - the result was that in low memory conditions
booting of a corrupted FW could be attempted - and user space would not
get proper failure code.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |   11 ++++++++---
 1 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index b8a37a8..41a3050 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -134,7 +134,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 	}
 
 	chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
-	if (!buf) {
+	if (!chunk) {
 		wl1271_error("allocation for firmware upload chunk failed");
 		return -ENOMEM;
 	}
@@ -184,6 +184,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 static int wl1271_boot_upload_firmware(struct wl1271 *wl)
 {
 	u32 chunks, addr, len;
+	int ret = 0;
 	u8 *fw;
 
 	fw = wl->fw;
@@ -204,11 +205,13 @@ static int wl1271_boot_upload_firmware(struct wl1271 *wl)
 		}
 		wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
 			     chunks, addr, len);
-		wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+		ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+		if (ret != 0)
+			break;
 		fw += len;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int wl1271_boot_upload_nvs(struct wl1271 *wl)
@@ -284,6 +287,8 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
 
 	/* Copy the NVS tables to a new block to ensure alignment */
 	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+	if (!nvs_aligned)
+		return -ENOMEM;
 
 	/* And finally we upload the NVS tables */
 	/* FIXME: In wl1271, we upload everything at once.
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 12/22] wl1271: Scan only enabled channels
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>

Added checking of whether channel is enabled or disabled by mac80211
stack to scan. Disabled channels are not scanned.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_cmd.c |   33 +++++++++++++++++++----------
 1 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index f38e3e0..204e872 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -515,12 +515,16 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 
 	struct wl1271_cmd_trigger_scan_to *trigger = NULL;
 	struct wl1271_cmd_scan *params = NULL;
-	int i, ret;
+	struct ieee80211_channel *channels;
+	int i, j, n_ch, ret;
 	u16 scan_options = 0;
 
 	if (wl->scanning)
 		return -EINVAL;
 
+	channels = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels;
+	n_ch = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels;
+
 	params = kzalloc(sizeof(*params), GFP_KERNEL);
 	if (!params)
 		return -ENOMEM;
@@ -535,24 +539,29 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 		scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
 	params->params.scan_options = scan_options;
 
-	params->params.num_channels = num_channels;
 	params->params.num_probe_requests = probe_requests;
 	params->params.tx_rate = cpu_to_le32(CONF_HW_BIT_RATE_2MBPS);
 	params->params.tid_trigger = 0;
 	params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
 
-	for (i = 0; i < num_channels; i++) {
-		params->channels[i].min_duration =
-			cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
-		params->channels[i].max_duration =
-			cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
-		memset(&params->channels[i].bssid_lsb, 0xff, 4);
-		memset(&params->channels[i].bssid_msb, 0xff, 2);
-		params->channels[i].early_termination = 0;
-		params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
-		params->channels[i].channel = i + 1;
+	for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) {
+		if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) {
+			params->channels[j].min_duration =
+				cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
+			params->channels[j].max_duration =
+				cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+			memset(&params->channels[j].bssid_lsb, 0xff, 4);
+			memset(&params->channels[j].bssid_msb, 0xff, 2);
+			params->channels[j].early_termination = 0;
+			params->channels[j].tx_power_att =
+				WL1271_SCAN_CURRENT_TX_PWR;
+			params->channels[j].channel = channels[i].hw_value;
+			j++;
+		}
 	}
 
+	params->params.num_channels = j;
+
 	if (len && ssid) {
 		params->params.ssid_len = len;
 		memcpy(params->params.ssid, ssid, len);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 16/22] wl1271: Fix multicast list handling
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Fixes bugs in the multicast list handling:
 - Use atomic memory allocation in non-sleepable context
 - Increment address pointer when iterating list of MC addresses

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index ae41a70..19dbdb1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1160,7 +1160,7 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 	 * configure_filter() instead of saving everything in the context.
 	 */
 
-	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+	fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
 	if (!fp) {
 		wl1271_error("Out of memory setting filters.");
 		return 0;
@@ -1180,6 +1180,7 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 			fp->mc_list_length++;
 		} else
 			wl1271_warning("Unknown mc address length.");
+		mc_list = mc_list->next;
 	}
 
 	/* FIXME: We still need to set our filters properly */
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 10/22] wl1271: Remove busy-word checking
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Remove busy-word checking to work around an SPI bug. To reduce the
chance of chipset-busy scenarios, increment the number of fixed busy
words.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h     |    6 ++++--
 drivers/net/wireless/wl12xx/wl1271_spi.c |    6 +++---
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 648223f..e0ebb1f 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -115,9 +115,11 @@ enum {
 /*
  * FIXME: for the wl1271, a busy word count of 1 here will result in a more
  * optimal SPI interface. There is some SPI bug however, causing RXS time outs
- * with this mode occasionally on boot, so lets have two for now.
+ * with this mode occasionally on boot, so lets have three for now. A value of
+ * three should make sure, that the chipset will always be ready, though this
+ * will impact throughput and latencies slightly.
  */
-#define WL1271_BUSY_WORD_CNT 2
+#define WL1271_BUSY_WORD_CNT 3
 #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
 
 #define WL1271_ELP_HW_STATE_ASLEEP 0
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 4800fdf..3c5aa58 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -294,9 +294,9 @@ void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
 
 	spi_sync(wl->spi, &m);
 
-	/* Check busy words */
-	if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1))
-		wl1271_spi_read_busy(wl, buf, len);
+	/* FIXME: Check busy words, removed due to SPI bug */
+	/* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1))
+	   wl1271_spi_read_busy(wl, buf, len); */
 
 	wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
 	wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 14/22] wl1271: Added 5 GHz support to join and rx
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>

Added support to assiociate and use connection on 5 GHz band (802.11a).

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_cmd.c |   13 ++++++-
 drivers/net/wireless/wl12xx/wl1271_cmd.h |    1 +
 drivers/net/wireless/wl12xx/wl1271_rx.c  |   57 ++++++++++++++++++++++++------
 3 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 6d7a40c..fe4f1e6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -219,6 +219,7 @@ int wl1271_cmd_join(struct wl1271 *wl)
 
 	join->rx_config_options = wl->rx_config;
 	join->rx_filter_options = wl->rx_filter;
+	join->bss_type = wl->bss_type;
 
 	/*
 	 * FIXME: disable temporarily all filters because after commit
@@ -229,12 +230,20 @@ int wl1271_cmd_join(struct wl1271 *wl)
 	join->rx_config_options = 0;
 	join->rx_filter_options = WL1271_DEFAULT_RX_FILTER;
 
-	join->basic_rate_set = CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS |
+	if (wl->band == IEEE80211_BAND_2GHZ)
+		join->basic_rate_set =
+			CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS |
 		CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS;
+	else {
+		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
+		join->basic_rate_set =
+			CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_12MBPS |
+			CONF_HW_BIT_RATE_24MBPS;
+	}
 
 	join->beacon_interval = WL1271_DEFAULT_BEACON_INT;
 	join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
-	join->bss_type = wl->bss_type;
+
 	join->channel = wl->channel;
 	join->ssid_len = wl->ssid_len;
 	memcpy(join->ssid, wl->ssid, wl->ssid_len);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 3308940..15254fa 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -198,6 +198,7 @@ enum {
 
 #define WL1271_JOIN_CMD_CTRL_TX_FLUSH     0x80 /* Firmware flushes all Tx */
 #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
+#define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
 
 struct wl1271_cmd_join {
 	struct wl1271_cmd_header header;
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 66b83e9..1dd8458 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -70,6 +70,36 @@ static u8 wl1271_rx_rate_to_idx[] = {
 	0                           /* WL1271_RATE_1    */
 };
 
+/* The values of this table must match the wl1271_rates[] array */
+static u8 wl1271_5_ghz_rx_rate_to_idx[] = {
+	/* MCS rates are used only with 11n */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
+
+	7,                          /* WL1271_RATE_54   */
+	6,                          /* WL1271_RATE_48   */
+	5,                          /* WL1271_RATE_36   */
+	4,                          /* WL1271_RATE_24   */
+
+	/* TI-specific rate */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22   */
+
+	3,                          /* WL1271_RATE_18   */
+	2,                          /* WL1271_RATE_12   */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11   */
+	1,                          /* WL1271_RATE_9    */
+	0,                          /* WL1271_RATE_6    */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5  */
+	WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2    */
+	WL1271_RX_RATE_UNSUPPORTED  /* WL1271_RATE_1    */
+};
+
 static void wl1271_rx_status(struct wl1271 *wl,
 			     struct wl1271_rx_descriptor *desc,
 			     struct ieee80211_rx_status *status,
@@ -77,15 +107,21 @@ static void wl1271_rx_status(struct wl1271 *wl,
 {
 	memset(status, 0, sizeof(struct ieee80211_rx_status));
 
-	if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
+	if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
+	    WL1271_RX_DESC_BAND_BG) {
 		status->band = IEEE80211_BAND_2GHZ;
-	else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
-		 WL1271_RX_DESC_BAND_A)
+		status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
+	} else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
+		 WL1271_RX_DESC_BAND_A) {
 		status->band = IEEE80211_BAND_5GHZ;
-	else
+		status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate];
+	} else
 		wl1271_warning("unsupported band 0x%x",
 			       desc->flags & WL1271_RX_DESC_BAND_MASK);
 
+	if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED))
+		wl1271_warning("unsupported rate");
+
 	/*
 	 * FIXME: Add mactime handling.  For IBSS (ad-hoc) we need to get the
 	 * timestamp from the beacon (acx_tsf_info).  In BSS mode (infra) we
@@ -108,15 +144,14 @@ static void wl1271_rx_status(struct wl1271 *wl,
 
 		if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
 			status->flag |= RX_FLAG_DECRYPTED;
-
+		/* FIXME: Flag should be also set when using 5 GHz band.
+		 * At the moment chip reports MIC failed on all packets,
+		 * so flag is silently discarded.
+		 */
 		if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
-			status->flag |= RX_FLAG_MMIC_ERROR;
+			if (status->band != IEEE80211_BAND_5GHZ)
+				status->flag |= RX_FLAG_MMIC_ERROR;
 	}
-
-	status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
-
-	if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)
-		wl1271_warning("unsupported rate");
 }
 
 static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 03/22] wl1271: Add config structure for RX path parameters
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add a configuration structure for RX path parameters, and set default
configuration values there.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   20 ++++----
 drivers/net/wireless/wl12xx/wl1271_acx.h  |   43 +--------------
 drivers/net/wireless/wl12xx/wl1271_conf.h |   85 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_init.c |    4 +-
 drivers/net/wireless/wl12xx/wl1271_main.c |   12 ++++
 5 files changed, 110 insertions(+), 54 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index d19d860..63aa646 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -198,7 +198,7 @@ int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
 	return 0;
 }
 
-int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
 {
 	struct acx_rx_msdu_lifetime *acx;
 	int ret;
@@ -211,7 +211,7 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
 		goto out;
 	}
 
-	acx->lifetime = life_time;
+	acx->lifetime = wl->conf.rx.rx_msdu_life_time;
 	ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
 				   acx, sizeof(*acx));
 	if (ret < 0) {
@@ -265,7 +265,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl)
 		goto out;
 	}
 
-	/* FIXME: threshold value not set */
+	pd->threshold = wl->conf.rx.packet_detection_threshold;
 
 	ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
 	if (ret < 0) {
@@ -349,8 +349,8 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
 
 	wl1271_debug(DEBUG_ACX, "acx service period timeout");
 
-	rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
-	rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
+	rx_timeout->ps_poll_timeout = wl->conf.rx.ps_poll_timeout;
+	rx_timeout->upsd_timeout = wl->conf.rx.upsd_timeout;
 
 	ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
 				   rx_timeout, sizeof(*rx_timeout));
@@ -557,7 +557,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl)
 		goto out;
 	}
 
-	detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
+	detection->rx_cca_threshold = wl->conf.rx.rx_cca_threshold;
 	detection->tx_energy_detection = 0;
 
 	ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
@@ -966,10 +966,10 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
 		goto out;
 	}
 
-	rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF;
-	rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF;
-	rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */
-	rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY;
+	rx_conf->threshold = wl->conf.rx.irq_pkt_threshold;
+	rx_conf->timeout = wl->conf.rx.irq_timeout;
+	rx_conf->mblk_threshold = wl->conf.rx.irq_blk_threshold;
+	rx_conf->queue_type = wl->conf.rx.queue_type;
 
 	ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
 				   sizeof(*rx_conf));
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 8e3b97c..1fbd4e5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -314,35 +314,13 @@ struct acx_dot11_grp_addr_tbl {
 	u8 mac_table[ADDRESS_GROUP_MAX_LEN];
 } __attribute__ ((packed));
 
-#define  RX_TIMEOUT_PS_POLL_MIN    0
-#define  RX_TIMEOUT_PS_POLL_MAX    (200000)
-#define  RX_TIMEOUT_PS_POLL_DEF    (15)
-#define  RX_TIMEOUT_UPSD_MIN       0
-#define  RX_TIMEOUT_UPSD_MAX       (200000)
-#define  RX_TIMEOUT_UPSD_DEF       (15)
-
 struct acx_rx_timeout {
 	struct acx_header header;
 
-	/*
-	 * The longest time the STA will wait to receive
-	 * traffic from the AP after a PS-poll has been
-	 * transmitted.
-	 */
 	u16 ps_poll_timeout;
-
-	/*
-	 * The longest time the STA will wait to receive
-	 * traffic from the AP after a frame has been sent
-	 * from an UPSD enabled queue.
-	 */
 	u16 upsd_timeout;
 } __attribute__ ((packed));
 
-#define RTS_THRESHOLD_MIN              0
-#define RTS_THRESHOLD_MAX              4096
-#define RTS_THRESHOLD_DEF              2347
-
 struct acx_rts_threshold {
 	struct acx_header header;
 
@@ -510,9 +488,6 @@ struct acx_bt_wlan_coex_param {
 	u8 padding[3];
 } __attribute__ ((packed));
 
-#define CCA_THRSH_ENABLE_ENERGY_D       0x140A
-#define CCA_THRSH_DISABLE_ENERGY_D      0xFFEF
-
 struct acx_energy_detection {
 	struct acx_header header;
 
@@ -1017,22 +992,6 @@ struct wl1271_acx_mem_map {
 	void *tx_ctrl;
 } __attribute__ ((packed));
 
-enum wl1271_acx_rx_queue_type {
-	RX_QUEUE_TYPE_RX_LOW_PRIORITY,    /* All except the high priority */
-	RX_QUEUE_TYPE_RX_HIGH_PRIORITY,   /* Management and voice packets */
-	RX_QUEUE_TYPE_NUM,
-	RX_QUEUE_TYPE_MAX = USHORT_MAX
-};
-
-#define WL1271_RX_INTR_THRESHOLD_DEF  0       /* no pacing, send interrupt on
-					       * every event */
-#define WL1271_RX_INTR_THRESHOLD_MIN  0
-#define WL1271_RX_INTR_THRESHOLD_MAX  15
-
-#define WL1271_RX_INTR_TIMEOUT_DEF    5
-#define WL1271_RX_INTR_TIMEOUT_MIN    1
-#define WL1271_RX_INTR_TIMEOUT_MAX    100
-
 struct wl1271_acx_rx_config_opt {
 	struct acx_header header;
 
@@ -1122,7 +1081,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power);
 int wl1271_acx_feature_cfg(struct wl1271 *wl);
 int wl1271_acx_mem_map(struct wl1271 *wl,
 		       struct acx_header *mem_map, size_t len);
-int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
+int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
 int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
 int wl1271_acx_pd_threshold(struct wl1271 *wl);
 int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 1d6a44b..8bf8bff 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -171,8 +171,93 @@ struct conf_sg_settings {
 	s8 rate_adaptation_snr;
 };
 
+enum conf_rx_queue_type {
+	CONF_RX_QUEUE_TYPE_LOW_PRIORITY,  /* All except the high priority */
+	CONF_RX_QUEUE_TYPE_HIGH_PRIORITY, /* Management and voice packets */
+};
+
+struct conf_rx_settings {
+	/*
+	 * The maximum amount of time, in TU, before the
+	 * firmware discards the MSDU.
+	 *
+	 * Range: 0 - 0xFFFFFFFF
+	 */
+	u32 rx_msdu_life_time;
+
+	/*
+	 * Packet detection threshold in the PHY.
+	 *
+	 * FIXME: details unknown.
+	 */
+	u32 packet_detection_threshold;
+
+	/*
+	 * The longest time the STA will wait to receive traffic from the AP
+	 * after a PS-poll has been transmitted.
+	 *
+	 * Range: 0 - 200000
+	 */
+	u16 ps_poll_timeout;
+	/*
+	 * The longest time the STA will wait to receive traffic from the AP
+	 * after a frame has been sent from an UPSD enabled queue.
+	 *
+	 * Range: 0 - 200000
+	 */
+	u16 upsd_timeout;
+
+	/*
+	 * The number of octets in an MPDU, below which an RTS/CTS
+	 * handshake is not performed.
+	 *
+	 * Range: 0 - 4096
+	 */
+	u16 rts_threshold;
+
+	/*
+	 * The RX Clear Channel Assessment threshold in the PHY
+	 * (the energy threshold).
+	 *
+	 * Range: ENABLE_ENERGY_D  == 0x140A
+	 *        DISABLE_ENERGY_D == 0xFFEF
+	 */
+	u16 rx_cca_threshold;
+
+	/*
+	 * Occupied Rx mem-blocks number which requires interrupting the host
+	 * (0 = no buffering, 0xffff = disabled).
+	 *
+	 * Range: u16
+	 */
+	u16 irq_blk_threshold;
+
+	/*
+	 * Rx packets number which requires interrupting the host
+	 * (0 = no buffering).
+	 *
+	 * Range: u16
+	 */
+	u16 irq_pkt_threshold;
+
+	/*
+	 * Max time in msec the FW may delay RX-Complete interrupt.
+	 *
+	 * Range: 1 - 100
+	 */
+	u16 irq_timeout;
+
+	/*
+	 * The RX queue type.
+	 *
+	 * Range: RX_QUEUE_TYPE_RX_LOW_PRIORITY, RX_QUEUE_TYPE_RX_HIGH_PRIORITY,
+	 */
+	u8 queue_type;
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
+	struct conf_rx_settings rx;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 9abe062..5738263 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -94,7 +94,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
 {
 	int ret;
 
-	ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
+	ret = wl1271_acx_rx_msdu_life_time(wl);
 	if (ret < 0)
 		return ret;
 
@@ -125,7 +125,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
+	ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 69bc929..d04706d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -61,6 +61,18 @@ static void wl1271_conf_init(struct wl1271 *wl)
 			.beacon_miss_threshold      = 60,
 			.rate_adaptation_threshold  = CONF_HW_BIT_RATE_12MBPS,
 			.rate_adaptation_snr        = 0
+		},
+		.rx = {
+			.rx_msdu_life_time          = 512000,
+			.packet_detection_threshold = 0,
+			.ps_poll_timeout            = 15,
+			.upsd_timeout               = 15,
+			.rts_threshold              = 2347,
+			.rx_cca_threshold           = 0xFFEF,
+			.irq_blk_threshold          = 0,
+			.irq_pkt_threshold          = USHORT_MAX,
+			.irq_timeout                = 5,
+			.queue_type           = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
 		}
 	};
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 22/22] wl1271: Fix filter configuration
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Fix the filter configuration to properly work with the two phase filter
configuration (prepare_multicast/configure_filter.)

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    3 -
 drivers/net/wireless/wl12xx/wl1271_main.c |  157 +++++++++-------------------
 2 files changed, 51 insertions(+), 109 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index fca5968..1309b20 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -363,9 +363,6 @@ struct wl1271 {
 
 	struct work_struct tx_work;
 
-	struct work_struct filter_work;
-	struct wl1271_filter_params *filter_params;
-
 	/* Pending TX frames */
 	struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 7b8d279..ee7ffaf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -675,74 +675,6 @@ out:
 	return ret;
 }
 
-struct wl1271_filter_params {
-	unsigned int filters;
-	unsigned int changed;
-	int mc_list_length;
-	u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
-};
-
-#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
-				  FIF_ALLMULTI | \
-				  FIF_FCSFAIL | \
-				  FIF_BCN_PRBRESP_PROMISC | \
-				  FIF_CONTROL | \
-				  FIF_OTHER_BSS)
-
-static void wl1271_filter_work(struct work_struct *work)
-{
-	struct wl1271 *wl =
-		container_of(work, struct wl1271, filter_work);
-	struct wl1271_filter_params *fp;
-	unsigned long flags;
-	bool enabled = true;
-	int ret;
-
-	/* first, get the filter parameters */
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	fp = wl->filter_params;
-	wl->filter_params = NULL;
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-	if (!fp)
-		return;
-
-	/* then, lock the mutex without risk of lock-up */
-	mutex_lock(&wl->mutex);
-
-	if (wl->state == WL1271_STATE_OFF)
-		goto out;
-
-	ret = wl1271_ps_elp_wakeup(wl, false);
-	if (ret < 0)
-		goto out;
-
-	/* configure the mc filter regardless of the changed flags */
-	if (fp->filters & FIF_ALLMULTI)
-		enabled = false;
-
-	ret = wl1271_acx_group_address_tbl(wl, enabled,
-					   fp->mc_list, fp->mc_list_length);
-	if (ret < 0)
-		goto out_sleep;
-
-	/* determine, whether supported filter values have changed */
-	if (fp->changed == 0)
-		goto out;
-
-	/* apply configured filters */
-	ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
-	if (ret < 0)
-		goto out_sleep;
-
-out_sleep:
-	wl1271_ps_elp_sleep(wl);
-
-out:
-	mutex_unlock(&wl->mutex);
-	kfree(fp);
-}
-
 int wl1271_plt_start(struct wl1271 *wl)
 {
 	int ret;
@@ -993,20 +925,12 @@ out:
 static void wl1271_op_stop(struct ieee80211_hw *hw)
 {
 	struct wl1271 *wl = hw->priv;
-	unsigned long flags;
 	int i;
 
 	wl1271_info("down");
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
 
-	/* complete/cancel ongoing work */
-	cancel_work_sync(&wl->filter_work);
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	kfree(wl->filter_params);
-	wl->filter_params = NULL;
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
 	unregister_inetaddr_notifier(&wl1271_dev_notifier);
 	list_del(&wl->list);
 
@@ -1029,7 +953,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
 
 	cancel_work_sync(&wl->irq_work);
 	cancel_work_sync(&wl->tx_work);
-	cancel_work_sync(&wl->filter_work);
 
 	mutex_lock(&wl->mutex);
 
@@ -1252,19 +1175,18 @@ out:
 	return ret;
 }
 
+struct wl1271_filter_params {
+	bool enabled;
+	int mc_list_length;
+	u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
 static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 				       struct dev_addr_list *mc_list)
 {
-	struct wl1271 *wl = hw->priv;
 	struct wl1271_filter_params *fp;
-	unsigned long flags;
 	int i;
 
-	/*
-	 * FIXME: we should return a hash that will be passed to
-	 * configure_filter() instead of saving everything in the context.
-	 */
-
 	fp = kzalloc(sizeof(*fp), GFP_ATOMIC);
 	if (!fp) {
 		wl1271_error("Out of memory setting filters.");
@@ -1272,9 +1194,10 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 	}
 
 	/* update multicast filtering parameters */
+	fp->enabled = true;
 	if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
 		mc_count = 0;
-		fp->filters |= FIF_ALLMULTI;
+		fp->enabled = false;
 	}
 
 	fp->mc_list_length = 0;
@@ -1288,42 +1211,65 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
 		mc_list = mc_list->next;
 	}
 
-	/* FIXME: We still need to set our filters properly */
-
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	kfree(wl->filter_params);
-	wl->filter_params = fp;
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-	return 1;
+	return (u64)(unsigned long)fp;
 }
 
+#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+				  FIF_ALLMULTI | \
+				  FIF_FCSFAIL | \
+				  FIF_BCN_PRBRESP_PROMISC | \
+				  FIF_CONTROL | \
+				  FIF_OTHER_BSS)
+
 static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 				       unsigned int changed,
 				       unsigned int *total, u64 multicast)
 {
+	struct wl1271_filter_params *fp = (void *)(unsigned long)multicast;
 	struct wl1271 *wl = hw->priv;
+	int ret;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
 
+	mutex_lock(&wl->mutex);
+
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl, false);
+	if (ret < 0)
+		goto out;
+
 	*total &= WL1271_SUPPORTED_FILTERS;
 	changed &= WL1271_SUPPORTED_FILTERS;
 
-	if (!multicast)
-		return;
+	if (*total & FIF_ALLMULTI)
+		ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
+	else if (fp)
+		ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
+						   fp->mc_list,
+						   fp->mc_list_length);
+	if (ret < 0)
+		goto out_sleep;
 
-	/*
-	 * FIXME: for now we are still using a workqueue for filter
-	 * configuration, but with the new mac80211, this is not needed,
-	 * since configure_filter can now sleep.  We now have
-	 * prepare_multicast, which needs to be atomic instead.
-	 */
+	kfree(fp);
+
+	/* FIXME: We still need to set our filters properly */
 
-	/* store current filter config */
-	wl->filter_params->filters = *total;
-	wl->filter_params->changed = changed;
+	/* determine, whether supported filter values have changed */
+	if (changed == 0)
+		goto out_sleep;
 
-	ieee80211_queue_work(wl->hw, &wl->filter_work);
+	/* apply configured filters */
+	ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
 }
 
 static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -1866,7 +1812,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 
 	skb_queue_head_init(&wl->tx_queue);
 
-	INIT_WORK(&wl->filter_work, wl1271_filter_work);
 	INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
 	wl->channel = WL1271_DEFAULT_CHANNEL;
 	wl->scanning = false;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 18/22] wl1271: Support for IPv4 ARP filtering
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen, Janne Ylälehto
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add support for IPv4 ARP filtering in the driver. This will dramatically
reduce the number of unnecessary interrupts by the device in conqested
networks.

This patch is based on a similar patch to wl1251 by Janne Ylälehto.

Cc: Janne Ylälehto <janne.ylalehto@nokia.com>
Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    2 +
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   38 +++++++++++
 drivers/net/wireless/wl12xx/wl1271_acx.h  |   17 +++++
 drivers/net/wireless/wl12xx/wl1271_main.c |  100 +++++++++++++++++++++++++++++
 4 files changed, 157 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 79a7324..1e399a2 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -441,6 +441,8 @@ struct wl1271 {
 
 	/* Current chipset configuration */
 	struct conf_drv_settings conf;
+
+	struct list_head list;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 44a1237..e891cd5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -1092,3 +1092,41 @@ out:
 	kfree(acx);
 	return ret;
 }
+
+int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
+			     u8 version)
+{
+	struct wl1271_acx_arp_filter *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx arp ip filter, enable: %d", enable);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->version = version;
+	acx->enable = enable;
+
+	if (enable == true) {
+		if (version == ACX_IPV4_VERSION)
+			memcpy(acx->address, address, ACX_IPV4_ADDR_SIZE);
+		else if (version == ACX_IPV6_VERSION)
+			memcpy(acx->address, address, sizeof(acx->address));
+		else
+			wl1271_error("Invalid IP version");
+	}
+
+	ret = wl1271_cmd_configure(wl, ACX_ARP_IP_FILTER,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("failed to set arp ip filter: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 29fd363..1580314 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -955,6 +955,21 @@ struct wl1271_acx_bet_enable {
 	u8 padding[2];
 } __attribute__ ((packed));
 
+#define ACX_IPV4_VERSION 4
+#define ACX_IPV6_VERSION 6
+#define ACX_IPV4_ADDR_SIZE 4
+struct wl1271_acx_arp_filter {
+	struct acx_header header;
+	u8 version;         /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
+	u8 enable;          /* 1 to enable ARP filtering, 0 to disable */
+	u8 padding[2];
+	u8 address[16];     /* The configured device IP address - all ARP
+			       requests directed to this IP address will pass
+			       through. For IPv4, the first four bytes are
+			       used. */
+} __attribute__((packed));
+
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
@@ -1064,5 +1079,7 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
 int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
+int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address,
+			     u8 version);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d6d1a4c..7d70f41 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -32,6 +32,7 @@
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/spi/wl12xx.h>
+#include <linux/inetdevice.h>
 
 #include "wl1271.h"
 #include "wl12xx_80211.h"
@@ -325,6 +326,8 @@ static struct conf_drv_settings default_conf = {
 	}
 };
 
+static LIST_HEAD(wl_list);
+
 static void wl1271_conf_init(struct wl1271 *wl)
 {
 
@@ -843,6 +846,93 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	return NETDEV_TX_OK;
 }
 
+static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
+			     void *arg)
+{
+	struct net_device *dev;
+	struct wireless_dev *wdev;
+	struct wiphy *wiphy;
+	struct ieee80211_hw *hw;
+	struct wl1271 *wl;
+	struct wl1271 *wl_temp;
+	struct in_device *idev;
+	struct in_ifaddr *ifa = arg;
+	int ret = 0;
+
+	/* FIXME: this ugly function should probably be implemented in the
+	 * mac80211, and here should only be a simple callback handling actual
+	 * setting of the filters. Now we need to dig up references to
+	 * various structures to gain access to what we need.
+	 * Also, because of this, there is no "initial" setting of the filter
+	 * in "op_start", because we don't want to dig up struct net_device
+	 * there - the filter will be set upon first change of the interface
+	 * IP address. */
+
+	dev = ifa->ifa_dev->dev;
+
+	wdev = dev->ieee80211_ptr;
+	if (wdev == NULL)
+		return -ENODEV;
+
+	wiphy = wdev->wiphy;
+	if (wiphy == NULL)
+		return -ENODEV;
+
+	hw = wiphy_priv(wiphy);
+	if (hw == NULL)
+		return -ENODEV;
+
+	/* Check that the interface is one supported by this driver. */
+	wl_temp = hw->priv;
+	list_for_each_entry(wl, &wl_list, list) {
+		if (wl == wl_temp)
+			break;
+	}
+	if (wl == NULL)
+		return -ENODEV;
+
+	/* Get the interface IP address for the device. "ifa" will become
+	   NULL if:
+	     - there is no IPV4 protocol address configured
+	     - there are multiple (virtual) IPV4 addresses configured
+	   When "ifa" is NULL, filtering will be disabled.
+	*/
+	ifa = NULL;
+	idev = dev->ip_ptr;
+	if (idev)
+		ifa = idev->ifa_list;
+
+	if (ifa && ifa->ifa_next)
+		ifa = NULL;
+
+	mutex_lock(&wl->mutex);
+
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl, false);
+	if (ret < 0)
+		goto out;
+	if (ifa)
+		ret = wl1271_acx_arp_ip_filter(wl, true,
+					       (u8 *)&ifa->ifa_address,
+					       ACX_IPV4_VERSION);
+	else
+		ret = wl1271_acx_arp_ip_filter(wl, false, NULL,
+					       ACX_IPV4_VERSION);
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
+static struct notifier_block wl1271_dev_notifier = {
+	.notifier_call = wl1271_dev_notify,
+};
+
+
 static int wl1271_op_start(struct ieee80211_hw *hw)
 {
 	struct wl1271 *wl = hw->priv;
@@ -886,6 +976,11 @@ out_power_off:
 out:
 	mutex_unlock(&wl->mutex);
 
+	if (!ret) {
+		list_add(&wl->list, &wl_list);
+		register_inetaddr_notifier(&wl1271_dev_notifier);
+	}
+
 	return ret;
 }
 
@@ -906,6 +1001,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
 	wl->filter_params = NULL;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
+	unregister_inetaddr_notifier(&wl1271_dev_notifier);
+	list_del(&wl->list);
+
 	mutex_lock(&wl->mutex);
 
 	WARN_ON(wl->state != WL1271_STATE_ON);
@@ -1754,6 +1852,8 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl = hw->priv;
 	memset(wl, 0, sizeof(*wl));
 
+	INIT_LIST_HEAD(&wl->list);
+
 	wl->hw = hw;
 	dev_set_drvdata(&spi->dev, wl);
 	wl->spi = spi;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 17/22] wl1271: Fix event handling mechanism
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

The event handling mechanism could miss events if multiple events would
occur simultaneously. Fix event handling mechanism to process all
events.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_event.c |    6 ++++--
 drivers/net/wireless/wl12xx/wl1271_event.h |    2 +-
 drivers/net/wireless/wl12xx/wl1271_main.c  |   17 +++++++++--------
 3 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index e2d7758..a4b11e4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -126,7 +126,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl)
 		     wl->mbox_ptr[0], wl->mbox_ptr[1]);
 }
 
-int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack)
 {
 	struct event_mailbox mbox;
 	int ret;
@@ -146,7 +146,9 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
 		return ret;
 
 	/* then we let the firmware know it can go on...*/
-	wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+	if (do_ack)
+		wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG,
+				   INTR_TRIG_EVENT_ACK);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h
index 2cdce7c..adc4653 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.h
+++ b/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -105,6 +105,6 @@ struct event_mailbox {
 
 int wl1271_event_unmask(struct wl1271 *wl);
 void wl1271_event_mbox_config(struct wl1271 *wl);
-int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
+int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 19dbdb1..d6d1a4c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -437,14 +437,15 @@ static void wl1271_irq_work(struct work_struct *work)
 
 	intr &= WL1271_INTR_MASK;
 
-	if (intr & (WL1271_ACX_INTR_EVENT_A |
-		    WL1271_ACX_INTR_EVENT_B)) {
-		wl1271_debug(DEBUG_IRQ,
-			     "WL1271_ACX_INTR_EVENT (0x%x)", intr);
-		if (intr & WL1271_ACX_INTR_EVENT_A)
-			wl1271_event_handle(wl, 0);
-		else
-			wl1271_event_handle(wl, 1);
+	if (intr & WL1271_ACX_INTR_EVENT_A) {
+		bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true;
+		wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A");
+		wl1271_event_handle(wl, 0, do_ack);
+	}
+
+	if (intr & WL1271_ACX_INTR_EVENT_B) {
+		wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B");
+		wl1271_event_handle(wl, 1, true);
 	}
 
 	if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 21/22] wl1271: make sure PS is disabled in PLT
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

We cannot be in PS mode when running PLT tests, so we need to make sure we're
in active mode.  Also, we need to clear up the rx_counter when we stop PLT,
otherwise it could cause problems when entering PLT again.

Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index dfa08a1..7b8d279 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -774,6 +774,11 @@ int wl1271_plt_start(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_irq_disable;
 
+	/* Make sure power saving is disabled */
+	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+	if (ret < 0)
+		goto out_irq_disable;
+
 	goto out;
 
 out_irq_disable:
@@ -807,6 +812,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
 	wl1271_power_off(wl);
 
 	wl->state = WL1271_STATE_OFF;
+	wl->rx_counter = 0;
 
 out:
 	mutex_unlock(&wl->mutex);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 19/22] wl1271: Remove unnecessary rx_descriptor memory allocation
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Remove unnecessary RX descriptor memory allocation from the driver. The
allocation was a remnant of the wl1251 driver.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    1 -
 drivers/net/wireless/wl12xx/wl1271_main.c |   13 -------------
 2 files changed, 0 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 1e399a2..fca5968 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -429,7 +429,6 @@ struct wl1271 {
 	u32 buffer_32;
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
-	struct wl1271_rx_descriptor *rx_descriptor;
 
 	struct wl1271_fw_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 7d70f41..dfa08a1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1893,13 +1893,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl->state = WL1271_STATE_OFF;
 	mutex_init(&wl->mutex);
 
-	wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
-	if (!wl->rx_descriptor) {
-		wl1271_error("could not allocate memory for rx descriptor");
-		ret = -ENOMEM;
-		goto out_free;
-	}
-
 	/* This is the only SPI value that we need to set here, the rest
 	 * comes from the board-peripherals file */
 	spi->bits_per_word = 32;
@@ -1965,9 +1958,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	free_irq(wl->irq, wl);
 
  out_free:
-	kfree(wl->rx_descriptor);
-	wl->rx_descriptor = NULL;
-
 	ieee80211_free_hw(hw);
 
 	return ret;
@@ -1988,9 +1978,6 @@ static int __devexit wl1271_remove(struct spi_device *spi)
 	kfree(wl->nvs);
 	wl->nvs = NULL;
 
-	kfree(wl->rx_descriptor);
-	wl->rx_descriptor = NULL;
-
 	kfree(wl->fw_status);
 	kfree(wl->tx_res_if);
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 06/22] wl1271: Add config structure for FW init parameters
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add a configuration structure for RX path parameters, and set default
configuration values there.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   39 ++-----
 drivers/net/wireless/wl12xx/wl1271_conf.h |  182 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_init.c |  128 ++++++++++-----------
 drivers/net/wireless/wl12xx/wl1271_init.h |   51 +++-----
 drivers/net/wireless/wl12xx/wl1271_main.c |  103 ++++++++++++++++
 5 files changed, 376 insertions(+), 127 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index d003686..880c828 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -1014,7 +1014,7 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl)
 {
 	struct acx_smart_reflex_state *sr_state = NULL;
 	struct acx_smart_reflex_config_params *sr_param = NULL;
-	int ret;
+	int i, ret;
 
 	wl1271_debug(DEBUG_ACX, "acx smart reflex");
 
@@ -1024,33 +1024,14 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl)
 		goto out;
 	}
 
-	/* set cryptic smart reflex parameters - source TI reference code */
-	sr_param->error_table[0].len = 0x07;
-	sr_param->error_table[0].upper_limit = 0x03;
-	sr_param->error_table[0].values[0] = 0x18;
-	sr_param->error_table[0].values[1] = 0x10;
-	sr_param->error_table[0].values[2] = 0x05;
-	sr_param->error_table[0].values[3] = 0xfb;
-	sr_param->error_table[0].values[4] = 0xf0;
-	sr_param->error_table[0].values[5] = 0xe8;
-
-	sr_param->error_table[1].len = 0x07;
-	sr_param->error_table[1].upper_limit = 0x03;
-	sr_param->error_table[1].values[0] = 0x18;
-	sr_param->error_table[1].values[1] = 0x10;
-	sr_param->error_table[1].values[2] = 0x05;
-	sr_param->error_table[1].values[3] = 0xf6;
-	sr_param->error_table[1].values[4] = 0xf0;
-	sr_param->error_table[1].values[5] = 0xe8;
-
-	sr_param->error_table[2].len = 0x07;
-	sr_param->error_table[2].upper_limit = 0x03;
-	sr_param->error_table[2].values[0] = 0x18;
-	sr_param->error_table[2].values[1] = 0x10;
-	sr_param->error_table[2].values[2] = 0x05;
-	sr_param->error_table[2].values[3] = 0xfb;
-	sr_param->error_table[2].values[4] = 0xf0;
-	sr_param->error_table[2].values[5] = 0xe8;
+	for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) {
+		struct conf_mart_reflex_err_table *e =
+			&(wl->conf.init.sr_err_tbl[i]);
+
+		sr_param->error_table[i].len = e->len;
+		sr_param->error_table[i].upper_limit = e->upper_limit;
+		memcpy(sr_param->error_table[i].values, e->values, e->len);
+	}
 
 	ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS,
 				   sr_param, sizeof(*sr_param));
@@ -1066,7 +1047,7 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl)
 	}
 
 	/* enable smart reflex */
-	sr_state->enable = 1;
+	sr_state->enable = wl->conf.init.sr_enable;
 
 	ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE,
 				   sr_state, sizeof(*sr_state));
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index f08e509..5333a27 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -691,11 +691,193 @@ struct conf_conn_settings {
 	struct conf_sig_weights sig_weights;
 };
 
+#define CONF_SR_ERR_TBL_MAX_VALUES   14
+
+struct conf_mart_reflex_err_table {
+	/*
+	 * Length of the error table values table.
+	 *
+	 * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES
+	 */
+	u8 len;
+
+	/*
+	 * Smart Reflex error table upper limit.
+	 *
+	 * Range: s8
+	 */
+	s8 upper_limit;
+
+	/*
+	 * Smart Reflex error table values.
+	 *
+	 * Range: s8
+	 */
+	s8 values[CONF_SR_ERR_TBL_MAX_VALUES];
+};
+
+enum {
+	CONF_REF_CLK_19_2_E,
+	CONF_REF_CLK_26_E,
+	CONF_REF_CLK_38_4_E,
+	CONF_REF_CLK_52_E
+};
+
+struct conf_general_parms {
+	/*
+	 * RF Reference Clock type / speed
+	 *
+	 * Range: CONF_REF_CLK_*
+	 */
+	u8 ref_clk;
+
+	/*
+	 * Settling time of the reference clock after boot.
+	 *
+	 * Range: u8
+	 */
+	u8 settling_time;
+
+	/*
+	 * Flag defining whether clock is valid on wakeup.
+	 *
+	 * Range: 0 - not valid on wakeup, 1 - valid on wakeup
+	 */
+	u8 clk_valid_on_wakeup;
+
+	/*
+	 * DC-to-DC mode.
+	 *
+	 * Range: Unknown
+	 */
+	u8 dc2dcmode;
+
+	/*
+	 * Flag defining whether used as single or dual-band.
+	 *
+	 * Range: Unknown
+	 */
+	u8 single_dual_band;
+
+	/*
+	 * TX bip fem autodetect flag.
+	 *
+	 * Range: Unknown
+	 */
+	u8 tx_bip_fem_autodetect;
+
+	/*
+	 * TX bip gem manufacturer.
+	 *
+	 * Range: Unknown
+	 */
+	u8 tx_bip_fem_manufacturer;
+
+	/*
+	 * Settings flags.
+	 *
+	 * Range: Unknown
+	 */
+	u8 settings;
+};
+
+#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
+#define CONF_NUMBER_OF_SUB_BANDS_5  7
+#define CONF_NUMBER_OF_RATE_GROUPS  6
+#define CONF_NUMBER_OF_CHANNELS_2_4 14
+#define CONF_NUMBER_OF_CHANNELS_5   35
+
+struct conf_radio_parms {
+	/*
+	 * Static radio parameters for 2.4GHz
+	 *
+	 * Range: unknown
+	 */
+	u8 rx_trace_loss;
+	u8 tx_trace_loss;
+	s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
+
+	/*
+	 * Static radio parameters for 5GHz
+	 *
+	 * Range: unknown
+	 */
+	u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
+
+	/*
+	 * Dynamic radio parameters for 2.4GHz
+	 *
+	 * Range: unknown
+	 */
+	s16 tx_ref_pd_voltage;
+	s8  tx_ref_power;
+	s8  tx_offset_db;
+
+	s8  tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
+
+	s8  tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
+	s8  tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
+	s8  tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
+
+	u8  tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
+	u8  rx_fem_insertion_loss;
+
+	/*
+	 * Dynamic radio parameters for 5GHz
+	 *
+	 * Range: unknown
+	 */
+	s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8  tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8  tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
+
+	s8  tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+	s8  tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
+	s8  tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
+
+	/* FIXME: this is inconsistent with the types for 2.4GHz */
+	s8  tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+};
+
+#define CONF_SR_ERR_TBL_COUNT        3
+
+struct conf_init_settings {
+	/*
+	 * Configure Smart Reflex error table values.
+	 */
+	struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT];
+
+	/*
+	 * Smart Reflex enable flag.
+	 *
+	 * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled
+	 */
+	u8 sr_enable;
+
+	/*
+	 * Configure general parameters.
+	 */
+	struct conf_general_parms genparam;
+
+	/*
+	 * Configure radio parameters.
+	 */
+	struct conf_radio_parms radioparam;
+
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
 	struct conf_tx_settings tx;
 	struct conf_conn_settings conn;
+	struct conf_init_settings init;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index a3fc4c9..5c2cf1e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -188,6 +188,7 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
 static int wl1271_init_general_parms(struct wl1271 *wl)
 {
 	struct wl1271_general_parms *gen_parms;
+	struct conf_general_parms *g = &wl->conf.init.genparam;
 	int ret;
 
 	gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
@@ -196,22 +197,14 @@ static int wl1271_init_general_parms(struct wl1271 *wl)
 
 	gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM;
 
-	/*
-	 * FIXME: The firmware crashes on boot with REF_CLK_38_4_E as clock.
-	 *        according to TI engineers, ref clk 5 is an unofficial
-	 *        38.4 XTAL clock config, which seems to boot the device.
-	 *        Restore correct value once the real problem source is
-	 *        identified.
-	 */
-	gen_parms->ref_clk = 5; /* REF_CLK_38_4_E; */
-	/* FIXME: magic numbers */
-	gen_parms->settling_time = 5;
-	gen_parms->clk_valid_on_wakeup = 0;
-	gen_parms->dc2dcmode = 0;
-	gen_parms->single_dual_band = 0;
-	gen_parms->tx_bip_fem_autodetect = 0;
-	gen_parms->tx_bip_fem_manufacturer = 1;
-	gen_parms->settings = 1;
+	gen_parms->ref_clk = g->ref_clk;
+	gen_parms->settling_time = g->settling_time;
+	gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
+	gen_parms->dc2dcmode = g->dc2dcmode;
+	gen_parms->single_dual_band = g->single_dual_band;
+	gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
+	gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
+	gen_parms->settings = g->settings;
 
 	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
 	if (ret < 0) {
@@ -225,32 +218,9 @@ static int wl1271_init_general_parms(struct wl1271 *wl)
 
 static int wl1271_init_radio_parms(struct wl1271 *wl)
 {
-	/*
-	 * FIXME: All these magic numbers should be moved to some place where
-	 * they can be configured (separate file?)
-	 */
-
 	struct wl1271_radio_parms *radio_parms;
-	int ret;
-	u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00,
-			      0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 };
-
-	u8 tx_rate_limits_normal[]   = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 };
-	u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 };
-
-	u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50,
-				       0x50, 0x50, 0x50, 0x50,
-				       0x50, 0x50, 0x22, 0x50,
-				       0x22, 0x50 };
-
-	u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50,
-					0x50, 0x50, 0x50, 0x50,
-					0x50, 0x50, 0x20, 0x50,
-					0x20, 0x50 };
-
-	u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-	u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 };
+	struct conf_radio_parms *r = &wl->conf.init.radioparam;
+	int i, ret;
 
 	radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
 	if (!radio_parms)
@@ -259,33 +229,59 @@ static int wl1271_init_radio_parms(struct wl1271 *wl)
 	radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM;
 
 	/* Static radio parameters */
-	radio_parms->rx_trace_loss = 10;
-	radio_parms->tx_trace_loss = 10;
-	memcpy(radio_parms->rx_rssi_and_proc_compens, compensation,
-	       sizeof(compensation));
-
-	/* We don't set the 5GHz -- N/A */
+	radio_parms->rx_trace_loss = r->rx_trace_loss;
+	radio_parms->tx_trace_loss = r->tx_trace_loss;
+	memcpy(radio_parms->rx_rssi_and_proc_compens,
+	       r->rx_rssi_and_proc_compens,
+	       CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
+
+	memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
+	       CONF_NUMBER_OF_SUB_BANDS_5);
+	memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
+	       CONF_NUMBER_OF_SUB_BANDS_5);
+	memcpy(radio_parms->rx_rssi_and_proc_compens_5,
+	       r->rx_rssi_and_proc_compens_5,
+	       CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
 
 	/* Dynamic radio parameters */
-	radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e);
-	radio_parms->tx_ref_power = 0x78;
-	radio_parms->tx_offset_db = 0x0;
-
-	memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal,
-	       sizeof(tx_rate_limits_normal));
-	memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded,
-	       sizeof(tx_rate_limits_degraded));
-
-	memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b,
-	       sizeof(tx_channel_limits_11b));
-	memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm,
-	       sizeof(tx_channel_limits_ofdm));
-	memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets,
-	       sizeof(tx_pdv_rate_offsets));
-	memcpy(radio_parms->tx_ibias, tx_ibias,
-	       sizeof(tx_ibias));
-
-	radio_parms->rx_fem_insertion_loss = 0x14;
+	radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
+	radio_parms->tx_ref_power = r->tx_ref_power;
+	radio_parms->tx_offset_db = r->tx_offset_db;
+
+	memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
+	       CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
+	       CONF_NUMBER_OF_RATE_GROUPS);
+
+	memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
+	       CONF_NUMBER_OF_CHANNELS_2_4);
+	memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
+	       CONF_NUMBER_OF_CHANNELS_2_4);
+	memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
+	       CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
+
+	radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
+
+	for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
+		radio_parms->tx_ref_pd_voltage_5[i] =
+			cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
+	memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
+	       CONF_NUMBER_OF_SUB_BANDS_5);
+	memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
+	       CONF_NUMBER_OF_SUB_BANDS_5);
+	memcpy(radio_parms->tx_rate_limits_normal_5,
+	       r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->tx_rate_limits_degraded_5,
+	       r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->tx_channel_limits_ofdm_5,
+	       r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
+	memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
+	       CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
+	       CONF_NUMBER_OF_RATE_GROUPS);
+	memcpy(radio_parms->rx_fem_insertion_loss_5,
+	       r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
 
 	ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h
index bd8ff0f..513d0cb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.h
+++ b/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -48,19 +48,6 @@ struct wl1271_general_parms {
 	u8 settings;
 } __attribute__ ((packed));
 
-enum ref_clk_enum {
-	REF_CLK_19_2_E,
-	REF_CLK_26_E,
-	REF_CLK_38_4_E,
-	REF_CLK_52_E
-};
-
-#define RSSI_AND_PROCESS_COMPENSATION_SIZE 15
-#define NUMBER_OF_SUB_BANDS_5  7
-#define NUMBER_OF_RATE_GROUPS  6
-#define NUMBER_OF_CHANNELS_2_4 14
-#define NUMBER_OF_CHANNELS_5   35
-
 struct wl1271_radio_parms {
 	u8 id;
 	u8 padding[3];
@@ -69,12 +56,12 @@ struct wl1271_radio_parms {
 	/* 2.4GHz */
 	u8 rx_trace_loss;
 	u8 tx_trace_loss;
-	s8 rx_rssi_and_proc_compens[RSSI_AND_PROCESS_COMPENSATION_SIZE];
+	s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
 
 	/* 5GHz */
-	u8 rx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
-	u8 tx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
-	s8 rx_rssi_and_proc_compens_5[RSSI_AND_PROCESS_COMPENSATION_SIZE];
+	u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
 
 	/* Dynamic radio parameters */
 	/* 2.4GHz */
@@ -82,32 +69,32 @@ struct wl1271_radio_parms {
 	s8  tx_ref_power;
 	s8  tx_offset_db;
 
-	s8  tx_rate_limits_normal[NUMBER_OF_RATE_GROUPS];
-	s8  tx_rate_limits_degraded[NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
 
-	s8  tx_channel_limits_11b[NUMBER_OF_CHANNELS_2_4];
-	s8  tx_channel_limits_ofdm[NUMBER_OF_CHANNELS_2_4];
-	s8  tx_pdv_rate_offsets[NUMBER_OF_RATE_GROUPS];
+	s8  tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
+	s8  tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
+	s8  tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
 
-	u8  tx_ibias[NUMBER_OF_RATE_GROUPS];
+	u8  tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
 	u8  rx_fem_insertion_loss;
 
 	u8 padding2;
 
 	/* 5GHz */
-	s16 tx_ref_pd_voltage_5[NUMBER_OF_SUB_BANDS_5];
-	s8  tx_ref_power_5[NUMBER_OF_SUB_BANDS_5];
-	s8  tx_offset_db_5[NUMBER_OF_SUB_BANDS_5];
+	s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8  tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
+	s8  tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
 
-	s8  tx_rate_limits_normal_5[NUMBER_OF_RATE_GROUPS];
-	s8  tx_rate_limits_degraded_5[NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
 
-	s8  tx_channel_limits_ofdm_5[NUMBER_OF_CHANNELS_5];
-	s8  tx_pdv_rate_offsets_5[NUMBER_OF_RATE_GROUPS];
+	s8  tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
+	s8  tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
 
 	/* FIXME: this is inconsistent with the types for 2.4GHz */
-	s8  tx_ibias_5[NUMBER_OF_RATE_GROUPS];
-	s8  rx_fem_insertion_loss_5[NUMBER_OF_SUB_BANDS_5];
+	s8  tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
+	s8  rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
 
 	u8 padding3[2];
 } __attribute__ ((packed));
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index a559a15..0b17b05 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -224,6 +224,109 @@ static void wl1271_conf_init(struct wl1271 *wl)
 				.snr_bcn_avg_weight  = 10,
 				.snr_pkt_avg_weight  = 10
 			}
+		},
+		.init = {
+			.sr_err_tbl = {
+				[0] = {
+					.len         = 7,
+					.upper_limit = 0x03,
+					.values      = {
+						0x18, 0x10, 0x05, 0xfb,
+						0xf0, 0xe8, 0x00 }
+				},
+				[1] = {
+					.len         = 7,
+					.upper_limit = 0x03,
+					.values      = {
+						0x18, 0x10, 0x05, 0xf6,
+						0xf0, 0xe8, 0x00 }
+				},
+				[2] = {
+					.len         = 7,
+					.upper_limit = 0x03,
+					.values      = {
+						0x18, 0x10, 0x05, 0xfb,
+						0xf0, 0xe8, 0x00 }
+				}
+			},
+			.sr_enable = 1,
+			.genparam = {
+				/*
+				 * FIXME: The correct value CONF_REF_CLK_38_4_E
+				 *        causes the firmware to crash on boot.
+				 *        The value 5 apparently is an
+				 *        unnoficial XTAL configuration of the
+				 *        same frequency, which appears to work.
+				 */
+				.ref_clk             = 5,
+				.settling_time       = 5,
+				.clk_valid_on_wakeup = 0,
+				.dc2dcmode           = 0,
+				.single_dual_band    = 0,
+				.tx_bip_fem_autodetect = 0,
+				.tx_bip_fem_manufacturer = 1,
+				.settings = 1,
+			},
+			.radioparam = {
+				/* FIXME: 5GHz values unset! */
+				.rx_trace_loss       = 10,
+				.tx_trace_loss       = 10,
+				.rx_rssi_and_proc_compens = {
+					0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
+					0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8,
+					0x00, 0x0a, 0x14 },
+				.rx_trace_loss_5     = {
+					0, 0, 0, 0, 0, 0, 0 },
+				.tx_trace_loss_5     = {
+					0, 0, 0, 0, 0, 0, 0 },
+				.rx_rssi_and_proc_compens_5 = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00 },
+				.tx_ref_pd_voltage   = 0x24e,
+				.tx_ref_power        = 0x78,
+				.tx_offset_db        = 0x0,
+				.tx_rate_limits_normal = {
+					0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 },
+				.tx_rate_limits_degraded = {
+					0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
+				.tx_channel_limits_11b = {
+					0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
+					0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
+					0x22, 0x50 },
+				.tx_channel_limits_ofdm = {
+					0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
+					0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
+					0x20, 0x50 },
+				.tx_pdv_rate_offsets = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+				.tx_ibias            = {
+					0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 },
+				.rx_fem_insertion_loss = 0x14,
+				.tx_ref_pd_voltage_5 = {
+					0, 0, 0, 0, 0, 0, 0 },
+				.tx_ref_power_5      = {
+					0, 0, 0, 0, 0, 0, 0 },
+				.tx_offset_db_5      = {
+					0, 0, 0, 0, 0, 0, 0 },
+				.tx_rate_limits_normal_5 = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+				.tx_rate_limits_degraded_5 = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+				.tx_channel_limits_ofdm_5 = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					0x00, 0x00, 0x00, 0x00, 0x00},
+				.tx_pdv_rate_offsets_5 = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+				.tx_ibias_5          = {
+					0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+				.rx_fem_insertion_loss_5 = {
+					0, 0, 0, 0, 0, 0, 0 }
+			}
 		}
 	};
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 02/22] wl1271: Add structure for firmware configuration values
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

In order to make the firmware configuration more manageable, collect
hardcoded configuration values into one data structure, and set default values
there.

Add the SoftGemini BT/WLAN coex paramters into the config structure.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    5 +
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   40 ++-----
 drivers/net/wireless/wl12xx/wl1271_acx.h  |  136 +++-------------------
 drivers/net/wireless/wl12xx/wl1271_cmd.c  |    6 +-
 drivers/net/wireless/wl12xx/wl1271_cmd.h  |    5 -
 drivers/net/wireless/wl12xx/wl1271_conf.h |  178 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_main.c |   84 ++++++++++----
 drivers/net/wireless/wl12xx/wl1271_reg.h  |   44 -------
 8 files changed, 274 insertions(+), 224 deletions(-)
 create mode 100644 drivers/net/wireless/wl12xx/wl1271_conf.h

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index aa9bb2e..64a3270 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -32,6 +32,8 @@
 #include <linux/bitops.h>
 #include <net/mac80211.h>
 
+#include "wl1271_conf.h"
+
 #define DRIVER_NAME "wl1271"
 #define DRIVER_PREFIX DRIVER_NAME ": "
 
@@ -420,6 +422,9 @@ struct wl1271 {
 
 	/* Used for a workaround to send disconnect before rejoining */
 	bool joined;
+
+	/* Current chipset configuration */
+	struct conf_drv_settings conf;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 6c29890..d19d860 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -509,6 +509,7 @@ out:
 int wl1271_acx_sg_cfg(struct wl1271 *wl)
 {
 	struct acx_bt_wlan_coex_param *param;
+	struct conf_sg_settings *c = &wl->conf.sg;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "acx sg cfg");
@@ -520,34 +521,17 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
 	}
 
 	/* BT-WLAN coext parameters */
-	param->min_rate = RATE_INDEX_24MBPS;
-	param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
-	param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
-	param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
-	param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
-	param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
-	param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
-	param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
-	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->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;
-	param->signal_type = PTA_SIGNALING_TYPE_DEF;
-	param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
-	param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
-	param->max_cts = PTA_MAX_NUM_CTS_DEF;
-	param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
-	param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
-	param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
-	param->wlan_elp_hp = PTA_ELP_HP_DEF;
-	param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
-	param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
-	param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
-	param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
-	param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
+	param->per_threshold = c->per_threshold;
+	param->max_scan_compensation_time = c->max_scan_compensation_time;
+	param->nfs_sample_interval = c->nfs_sample_interval;
+	param->load_ratio = c->load_ratio;
+	param->auto_ps_mode = c->auto_ps_mode;
+	param->probe_req_compensation = c->probe_req_compensation;
+	param->scan_window_compensation = c->scan_window_compensation;
+	param->antenna_config = c->antenna_config;
+	param->beacon_miss_threshold = c->beacon_miss_threshold;
+	param->rate_adaptation_threshold = c->rate_adaptation_threshold;
+	param->rate_adaptation_snr = c->rate_adaptation_snr;
 
 	ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
 	if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 0c704af..8e3b97c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -496,126 +496,18 @@ struct acx_smart_reflex_config_params {
 struct acx_bt_wlan_coex_param {
 	struct acx_header header;
 
-	/*
-	 * The minimum rate of a received WLAN packet in the STA,
-	 * during protective mode, of which a new BT-HP request
-	 * during this Rx will always be respected and gain the antenna.
-	 */
-	u32 min_rate;
-
-	/* Max time the BT HP will be respected. */
-	u16 bt_hp_max_time;
-
-	/* Max time the WLAN HP will be respected. */
-	u16 wlan_hp_max_time;
-
-	/*
-	 * The time between the last BT activity
-	 * and the moment when the sense mode returns
-	 * to SENSE_INACTIVE.
-	 */
-	u16 sense_disable_timer;
-
-	/* Time before the next BT HP instance */
-	u16 rx_time_bt_hp;
-	u16 tx_time_bt_hp;
-
-	/* range: 10-20000    default: 1500 */
-	u16 rx_time_bt_hp_fast;
-	u16 tx_time_bt_hp_fast;
-
-	/* range: 2000-65535  default: 8700 */
-	u16 wlan_cycle_fast;
-
-	/* range: 0 - 15000 (Msec) default: 1000 */
-	u16 bt_anti_starvation_period;
-
-	/* range 400-10000(Usec) default: 3000 */
-	u16 next_bt_lp_packet;
-
-	/* Deafult: worst case for BT DH5 traffic */
-	u16 wake_up_beacon;
-
-	/* range: 0-50000(Usec) default: 1050 */
-	u16 hp_dm_max_guard_time;
-
-	/*
-	 * This is to prevent both BT & WLAN antenna
-	 * starvation.
-	 * Range: 100-50000(Usec) default:2550
-	 */
-	u16 next_wlan_packet;
-
-	/* 0 -> shared antenna */
-	u8 antenna_type;
-
-	/*
-	 * 0 -> TI legacy
-	 * 1 -> Palau
-	 */
-	u8 signal_type;
-
-	/*
-	 * BT AFH status
-	 * 0 -> no AFH
-	 * 1 -> from dedicated GPIO
-	 * 2 -> AFH on (from host)
-	 */
-	u8 afh_leverage_on;
-
-	/*
-	 * The number of cycles during which no
-	 * TX will be sent after 1 cycle of RX
-	 * transaction in protective mode
-	 */
-	u8 quiet_cycle_num;
-
-	/*
-	 * The maximum number of CTSs that will
-	 * be sent for receiving RX packet in
-	 * protective mode
-	 */
-	u8 max_cts;
-
-	/*
-	 * The number of WLAN packets
-	 * transferred in common mode before
-	 * switching to BT.
-	 */
-	u8 wlan_packets_num;
-
-	/*
-	 * The number of BT packets
-	 * transferred in common mode before
-	 * switching to WLAN.
-	 */
-	u8 bt_packets_num;
-
-	/* range: 1-255  default: 5 */
-	u8 missed_rx_avalanche;
-
-	/* range: 0-1    default: 1 */
-	u8 wlan_elp_hp;
-
-	/* range: 0 - 15  default: 4 */
-	u8 bt_anti_starvation_cycles;
-
-	u8 ack_mode_dual_ant;
-
-	/*
-	 * Allow PA_SD assertion/de-assertion
-	 * during enabled BT activity.
-	 */
-	u8 pa_sd_enable;
-
-	/*
-	 * Enable/Disable PTA in auto mode:
-	 * Support Both Active & P.S modes
-	 */
-	u8 pta_auto_mode_enable;
-
-	/* range: 0 - 20  default: 1 */
-	u8 bt_hp_respected_num;
+	u32 per_threshold;
+	u32 max_scan_compensation_time;
+	u16 nfs_sample_interval;
+	u8 load_ratio;
+	u8 auto_ps_mode;
+	u8 probe_req_compensation;
+	u8 scan_window_compensation;
+	u8 antenna_config;
+	u8 beacon_miss_threshold;
+	u32 rate_adaptation_threshold;
+	s8 rate_adaptation_snr;
+	u8 padding[3];
 } __attribute__ ((packed));
 
 #define CCA_THRSH_ENABLE_ENERGY_D       0x140A
@@ -690,6 +582,10 @@ struct acx_event_mask {
 #define SCAN_TRIGGERED		BIT(2)
 #define SCAN_PRIORITY_HIGH	BIT(3)
 
+/* When set, disable HW encryption */
+#define DF_ENCRYPTION_DISABLE      0x01
+#define DF_SNIFF_MODE_ENABLE       0x80
+
 struct acx_feature_config {
 	struct acx_header header;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index eaa1de9..c7a8a64 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -229,8 +229,8 @@ int wl1271_cmd_join(struct wl1271 *wl)
 	join->rx_config_options = 0;
 	join->rx_filter_options = WL1271_DEFAULT_RX_FILTER;
 
-	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
-		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
+	join->basic_rate_set = CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS |
+		CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS;
 
 	join->beacon_interval = WL1271_DEFAULT_BEACON_INT;
 	join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
@@ -538,7 +538,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 
 	params->params.num_channels = num_channels;
 	params->params.num_probe_requests = probe_requests;
-	params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS);
+	params->params.tx_rate = cpu_to_le32(CONF_HW_BIT_RATE_2MBPS);
 	params->params.tid_trigger = 0;
 	params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 0219664..9143087 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -288,11 +288,6 @@ struct wl1271_cmd_ps_params {
 #define NUM_ACCESS_CATEGORIES_COPY 4
 #define MAX_KEY_SIZE 32
 
-/* When set, disable HW encryption */
-#define DF_ENCRYPTION_DISABLE      0x01
-/* When set, disable HW decryption */
-#define DF_SNIFF_MODE_ENABLE       0x80
-
 enum wl1271_cmd_key_action {
 	KEY_ADD_OR_REPLACE = 1,
 	KEY_REMOVE         = 2,
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
new file mode 100644
index 0000000..1d6a44b
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -0,0 +1,178 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL1271_CONF_H__
+#define __WL1271_CONF_H__
+
+enum {
+	CONF_HW_BIT_RATE_1MBPS   = BIT(0),
+	CONF_HW_BIT_RATE_2MBPS   = BIT(1),
+	CONF_HW_BIT_RATE_5_5MBPS = BIT(2),
+	CONF_HW_BIT_RATE_6MBPS   = BIT(3),
+	CONF_HW_BIT_RATE_9MBPS   = BIT(4),
+	CONF_HW_BIT_RATE_11MBPS  = BIT(5),
+	CONF_HW_BIT_RATE_12MBPS  = BIT(6),
+	CONF_HW_BIT_RATE_18MBPS  = BIT(7),
+	CONF_HW_BIT_RATE_22MBPS  = BIT(8),
+	CONF_HW_BIT_RATE_24MBPS  = BIT(9),
+	CONF_HW_BIT_RATE_36MBPS  = BIT(10),
+	CONF_HW_BIT_RATE_48MBPS  = BIT(11),
+	CONF_HW_BIT_RATE_54MBPS  = BIT(12),
+	CONF_HW_BIT_RATE_MCS_0   = BIT(13),
+	CONF_HW_BIT_RATE_MCS_1   = BIT(14),
+	CONF_HW_BIT_RATE_MCS_2   = BIT(15),
+	CONF_HW_BIT_RATE_MCS_3   = BIT(16),
+	CONF_HW_BIT_RATE_MCS_4   = BIT(17),
+	CONF_HW_BIT_RATE_MCS_5   = BIT(18),
+	CONF_HW_BIT_RATE_MCS_6   = BIT(19),
+	CONF_HW_BIT_RATE_MCS_7   = BIT(20)
+};
+
+enum {
+	CONF_HW_RATE_INDEX_1MBPS   = 0,
+	CONF_HW_RATE_INDEX_2MBPS   = 1,
+	CONF_HW_RATE_INDEX_5_5MBPS = 2,
+	CONF_HW_RATE_INDEX_6MBPS   = 3,
+	CONF_HW_RATE_INDEX_9MBPS   = 4,
+	CONF_HW_RATE_INDEX_11MBPS  = 5,
+	CONF_HW_RATE_INDEX_12MBPS  = 6,
+	CONF_HW_RATE_INDEX_18MBPS  = 7,
+	CONF_HW_RATE_INDEX_22MBPS  = 8,
+	CONF_HW_RATE_INDEX_24MBPS  = 9,
+	CONF_HW_RATE_INDEX_36MBPS  = 10,
+	CONF_HW_RATE_INDEX_48MBPS  = 11,
+	CONF_HW_RATE_INDEX_54MBPS  = 12,
+	CONF_HW_RATE_INDEX_MAX     = CONF_HW_RATE_INDEX_54MBPS,
+};
+
+struct conf_sg_settings {
+	/*
+	 * Defines the PER threshold in PPM of the BT voice of which reaching
+	 * this value will trigger raising the priority of the BT voice by
+	 * the BT IP until next NFS sample interval time as defined in
+	 * nfs_sample_interval.
+	 *
+	 * Unit: PER value in PPM (parts per million)
+	 * #Error_packets / #Total_packets
+
+	 * Range: u32
+	 */
+	u32 per_threshold;
+
+	/*
+	 * This value is an absolute time in micro-seconds to limit the
+	 * maximum scan duration compensation while in SG
+	 */
+	u32 max_scan_compensation_time;
+
+	/* Defines the PER threshold of the BT voice of which reaching this
+	 * value will trigger raising the priority of the BT voice until next
+	 * NFS sample interval time as defined in sample_interval.
+	 *
+	 * Unit: msec
+	 * Range: 1-65000
+	 */
+	u16 nfs_sample_interval;
+
+	/*
+	 * Defines the load ratio for the BT.
+	 * The WLAN ratio is: 100 - load_ratio
+	 *
+	 * Unit: Percent
+	 * Range: 0-100
+	 */
+	u8 load_ratio;
+
+	/*
+	 * true - Co-ex is allowed to enter/exit P.S automatically and
+	 *        transparently to the host
+	 *
+	 * false - Co-ex is disallowed to enter/exit P.S and will trigger an
+	 *         event to the host to notify for the need to enter/exit P.S
+	 *         due to BT change state
+	 *
+	 */
+	u8 auto_ps_mode;
+
+	/*
+	 * This parameter defines the compensation percentage of num of probe
+	 * requests in case scan is initiated during BT voice/BT ACL
+	 * guaranteed link.
+	 *
+	 * Unit: Percent
+	 * Range: 0-255 (0 - No compensation)
+	 */
+	u8 probe_req_compensation;
+
+	/*
+	 * This parameter defines the compensation percentage of scan window
+	 * size in case scan is initiated during BT voice/BT ACL Guaranteed
+	 * link.
+	 *
+	 * Unit: Percent
+	 * Range: 0-255 (0 - No compensation)
+	 */
+	u8 scan_window_compensation;
+
+	/*
+	 * Defines the antenna configuration.
+	 *
+	 * Range: 0 - Single Antenna; 1 - Dual Antenna
+	 */
+	u8 antenna_config;
+
+	/*
+	 * The percent out of the Max consecutive beacon miss roaming trigger
+	 * which is the threshold for raising the priority of beacon
+	 * reception.
+	 *
+	 * Range: 1-100
+	 * N = MaxConsecutiveBeaconMiss
+	 * P = coexMaxConsecutiveBeaconMissPrecent
+	 * Threshold = MIN( N-1, round(N * P / 100))
+	 */
+	u8 beacon_miss_threshold;
+
+	/*
+	 * The RX rate threshold below which rate adaptation is assumed to be
+	 * occurring at the AP which will raise priority for ACTIVE_RX and RX
+	 * SP.
+	 *
+	 * Range: HW_BIT_RATE_*
+	 */
+	u32 rate_adaptation_threshold;
+
+	/*
+	 * The SNR above which the RX rate threshold indicating AP rate
+	 * adaptation is valid
+	 *
+	 * Range: -128 - 127
+	 */
+	s8 rate_adaptation_snr;
+};
+
+struct conf_drv_settings {
+	struct conf_sg_settings sg;
+};
+
+#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 821a775..69bc929 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -46,6 +46,39 @@
 #include "wl1271_cmd.h"
 #include "wl1271_boot.h"
 
+static void wl1271_conf_init(struct wl1271 *wl)
+{
+	struct conf_drv_settings conf = {
+		.sg = {
+			.per_threshold              = 7500,
+			.max_scan_compensation_time = 120000,
+			.nfs_sample_interval        = 400,
+			.load_ratio                 = 50,
+			.auto_ps_mode               = 0,
+			.probe_req_compensation     = 170,
+			.scan_window_compensation   = 50,
+			.antenna_config             = 0,
+			.beacon_miss_threshold      = 60,
+			.rate_adaptation_threshold  = CONF_HW_BIT_RATE_12MBPS,
+			.rate_adaptation_snr        = 0
+		}
+	};
+
+	/*
+	 * This function applies the default configuration to the driver. This
+	 * function is invoked upon driver load (spi probe.)
+	 *
+	 * The configuration is stored in a run-time structure in order to
+	 * facilitate for run-time adjustment of any of the parameters. Making
+	 * changes to the configuration structure will apply the new values on
+	 * the next interface up (wl1271_op_start.)
+	 */
+
+	/* apply driver default configuration */
+	memcpy(&wl->conf, &conf, sizeof(conf));
+}
+
+
 static int wl1271_plt_init(struct wl1271 *wl)
 {
 	int ret;
@@ -1180,44 +1213,44 @@ out:
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_rate wl1271_rates[] = {
 	{ .bitrate = 10,
-	  .hw_value = 0x1,
-	  .hw_value_short = 0x1, },
+	  .hw_value = CONF_HW_BIT_RATE_1MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_1MBPS, },
 	{ .bitrate = 20,
-	  .hw_value = 0x2,
-	  .hw_value_short = 0x2,
+	  .hw_value = CONF_HW_BIT_RATE_2MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_2MBPS,
 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 	{ .bitrate = 55,
-	  .hw_value = 0x4,
-	  .hw_value_short = 0x4,
+	  .hw_value = CONF_HW_BIT_RATE_5_5MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_5_5MBPS,
 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 	{ .bitrate = 110,
-	  .hw_value = 0x20,
-	  .hw_value_short = 0x20,
+	  .hw_value = CONF_HW_BIT_RATE_11MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_11MBPS,
 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE },
 	{ .bitrate = 60,
-	  .hw_value = 0x8,
-	  .hw_value_short = 0x8, },
+	  .hw_value = CONF_HW_BIT_RATE_6MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_6MBPS, },
 	{ .bitrate = 90,
-	  .hw_value = 0x10,
-	  .hw_value_short = 0x10, },
+	  .hw_value = CONF_HW_BIT_RATE_9MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_9MBPS, },
 	{ .bitrate = 120,
-	  .hw_value = 0x40,
-	  .hw_value_short = 0x40, },
+	  .hw_value = CONF_HW_BIT_RATE_12MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_12MBPS, },
 	{ .bitrate = 180,
-	  .hw_value = 0x80,
-	  .hw_value_short = 0x80, },
+	  .hw_value = CONF_HW_BIT_RATE_18MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_18MBPS, },
 	{ .bitrate = 240,
-	  .hw_value = 0x200,
-	  .hw_value_short = 0x200, },
+	  .hw_value = CONF_HW_BIT_RATE_24MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_24MBPS, },
 	{ .bitrate = 360,
-	 .hw_value = 0x400,
-	 .hw_value_short = 0x400, },
+	 .hw_value = CONF_HW_BIT_RATE_36MBPS,
+	 .hw_value_short = CONF_HW_BIT_RATE_36MBPS, },
 	{ .bitrate = 480,
-	  .hw_value = 0x800,
-	  .hw_value_short = 0x800, },
+	  .hw_value = CONF_HW_BIT_RATE_48MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_48MBPS, },
 	{ .bitrate = 540,
-	  .hw_value = 0x1000,
-	  .hw_value_short = 0x1000, },
+	  .hw_value = CONF_HW_BIT_RATE_54MBPS,
+	  .hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
 };
 
 /* can't be const, mac80211 writes to this */
@@ -1433,6 +1466,9 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	}
 	dev_set_drvdata(&wl1271_device.dev, wl);
 
+	/* Apply default driver configuration. */
+	wl1271_conf_init(wl);
+
 	ret = wl1271_init_ieee80211(wl);
 	if (ret)
 		goto out_platform;
diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index 6af87b5..1f23738 100644
--- a/drivers/net/wireless/wl12xx/wl1271_reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -613,50 +613,6 @@ enum {
 	MAX_RADIO_BANDS = 0xFF
 };
 
-enum {
-	NO_RATE      = 0,
-	RATE_1MBPS   = 0x0A,
-	RATE_2MBPS   = 0x14,
-	RATE_5_5MBPS = 0x37,
-	RATE_6MBPS   = 0x0B,
-	RATE_9MBPS   = 0x0F,
-	RATE_11MBPS  = 0x6E,
-	RATE_12MBPS  = 0x0A,
-	RATE_18MBPS  = 0x0E,
-	RATE_22MBPS  = 0xDC,
-	RATE_24MBPS  = 0x09,
-	RATE_36MBPS  = 0x0D,
-	RATE_48MBPS  = 0x08,
-	RATE_54MBPS  = 0x0C
-};
-
-enum {
-	RATE_INDEX_1MBPS   =  0,
-	RATE_INDEX_2MBPS   =  1,
-	RATE_INDEX_5_5MBPS =  2,
-	RATE_INDEX_6MBPS   =  3,
-	RATE_INDEX_9MBPS   =  4,
-	RATE_INDEX_11MBPS  =  5,
-	RATE_INDEX_12MBPS  =  6,
-	RATE_INDEX_18MBPS  =  7,
-	RATE_INDEX_22MBPS  =  8,
-	RATE_INDEX_24MBPS  =  9,
-	RATE_INDEX_36MBPS  =  10,
-	RATE_INDEX_48MBPS  =  11,
-	RATE_INDEX_54MBPS  =  12,
-	RATE_INDEX_MAX     =  RATE_INDEX_54MBPS,
-	MAX_RATE_INDEX,
-	INVALID_RATE_INDEX = MAX_RATE_INDEX,
-	RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF
-};
-
-enum {
-	RATE_MASK_1MBPS = 0x1,
-	RATE_MASK_2MBPS = 0x2,
-	RATE_MASK_5_5MBPS = 0x4,
-	RATE_MASK_11MBPS = 0x20,
-};
-
 #define SHORT_PREAMBLE_BIT   BIT(0) /* CCK or Barker depending on the rate */
 #define OFDM_RATE_BIT        BIT(6)
 #define PBCC_RATE_BIT        BIT(7)
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 08/22] wl1271: Fix IRQ enable handling on FW init failure
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Disable IRQ's after FW initialization failure - originally this was not
done in all cases, and it resulted in a kernel warning if firmware
initialization was tried again without reboot.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |    6 ++--
 drivers/net/wireless/wl12xx/wl1271_init.c |    4 +-
 drivers/net/wireless/wl12xx/wl1271_main.c |   42 ++++++++++++++++++++--------
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index a27601d..b8a37a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -400,9 +400,6 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 	 * ready to receive event from the command mailbox
 	 */
 
-	/* enable gpio interrupts */
-	wl1271_boot_enable_interrupts(wl);
-
 	/* unmask required mbox events  */
 	wl->event_mask = BSS_LOSE_EVENT_ID |
 		SCAN_COMPLETE_EVENT_ID;
@@ -540,6 +537,9 @@ int wl1271_boot(struct wl1271 *wl)
 	if (ret < 0)
 		goto out;
 
+	/* Enable firmware interrupts now */
+	wl1271_boot_enable_interrupts(wl);
+
 	/* set the wl1271 default filters */
 	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
 	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 5c2cf1e..6f21eea 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -315,8 +315,8 @@ int wl1271_hw_init(struct wl1271 *wl)
 
 	/* RX config */
 	ret = wl1271_init_rx_config(wl,
-				       RX_CFG_PROMISCUOUS | RX_CFG_TSF,
-				       RX_FILTER_OPTION_DEF);
+				    RX_CFG_PROMISCUOUS | RX_CFG_TSF,
+				    RX_FILTER_OPTION_DEF);
 	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
 	   RX_FILTER_OPTION_FILTER_ALL); */
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index eba38df..7f1093c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -625,7 +625,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 
 		ret = wl1271_setup(wl);
 		if (ret < 0)
-			goto out;
+			goto out_power_off;
 		break;
 	case CHIP_ID_1271_PG20:
 		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
@@ -633,27 +633,32 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 
 		ret = wl1271_setup(wl);
 		if (ret < 0)
-			goto out;
+			goto out_power_off;
 		break;
 	default:
 		wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
 		ret = -ENODEV;
-		goto out;
+		goto out_power_off;
 	}
 
 	if (wl->fw == NULL) {
 		ret = wl1271_fetch_firmware(wl);
 		if (ret < 0)
-			goto out;
+			goto out_power_off;
 	}
 
 	/* No NVS from netlink, try to get it from the filesystem */
 	if (wl->nvs == NULL) {
 		ret = wl1271_fetch_nvs(wl);
 		if (ret < 0)
-			goto out;
+			goto out_power_off;
 	}
 
+	goto out;
+
+out_power_off:
+	wl1271_power_off(wl);
+
 out:
 	return ret;
 }
@@ -749,13 +754,21 @@ int wl1271_plt_start(struct wl1271 *wl)
 
 	ret = wl1271_boot(wl);
 	if (ret < 0)
-		goto out;
+		goto out_power_off;
 
 	wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
 
 	ret = wl1271_plt_init(wl);
 	if (ret < 0)
-		goto out;
+		goto out_irq_disable;
+
+	goto out;
+
+out_irq_disable:
+	wl1271_disable_interrupts(wl);
+
+out_power_off:
+	wl1271_power_off(wl);
 
 out:
 	mutex_unlock(&wl->mutex);
@@ -843,20 +856,25 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
 
 	ret = wl1271_boot(wl);
 	if (ret < 0)
-		goto out;
+		goto out_power_off;
 
 	ret = wl1271_hw_init(wl);
 	if (ret < 0)
-		goto out;
+		goto out_irq_disable;
 
 	wl->state = WL1271_STATE_ON;
 
 	wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
 
-out:
-	if (ret < 0)
-		wl1271_power_off(wl);
+	goto out;
+
+out_irq_disable:
+	wl1271_disable_interrupts(wl);
 
+out_power_off:
+	wl1271_power_off(wl);
+
+out:
 	mutex_unlock(&wl->mutex);
 
 	return ret;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 09/22] wl1271: Implement beacon early termination support
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add support to enable beacon early termination in the firmware. Early
Beacon termination is a feature which allows the radio to be turned off
after TIM IE to save power.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   30 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_acx.h  |   12 ++++++++++-
 drivers/net/wireless/wl12xx/wl1271_conf.h |   23 ++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_main.c |    4 ++-
 drivers/net/wireless/wl12xx/wl1271_ps.c   |   10 +++++++++
 5 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 880c828..44a1237 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -1062,3 +1062,33 @@ out:
 	return ret;
 
 }
+
+int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
+{
+	struct wl1271_acx_bet_enable *acx = NULL;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_ACX, "acx bet enable");
+
+	if (enable && wl->conf.conn.bet_enable == CONF_BET_MODE_DISABLE)
+		goto out;
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
+	acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
+
+	ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx bet enable failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 73ef2bd..29fd363 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -946,6 +946,15 @@ struct wl1271_acx_rx_config_opt {
 	u8 reserved;
 } __attribute__ ((packed));
 
+
+struct wl1271_acx_bet_enable {
+	struct acx_header header;
+
+	u8 enable;
+	u8 max_consecutive;
+	u8 padding[2];
+} __attribute__ ((packed));
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
@@ -1043,7 +1052,7 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
 int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask);
 int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
 int wl1271_acx_cts_protect(struct wl1271 *wl,
-			    enum acx_ctsprotect_type ctsprotect);
+			   enum acx_ctsprotect_type ctsprotect);
 int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
 int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates);
 int wl1271_acx_ac_cfg(struct wl1271 *wl);
@@ -1054,5 +1063,6 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
+int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 5333a27..00ffa66 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -603,6 +603,11 @@ enum conf_bcn_filt_mode {
 	CONF_BCN_FILT_MODE_ENABLED = 1
 };
 
+enum conf_bet_mode {
+	CONF_BET_MODE_DISABLE = 0,
+	CONF_BET_MODE_ENABLE = 1,
+};
+
 struct conf_conn_settings {
 	/*
 	 * Firmware wakeup conditions configuration. The host may set only
@@ -689,6 +694,24 @@ struct conf_conn_settings {
 	 * Configuration of signal average weights.
 	 */
 	struct conf_sig_weights sig_weights;
+
+	/*
+	 * Specifies if beacon early termination procedure is enabled or
+	 * disabled.
+	 *
+	 * Range: CONF_BET_MODE_*
+	 */
+	u8 bet_enable;
+
+	/*
+	 * Specifies the maximum number of consecutive beacons that may be
+	 * early terminated. After this number is reached at least one full
+	 * beacon must be correctly received in FW before beacon ET
+	 * resumes.
+	 *
+	 * Range 0 - 255
+	 */
+	u8 bet_max_consecutive;
 };
 
 #define CONF_SR_ERR_TBL_MAX_VALUES   14
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 7f1093c..3d2e999 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -219,7 +219,9 @@ static struct conf_drv_settings default_conf = {
 			.rssi_pkt_avg_weight = 10,
 			.snr_bcn_avg_weight  = 10,
 			.snr_pkt_avg_weight  = 10
-		}
+		},
+		.bet_enable                  = CONF_BET_MODE_ENABLE,
+		.bet_max_consecutive         = 100
 	},
 	.init = {
 		.sr_err_tbl = {
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index bb8745d..507cd91 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -130,6 +130,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
+		/* enable beacon early termination */
+		ret = wl1271_acx_bet_enable(wl, true);
+		if (ret < 0)
+			return ret;
+
 		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
@@ -147,6 +152,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
+		/* disable beacon early termination */
+		ret = wl1271_acx_bet_enable(wl, false);
+		if (ret < 0)
+			return ret;
+
 		/* disable beacon filtering */
 		ret = wl1271_acx_beacon_filter_opt(wl, false);
 		if (ret < 0)
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 13/22] wl1271: Added support to scan on 5 GHz band
From: Luciano Coelho @ 2009-10-13  9:47 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Teemu Paasikivi
In-Reply-To: <1255427279-1224-1-git-send-email-luciano.coelho@nokia.com>

From: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>

Added support to scan 802.11a access points on 5 GHz band when using
wl1273 chip.

Signed-off-by: Teemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h       |   10 +++
 drivers/net/wireless/wl12xx/wl1271_cmd.c   |  121 ++++++++++++++++++++++------
 drivers/net/wireless/wl12xx/wl1271_cmd.h   |    8 ++-
 drivers/net/wireless/wl12xx/wl1271_event.c |   37 +++++++--
 drivers/net/wireless/wl12xx/wl1271_init.c  |    8 ++
 drivers/net/wireless/wl12xx/wl1271_main.c  |   11 ++-
 drivers/net/wireless/wl12xx/wl1271_rx.c    |    3 +
 7 files changed, 160 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index dc9957e..79a7324 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -299,6 +299,15 @@ struct wl1271_rx_mem_pool_addr {
 	u32 addr_extra;
 };
 
+struct wl1271_scan {
+	u8 state;
+	u8 ssid[IW_ESSID_MAX_SIZE+1];
+	size_t ssid_len;
+	u8 active;
+	u8 high_prio;
+	u8 probe_requests;
+};
+
 struct wl1271 {
 	struct ieee80211_hw *hw;
 	bool mac80211_registered;
@@ -382,6 +391,7 @@ struct wl1271 {
 
 	/* Are we currently scanning */
 	bool scanning;
+	struct wl1271_scan scan;
 
 	/* Our association ID */
 	u16 aid;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 204e872..6d7a40c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -509,7 +509,7 @@ out:
 }
 
 int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
-		    u8 active_scan, u8 high_prio, u8 num_channels,
+		    u8 active_scan, u8 high_prio, u8 band,
 		    u8 probe_requests)
 {
 
@@ -518,12 +518,25 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 	struct ieee80211_channel *channels;
 	int i, j, n_ch, ret;
 	u16 scan_options = 0;
+	u8 ieee_band;
+
+	if (band == WL1271_SCAN_BAND_2_4_GHZ)
+		ieee_band = IEEE80211_BAND_2GHZ;
+	else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled())
+		ieee_band = IEEE80211_BAND_2GHZ;
+	else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled())
+		ieee_band = IEEE80211_BAND_5GHZ;
+	else
+		return -EINVAL;
 
-	if (wl->scanning)
+	if (wl->hw->wiphy->bands[ieee_band]->channels == NULL)
 		return -EINVAL;
 
-	channels = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels;
-	n_ch = wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels;
+	channels = wl->hw->wiphy->bands[ieee_band]->channels;
+	n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels;
+
+	if (wl->scanning)
+		return -EINVAL;
 
 	params = kzalloc(sizeof(*params), GFP_KERNEL);
 	if (!params)
@@ -540,10 +553,16 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 	params->params.scan_options = scan_options;
 
 	params->params.num_probe_requests = probe_requests;
-	params->params.tx_rate = cpu_to_le32(CONF_HW_BIT_RATE_2MBPS);
+	/* Let the fw autodetect suitable tx_rate for probes */
+	params->params.tx_rate = 0;
 	params->params.tid_trigger = 0;
 	params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
 
+	if (band == WL1271_SCAN_BAND_DUAL)
+		params->params.band = WL1271_SCAN_BAND_2_4_GHZ;
+	else
+		params->params.band = band;
+
 	for (i = 0, j = 0; i < n_ch && i < WL1271_SCAN_MAX_CHANNELS; i++) {
 		if (!(channels[i].flags & IEEE80211_CHAN_DISABLED)) {
 			params->channels[j].min_duration =
@@ -567,7 +586,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 		memcpy(params->params.ssid, ssid, len);
 	}
 
-	ret = wl1271_cmd_build_probe_req(wl, ssid, len);
+	ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band);
 	if (ret < 0) {
 		wl1271_error("PROBE request template failed");
 		goto out;
@@ -592,6 +611,19 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
 	wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
 
 	wl->scanning = true;
+	if (wl1271_11a_enabled()) {
+		wl->scan.state = band;
+		if (band == WL1271_SCAN_BAND_DUAL) {
+			wl->scan.active = active_scan;
+			wl->scan.high_prio = high_prio;
+			wl->scan.probe_requests = probe_requests;
+			if (len && ssid) {
+				wl->scan.ssid_len = len;
+				memcpy(wl->scan.ssid, ssid, len);
+			} else
+				wl->scan.ssid_len = 0;
+		}
+	}
 
 	ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
 	if (ret < 0) {
@@ -654,30 +686,62 @@ out:
 	return ret;
 }
 
-static int wl1271_build_basic_rates(char *rates)
+static int wl1271_build_basic_rates(char *rates, u8 band)
 {
 	u8 index = 0;
 
-	rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
-	rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
-	rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
-	rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
+	if (band == IEEE80211_BAND_2GHZ) {
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
+	} else if (band == IEEE80211_BAND_5GHZ) {
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
+	} else {
+		wl1271_error("build_basic_rates invalid band: %d", band);
+	}
 
 	return index;
 }
 
-static int wl1271_build_extended_rates(char *rates)
+static int wl1271_build_extended_rates(char *rates, u8 band)
 {
 	u8 index = 0;
 
-	rates[index++] = IEEE80211_OFDM_RATE_6MB;
-	rates[index++] = IEEE80211_OFDM_RATE_9MB;
-	rates[index++] = IEEE80211_OFDM_RATE_12MB;
-	rates[index++] = IEEE80211_OFDM_RATE_18MB;
-	rates[index++] = IEEE80211_OFDM_RATE_24MB;
-	rates[index++] = IEEE80211_OFDM_RATE_36MB;
-	rates[index++] = IEEE80211_OFDM_RATE_48MB;
-	rates[index++] = IEEE80211_OFDM_RATE_54MB;
+	if (band == IEEE80211_BAND_2GHZ) {
+		rates[index++] = IEEE80211_OFDM_RATE_6MB;
+		rates[index++] = IEEE80211_OFDM_RATE_9MB;
+		rates[index++] = IEEE80211_OFDM_RATE_12MB;
+		rates[index++] = IEEE80211_OFDM_RATE_18MB;
+		rates[index++] = IEEE80211_OFDM_RATE_24MB;
+		rates[index++] = IEEE80211_OFDM_RATE_36MB;
+		rates[index++] = IEEE80211_OFDM_RATE_48MB;
+		rates[index++] = IEEE80211_OFDM_RATE_54MB;
+	} else if (band == IEEE80211_BAND_5GHZ) {
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
+		rates[index++] =
+			IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
+	} else {
+		wl1271_error("build_basic_rates invalid band: %d", band);
+	}
 
 	return index;
 }
@@ -720,12 +784,14 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
 
 }
 
-int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len)
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len,
+			       u8 band)
 {
 	struct wl12xx_probe_req_template template;
 	struct wl12xx_ie_rates *rates;
 	char *ptr;
 	u16 size;
+	int ret;
 
 	ptr = (char *)&template;
 	size = sizeof(struct ieee80211_header);
@@ -747,20 +813,25 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len)
 	/* Basic Rates */
 	rates = (struct wl12xx_ie_rates *)ptr;
 	rates->header.id = WLAN_EID_SUPP_RATES;
-	rates->header.len = wl1271_build_basic_rates(rates->rates);
+	rates->header.len = wl1271_build_basic_rates(rates->rates, band);
 	size += sizeof(struct wl12xx_ie_header) + rates->header.len;
 	ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
 
 	/* Extended rates */
 	rates = (struct wl12xx_ie_rates *)ptr;
 	rates->header.id = WLAN_EID_EXT_SUPP_RATES;
-	rates->header.len = wl1271_build_extended_rates(rates->rates);
+	rates->header.len = wl1271_build_extended_rates(rates->rates, band);
 	size += sizeof(struct wl12xx_ie_header) + rates->header.len;
 
 	wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
 
-	return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
-				       &template, size);
+	if (band == IEEE80211_BAND_2GHZ)
+		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
+					      &template, size);
+	else
+		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
+					      &template, size);
+	return ret;
 }
 
 int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 9143087..3308940 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -39,13 +39,14 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
 			   size_t len);
 int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
-		    u8 active_scan, u8 high_prio, u8 num_channels,
+		    u8 active_scan, u8 high_prio, u8 band,
 		    u8 probe_requests);
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
 			    void *buf, size_t buf_len);
 int wl1271_cmd_build_null_data(struct wl1271 *wl);
 int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
-int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
+int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len,
+			       u8 band);
 int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
 int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
@@ -343,6 +344,9 @@ struct wl1271_cmd_set_keys {
 #define WL1271_SCAN_OPT_PRIORITY_HIGH  4
 #define WL1271_SCAN_CHAN_MIN_DURATION  30000  /* TU */
 #define WL1271_SCAN_CHAN_MAX_DURATION  60000  /* TU */
+#define WL1271_SCAN_BAND_2_4_GHZ 0
+#define WL1271_SCAN_BAND_5_GHZ 1
+#define WL1271_SCAN_BAND_DUAL 2
 
 struct basic_scan_params {
 	u32 rx_config_options;
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 4189e97..e2d7758 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -31,19 +31,40 @@
 static int wl1271_event_scan_complete(struct wl1271 *wl,
 				      struct event_mailbox *mbox)
 {
+	int size = sizeof(struct wl12xx_probe_req_template);
 	wl1271_debug(DEBUG_EVENT, "status: 0x%x",
 		     mbox->scheduled_scan_status);
 
 	if (wl->scanning) {
-		int size = sizeof(struct wl12xx_probe_req_template);
-		wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
-					size);
-		mutex_unlock(&wl->mutex);
-		ieee80211_scan_completed(wl->hw, false);
-		mutex_lock(&wl->mutex);
-		wl->scanning = false;
+		if (wl->scan.state == WL1271_SCAN_BAND_DUAL) {
+			wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
+						NULL, size);
+			/* 2.4 GHz band scanned, scan 5 GHz band, pretend
+			 * to the wl1271_cmd_scan function that we are not
+			 * scanning as it checks that.
+			 */
+			wl->scanning = false;
+			wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
+						wl->scan.active,
+						wl->scan.high_prio,
+						WL1271_SCAN_BAND_5_GHZ,
+						wl->scan.probe_requests);
+		} else {
+			if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ)
+				wl1271_cmd_template_set(wl,
+						CMD_TEMPL_CFG_PROBE_REQ_2_4,
+						NULL, size);
+			else
+				wl1271_cmd_template_set(wl,
+						CMD_TEMPL_CFG_PROBE_REQ_5,
+						NULL, size);
+
+			mutex_unlock(&wl->mutex);
+			ieee80211_scan_completed(wl->hw, false);
+			mutex_lock(&wl->mutex);
+			wl->scanning = false;
+		}
 	}
-
 	return 0;
 }
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 6f21eea..417b415 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -59,6 +59,14 @@ static int wl1271_init_templates_config(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	if (wl1271_11a_enabled()) {
+		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
+				NULL,
+				sizeof(struct wl12xx_probe_req_template));
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
 				      sizeof(struct wl12xx_null_data_template));
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 9b1cc8d..ae41a70 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1332,13 +1332,13 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
 	struct wl1271 *wl = hw->priv;
 	int ret;
 	u8 *ssid = NULL;
-	size_t ssid_len = 0;
+	size_t len = 0;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
 
 	if (req->n_ssids) {
 		ssid = req->ssids[0].ssid;
-		ssid_len = req->ssids[0].ssid_len;
+		len = req->ssids[0].ssid_len;
 	}
 
 	mutex_lock(&wl->mutex);
@@ -1347,7 +1347,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
 	if (ret < 0)
 		goto out;
 
-	ret = wl1271_cmd_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
+	if (wl1271_11a_enabled())
+		ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
+				      WL1271_SCAN_BAND_DUAL, 3);
+	else
+		ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
+				      WL1271_SCAN_BAND_2_4_GHZ, 3);
 
 	wl1271_ps_elp_sleep(wl);
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 7979b69..66b83e9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -79,6 +79,9 @@ static void wl1271_rx_status(struct wl1271 *wl,
 
 	if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
 		status->band = IEEE80211_BAND_2GHZ;
+	else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) ==
+		 WL1271_RX_DESC_BAND_A)
+		status->band = IEEE80211_BAND_5GHZ;
 	else
 		wl1271_warning("unsupported band 0x%x",
 			       desc->flags & WL1271_RX_DESC_BAND_MASK);
-- 
1.5.6.5


^ 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