MdeModulePkg UfsPassThruDxe: Add Non-blocking I/O Support

Previously, UfsPassThruPassThru function does not handle the 'Event'
parameter and blocking read/write operations are always executed.

This commit enables non-blocking read/write feature for UFS devices.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19216 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Hao Wu
2015-12-11 01:58:45 +00:00
committed by hwu1225
parent d670bf5336
commit 0350b57cf7
3 changed files with 393 additions and 40 deletions

View File

@@ -1,6 +1,6 @@
/** @file
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -21,10 +21,7 @@ UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
NULL, // Handle
{ // ExtScsiPassThruMode
0xFFFFFFFF,
//
// Note that the driver doesn't support ExtScsiPassThru non blocking I/O.
//
EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL,
EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
sizeof (UINTN)
},
{ // ExtScsiPassThru
@@ -64,6 +61,11 @@ UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
},
0x0000, // By default don't expose any Luns.
0x0
},
NULL, // TimerEvent
{ // Queue
NULL,
NULL
}
};
@@ -212,7 +214,7 @@ UfsPassThruPassThru (
return EFI_INVALID_PARAMETER;
}
Status = UfsExecScsiCmds (Private, UfsLun, Packet);
Status = UfsExecScsiCmds (Private, UfsLun, Packet, Event);
return Status;
}
@@ -816,6 +818,7 @@ UfsPassThruDriverBindingStart (
//
Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
if (Private == NULL) {
DEBUG ((EFI_D_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
Status = EFI_OUT_OF_RESOURCES;
goto Error;
}
@@ -823,6 +826,7 @@ UfsPassThruDriverBindingStart (
Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
Private->UfsHostController = UfsHc;
Private->UfsHcBase = UfsHcBase;
InitializeListHead (&Private->Queue);
//
// Initialize UFS Host Controller H/W.
@@ -873,6 +877,31 @@ UfsPassThruDriverBindingStart (
}
}
//
// Start the asynchronous interrupt monitor
//
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
ProcessAsyncTaskList,
Private,
&Private->TimerEvent
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
goto Error;
}
Status = gBS->SetTimer (
Private->TimerEvent,
TimerPeriodic,
UFS_HC_ASYNC_TIMER
);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
goto Error;
}
Status = gBS->InstallProtocolInterface (
&Controller,
&gEfiExtScsiPassThruProtocolGuid,
@@ -899,6 +928,10 @@ Error:
UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
}
if (Private->TimerEvent != NULL) {
gBS->CloseEvent (Private->TimerEvent);
}
FreePool (Private);
}
@@ -953,6 +986,9 @@ UfsPassThruDriverBindingStop (
UFS_PASS_THRU_PRIVATE_DATA *Private;
EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
UFS_PASS_THRU_TRANS_REQ *TransReq;
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
DEBUG ((EFI_D_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
@@ -972,6 +1008,24 @@ UfsPassThruDriverBindingStop (
Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
UfsHc = Private->UfsHostController;
//
// Cleanup the resources of I/O requests in the async I/O queue
//
if (!IsListEmpty(&Private->Queue)) {
EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
//
// TODO: Should find/add a proper host adapter return status for this
// case.
//
TransReq->Packet->HostAdapterStatus =
EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
SignalCallerEvent (Private, TransReq);
}
}
Status = gBS->UninstallProtocolInterface (
Controller,
&gEfiExtScsiPassThruProtocolGuid,
@@ -1002,6 +1056,10 @@ UfsPassThruDriverBindingStop (
UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
}
if (Private->TimerEvent != NULL) {
gBS->CloseEvent (Private->TimerEvent);
}
FreePool (Private);
//