summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h4
-rw-r--r--c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c44
2 files changed, 33 insertions, 15 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
index 83d5c9c590..9a2a4405fd 100644
--- a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
+++ b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
@@ -312,7 +312,7 @@ extern void grspw_initialize_user(
);
extern int grspw_dev_count(void);
extern void *grspw_open(int dev_no);
-extern void grspw_close(void *d);
+extern int grspw_close(void *d);
extern void grspw_hw_support(void *d, struct grspw_hw_sup *hw);
extern void grspw_stats_read(void *d, struct grspw_core_stats *sts);
extern void grspw_stats_clr(void *d);
@@ -422,7 +422,7 @@ extern int grspw_port_active(void *d);
/*** DMA Interface ***/
extern void *grspw_dma_open(void *d, int chan_no);
-extern void grspw_dma_close(void *c);
+extern int grspw_dma_close(void *c);
extern int grspw_dma_start(void *c);
extern void grspw_dma_stop(void *c);
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++;