summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2017-05-11 12:54:46 +0200
committerDaniel Hellstrom <daniel@gaisler.com>2017-05-14 12:32:00 +0200
commit818f10bc6c82990c5f0a33200d34de86b344e688 (patch)
treedfa037931b6ad03f400ac718dd4f416489d4cf93
parentleon, gr1553bm: SMP support by using spin-locks (diff)
downloadrtems-818f10bc6c82990c5f0a33200d34de86b344e688.tar.bz2
leon, grtc: updated overrun condition handling
The following functions now reports to the user that an overrun has occured by returning errno EIO: * grtc_read, on overrun and no more data in the DMA buffer * ioctl(GRTC_IOC_RECV), on overrun and no more frames in the DMA buffer * ioctl(GRTC_IOC_ISSTARTED), EIO is returned on overrun
-rw-r--r--c/src/lib/libbsp/sparc/shared/tmtc/grtc.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
index e2661c8ce4..3cceb60c86 100644
--- a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
+++ b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
@@ -523,7 +523,7 @@ static int __inline__ grtc_hw_data_avail(unsigned int rrp, unsigned rwp, unsigne
return rwp+(bufsize-rrp);
}
-/* Reads as much as possiböe but not more than 'max' bytes from the TC receive buffer.
+/* Reads as much as possible but not more than 'max' bytes from the TC receive buffer.
* Number of bytes put into 'buf' is returned.
*/
static int grtc_hw_read_try(struct grtc_priv *pDev, char *buf, int max)
@@ -599,7 +599,7 @@ static int grtc_hw_read_try(struct grtc_priv *pDev, char *buf, int max)
return count;
}
-/* Reads as much as possiböe but not more than 'max' bytes from the TC receive buffer.
+/* Reads as much as possible but not more than 'max' bytes from the TC receive buffer.
* Number of bytes put into 'buf' is returned.
*/
static int grtc_data_avail(struct grtc_priv *pDev)
@@ -659,6 +659,12 @@ static int grtc_start(struct grtc_priv *pDev)
return RTEMS_IO_ERROR;
}
+ /* make sure the RX semaphore is in the correct state when starting.
+ * In case of a previous overrun condition it could be in incorrect
+ * state (where rtems_semaphore_flush was used).
+ */
+ rtems_semaphore_obtain(pDev->sem_rx, RTEMS_NO_WAIT, 0);
+
/* Set operating modes */
tmp = 0;
if ( pDev->config.psr_enable )
@@ -814,6 +820,7 @@ static rtems_device_driver grtc_open(
pDev->ready.cnt = 0;
pDev->running = 0;
+ pDev->overrun_condition = 0;
memset(&pDev->config,0,sizeof(pDev->config));
@@ -841,7 +848,7 @@ static rtems_device_driver grtc_close(rtems_device_major_number major, rtems_dev
grtc_stop(pDev);
pDev->running = 0;
}
-
+
/* Reset core */
grtc_hw_reset(pDev);
@@ -910,16 +917,22 @@ read_from_buffer:
/* Non-blocking mode and no data read. */
return RTEMS_TIMEOUT;
}
-
+
/* Tell caller how much was read. */
-
+
DBG("READ returning %d bytes, left: %d\n",rw_args->count-left,left);
-
+
rw_args->bytes_moved = rw_args->count - left;
- if ( rw_args->bytes_moved == 0 ){
+ if ( rw_args->bytes_moved == 0 ) {
+ if ( pDev->overrun_condition ) {
+ /* signal to the user that overrun has happend when
+ * no more data can be read out.
+ */
+ return RTEMS_IO_ERROR;
+ }
return RTEMS_TIMEOUT;
}
-
+
return RTEMS_SUCCESSFUL;
}
@@ -1569,6 +1582,8 @@ static rtems_device_driver grtc_ioctl(rtems_device_major_number major, rtems_dev
case GRTC_IOC_ISSTARTED:
if ( !pDev->running ) {
return RTEMS_RESOURCE_IN_USE;
+ } else if ( pDev->overrun_condition ) {
+ return RTEMS_IO_ERROR;
}
break;
@@ -1850,13 +1865,20 @@ static rtems_device_driver grtc_ioctl(rtems_device_major_number major, rtems_dev
frmlist->head = pDev->ready.head;
frmlist->tail = pDev->ready.tail;
frmlist->cnt = pDev->ready.cnt;
-
+
/* Empty list */
pDev->ready.head = NULL;
pDev->ready.tail = NULL;
pDev->ready.cnt = 0;
+
+ if ((frmlist->cnt == 0) && pDev->overrun_condition) {
+ /* signal to the user that overrun has happend when
+ * no more data can be read out.
+ */
+ return RTEMS_IO_ERROR;
+ }
break;
-
+
case GRTC_IOC_GET_CLCW_ADR:
if ( !data ) {
return RTEMS_INVALID_NAME;
@@ -1878,7 +1900,7 @@ static void grtc_interrupt(void *arg)
/* Clear interrupt by reading it */
status = READ_REG(&regs->pisr);
-
+
/* Spurious Interrupt? */
if ( !pDev->running )
return;