Example #1
0
void tegra_audiofx_destroyfx(struct tegra_audio_data *audio_context)
{
	FxNotifier *m_FxNotifier = (FxNotifier*)&audio_context->m_FxNotifier;

	if (m_FxNotifier->Connected) {
		m_FxNotifier->Exit = 1;
		NvOsSemaphoreSignal(m_FxNotifier->hTransportSemaphore);
		NvOsThreadJoin(m_FxNotifier->hTransportThread);
		m_FxNotifier->hTransportThread = 0;
		tegra_transport_set_property(
			(NvAudioFxObjectHandle)m_FxNotifier->hNotifier,
			NvAudioFxNotifierProperty_Disconnect,
			0,
			0);
	}

	if (m_FxNotifier->hTransport) {
		NvRmTransportClose(m_FxNotifier->hTransport);
		m_FxNotifier->hTransport = 0;
	}

	if (m_FxNotifier->hNotifier) {
		tegra_transport_mixer_destroy_object(
		        (NvAudioFxObjectHandle)m_FxNotifier->hNotifier);
		m_FxNotifier->hNotifier = 0;
	}

	if (m_FxNotifier->hTransportSemaphore) {
		NvOsSemaphoreDestroy(m_FxNotifier->hTransportSemaphore);
		m_FxNotifier->hTransportSemaphore = 0;
	}

	return;
}
Example #2
0
static void nvec_battery_remove(struct nvec_device *pdev)
{
	unsigned int i = 0;

	if (batt_dev) {
		batt_dev->exitThread = NV_TRUE;
		if (batt_dev->hOdmSemaphore) {
			NvOsSemaphoreSignal(batt_dev->hOdmSemaphore);
			NvOsSemaphoreDestroy(batt_dev->hOdmSemaphore);
			batt_dev->hOdmSemaphore = NULL;
		}

		if (batt_dev->hBattEventThread) {
			NvOsThreadJoin(batt_dev->hBattEventThread);
		}

		if (batt_dev->hOdmBattDev) {
			device_remove_file(&pdev->dev, &tegra_battery_attr);
			device_remove_file(&pdev->dev, &tegra_battery_version);  //Daniel 20100823, put ec version to fs

			del_timer_sync(&(batt_dev->battery_poll_timer));

			NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev);
			batt_dev->hOdmBattDev = NULL;

			for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
				power_supply_unregister(&tegra_power_supplies[i]);
			}
		}

		kfree(batt_dev);
		batt_dev = NULL;

	}
}
Example #3
0
static void FreePowerClient(NvRmPowerClient* pPowerClient)
{
    ModuleVoltageReq* pVoltageReq = NULL;
    ModuleClockReq* pClockReq = NULL;

    // Just return if null-pointer
    if (pPowerClient == NULL)
        return;

    // Free memory occupied by voltage requests
    while (pPowerClient->pVoltageReqHead != NULL)
    {
        pVoltageReq = pPowerClient->pVoltageReqHead;
        pPowerClient->pVoltageReqHead = pVoltageReq->pNext;
        NvOsFree(pVoltageReq);
    }

    // Free memory occupied by clock requests
    while (pPowerClient->pClockReqHead != NULL)
    {
        pClockReq = pPowerClient->pClockReqHead;
        pPowerClient->pClockReqHead = pClockReq->pNext;
        NvOsFree(pClockReq);
    }

    // Free memory occupied by starvation hints array
    NvOsFree(pPowerClient->pStarvationHints);

    // Free power management event semaphore handle
    NvOsSemaphoreDestroy(pPowerClient->hEventSemaphore);

    // Free memory occupied by the client record
    NvOsFree(pPowerClient);
}
void NvRmPrivPmuDeinit(NvRmDeviceHandle hRmDevice)
{
    if (s_PmuSupportedEnv == NV_FALSE)
        return;

    PmuThreadTerminate(&s_Pmu);
    NvOdmPmuDeviceClose(s_Pmu.hOdmPmu);
    NvRmInterruptUnregister(hRmDevice, s_Pmu.hInterrupt);
    NvOsSemaphoreDestroy(s_Pmu.hSemaphore);
    NvOsMutexDestroy(s_Pmu.hMutex);

    NvOsMemset(&s_Pmu, 0, sizeof(NvRmPmu));
    s_PmuSupportedEnv = NV_FALSE;
}
Example #5
0
void tegra_transport_deinit(void)
{
	if (!atrans)
		goto EXIT;

	spin_lock(&atrans->lock);
	atrans->RefCount--;

	if (atrans->RefCount > 0){
		spin_unlock(&atrans->lock);
		goto EXIT;
	}
	spin_unlock(&atrans->lock);

	atrans->ShutDown = 1;

	if (atrans->hRmTransport) {
		NvRmTransportClose(atrans->hRmTransport);
		atrans->hRmTransport = 0;
		atrans->TransportConnected = 0;
	}

	if (atrans->hServiceThread) {
		NvOsSemaphoreSignal(atrans->hServiceSema);
		NvOsThreadJoin(atrans->hServiceThread);
		atrans->hServiceThread = 0;
	}

	if (atrans->hServiceSema) {
		NvOsSemaphoreDestroy(atrans->hServiceSema);
		atrans->hServiceSema = 0;
	}
	atrans->hRmDevice = 0;
	kfree(atrans);
	atrans = 0;

EXIT:
	return;
}
Example #6
0
static void nvec_battery_remove(struct nvec_device *pdev)
{
	unsigned int i = 0;

	if (batt_dev) {
		batt_dev->exitThread = NV_TRUE;
		if (batt_dev->hOdmSemaphore) {
			NvOsSemaphoreSignal(batt_dev->hOdmSemaphore);
			NvOsSemaphoreDestroy(batt_dev->hOdmSemaphore);
			batt_dev->hOdmSemaphore = NULL;
		}

		if (batt_dev->hBattEventThread) {
			NvOsThreadJoin(batt_dev->hBattEventThread);
		}

	    if (batt_dev->hBattEventMutex) {    
		    NvOsMutexDestroy(batt_dev->hBattEventMutex);
		    batt_dev->hBattEventMutex = NULL;
	    }

		if (batt_dev->hOdmBattDev) {
			device_remove_file(&pdev->dev, &tegra_battery_attr);

			NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev);
			batt_dev->hOdmBattDev = NULL;

			for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
				power_supply_unregister(&tegra_power_supplies[i]);
			}
		}

		kfree(batt_dev);
		batt_dev = NULL;

	}
}
NvError
NvEcUnregisterForEvents(
    NvEcEventRegistrationHandle hEcEventRegistration)
{
    NvEcPrivState   *ec;
    NvU32           tag;
    NvU32           tagMask;
    NvError         e = NvSuccess;
    NvEcEventRegistration *p = NULL, *reg = NULL;
    NvEcEventNode   *eventNode, *t;
    NvU32           i;

    if( NULL == hEcEventRegistration )
        return NvError_BadParameter;
    
    ec = hEcEventRegistration->hEc->ec;
    tag = hEcEventRegistration->hEc->tag;
    tagMask = (1UL << tag);

    NvOsMutexLock( ec->eventMutex );
    
    NVEC_REMOVE_FROM_Q( ec->eventReg[tag].reg, hEcEventRegistration, reg, p );
    if ( !reg )
    {
        e = NvError_BadParameter;      // can't find the handle
        goto fail;
    }

    eventNode = ec->eventReadyBegin;
    while ( eventNode )
    {
        // pre advance eventNode since current one could be removed
        t = eventNode;
        eventNode = eventNode->next;
        if ( (reg->eventBitmap & (1UL << t->event.EventType)) &&
                (t->tagBitmap & tagMask) )
        {
            t->tagBitmap &= ~tagMask;
            if ( !t->tagBitmap )
            {
                NvEcPrivRemoveEventFromReady( ec, t );
            }
        }
    }
 
    // remove global references to this registration
    i = 0;
    while( reg->eventBitmap )
    {
        NV_ASSERT(i < NvEcEventType_Num);
        if ( reg->eventBitmap & 1 )
        {
            ec->eventTagBitmap[i] &= ~tagMask;
            ec->eventMap[tag][i] = NULL;
        }
        reg->eventBitmap = reg->eventBitmap >> 1;
        i++;
    }

    NvOsSemaphoreDestroy( reg->sema );
    NvOsFree( hEcEventRegistration );
fail:
    NvOsMutexUnlock( ec->eventMutex );

    return e;
}
NvError
NvEcRegisterForEvents(
    NvEcHandle hEc,
    NvEcEventRegistrationHandle *phEcEventRegistration,
    NvOsSemaphoreHandle hSema,
    NvU32 NumEventTypes,
    NvEcEventType *pEventTypes,
    NvU32 NumEventPackets,
    NvU32 EventPacketSize)
{
    NvEcPrivState   *ec = hEc->ec;
    NvEcEventRegistration *h = NULL;
    NvOsSemaphoreHandle hSemaClone = NULL;
    NvError e = NvSuccess;
    NvU32   val, i, tag = hEc->tag;
    NvU32   tagMask = (1UL << tag);

    if ( !hSema || !pEventTypes )
        return NvError_BadParameter;

    if ( !NumEventTypes || (NumEventTypes > NvEcEventType_Num) )
        return NvError_InvalidSize;     // FIXME: is this sufficient?

    NV_ASSERT( phEcEventRegistration );

    NvOsMutexLock( ec->mutex );
    if ( !ec->thread )
        NvEcPrivThreadCreate( ec );

    // Allocate common pool of internal event nodes bufferring if not already
    if ( !ec->eventNodes )
    {
        val = NVEC_NUM_EVENT_PACKETS_DEFAULT;
        if ( NumEventPackets > val )
            val = NumEventPackets;
        ec->eventNodes = NvOsAlloc(val * sizeof(NvEcEventNode));
        if ( NULL == ec->eventNodes )
        {
            NvOsMutexUnlock( ec->mutex );
            return NvError_InsufficientMemory;
        }
        NvOsMemset( ec->eventNodes, 0, (val * sizeof(NvEcEventNode)) );
        for( i = 0; i < val - 1; i++ )
            ec->eventNodes[i].next = &ec->eventNodes[i+1];
        ec->eventFreeBegin = ec->eventNodes;
        ec->eventFreeEnd = ec->eventNodes + val - 1;
    }
    NvOsMutexUnlock( ec->mutex );

    NV_CHECK_ERROR( NvOsSemaphoreClone( hSema, &hSemaClone ) );

    NvOsMutexLock( ec->eventMutex );
    // Quick pre-check for for AlreadyAllocated case
    for ( i = 0; i < NumEventTypes; i++ )
    {
        val = pEventTypes[i];
        if ( val >= NvEcEventType_Num )
            e = NvError_BadParameter;
        else if ( ec->eventMap[tag][val] )
            e = NvError_AlreadyAllocated;
        if ( NvSuccess != e )
            goto fail;
    }
    h = NvOsAlloc( sizeof(NvEcEventRegistration));
    if ( NULL == h )
    {
        e = NvError_InsufficientMemory;
        goto fail;
    }

    NvOsMemset( h, 0, sizeof(NvEcEventRegistration) );
    NVEC_ENQ( ec->eventReg[tag].reg, h );

    // Fill up new registration handle
    NV_ASSERT( NvEcEventType_Num <= 32 );   // eventBitmap only works if <= 32
    for ( i = 0; i < NumEventTypes; i++ )
    {
        val = pEventTypes[i];
        h->eventBitmap |= (1 << val);
        ec->eventMap[tag][val] = h;
        ec->eventTagBitmap[val] |= tagMask;
    }
    h->numEventTypes = NumEventTypes;
    h->sema = hSemaClone;
    h->hEc = hEc;

    h->numEventPacketsHint = NumEventPackets;
    h->eventPacketSizeHint = EventPacketSize;       // ignored hints for now

    NvOsMutexUnlock( ec->eventMutex );
    *phEcEventRegistration = h;
    return e;

fail:
    NvOsSemaphoreDestroy( hSemaClone );
    NvOsMutexUnlock( ec->eventMutex );
    NvOsFree( h );
    return e;
}
NvError
NvEcSendRequest(
    NvEcHandle hEc,
    NvEcRequest *pRequest,
    NvEcResponse *pResponse,
    NvU32 RequestSize,
    NvU32 ResponseSize)
{
    NvEcPrivState       *ec;
    NvError             e = NvSuccess;
    NvEcRequestNode     *requestNode = NULL;
    NvEcResponseNode    *responseNode = NULL;
    NvOsSemaphoreHandle requestSema = NULL;
    NvOsSemaphoreHandle responseSema = NULL;
    
    NV_ASSERT( pRequest );
    NV_ASSERT( hEc );
    if ( (RequestSize > sizeof(NvEcRequest)) || 
         (ResponseSize > sizeof(NvEcResponse)) )
        return NvError_InvalidSize;
    
    ec = hEc->ec;
    requestNode = NvOsAlloc(sizeof(NvEcRequestNode));
    if ( NULL == requestNode )
    {
        e = NvError_InsufficientMemory;
        goto fail;
    }
    NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &requestSema, 0 ) );
    
    if ( pResponse )
    {
        responseNode = NvOsAlloc(sizeof(NvEcResponseNode));
        if ( NULL == responseNode )
        {
            e = NvError_InsufficientMemory;
            goto fail;
        }
        NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &responseSema, 0 ) );
    }

    ec->IsEcActive = NV_TRUE;

    // request end-queue.  Timeout set to infinite until request sent.
    NvOsMemset( requestNode, 0, sizeof(NvEcRequestNode) );
    pRequest->RequestorTag = hEc->tag;      // assigned tag here
    DISP_MESSAGE(("NvEcSendRequest:pRequest->RequestorTag=0x%x\n", pRequest->RequestorTag));
    NvOsMemcpy(&requestNode->request, pRequest, RequestSize);
    requestNode->tag = hEc->tag;
    DISP_MESSAGE(("NvEcSendRequest:requestNode->tag=0x%x\n", requestNode->tag));
    requestNode->sema = requestSema;
    requestNode->timeout = NV_WAIT_INFINITE;
    requestNode->completed = NV_FALSE;
    requestNode->size = RequestSize;
    
    NvOsMutexLock( ec->requestMutex );
    NVEC_ENQ( ec->request, requestNode );
    DISP_MESSAGE(("\r\nSendReq ec->requestBegin=0x%x", ec->requestBegin));
    NvOsMutexUnlock( ec->requestMutex );
    
    // response en-queue.  Timeout set to infinite until request completes.
    if ( pResponse )
    {
        NvOsMemset( responseNode, 0, sizeof(NvEcResponseNode) );
        requestNode->responseNode = responseNode;   // association between
        responseNode->requestNode = requestNode;    //   request & response
        responseNode->sema = responseSema;
        responseNode->timeout = NV_WAIT_INFINITE;
        responseNode->tag = hEc->tag;
        DISP_MESSAGE(("NvEcSendRequest:responseNode->tag=0x%x\n", responseNode->tag));
        responseNode->size = ResponseSize;
        NvOsMutexLock( ec->responseMutex );
        NVEC_ENQ( ec->response, responseNode );
        DISP_MESSAGE(("\r\nSendReq ec->responseBegin=0x%x", ec->responseBegin));
        NvOsMutexUnlock( ec->responseMutex );
    }

    NvOsMutexLock( ec->mutex );
    if ( !ec->thread )
        NvEcPrivThreadCreate( ec );
    NvOsMutexUnlock( ec->mutex );

    // Trigger EcPrivThread
    NvOsSemaphoreSignal( ec->sema );
    DISP_MESSAGE(("\r\nSendReq requestNode=0x%x, requestNode->responseNode=0x%x",
        requestNode, requestNode->responseNode));
    // Wait on Request returns
    NvOsSemaphoreWait( requestSema );
    DISP_MESSAGE(("\r\nSendReq Out of req sema"));

    e = requestNode->status;
    if ( NvSuccess != e )
    {
        NvEcResponseNode    *t = NULL, *p = NULL;

        // de-queue responseNode too !!!!
        NvOsMutexLock( ec->responseMutex );
        NVEC_REMOVE_FROM_Q( ec->response, responseNode, t, p );
        DISP_MESSAGE(("\r\nSendReq responseBegin=0x%x", ec->responseBegin));
        NvOsMutexUnlock( ec->responseMutex );
        goto fail;
    }

    if ( pResponse )
    {
        // Wait on Response returns
        NvOsSemaphoreWait( responseSema );
        DISP_MESSAGE(("\r\nSendReq Out of resp sema"));
        NV_CHECK_ERROR_CLEANUP( responseNode->status );
        NvOsMemcpy(pResponse, &responseNode->response, ResponseSize);
    }
    // if successful, nodes should be de-queue already but not freed yet

fail:
    NvOsSemaphoreDestroy( requestSema );
    NvOsSemaphoreDestroy( responseSema );
    DISP_MESSAGE(("\r\nSendReq Freeing requestNode=0x%x, responseNode=0x%x", 
        requestNode, responseNode));
    NvOsFree( requestNode );
    NvOsFree( responseNode );
    return e;
}
Example #10
0
static int nvec_battery_probe(struct nvec_device *pdev)
{
	int i, rc;
	NvError ErrorStatus = NvSuccess;
	NvBool result = NV_FALSE;

	batt_dev = kzalloc(sizeof(struct tegra_battery_dev), GFP_KERNEL);
	if (!batt_dev) {
		pr_err("nvec_battery_probe:NOMEM\n");
		return -ENOMEM;
	}

	ErrorStatus = NvOsMutexCreate(&batt_dev->hBattEventMutex);
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsMutexCreate Failed!\n");
		goto Cleanup;
	}

	ErrorStatus = NvOsSemaphoreCreate(&batt_dev->hOdmSemaphore, 0);
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsSemaphoreCreate Failed!\n");
		goto Cleanup;
	}
/*Henry++ adjust thread to be createn at last
	batt_dev->exitThread = NV_FALSE;
	batt_dev->inSuspend  = NV_FALSE;
	ErrorStatus = NvOsThreadCreate(NvBatteryEventHandlerThread,
					batt_dev,
					&(batt_dev->hBattEventThread));
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsThreadCreate FAILED\n");
		goto Cleanup;
	}
*/

//Henry add retry when fail ****
for(i=0;i<BATTERY_RETRY_TIMES;i++){
	result = NvOdmBatteryDeviceOpen(&(batt_dev->hOdmBattDev),
		(NvOdmOsSemaphoreHandle *)&batt_dev->hOdmSemaphore);
	if (!result || !batt_dev->hOdmBattDev) {
		pr_err("NvOdmBatteryDeviceOpen FAILED,retry i=%i\n",i);
		NvOsWaitUS(10000);
		continue;
	}
	else{
		break;
	}
}
if(i==BATTERY_RETRY_TIMES){
	pr_err("NvOdmBatteryDeviceOpen FAILED\n");	
	goto Cleanup;
}
//******************************
    
	for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
		if (power_supply_register(&pdev->dev, &tegra_power_supplies[i]))
			pr_err("Failed to register power supply\n");
	}

	batt_dev->batt_status_poll_period = NVBATTERY_POLLING_INTERVAL;

	rc = device_create_file(&pdev->dev, &tegra_battery_attr);
	if (rc) {
		for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
			power_supply_unregister(&tegra_power_supplies[i]);
		}

		pr_err("nvec_battery_probe:device_create_file FAILED");
		goto Cleanup;
	}

//Henry++ adjust thread to be createn at last
	batt_dev->exitThread = NV_FALSE;
	batt_dev->inSuspend  = NV_FALSE;
	ErrorStatus = NvOsThreadCreate(NvBatteryEventHandlerThread,
					batt_dev,
					&(batt_dev->hBattEventThread));
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsThreadCreate FAILED\n");
		goto Cleanup;
	}

	return 0;

Cleanup:
	batt_dev->exitThread = NV_TRUE;
	if (batt_dev->hOdmSemaphore) {
		NvOsSemaphoreSignal(batt_dev->hOdmSemaphore);
		NvOsSemaphoreDestroy(batt_dev->hOdmSemaphore);
		batt_dev->hOdmSemaphore = NULL;
	}

	if (batt_dev->hBattEventThread) {
		NvOsThreadJoin(batt_dev->hBattEventThread);
	}
    
	if (batt_dev->hBattEventMutex) {    
		NvOsMutexDestroy(batt_dev->hBattEventMutex);
		batt_dev->hBattEventMutex = NULL;
	}

	if (batt_dev->hOdmBattDev) {
		NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev);
		batt_dev->hOdmBattDev = NULL;
	}

	kfree(batt_dev);
	batt_dev = NULL;
	//return -1;
   return 0;  //henry++ workaround system can't enter suspend
}
Example #11
0
NvError
NvRmPowerRegister(
    NvRmDeviceHandle hRmDeviceHandle,
    NvOsSemaphoreHandle hEventSemaphore,
    NvU32* pClientId)
{
    NvU32 FreeIndex;
    NvError error;
    NvOsSemaphoreHandle hSema = NULL;
    NvRmPowerClient* pNewClient = NULL;
    NvRmPowerRegistry* pRegistry = &s_PowerRegistry;

    NV_ASSERT(hRmDeviceHandle);
    NV_ASSERT(pClientId);

    // If non-zero semaphore handle is passed, duplicate it to be avialable
    // after the call. Abort registration if non-zero handle is invalid
    if (hEventSemaphore != NULL)
    {
        error = NvOsSemaphoreClone(hEventSemaphore, &hSema);
        if (error != NvSuccess)
        {
            NV_ASSERT(!" Power Register Semaphore Clone error. ");
        }
    }

    NvOsMutexLock(s_hPowerClientMutex);

    // Find free registry entry for the new client
    for (FreeIndex = 0; FreeIndex < pRegistry->UsedIndexRange; FreeIndex++)
    {
        if (pRegistry->pPowerClients[FreeIndex] == NULL)
            break;
    }
    if (FreeIndex == pRegistry->AvailableEntries)
    {
        // If all avilable entries are used, re-size registry array
        NvU32 entries = pRegistry->AvailableEntries +
            NVRM_POWER_REGISTRY_DELTA;
        size_t s = sizeof(*pRegistry->pPowerClients) * (size_t)entries;
        NvRmPowerClient** p = NvOsRealloc(pRegistry->pPowerClients, s);
        if (p == NULL)
        {
            NvU32 old_size;

            /* fall back to NvOsAlloc */
            p = NvOsAlloc( s );
            if( p == NULL )
            {
                goto failed;
            }

            /* copy the old data, free, etc, */
            old_size = sizeof(*pRegistry->pPowerClients) *
                pRegistry->AvailableEntries;

            NvOsMemcpy( p, pRegistry->pPowerClients, old_size );
            NvOsFree( pRegistry->pPowerClients );
        }
        pRegistry->pPowerClients = p;
        pRegistry->AvailableEntries = entries;
    }
    if (FreeIndex == pRegistry->UsedIndexRange)
    {
        // If reached used index range boundary, advance it
        pRegistry->UsedIndexRange++;
    }

    // Allocate and store new client record pointer in registry (null-pointer
    // marks registry entry as free, so it's OK to store it before error check)
    pNewClient = NvOsAlloc(sizeof(*pNewClient));
    pRegistry->pPowerClients[FreeIndex] = pNewClient;
    if (pNewClient == NULL)
    {
        goto failed;
    }

    // Fill in new client entry
    pNewClient->hEventSemaphore = hSema;
    pNewClient->Event = NvRmPowerEvent_NoEvent;
    pNewClient->pVoltageReqHead = NULL;
    pNewClient->pClockReqHead = NULL;
    pNewClient->pStarvationHints = NULL;
    pNewClient->tag = *pClientId;

    /*
     * Combine index with client pointer into registration ID returned to the
     * client. This will make it a little bit more difficult for not-registered
     * clients to guess/re-use IDs
     */
    pNewClient->id = NVRM_POWER_INDEX2ID(FreeIndex, (NvU32)pClientId);
    *pClientId = pNewClient->id;

    NvOsMutexUnlock(s_hPowerClientMutex);
    return NvSuccess;

failed:
    NvOsFree(pNewClient);
    NvOsSemaphoreDestroy(hSema);
    NvOsMutexUnlock(s_hPowerClientMutex);
    return NvError_InsufficientMemory;
}
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;
    }
}
Example #13
0
void NvOdmOsSemaphoreDestroy(NvOdmOsSemaphoreHandle semaphore)
{
    NvOsSemaphoreDestroy((NvOsSemaphoreHandle)semaphore);
}
void
NvDdkUsbPhyClose(
    NvDdkUsbPhyHandle hUsbPhy)
{
    if (!hUsbPhy)
        return;

    NvOsMutexLock(s_UsbPhyMutex);

    if (!hUsbPhy->RefCount)
    {
        NvOsMutexUnlock(s_UsbPhyMutex);
        return;
    }

    --hUsbPhy->RefCount;

    if (hUsbPhy->RefCount)
    {
        NvOsMutexUnlock(s_UsbPhyMutex);
        return;
    }

    NvRmSetModuleTristate(
        hUsbPhy->hRmDevice,
        NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
        NV_TRUE);

    NvOsMutexLock(hUsbPhy->ThreadSafetyMutex);
    if (hUsbPhy->RmPowerClientId)
    {
        if (hUsbPhy->IsPhyPoweredUp)
        {
            NV_ASSERT_SUCCESS(
                NvRmPowerModuleClockControl(hUsbPhy->hRmDevice,
                  NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
                  hUsbPhy->RmPowerClientId,
                  NV_FALSE));

            //NvOsDebugPrintf("NvDdkUsbPhyClose::VOLTAGE OFF\n");
            NV_ASSERT_SUCCESS(
                NvRmPowerVoltageControl(hUsbPhy->hRmDevice,
                  NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
                  hUsbPhy->RmPowerClientId,
                  NvRmVoltsOff, NvRmVoltsOff,
                  NULL, 0, NULL));
            hUsbPhy->IsPhyPoweredUp = NV_FALSE;
        }
        // Unregister driver from Power Manager
        NvRmPowerUnRegister(hUsbPhy->hRmDevice, hUsbPhy->RmPowerClientId);
        NvOsSemaphoreDestroy(hUsbPhy->hPwrEventSem);
    }
    NvOsMutexUnlock(hUsbPhy->ThreadSafetyMutex);

    NvOsMutexDestroy(hUsbPhy->ThreadSafetyMutex);

    if (hUsbPhy->CloseHwInterface)
    {
        hUsbPhy->CloseHwInterface(hUsbPhy);
    }

    if ((hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_Host) ||
        (hUsbPhy->pProperty->UsbMode == NvOdmUsbModeType_OTG))
    {
        UsbPrivEnableVbus(hUsbPhy, NV_FALSE);
    }

    NvOdmEnableUsbPhyPowerRail(NV_FALSE);

    NvRmPhysicalMemUnmap(
        (void*)hUsbPhy->UsbVirAdr, hUsbPhy->UsbBankSize);

    NvRmPhysicalMemUnmap(
        (void*)hUsbPhy->MiscVirAdr, hUsbPhy->MiscBankSize);

    NvOsMemset(hUsbPhy, 0, sizeof(NvDdkUsbPhy));
    NvOsMutexUnlock(s_UsbPhyMutex);
}
NvError
NvEcOpen(NvEcHandle *phEc,
         NvU32 InstanceId)
{
    NvEc            *hEc = NULL;
    NvU32           i;
    NvEcPrivState   *ec = &g_ec;
    NvOsMutexHandle mutex = NULL;
    NvError         e = NvSuccess;

    NV_ASSERT( phEc );

    if ( NULL == ec->mutex )
    {
        e = NvOsMutexCreate(&mutex);
        if (NvSuccess != e)
            return e;
        if (0 != NvOsAtomicCompareExchange32((NvS32*)&ec->mutex, 0,
                                                        (NvS32)mutex) )
            NvOsMutexDestroy( mutex );
    }

    NvOsMutexLock(ec->mutex);

    if ( !s_refcount )
    {
        mutex = ec->mutex;
        NvOsMemset( ec, 0, sizeof(NvEcPrivState) );
        ec->mutex = mutex;
        
        NV_CHECK_ERROR_CLEANUP( NvOsMutexCreate( &ec->requestMutex ));
        NV_CHECK_ERROR_CLEANUP( NvOsMutexCreate( &ec->responseMutex ));
        NV_CHECK_ERROR_CLEANUP( NvOsMutexCreate( &ec->eventMutex ));
        
        NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &ec->sema, 0));
        NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &ec->LowPowerEntrySema, 0));
        NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &ec->LowPowerExitSema, 0));
        
        NV_CHECK_ERROR_CLEANUP( NvEcTransportOpen( &ec->transport, InstanceId,
            ec->sema, 0 ) );
    }

    // Set this flag as TRUE to indicate power is enabled
    ec->powerState = NV_TRUE;

    // create private handle for internal communications between NvEc driver
    // and EC
    if ( !s_refcount )
    {
        ec->hEc = NvOsAlloc( sizeof(NvEc) );
        if ( NULL == ec->hEc )
            goto clean;
        
        // reserve the zero tag for internal use by the nvec driver; this ensures
        // that the driver always has a requestor tag available and can therefore
        // always talk to the EC
        ec->tagAllocated[0] = NV_TRUE;
        ec->hEc->ec = ec;
        ec->hEc->tag = 0;

        NV_CHECK_ERROR_CLEANUP(NvOsSemaphoreCreate(&ec->hPingSema, 0));

        // perform startup operations before mutex is unlocked
        NV_CHECK_ERROR_CLEANUP( NvEcPrivInitHook(ec->hEc) );

        // start thread to send "pings" - no-op commands to keep EC "alive"
        NV_CHECK_ERROR_CLEANUP(NvOsThreadCreate(
            (NvOsThreadFunction)NvEcPrivPingThread, ec, &ec->hPingThread));
    }

    hEc = NvOsAlloc( sizeof(NvEc) );
    if ( NULL == hEc )
        goto clean;

    NvOsMemset(hEc, 0x00, sizeof(NvEc));

    hEc->ec = ec;

    hEc->tag = NVEC_REQUESTOR_TAG_INVALID;
    for ( i = 0; i < NVEC_MAX_REQUESTOR_TAG; i++ )
    {
        if ( !ec->tagAllocated[i] )
        {
            ec->tagAllocated[i] = NV_TRUE;
            hEc->tag = i;
            break;
        }
    }
    if ( NVEC_REQUESTOR_TAG_INVALID == hEc->tag )
        goto clean;      // run out of tag, clean it up!

    *phEc = hEc;
    s_refcount++;

    NvOsMutexUnlock( ec->mutex );

    ec->IsEcActive = NV_FALSE;

    return NvSuccess;

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

    return NvError_InsufficientMemory;

fail:
    if (!s_refcount)
    {
        ec->exitPingThread = NV_TRUE;
        if (ec->hPingSema)
            NvOsSemaphoreSignal( ec->hPingSema );
        NvOsThreadJoin( ec->hPingThread );
        NvOsSemaphoreDestroy(ec->hPingSema);
        ec->exitThread = NV_TRUE;
        if (ec->sema)
            NvOsSemaphoreSignal( ec->sema );
        NvOsThreadJoin( ec->thread );
        NvOsFree( ec->hEc );
        if ( ec->transport )
            NvEcTransportClose( ec->transport );
        NvOsMutexDestroy( ec->requestMutex );
        NvOsMutexDestroy( ec->responseMutex );
        NvOsMutexDestroy( ec->eventMutex );
        NvOsSemaphoreDestroy( ec->sema );
        NvOsSemaphoreDestroy( ec->LowPowerEntrySema );
        NvOsSemaphoreDestroy( ec->LowPowerExitSema );
        if ( ec->mutex )
        {
            NvOsMutexUnlock( ec->mutex );
            // Destroying of this mutex here is not safe, if another thread is
            // waiting on this mutex, it can cause issues.  We shold have
            // serialized Init/DeInit calls for creating and destroying this mutex.
            NvOsMutexDestroy( ec->mutex );
            NvOsMemset( ec, 0, sizeof(NvEcPrivState) );
            ec->mutex = NULL;
        }
    }
    return NvError_NotInitialized;
}
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;
    }
}
Example #17
0
static int nvec_battery_probe(struct nvec_device *pdev)
{
	int i, rc;
	NvError ErrorStatus = NvSuccess;
	NvBool result = NV_FALSE;

	batt_dev = kzalloc(sizeof(struct tegra_battery_dev), GFP_KERNEL);
	if (!batt_dev) {
		pr_err("nvec_battery_probe:NOMEM\n");
		return -ENOMEM;
	}

	ErrorStatus = NvOsSemaphoreCreate(&batt_dev->hOdmSemaphore, 0);
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsSemaphoreCreate Failed!\n");
		goto Cleanup;
	}

	batt_dev->exitThread = NV_FALSE;
	ErrorStatus = NvOsThreadCreate(NvBatteryEventHandlerThread,
					batt_dev,
					&(batt_dev->hBattEventThread));
	if (NvSuccess != ErrorStatus) {
		pr_err("NvOsThreadCreate FAILED\n");
		goto Cleanup;
	}

	result = NvOdmBatteryDeviceOpen(&(batt_dev->hOdmBattDev),
		(NvOdmOsSemaphoreHandle *)&batt_dev->hOdmSemaphore,
		&(batt_dev->ec_version)); //Daniel 20100823, put ec version to fs.
	if (!result || !batt_dev->hOdmBattDev) {
		pr_err("NvOdmBatteryDeviceOpen FAILED\n");
		goto Cleanup;
	}

	for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
		if (power_supply_register(&pdev->dev, &tegra_power_supplies[i]))
			pr_err("Failed to register power supply\n");
	}

	batt_dev->batt_status_poll_period = NVBATTERY_POLLING_INTERVAL_MILLISECS;
	setup_timer(&(batt_dev->battery_poll_timer), tegra_battery_poll_timer_func, 0);
	mod_timer(&(batt_dev->battery_poll_timer),
		jiffies + msecs_to_jiffies(batt_dev->batt_status_poll_period));

	rc = device_create_file(&pdev->dev, &tegra_battery_attr);
	rc = device_create_file(&pdev->dev, &tegra_battery_version); //Daniel 20100823, put ec version to fs
	if (rc) {
		for (i = 0; i < ARRAY_SIZE(tegra_power_supplies); i++) {
			power_supply_unregister(&tegra_power_supplies[i]);
		}

		del_timer_sync(&(batt_dev->battery_poll_timer));

		pr_err("nvec_battery_probe:device_create_file FAILED");
		goto Cleanup;
	}

	return 0;

Cleanup:
	batt_dev->exitThread = NV_TRUE;
	if (batt_dev->hOdmSemaphore) {
		NvOsSemaphoreSignal(batt_dev->hOdmSemaphore);
		NvOsSemaphoreDestroy(batt_dev->hOdmSemaphore);
		batt_dev->hOdmSemaphore = NULL;
	}

	if (batt_dev->hBattEventThread) {
		NvOsThreadJoin(batt_dev->hBattEventThread);
	}

	if (batt_dev->hOdmBattDev) {
		NvOdmBatteryDeviceClose(batt_dev->hOdmBattDev);
		batt_dev->hOdmBattDev = NULL;
	}

	kfree(batt_dev);
	batt_dev = NULL;
	return -1;
}