diff -r e7d2d738d3c2 -r 2f92ad2dc5db kernel/eka/drivers/dma/dma2_pil.cpp --- a/kernel/eka/drivers/dma/dma2_pil.cpp Mon Mar 15 12:45:50 2010 +0200 +++ b/kernel/eka/drivers/dma/dma2_pil.cpp Wed Mar 31 23:38:45 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available // under the terms of "Eclipse Public License v1.0" @@ -1955,20 +1955,6 @@ stop = __e32_atomic_load_acq32(&iIsrDfc) & (TUint32)KCancelFlagMask; } - // Some interrupts may be missed (double-buffer and scatter-gather - // controllers only) if two or more transfers complete while interrupts are - // disabled in the CPU. If this happens, the framework will go out of sync - // and leave some orphaned requests in the queue. - // - // To ensure correctness we handle this case here by checking that the request - // queue is empty when all transfers have completed and, if not, cleaning up - // and notifying the client of the completion of the orphaned requests. - // - // Note that if some interrupts are missed and the controller raises an - // error while transferring a subsequent fragment, the error will be reported - // on a fragment which was successfully completed. There is no easy solution - // to this problem, but this is okay as the only possible action following a - // failure is to flush the whole queue. if (stop) { // If another thread set the cancel flag, it should have @@ -1989,66 +1975,6 @@ // release threads doing CancelAll() waiters->Signal(); } - else if (!error && !iReqQ.IsEmpty() && iController->IsIdle(*this)) - { -#ifdef __SMP__ - // On an SMP system we must call stop transfer, it will block until - // any ISRs have completed so that the system does not spuriously - // attempt to recover from a missed interrupt. - // - // On an SMP system it is possible for the code here to execute - // concurrently with the DMA ISR. It is therefore possible that at this - // point the previous transfer has already completed (so that IsIdle - // reports true), but that the ISR has not yet queued a DFC. Therefore - // we must wait for the ISR to complete. - // - // StopTransfer should have no other side effect, given that the - // channel is already idle. - iController->StopTransfer(*this); // should block till ISR completion -#endif - - const TBool cleanup = !iDfc.Queued(); - if(cleanup) - { - __KTRACE_OPT(KDMA, Kern::Printf("Missed interrupt(s) - draining request queue")); - ResetStateMachine(); - - // Move orphaned requests to temporary queue so channel queue can - // accept new requests. - SDblQue q; - q.MoveFrom(&iReqQ); - - SDblQueLink* pL; - while ((pL = q.GetFirst()) != NULL) - { - DDmaRequest* const pR = _LOFF(pL, DDmaRequest, iLink); - __KTRACE_OPT(KDMA, Kern::Printf("Removing request from queue and notifying client")); - pR->OnDeque(); - // Old style callback - DDmaRequest::TCallback const cb = pR->iCb; - if (cb) - { - TAny* const arg = pR->iCbArg; - Signal(); - (*cb)(DDmaRequest::EOk, arg); - Wait(); - } - else - { - // New style callback - TDmaCallback const ncb = pR->iDmaCb; - if (ncb) - { - TAny* const arg = pR->iDmaCbArg; - Signal(); - (*ncb)(EDmaCallbackRequestCompletion, EDmaResultOK, arg, NULL); - Wait(); - } - } - } - } - Signal(); - } else Signal();