Search Linux Wireless

[PATCH/RFC] ath5k: clear rx queue on reset

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

 



When changing channels or otherwise resetting the card, dump
any queued rx buffers so that we don't use the wrong channel
information when reporting the packets.  This should fix the
remaining instances of this warning:

WARNING: at /build/buildd-linux-2.6_2.6.30-1-i386-06t6n0/linux-2.6-2.6.30/debian/build/source_i386_none/drivers/net/wireless/ath5k/base.c:1096 ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]()
Hardware name: MacBook1,1
invalid hw_rix: 1b
Modules linked in: i915 drm i2c_algo_bit binfmt_misc uvcvideo videodev v4l1_compat btusb rfcomm l2cap bluetooth ppdev parport_pc lp parport acpi_cpufreq cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats ext4 jbd2 crc16 ext2 fuse arc4 ecb ath5k mac80211 cfg80211 firewire_sbp2 loop joydev applesmc led_class input_polldev snd_hda_codec_idt isight_firmware pcspkr i2c_i801 i2c_core rng_core appletouch evdev iTCO_wdt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq snd_timer snd_seq_device tpm_infineon tpm tpm_bios video output battery processor ac button snd soundcore snd_page_alloc intel_agp agpgart ext3 jbd mbcache usbhid dm_mirror dm_region_hash dm_log dm_snapshot dm_mod sd_mod crc_t10dif ide_cd_mod cdrom ata_piix ata_generic libata scsi_mod firewire_ohci firewire_core crc_itu_t ehci_hcd uhci_hcd ide_pci_generic piix ide_core sky2 usbcore thermal fan thermal_sys hid_apple hid
Pid: 5218, comm: euphoria Tainted: G        W  2.6.30-1-686 #1
Call Trace:
 [<c0126ff8>] ? warn_slowpath_common+0x5e/0x8a
 [<c0127056>] ? warn_slowpath_fmt+0x26/0x2a
 [<f86c139b>] ? ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]
 [<f86c1899>] ? ath5k_tasklet_rx+0x2b7/0x42e [ath5k]
 [<c012e618>] ? __mod_timer+0xc9/0xd3
 [<c012abcf>] ? tasklet_action+0x63/0xa8
 [<c012b0d7>] ? __do_softirq+0x8e/0x135
 [<c012b1ac>] ? do_softirq+0x2e/0x38
 [<c012b28f>] ? irq_exit+0x26/0x53
 [<c01105c6>] ? smp_apic_timer_interrupt+0x6c/0x76
 [<c0103966>] ? apic_timer_interrupt+0x2a/0x30
 [<c01100d8>] ? lapic_suspend+0x47/0x15c
 [<f8ab68df>] ? drm_clflush_pages+0x3b/0x68 [drm]
 [<f8b0ad19>] ? i915_gem_execbuffer+0x6cf/0xbdd [i915]
 [<f8b08b88>] ? i915_gem_busy_ioctl+0x73/0x7a [i915]
 [<f8ab7667>] ? drm_ioctl+0x1ca/0x24b [drm]
 [<f8b0a64a>] ? i915_gem_execbuffer+0x0/0xbdd [i915]
 [<c011cc82>] ? update_curr+0x58/0x178
 [<c0138b88>] ? hrtimer_forward+0x10c/0x124
 [<c013d424>] ? getnstimeofday+0x4d/0xca
 [<c0197064>] ? vfs_ioctl+0x49/0x5f
 [<c01974be>] ? do_vfs_ioctl+0x444/0x47f
 [<c01052e6>] ? timer_interrupt+0x32/0x38
 [<c015a9e5>] ? handle_IRQ_event+0x4e/0x101
 [<c015bbdf>] ? handle_edge_irq+0xc6/0xe6
 [<c019753a>] ? sys_ioctl+0x41/0x58
 [<c0103014>] ? sysenter_do_call+0x12/0x28
---[ end trace 56450801255ccacd ]---

Signed-off-by: Bob Copeland <me@xxxxxxxxxxxxxxx>
---

Luis, what do you think of this for the time being?

I also tried just calling the tasklet so that we don't lose this
information.  This makes the locking a bit more complicated since
reset can run in process or softirq context and I didn't quite get
it working right, though it would be a worthy avenue to persue.

This seems to work ok though -- it artificially dropped about 50
packets while running iperf in parallel with continual scans for
10 minutes, but I still got decent iperf numbers.

 drivers/net/wireless/ath/ath5k/base.c |   53 ++++++++++++++++++++------------
 1 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9c6ab53..1f62325 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -548,6 +548,8 @@ ath5k_pci_probe(struct pci_dev *pdev,
 
 	sc->iobase = mem; /* So we can unmap it on detach */
 	sc->common.cachelsz = csz << 2; /* convert to bytes */
+	sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
+
 	sc->opmode = NL80211_IFTYPE_STATION;
 	sc->bintval = 1000;
 	mutex_init(&sc->lock);
@@ -1221,6 +1223,32 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	return 0;
 }
 
+/*
+ * Clear out any unprocessed RX buffers and reset the buffers to
+ * their initial state.
+ */
+static int
+ath5k_rxbuf_init(struct ath5k_softc *sc)
+{
+	int ret;
+	struct ath5k_buf *bf;
+
+	spin_lock_bh(&sc->rxbuflock);
+	sc->rxlink = NULL;
+	list_for_each_entry(bf, &sc->rxbuf, list) {
+		ret = ath5k_rxbuf_setup(sc, bf);
+		if (ret)
+			goto err;
+	}
+	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+	ath5k_hw_set_rxdp(sc->ah, bf->daddr);
+	ret = 0;
+err:
+	spin_unlock_bh(&sc->rxbuflock);
+	return ret;
+}
+
+
 static int
 ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
 		  struct ath5k_txq *txq)
@@ -1606,32 +1634,17 @@ static int
 ath5k_rx_start(struct ath5k_softc *sc)
 {
 	struct ath5k_hw *ah = sc->ah;
-	struct ath5k_buf *bf;
 	int ret;
 
-	sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
-
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
-		sc->common.cachelsz, sc->rxbufsize);
-
-	spin_lock_bh(&sc->rxbuflock);
-	sc->rxlink = NULL;
-	list_for_each_entry(bf, &sc->rxbuf, list) {
-		ret = ath5k_rxbuf_setup(sc, bf);
-		if (ret != 0) {
-			spin_unlock_bh(&sc->rxbuflock);
-			goto err;
-		}
-	}
-	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
-	ath5k_hw_set_rxdp(ah, bf->daddr);
-	spin_unlock_bh(&sc->rxbuflock);
+	ret = ath5k_rxbuf_init(sc);
+	if (ret)
+		goto err;
 
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
 	ath5k_mode_setup(sc);		/* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
 
-	return 0;
+	ret = 0;
 err:
 	return ret;
 }
@@ -1650,7 +1663,7 @@ ath5k_rx_stop(struct ath5k_softc *sc)
 
 	ath5k_debug_printrxbuffs(sc, ah);
 
-	sc->rxlink = NULL;		/* just in case */
+	ath5k_rxbuf_init(sc);		/* clear rx buffers */
 }
 
 static unsigned int
-- 
1.6.2.5

-- 
Bob Copeland %% www.bobcopeland.com

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux