From ae5fa08abd1b898c0c080927e75c7249b3982c2d Mon Sep 17 00:00:00 2001 From: John Sloan Date: Fri, 13 Feb 2015 14:46:22 -0600 Subject: [PATCH] wcxb: Fix "I/O error reported by firmware" followed by underruns The cards affected include the TE131/3, TE235/435, A4B, and A8B. Update all PCIe cards' firmware to increase the incoming and outgoing TDM FIFOs to 16ms. The FIFOs will only be filled to a depth equal to the driver's latency setting (ie. 3ms default). The total system latency is not effected. The firmware and driver now also report the maximum DMA transaction time when in DEBUG mode to aid in determining if the system is experiencing long PCIe transactions (ie. TLP completion timeouts). Decreased the maximum latency to from 20 to 12ms Signed-off-by: Russ Meyerriecks --- drivers/dahdi/firmware/Makefile | 8 ++--- drivers/dahdi/wcaxx-base.c | 4 +-- drivers/dahdi/wcte13xp-base.c | 2 +- drivers/dahdi/wcte43x-base.c | 2 +- drivers/dahdi/wcxb.c | 54 +++++++++++---------------------- drivers/dahdi/wcxb.h | 7 +++-- 6 files changed, 30 insertions(+), 47 deletions(-) diff --git a/drivers/dahdi/firmware/Makefile b/drivers/dahdi/firmware/Makefile index e93347e..fbd6582 100644 --- a/drivers/dahdi/firmware/Makefile +++ b/drivers/dahdi/firmware/Makefile @@ -31,14 +31,14 @@ VPMADT032_VERSION:=1.25.0 HX8_VERSION:=2.06 VPMOCT032_VERSION:=1.12.0 WCT820_VERSION:=1.76 -TE133_VERSION:=780019 +TE133_VERSION:=7a001e TE134_VERSION:=780017 -TE435_VERSION:=e0019 +TE435_VERSION:=13001e TE436_VERSION:=10017 A8A_VERSION:=1d0017 -A8B_VERSION:=1d0019 +A8B_VERSION:=1f001e A4A_VERSION:=a0017 -A4B_VERSION:=b0019 +A4B_VERSION:=d001e FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases diff --git a/drivers/dahdi/wcaxx-base.c b/drivers/dahdi/wcaxx-base.c index 3d3329f..00c2d21 100644 --- a/drivers/dahdi/wcaxx-base.c +++ b/drivers/dahdi/wcaxx-base.c @@ -3886,9 +3886,9 @@ static int wcaxx_check_firmware(struct wcaxx *wc) u32 firmware_version; const bool force_firmware = false; const unsigned int A4A_VERSION = 0x0a0017; - const unsigned int A4B_VERSION = 0x0b0019; + const unsigned int A4B_VERSION = 0x0d001e; const unsigned int A8A_VERSION = 0x1d0017; - const unsigned int A8B_VERSION = 0x1d0019; + const unsigned int A8B_VERSION = 0x1f001e; if (wc->desc == &device_a8a) { firmware_version = A8A_VERSION; diff --git a/drivers/dahdi/wcte13xp-base.c b/drivers/dahdi/wcte13xp-base.c index 1917583..c5ebe9d 100644 --- a/drivers/dahdi/wcte13xp-base.c +++ b/drivers/dahdi/wcte13xp-base.c @@ -45,7 +45,7 @@ static const char *TE133_FW_FILENAME = "dahdi-fw-te133.bin"; static const char *TE134_FW_FILENAME = "dahdi-fw-te134.bin"; -static const u32 TE133_FW_VERSION = 0x780019; +static const u32 TE133_FW_VERSION = 0x7a001e; static const u32 TE134_FW_VERSION = 0x780017; #define WC_MAX_IFACES 8 diff --git a/drivers/dahdi/wcte43x-base.c b/drivers/dahdi/wcte43x-base.c index a718393..3f00c5d 100644 --- a/drivers/dahdi/wcte43x-base.c +++ b/drivers/dahdi/wcte43x-base.c @@ -66,7 +66,7 @@ static inline int delayed_work_pending(struct work_struct *work) static const char *TE435_FW_FILENAME = "dahdi-fw-te435.bin"; static const char *TE436_FW_FILENAME = "dahdi-fw-te436.bin"; -static const u32 TE435_VERSION = 0xe0019; +static const u32 TE435_VERSION = 0x13001e; static const u32 TE436_VERSION = 0x10017; /* #define RPC_RCLK */ diff --git a/drivers/dahdi/wcxb.c b/drivers/dahdi/wcxb.c index 9ab53c8..f45125a 100644 --- a/drivers/dahdi/wcxb.c +++ b/drivers/dahdi/wcxb.c @@ -66,7 +66,6 @@ #define DRING_SIZE_MASK (DRING_SIZE-1) #define DESC_EOR (1 << 0) #define DESC_INT (1 << 1) -#define DESC_IO_ERROR (1 << 30) #define DESC_OWN (1 << 31) #define DESC_DEFAULT_STATUS 0xdeadbe00 #define DMA_CHAN_SIZE 128 @@ -358,45 +357,25 @@ static void _wcxb_reset_dring(struct wcxb *xb) hdesc->control |= cpu_to_be32(DESC_EOR); #ifdef DEBUG xb->last_retry_count = 0; + xb->max_retry_count = 0; + xb->last_dma_time = 0; + xb->max_dma_time = 0; #endif iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR); } static void wcxb_handle_dma(struct wcxb *xb) { -#ifdef DEBUG - bool did_retry_dma = false; - u8 retry; -#endif struct wcxb_meta_desc *mdesc; struct wcxb_hw_desc *tail = &(xb->hw_dring[xb->dma_tail]); while (!(tail->control & cpu_to_be32(DESC_OWN))) { u_char *frame; - if (tail->control & cpu_to_be32(DESC_IO_ERROR)) { - u32 ier; - unsigned long flags; - - /* The firmware detected an error condition on the bus. - * Force an underrun by disabling the descriptor - * complete interrupt. When the driver processes the - * underrun it will reset the TDM engine. */ - xb->flags.io_error = 1; - - spin_lock_irqsave(&xb->lock, flags); - ier = ioread32be(xb->membase + IER); - iowrite32be(ier & ~DESC_COMPLETE, xb->membase + IER); - spin_unlock_irqrestore(&xb->lock, flags); - return; - } - #ifdef DEBUG - retry = be32_to_cpu(tail->status) & 0xff; - if (xb->last_retry_count != retry) { - xb->last_retry_count = retry; - did_retry_dma = true; - } + xb->last_retry_count = + ((be32_to_cpu(tail->control) & 0x0000ff00) >> 8); + xb->last_dma_time = (be32_to_cpu(tail->status)); #endif mdesc = &xb->meta_dring[xb->dma_tail]; @@ -420,9 +399,17 @@ static void wcxb_handle_dma(struct wcxb *xb) } #ifdef DEBUG - if (did_retry_dma) { + if (xb->last_retry_count > xb->max_retry_count) { + xb->max_retry_count = xb->last_retry_count; dev_info(&xb->pdev->dev, - "DMA retries detected: %d\n", xb->last_retry_count); + "New DMA max retries detected: %d\n", + xb->max_retry_count); + } + if (xb->last_dma_time > xb->max_dma_time) { + xb->max_dma_time = xb->last_dma_time; + dev_info(&xb->pdev->dev, + "New DMA max transfer time detected: %d\n", + xb->max_dma_time); } #endif } @@ -451,14 +438,7 @@ static irqreturn_t _wcxb_isr(int irq, void *dev_id) spin_lock(&xb->lock); - if (xb->flags.io_error) { - /* Since an IO error is not necessarily because - * the host could not keep up, we do not want to - * bump the latency. */ - xb->flags.io_error = 0; - dev_warn(&xb->pdev->dev, - "IO error reported by firmware.\n"); - } else if (!xb->flags.latency_locked) { + if (!xb->flags.latency_locked) { /* bump latency */ xb->latency = min(xb->latency + 1, diff --git a/drivers/dahdi/wcxb.h b/drivers/dahdi/wcxb.h index 3a0f8d3..d23c89f 100644 --- a/drivers/dahdi/wcxb.h +++ b/drivers/dahdi/wcxb.h @@ -24,7 +24,7 @@ #define __WCXB_H__ #define WCXB_DEFAULT_LATENCY 3U -#define WCXB_DEFAULT_MAXLATENCY 20U +#define WCXB_DEFAULT_MAXLATENCY 12U #define WCXB_DMA_CHAN_SIZE 128 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) @@ -66,7 +66,7 @@ struct wcxb { #ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE u32 is_pcie:1; #endif - u32 io_error:1; + u32 dma_ins:1; } flags; void __iomem *membase; struct wcxb_meta_desc *meta_dring; @@ -78,6 +78,9 @@ struct wcxb { unsigned long framecount; #ifdef DEBUG u8 last_retry_count; + u8 max_retry_count; + u32 last_dma_time; + u32 max_dma_time; #endif };