diff -r 000000000000 -r c40eb8fe8501 wlan_bearer/wlanldd/wlan_symbian/wlanldd_symbian/src/MgmtFrameMemMngr.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wlan_bearer/wlanldd/wlan_symbian/wlanldd_symbian/src/MgmtFrameMemMngr.cpp Tue Feb 02 02:03:13 2010 +0200 @@ -0,0 +1,622 @@ +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of the MgmtFrameMemMngr class. +* +*/ + +/* +* %version: 19 % +*/ + +#include "WlLddWlanLddConfig.h" +#include "MgmtFrameMemMngr.h" +#include "osachunk.h" +#include + +extern TAny* os_alloc( const TUint32 ); +extern void os_free( const TAny* ); + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt MgmtFrameMemMngr::DoAllocate( DChunk*& aSharedMemoryChunk ) + { + TraceDump( INIT_LEVEL, + ("WLANLDD: MgmtFrameMemMngr::DoAllocate:") ); + + // determine if cached memory shall be used + TUint cacheOption = iUseCachedMemory ? + EMapAttrCachedMax : + EMapAttrFullyBlocking; + + // Start creating the chunk + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = iChunkSize; + info.iMapAttr = EMapAttrReadUser | + EMapAttrWriteUser | + EMapAttrShared | + cacheOption; + info.iOwnsMemory = ETrue; + info.iDestroyedDfc = NULL; + + DChunk* chunk; + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: create chunk of size: %d"), + iChunkSize) ); + + TUint32 chunkMapAttrNotNeeded ( 0 ); + + // Enter critical section so we can't die and leak the object we are + // creating, i.e. DChunk (shared memory chunk) + NKern::ThreadEnterCS(); + + TInt r = Kern::ChunkCreate( + info, + chunk, + iChunkKernelAddr, + chunkMapAttrNotNeeded ); + + if( r != KErrNone) + { + TraceDump( WARNING_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: create chunk failed. Status: %d"), + r ) ); + + NKern::ThreadLeaveCS(); + return r; + } + + TraceDump(MEMORY, (("WLANLDD: new DChunk: 0x%08x"), + reinterpret_cast(chunk))); + + TraceDump(INIT_LEVEL, + (("MgmtFrameMemMngr::DoAllocate: Platform Hw Chunk create success with cacheOption: 0x%08x"), + cacheOption)); + + TUint32 physicalAddressNotNeeded ( 0 ); + + // Map our device's memory into the chunk (at offset 0) + r = Kern::ChunkCommitContiguous( chunk, 0, iChunkSize, physicalAddressNotNeeded ); + + if ( r != KErrNone) + { + TraceDump( WARNING_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: chunk commit failed. Status: %d"), + r ) ); + + // Commit failed so tidy-up. + // Close chunk, which will then get deleted at some point + Kern::ChunkClose( chunk ); + } + else + { + TraceDump( INIT_LEVEL, + ("WLANLDD: MgmtFrameMemMngr::DoAllocate: chunk commit success") ); + + // Commit succeeded so pass back the chunk pointer + aSharedMemoryChunk = chunk; + } + + // Can leave critical section now that we have saved pointer to created object + NKern::ThreadLeaveCS(); + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: chunk map attr: %d"), + chunkMapAttrNotNeeded ) ); + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: iChunkKernelAddr: 0x%08x"), + static_cast(iChunkKernelAddr) ) ); + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoAllocate: chunk physical address: 0x%08x"), + physicalAddressNotNeeded ) ); + + return r; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt MgmtFrameMemMngr::DoOpenHandle( + DThread& aThread, + TSharedChunkInfo& aSharedChunkInfo, + DChunk* aSharedMemoryChunk ) + { + TInt ret ( KErrGeneral ); + + if ( aSharedMemoryChunk ) + { + + // Need to be in critical section while creating handles + NKern::ThreadEnterCS(); + + // Create handle to shared memory chunk for client thread + TInt r = Kern::MakeHandleAndOpen( &aThread, aSharedMemoryChunk ); + + // Leave critical section + NKern::ThreadLeaveCS(); + + // positive r value is a handle, negative value is an error code + if( r >= 0 ) + { + // mapping success + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::OnInitialiseMemory: Handle create & open ok: handle: %d"), + r ) ); + + // store the handle & the chunk size + aSharedChunkInfo.iChunkHandle = r; + aSharedChunkInfo.iSize = iChunkSize; + + // store the kernel addresses + + TUint8* start_of_mem = reinterpret_cast(iChunkKernelAddr ); + + const TUint KRxDataChunkSize( + iChunkSize + - ( sizeof( TDataBuffer ) + + KMgmtSideTxBufferLength + + KProtocolStackSideTxDataChunkSize + + sizeof( RFrameXferBlock ) + + sizeof( RFrameXferBlockProtocolStack ) ) ); + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoOpenHandle: KRxDataChunkSize: %d"), + KRxDataChunkSize ) ); + + iRxDataChunk = start_of_mem; + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoOpenHandle: iRxDataChunk start addr: 0x%08x"), + reinterpret_cast(iRxDataChunk) ) ); + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoOpenHandle: iRxDataChunk end addr: 0x%08x"), + reinterpret_cast(iRxDataChunk + KRxDataChunkSize) ) ); + + // create the Rx frame memory pool manager + iRxFrameMemoryPool = new WlanChunk( + iRxDataChunk, + iRxDataChunk + KRxDataChunkSize, + iRxFrameBufAllocationUnit ); + + if ( iRxFrameMemoryPool && iRxFrameMemoryPool->IsValid() ) + { + ret = KErrNone; + + TraceDump(MEMORY, (("WLANLDD: new WlanChunk: 0x%08x"), + reinterpret_cast(iRxFrameMemoryPool))); + + iTxDataBuffer = reinterpret_cast( + start_of_mem + + KRxDataChunkSize ); + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoOpenHandle: Engine TxDataBuf start addr: 0x%08x"), + reinterpret_cast(iTxDataBuffer) ) ); + + // for the single Tx buffer the actual buffer memory immediately + // follows the Tx frame meta header + iTxDataBuffer->KeSetBufferOffset( sizeof( TDataBuffer ) ); + + iFrameXferBlock = reinterpret_cast( + start_of_mem + + KRxDataChunkSize + + sizeof( TDataBuffer ) + + KMgmtSideTxBufferLength + + KProtocolStackSideTxDataChunkSize ); + + TraceDump( INIT_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::DoOpenHandle: Engine RFrameXferBlock addr: 0x%08x"), + reinterpret_cast(iFrameXferBlock) ) ); + + // initiliase xfer block + iFrameXferBlock->Initialize( KMgmtSideTxBufferLength ); + + iRxBufAlignmentPadding = RxBufAlignmentPadding(); + + iParent.SetRxBufAlignmentPadding( iRxBufAlignmentPadding ); + } + else + { + // create failed + delete iRxFrameMemoryPool; + iRxFrameMemoryPool = NULL; + // error is returned + } + } + else + { + // handle creation & open failed. Error is returned + + TraceDump( INIT_LEVEL | ERROR_LEVEL, + (("WLANLDD: MgmtFrameMemMngr::OnInitialiseMemory: Handle create & open error: %d"), + r ) ); + } + } + else + { + // at this point the shared memory chunk should always exist. However, + // as it doesn't exist in this case, we return an error + + TraceDump( INIT_LEVEL | ERROR_LEVEL, + ("WLANLDD: MgmtFrameMemMngr::OnInitialiseMemory: Error aSharedMemoryChunk is NULL") ); + } + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint8* MgmtFrameMemMngr::DoGetNextFreeRxBuffer( TUint aLengthinBytes ) + { + TraceDump( RX_FRAME, + ("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer") ); + + // if there are any Rx buffers which have been handled and + // can already be re-used, free them first + + const TUint32* rxHandledBuffersArray ( NULL ); + TUint32 numOfHandled ( 0 ); + + iFrameXferBlock->KeGetHandledRxBuffers( + rxHandledBuffersArray, + numOfHandled ); + + if ( numOfHandled ) + { + // there are buffers which can be freed, so free them + for ( TUint i = 0; i < numOfHandled; ++i ) + { + // first free the actual Rx frame buffer + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer: free Rx buf at addr: 0x%08x"), + reinterpret_cast(reinterpret_cast( + iRxDataChunk + + rxHandledBuffersArray[i])->KeGetBufferStart()) ) ); + + iRxFrameMemoryPool->Free( + reinterpret_cast( + iRxDataChunk + rxHandledBuffersArray[i])->KeGetBufferStart() + // take into account the alignment padding + - iRxBufAlignmentPadding ); + + // then free the Rx frame meta header + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer: free Rx meta header at addr: 0x%08x"), + reinterpret_cast( iRxDataChunk + rxHandledBuffersArray[i])) ); + + iRxFrameMemoryPool->Free( iRxDataChunk + rxHandledBuffersArray[i] ); + } + + // remove the buffers we freed above from the completed buffers of this + // object so that they are not tried to be freed again once the Mgmt + // Client issues the next Rx request + + iCountCompleted -= numOfHandled; + assign( + iCompletedBuffers + numOfHandled, + iCompletedBuffers, + iCountCompleted ); + } + + // reserve a new Rx buffer. + + TUint8* buffer ( NULL ); + + if ( iRxFrameMemoryPool ) + { + buffer = reinterpret_cast(iRxFrameMemoryPool->Alloc( + aLengthinBytes + + iRxBufAlignmentPadding, + EFalse ) ); // no need to zero stamp the buffer content + + if ( buffer ) + { + // allocation succeeded + + // the alignment padding is before the Rx buffer + buffer += iRxBufAlignmentPadding; + + TraceDump(RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer: addr of allocated Rx buf: 0x%08x"), + reinterpret_cast(buffer)) ); + } + else + { + TraceDump(RX_FRAME | WARNING_LEVEL, + ("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer: WARNING: not enough free memory => failed")); + } + } + else + { + TraceDump(RX_FRAME | WARNING_LEVEL, + ("WLANLDD: MgmtFrameMemMngr::DoGetNextFreeRxBuffer: WARNING: no Rx mem pool mgr => failed")); + } + + return buffer; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TBool MgmtFrameMemMngr::DoEthernetFrameRxComplete( + const TDataBuffer*& aBufferStart, + TUint32 aNumOfBuffers ) + { + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: aNumOfBuffers: %d"), + aNumOfBuffers) ); + + if ( aNumOfBuffers + iCountTobeCompleted > KMaxToBeCompletedRxBufs ) + { + // too little space reserved for Rx buffer handles + os_assert( (TUint8*)("WLANLDD: panic"), (TUint8*)(WLAN_FILE), __LINE__ ); + } + + TBool ret( EFalse ); + + if ( iReadStatus == EPending ) + { + // read pending + if ( !iCountTobeCompleted ) + { + // no existing Rx buffers to complete in queue + // we may complete these ones on the fly + + // note the completed Rx buffers first so that we can change + // their addresses to offsets + assign( + reinterpret_cast(&aBufferStart), + iCompletedBuffers, + aNumOfBuffers ); + + // update the new Rx buffer start addresses added above to be + // offsets from the Rx memory pool beginning + for( TUint i = 0; i < aNumOfBuffers; ++i ) + { + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: supplied Rx buf addr: 0x%08x"), + iCompletedBuffers[i]) ); + + iCompletedBuffers[i] + -= reinterpret_cast(iRxDataChunk); + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: Rx buf offset addr: 0x%08x"), + iCompletedBuffers[i]) ); + } + + iCountCompleted = aNumOfBuffers; + + iFrameXferBlock->KeRxComplete( iCompletedBuffers, iCountCompleted); + } + else + { + // existing rx buffers to complete in queue. + // We must append these at the rear and after that + // complete the existing read request + assign( + reinterpret_cast(&aBufferStart), + iTobeCompletedBuffers + iCountTobeCompleted, + aNumOfBuffers ); + + // update the new Rx buffer start addresses added above to be + // offsets from the Rx memory pool beginning + for( TUint i = 0; i < aNumOfBuffers; ++i ) + { + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: supplied Rx buf addr: 0x%08x"), + iTobeCompletedBuffers[iCountTobeCompleted + i]) ); + + iTobeCompletedBuffers[iCountTobeCompleted + i] + -= reinterpret_cast(iRxDataChunk); + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: Rx buf offset addr: 0x%08x"), + iTobeCompletedBuffers[iCountTobeCompleted + i]) ); + } + + iCountCompleted = iCountTobeCompleted + aNumOfBuffers; + + iFrameXferBlock->KeRxComplete( + iTobeCompletedBuffers, + iCountCompleted ); + + // note the completed Rx buffers + assign( iTobeCompletedBuffers, iCompletedBuffers, iCountCompleted ); + iCountTobeCompleted = 0; + } + + ret = ETrue; + } + else + { + // no read pending + // append at the rear + assign( + reinterpret_cast(&aBufferStart), + iTobeCompletedBuffers + iCountTobeCompleted, + aNumOfBuffers ); + + // update the new Rx buffer start addresses added above to be + // offsets from the Rx memory pool beginning + for( TUint i = 0; i < aNumOfBuffers; ++i ) + { + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: supplied Rx buf addr: 0x%08x"), + iTobeCompletedBuffers[iCountTobeCompleted + i]) ); + + iTobeCompletedBuffers[iCountTobeCompleted + i] + -= reinterpret_cast(iRxDataChunk); + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: Rx buf offset addr: 0x%08x"), + iTobeCompletedBuffers[iCountTobeCompleted + i]) ); + } + + iCountTobeCompleted += aNumOfBuffers; + } + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: end: iCountCompleted: %d"), + iCountCompleted) ); + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoEthernetFrameRxComplete: end: iCountTobeCompleted: %d"), + iCountTobeCompleted) ); + + return ret; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint32* MgmtFrameMemMngr::DoGetTobeCompletedBuffersStart() + { + return iTobeCompletedBuffers; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TUint32* MgmtFrameMemMngr::DoGetCompletedBuffersStart() + { + return iCompletedBuffers; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void MgmtFrameMemMngr::DoFreeRxBuffers() + { + if ( IsMemInUse() ) + { + for ( TUint i = 0; i < iCountCompleted; ++i ) + { + TDataBuffer* metaHdr ( reinterpret_cast( + iRxDataChunk + iCompletedBuffers[i]) ); + + // first free the actual Rx frame buffer + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoFreeRxBuffers: free Rx buf at addr: 0x%08x"), + reinterpret_cast(metaHdr->KeGetBufferStart()) ) ); + + iRxFrameMemoryPool->Free( + metaHdr->KeGetBufferStart() + // take into account the alignment padding + - iRxBufAlignmentPadding ); + + // free the Rx frame meta header + + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoFreeRxBuffers: free Rx meta header at addr: 0x%08x"), + reinterpret_cast(metaHdr)) ); + + iRxFrameMemoryPool->Free( metaHdr ); + } + } + else + { + // the whole Rx memory pool has already been deallocated, so nothing + // is done in this case + TraceDump( RX_FRAME, + ("WLANLDD: MgmtFrameMemMngr::DoFreeRxBuffers: Rx memory pool already deallocated; no action needed") ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void MgmtFrameMemMngr::DoMarkRxBufFree( TUint8* aBufferToFree ) + { + TraceDump( RX_FRAME, + (("WLANLDD: MgmtFrameMemMngr::DoMarkRxBufFree: free Rx buf at addr: 0x%08x"), + reinterpret_cast(aBufferToFree) ) ); + + if ( IsMemInUse() ) + { + iRxFrameMemoryPool->Free( + aBufferToFree + // take into account the alignment padding + - iRxBufAlignmentPadding ); + } + else + { + // the whole Rx memory pool - including aBufferToFree - has already + // been deallocated, so nothing is done in this case + TraceDump( RX_FRAME, + ("WLANLDD: MgmtFrameMemMngr::DoMarkRxBufFree: Rx memory pool already deallocated; no action needed") ); + } + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +TInt MgmtFrameMemMngr::RxBufAlignmentPadding() const + { + const TInt KMemMgrHdrLen = iRxFrameMemoryPool->HeaderSize(); + const TInt KRemainder ( KMemMgrHdrLen % iRxFrameBufAllocationUnit ); + TInt padding = KRemainder ? + ( iRxFrameBufAllocationUnit - KRemainder ) : KRemainder; + + TraceDump(INIT_LEVEL, (("WLANLDD: MgmtFrameMemMngr::RxBufAlignmentPadding: %d"), + padding)); + + return padding; + } + +// --------------------------------------------------------------------------- +// +// --------------------------------------------------------------------------- +// +void MgmtFrameMemMngr::OnReleaseMemory() + { + TraceDump(INIT_LEVEL, ("WLANLDD: MgmtFrameMemMngr::OnReleaseMemory")); + + TraceDump(MEMORY, (("WLANLDD: delete WlanChunk: 0x%08x"), + reinterpret_cast(iRxFrameMemoryPool))); + + delete iRxFrameMemoryPool; + iRxFrameMemoryPool = NULL; + + if ( iParent.SharedMemoryChunk() ) + { + TraceDump(MEMORY, (("WLANLDD: delete DChunk: 0x%08x"), + reinterpret_cast(iParent.SharedMemoryChunk()))); + + // schedule the shared memory chunk for destruction + Kern::ChunkClose( iParent.SharedMemoryChunk() ); + iParent.SharedMemoryChunk() = NULL; + MarkMemFree(); // mark as free + } + else + { + // nothing here + } + }