All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Bogdanov <d.bogdanov@yadro.com>
To: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Cc: Felipe Balbi <balbi@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	<linux-usb@vger.kernel.org>,
	Mike Christie <michael.christie@oracle.com>,
	"Martin K. Petersen" <martin.petersen@oracle.com>,
	Roman Bolshakov <r.bolshakov@yadro.com>,
	<linux-scsi@vger.kernel.org>, <target-devel@vger.kernel.org>
Subject: Re: [PATCH 35/36] usb: gadget: f_tcm: Handle TASK_MANAGEMENT commands
Date: Fri, 8 Jul 2022 12:07:04 +0300	[thread overview]
Message-ID: <20220708090704.GM23838@yadro.com> (raw)
In-Reply-To: <70aa4f59a7f9d9d0c770bf42a0723825fa564548.1657149962.git.Thinh.Nguyen@synopsys.com>

On Wed, Jul 06, 2022 at 04:38:01PM -0700, Thinh Nguyen wrote:
> Handle target_core_fabric_ops TASK MANAGEMENT functions and their
> response. If a TASK MANAGEMENT command is received, the driver will
> interpret the function TMF_*, translate to TMR_*, and fire off a command
> work executing target_submit_tmr(). On completion, it will handle the
> TASK MANAGEMENT response through uasp_send_tm_response().
> 
> Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
> ---
> NOTE: I appologize for this big patch. I feel that this feature needs to be
> viewed in its entirety to see the whole picture and easier review.
> 
> 
>  drivers/usb/gadget/function/f_tcm.c | 260 +++++++++++++++++++++++++---
>  drivers/usb/gadget/function/tcm.h   |   7 +-
>  2 files changed, 241 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
> index fa09999adda7..a68436f97f91 100644
> --- a/drivers/usb/gadget/function/f_tcm.c
> +++ b/drivers/usb/gadget/function/f_tcm.c
> @@ -12,6 +12,7 @@
>  #include <linux/string.h>
>  #include <linux/configfs.h>
>  #include <linux/ctype.h>
> +#include <linux/delay.h>
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/composite.h>
>  #include <linux/usb/gadget.h>
> @@ -462,6 +463,53 @@ static int usbg_bot_setup(struct usb_function *f,
>  
>  /* Start uas.c code */
>  
> +static int tcm_to_uasp_response(enum tcm_tmrsp_table code)
> +{
> +	switch (code) {
> +	case TMR_FUNCTION_FAILED:
> +		return RC_TMF_FAILED;
> +	case TMR_FUNCTION_COMPLETE:
> +		return RC_TMF_COMPLETE;
> +	case TMR_FUNCTION_REJECTED:
> +		return RC_TMF_NOT_SUPPORTED;
> +	case TMR_LUN_DOES_NOT_EXIST:
> +		return RC_INCORRECT_LUN;
> +	case TMR_OVERLAPPED_TAG_ATTEMPTED:
> +		return RC_OVERLAPPED_TAG;
> +	case TMR_TASK_DOES_NOT_EXIST:
> +		return RC_INVALID_INFO_UNIT;
> +	case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
> +	default:
> +		return RC_TMF_NOT_SUPPORTED;
> +	}
> +}
> +
> +static unsigned char uasp_to_tcm_func(int code)
> +{
> +	switch (code) {
> +	case TMF_ABORT_TASK:
> +		return TMR_ABORT_TASK;
> +	case TMF_ABORT_TASK_SET:
> +		return TMR_ABORT_TASK_SET;
> +	case TMF_CLEAR_TASK_SET:
> +		return TMR_CLEAR_TASK_SET;
> +	case TMF_LOGICAL_UNIT_RESET:
> +		return TMR_LUN_RESET;
> +	case TMF_I_T_NEXUS_RESET:
> +		return TMR_I_T_NEXUS_RESET;
> +	case TMF_CLEAR_ACA:
> +		return TMR_CLEAR_ACA;
> +	case TMF_QUERY_TASK:
> +		return TMR_QUERY_TASK;
> +	case TMF_QUERY_TASK_SET:
> +		return TMR_QUERY_TASK_SET;
> +	case TMF_QUERY_ASYNC_EVENT:
> +		return TMR_QUERY_ASYNC_EVENT;
> +	default:
> +		return TMR_UNKNOWN;
> +	}
> +}
> +
>  static void uasp_cleanup_one_stream(struct f_uas *fu, struct uas_stream *stream)
>  {
>  	/* We have either all three allocated or none */
> @@ -506,6 +554,11 @@ static void uasp_cleanup_old_alt(struct f_uas *fu)
>  	uasp_free_cmdreq(fu);
>  }
>  
> +static struct uas_stream *uasp_get_stream_by_tag(struct f_uas *fu, u16 tag)
> +{
> +	return &fu->stream[tag % USBG_NUM_CMDS];
> +}
> +
>  static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req);
>  
>  static int uasp_prepare_r_request(struct usbg_cmd *cmd)
> @@ -513,7 +566,7 @@ static int uasp_prepare_r_request(struct usbg_cmd *cmd)
>  	struct se_cmd *se_cmd = &cmd->se_cmd;
>  	struct f_uas *fu = cmd->fu;
>  	struct usb_gadget *gadget = fuas_to_gadget(fu);
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  
>  	if (!gadget->sg_supported) {
>  		cmd->data_buf = kmalloc(se_cmd->data_length, GFP_ATOMIC);
> @@ -546,7 +599,7 @@ static void uasp_prepare_status(struct usbg_cmd *cmd)
>  {
>  	struct se_cmd *se_cmd = &cmd->se_cmd;
>  	struct sense_iu *iu = &cmd->sense_iu;
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(cmd->fu, cmd->tag);
>  
>  	cmd->state = UASP_QUEUE_COMMAND;
>  	iu->iu_id = IU_ID_STATUS;
> @@ -565,11 +618,36 @@ static void uasp_prepare_status(struct usbg_cmd *cmd)
>  	stream->req_status->complete = uasp_status_data_cmpl;
>  }
>  
> +static void uasp_prepare_response(struct usbg_cmd *cmd)
> +{
> +	struct se_cmd *se_cmd = &cmd->se_cmd;
> +	struct response_iu *rsp_iu = &cmd->response_iu;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(cmd->fu, cmd->tag);
> +
> +	cmd->state = UASP_QUEUE_COMMAND;
> +	rsp_iu->iu_id = IU_ID_RESPONSE;
> +	rsp_iu->tag = cpu_to_be16(cmd->tag);
> +
> +	if (cmd->tmr_rsp != TMR_RESPONSE_UNKNOWN)
> +		rsp_iu->response_code =
> +			tcm_to_uasp_response(cmd->tmr_rsp);
> +	else
> +		rsp_iu->response_code =
> +			tcm_to_uasp_response(se_cmd->se_tmr_req->response);
> +
> +	stream->req_status->is_last = 1;
> +	stream->req_status->stream_id = cmd->tag;
> +	stream->req_status->context = cmd;
> +	stream->req_status->length = sizeof(struct response_iu);
> +	stream->req_status->buf = rsp_iu;
> +	stream->req_status->complete = uasp_status_data_cmpl;
> +}
> +
>  static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
>  {
>  	struct usbg_cmd *cmd = req->context;
> -	struct uas_stream *stream = cmd->stream;
>  	struct f_uas *fu = cmd->fu;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  	struct se_session *se_sess = cmd->se_cmd.se_sess;
>  	int ret;
>  
> @@ -604,6 +682,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
>  		break;
>  
>  	case UASP_QUEUE_COMMAND:
> +		stream->cmd = NULL;
>  
>  		target_free_tag(se_sess, &cmd->se_cmd);
>  		transport_generic_free_cmd(&cmd->se_cmd, 0);
> @@ -617,6 +696,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
>  	return;
>  
>  cleanup:
> +	stream->cmd = NULL;
>  	target_free_tag(se_sess, &cmd->se_cmd);
>  	transport_generic_free_cmd(&cmd->se_cmd, 0);
>  }
> @@ -624,7 +704,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct usb_request *req)
>  static int uasp_send_status_response(struct usbg_cmd *cmd)
>  {
>  	struct f_uas *fu = cmd->fu;
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  	struct sense_iu *iu = &cmd->sense_iu;
>  
>  	iu->tag = cpu_to_be16(cmd->tag);
> @@ -633,10 +713,22 @@ static int uasp_send_status_response(struct usbg_cmd *cmd)
>  	return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
>  }
>  
> +static int uasp_send_tm_response(struct usbg_cmd *cmd)
> +{
> +	struct f_uas *fu = cmd->fu;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
> +	struct response_iu *iu = &cmd->response_iu;
> +
> +	iu->tag = cpu_to_be16(cmd->tag);
> +	cmd->fu = fu;
> +	uasp_prepare_response(cmd);
> +	return usb_ep_queue(fu->ep_status, stream->req_status, GFP_ATOMIC);
> +}
> +
>  static int uasp_send_read_response(struct usbg_cmd *cmd)
>  {
>  	struct f_uas *fu = cmd->fu;
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  	struct sense_iu *iu = &cmd->sense_iu;
>  	int ret;
>  
> @@ -682,7 +774,7 @@ static int uasp_send_read_response(struct usbg_cmd *cmd)
>  static int uasp_send_write_request(struct usbg_cmd *cmd)
>  {
>  	struct f_uas *fu = cmd->fu;
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  	struct sense_iu *iu = &cmd->sense_iu;
>  	int ret;
>  
> @@ -943,8 +1035,10 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
>  {
>  	struct usbg_cmd *cmd = req->context;
>  	struct se_cmd *se_cmd = &cmd->se_cmd;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(cmd->fu, cmd->tag);
>  
>  	if (req->status == -ESHUTDOWN) {
> +		stream->cmd = NULL;
>  		target_free_tag(se_cmd->se_sess, se_cmd);
>  		transport_generic_free_cmd(&cmd->se_cmd, 0);
>  		return;
> @@ -962,6 +1056,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct usb_request *req)
>  				se_cmd->data_length);
>  	}
>  
> +	cmd->state = UASP_QUEUE_COMMAND;
>  	target_execute_cmd(se_cmd);
>  	return;
>  
> @@ -1042,9 +1137,66 @@ static int usbg_send_read_response(struct se_cmd *se_cmd)
>  		return uasp_send_read_response(cmd);
>  }
>  
> -static void usbg_cmd_work(struct work_struct *work)
> +static void usbg_submit_tmr(struct usbg_cmd *cmd)
> +{
> +	struct se_cmd *se_cmd;
> +	struct tcm_usbg_nexus *tv_nexus;
> +	struct uas_stream *stream;
> +	int flags = TARGET_SCF_ACK_KREF;
> +
> +	se_cmd = &cmd->se_cmd;
> +	tv_nexus = cmd->fu->tpg->tpg_nexus;
> +	stream = uasp_get_stream_by_tag(cmd->fu, cmd->tag);
> +
> +	/* Failure detected by f_tcm */
> +	if (cmd->tmr_rsp != TMR_RESPONSE_UNKNOWN) {
> +		if (cmd->tmr_rsp == TMR_OVERLAPPED_TAG_ATTEMPTED) {
> +			/*
> +			 * There's no guarantee of a matching completion order
> +			 * between different endpoints. i.e. The device may
> +			 * receive a new (CDB) command request completion of the
> +			 * command endpoint before it gets notified of the
> +			 * previous command status completion from a status
> +			 * endpoint. The driver still needs to detect
> +			 * misbehaving host and respond with an overlap command
> +			 * tag. To prevent false overlapped tag failure, give
> +			 * the active and matching stream id a short time (1ms)
> +			 * to complete before respond with overlapped command
> +			 * failure.
> +			 */
> +			msleep(1);
> +
> +			/* If the stream is completed, retry the command */
> +			if (!stream->cmd) {
> +				usbg_submit_command(cmd->fu, cmd->req);
> +				return;
> +			}
> +
> +			/* Overlap command tag detected. Abort command. */
> +			cmd->state = UASP_QUEUE_COMMAND;
> +			stream->cmd->se_cmd.transport_state |= CMD_T_ABORTED;
> +			target_get_sess_cmd(&stream->cmd->se_cmd, true);
> +
> +			/* This will trigger command abort handler */
> +			target_execute_cmd(&stream->cmd->se_cmd);
> +			transport_generic_free_cmd(&stream->cmd->se_cmd, 1);
> +		}
> +
> +
> +		target_submit_tmr_fail_response(se_cmd, cmd->tmr_rsp,
> +				tv_nexus->tvn_se_sess, cmd->unpacked_lun,
> +				GFP_ATOMIC, cmd->tag, flags);
I think there is no reason to reject TMR via Core, you may use
your uasp_send_tm_response(cmd) directly like other fabric drivers does.
That will need some coding to distinguish a completion of the response
initiated from Core and from fabric driver.
> +		return;
> +	}
> +
> +	target_submit_tmr(se_cmd, tv_nexus->tvn_se_sess,
> +			  cmd->response_iu.add_response_info,
> +			  cmd->unpacked_lun, NULL, cmd->tmr_func,
> +			  GFP_ATOMIC, cmd->tag, flags);
> +}
> +
> +static void usbg_submit_cmd(struct usbg_cmd *cmd)
>  {
> -	struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
>  	struct se_cmd *se_cmd;
>  	struct tcm_usbg_nexus *tv_nexus;
>  	struct usbg_tpg *tpg;
> @@ -1073,6 +1225,16 @@ static void usbg_cmd_work(struct work_struct *work)
>  			TCM_UNSUPPORTED_SCSI_OPCODE, 0);
>  }
>  
> +static void usbg_cmd_work(struct work_struct *work)
> +{
> +	struct usbg_cmd *cmd = container_of(work, struct usbg_cmd, work);
> +
> +	if (cmd->tmr_func || cmd->tmr_rsp != TMR_RESPONSE_UNKNOWN)
> +		usbg_submit_tmr(cmd);
That looks very strange - in response of received SCSI command you will
send a TMR response???
I am about cmd->tmr_rsp != TMR_RESPONSE_UNKNOWN case.
> +	else
> +		usbg_submit_cmd(cmd);
> +}
> +
>  static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
>  		struct tcm_usbg_nexus *tv_nexus, u32 scsi_tag)
>  {
> @@ -1099,37 +1261,84 @@ static void usbg_release_cmd(struct se_cmd *);
>  
>  static int usbg_submit_command(struct f_uas *fu, struct usb_request *req)
>  {
> -	struct command_iu *cmd_iu = req->buf;
> +	struct iu *iu = req->buf;
>  	struct usbg_cmd *cmd;
>  	struct usbg_tpg *tpg = fu->tpg;
>  	struct tcm_usbg_nexus *tv_nexus;
> +	struct uas_stream *stream;
> +	struct command_iu *cmd_iu;
>  	u32 cmd_len;
>  	u16 scsi_tag;
>  
> -	if (cmd_iu->iu_id != IU_ID_COMMAND) {
> -		pr_err("Unsupported type %d\n", cmd_iu->iu_id);
> -		return -EINVAL;
> -	}
> -
>  	tv_nexus = tpg->tpg_nexus;
>  	if (!tv_nexus) {
>  		pr_err("Missing nexus, ignoring command\n");
>  		return -EINVAL;
>  	}
>  
> -	cmd_len = (cmd_iu->len & ~0x3) + 16;
> -	if (cmd_len > USBG_MAX_CMD)
> -		return -EINVAL;
> -
> -	scsi_tag = be16_to_cpup(&cmd_iu->tag);
> +	scsi_tag = be16_to_cpup(&iu->tag);
>  	cmd = usbg_get_cmd(fu, tv_nexus, scsi_tag);
>  	if (IS_ERR(cmd)) {
>  		pr_err("usbg_get_cmd failed\n");
>  		return -ENOMEM;
>  	}
> -	memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
>  
> -	cmd->stream = &fu->stream[cmd->tag % USBG_NUM_CMDS];
> +	cmd->req = req;
> +	cmd->fu = fu;
> +	cmd->tag = scsi_tag;
> +	cmd->se_cmd.tag = scsi_tag;
> +	cmd->tmr_func = 0;
> +	cmd->tmr_rsp = TMR_RESPONSE_UNKNOWN;
TMR_* constant are fabric agnostic enum. Better use RC_TMF_* values in
variables of this driver.
> +
> +	cmd_iu = (struct command_iu *)iu;
> +
> +	/* Command and Task Management IUs share the same LUN offset */
> +	cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
> +
> +	if (iu->iu_id != IU_ID_COMMAND && iu->iu_id != IU_ID_TASK_MGMT) {
> +		cmd->tmr_rsp = TMR_TASK_DOES_NOT_EXIST;
> +		goto skip;
> +	}
> +
> +	/*
> +	 * For simplicity, we use mod operation to quickly find an in-progress
> +	 * matching command tag and respond with overlapped command. The
> +	 * assumption is that the UASP class driver will limit to using tag id
> +	 * from 1 to USBG_NUM_CMDS. This is based on observation from the
> +	 * Windows and Linux UASP storage class driver behavior. If an unusual
> +	 * UASP class driver uses a tag greater than USBG_NUM_CMDS, then this
> +	 * method may no longer work due to possible stream id collision. In
> +	 * that case, we need to use a proper algorithm to fetch the stream (or
> +	 * simply walk through all active streams to check for overlap).
> +	 */
> +	stream = uasp_get_stream_by_tag(fu, scsi_tag);
> +	if (stream->cmd) {
> +		WARN_ONCE(stream->cmd->tag != scsi_tag,
WARN is used to indicate a non fatal bug in the code. May be you want to
use pr_warn/pr_err here?
> +			  "Command tag %d collided with Stream id %d\n",
> +			  scsi_tag, stream->cmd->tag);
> +
> +		cmd->tmr_rsp = TMR_OVERLAPPED_TAG_ATTEMPTED;
> +		goto skip;
> +	}
> +
> +	stream->cmd = cmd;
> +
> +	if (iu->iu_id == IU_ID_TASK_MGMT) {
> +		struct task_mgmt_iu *tm_iu;
> +
> +		tm_iu = (struct task_mgmt_iu *)iu;
> +		cmd->tmr_func = uasp_to_tcm_func(tm_iu->function);
> +		goto skip;
> +	}
> +
> +	cmd_len = (cmd_iu->len & ~0x3) + 16;
> +	if (cmd_len > USBG_MAX_CMD) {
> +		pr_err("invalid len %d\n", cmd_len);
> +		target_free_tag(tv_nexus->tvn_se_sess, &cmd->se_cmd);
> +		stream->cmd = NULL;
> +		return -EINVAL;
> +	}
> +	memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
>  
>  	switch (cmd_iu->prio_attr & 0x7) {
>  	case UAS_HEAD_TAG:
> @@ -1150,9 +1359,7 @@ static int usbg_submit_command(struct f_uas *fu, struct usb_request *req)
>  		break;
>  	}
>  
> -	cmd->unpacked_lun = scsilun_to_int(&cmd_iu->lun);
> -	cmd->req = req;
> -
> +skip:
>  	INIT_WORK(&cmd->work, usbg_cmd_work);
>  	queue_work(tpg->workqueue, &cmd->work);
>  
> @@ -1298,13 +1505,16 @@ static int usbg_get_cmd_state(struct se_cmd *se_cmd)
>  
>  static void usbg_queue_tm_rsp(struct se_cmd *se_cmd)
>  {
> +	struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd, se_cmd);
> +
> +	uasp_send_tm_response(cmd);
>  }
>  
>  static void usbg_aborted_task(struct se_cmd *se_cmd)
>  {
>  	struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd, se_cmd);
>  	struct f_uas *fu = cmd->fu;
> -	struct uas_stream *stream = cmd->stream;
> +	struct uas_stream *stream = uasp_get_stream_by_tag(fu, cmd->tag);
>  	int ret = 0;
>  
>  	if (stream->req_out->status == -EINPROGRESS)
> diff --git a/drivers/usb/gadget/function/tcm.h b/drivers/usb/gadget/function/tcm.h
> index 5157af1b166b..f1cd2399fd69 100644
> --- a/drivers/usb/gadget/function/tcm.h
> +++ b/drivers/usb/gadget/function/tcm.h
> @@ -82,8 +82,11 @@ struct usbg_cmd {
>  	u16 tag;
>  	u16 prio_attr;
>  	struct sense_iu sense_iu;
> +	struct response_iu response_iu;
>  	enum uas_state state;
> -	struct uas_stream *stream;
> +	int tmr_func;
> +	int tmr_rsp;
> +#define	TMR_RESPONSE_UNKNOWN 0xff
>  
>  	/* BOT only */
>  	__le32 bot_tag;
> @@ -96,6 +99,8 @@ struct uas_stream {
>  	struct usb_request	*req_in;
>  	struct usb_request	*req_out;
>  	struct usb_request	*req_status;
> +
> +	struct usbg_cmd		*cmd;
>  };
>  
>  struct usbg_cdb {

  reply	other threads:[~2022-07-08  9:07 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-06 23:34 [PATCH 00/36] usb: gadget: f_tcm: Enhance UASP driver Thinh Nguyen
2022-07-06 23:34 ` [PATCH 01/36] target: Handle MI_REPORT_SUPPORTED_OPERATION_CODES Thinh Nguyen
2022-07-07  8:01   ` Oliver Neukum
2022-07-07 11:44   ` kernel test robot
2022-07-06 23:34 ` [PATCH 02/36] target: Add overlapped response to tmrsp_table Thinh Nguyen
2022-07-06 23:34 ` [PATCH 03/36] target: Don't drain empty list Thinh Nguyen
2022-07-07 12:42   ` Dmitry Bogdanov
2022-07-06 23:34 ` [PATCH 04/36] target: Does tmr notify on aborted command Thinh Nguyen
2022-07-07 12:56   ` Dmitry Bogdanov
2022-07-08 23:11     ` Thinh Nguyen
2022-07-11  9:44       ` Dmitry Bogdanov
2022-07-12  2:57         ` Thinh Nguyen
2022-07-11 10:31       ` Bodo Stroesser
2022-07-12  3:09         ` Thinh Nguyen
2022-07-06 23:34 ` [PATCH 05/36] target: Don't remove command too early Thinh Nguyen
2022-07-07 13:16   ` Dmitry Bogdanov
2022-07-08 23:40     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 06/36] target: Return Function Complete Thinh Nguyen
2022-07-07 13:34   ` Dmitry Bogdanov
2022-07-08 23:51     ` Thinh Nguyen
2022-07-11  9:53       ` Dmitry Bogdanov
2022-07-06 23:35 ` [PATCH 07/36] target: Don't do tmr_notify on empty aborted list Thinh Nguyen
2022-07-07 13:36   ` Dmitry Bogdanov
2022-07-08 23:53     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 08/36] target: Refactor core_tmr_abort_task Thinh Nguyen
2022-07-07 13:40   ` Dmitry Bogdanov
2022-07-09  0:02     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 09/36] target: Add common Task Management values Thinh Nguyen
2022-07-07 19:36   ` Dmitry Bogdanov
2022-07-09  0:04     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 10/36] target: Implement TMR_ABORT_TASK_SET Thinh Nguyen
2022-07-07 19:40   ` Dmitry Bogdanov
2022-07-08  9:50     ` Dmitry Bogdanov
2022-07-09  0:46       ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 11/36] target: Properly set Sense Data Length of CHECK CONDITION Thinh Nguyen
2022-07-07  8:24   ` Oliver Neukum
2022-07-07 10:21     ` Thinh Nguyen
2022-07-07 20:27   ` Dmitry Bogdanov
2022-07-09  0:11     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 12/36] target: Properly set Sense data length when copy sense Thinh Nguyen
2022-07-07 20:53   ` Dmitry Bogdanov
2022-07-09  0:11     ` Thinh Nguyen
2022-07-06 23:35 ` [PATCH 13/36] target: Don't respond TMR_LUN_DOES_NOT_EXIST for all TMR failure Thinh Nguyen
2022-07-06 23:35 ` [PATCH 14/36] target: Introduce target_submit_tmr_fail_response Thinh Nguyen
2022-07-06 23:35 ` [PATCH 15/36] target: Include INQUIRY length Thinh Nguyen
2022-07-07 10:11   ` Konstantin Shelekhin
2022-07-14  1:42     ` Thinh Nguyen
2022-07-06 23:36 ` [PATCH 16/36] usb: gadget: f_tcm: Increase stream count Thinh Nguyen
2022-07-06 23:36 ` [PATCH 17/36] usb: gadget: f_tcm: Increase bMaxBurst Thinh Nguyen
2022-07-06 23:36 ` [PATCH 18/36] usb: gadget: f_tcm: Don't set static stream_id Thinh Nguyen
2022-07-08  7:00   ` Dmitry Bogdanov
2022-07-09  0:12     ` Thinh Nguyen
2022-07-06 23:36 ` [PATCH 19/36] usb: gadget: f_tcm: Allocate matching number of commands to streams Thinh Nguyen
2022-07-06 23:36 ` [PATCH 20/36] usb: gadget: f_tcm: Limit number of sessions Thinh Nguyen
2022-07-07  6:57   ` Greg Kroah-Hartman
2022-07-07 10:31     ` Thinh Nguyen
2022-07-06 23:36 ` [PATCH 21/36] usb: gadget: f_tcm: Handle multiple commands in parallel Thinh Nguyen
2022-07-06 23:36 ` [PATCH 22/36] usb: gadget: f_tcm: Use extra number of commands Thinh Nguyen
2022-07-06 23:36 ` [PATCH 23/36] usb: gadget: f_tcm: Return ATA cmd direction Thinh Nguyen
2022-07-06 23:36 ` [PATCH 24/36] usb: gadget: f_tcm: Execute command on write completion Thinh Nguyen
2022-07-06 23:36 ` [PATCH 25/36] usb: gadget: f_tcm: Minor cleanup redundant code Thinh Nguyen
2022-07-06 23:37 ` [PATCH 26/36] usb: gadget: f_tcm: Don't free command immediately Thinh Nguyen
2022-07-06 23:37 ` [PATCH 27/36] usb: gadget: f_tcm: Translate error to sense Thinh Nguyen
2022-07-06 23:37 ` [PATCH 28/36] usb: gadget: f_tcm: Cleanup unused variable Thinh Nguyen
2022-07-06 23:37 ` [PATCH 29/36] usb: gadget: f_tcm: Update state on data write Thinh Nguyen
2022-07-06 23:37 ` [PATCH 30/36] usb: gadget: f_tcm: Handle abort command Thinh Nguyen
2022-07-06 23:37 ` [PATCH 31/36] usb: gadget: f_tcm: Cleanup requests on ep disable Thinh Nguyen
2022-07-06 23:37 ` [PATCH 32/36] usb: gadget: f_tcm: Send sense reason Thinh Nguyen
2022-07-08  7:35   ` Dmitry Bogdanov
2022-07-09  0:13     ` Thinh Nguyen
2022-07-06 23:37 ` [PATCH 33/36] usb: gadget: f_tcm: Save CPU ID per command Thinh Nguyen
2022-07-06 23:37 ` [PATCH 34/36] usb: gadget: f_tcm: Free tags earlier Thinh Nguyen
2022-07-07  9:14   ` Dmitriy Bogdanov
2022-07-07 10:11     ` Thinh Nguyen
2022-07-07 12:37       ` Dmitry Bogdanov
2022-07-06 23:38 ` [PATCH 35/36] usb: gadget: f_tcm: Handle TASK_MANAGEMENT commands Thinh Nguyen
2022-07-08  9:07   ` Dmitry Bogdanov [this message]
2022-07-09  0:41     ` Thinh Nguyen
2022-07-06 23:38 ` [PATCH 36/36] usb: gadget: f_tcm: Comply with UAS Task Management requirement Thinh Nguyen
2022-07-07  4:38 ` [PATCH 00/36] usb: gadget: f_tcm: Enhance UASP driver Christoph Hellwig
2022-07-07  4:50   ` Thinh Nguyen
2022-07-07  6:59 ` Greg Kroah-Hartman
2022-07-07 10:15   ` Thinh Nguyen
2022-07-07 11:15     ` Greg Kroah-Hartman

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-all 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=20220708090704.GM23838@yadro.com \
    --to=d.bogdanov@yadro.com \
    --cc=Thinh.Nguyen@synopsys.com \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=michael.christie@oracle.com \
    --cc=r.bolshakov@yadro.com \
    --cc=target-devel@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.