wcxb: Add diagnostic message if DMA retries are increasing when DEBUG is defined.

There are some platforms where the DMA operation to the host does not complete
within the required 50us. When this happens some versions of the firmware will
issue a retry and increment the retry field in the descriptor status word.

Now if this driver is configured in DEBUG mode, the presence of these retries
will be printed to the kernel log as a potential troubleshooting aide.

Internal-Issue-ID: DAHDI-1087
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
This commit is contained in:
Shaun Ruffell 2014-03-13 01:37:51 -05:00
parent 665bf9feb6
commit 50f2fd15b6
2 changed files with 31 additions and 1 deletions

View File

@ -64,7 +64,7 @@
#define DESC_INT (1 << 1) #define DESC_INT (1 << 1)
#define DESC_IO_ERROR (1 << 30) #define DESC_IO_ERROR (1 << 30)
#define DESC_OWN (1 << 31) #define DESC_OWN (1 << 31)
#define DESC_DEFAULT_STATUS 0xdeadbeef #define DESC_DEFAULT_STATUS 0xdeadbe00
#define DMA_CHAN_SIZE 128 #define DMA_CHAN_SIZE 128
/* Echocan definitions */ /* Echocan definitions */
@ -352,11 +352,18 @@ static void _wcxb_reset_dring(struct wcxb *xb)
BUG_ON(!hdesc); BUG_ON(!hdesc);
/* Set end of ring bit in last descriptor to force hw to loop around */ /* Set end of ring bit in last descriptor to force hw to loop around */
hdesc->control |= cpu_to_be32(DESC_EOR); hdesc->control |= cpu_to_be32(DESC_EOR);
#ifdef DEBUG
xb->last_retry_count = 0;
#endif
iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR); iowrite32be(xb->hw_dring_phys, xb->membase + TDM_DRING_ADDR);
} }
static void wcxb_handle_dma(struct wcxb *xb) 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_meta_desc *mdesc;
struct wcxb_hw_desc *tail = &(xb->hw_dring[xb->dma_tail]); struct wcxb_hw_desc *tail = &(xb->hw_dring[xb->dma_tail]);
@ -380,6 +387,14 @@ static void wcxb_handle_dma(struct wcxb *xb)
return; 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;
}
#endif
mdesc = &xb->meta_dring[xb->dma_tail]; mdesc = &xb->meta_dring[xb->dma_tail];
frame = mdesc->rx_buf_virt; frame = mdesc->rx_buf_virt;
@ -399,6 +414,13 @@ static void wcxb_handle_dma(struct wcxb *xb)
xb->dma_head = xb->dma_head =
(xb->dma_head == xb->latency-1) ? 0 : xb->dma_head + 1; (xb->dma_head == xb->latency-1) ? 0 : xb->dma_head + 1;
} }
#ifdef DEBUG
if (did_retry_dma) {
dev_info(&xb->pdev->dev,
"DMA retries detected: %d\n", xb->last_retry_count);
}
#endif
} }
static irqreturn_t _wcxb_isr(int irq, void *dev_id) static irqreturn_t _wcxb_isr(int irq, void *dev_id)

View File

@ -47,6 +47,11 @@ struct wcxb_operations {
struct wcxb_meta_desc; struct wcxb_meta_desc;
struct wcxb_hw_desc; struct wcxb_hw_desc;
/**
* struct wcxb - Interface to wcxb firmware.
* @last_retry_count: Running count of times firmware had to retry host DMA
* transaction. Debugging aide.
*/
struct wcxb { struct wcxb {
struct pci_dev *pdev; struct pci_dev *pdev;
spinlock_t lock; spinlock_t lock;
@ -71,6 +76,9 @@ struct wcxb {
dma_addr_t hw_dring_phys; dma_addr_t hw_dring_phys;
struct dma_pool *pool; struct dma_pool *pool;
unsigned long framecount; unsigned long framecount;
#ifdef DEBUG
u8 last_retry_count;
#endif
}; };
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode); extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);