bluetooth/btstack/linkmgr/hostmbufpool.cpp
author hgs
Thu, 23 Sep 2010 17:06:47 +0300
changeset 48 22de2e391156
parent 33 4e80e1b997a8
child 51 20ac952a623c
permissions -rw-r--r--
201036
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     1
// Copyright (c) 1999-2010 Nokia Corporation and/or its subsidiary(-ies).
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     2
// All rights reserved.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     7
//
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     8
// Initial Contributors:
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    10
//
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    11
// Contributors:
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    12
//
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    13
// Description:
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    14
// 
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    15
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    16
#include "hostmbufpool.h"
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    17
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    18
#include <bluetooth/hcicommandqueue.h>
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    19
#include <bluetooth/hci/hostnumberofcompletedpacketscommand.h>
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    20
#include <bluetooth/hci/hcievents.h>
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    21
#include <bluetooth/hci/commandcompleteevent.h>
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    22
#include <bluetooth/hci/hciutil.h>
48
hgs
parents: 33
diff changeset
    23
#include <bluetooth/hci/hciconsts.h>
33
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    24
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    25
#include "linkconsts.h"
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    26
#include "linkutil.h"
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    27
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    28
#include <bluetooth/logger.h>
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    29
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    30
#ifdef HOSTCONTROLLER_TO_HOST_FLOW_CONTROL
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    31
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    32
#ifdef __FLOG_ACTIVE
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    33
_LIT8(KLogComponent, LOG_COMPONENT_LINKMGR);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    34
#endif
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    35
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    36
__DEBUG_ONLY(PANICCATEGORY("mbufpool");)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    37
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    38
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    39
CHostMBufPool* CHostMBufPool::NewL(MHCICommandQueue& aCommandQueue)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    40
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    41
	LOG_STATIC_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    42
	CHostMBufPool* self = new (ELeave) CHostMBufPool(aCommandQueue);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    43
	CleanupStack::PushL(self);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    44
	self->ConstructL();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    45
	CleanupStack::Pop(self);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    46
	return self;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    47
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    48
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    49
void CHostMBufPool::DeletePool(TSglQue<TPoolBuffer>& aQueue)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    50
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    51
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    52
	TPoolBuffer* buffer = NULL;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    53
	TSglQueIter<TPoolBuffer> iter(aQueue);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    54
	while(buffer=iter++, buffer)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    55
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    56
		aQueue.Remove(*buffer);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    57
		DeleteBuffer(buffer);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    58
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    59
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    60
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    61
void CHostMBufPool::DeleteBuffer(TPoolBuffer*& aBuffer)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    62
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    63
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    64
	if(aBuffer)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    65
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    66
		aBuffer->iMBufChain.Free();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    67
		delete aBuffer;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    68
		aBuffer = NULL;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    69
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    70
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    71
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    72
CHostMBufPool::~CHostMBufPool()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    73
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    74
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    75
	Cancel();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    76
	// iMBufRequester is cleaned in it's destructor (not much of an R-class...but it is what it is)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    77
	DeletePool(iBufferPool);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    78
	DeletePool(iWaitingAllocPool);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    79
	DeleteBuffer(iBufferBeingAllocd);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    80
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    81
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    82
CHostMBufPool::CHostMBufPool(MHCICommandQueue& aCommandQueue)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    83
	: CActive(EPriorityHigh) 
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    84
	// High priority so that buffers are allocated occur before more data is read, this prevents
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    85
	// the cases the data floods the device and exhausts the buffers before any more can be allocated.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    86
	// This maximises throughput since we will ensure we send packet completion notifications in a
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    87
	// timely manner.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    88
	, iCmdQ(aCommandQueue)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    89
	, iBufferPool(_FOFF(TPoolBuffer,iLink))
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    90
	, iWaitingAllocPool(_FOFF(TPoolBuffer,iLink))
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    91
	, iCurrAckHandle(KErrNotFound)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    92
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    93
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    94
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    95
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    96
void CHostMBufPool::ConstructL()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    97
/**
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    98
2nd phase constructor for the Host MBuf Pool.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
    99
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   100
This method will attempt to reserve enough MBufs from the global pool
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   101
for bluetooth use.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   102
@leave KErrNoMemory If the required number of MBufs couldn't be reserved
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   103
*/
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   104
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   105
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   106
	LOG2(_L("CHostMBufPool: now reserving %d size %d MBufChains"), KStackACLBuffersNum, KLinkMgrIncomingBufferSize);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   107
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   108
	for (TInt i=0; i<=KStackACLBuffersNum-1; i++)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   109
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   110
		TPoolBuffer* thisBuffer = CreatePoolBufferL();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   111
		AddToBufferPool(*thisBuffer);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   112
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   113
		
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   114
	CActiveScheduler::Add(this);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   115
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   116
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   117
CHostMBufPool::TPoolBuffer* CHostMBufPool::CreatePoolBufferL()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   118
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   119
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   120
	TPoolBuffer* newBuffer = new(ELeave) TPoolBuffer();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   121
	CleanupStack::PushL(newBuffer);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   122
	newBuffer->iCurrentHandle = KInvalidConnectionHandle; // we assert on this later
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   123
	newBuffer->iMBufChain.AllocL(KLinkMgrIncomingBufferSize);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   124
	CleanupStack::Pop(newBuffer);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   125
	return newBuffer;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   126
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   127
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   128
void CHostMBufPool::DoCancel()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   129
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   130
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   131
	iMBufRequester.Cancel();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   132
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   133
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   134
RMBufChain CHostMBufPool::TakeBufferL(THCIConnHandle aConnHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   135
/**
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   136
Takes a buffer from the pool and schedules an asynchronous allocation
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   137
of the next buffer.	 Only when that allocation has succeeded will the host
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   138
controller be signalled with a host_number_of_completed_packets.  Hence,
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   139
if we cannot allocate a buffer from the global MBuf pool, the host controller
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   140
will be flowed off and no data will be lost.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   141
*/
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   142
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   143
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   144
	ASSERT_DEBUG(aConnHandle != KInvalidConnectionHandle);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   145
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   146
	// Speculatively attempt to allocate any queued allocations that may have previously failed.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   147
	TryToAllocQueuedBuffer();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   148
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   149
	TPoolBuffer* ready = iBufferPool.First();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   150
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   151
	if(!ready)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   152
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   153
		// Whoops run out of buffers - even though we were trying to prevent this with
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   154
		// flow control, in the case of disconnection the controller will assume all the
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   155
		// data for a connection handle will be flushed and therefore the buffers associated
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   156
		// with that connection handle will be free.  Unfortunately for us we don't have
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   157
		// that much control with the MBuf pool (since flow control is for asynchronous
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   158
		// buffer allocation rather than waiting for the given MBufs to be relinquished
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   159
		// by a higher layer).
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   160
		// So the controller could think we have more buffers than we actually have...
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   161
		LOG(_L8("CHostMBufPool: Ran out of buffers!!!!"));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   162
		LEAVEL(KErrOverflow);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   163
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   164
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   165
	// If here then we should have a valid pool buffer to use
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   166
	__ASSERT_DEBUG(!ready->iMBufChain.IsEmpty(), Panic(ELinkMgrHostControllerHasOverflowedHost));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   167
	__ASSERT_DEBUG(ready->iCurrentHandle == KInvalidConnectionHandle, Panic(ELinkMgrHostControllerHasOverflowedHost));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   168
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   169
	RemoveFromBufferPool(*ready);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   170
	ready->iCurrentHandle = aConnHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   171
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   172
	RMBufChain retChain;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   173
	retChain.Assign(ready->iMBufChain);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   174
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   175
	if (IsActive())
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   176
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   177
		//This buffer will be reclaimed from the global pool
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   178
		//after the one(s) we're currently trying to reclaim
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   179
		LOG(_L8("CHostMBufPool: TakeBuffer, buffer taken while alloc outstanding: queued alloc"));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   180
		iWaitingAllocPool.AddLast(*ready);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   181
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   182
	else
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   183
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   184
		LOG(_L8("CHostMBufPool: TakeBuffer, buffer taken"));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   185
		AllocNewBuffer(*ready);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   186
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   187
		
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   188
	return retChain;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   189
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   190
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   191
void CHostMBufPool::InvalidateByConnH(THCIConnHandle aConnHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   192
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   193
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   194
	ASSERT_DEBUG(aConnHandle != KInvalidConnectionHandle);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   195
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   196
	// We need to scan through the two pending "lists" to remove the
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   197
	// connection handle from record so we don't try to provide a 
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   198
	// packet completion notification (the controller already assumes
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   199
	// the buffers are free as they are entitled to by the spec).
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   200
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   201
	// The current buffer being allocated
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   202
	if(iBufferBeingAllocd && iBufferBeingAllocd->iCurrentHandle == aConnHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   203
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   204
		iBufferBeingAllocd->iCurrentHandle = KInvalidConnectionHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   205
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   206
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   207
	// The list of buffers waiting to be allocted
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   208
	TPoolBuffer* buffer = NULL;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   209
	TSglQueIter<TPoolBuffer> iter(iWaitingAllocPool);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   210
	while(buffer=iter++, buffer)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   211
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   212
		if(buffer->iCurrentHandle == aConnHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   213
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   214
			buffer->iCurrentHandle = KInvalidConnectionHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   215
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   216
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   217
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   218
	// Finally we need to purge any batched up completions if they
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   219
	// are for this connection handle
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   220
	if(iCurrAckHandle == aConnHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   221
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   222
		iCurrAckHandle = KErrNotFound;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   223
		iCurrCompletedPackets = 0;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   224
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   225
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   226
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   227
void CHostMBufPool::RunL()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   228
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   229
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   230
	LEAVEIFERRORL(iStatus.Int());
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   231
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   232
	// We've successfully allocated a new MBufChain
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   233
	TPoolBuffer* justAllocd = iBufferBeingAllocd;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   234
	iBufferBeingAllocd = NULL;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   235
	THCIConnHandle justAllocdHandle = justAllocd->iCurrentHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   236
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   237
	// Return buffer to pool for re-use
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   238
	AddToBufferPool(*justAllocd);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   239
	justAllocd->iCurrentHandle = KInvalidConnectionHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   240
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   241
	// If connection handle is still valid then we need to provide a completion
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   242
	// notification for the packet to the connection handle it was from.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   243
	if(justAllocdHandle != KInvalidConnectionHandle)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   244
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   245
		if (iCurrAckHandle == KErrNotFound)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   246
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   247
			// This is the first completion we have seen
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   248
			iCurrAckHandle = justAllocdHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   249
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   250
		ASSERT_DEBUG(iCurrAckHandle != KInvalidConnectionHandle); // just to be sure
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   251
		
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   252
		TBool ackNow = (justAllocdHandle != iCurrAckHandle);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   253
		
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   254
		if (!ackNow)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   255
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   256
			iCurrCompletedPackets++;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   257
			LOG2(_L8("CHostMBufPool: CompletedPackets++ for conn: %d [->%d]"), justAllocdHandle, iCurrCompletedPackets);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   258
			ackNow = (iCurrCompletedPackets >= KStackACLBuffersTideMarkNum);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   259
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   260
			
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   261
		if (ackNow)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   262
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   263
			TInt err = KErrNone;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   264
			
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   265
			if (iCurrCompletedPackets > 0)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   266
				{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   267
				LOG2(_L8("CHostMBufPool: Sending HostNumberOfCompletedPackets for conn: %d [%d completed]"), iCurrAckHandle, iCurrCompletedPackets);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   268
				//Acknowledge the completed packets
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   269
				TRAP(err, HostNumberOfCompletedPacketsL(iCurrAckHandle, iCurrCompletedPackets));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   270
				//if this failed we probably couldn't alloc the memory for the command frame,
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   271
				//the HC is still flowed off.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   272
				__ASSERT_DEBUG(err == KErrNone, Panic(ELinkMgrCouldNotSendHostNumberOfCompletedPackets));
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   273
				LEAVEIFERRORL(err);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   274
				}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   275
			
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   276
			iCurrCompletedPackets = (justAllocdHandle != iCurrAckHandle) ? 1 : 0;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   277
			iCurrAckHandle = justAllocdHandle;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   278
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   279
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   280
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   281
	TryToAllocQueuedBuffer();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   282
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   283
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   284
void CHostMBufPool::TryToAllocQueuedBuffer()
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   285
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   286
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   287
	if (!iWaitingAllocPool.IsEmpty() && !IsActive())
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   288
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   289
		TPoolBuffer* needsAlloc = iWaitingAllocPool.First();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   290
		iWaitingAllocPool.Remove(*needsAlloc);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   291
		AllocNewBuffer(*needsAlloc);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   292
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   293
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   294
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   295
void CHostMBufPool::AllocNewBuffer(TPoolBuffer& aBuffer)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   296
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   297
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   298
	ASSERT_DEBUG(!iBufferBeingAllocd);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   299
	iBufferBeingAllocd = &aBuffer;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   300
	iMBufRequester.Alloc(aBuffer.iMBufChain, KLinkMgrIncomingBufferSize, iStatus);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   301
	SetActive();
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   302
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   303
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   304
void CHostMBufPool::HostNumberOfCompletedPacketsL(THCIConnHandle aConnH, TUint16 aNumPackets)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   305
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   306
	RArray<THCIConnectionHandle> connHandles;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   307
	connHandles.AppendL(aConnH);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   308
	CleanupClosePushL(connHandles);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   309
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   310
	RArray<THCINumOfCompletedPackets> numPackets;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   311
	numPackets.AppendL(aNumPackets);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   312
	CleanupClosePushL(numPackets);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   313
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   314
	CHostNumberOfCompletedPacketsCommand* cmd = CHostNumberOfCompletedPacketsCommand::NewL(1, connHandles, numPackets);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   315
	// Ownership of the arrays is taken by the command object.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   316
	CleanupStack::Pop(2, &connHandles); // &numPackets, &connHandles
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   317
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   318
	// This is a priority command as we want to try to get this out as soon as possible (and not wait
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   319
	// for all normal control aspects to be processed).  This command shouldn't normally consume any credits
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   320
	// so as a priority command it has little impact.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   321
	// Ownership of cmd transfered even if MhcqAddPriorityCommandL leaves
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   322
	iCmdQ.MhcqAddPriorityCommandL(cmd, *this);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   323
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   324
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   325
void CHostMBufPool::MhcqcCommandEventReceived(const THCIEventBase& aEvent, const CHCICommandBase* /*aRelatedCommand*/)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   326
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   327
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   328
	// We don't expect a non-error event back because we're only sending Host_Number_of_Completed_Packet commands
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   329
	if(aEvent.EventCode() == ECommandCompleteEvent)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   330
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   331
		const THCICommandCompleteEvent& completeEvent = THCICommandCompleteEvent::Cast(aEvent);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   332
		if(completeEvent.CommandOpcode() == KHostNumberOfCompletedPacketsOpcode)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   333
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   334
			// a regular error for a Host_Number_Of_Completed_Packets command
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   335
			TInt err = CHciUtil::SymbianErrorCode(completeEvent.ErrorCode());
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   336
			if(err != KErrNone) // we shouldn't get a non-erroring event back, but just in case
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   337
				{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   338
				Error(err);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   339
				}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   340
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   341
		else // an unexpected command complete event
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   342
			{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   343
			LOG1(_L8("CHostMBufPool: Unexpected HCI command complete event; opcode = 0x%04x"), completeEvent.CommandOpcode());
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   344
			DEBUG_PANIC_LINENUM;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   345
			}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   346
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   347
	else // some unexpected event
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   348
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   349
		LOG1(_L8("CHostMBufPool: Unexpected HCI event received; code = 0x%02x"), aEvent.EventCode());
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   350
		DEBUG_PANIC_LINENUM;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   351
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   352
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   353
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   354
void CHostMBufPool::MhcqcCommandErrored(TInt aErrorCode, const CHCICommandBase* /*aCommand*/)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   355
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   356
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   357
	Error(aErrorCode);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   358
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   359
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   360
TInt CHostMBufPool::RunError(TInt aError)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   361
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   362
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   363
	if(iBufferBeingAllocd)
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   364
		{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   365
		TPoolBuffer* justFailedToAlloc = iBufferBeingAllocd;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   366
		iBufferBeingAllocd = NULL;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   367
		// Add to wait for alloc queue - we may get another chance
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   368
		iWaitingAllocPool.AddFirst(*justFailedToAlloc);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   369
		}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   370
	Error(aError);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   371
	return KErrNone;
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   372
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   373
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   374
void CHostMBufPool::Error(TInt IF_FLOGGING(aError))
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   375
	{
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   376
	LOG_FUNC
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   377
	// So there has been some internal error when handling controller to host
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   378
	// flow control.  Tough, we've done our best for now - the only real thing
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   379
	// that might be worth doing is a hard reset to start-up clean.
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   380
	LOG1(_L8("CHostMBufPool: ERROR (%d) - inbound data to the stack may stall soon"), aError);
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   381
	}
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   382
	
4e80e1b997a8 201025_01
hgs
parents:
diff changeset
   383
#endif