summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c')
-rw-r--r--c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c76
1 files changed, 72 insertions, 4 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
index 066d30fb72..048f7d19b8 100644
--- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
+++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
@@ -334,6 +334,8 @@ struct grspw_txbd {
/* GRSPW Constants */
#define GRSPW_TXBD_NR 64 /* Maximum number of TX Descriptors */
#define GRSPW_RXBD_NR 128 /* Maximum number of RX Descriptors */
+#define GRSPW_TXBD_SIZE 16 /* Size in bytes of one TX descriptor */
+#define GRSPW_RXBD_SIZE 8 /* Size in bytes of one RX descriptor */
#define BDTAB_SIZE 0x400 /* BD Table Size (RX or TX) */
#define BDTAB_ALIGN 0x400 /* BD Table Alignment Requirement */
@@ -1894,16 +1896,49 @@ int grspw_dma_tx_reclaim(void *c, int opts, struct grspw_list *pkts, int *count)
return (~started) & 1; /* signal DMA has been stopped */
}
-void grspw_dma_tx_count(void *c, int *send, int *sched, int *sent)
+void grspw_dma_tx_count(void *c, int *send, int *sched, int *sent, int *hw)
{
struct grspw_dma_priv *dma = c;
+ int sched_cnt, diff;
+ unsigned int hwbd;
+ struct grspw_txbd *tailbd;
+
+ /* Take device lock - Wait until we get semaphore.
+ * The lock is taken so that the counters are in sync with each other
+ * and that DMA descriptor table and tx_ring_tail is not being updated
+ * during HW counter processing in this function.
+ */
+ if (rtems_semaphore_obtain(dma->sem_dma, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
+ != RTEMS_SUCCESSFUL)
+ return;
if (send)
*send = dma->send_cnt;
+ sched_cnt = dma->tx_sched_cnt;
if (sched)
- *sched = dma->tx_sched_cnt;
+ *sched = sched_cnt;
if (sent)
*sent = dma->sent_cnt;
+ if (hw) {
+ /* Calculate number of descriptors (processed by HW) between
+ * HW pointer and oldest SW pointer.
+ */
+ hwbd = REG_READ(&dma->regs->txdesc);
+ tailbd = dma->tx_ring_tail->bd;
+ diff = ((hwbd - (unsigned int)tailbd) / GRSPW_TXBD_SIZE) &
+ (GRSPW_TXBD_NR - 1);
+ /* Handle special case when HW and SW pointers are equal
+ * because all TX descriptors have been processed by HW.
+ */
+ if ((diff == 0) && (sched_cnt == GRSPW_TXBD_NR) &&
+ ((BD_READ(&tailbd->ctrl) & GRSPW_TXBD_EN) == 0)) {
+ diff = GRSPW_TXBD_NR;
+ }
+ *hw = diff;
+ }
+
+ /* Unlock DMA channel */
+ rtems_semaphore_release(dma->sem_dma);
}
static inline int grspw_tx_wait_eval(struct grspw_dma_priv *dma)
@@ -2108,16 +2143,49 @@ out:
return ret;
}
-void grspw_dma_rx_count(void *c, int *ready, int *sched, int *recv)
+void grspw_dma_rx_count(void *c, int *ready, int *sched, int *recv, int *hw)
{
struct grspw_dma_priv *dma = c;
+ int sched_cnt, diff;
+ unsigned int hwbd;
+ struct grspw_rxbd *tailbd;
+
+ /* Take device lock - Wait until we get semaphore.
+ * The lock is taken so that the counters are in sync with each other
+ * and that DMA descriptor table and rx_ring_tail is not being updated
+ * during HW counter processing in this function.
+ */
+ if (rtems_semaphore_obtain(dma->sem_dma, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
+ != RTEMS_SUCCESSFUL)
+ return;
if (ready)
*ready = dma->ready_cnt;
+ sched_cnt = dma->rx_sched_cnt;
if (sched)
- *sched = dma->rx_sched_cnt;
+ *sched = sched_cnt;
if (recv)
*recv = dma->recv_cnt;
+ if (hw) {
+ /* Calculate number of descriptors (processed by HW) between
+ * HW pointer and oldest SW pointer.
+ */
+ hwbd = REG_READ(&dma->regs->rxdesc);
+ tailbd = dma->rx_ring_tail->bd;
+ diff = ((hwbd - (unsigned int)tailbd) / GRSPW_RXBD_SIZE) &
+ (GRSPW_RXBD_NR - 1);
+ /* Handle special case when HW and SW pointers are equal
+ * because all RX descriptors have been processed by HW.
+ */
+ if ((diff == 0) && (sched_cnt == GRSPW_RXBD_NR) &&
+ ((BD_READ(&tailbd->ctrl) & GRSPW_RXBD_EN) == 0)) {
+ diff = GRSPW_RXBD_NR;
+ }
+ *hw = diff;
+ }
+
+ /* Unlock DMA channel */
+ rtems_semaphore_release(dma->sem_dma);
}
static inline int grspw_rx_wait_eval(struct grspw_dma_priv *dma)