Changeset 91541551 in rtems


Ignore:
Timestamp:
Apr 11, 2017, 10:30:02 AM (2 years ago)
Author:
Daniel Hellstrom <daniel@…>
Branches:
master
Children:
ee078c21
Parents:
9855690
git-author:
Daniel Hellstrom <daniel@…> (04/11/17 10:30:02)
git-committer:
Daniel Hellstrom <daniel@…> (05/14/17 10:31:58)
Message:

leon, grcan: semaphore reset count required after flushing

It is also required to use semaphore release instead of flush when stopping
or on BUSOFF/AHBERR condition. Otherwise a task just about to wait
(taking the semaphore) could end up locked because the semaphore count is
still the same.

There was previously a scenario where the semaphore flush would not always make
semaphore obtain to return in case of BUSOFF, AHBERROR or grcan_stop. It has to
do with the rtems_semaphore_flush() not releasing the semaphore but just aborts
any _current_ waiter.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/sparc/shared/can/grcan.c

    r9855690 r91541551  
    493493static void grcan_sw_stop(struct grcan_priv *pDev)
    494494{
    495         /* Reset semaphores to the initial state and wakeing
    496          * all threads waiting for an IRQ. The threads that
    497          * get woken up must check for RTEMS_UNSATISFIED in
     495        /*
     496         * Release semaphores to wake all threads waiting for an IRQ.
     497         * The threads that
     498         * get woken up must check started state in
    498499         * order to determine that they should return to
    499500         * user space with error status.
     501         *
     502         * Entering into started mode again will reset the
     503         * semaphore count.
    500504         */
    501         rtems_semaphore_flush(pDev->rx_sem);
    502         rtems_semaphore_flush(pDev->tx_sem);
    503         rtems_semaphore_flush(pDev->txempty_sem);
     505        rtems_semaphore_release(pDev->rx_sem);
     506        rtems_semaphore_release(pDev->tx_sem);
     507        rtems_semaphore_release(pDev->txempty_sem);
    504508}
    505509
     
    963967        /* Wait for IRQ to fire only if has been triggered */
    964968        if (wait) {
    965                 if (
    966                         rtems_semaphore_obtain(
    967                                 pDev->rx_sem,
    968                                 RTEMS_WAIT,
    969                                 RTEMS_NO_TIMEOUT
    970                         ) == RTEMS_UNSATISFIED
    971                 ) {
    972                         DBGC(DBG_STATE, "UNSATISFIED\n");
    973                         /* Device driver has been closed or stopped, return with error status */
    974                         return state2err[pDev->started];
    975                 }
     969                rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     970                /*
     971                 * The semaphore is released either due to the expected IRQ
     972                 * condition or by BUSOFF, AHBERROR or another thread calling
     973                 * grcan_stop(). In either case, state2err[] has the correnct
     974                 * return value.
     975                 */
     976                return state2err[pDev->started];
    976977        }
    977978
     
    10551056        /* Wait for IRQ to fire only if it has been triggered */
    10561057        if (wait) {
    1057                 if (rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) ==
    1058                     RTEMS_UNSATISFIED) {
    1059                         /* Device driver has flushed us, this may be due to another thread has
    1060                          * closed the device, this is to avoid deadlock */
    1061                         DBGC(DBG_STATE, "UNSATISFIED\n");
    1062                         return state2err[pDev->started];
    1063                 }
     1058                rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     1059                return state2err[pDev->started];
    10641060        }
    10651061
     
    11181114
    11191115                /* Wait for IRQ to wake us */
    1120                 if (rtems_semaphore_obtain
    1121                     (pDev->txempty_sem, RTEMS_WAIT,
    1122                      RTEMS_NO_TIMEOUT) == RTEMS_UNSATISFIED) {
    1123                         DBGC(DBG_STATE, "UNSATISFIED\n");
    1124                         return state2err[pDev->started];
     1116                rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     1117                state = pDev->started;
     1118                if (state != STATE_STARTED) {
     1119                        return state2err[state];
    11251120                }
    11261121        }
     
    15661561        }
    15671562
     1563        /* Clear semaphore state. This is to avoid effects from previous
     1564         * bus-off/stop where semahpores where flushed() but the count remained.
     1565         */
     1566        rtems_semaphore_obtain(pDev->rx_sem, RTEMS_NO_WAIT, 0);
     1567        rtems_semaphore_obtain(pDev->tx_sem, RTEMS_NO_WAIT, 0);
     1568        rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_NO_WAIT, 0);
     1569
    15681570        /* Read and write are now open... */
    15691571        pDev->started = STATE_STARTED;
     
    19431945                SPIN_UNLOCK(&pDev->devlock, irqflags);
    19441946
    1945                 /* flush semaphores to wake blocked threads */
     1947                /* Release semaphores to wake blocked threads. */
    19461948                grcan_sw_stop(pDev);
    19471949
Note: See TracChangeset for help on using the changeset viewer.