diff options
author | Thommy Jakobsson <thommyj@gmail.com> | 2013-04-23 15:45:11 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-05-08 17:15:06 -0400 |
commit | 73b82bf0bfbf58e6ff328d3726934370585f6e78 (patch) | |
tree | 19c23412ef8e7fbf7353eeb7084bf96c962ed725 /drivers/net/wireless/b43/main.c | |
parent | db178340433f90e09ada35c174dfb2c84c2c71f4 (diff) |
B43: Handle DMA RX descriptor underrun
Add handling of rx descriptor underflow. This fixes a fault that could
happen on slow machines, where data is received faster than the CPU can
handle. In such a case the device will use up all rx descriptors and
refuse to send any more data before confirming that it is ok. This
patch enables necessary interrupt to discover such a situation and will
handle them by dropping everything in the ring buffer.
Reviewed-by: Michael Buesch <m@bues.ch>
Signed-off-by: Thommy Jakobsson <thommyj@gmail.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 43 |
1 files changed, 18 insertions, 25 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d377f77d30b5..6dd07e2ec595 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1902 | } | 1902 | } |
1903 | } | 1903 | } |
1904 | 1904 | ||
1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | | 1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) { |
1906 | B43_DMAIRQ_NONFATALMASK))) { | 1906 | b43err(dev->wl, |
1907 | if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { | 1907 | "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", |
1908 | b43err(dev->wl, "Fatal DMA error: " | 1908 | dma_reason[0], dma_reason[1], |
1909 | "0x%08X, 0x%08X, 0x%08X, " | 1909 | dma_reason[2], dma_reason[3], |
1910 | "0x%08X, 0x%08X, 0x%08X\n", | 1910 | dma_reason[4], dma_reason[5]); |
1911 | dma_reason[0], dma_reason[1], | 1911 | b43err(dev->wl, "This device does not support DMA " |
1912 | dma_reason[2], dma_reason[3], | ||
1913 | dma_reason[4], dma_reason[5]); | ||
1914 | b43err(dev->wl, "This device does not support DMA " | ||
1915 | "on your system. It will now be switched to PIO.\n"); | 1912 | "on your system. It will now be switched to PIO.\n"); |
1916 | /* Fall back to PIO transfers if we get fatal DMA errors! */ | 1913 | /* Fall back to PIO transfers if we get fatal DMA errors! */ |
1917 | dev->use_pio = true; | 1914 | dev->use_pio = true; |
1918 | b43_controller_restart(dev, "DMA error"); | 1915 | b43_controller_restart(dev, "DMA error"); |
1919 | return; | 1916 | return; |
1920 | } | ||
1921 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | ||
1922 | b43err(dev->wl, "DMA error: " | ||
1923 | "0x%08X, 0x%08X, 0x%08X, " | ||
1924 | "0x%08X, 0x%08X, 0x%08X\n", | ||
1925 | dma_reason[0], dma_reason[1], | ||
1926 | dma_reason[2], dma_reason[3], | ||
1927 | dma_reason[4], dma_reason[5]); | ||
1928 | } | ||
1929 | } | 1917 | } |
1930 | 1918 | ||
1931 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) | 1919 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) |
@@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1944 | handle_irq_noise(dev); | 1932 | handle_irq_noise(dev); |
1945 | 1933 | ||
1946 | /* Check the DMA reason registers for received data. */ | 1934 | /* Check the DMA reason registers for received data. */ |
1935 | if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) { | ||
1936 | if (B43_DEBUG) | ||
1937 | b43warn(dev->wl, "RX descriptor underrun\n"); | ||
1938 | b43_dma_handle_rx_overflow(dev->dma.rx_ring); | ||
1939 | } | ||
1947 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { | 1940 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { |
1948 | if (b43_using_pio_transfers(dev)) | 1941 | if (b43_using_pio_transfers(dev)) |
1949 | b43_pio_rx(dev->pio.rx_queue); | 1942 | b43_pio_rx(dev->pio.rx_queue); |
@@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) | |||
2001 | return IRQ_NONE; | 1994 | return IRQ_NONE; |
2002 | 1995 | ||
2003 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) | 1996 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) |
2004 | & 0x0001DC00; | 1997 | & 0x0001FC00; |
2005 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) | 1998 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) |
2006 | & 0x0000DC00; | 1999 | & 0x0000DC00; |
2007 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) | 2000 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) |
@@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
3130 | b43_write32(dev, 0x018C, 0x02000000); | 3123 | b43_write32(dev, 0x018C, 0x02000000); |
3131 | } | 3124 | } |
3132 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); | 3125 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); |
3133 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); | 3126 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00); |
3134 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); | 3127 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); |
3135 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); | 3128 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); |
3136 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); | 3129 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); |