linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] b43: Fix MAC control and microcode init
@ 2008-01-22 19:23 Michael Buesch
  2008-01-24  9:13 ` Johannes Berg
  0 siblings, 1 reply; 3+ messages in thread
From: Michael Buesch @ 2008-01-22 19:23 UTC (permalink / raw)
  To: John Linville; +Cc: bcm43xx-dev, linux-wireless, Stefano Brivio

This zeros out all microcode related memory before loading
the microcode.

This also fixes initialization of the MAC control register.
The _only_ place where we overwrite the contents of the MAC control
register is at the beginning of b43_chip_init().
All other places must do read() -> mask/set -> write() to not
overwrite existing bits.

This also adds a longer delay for waiting for the microcode
to initialize itself. It seems that the current timeout is sufficient
on all available devices, but there's no real reason why we shouldn't
wait for up to one second. Slow embedded devices might exist.
Better safe than sorry.

Signed-off-by: Michael Buesch <mb@bu3sch.de>

---

John, this bugfix should go into 2.6.24.
Stefano, this must be ported to b43legacy.



Index: wireless-2.6/drivers/net/wireless/b43/main.c
===================================================================
--- wireless-2.6.orig/drivers/net/wireless/b43/main.c	2008-01-22 19:23:50.000000000 +0100
+++ wireless-2.6/drivers/net/wireless/b43/main.c	2008-01-22 20:00:00.000000000 +0100
@@ -1775,15 +1775,26 @@ error:
 static int b43_upload_microcode(struct b43_wldev *dev)
 {
 	const size_t hdr_len = sizeof(struct b43_fw_header);
 	const __be32 *data;
 	unsigned int i, len;
 	u16 fwrev, fwpatch, fwdate, fwtime;
-	u32 tmp;
+	u32 tmp, macctl;
 	int err = 0;
 
+	/* Jump the microcode PSM to offset 0 */
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	B43_WARN_ON(macctl & B43_MACCTL_PSM_RUN);
+	macctl |= B43_MACCTL_PSM_JMP0;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+	/* Zero out all microcode PSM registers and shared memory. */
+	for (i = 0; i < 64; i++)
+		b43_shm_write16(dev, B43_SHM_SCRATCH, i, 0);
+	for (i = 0; i < 4096; i += 2)
+		b43_shm_write16(dev, B43_SHM_SHARED, i, 0);
+
 	/* Upload Microcode. */
 	data = (__be32 *) (dev->fw.ucode.data->data + hdr_len);
 	len = (dev->fw.ucode.data->size - hdr_len) / sizeof(__be32);
 	b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);
 	for (i = 0; i < len; i++) {
 		b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
@@ -1802,30 +1813,37 @@ static int b43_upload_microcode(struct b
 			b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
 			udelay(10);
 		}
 	}
 
 	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
-	b43_write32(dev, B43_MMIO_MACCTL,
-		    B43_MACCTL_PSM_RUN |
-		    B43_MACCTL_IHR_ENABLED | B43_MACCTL_INFRA);
+
+	/* Start the microcode PSM */
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl &= ~B43_MACCTL_PSM_JMP0;
+	macctl |= B43_MACCTL_PSM_RUN;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 
 	/* Wait for the microcode to load and respond */
 	i = 0;
 	while (1) {
 		tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
 		if (tmp == B43_IRQ_MAC_SUSPENDED)
 			break;
 		i++;
-		if (i >= 50) {
+		if (i >= 20) {
 			b43err(dev->wl, "Microcode not responding\n");
 			b43_print_fw_helptext(dev->wl, 1);
 			err = -ENODEV;
-			goto out;
+			goto error;
+		}
+		msleep_interruptible(50);
+		if (signal_pending(current)) {
+			err = -EINTR;
+			goto error;
 		}
-		udelay(10);
 	}
 	b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);	/* dummy read */
 
 	/* Get and check the revisions. */
 	fwrev = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEREV);
 	fwpatch = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEPATCH);
@@ -1834,15 +1852,14 @@ static int b43_upload_microcode(struct b
 
 	if (fwrev <= 0x128) {
 		b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "
 		       "binary drivers older than version 4.x is unsupported. "
 		       "You must upgrade your firmware files.\n");
 		b43_print_fw_helptext(dev->wl, 1);
-		b43_write32(dev, B43_MMIO_MACCTL, 0);
 		err = -EOPNOTSUPP;
-		goto out;
+		goto error;
 	}
 	b43dbg(dev->wl, "Loading firmware version %u.%u "
 	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
 	       fwrev, fwpatch,
 	       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
 	       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
@@ -1853,13 +1870,20 @@ static int b43_upload_microcode(struct b
 	if (b43_is_old_txhdr_format(dev)) {
 		b43warn(dev->wl, "You are using an old firmware image. "
 			"Support for old firmware will be removed in July 2008.\n");
 		b43_print_fw_helptext(dev->wl, 0);
 	}
 
-out:
+	return 0;
+
+error:
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl &= ~B43_MACCTL_PSM_RUN;
+	macctl |= B43_MACCTL_PSM_JMP0;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+
 	return err;
 }
 
 static int b43_write_initvals(struct b43_wldev *dev,
 			      const struct b43_iv *ivals,
 			      size_t count,
@@ -2225,17 +2249,21 @@ static void b43_chip_exit(struct b43_wld
  * http://bcm-specs.sipsolutions.net/ChipInit
  */
 static int b43_chip_init(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
 	int err, tmp;
-	u32 value32;
+	u32 value32, macctl;
 	u16 value16;
 
-	b43_write32(dev, B43_MMIO_MACCTL,
-		    B43_MACCTL_PSM_JMP0 | B43_MACCTL_IHR_ENABLED);
+	/* Initialize the MAC control */
+	macctl = B43_MACCTL_IHR_ENABLED | B43_MACCTL_SHM_ENABLED;
+	if (dev->phy.gmode)
+		macctl |= B43_MACCTL_GMODE;
+	macctl |= B43_MACCTL_INFRA;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 
 	err = b43_request_firmware(dev);
 	if (err)
 		goto out;
 	err = b43_upload_microcode(dev);
 	if (err)
@@ -3373,18 +3401,25 @@ static void b43_set_retry_limits(struct 
 
 /* Shutdown a wireless core */
 /* Locking: wl->mutex */
 static void b43_wireless_core_exit(struct b43_wldev *dev)
 {
 	struct b43_phy *phy = &dev->phy;
+	u32 macctl;
 
 	B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
 	if (b43_status(dev) != B43_STAT_INITIALIZED)
 		return;
 	b43_set_status(dev, B43_STAT_UNINIT);
 
+	/* Stop the microcode PSM. */
+	macctl = b43_read32(dev, B43_MMIO_MACCTL);
+	macctl &= ~B43_MACCTL_PSM_RUN;
+	macctl |= B43_MACCTL_PSM_JMP0;
+	b43_write32(dev, B43_MMIO_MACCTL, macctl);
+
 	b43_leds_exit(dev);
 	b43_rng_exit(dev->wl);
 	b43_dma_free(dev);
 	b43_chip_exit(dev);
 	b43_radio_turn_off(dev, 1);
 	b43_switch_analog(dev, 0);

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] b43: Fix MAC control and microcode init
  2008-01-22 19:23 [PATCH] b43: Fix MAC control and microcode init Michael Buesch
@ 2008-01-24  9:13 ` Johannes Berg
  2008-01-24 22:03   ` Michael Buesch
  0 siblings, 1 reply; 3+ messages in thread
From: Johannes Berg @ 2008-01-24  9:13 UTC (permalink / raw)
  To: Michael Buesch; +Cc: John Linville, bcm43xx-dev, linux-wireless, Stefano Brivio

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


> This also adds a longer delay for waiting for the microcode
> to initialize itself. It seems that the current timeout is sufficient
> on all available devices, but there's no real reason why we shouldn't
> wait for up to one second. Slow embedded devices might exist.

Your decision, but I very much doubt you can make the MAC any slower
than on the old devices, in fact, on new chips it runs considerably
faster I think.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] b43: Fix MAC control and microcode init
  2008-01-24  9:13 ` Johannes Berg
@ 2008-01-24 22:03   ` Michael Buesch
  0 siblings, 0 replies; 3+ messages in thread
From: Michael Buesch @ 2008-01-24 22:03 UTC (permalink / raw)
  To: Johannes Berg; +Cc: John Linville, bcm43xx-dev, linux-wireless, Stefano Brivio

On Thursday 24 January 2008 10:13:01 Johannes Berg wrote:
> 
> > This also adds a longer delay for waiting for the microcode
> > to initialize itself. It seems that the current timeout is sufficient
> > on all available devices, but there's no real reason why we shouldn't
> > wait for up to one second. Slow embedded devices might exist.
> 
> Your decision, but I very much doubt you can make the MAC any slower
> than on the old devices, in fact, on new chips it runs considerably
> faster I think.

Ok, well. But the host machine does get faster. In theory we only
gave the microcode 500 microseconds of time to initialize. I think
that is is a pretty tiny timeframe. In practice the time was higher,
because we had a loop that checked MMIO and delayed for 10usec.
Of course this all has overhead. But as machines get faster and faster
I think we can't assume to have more than 500 microseconds of time.

So, increasing the delay to one second doesn't hurt anyone. In
all common cases it will continue after a few milliseconds. That's fine.
Even if there is something going wrong (wrong firmware) you can
interrupt the one second delay by hitting ^C.

I think the specs originally sayed to use a much longer delay than
we were using. But we did use a shorter delay, because in some old
bcm43xx code this ran unter spinlock as far as I remember. So we didn't
want to spin several milliseconds and lockup the system, if something
goes wrong in firmware. These times are gone and now we can sleep
in this part of the code.

-- 
Greetings Michael.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-01-24 22:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-22 19:23 [PATCH] b43: Fix MAC control and microcode init Michael Buesch
2008-01-24  9:13 ` Johannes Berg
2008-01-24 22:03   ` Michael Buesch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).