On 09/09/15 09:11, Tian, Feng wrote: > I agreed ScsiDisk misses the handling for EFI_BAD_BUFFER_SIZE. That's why I > proposed a patch although it's not good:-) > > The uncertain part from my side at previous discussion is about the value of > In/OutTransferLength when EFI_BAD_BUFFER_SIZE is returned. > > In UEFI spec, there are two sentences to explain EFI_BAD_BUFFER_SIZE: > > 1) If InTransferLength is larger than the SCSI controller can handle, no data > will be transferred, InTransferLength will be updated to contain the number > of bytes that the SCSI controller is able to transfer, and > EFI_BAD_BUFFER_SIZE will be returned. > > 2) If the data buffer described by InDataBuffer and InTransferLength is too > big to be transferred in a single command, then no data is transferred and > EFI_BAD_BUFFER_SIZE is returned. The number of bytes that can be transferred > in a single command are returned in InTransferLength. > > I used to only refer to #2 and thought it means the target's capability > rather than host. So I thought for read/write cmd the In/OutTransferLength == > SectorCount * BlockSize. > > But now it looks Paolo's explanation makes more sense. So I agree with > Laszlo's 2nd patch. > > Reviewed-by: Feng Tian <feng.t...@intel.com>
Thank you. I'll now repost the full series (two patches), because I'd like to make sure that you agree with the commit message I wrote for the separate EFI_BAD_BUFFER_SIZE handling patch, and also just to be sure that your Reviewed-by covers both patches. Therefore I will not add your R-b from above just yet to those two patches -- can you please respond separately with your R-b to the series I'm about to post? There won't be any changes in that series relative to what you've seen here. (Sorry about the churn, but I think this is safer than me going ahead and committing it now, and then realizing you meant something else, and having to revert / update the patches.) Thank you! Laszlo > Thanks > Feng > > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Laszlo > Ersek > Sent: Tuesday, September 08, 2015 18:23 > To: Paolo Bonzini; Tian, Feng > Cc: edk2-de...@ml01.01.org > Subject: Re: [edk2] [PATCH] MdeModulePkg: ScsiDiskDxe: adapt SectorCount when > shortening transfers > > On 09/08/15 10:07, Paolo Bonzini wrote: >> >> >> On 08/09/2015 09:02, Tian, Feng wrote: >>> Hi, Laszlo >>> >>> 1. I don't think the code in VirtioScsi.c is correct. It hardcodes >>> the block size as 512bytes. The driver should send READ_CAPACITY cmd >>> to get block size, then convert it to InTransferLength & OutTransferLength. >> >> This is the controller's maximum transfer size, not the LUN. The >> LUN's limits are available from VPD and depend on the block size. The >> controller's limit apply to all LUNs and to all commands, even those >> that transfer bytes rather than blocks. >> >> For historical reasons the controller's maximum transfer size is >> provided in 512-byte units. In fact, Laszlo raised this point to the >> virtio committee just to be sure that his code is correct, which it is. > > Thanks. > >>> 2. Although the UEFI spec doesn't say the relationship of >>> InTransferLength/OutTransferLength and CDB.TransferLength, but I >>> think it's implied that InTransferLength/OutTransferLength = >>> CDB.TransferLength * BlockSize. Otherwise how the lowest layer host >>> controller driver constructs transfer descriptor? How many bytes to >>> read? Is InTransferLength/OutTransferLength or the one of >>> CDB.TransferLength * BlockSize? >> >> It's always InTransferLength/OutTransferLength. If it is < or > >> CDB.TransferLength * BlockSize you get respectively an underrun or an >> overrun. An underrun is fatal, an overrun is not. >> >> InTransferLength/OutTransferLength exist because the controller may >> not know how to infer the transfer length for all CDB opcodes (some >> express it in bytes, some express it in blocks, some are vendor >> specific, some are just crazy and you have to inspect multiple CDB >> fields to compute the transfer length). >> >> Of course ScsiDisk *does* know how to infer the transfer length for >> the CDBs it builds. Therefore, it makes sense for ScsiDisk's own READ >> and WRITE CDBs to always have InTransferLength/OutTransferLength = >> CDB.TransferLength * BlockSize. However, the controller driver must >> not rely on this. > > I'd like to add something here (which might be simply rephrasing what you > said): > > I think Feng's question is about my former statement, which goes like: > > In case the host controller (ie. not the LUN) is unable to satisfy > the request, due to its size (InTransferLength/OutTransferLength) > being too large, then it is allowed to return any kind of shorter > InTransferLength/OutTransferLength, and the returned max transfer > size *need not* be an integral multiple of any kind of block size. > Ad absurdum, it could be a prime number too. > > Feng's patch allowed the controller to return a lower transfer length, but it > also expected said lower transfer length to be a multiple of "the" block size. > > But this is incorrect, because at the host controller level, the concept of > "block size" doesn't exist at all! Some LUN hanging off the same host > controller could have a block size of 2KB, another 512B, yet another 4KB. > > So, going beyond the statement "the controller driver must not rely on this", > I state that the controller driver doesn't even *know* about any block size! > The condition that the host controller's maximum transfer size is exceeded is > detected *much earlier* than talking to any LUN. > > Therefore, if the host controller driver returns a value saying "hey this is > my max transfer size", it is the responsibility of the LUN- and > media-specific higher level driver (instance) to round that down to a whole > multiple of the block size that exists on *that* level (and that level only). > > Feng said: > >>> 3. If we don't think #2 is implied, why we can assume "if pass thru >>> driver returns EFI_BAD_BUFFER_SIZE and leave HostAdapterStatus at >>> EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK, but *then* it must set either >>> TargetStatus to some error code (different from >>> EFI_EXT_SCSI_STATUS_TARGET_GOOD), *or* it must report some problem in >>> the sense data."? IMHO, a pass thru driver could only return >>> EFI_BAD_BUFFER_SIZE and leave HostAdpterStatus/TargetStatus to ok and >>> no sense data. > > I think so, yes. As long as the passthru driver complies with the priority > order, ultimately it can set *just* the return status (to > EFI_BAD_BUFFER_SIZE), and leave everything else zeroed (ie. "success" > codes, and no sense data). In my previous statement I wanted to describe the > order in which a passthrough driver was allowed to provide error details, but > I missed that said priority order can be satisfied also by returning just > EFI_BAD_BUFFER_SIZE, and not explaining anything else. > > Back to Paolo's comments: > >> I agree that: >> >> - there's no need for the controller driver to set HostAdapterStatus >> to anything > > Agreed. There is no *need*, but it is allowed by the specification of > EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru(), and VirtioScsiDxe conforms to > that. > >> >> - even if it sets it to something, TargetStatus should not be set and >> there should be no sense data. > > Agreed, and VirtioScsiDxe behaves exactly like that. In the case at hand, > TargetStatus is set to EFI_EXT_SCSI_STATUS_TARGET_GOOD (value 0), and > SenseDataLength is set to zero. > >> Regarding the first point, this is not exactly an underrun, though it >> may remind of one. EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER might be >> just as good, and even EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK might be >> okay because the request has never reached the controller. The >> important bit is EFI_BAD_BUFFER_SIZE. Thus, Laszlo's incremental >> patch in >> http://article.gmane.org/gmane.comp.bios.edk2.devel/2007 is necessary >> if I understand it correctly. > > Yes. My original patch worked in isolation (ie. without the incremental > patch) probably only because VirtioScsiDxe had been setting HostAdapterStatus > to EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN, which is just one > of the correct possibilities, as you say. That HostAdapterStatus happened to > trigger a path in ScsiDiskDxe that was ultimately good. But, if VirtioScsiDxe > had set HostAdapterStatus to something else (eg. > ADAPTER_OTHER or ADAPTER_OK, as you say), then maybe ScsiDiskDxe would have > done the wrong thing even with my first patch in place, because it never > looked for EFI_BAD_BUFFER_SIZE explicitly. Other SCSI drivers could set > HostAdapterStatus like this, on EFI_BAD_BUFFER_SIZE (and it would be valid), > so that's why the incremental patch is needed for ScsiDiskDxe. > >> Regarding the second point, the TargetStatus and sense data *could* be >> set if the transfer length in the CDB exceeds the maximum transfer >> length in the VPD. In this case, the sense data will be filled and the >> target status will be EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION. >> This is the case where the LUN's maximum transfer length is exceeded, >> which is why it is based on the CDB rather than >> InTransferLength/OutTransferLength. However, in this case you cannot >> expect EFI_BAD_BUFFER_SIZE to be set, because it's not the controller >> driver's business to inspect target status and sense data (it's called >> "passthru driver" for a reason :)). > > VirtioScsiDxe conforms to this; the only place PassThru() returns > EFI_BAD_BUFFER_SIZE is when the host controller's transfer limit is exceeded. > >> Thus, the best you can do is to always back off to smaller sector >> sizes > > (To smaller sector *counts*, ITYM. > > Independently, UefiScsiLib uses the "SectorSize" parameter name confusingly > in a few places; it should say "SectorCount".) > >> when you get an unexpected error, like you did in r15491. >> >> Paolo >> > > Thanks! > Laszlo > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel