uasp: COMMAND IU handling infrastructure
Subsystems (2)
PATCH 2/4 uasp: COMMAND IU handling infrastructure
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(-)
drivers/usb/gadget/uasp_cmdiu.c +436 -0
@@ -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 ; + } + } }
Signature · 4 lines
1.6.3.3 -- Sent by a Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum