summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f62e3bf0c8..9b4a313947 100644
--- a/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
+++ b/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h
@@ -313,7 +313,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);
@@ -423,7 +423,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 3bbfc84194..9f2f9bd055 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++;