public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Liran Alon" <liran.alon@oracle.com>
To: Laszlo Ersek <lersek@redhat.com>, devel@edk2.groups.io
Cc: nikita.leshchenko@oracle.com, aaron.young@oracle.com,
	jordan.l.justen@intel.com, ard.biesheuvel@linaro.org
Subject: Re: [edk2-devel] [PATCH v2 15/17] OvmfPkg/PvScsiDxe: Support sending SCSI request and receive response
Date: Sat, 28 Mar 2020 22:18:47 +0300	[thread overview]
Message-ID: <9bbdb66f-9fdb-bd5a-74b8-6dc31015dc8a@oracle.com> (raw)
In-Reply-To: <65eb2511-e2f5-d2b5-4470-278b06a0e077@oracle.com>


On 28/03/2020 1:17, Liran Alon wrote:
>
> On 28/03/2020 1:04, Liran Alon wrote:
>>
>> On 28/03/2020 0:05, Laszlo Ersek wrote:
>>> On 03/27/20 14:04, Liran Alon wrote:
>>>> On 27/03/2020 14:26, Laszlo Ersek wrote:
>>>>> On 03/25/20 17:10, Liran Alon wrote:
>>>>>> + Packet->HostAdapterStatus =
>>>>>> + EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
>>>>>> +      return EFI_BAD_BUFFER_SIZE;
>>>>> I think EFI_BAD_BUFFER_SIZE is invalid here. According to the UEFI 
>>>>> spec,
>>>>> EFI_BAD_BUFFER_SIZE means "The SCSI Request Packet was not executed".
>>>>> But that's not the case here -- we do have a partially completed
>>>>> transfer.
>>>> Hmm... According to the documentation above 
>>>> EFI_SCSI_PASS_THRU_PASSTHRU
>>>> in MdePkg/Include/Protocol/ScsiPassThru.h:
>>>>
>>>>    @retval EFI_BAD_BUFFER_SIZE       The SCSI Request Packet was
>>>> executed, but the
>>>>                                      entire DataBuffer could not be
>>>> transferred.
>>>>                                      The actual number of bytes
>>>> transferred is returned
>>>>                                      in TransferLength. See
>>>> HostAdapterStatus,
>>>>                                      TargetStatus, SenseDataLength, 
>>>> and
>>>> SenseData in
>>>>                                      that order for additional status
>>>> information.
>>>>
>>>> So I don't know who to believe... It does seem to me that this
>>>> documentation in the code makes more sense
>>>> and then my current code is correct. What do you think?
>>> You are looking at the wrong protocol header file.
>> Oops. You are right.
>>> The top of this
>>> header file bears the comment
>>>
>>>    SCSI Pass Through protocol as defined in EFI 1.1.
>>>
>>> and the UEFI-2.8 spec does not define EFI_SCSI_PASS_THRU_PROTOCOL; it
>>> only refers to Mantis ticket 845
>>> <https://urldefense.com/v3/__https://mantis.uefi.org/mantis/view.php?id=845__;!!GqivPVa7Brio!M5o2BC3kQvh7gEgQh98Kb7YJeFCM_ajknF8iRXjDer3Ir8hUy6dHOReS12oCRvE$ 
>>> > with subject
>>> "EFI_SCSI_PASS_THRU_PROTOCOL replacement".
>>>
>>> Instead, please consult EFI_EXT_SCSI_PASS_THRU_PASSTHRU in
>>> "MdePkg/Include/Protocol/ScsiPassThruExt.h". There, the
>>> EFI_BAD_BUFFER_SIZE return value conforms to the UEFI 2.8 spec ("The
>>> SCSI Request Packet was not executed").
>>
>> Honestly, I'm not sure if this is not a bug in UEFI-2.8 spec and 
>> ScsiPassThruExt.h header file. It doesn't make sense.
>> In the new header file, there is no way for PassThru() to indicate to 
>> caller that a partial data-transfer have occurred.
>> Which seems to be a quite standard functionality. Almost all SCSI 
>> devices are able to return information on partial data-transfer 
>> completions.
>>
>> Looking at QEMU's virtio-scsi.c virtio_scsi_command_complete() 
>> implementation, we can see how it handles partial data-transfer 
>> completions.
>> It sets Response->Response to VIRTIO_SCSI_S_OK and Response->Residual 
>> accordingly.
>> Looking at EDK2 VirtioScsi driver, function ParseResponse(), this 
>> will be handled by updating Packet->InTransferLength and 
>> Packet->OutTransferLength based on Response->Residual,
>> but then setting Packet->HostAdapterStatus to 
>> EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK and returning EFI_SUCCESS.
>> (In contrast to your suggestion for me to return EFI_DEVICE_ERROR in 
>> this case).
>>
>> The documentation of PassThru in ScsiPassThruExt.h for EFI_SUCCESS 
>> specifies:
>>
>>   @retval EFI_SUCCESS           The SCSI Request Packet was sent by 
>> the host. For bi-directional
>>                                 commands, InTransferLength bytes were 
>> transferred from
>>                                 InDataBuffer. For write and 
>> bi-directional commands,
>>                                 OutTransferLength bytes were 
>> transferred by
>>                                 OutDataBuffer.
>>
>> But it seems to reference the InTransferLength and OutTransferLength 
>> *before* the call to PassThru().
>>
>> In contrast to old header file, ScsiPassThru.h, which for 
>> EFI_BAD_BUFFER_SIZE specifies explicitly:
>>
>>  @retval EFI_BAD_BUFFER_SIZE       The SCSI Request Packet was 
>> executed, but the
>>                                     entire DataBuffer could not be 
>> transferred.
>>                                     The actual number of bytes 
>> transferred is returned
>>                                     in TransferLength. See 
>> HostAdapterStatus,
>>                                     TargetStatus, SenseDataLength, 
>> and SenseData in
>>                                     that order for additional status 
>> information.
>>
>> In addition, looking at EDK2 iSCSI ScsiPassThru driver 
>> (NetworkPkg/IScsiDxe/IScsiExtScsiPassThru.c), one can see it use 
>> EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
>> (Which matches the new header file ScsiPassThruExt.h and not the old 
>> ScsiPassThru.h).
>> If you would have a look at how IScsiOnScsiRspRcvd() handles 
>> SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW and SCSI_RSP_PDU_FLAG_OVERFLOW 
>> bits, it seems to always
>> set Status to EFI_BAD_BUFFER_SIZE as I have done. After updating 
>> Packet->InTransferLength / Packet->OutTransferLength.
>>
>> What do you think? Do you have any further insights? This is quite 
>> confusing to me.
>>
>> -Liran
>>
> Furthermore, I have later found ScsiExecuteSCSICommand() in 
> MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c to be the one that calls 
> the PassThru() method.
> Looking at it's "if (ScsiIoDevice->ExtScsiSupport)" branch (Which is 
> relevant to us), one can see it just simply executes the PassThru() 
> device and returns.
> Examining ScsiExecuteSCSICommand() documentation specifies for 
> EFI_BAD_BUFFER_SIZE:
>
>   @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
>                               but the entire DataBuffer could not be 
> transferred.
>                               The actual number of bytes transferred 
> is returned
>                               in TransferLength. See HostAdapterStatus,
>                               TargetStatus, SenseDataLength, and 
> SenseData in
>                               that order for additional status 
> information.
>
> Which again seems to align to what I have done in my PvScsi driver...
>
> -Liran
>
Sorry for the spam but I think I eventually figured it out.

The call-chain in EDK2 looks like this:
ScsiDiskWriteSectors() (MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c)
ScsiDiskWrite16() (MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c)
ScsiWrite16Command() (MdePkg/Library/UefiScsiLib/UefiScsiLib.c)
ScsiExecuteSCSICommand() (MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c)
ExtScsiPassThru->PassThru()

It can be seen that:
* ScsiExecuteSCSICommand() just passes Packet to 
ExtScsiPassThru->PassThru() and returns it's return value.
* ScsiWrite16Command() always updates DataLength with 
Packet->OutTransferLength and returns ScsiExecuteSCSICommand() return value.
* In ScsiDiskWrite16():
   ** If EFI_BAD_BUFFER_SIZE is returned, NeedRetry is set to TRUE and 
EFI_DEVICE_ERROR is returned.
   ** Otherwise, if EFI_SUCCESS is returned but HostAdapterStatus is set 
to EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN, then again 
NeedRetry is set to TRUE and EFI_DEVICE_ERROR is returned.
   ** Otherwise, just return EFI_SUCCESS to caller.
* In ScsiDiskWriteSectors() we finally see the logic we were looking for:
   ** If ScsiDiskWrite16() returned EFI_SUCCESS, then we break out of 
retry loop and indeed take into account ByteCount. (Which was updated 
from Packet->OutTransferLength).
   ** Otherwise, (e.g. EFI_BAD_BUFFER_SIZE was returned), if NeedRetry 
is set to TRUE, then next request retry is updated to be done with 
ByteCount (Which was updated from Packet->OutTransferLength).

So it seems the UEFI-2.8 spec is right and a lot of EDK2 function 
documentation is out-of-date.

Therefore, I will update my code accordingly. i.e.:
1) Change PvScsi.c PopulateRequest() such that in case TransferLength is 
too big for DMA communication buffer Data field, we update 
TransferLength and return EFI_BAD_BUFFER_SIZE.
     But in addition, for completion, we should also set 
HostAdapterStatus to 
EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN and TargetStatus 
to EFI_EXT_SCSI_STATUS_TARGET_GOOD
     and SenseDataLength to 0 as done in VirtioScsi.c PopulateRequest() 
in case it returns EFI_BAD_BUFFER_SIZE.
2) Change PvScsi.c HandleResponse() such that:
   ** If device returned PvScsiBtStatDataUnderrun: Update TransferLength 
with Response->DataLen, set HostAdapterStatus to 
EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN and return 
EFI_SUCCESS.
   ** If device returned PvScsiBtStatDatarun: Just set HostAdapterStatus 
to EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN and return 
EFI_SUCCESS.

Regards,
-Liran


  reply	other threads:[~2020-03-28 19:18 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-25 16:09 [PATCH v2 00/17] OvmfPkg: Support booting from VMware PVSCSI controller Liran Alon
2020-03-25 16:09 ` [PATCH v2 01/17] OvmfPkg/PvScsiDxe: Create empty driver Liran Alon
2020-03-26 14:44   ` [edk2-devel] " Laszlo Ersek
2020-03-25 16:09 ` [PATCH v2 02/17] OvmfPkg/PvScsiDxe: Install DriverBinding protocol Liran Alon
2020-03-25 16:09 ` [PATCH v2 03/17] OvmfPkg/PvScsiDxe: Report name of driver Liran Alon
2020-03-25 16:09 ` [PATCH v2 04/17] OvmfPkg/PvScsiDxe: Probe PCI devices and look for PvScsi Liran Alon
2020-03-25 16:09 ` [PATCH v2 05/17] OvmfPkg/PvScsiDxe: Install stubbed EXT_SCSI_PASS_THRU Liran Alon
2020-03-25 16:09 ` [PATCH v2 06/17] OvmfPkg/PvScsiDxe: Report the number of targets and LUNs Liran Alon
2020-03-25 16:09 ` [PATCH v2 07/17] OvmfPkg/PvScsiDxe: Translate Target & LUN to/from DevicePath Liran Alon
2020-03-25 16:09 ` [PATCH v2 08/17] OvmfPkg/PvScsiDxe: Open PciIo protocol for later use Liran Alon
2020-03-25 16:09 ` [PATCH v2 09/17] OvmfPkg/PvScsiDxe: Backup/Restore PCI attributes on Init/UnInit Liran Alon
2020-03-26 17:04   ` [edk2-devel] " Laszlo Ersek
2020-03-25 16:09 ` [PATCH v2 10/17] OvmfPkg/PvScsiDxe: Enable MMIO-Space & Bus-Mastering in PCI attributes Liran Alon
2020-03-26 17:12   ` Laszlo Ersek
2020-03-25 16:09 ` [PATCH v2 11/17] OvmfPkg/PvScsiDxe: Define device interface structures and constants Liran Alon
2020-03-26 17:19   ` [edk2-devel] " Laszlo Ersek
2020-03-25 16:10 ` [PATCH v2 12/17] OvmfPkg/PvScsiDxe: Reset adapter on init Liran Alon
2020-03-26 18:25   ` [edk2-devel] " Laszlo Ersek
2020-03-25 16:10 ` [PATCH v2 13/17] OvmfPkg/PvScsiDxe: Setup requests and completions rings Liran Alon
2020-03-26 20:51   ` Laszlo Ersek
2020-03-25 16:10 ` [PATCH v2 14/17] OvmfPkg/PvScsiDxe: Introduce DMA communication buffer Liran Alon
2020-03-26 22:17   ` Laszlo Ersek
2020-03-27  0:05     ` Liran Alon
2020-03-27 13:35       ` Laszlo Ersek
2020-03-27 21:31         ` Liran Alon
2020-03-30 11:29           ` Laszlo Ersek
2020-03-25 16:10 ` [PATCH v2 15/17] OvmfPkg/PvScsiDxe: Support sending SCSI request and receive response Liran Alon
2020-03-27 11:26   ` [edk2-devel] " Laszlo Ersek
2020-03-27 13:04     ` Liran Alon
2020-03-27 13:20       ` Liran Alon
2020-03-27 21:05         ` Laszlo Ersek
2020-03-27 21:05       ` Laszlo Ersek
2020-03-27 22:04         ` Liran Alon
2020-03-27 22:17           ` Liran Alon
2020-03-28 19:18             ` Liran Alon [this message]
2020-03-30 11:23               ` Laszlo Ersek
2020-03-30 11:12             ` Laszlo Ersek
2020-03-30 10:30           ` Laszlo Ersek
2020-03-25 16:10 ` [PATCH v2 16/17] OvmfPkg/PvScsiDxe: Reset device on ExitBootServices() Liran Alon
2020-03-25 16:10 ` [PATCH v2 17/17] OvmfPkg/PvScsiDxe: Enable device 64-bit DMA addresses Liran Alon
2020-03-26 22:29   ` [edk2-devel] " Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9bbdb66f-9fdb-bd5a-74b8-6dc31015dc8a@oracle.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox