diff options
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h | 4 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c | 44 |
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++; |