/* 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; }
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*)∁ 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; }
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; }
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; } } } }
void NvOdmOsMemcpy(void *dest, const void *src, size_t size) { NvOsMemcpy(dest, src, size); }