/* Process receive response and update individual timeout */
static NvError
NvEcPrivProcessReceiveResponse( NvEcPrivState *ec,
                                NvError       transportStatus )
{
    NvError             e = NvSuccess;
    NvEcResponse        packet;
    NvEcResponseNode    *responseNode = NULL;
    NvU32               size;

    // FIXME: remove this extra copying and buffering for optimization
    NV_CHECK_ERROR( NvEcTransportGetReceivePacket( ec->transport,
                                &packet, sizeof(NvEcResponse) ) );
                                // nothing we can do here if error!

    NvEcPrivFindAndDequeueResponse( ec, &packet, &responseNode);
    if ( responseNode )
    {
        size = responseNode->size;
        if ( size > sizeof(NvEcResponse) )
            size = sizeof(NvEcResponse);
        NvOsMemcpy( &responseNode->response, &packet, size );
        responseNode->status = transportStatus;
        NvOsSemaphoreSignal(responseNode->sema);
            // all response stuff should be completed before signalling
    }
    else
        e = NvError_BadParameter;
            // will return Bad Param if can't find waiting response

    return e;
}
Пример #2
0
static NvError tegra_transport_set_property(NvAudioFxObjectHandle hObject,
					    NvAudioFxProperty Property,
					    NvU32 Size,
					    void* pProperty)
{
	NvError status = NvSuccess;
	NvError retStatus = NvSuccess;
	NvFxTransportMessageSetProperty message;
	struct completion comp;

	if (FXTRANSPORT_MSG_BUFFER_PROPERTY_SIZE < Size) {
		snd_printk(KERN_ERR "Property length too long!\n");
		goto EXIT_WITH_ERROR;
	}

	init_completion(&comp);
	message.Message = NVFXTRANSPORT_MESSAGE_SET_PROPERTY;
	message.pPrivateData = (void*)&comp;
	message.hObject = hObject;
	message.Property = Property;
	message.Size = Size;
	NvOsMemcpy(message.PropertyData, pProperty, Size);
	message.pReturnError = &retStatus;

	transport_send_message(NvFxTransportMessageSetProperty);
	goto EXIT;

EXIT_WITH_ERROR:
	retStatus = status;

EXIT:
	return retStatus;
}
/* We could potentially re-adjust the internal eventNode queue when there
   is no ready queue to base on accumulated NumEventPacket hint. */
NvError
NvEcGetEvent(
    NvEcEventRegistrationHandle hEcEventRegistration,
    NvEcEvent *pEvent,
    NvU32 EventSize)
{
    NvEcHandle      hEc = hEcEventRegistration->hEc;
    NvEcPrivState   *ec = hEc->ec;
    NvError         e = NvError_InvalidState;
    NvEcEventNode   *eventNode, *t;
    NvU32           tagMask = (1UL << hEc->tag);

    // FIXME: Should change these to assert ???
    if ( !pEvent )
        return NvError_InvalidAddress;

    if ( !hEcEventRegistration )
        return NvError_BadParameter;

    if ( EventSize > sizeof(NvEcEvent) )
        EventSize = sizeof(NvEcEvent);
    else if ( EventSize < NVEC_MIN_EVENT_SIZE )
        return NvError_InvalidSize;

    NvOsMutexLock( ec->eventMutex );
 
    eventNode = ec->eventReadyBegin;
    while ( eventNode )
    {
        // pre advance eventNode since current one could be removed
        t = eventNode;
        eventNode = eventNode->next;
        if ( (hEcEventRegistration->eventBitmap &
                            (1UL << t->event.EventType)) &&
                (t->tagBitmap & tagMask) )
        {
            // only return event with matching client tag set
            NvOsMemcpy( pEvent, &(t->event), EventSize );
            e = NvSuccess;
            t->tagBitmap &= ~tagMask;
            // removed if all registered client has GetEvent(t)
            if ( !t->tagBitmap )
            {
                // In case transport has been nack'ing due to eventFree
                // queue is all used up, signal thread to retrieve
                // queued up event in transport.  eventMutex should
                // synchronize NvEcPrivProcessReceiveEvent properly.
                if ( NULL == ec->eventFreeBegin )
                    NvOsSemaphoreSignal( ec->sema );
                NvEcPrivRemoveEventFromReady( ec, t );
            }
            break;
        }
    }
    
    NvOsMutexUnlock( ec->eventMutex );
    return e;
}
static void
UsbPhyOpenHwInterface(
    NvDdkUsbPhyHandle hUsbPhy)
{
    static NvDdkUsbPhyCapabilities s_UsbPhyCap[] =
    {
        //  AP15
        { NV_FALSE, NV_FALSE },
        //  AP16
        { NV_FALSE, NV_TRUE },
        //  AP20
        { NV_TRUE, NV_FALSE},
    };
    NvDdkUsbPhyCapabilities *pUsbfCap = NULL;
    NvRmModuleCapability s_UsbPhyCaps[] =
    {
        {1, 0, 0, &s_UsbPhyCap[0]},  // AP15 A01
        {1, 1, 0, &s_UsbPhyCap[0]},  // AP15 A02
        {1, 2, 0, &s_UsbPhyCap[1]},  // AP16, USB1
        {1, 3, 0, &s_UsbPhyCap[1]},  // AP16, USB2
        {1, 5, 0, &s_UsbPhyCap[2]}, // AP20, USB1
        {1, 6, 0, &s_UsbPhyCap[2]}, // AP20, USB2
        {1, 7, 0, &s_UsbPhyCap[2]}, // AP20, USB3
    };

    NV_ASSERT_SUCCESS(
        NvRmModuleGetCapabilities(hUsbPhy->hRmDevice,
            NVRM_MODULE_ID(NvRmModuleID_Usb2Otg, hUsbPhy->Instance),
            s_UsbPhyCaps, NV_ARRAY_SIZE(s_UsbPhyCaps),
            (void**)&pUsbfCap));

    // Fill the client capabilities structure.
    NvOsMemcpy(&hUsbPhy->Caps, pUsbfCap, sizeof(NvDdkUsbPhyCapabilities));

    //NvOsDebugPrintf("NvDdkUsbPhyCapabilities::\n");
    //NvOsDebugPrintf("PhyRegInController::[%d] 0-FALSE 1-TRUE\n", hUsbPhy->Caps.PhyRegInController);
    //NvOsDebugPrintf("CommonClockAndReset::[%d] 0-FALSE 1-TRUE\n", hUsbPhy->Caps.CommonClockAndReset);

    if (hUsbPhy->Caps.PhyRegInController)
    {
        //NvOsDebugPrintf("AP20 USB Controllers\n");
        Ap20UsbPhyOpenHwInterface(hUsbPhy);
    }
}
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;
}
Пример #6
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;
}
Пример #7
0
static void AlsaTransportServiceThread(void *arg)
{
	NvError status = NvSuccess;
	static NvFxTransportMessageResultBuffer in;
	NvU32 messageSize = 0;
	int retry = 0;
#define transport_complete(comp)                                               \
	complete((struct completion*)comp);

	while (retry < 5 ) {
		status = NvRmTransportConnect(atrans->hRmTransport,
					TEGRA_TRANSPORT_CONNECT_TIMEOUT);
		if (status == NvSuccess)
			break;
		retry++;
	}

	if (status) {
		snd_printk(KERN_ERR "AlsaTransportServiceThread: Failed to \
			connect to remote end. Giving up ! \n");
		atrans->TransportConnected = 0;
		return;
	}

	atrans->TransportConnected = 1;

	while (!atrans->ShutDown) {
		NvOsSemaphoreWait(atrans->hServiceSema);
		if (atrans->ShutDown)
			break;

		status = NvRmTransportRecvMsg(atrans->hRmTransport,
					&in,
					sizeof(NvFxTransportMessageResultBuffer),
					&messageSize);
		if (status == NvSuccess) {
			switch (in.Message.Message) {
			case NVFXTRANSPORT_MESSAGE_MIXER_OPEN: {
				*in.MixerOpen.phMixer = in.MixerOpen.hMixer;
// 20110223, , media server restart 2 [start]
				*in.MixerOpen.pReturnError = in.MixerOpen.ReturnError;
// 20110223, , media server restart 2 [end]				
				transport_complete(in.MixerOpen.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_MIXER_CLOSE: {
				transport_complete(in.MixerClose.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_CREATE_OBJECT: {
				*in.CreateObject.phObject =
				        in.CreateObject.hObject;
				transport_complete(in.CreateObject.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_DESTROY_OBJECT: {
				transport_complete(in.DestroyObject.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_MAP_BUFFER: {
				*in.MapBuffer.phMixBuffer =
				        in.MapBuffer.hMixBuffer;
				transport_complete(in.MapBuffer.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_UNMAP_BUFFER: {
				transport_complete(in.UnmapBuffer.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_GET_PROPERTY: {
				*in.GetProperty.pReturnError =
				        in.GetProperty.ReturnError;
				if (in.GetProperty.ReturnError == NvSuccess) {
					NvOsMemcpy(in.GetProperty.pProperty,
					           in.GetProperty.PropertyData,
					           in.GetProperty.Size);
				}
				transport_complete(in.GetProperty.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_SET_PROPERTY: {
				*in.SetProperty.pReturnError =
				        in.SetProperty.ReturnError;
				transport_complete(in.SetProperty.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_STREAM_ADD_BUFFER: {
				*in.StreamAddBuffer.pReturnError =
				        in.StreamAddBuffer.ReturnError;
				transport_complete(in.StreamAddBuffer.pPrivateData);
			}
			break;

			default:
				break;
			}
		}
	}

}
Пример #8
0
void NvOdmOsMemcpy(void *dest, const void *src, size_t size)
{
    NvOsMemcpy(dest, src, size);
}