[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#533357: linux-2.6: please add "b43: Add fw capabilities", to support OpenFWWF 5.1



Package: linux-2.6
Version: 2.6.30-1
Severity: wishlist
Tags: patch

Hi

I am currently packaging [1], [2] the OpenFWWF (GPL2) [3] firmware for 
"core revision 5" Broadcom AirForce wlan chipsets [4], while the most 
important patches to support OpenFWWF have already been merged for 2.6.30,
"b43: Add fw capabilities" 403a3a136122457165321e90b7569a321cc9ac12
has only been merged mainline yesterday [5].

I would really appreciate if you could consider adding that patch to the 
next 2.6.30 kernel upload for Debian (I am using it successfully since 
kernel 2.6.29), as it would make packaging openfwwf significantly easier 
and avoid ugly upgrade handling. 

To explain the reasoning for my request (an overview is presented at [6]),
as of now OpenFWWF doesn't support hardware encryption and QoS yet, which 
are available in the proprietary Broadcom firmware (b43-fwcutter/ 
non-free), while b43 (until 2.6.30-git9) enables both on default, making
b43 to failing to authentificate and resulting numerous PHY resets 
and firmware crashes/ restarts (potential log spam). While it is possible
to force b43 into disabling both features through a modprobe.d override
[7], this would only be required until kernel 2.6.31 enters the archive and
present some problems with the upgrade handling (introducing 
/etc/modprobe.d/openfwwf.conf as a Debian conffile for ~3 months and 
subsequently removing it) and additionally hard-disables QoS even in case
OpenFWWF and the proprietary firmware (b43-fwcutter/ non-free) are 
coinstalled (since kernel 2.6.30, b43 first probes ${FIRMWARE_DIRS}/b43/, 
before falling back to ${FIRMWARE_DIRS}/b43-open/, provided by OpenFWWF).
Assuming this patch would be merged into 2.6.30-2, this would not affect 
compatibility with previous kernels, because ${FIRMWARE_DIRS}/b43-open/ 
is ignored until kernel 2.6.30 and therefore isn't eligible to the 
described problems (only 2.6.30-1 would be).

openfwwf and b43-asm (its build-dependency), as a dfsg-free firmware for, 
many devices covered by b43 are basically ready and only pending your 
decision, as this patch has already been merged upstream for 2.6.31, it
only applies to kernel 2.6.30. Backports to lenny's 2.6.26 are not 
reasonable (as it would require installing openfwwf under
${FIRMWARE_DIRS}/b43/ in conflict with b43-fwcutter/ non-free and the 
modprobe overrides at [7]), while it would be compatible lenny-and-a-half,
assuming "b43: Add fw capabilities" is present.

Regarding DebianKernelPatchAcceptanceGuidelines:
- Security Fixes:			FAIL
- Driver Fixes:			depending on the interpretation, it was meant to go into 
						2.6.30, but fell through the cracks and basically makes a new feature
						of 2.6.30 (transparent OpenFWWF compatibility) work for the first 
						time and would allow to operate these devices solely with packages 
						from main, once openfwwf enters the archive.
- Stability Fixes:			FAIL

- New features:			YES, strictly speaking
- Out-of Tree Drivers:		NO
- My favourite patch-set:	NO, single patch already merged upstream

I am aware that this patch is borderline following these patch acceptance 
guidelines, but hope that you might consider it nevertheless.

A short word regarding the current state of OpenFWWF, for "core revision 5"
devices [4], it is mostly stable, but as a reverse engineering efforts 
there may be still unknown corner cases and behaviour under (articifically)
high package pressure is said to be still slightly erratic (I haven't been 
able to observe such issues myself) and a decent replacement for the 
proprietary firmware. "core revision 6-10" devices are likely to work, but
might expose several problems in practice and are not claimed to be 
supported upstream yet. "core revision >=11" devices do not work yet. I am
personally using this patch successfully since early 2.6.29 kernels on 
BCM4306 (rev 5 core) in STA and AP modi, BCM4318 (rev 9 core) works, but 
not perfectly and I have positive feedback from BCM4311/1 (rev 5 core) and 
BCM4318 (rev 5 core) users. 

Potential real world compatibility scenarios:
- for users who have the proprietary firmware installed already, this patch
  is basically a no-op, because ${FIRMWARE_DIRS}/b43/ is always preferred 
  by b43.
- users with kernel <= 2.6.29 and only openfwwf installed won't experience
  any change, their b43 module ignores ${FIRMWARE_DIRS}/b43-open/ 
  (openfwwf) - recent compat-wireless snapshots contain this patch already.
- users with vanilla 2.6.30 or linux-2.6 2.6.30-1 and _only_ openfwwf 
  installed, are not able to get a connection with b43 and openfwwf and do 
  experience numerous PHY resets and firmware restarts (triggered by the 
  netdev watchdog), manifesting itself in syslog/ kern.log (not rate 
  limited).
  --> manual modprobe overrides required, regressing performance with the 
  proprietary firmware and introducing potential upgrade hassles.
- starting with 2.6.31 (or depending on your decision linux-2.6 2.6.30-2), 
  openfwwf would make many b43 based wlan devices work with only dfsg-free 
  components required - the proprietary firmware can be transparently 
  coinstalled and supersedes openfwwf, if present.

Regards
	Stefan Lippers-Hollmann

[1]	BUG #513974: ITP: openfwwf -- Open Firmware for Broadcom b43 wlan devices
	Vcs-Svn: svn://svn.berlios.de/fullstory/openfwwf/trunk
	Vcs-Browser: http://svn.berlios.de/svnroot/repos/fullstory/openfwwf/trunk/
[2]	BUG #513973: ITP: b43-asm -- assembler and disassembler for Broadcom BCM43xx firmware
	Vcs-Svn: svn://svn.berlios.de/fullstory/b43-asm/trunk
	Vcs-Browser: http://svn.berlios.de/svnroot/repos/fullstory/b43-asm/trunk/
[3]	http://www.ing.unibs.it/openfwwf/
[4]	Broadcom wlan chipsets currently supported by OpenFWWF 5.1:
	- BCM4306
	- BCM4311 revision 1
	- BCM4318
	- BCM4320
[5]	http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=403a3a136122457165321e90b7569a321cc9ac12
[6]	http://svn.berlios.de/svnroot/repos/fullstory/openfwwf/trunk/debian/README.Debian
[7]	options b43 nohwcrypt=1 qos=0

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.30-0.slh.2-sidux-amd64 (SMP w/4 CPU cores; PREEMPT)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
From 403a3a136122457165321e90b7569a321cc9ac12 Mon Sep 17 00:00:00 2001
From: Michael Buesch <mb@bu3sch.de>
Date: Mon, 8 Jun 2009 21:04:57 +0200
Subject: [PATCH 16394/17325] b43: Add fw capabilities

Add automagic feature flags, so the firmware can tell the driver
about supported features and the driver can switch features on/off as
needed.

Signed-off-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 drivers/net/wireless/b43/b43.h  |   14 +++++++++
 drivers/net/wireless/b43/dma.c  |    2 +-
 drivers/net/wireless/b43/main.c |   56 +++++++++++++++++++++++++++++++-------
 drivers/net/wireless/b43/main.h |    1 -
 drivers/net/wireless/b43/pio.c  |    2 +-
 5 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 75aede0..f580c28 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -163,6 +163,7 @@ enum {
 #define B43_SHM_SH_WLCOREREV		0x0016	/* 802.11 core revision */
 #define B43_SHM_SH_PCTLWDPOS		0x0008
 #define B43_SHM_SH_RXPADOFF		0x0034	/* RX Padding data offset (PIO only) */
+#define B43_SHM_SH_FWCAPA		0x0042	/* Firmware capabilities (Opensource firmware only) */
 #define B43_SHM_SH_PHYVER		0x0050	/* PHY version */
 #define B43_SHM_SH_PHYTYPE		0x0052	/* PHY type */
 #define B43_SHM_SH_ANTSWAP		0x005C	/* Antenna swap threshold */
@@ -297,6 +298,10 @@ enum {
 #define B43_HF_MLADVW		0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */
 #define B43_HF_PR45960W		0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */
 
+/* Firmware capabilities field in SHM (Opensource firmware only) */
+#define B43_FWCAPA_HWCRYPTO	0x0001
+#define B43_FWCAPA_QOS		0x0002
+
 /* MacFilter offsets. */
 #define B43_MACFILTER_SELF		0x0000
 #define B43_MACFILTER_BSSID		0x0003
@@ -596,6 +601,13 @@ struct b43_wl {
 	/* Pointer to the ieee80211 hardware data structure */
 	struct ieee80211_hw *hw;
 
+	/* The number of queues that were registered with the mac80211 subsystem
+	 * initially. This is a backup copy of hw->queues in case hw->queues has
+	 * to be dynamically lowered at runtime (Firmware does not support QoS).
+	 * hw->queues has to be restored to the original value before unregistering
+	 * from the mac80211 subsystem. */
+	u16 mac80211_initially_registered_queues;
+
 	struct mutex mutex;
 	spinlock_t irq_lock;
 	/* R/W lock for data transmission.
@@ -749,6 +761,8 @@ struct b43_wldev {
 	bool dfq_valid;		/* Directed frame queue valid (IBSS PS mode, ATIM) */
 	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
 	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
+	bool qos_enabled;		/* TRUE, if QoS is used. */
+	bool hwcrypto_enabled;		/* TRUE, if HW crypto acceleration is enabled. */
 
 	/* PHY/Radio device. */
 	struct b43_phy phy;
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index eae680b..7964cc3 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1285,7 +1285,7 @@ static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev,
 {
 	struct b43_dmaring *ring;
 
-	if (b43_modparam_qos) {
+	if (dev->qos_enabled) {
 		/* 0 = highest priority */
 		switch (queue_prio) {
 		default:
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5d9f198..6456afe 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -80,8 +80,8 @@ static int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
-int b43_modparam_qos = 1;
-module_param_named(qos, b43_modparam_qos, int, 0444);
+static int modparam_qos = 1;
+module_param_named(qos, modparam_qos, int, 0444);
 MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
 
 static int modparam_btcoex = 1;
@@ -538,6 +538,13 @@ void b43_hf_write(struct b43_wldev *dev, u64 value)
 	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi);
 }
 
+/* Read the firmware capabilities bitmask (Opensource firmware only) */
+static u16 b43_fwcapa_read(struct b43_wldev *dev)
+{
+	B43_WARN_ON(!dev->fw.opensource);
+	return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA);
+}
+
 void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)
 {
 	u32 low, high;
@@ -2307,12 +2314,34 @@ static int b43_upload_microcode(struct b43_wldev *dev)
 	dev->fw.patch = fwpatch;
 	dev->fw.opensource = (fwdate == 0xFFFF);
 
+	/* Default to use-all-queues. */
+	dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
+	dev->qos_enabled = !!modparam_qos;
+	/* Default to firmware/hardware crypto acceleration. */
+	dev->hwcrypto_enabled = 1;
+
 	if (dev->fw.opensource) {
+		u16 fwcapa;
+
 		/* Patchlevel info is encoded in the "time" field. */
 		dev->fw.patch = fwtime;
-		b43info(dev->wl, "Loading OpenSource firmware version %u.%u%s\n",
-			dev->fw.rev, dev->fw.patch,
-			dev->fw.pcm_request_failed ? " (Hardware crypto not supported)" : "");
+		b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n",
+			dev->fw.rev, dev->fw.patch);
+
+		fwcapa = b43_fwcapa_read(dev);
+		if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) {
+			b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n");
+			/* Disable hardware crypto and fall back to software crypto. */
+			dev->hwcrypto_enabled = 0;
+		}
+		if (!(fwcapa & B43_FWCAPA_QOS)) {
+			b43info(dev->wl, "QoS not supported by firmware\n");
+			/* Disable QoS. Tweak hw->queues to 1. It will be restored before
+			 * ieee80211_unregister to make sure the networking core can
+			 * properly free possible resources. */
+			dev->wl->hw->queues = 1;
+			dev->qos_enabled = 0;
+		}
 	} else {
 		b43info(dev->wl, "Loading firmware version %u.%u "
 			"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
@@ -3627,7 +3656,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
 		goto out_unlock;
 
-	if (dev->fw.pcm_request_failed) {
+	if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) {
 		/* We don't have firmware for the crypto engine.
 		 * Must use software-crypto. */
 		err = -EOPNOTSUPP;
@@ -4727,6 +4756,7 @@ static int b43_wireless_init(struct ssb_device *dev)
 		b43err(NULL, "Could not allocate ieee80211 device\n");
 		goto out;
 	}
+	wl = hw_to_b43_wl(hw);
 
 	/* fill hw info */
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
@@ -4740,7 +4770,8 @@ static int b43_wireless_init(struct ssb_device *dev)
 		BIT(NL80211_IFTYPE_WDS) |
 		BIT(NL80211_IFTYPE_ADHOC);
 
-	hw->queues = b43_modparam_qos ? 4 : 1;
+	hw->queues = modparam_qos ? 4 : 1;
+	wl->mac80211_initially_registered_queues = hw->queues;
 	hw->max_rates = 2;
 	SET_IEEE80211_DEV(hw, dev->dev);
 	if (is_valid_ether_addr(sprom->et1mac))
@@ -4748,9 +4779,7 @@ static int b43_wireless_init(struct ssb_device *dev)
 	else
 		SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
 
-	/* Get and initialize struct b43_wl */
-	wl = hw_to_b43_wl(hw);
-	memset(wl, 0, sizeof(*wl));
+	/* Initialize struct b43_wl */
 	wl->hw = hw;
 	spin_lock_init(&wl->irq_lock);
 	rwlock_init(&wl->tx_lock);
@@ -4816,8 +4845,13 @@ static void b43_remove(struct ssb_device *dev)
 	cancel_work_sync(&wldev->restart_work);
 
 	B43_WARN_ON(!wl);
-	if (wl->current_dev == wldev)
+	if (wl->current_dev == wldev) {
+		/* Restore the queues count before unregistering, because firmware detect
+		 * might have modified it. Restoring is important, so the networking
+		 * stack can properly free resources. */
+		wl->hw->queues = wl->mac80211_initially_registered_queues;
 		ieee80211_unregister_hw(wl->hw);
+	}
 
 	b43_one_core_detach(dev);
 
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 40abcf5..950fb1b 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -39,7 +39,6 @@
 #define PAD_BYTES(nr_bytes)		P4D_BYTES( __LINE__ , (nr_bytes))
 
 
-extern int b43_modparam_qos;
 extern int b43_modparam_verbose;
 
 /* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 8cd9776..69138e8 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -313,7 +313,7 @@ static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev,
 {
 	struct b43_pio_txqueue *q;
 
-	if (b43_modparam_qos) {
+	if (dev->qos_enabled) {
 		/* 0 = highest priority */
 		switch (queue_prio) {
 		default:
-- 
1.6.3.1

Attachment: signature.asc
Description: This is a digitally signed message part.


Reply to: