summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2016-03-23 10:45:26 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2017-03-06 07:54:55 +0100
commiteb5a42f6e000b1e3c0d8bc75c68855028e77eca0 (patch)
treeb76efa0153e4d47eb2b976be73fabcb743e87b2f /c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
parentleon, grspw_pkt: coding style fixups (diff)
downloadrtems-eb5a42f6e000b1e3c0d8bc75c68855028e77eca0.tar.bz2
leon, grspw_pkt: fixed device/dma closing
The user is now responsible to stop and close the DMA channels before closing the device. To prevent complicated situations and blocking the caller of grspw_close and grspw_dma_close a return code was added to indicate to the user that the DMA may not have been stopped or that blocked tasks are still active within the driver for the specified device.
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.c44
1 files changed, 31 insertions, 13 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 359b1ac04f..066d30fb72 100644
--- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
+++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
@@ -623,7 +623,7 @@ out:
return priv;
}
-void grspw_close(void *d)
+int grspw_close(void *d)
{
struct grspw_priv *priv = d;
int i;
@@ -631,21 +631,24 @@ void grspw_close(void *d)
/* Take GRSPW lock - Wait until we get semaphore */
if (rtems_semaphore_obtain(grspw_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
!= RTEMS_SUCCESSFUL)
- return;
+ return -1;
- /* Stop Hardware from doing DMA, put HW into "startup-state",
- * Stop hardware from generating IRQ.
+ /* Check that user has stopped and closed all DMA channels
+ * appropriately. At this point the Hardware shall not be doing DMA
+ * or generating Interrupts. We want HW in a "startup-state".
*/
- for (i=0; i<priv->hwsup.ndma_chans; i++)
- grspw_dma_close(&priv->dma[i]);
+ for (i=0; i<priv->hwsup.ndma_chans; i++) {
+ if (priv->dma[i].open) {
+ rtems_semaphore_release(grspw_sem);
+ return 1;
+ }
+ }
grspw_hw_stop(priv);
/* Mark not open */
priv->open = 0;
-
rtems_semaphore_release(grspw_sem);
-
- /* Check that all threads are out? */
+ return 0;
}
void grspw_hw_support(void *d, struct grspw_hw_sup *hw)
@@ -1751,19 +1754,25 @@ STATIC void grspw_dma_reset(struct grspw_dma_priv *dma)
grspw_dma_stats_clr(dma);
}
-void grspw_dma_close(void *c)
+int grspw_dma_close(void *c)
{
struct grspw_dma_priv *dma = c;
if (!dma->open)
- return;
+ return 0;
/* Take device lock - Wait until we get semaphore */
if (rtems_semaphore_obtain(dma->sem_dma, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
!= RTEMS_SUCCESSFUL)
- return;
+ return -1;
- grspw_dma_stop_locked(dma);
+ /* Can not close active DMA channel. User must stop DMA and make sure
+ * no threads are active/blocked within driver.
+ */
+ if (dma->started || dma->rx_wait.waiting || dma->tx_wait.waiting) {
+ rtems_semaphore_release(dma->sem_dma);
+ return 1;
+ }
/* Free resources */
rtems_semaphore_delete(dma->rx_wait.sem_wait);
@@ -1779,6 +1788,7 @@ void grspw_dma_close(void *c)
dma->tx_ring_base = NULL;
dma->open = 0;
+ return 0;
}
/* Schedule List of packets for transmission at some point in
@@ -2398,6 +2408,10 @@ void grspw_dma_stop(void *c)
{
struct grspw_dma_priv *dma = c;
+ /* If DMA channel is closed we should not access the semaphore */
+ if (!dma->open)
+ return;
+
/* Take DMA Channel lock */
if (rtems_semaphore_obtain(dma->sem_dma, RTEMS_WAIT, RTEMS_NO_TIMEOUT)
!= RTEMS_SUCCESSFUL)
@@ -2429,6 +2443,10 @@ static void grspw_work_dma_func(struct grspw_dma_priv *dma)
unsigned int ctrl;
IRQFLAGS_TYPE irqflags;
+ /* If DMA channel is closed we should not access the semaphore */
+ if (dma->open == 0)
+ return;
+
rx_cond_true = 0;
tx_cond_true = 0;
dma->stats.irq_cnt++;