This patch defines APIs for different COMMAND IUs implementation

Signed-off-by: Tatyana Brokhman <[email protected]>
---
 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-arm-msm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to