lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date:	Fri, 21 Jan 2011 09:44:52 +0200
From:	Tatyana Brokhman <tlinder@...eaurora.org>
To:	gregkh@...e.de
Cc:	linux-arm-msm@...r.kernel.org,
	Tatyana Brokhman <tlinder@...eaurora.org>,
	linux-usb@...r.kernel.org (open list:USB GADGET/PERIPH...),
	linux-kernel@...r.kernel.org (open list)
Subject: [RFC/PATCH 2/4] uasp: COMMAND IU handling infrastructure

This patch defines APIs for different COMMAND IUs implementation

Signed-off-by: Tatyana Brokhman <tlinder@...eaurora.org>
---
 drivers/usb/gadget/uasp_cmdiu.c |  436 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 436 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/gadget/uasp_cmdiu.c b/drivers/usb/gadget/uasp_cmdiu.c
index 8a7b34e..1444d56 100644
--- a/drivers/usb/gadget/uasp_cmdiu.c
+++ b/drivers/usb/gadget/uasp_cmdiu.c
@@ -48,6 +48,53 @@ struct fsg_buffhd *get_buffhd(struct fsg_buffhd *bh)
 }
 
 /**
+ * check_cmdiu() - initial verification of the COMMAND IU
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct lun if the COMMAND IU to be checked is addressed
+ *	to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be checked.
+ * @needs_medium: Specifies, is the medium needed for the COMMAND IU processing.
+ */
+static uint32_t check_cmdiu(struct uasp_dev *udev,
+			    struct uasp_lun *curlun,
+			    struct cmd_iu *cmdiu,
+			    u8 needs_medium)
+{
+	u32 ua_data = 0;
+
+	DBG(udev->ucommon->common, "%s() - Enter\n", __func__);
+
+	if (!curlun || !curlun->lun) {
+		if (cmdiu->cdb[0] != INQUIRY &&
+		    cmdiu->cdb[0] != REQUEST_SENSE) {
+			DBG(udev->ucommon->common,
+			      "%s() - Logical unit is not supported\n",
+			      __func__);
+			return SS_LOGICAL_UNIT_NOT_SUPPORTED;
+		}
+	} else {
+		if (curlun->lun->unit_attention_data &&
+		    cmdiu->cdb[0] != INQUIRY &&
+		    cmdiu->cdb[0] != REQUEST_SENSE) {
+			DBG(udev->ucommon->common,
+			    "%s() - There is an unit attention condition\n",
+			    __func__);
+			ua_data = curlun->lun->unit_attention_data;
+			curlun->lun->unit_attention_data = SS_NO_SENSE;
+			return ua_data;
+		}
+	}
+
+	if (curlun && !(curlun->lun->filp) && needs_medium) {
+		DBG(udev->ucommon->common,
+		    "%s() - Medium is not present\n", __func__);
+		return SS_MEDIUM_NOT_PRESENT;
+	}
+
+	return SS_NO_SENSE;
+}
+
+/**
  * fill_sense_iu() - fills the struct sense_iu with a given values.
  * @udev: Programming view of UASP device.
  * @siu: Pointer to structure to be filled.
@@ -77,6 +124,330 @@ void fill_sense_iu(struct uasp_dev *udev,
 }
 
 /**
+ * do_uasp_inquiry() - performs INQUIRY SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be
+ *	performed is addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_inquiry(struct uasp_dev *udev,
+			struct uasp_lun *curlun,
+			struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+
+/**
+ * do_uasp_request_sense() - performs REQUEST SENSE SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be
+ *	   performed is addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_request_sense(struct uasp_dev *udev,
+			      struct uasp_lun *curlun,
+			      struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_test_unit_ready() - performs TEST UNIT READY SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be
+ *	   performed is addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_test_unit_ready(struct uasp_dev *udev,
+				struct uasp_lun *curlun,
+				struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_mode_sense() - performs MODE SENSE(6) and MODE SENSE(10)
+ * SCSI commands.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be
+ *	   performed is addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *	   0 otherwise.
+ */
+static int do_uasp_mode_sense(struct uasp_dev *udev,
+			   struct uasp_lun *curlun,
+			   struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_prevent_allow() - performs PREVENT ALLOW MEDIUM REMOVAL SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be
+ *	   performed is addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_prevent_allow(struct uasp_dev *udev,
+			      struct uasp_lun *curlun,
+			      struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_read() - performs READ(6), READ(10), READ(12) SCSI commands.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns non zero if usb request(s) should be submitted to PCD after cmdiu
+ * processing, 0 otherwise.
+ */
+static int do_uasp_read(struct uasp_dev *udev,
+		     struct uasp_lun *curlun,
+		     struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_read_capacity() - This function performs READ CAPACITY SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *	   0 otherwise.
+ *
+ */
+static int do_uasp_read_capacity(struct uasp_dev *udev,
+			 struct uasp_lun *curlun,
+			 struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_read_format_capacities() - performs READ FORMAT CAPACITIES
+ * SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_read_format_capacities(struct uasp_dev *udev,
+				       struct uasp_lun *curlun,
+				       struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_start_stop() - performs START STOP UNIT SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *	   0 otherwise.
+ *
+ */
+static int do_uasp_start_stop(struct uasp_dev *udev,
+			   struct uasp_lun *curlun,
+			   struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_verify() - This function performs VERIFY SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_verify(struct uasp_dev *udev,
+		       struct uasp_lun *curlun,
+		       struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_write() - This function performs WRITE(6), WRITE(10), WRITE(12)
+ * SCSI commands.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns: 1 if an IN usb request should be submitted to PCD after processing
+ *	    2 if an OUT usb request should be submitted to PCD after processing
+ *	    0 otherwise.
+ */
+static int do_uasp_write(struct uasp_dev *udev,
+		      struct uasp_lun *curlun,
+		      struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * do_uasp_synchronize_cache() - performs SYNCHRONIZE CACHE SCSI command.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ *
+ * Returns 1 if usb request should be submitted to PCD after cmdiu processing,
+ *         0 otherwise.
+ */
+static int do_uasp_synchronize_cache(struct uasp_dev *udev,
+				  struct uasp_lun *curlun,
+				  struct cmd_iu *cmdiu)
+{
+	return 0;
+}
+
+/**
+ * process_cmdiu() - This function performs a given COMMAND IU.
+ * @udev: Programming view of UASP device.
+ * @curlun: Pointer to struct uasp_lun if the COMMAND IU to be performed is
+ *	   addressed to a valid LUN, 0 otherwise.
+ * @cmdiu: COMMAND IU to be performed.
+ */
+static void process_cmdiu(struct uasp_dev *udev,
+			  struct uasp_lun *curlun,
+			  struct cmd_iu *cmdiu)
+{
+	unsigned long flags;
+	struct sense_iu *siu;
+	struct usb_request *req;
+	int rc = 0;
+
+	DBG(udev->ucommon->common, "%s() Enter. (cmdiu->cdb[0]=%04x)\n",
+	    __func__, cmdiu->cdb[0]);
+
+	/* We're using the backing file */
+	down_read(&udev->ucommon->common->filesem);
+	switch (cmdiu->cdb[0]) {
+	case INQUIRY:
+		rc = do_uasp_inquiry(udev, curlun, cmdiu);
+		break;
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+		rc = do_uasp_mode_sense(udev, curlun, cmdiu);
+		break;
+	case ALLOW_MEDIUM_REMOVAL:
+		rc = do_uasp_prevent_allow(udev, curlun, cmdiu);
+		break;
+	case READ_6:
+	case READ_10:
+	case READ_12:
+		rc = do_uasp_read(udev, curlun, cmdiu);
+		break;
+	case READ_CAPACITY:
+		rc = do_uasp_read_capacity(udev, curlun, cmdiu);
+		break;
+	case READ_FORMAT_CAPACITIES:
+		rc = do_uasp_read_format_capacities(udev, curlun, cmdiu);
+		break;
+	case REQUEST_SENSE:
+		rc = do_uasp_request_sense(udev, curlun, cmdiu);
+		break;
+	case START_STOP:
+		rc = do_uasp_start_stop(udev, curlun, cmdiu);
+		break;
+	case SYNCHRONIZE_CACHE:
+		rc = do_uasp_synchronize_cache(udev, curlun, cmdiu);
+		break;
+	case TEST_UNIT_READY:
+		rc = do_uasp_test_unit_ready(udev, curlun, cmdiu);
+		break;
+	case VERIFY:
+		rc = do_uasp_verify(udev, curlun, cmdiu);
+		break;
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_12:
+		rc = do_uasp_write(udev, curlun, cmdiu);
+		break;
+	case FORMAT_UNIT:
+	case MODE_SELECT:
+	case MODE_SELECT_10:
+	case RELEASE:
+	case RESERVE:
+	case SEND_DIAGNOSTIC:
+	default:
+		ERROR(udev->ucommon->common,
+		      "%s(): Unsupported  command = %x\n",
+		    __func__, cmdiu->cdb[0]);
+		cmdiu->state = COMMAND_STATE_STATUS;
+		siu = (struct sense_iu *)cmdiu->bh->inreq->buf;
+		fill_sense_iu(udev, siu, IUGETW(cmdiu->ip_tag),
+			      STATUS_CHECK_CONDITION,
+			      SS_INVALID_COMMAND);
+		fill_usb_request(cmdiu->bh->inreq, (void *)siu,
+				 UASP_SIZEOF_SENSE_IU, 0,
+				 (void *)cmdiu, 0, IUGETW(cmdiu->ip_tag),
+				 status_complete);
+		cmdiu->ep = udev->status;
+		rc = 1;
+		break;
+	}
+
+	up_read(&udev->ucommon->common->filesem);
+	if (rc) {
+		req = (rc == 2 ? cmdiu->bh->outreq : cmdiu->bh->inreq);
+		if (usb_ep_queue(cmdiu->ep, req, 0)) {
+			ERROR(udev->ucommon->common,
+			      "%s()usb_ep_queue failed\n",  __func__);
+			cmdiu->state = COMMAND_STATE_FAILED;
+		} else {
+			DBG(udev->ucommon->common,
+			    "%s() - process_cmdiu: queued req to ep\n",
+			    __func__);
+			if (curlun) {
+				spin_lock_irqsave(&(curlun->lock), flags);
+				curlun->active_requests++;
+				spin_unlock_irqrestore(&(curlun->lock), flags);
+			} else {
+				spin_lock_irqsave(
+					&(udev->ucommon->common->lock), flags);
+				udev->active_requests++;
+				spin_unlock_irqrestore(
+					&(udev->ucommon->common->lock), flags);
+			}
+		}
+	}
+}
+
+/**
  * do_cmdiu() - This function performs the COMMAND IUs from a given queue.
  * @udev: Programming view of UASP device.
  * @curlun: Pointer to struct uasp_lun if COMMAND IUs from lun::cmd_queue
@@ -85,7 +456,72 @@ void fill_sense_iu(struct uasp_dev *udev,
  */
 void do_cmdiu(struct uasp_dev *udev, struct uasp_lun *curlun)
 {
+	struct list_head *link;
+	struct cmd_iu *cmdiu, *tmp;
+	unsigned long flags;
+	int cmd_is_active = 0;
+
 	DBG(udev->ucommon->common, "%s() - Enter\n", __func__);
+
+	/* Select the cmd_queue from which cmdius should be processed */
+	if (curlun)
+		link = &curlun->cmd_queue;
+	else
+		link = &udev->cmd_queue;
+
+	list_for_each_entry_safe(cmdiu, tmp, link, node) {
+		DBG(udev->ucommon->common, "%s() - Rolling over cmdiu queue\n",
+		     __func__);
+
+		/*
+		 * TODO: this is a workaround. It is added for processing
+		 * of only one command in a certain nexus or lun.
+		 * Remove this after initial testing.
+		 */
+		if (cmd_is_active) {
+			DBG(udev->ucommon->common,
+			    "%s() - Cmdiu is on data stage, do not process"
+				 " next cmdiu\n", __func__);
+			break;
+		}
+
+		spin_lock_irqsave(&(udev->ucommon->common->lock), flags);
+		if (cmdiu->state == COMMAND_STATE_IDLE) {
+			/* Try to get buffers for cmdiu processing */
+			cmdiu->bh = get_buffhd(udev->ucommon->common->buffhds);
+			spin_unlock_irqrestore(&(udev->ucommon->common->lock),
+					       flags);
+
+			if (!cmdiu->bh) {
+				ERROR(udev->ucommon->common,
+				      "%s() -Didn't manage to get buffers for "
+				      "cmdiu!\n", __func__);
+				continue;
+			}
+		} else if (cmdiu->state == COMMAND_STATE_DATA) {
+			cmd_is_active = 1;
+			if (cmdiu->req_sts == CMD_REQ_COMPLETED)
+				spin_unlock_irqrestore(
+					&(udev->ucommon->common->lock), flags);
+			else {
+				spin_unlock_irqrestore(
+					&(udev->ucommon->common->lock), flags);
+				continue;
+			}
+			cmd_is_active = 0;
+		} else {
+			spin_unlock_irqrestore(&(udev->ucommon->common->lock),
+					       flags);
+			continue;
+		}
+
+		process_cmdiu(udev, curlun, cmdiu);
+
+		if (cmdiu->state == COMMAND_STATE_DATA) {
+			cmd_is_active = 1;
+			break;
+		}
+	}
 }
 
 
-- 
1.6.3.3
--
Sent by a Consultant for Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ