void
NvEcClose(NvEcHandle hEc)
{
    NvEcPrivState   *ec;
    NvBool          destroy = NV_FALSE;

    if ( NULL == hEc )
        return;

    NV_ASSERT( s_refcount );

    ec = hEc->ec;
    NvOsMutexLock( ec->mutex );

    // FIXME: handle client still with outstanding event types
    if ( !--s_refcount )
    {
        NvEcPrivDeinitHook(ec->hEc);

        NV_ASSERT( NULL == ec->eventReg[hEc->tag].regBegin &&
                    NULL == ec->eventReg[hEc->tag].regEnd );
        NV_ASSERT( NULL == ec->requestBegin && NULL == ec->requestEnd );
        NV_ASSERT( NULL == ec->responseBegin && NULL == ec->responseEnd );

        ec->exitPingThread = NV_TRUE;
        NvOsSemaphoreSignal( ec->hPingSema );
        NvOsThreadJoin( ec->hPingThread );
        ec->exitThread = NV_TRUE;
        NvOsSemaphoreSignal( ec->sema );
        NvOsThreadJoin( ec->thread );

        NvEcTransportClose( ec->transport );
        NvOsMutexDestroy( ec->requestMutex );
        NvOsMutexDestroy( ec->responseMutex );
        NvOsMutexDestroy( ec->eventMutex );
        NvOsSemaphoreDestroy( ec->sema );
        NvOsSemaphoreDestroy( ec->hPingSema );
        NvOsSemaphoreDestroy( ec->LowPowerEntrySema );
        NvOsSemaphoreDestroy( ec->LowPowerExitSema );
        destroy = NV_TRUE;

        NvOsFree( ec->eventNodes );
        NvOsFree( ec->hEc );
    }

    // Set this flag as FALSE to indicate power is disabled
    ec->powerState = NV_FALSE;

    NV_ASSERT( hEc->tag < NVEC_MAX_REQUESTOR_TAG );
    ec->tagAllocated[hEc->tag] = NV_FALSE;      // to be recycled

    NvOsFree( hEc );
    NvOsMutexUnlock( ec->mutex );

    if ( destroy )
    {
        NvOsMutexDestroy( ec->mutex );
        NvOsMemset( ec, 0, sizeof(NvEcPrivState) );
        ec->mutex = NULL;
    }
}
void
NvEcClose(NvEcHandle hEc)
{
    NvEcPrivState   *ec;
    NvBool          destroy = NV_FALSE;

    if ( NULL == hEc )
        return;

    NV_ASSERT( s_refcount );

    ec = hEc->ec;
    NvOsMutexLock( ec->mutex );

    // FIXME: handle client still with outstanding event types
    if ( !--s_refcount )
    {
        NvEcPrivDeinitHook(ec->hEc);

        NV_ASSERT( NULL == ec->eventReg[hEc->tag].regBegin &&
                    NULL == ec->eventReg[hEc->tag].regEnd );
        NV_ASSERT( NULL == ec->requestBegin && NULL == ec->requestEnd );
        NV_ASSERT( NULL == ec->responseBegin && NULL == ec->responseEnd );
#ifndef CONFIG_TEGRA_ODM_BETELGEUSE
        ec->exitPingThread = NV_TRUE;
        NvOsSemaphoreSignal( ec->hPingSema );
        NvOsThreadJoin( ec->hPingThread );
#endif
        ec->exitThread = NV_TRUE;
        NvOsSemaphoreSignal( ec->sema );
        NvOsThreadJoin( ec->thread );

        NvEcTransportClose( ec->transport );
        NvOsMutexDestroy( ec->requestMutex );
        NvOsMutexDestroy( ec->responseMutex );
        NvOsMutexDestroy( ec->eventMutex );
        NvOsSemaphoreDestroy( ec->sema );
#ifndef CONFIG_TEGRA_ODM_BETELGEUSE
        NvOsSemaphoreDestroy( ec->hPingSema );
#endif
        NvOsSemaphoreDestroy( ec->LowPowerEntrySema );
        NvOsSemaphoreDestroy( ec->LowPowerExitSema );
        destroy = NV_TRUE;

        NvOsFree( ec->eventNodes );
        NvOsFree( ec->hEc );
    }

    // Set this flag as FALSE to indicate power is disabled
    //Daniel 20100723, if we change power state to NV_FALSE, we won't be able to suspend/poweroff it.
    //Is there any side effect ????? 
    //ec->powerState = NV_FALSE;

    NV_ASSERT( hEc->tag < NVEC_MAX_REQUESTOR_TAG );
    ec->tagAllocated[hEc->tag] = NV_FALSE;      // to be recycled

    NvOsFree( hEc );
    NvOsMutexUnlock( ec->mutex );

    if ( destroy )
    {
        NvOsMutexDestroy( ec->mutex );
        NvOsMemset( ec, 0, sizeof(NvEcPrivState) );
        ec->mutex = NULL;
    }
}