Apologies for the delay; after two years and multiple requests to resume this series, I squeezed some time to push an update. This series applies on top of Greg's usb-testing branch.
If possible, please help test this series and get this merged as my resources are nil for this work.
Example Bringup Steps ===================== To test UASP, here's an example perl script snippet to bring it up.
Note: the script was cut down and quickly rewritten, so sorry if I make mistakes.
my $MY_UAS_VID = xxxx; my $MY_UAS_PID = yyyy; my $SERIAL = "1234"; my $VENDOR = "VENDOR"; my $MY_VER = "VER";
my $vendor_id = "my_vid"; my $product_id = "my_pid"; my $revision = "my_rev";
# Must update: my $backing_storage = "/tmp/some_file"; my $backing_storage_size = 1024*1024*16; my $use_ramdisk = 0;
my $g = "/sys/kernel/config/usb_gadget/g1";
system("modprobe libcomposite"); system("modprobe usb_f_tcm"); system("mkdir -p $g"); system("mkdir -p $g/configs/c.1"); system("mkdir -p $g/functions/tcm.0"); system("mkdir -p $g/strings/0x409"); system("mkdir -p $g/configs/c.1/strings/0x409");
my $tp = "/sys/kernel/config/target/usb_gadget/naa.0/tpgt_1";
my $tf; my $ctrl;
if ($use_ramdisk) { $tf = "/sys/kernel/config/target/core/rd_mcp_0/ramdisk"; $ctrl = 'rd_pages=524288'; } else { $tf = "/sys/kernel/config/target/core/fileio_0/fileio"; $ctrl = 'fd_dev_name=$backing_storage,fd_dev_size=$backing_storage_size,fd_async_io=1'; }
system("mkdir -p /etc/target");
system("mkdir -p $tp"); system("mkdir -p $tf"); system("mkdir -p $tp/lun/lun_0");
system("echo naa.0 > $tp/nexus"); system("echo $ctrl > $tf/control"); system("echo 1 > $tf/attrib/emulate_ua_intlck_ctrl"); system("echo 123 > $tf/wwn/vpd_unit_serial"); system("echo $vendor_id > $tf/wwn/vendor_id"); system("echo $product_id > $tf/wwn/product_id"); system("echo $revision > $tf/wwn/revision"); system("echo 1 > $tf/enable");
system("ln -s $tf $tp/lun/lun_0/virtual_scsi_port"); system("echo 1 > $tp/enable");
system("echo $MY_UAS_PID > $g/idProduct");
system("ln -s $g/functions/tcm.0 $g/configs/c.1");
system("echo $MY_UAS_VID > $g/idVendor"); system("echo $SERIAL > $g/strings/0x409/serialnumber"); system("echo $VENDOR > $g/strings/0x409/manufacturer"); system("echo "$MY_VER" > $g/strings/0x409/product"); system("echo "Conf 1" > $g/configs/c.1/strings/0x409/configuration"); system("echo super-speed-plus > $g/max_speed");
# Make sure the UDC is available system("echo $my_udc > $g/UDC");
Target Subsystem Fixes ====================== I have eliminated unnecessary changes related to the Target subsystem and reworked f_tcm to minimize the modifications required in the Target subsystem. There are unimplemented Task Management Requests in the Target subsystem, but the basic flow should still work.
Regardless, you should still need to apply at least these 2 fixes:
1) Fix Data Corruption ----------------------
Properly increment the "len" base on the command requested length instead of the SG entry length.
If you're using File backend, then you need to fix target_core_file. If you're using other backend such as Ramdisk, then you need a similar fix there.
--- drivers/target/target_core_file.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 2d78ef74633c..d9fc048c1734 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -283,7 +283,12 @@ fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, for_each_sg(sgl, sg, sgl_nents, i) { bvec_set_page(&aio_cmd->bvecs[i], sg_page(sg), sg->length, sg->offset); - len += sg->length; + if (len + sg->length >= cmd->data_length) { + len = cmd->data_length; + break; + } else { + len += sg->length; + } }
iov_iter_bvec(&iter, is_write, aio_cmd->bvecs, sgl_nents, len); @@ -328,7 +333,12 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
for_each_sg(sgl, sg, sgl_nents, i) { bvec_set_page(&bvec[i], sg_page(sg), sg->length, sg->offset); - len += sg->length; + if (len + sg->length >= data_length) { + len = data_length; + break; + } else { + len += sg->length; + } }
iov_iter_bvec(&iter, is_write, bvec, sgl_nents, len);