2017-11-03 11:28:30 +01:00
// SPDX-License-Identifier: GPL-2.0
2010-10-07 13:05:23 +02:00
/*
* USB Attached SCSI
* Note that this is not the same as the USB Mass Storage driver
*
2016-04-12 12:27:09 +02:00
* Copyright Hans de Goede < hdegoede @ redhat . com > for Red Hat , Inc . 2013 - 2016
2010-10-07 13:05:23 +02:00
* Copyright Matthew Wilcox for Intel Corp , 2010
* Copyright Sarah Sharp for Intel Corp , 2010
*/
# include <linux/blkdev.h>
# include <linux/slab.h>
# include <linux/types.h>
2011-07-03 16:09:31 -04:00
# include <linux/module.h>
2010-10-07 13:05:23 +02:00
# include <linux/usb.h>
2013-10-25 17:04:33 +01:00
# include <linux/usb_usual.h>
2012-01-11 12:42:32 +01:00
# include <linux/usb/hcd.h>
2010-10-07 13:05:23 +02:00
# include <linux/usb/storage.h>
2012-01-11 12:45:56 +01:00
# include <linux/usb/uas.h>
2010-10-07 13:05:23 +02:00
# include <scsi/scsi.h>
2013-10-22 16:10:44 +01:00
# include <scsi/scsi_eh.h>
2010-10-07 13:05:23 +02:00
# include <scsi/scsi_dbg.h>
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_device.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_tcq.h>
2013-10-21 08:53:31 +01:00
# include "uas-detect.h"
2014-09-15 16:04:12 +02:00
# include "scsiglue.h"
2013-10-21 08:53:31 +01:00
2014-09-13 12:26:32 +02:00
# define MAX_CMNDS 256
2010-10-07 13:05:23 +02:00
struct uas_dev_info {
struct usb_interface * intf ;
struct usb_device * udev ;
2012-09-25 10:47:04 +02:00
struct usb_anchor cmd_urbs ;
2012-06-19 09:54:53 +02:00
struct usb_anchor sense_urbs ;
struct usb_anchor data_urbs ;
2014-09-15 16:04:12 +02:00
unsigned long flags ;
2012-06-19 09:54:54 +02:00
int qdepth , resetting ;
2010-10-07 13:05:23 +02:00
unsigned cmd_pipe , status_pipe , data_in_pipe , data_out_pipe ;
unsigned use_streams : 1 ;
2013-11-11 11:51:42 +01:00
unsigned shutdown : 1 ;
2014-09-13 12:26:32 +02:00
struct scsi_cmnd * cmnd [ MAX_CMNDS ] ;
2012-09-25 10:47:08 +02:00
spinlock_t lock ;
2013-09-13 13:27:12 +02:00
struct work_struct work ;
2020-01-30 01:25:06 -08:00
struct work_struct scan_work ; /* for async scanning */
2010-10-07 13:05:23 +02:00
} ;
enum {
2015-11-05 16:20:36 +01:00
SUBMIT_STATUS_URB = BIT ( 1 ) ,
ALLOC_DATA_IN_URB = BIT ( 2 ) ,
SUBMIT_DATA_IN_URB = BIT ( 3 ) ,
ALLOC_DATA_OUT_URB = BIT ( 4 ) ,
SUBMIT_DATA_OUT_URB = BIT ( 5 ) ,
ALLOC_CMD_URB = BIT ( 6 ) ,
SUBMIT_CMD_URB = BIT ( 7 ) ,
COMMAND_INFLIGHT = BIT ( 8 ) ,
DATA_IN_URB_INFLIGHT = BIT ( 9 ) ,
DATA_OUT_URB_INFLIGHT = BIT ( 10 ) ,
COMMAND_ABORTED = BIT ( 11 ) ,
IS_IN_WORK_LIST = BIT ( 12 ) ,
2010-10-07 13:05:23 +02:00
} ;
/* Overrides scsi_pointer */
struct uas_cmd_info {
unsigned int state ;
2014-10-12 12:19:40 +02:00
unsigned int uas_tag ;
2010-10-07 13:05:23 +02:00
struct urb * cmd_urb ;
struct urb * data_in_urb ;
struct urb * data_out_urb ;
} ;
/* I hate forward declarations, but I actually have a loop */
static int uas_submit_urbs ( struct scsi_cmnd * cmnd ,
2015-11-03 16:43:17 +01:00
struct uas_dev_info * devinfo ) ;
2011-12-02 11:55:44 -08:00
static void uas_do_work ( struct work_struct * work ) ;
2012-11-30 11:54:44 +01:00
static int uas_try_complete ( struct scsi_cmnd * cmnd , const char * caller ) ;
2013-09-13 13:27:11 +02:00
static void uas_free_streams ( struct uas_dev_info * devinfo ) ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
static void uas_log_cmd_state ( struct scsi_cmnd * cmnd , const char * prefix ,
int status ) ;
2012-11-30 11:54:40 +01:00
2020-04-15 16:17:50 +02:00
/*
* This driver needs its own workqueue , as we need to control memory allocation .
*
* In the course of error handling and power management uas_wait_for_pending_cmnds ( )
* needs to flush pending work items . In these contexts we cannot allocate memory
* by doing block IO as we would deadlock . For the same reason we cannot wait
* for anything allocating memory not heeding these constraints .
*
* So we have to control all work items that can be on the workqueue we flush .
* Hence we cannot share a queue and need our own .
*/
static struct workqueue_struct * workqueue ;
2010-10-07 13:05:23 +02:00
static void uas_do_work ( struct work_struct * work )
{
2013-09-13 13:27:12 +02:00
struct uas_dev_info * devinfo =
container_of ( work , struct uas_dev_info , work ) ;
2010-10-07 13:05:23 +02:00
struct uas_cmd_info * cmdinfo ;
2014-09-13 12:26:38 +02:00
struct scsi_cmnd * cmnd ;
2012-09-25 10:47:08 +02:00
unsigned long flags ;
2014-09-13 12:26:38 +02:00
int i , err ;
2010-10-07 13:05:23 +02:00
2013-09-13 13:27:12 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2014-09-13 12:26:30 +02:00
if ( devinfo - > resetting )
goto out ;
2014-09-13 12:26:38 +02:00
for ( i = 0 ; i < devinfo - > qdepth ; i + + ) {
if ( ! devinfo - > cmnd [ i ] )
continue ;
cmnd = devinfo - > cmnd [ i ] ;
cmdinfo = ( void * ) & cmnd - > SCp ;
2013-11-12 13:44:20 +01:00
if ( ! ( cmdinfo - > state & IS_IN_WORK_LIST ) )
continue ;
2015-11-03 16:43:17 +01:00
err = uas_submit_urbs ( cmnd , cmnd - > device - > hostdata ) ;
2013-11-12 13:44:20 +01:00
if ( ! err )
2012-11-30 11:54:42 +01:00
cmdinfo - > state & = ~ IS_IN_WORK_LIST ;
2013-11-12 13:44:20 +01:00
else
2020-04-15 16:17:50 +02:00
queue_work ( workqueue , & devinfo - > work ) ;
2010-10-07 13:05:23 +02:00
}
2014-09-13 12:26:30 +02:00
out :
2012-11-30 11:54:44 +01:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
}
2020-01-30 01:25:06 -08:00
static void uas_scan_work ( struct work_struct * work )
{
struct uas_dev_info * devinfo =
container_of ( work , struct uas_dev_info , scan_work ) ;
struct Scsi_Host * shost = usb_get_intfdata ( devinfo - > intf ) ;
dev_dbg ( & devinfo - > intf - > dev , " starting scan \n " ) ;
scsi_scan_host ( shost ) ;
dev_dbg ( & devinfo - > intf - > dev , " scan complete \n " ) ;
}
2013-09-13 13:27:12 +02:00
static void uas_add_work ( struct uas_cmd_info * cmdinfo )
{
struct scsi_pointer * scp = ( void * ) cmdinfo ;
struct scsi_cmnd * cmnd = container_of ( scp , struct scsi_cmnd , SCp ) ;
struct uas_dev_info * devinfo = cmnd - > device - > hostdata ;
2014-08-12 12:10:21 +05:30
lockdep_assert_held ( & devinfo - > lock ) ;
2013-09-13 13:27:12 +02:00
cmdinfo - > state | = IS_IN_WORK_LIST ;
2020-04-15 16:17:50 +02:00
queue_work ( workqueue , & devinfo - > work ) ;
2013-09-13 13:27:12 +02:00
}
2014-09-13 12:26:36 +02:00
static void uas_zap_pending ( struct uas_dev_info * devinfo , int result )
2013-09-13 13:27:13 +02:00
{
struct uas_cmd_info * cmdinfo ;
2014-09-13 12:26:38 +02:00
struct scsi_cmnd * cmnd ;
2013-09-13 13:27:13 +02:00
unsigned long flags ;
2014-09-13 12:26:38 +02:00
int i , err ;
2013-09-13 13:27:13 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2014-09-13 12:26:38 +02:00
for ( i = 0 ; i < devinfo - > qdepth ; i + + ) {
if ( ! devinfo - > cmnd [ i ] )
continue ;
cmnd = devinfo - > cmnd [ i ] ;
cmdinfo = ( void * ) & cmnd - > SCp ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , __func__ , 0 ) ;
2014-09-13 12:26:37 +02:00
/* Sense urbs were killed, clear COMMAND_INFLIGHT manually */
cmdinfo - > state & = ~ COMMAND_INFLIGHT ;
2014-09-13 12:26:36 +02:00
cmnd - > result = result < < 16 ;
2014-09-13 12:26:37 +02:00
err = uas_try_complete ( cmnd , __func__ ) ;
WARN_ON ( err ! = 0 ) ;
2013-09-13 13:27:13 +02:00
}
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
}
2010-10-07 13:05:23 +02:00
static void uas_sense ( struct urb * urb , struct scsi_cmnd * cmnd )
{
struct sense_iu * sense_iu = urb - > transfer_buffer ;
struct scsi_device * sdev = cmnd - > device ;
if ( urb - > actual_length > 16 ) {
unsigned len = be16_to_cpup ( & sense_iu - > len ) ;
if ( len + 16 ! = urb - > actual_length ) {
int newlen = min ( len + 16 , urb - > actual_length ) - 16 ;
if ( newlen < 0 )
newlen = 0 ;
sdev_printk ( KERN_INFO , sdev , " %s: urb length %d "
" disagrees with IU sense data length %d, "
" using %d bytes of sense data \n " , __func__ ,
urb - > actual_length , len , newlen ) ;
len = newlen ;
}
memcpy ( cmnd - > sense_buffer , sense_iu - > sense , len ) ;
}
cmnd - > result = sense_iu - > status ;
}
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
static void uas_log_cmd_state ( struct scsi_cmnd * cmnd , const char * prefix ,
int status )
2012-06-19 09:54:51 +02:00
{
struct uas_cmd_info * ci = ( void * ) & cmnd - > SCp ;
2014-10-12 12:19:40 +02:00
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2012-06-19 09:54:51 +02:00
2020-04-15 16:17:49 +02:00
if ( status = = - ENODEV ) /* too late */
return ;
2014-09-13 12:26:34 +02:00
scmd_printk ( KERN_INFO , cmnd ,
2014-10-12 12:19:40 +02:00
" %s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s " ,
prefix , status , cmdinfo - > uas_tag ,
2012-06-19 09:54:51 +02:00
( ci - > state & SUBMIT_STATUS_URB ) ? " s-st " : " " ,
( ci - > state & ALLOC_DATA_IN_URB ) ? " a-in " : " " ,
( ci - > state & SUBMIT_DATA_IN_URB ) ? " s-in " : " " ,
( ci - > state & ALLOC_DATA_OUT_URB ) ? " a-out " : " " ,
( ci - > state & SUBMIT_DATA_OUT_URB ) ? " s-out " : " " ,
( ci - > state & ALLOC_CMD_URB ) ? " a-cmd " : " " ,
( ci - > state & SUBMIT_CMD_URB ) ? " s-cmd " : " " ,
( ci - > state & COMMAND_INFLIGHT ) ? " CMD " : " " ,
( ci - > state & DATA_IN_URB_INFLIGHT ) ? " IN " : " " ,
( ci - > state & DATA_OUT_URB_INFLIGHT ) ? " OUT " : " " ,
2012-11-30 11:54:41 +01:00
( ci - > state & COMMAND_ABORTED ) ? " abort " : " " ,
2012-11-30 11:54:42 +01:00
( ci - > state & IS_IN_WORK_LIST ) ? " work " : " " ) ;
2014-09-13 12:26:45 +02:00
scsi_print_command ( cmnd ) ;
2012-06-19 09:54:51 +02:00
}
2014-09-13 12:26:41 +02:00
static void uas_free_unsubmitted_urbs ( struct scsi_cmnd * cmnd )
{
struct uas_cmd_info * cmdinfo ;
if ( ! cmnd )
return ;
cmdinfo = ( void * ) & cmnd - > SCp ;
if ( cmdinfo - > state & SUBMIT_CMD_URB )
usb_free_urb ( cmdinfo - > cmd_urb ) ;
/* data urbs may have never gotten their submit flag set */
if ( ! ( cmdinfo - > state & DATA_IN_URB_INFLIGHT ) )
usb_free_urb ( cmdinfo - > data_in_urb ) ;
if ( ! ( cmdinfo - > state & DATA_OUT_URB_INFLIGHT ) )
usb_free_urb ( cmdinfo - > data_out_urb ) ;
2012-06-19 09:54:51 +02:00
}
static int uas_try_complete ( struct scsi_cmnd * cmnd , const char * caller )
{
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2012-09-25 10:47:08 +02:00
struct uas_dev_info * devinfo = ( void * ) cmnd - > device - > hostdata ;
2012-06-19 09:54:51 +02:00
2014-08-12 12:10:21 +05:30
lockdep_assert_held ( & devinfo - > lock ) ;
2012-06-19 09:54:51 +02:00
if ( cmdinfo - > state & ( COMMAND_INFLIGHT |
DATA_IN_URB_INFLIGHT |
2012-11-30 11:54:41 +01:00
DATA_OUT_URB_INFLIGHT |
2014-09-13 12:26:40 +02:00
COMMAND_ABORTED ) )
2012-06-19 09:54:51 +02:00
return - EBUSY ;
2014-10-12 12:19:40 +02:00
devinfo - > cmnd [ cmdinfo - > uas_tag - 1 ] = NULL ;
2014-09-13 12:26:41 +02:00
uas_free_unsubmitted_urbs ( cmnd ) ;
2012-06-19 09:54:48 +02:00
cmnd - > scsi_done ( cmnd ) ;
2012-06-19 09:54:51 +02:00
return 0 ;
2010-10-07 13:05:23 +02:00
}
static void uas_xfer_data ( struct urb * urb , struct scsi_cmnd * cmnd ,
2012-06-19 09:54:51 +02:00
unsigned direction )
2010-10-07 13:05:23 +02:00
{
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
int err ;
2012-06-19 09:54:51 +02:00
cmdinfo - > state | = direction | SUBMIT_STATUS_URB ;
2015-11-03 16:43:17 +01:00
err = uas_submit_urbs ( cmnd , cmnd - > device - > hostdata ) ;
2010-10-07 13:05:23 +02:00
if ( err ) {
2013-09-13 13:27:12 +02:00
uas_add_work ( cmdinfo ) ;
2010-10-07 13:05:23 +02:00
}
}
2016-01-19 10:51:09 +01:00
static bool uas_evaluate_response_iu ( struct response_iu * riu , struct scsi_cmnd * cmnd )
{
u8 response_code = riu - > response_code ;
switch ( response_code ) {
case RC_INCORRECT_LUN :
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_BAD_TARGET ) ;
2016-01-19 10:51:09 +01:00
break ;
case RC_TMF_SUCCEEDED :
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_OK ) ;
2016-01-19 10:51:09 +01:00
break ;
case RC_TMF_NOT_SUPPORTED :
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_TARGET_FAILURE ) ;
2016-01-19 10:51:09 +01:00
break ;
default :
uas_log_cmd_state ( cmnd , " response iu " , response_code ) ;
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_ERROR ) ;
2016-01-19 10:51:09 +01:00
break ;
}
return response_code = = RC_TMF_SUCCEEDED ;
}
2010-10-07 13:05:23 +02:00
static void uas_stat_cmplt ( struct urb * urb )
{
struct iu * iu = urb - > transfer_buffer ;
2011-12-19 20:22:39 +01:00
struct Scsi_Host * shost = urb - > context ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2014-09-13 12:26:34 +02:00
struct urb * data_in_urb = NULL ;
struct urb * data_out_urb = NULL ;
2010-10-07 13:05:23 +02:00
struct scsi_cmnd * cmnd ;
2012-06-19 09:54:51 +02:00
struct uas_cmd_info * cmdinfo ;
2012-09-25 10:47:08 +02:00
unsigned long flags ;
2014-09-13 12:26:32 +02:00
unsigned int idx ;
2015-08-24 11:10:43 +02:00
int status = urb - > status ;
2016-01-19 10:51:09 +01:00
bool success ;
2010-10-07 13:05:23 +02:00
2014-09-13 12:26:30 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
if ( devinfo - > resetting )
goto out ;
2010-10-07 13:05:23 +02:00
2015-08-24 11:10:43 +02:00
if ( status ) {
if ( status ! = - ENOENT & & status ! = - ECONNRESET & & status ! = - ESHUTDOWN )
dev_err ( & urb - > dev - > dev , " stat urb: status %d \n " , status ) ;
2014-09-13 12:26:30 +02:00
goto out ;
2010-10-07 13:05:23 +02:00
}
2014-09-13 12:26:32 +02:00
idx = be16_to_cpup ( & iu - > tag ) - 1 ;
if ( idx > = MAX_CMNDS | | ! devinfo - > cmnd [ idx ] ) {
dev_err ( & urb - > dev - > dev ,
2014-10-12 12:19:40 +02:00
" stat urb: no pending cmd for uas-tag %d \n " , idx + 1 ) ;
2014-09-13 12:26:30 +02:00
goto out ;
2012-06-19 09:54:54 +02:00
}
2014-09-13 12:26:32 +02:00
cmnd = devinfo - > cmnd [ idx ] ;
2012-09-26 10:29:03 +02:00
cmdinfo = ( void * ) & cmnd - > SCp ;
2014-09-13 12:26:33 +02:00
if ( ! ( cmdinfo - > state & COMMAND_INFLIGHT ) ) {
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " unexpected status cmplt " , 0 ) ;
2014-09-13 12:26:33 +02:00
goto out ;
2011-12-02 11:55:48 -08:00
}
2010-10-07 13:05:23 +02:00
switch ( iu - > iu_id ) {
case IU_ID_STATUS :
2014-09-13 12:26:47 +02:00
uas_sense ( urb , cmnd ) ;
2012-06-19 09:54:52 +02:00
if ( cmnd - > result ! = 0 ) {
/* cancel data transfers on error */
2014-09-13 12:26:34 +02:00
data_in_urb = usb_get_urb ( cmdinfo - > data_in_urb ) ;
data_out_urb = usb_get_urb ( cmdinfo - > data_out_urb ) ;
2012-06-19 09:54:52 +02:00
}
2012-06-19 09:54:51 +02:00
cmdinfo - > state & = ~ COMMAND_INFLIGHT ;
uas_try_complete ( cmnd , __func__ ) ;
2010-10-07 13:05:23 +02:00
break ;
case IU_ID_READ_READY :
2013-11-15 10:04:11 +01:00
if ( ! cmdinfo - > data_in_urb | |
( cmdinfo - > state & DATA_IN_URB_INFLIGHT ) ) {
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " unexpected read rdy " , 0 ) ;
2013-11-15 10:04:11 +01:00
break ;
}
2010-10-07 13:05:23 +02:00
uas_xfer_data ( urb , cmnd , SUBMIT_DATA_IN_URB ) ;
break ;
case IU_ID_WRITE_READY :
2013-11-15 10:04:11 +01:00
if ( ! cmdinfo - > data_out_urb | |
( cmdinfo - > state & DATA_OUT_URB_INFLIGHT ) ) {
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " unexpected write rdy " , 0 ) ;
2013-11-15 10:04:11 +01:00
break ;
}
2010-10-07 13:05:23 +02:00
uas_xfer_data ( urb , cmnd , SUBMIT_DATA_OUT_URB ) ;
break ;
2014-09-13 12:26:51 +02:00
case IU_ID_RESPONSE :
cmdinfo - > state & = ~ COMMAND_INFLIGHT ;
2016-01-19 10:51:09 +01:00
success = uas_evaluate_response_iu ( ( struct response_iu * ) iu , cmnd ) ;
if ( ! success ) {
/* Error, cancel data transfers */
data_in_urb = usb_get_urb ( cmdinfo - > data_in_urb ) ;
data_out_urb = usb_get_urb ( cmdinfo - > data_out_urb ) ;
}
2014-09-13 12:26:51 +02:00
uas_try_complete ( cmnd , __func__ ) ;
break ;
2010-10-07 13:05:23 +02:00
default :
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " bogus IU " , iu - > iu_id ) ;
2010-10-07 13:05:23 +02:00
}
2014-09-13 12:26:30 +02:00
out :
2012-06-19 09:54:50 +02:00
usb_free_urb ( urb ) ;
2012-09-25 10:47:08 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2014-09-13 12:26:34 +02:00
/* Unlinking of data urbs must be done without holding the lock */
if ( data_in_urb ) {
usb_unlink_urb ( data_in_urb ) ;
usb_put_urb ( data_in_urb ) ;
}
if ( data_out_urb ) {
usb_unlink_urb ( data_out_urb ) ;
usb_put_urb ( data_out_urb ) ;
}
2010-10-07 13:05:23 +02:00
}
2012-06-19 09:54:48 +02:00
static void uas_data_cmplt ( struct urb * urb )
2010-10-07 13:05:23 +02:00
{
2012-06-19 09:54:51 +02:00
struct scsi_cmnd * cmnd = urb - > context ;
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2012-09-25 10:47:08 +02:00
struct uas_dev_info * devinfo = ( void * ) cmnd - > device - > hostdata ;
2019-01-29 09:33:07 +01:00
struct scsi_data_buffer * sdb = & cmnd - > sdb ;
2012-09-25 10:47:08 +02:00
unsigned long flags ;
2015-08-24 11:10:43 +02:00
int status = urb - > status ;
2012-06-19 09:54:51 +02:00
2012-09-25 10:47:08 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2014-09-13 12:26:30 +02:00
2012-06-19 09:54:51 +02:00
if ( cmdinfo - > data_in_urb = = urb ) {
cmdinfo - > state & = ~ DATA_IN_URB_INFLIGHT ;
2014-09-13 12:26:35 +02:00
cmdinfo - > data_in_urb = NULL ;
2012-06-19 09:54:51 +02:00
} else if ( cmdinfo - > data_out_urb = = urb ) {
cmdinfo - > state & = ~ DATA_OUT_URB_INFLIGHT ;
2014-09-13 12:26:35 +02:00
cmdinfo - > data_out_urb = NULL ;
2012-06-19 09:54:51 +02:00
}
2014-09-13 12:26:30 +02:00
if ( devinfo - > resetting )
goto out ;
2014-09-13 12:26:33 +02:00
/* Data urbs should not complete before the cmd urb is submitted */
if ( cmdinfo - > state & SUBMIT_CMD_URB ) {
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " unexpected data cmplt " , 0 ) ;
2014-09-13 12:26:33 +02:00
goto out ;
}
2015-08-24 11:10:43 +02:00
if ( status ) {
if ( status ! = - ENOENT & & status ! = - ECONNRESET & & status ! = - ESHUTDOWN )
uas_log_cmd_state ( cmnd , " data cmplt err " , status ) ;
2012-06-19 09:54:52 +02:00
/* error: no data transfered */
2019-02-08 13:25:01 -08:00
scsi_set_resid ( cmnd , sdb - > length ) ;
2012-06-19 09:54:52 +02:00
} else {
2019-02-08 13:25:01 -08:00
scsi_set_resid ( cmnd , sdb - > length - urb - > actual_length ) ;
2012-06-19 09:54:52 +02:00
}
2012-06-19 09:54:51 +02:00
uas_try_complete ( cmnd , __func__ ) ;
2014-09-13 12:26:30 +02:00
out :
2014-09-13 12:26:35 +02:00
usb_free_urb ( urb ) ;
2012-09-25 10:47:08 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2010-10-07 13:05:23 +02:00
}
2013-11-07 08:52:42 +01:00
static void uas_cmd_cmplt ( struct urb * urb )
{
2014-09-13 12:26:39 +02:00
if ( urb - > status )
dev_err ( & urb - > dev - > dev , " cmd cmplt err %d \n " , urb - > status ) ;
2013-11-07 08:52:42 +01:00
usb_free_urb ( urb ) ;
}
2010-10-07 13:05:23 +02:00
static struct urb * uas_alloc_data_urb ( struct uas_dev_info * devinfo , gfp_t gfp ,
2012-06-19 09:54:51 +02:00
struct scsi_cmnd * cmnd ,
enum dma_data_direction dir )
2010-10-07 13:05:23 +02:00
{
struct usb_device * udev = devinfo - > udev ;
2014-10-03 12:08:56 +02:00
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2010-10-07 13:05:23 +02:00
struct urb * urb = usb_alloc_urb ( 0 , gfp ) ;
2019-01-29 09:33:07 +01:00
struct scsi_data_buffer * sdb = & cmnd - > sdb ;
2014-10-03 12:08:56 +02:00
unsigned int pipe = ( dir = = DMA_FROM_DEVICE )
? devinfo - > data_in_pipe : devinfo - > data_out_pipe ;
2010-10-07 13:05:23 +02:00
if ( ! urb )
goto out ;
2012-06-19 09:54:51 +02:00
usb_fill_bulk_urb ( urb , udev , pipe , NULL , sdb - > length ,
uas_data_cmplt , cmnd ) ;
2014-10-12 12:19:40 +02:00
if ( devinfo - > use_streams )
urb - > stream_id = cmdinfo - > uas_tag ;
2010-10-07 13:05:23 +02:00
urb - > num_sgs = udev - > bus - > sg_tablesize ? sdb - > table . nents : 0 ;
urb - > sg = sdb - > table . sgl ;
out :
return urb ;
}
static struct urb * uas_alloc_sense_urb ( struct uas_dev_info * devinfo , gfp_t gfp ,
2014-10-03 12:08:56 +02:00
struct scsi_cmnd * cmnd )
2010-10-07 13:05:23 +02:00
{
struct usb_device * udev = devinfo - > udev ;
2014-10-03 12:08:56 +02:00
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2010-10-07 13:05:23 +02:00
struct urb * urb = usb_alloc_urb ( 0 , gfp ) ;
struct sense_iu * iu ;
if ( ! urb )
goto out ;
2010-12-15 15:44:03 -05:00
iu = kzalloc ( sizeof ( * iu ) , gfp ) ;
2010-10-07 13:05:23 +02:00
if ( ! iu )
goto free ;
usb_fill_bulk_urb ( urb , udev , devinfo - > status_pipe , iu , sizeof ( * iu ) ,
2014-10-03 12:08:56 +02:00
uas_stat_cmplt , cmnd - > device - > host ) ;
2014-10-12 12:19:40 +02:00
if ( devinfo - > use_streams )
urb - > stream_id = cmdinfo - > uas_tag ;
2010-10-07 13:05:23 +02:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
out :
return urb ;
free :
usb_free_urb ( urb ) ;
return NULL ;
}
static struct urb * uas_alloc_cmd_urb ( struct uas_dev_info * devinfo , gfp_t gfp ,
2013-10-17 19:47:28 +02:00
struct scsi_cmnd * cmnd )
2010-10-07 13:05:23 +02:00
{
struct usb_device * udev = devinfo - > udev ;
struct scsi_device * sdev = cmnd - > device ;
2014-10-12 12:19:40 +02:00
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2010-10-07 13:05:23 +02:00
struct urb * urb = usb_alloc_urb ( 0 , gfp ) ;
struct command_iu * iu ;
int len ;
if ( ! urb )
goto out ;
len = cmnd - > cmd_len - 16 ;
if ( len < 0 )
len = 0 ;
len = ALIGN ( len , 4 ) ;
2010-12-15 15:44:03 -05:00
iu = kzalloc ( sizeof ( * iu ) + len , gfp ) ;
2010-10-07 13:05:23 +02:00
if ( ! iu )
goto free ;
iu - > iu_id = IU_ID_COMMAND ;
2014-10-12 12:19:40 +02:00
iu - > tag = cpu_to_be16 ( cmdinfo - > uas_tag ) ;
2010-11-10 14:54:09 +01:00
iu - > prio_attr = UAS_SIMPLE_TAG ;
2010-10-07 13:05:23 +02:00
iu - > len = len ;
int_to_scsilun ( sdev - > lun , & iu - > lun ) ;
memcpy ( iu - > cdb , cmnd - > cmnd , cmnd - > cmd_len ) ;
usb_fill_bulk_urb ( urb , udev , devinfo - > cmd_pipe , iu , sizeof ( * iu ) + len ,
2014-09-13 12:26:39 +02:00
uas_cmd_cmplt , NULL ) ;
2010-10-07 13:05:23 +02:00
urb - > transfer_flags | = URB_FREE_BUFFER ;
out :
return urb ;
free :
usb_free_urb ( urb ) ;
return NULL ;
}
/*
* Why should I request the Status IU before sending the Command IU ? Spec
* says to , but also says the device may receive them in any order . Seems
* daft to me .
*/
2014-10-03 12:08:56 +02:00
static struct urb * uas_submit_sense_urb ( struct scsi_cmnd * cmnd , gfp_t gfp )
2010-10-07 13:05:23 +02:00
{
2014-10-03 12:08:56 +02:00
struct uas_dev_info * devinfo = cmnd - > device - > hostdata ;
2012-06-19 09:54:50 +02:00
struct urb * urb ;
2013-11-07 08:52:42 +01:00
int err ;
2010-10-07 13:05:23 +02:00
2014-10-03 12:08:56 +02:00
urb = uas_alloc_sense_urb ( devinfo , gfp , cmnd ) ;
2012-06-19 09:54:50 +02:00
if ( ! urb )
2013-10-29 10:37:23 +01:00
return NULL ;
2013-10-17 19:30:26 +02:00
usb_anchor_urb ( urb , & devinfo - > sense_urbs ) ;
2013-11-07 08:52:42 +01:00
err = usb_submit_urb ( urb , gfp ) ;
if ( err ) {
2013-10-17 19:30:26 +02:00
usb_unanchor_urb ( urb ) ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " sense submit err " , err ) ;
2012-06-19 09:54:50 +02:00
usb_free_urb ( urb ) ;
2013-10-29 10:37:23 +01:00
return NULL ;
2010-10-07 13:05:23 +02:00
}
2013-10-29 10:37:23 +01:00
return urb ;
2012-06-19 09:54:50 +02:00
}
static int uas_submit_urbs ( struct scsi_cmnd * cmnd ,
2015-11-03 16:43:17 +01:00
struct uas_dev_info * devinfo )
2012-06-19 09:54:50 +02:00
{
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2013-10-29 10:37:23 +01:00
struct urb * urb ;
2013-11-07 08:52:42 +01:00
int err ;
2010-10-07 13:05:23 +02:00
2014-08-12 12:10:21 +05:30
lockdep_assert_held ( & devinfo - > lock ) ;
2010-12-15 15:44:04 -05:00
if ( cmdinfo - > state & SUBMIT_STATUS_URB ) {
2015-11-03 16:43:17 +01:00
urb = uas_submit_sense_urb ( cmnd , GFP_ATOMIC ) ;
2013-10-29 10:37:23 +01:00
if ( ! urb )
return SCSI_MLQUEUE_DEVICE_BUSY ;
2010-12-15 15:44:04 -05:00
cmdinfo - > state & = ~ SUBMIT_STATUS_URB ;
2010-10-07 13:05:23 +02:00
}
if ( cmdinfo - > state & ALLOC_DATA_IN_URB ) {
2015-11-03 16:43:17 +01:00
cmdinfo - > data_in_urb = uas_alloc_data_urb ( devinfo , GFP_ATOMIC ,
2014-10-03 12:08:56 +02:00
cmnd , DMA_FROM_DEVICE ) ;
2010-10-07 13:05:23 +02:00
if ( ! cmdinfo - > data_in_urb )
return SCSI_MLQUEUE_DEVICE_BUSY ;
cmdinfo - > state & = ~ ALLOC_DATA_IN_URB ;
}
if ( cmdinfo - > state & SUBMIT_DATA_IN_URB ) {
2013-10-17 19:30:26 +02:00
usb_anchor_urb ( cmdinfo - > data_in_urb , & devinfo - > data_urbs ) ;
2015-11-03 16:43:17 +01:00
err = usb_submit_urb ( cmdinfo - > data_in_urb , GFP_ATOMIC ) ;
2013-11-07 08:52:42 +01:00
if ( err ) {
2013-10-17 19:30:26 +02:00
usb_unanchor_urb ( cmdinfo - > data_in_urb ) ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " data in submit err " , err ) ;
2010-10-07 13:05:23 +02:00
return SCSI_MLQUEUE_DEVICE_BUSY ;
}
cmdinfo - > state & = ~ SUBMIT_DATA_IN_URB ;
2012-06-19 09:54:51 +02:00
cmdinfo - > state | = DATA_IN_URB_INFLIGHT ;
2010-10-07 13:05:23 +02:00
}
if ( cmdinfo - > state & ALLOC_DATA_OUT_URB ) {
2015-11-03 16:43:17 +01:00
cmdinfo - > data_out_urb = uas_alloc_data_urb ( devinfo , GFP_ATOMIC ,
2014-10-03 12:08:56 +02:00
cmnd , DMA_TO_DEVICE ) ;
2010-10-07 13:05:23 +02:00
if ( ! cmdinfo - > data_out_urb )
return SCSI_MLQUEUE_DEVICE_BUSY ;
cmdinfo - > state & = ~ ALLOC_DATA_OUT_URB ;
}
if ( cmdinfo - > state & SUBMIT_DATA_OUT_URB ) {
2013-10-17 19:30:26 +02:00
usb_anchor_urb ( cmdinfo - > data_out_urb , & devinfo - > data_urbs ) ;
2015-11-03 16:43:17 +01:00
err = usb_submit_urb ( cmdinfo - > data_out_urb , GFP_ATOMIC ) ;
2013-11-07 08:52:42 +01:00
if ( err ) {
2013-10-17 19:30:26 +02:00
usb_unanchor_urb ( cmdinfo - > data_out_urb ) ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " data out submit err " , err ) ;
2010-10-07 13:05:23 +02:00
return SCSI_MLQUEUE_DEVICE_BUSY ;
}
cmdinfo - > state & = ~ SUBMIT_DATA_OUT_URB ;
2012-06-19 09:54:51 +02:00
cmdinfo - > state | = DATA_OUT_URB_INFLIGHT ;
2010-10-07 13:05:23 +02:00
}
if ( cmdinfo - > state & ALLOC_CMD_URB ) {
2015-11-03 16:43:17 +01:00
cmdinfo - > cmd_urb = uas_alloc_cmd_urb ( devinfo , GFP_ATOMIC , cmnd ) ;
2010-10-07 13:05:23 +02:00
if ( ! cmdinfo - > cmd_urb )
return SCSI_MLQUEUE_DEVICE_BUSY ;
cmdinfo - > state & = ~ ALLOC_CMD_URB ;
}
if ( cmdinfo - > state & SUBMIT_CMD_URB ) {
2013-10-17 19:30:26 +02:00
usb_anchor_urb ( cmdinfo - > cmd_urb , & devinfo - > cmd_urbs ) ;
2015-11-03 16:43:17 +01:00
err = usb_submit_urb ( cmdinfo - > cmd_urb , GFP_ATOMIC ) ;
2013-11-07 08:52:42 +01:00
if ( err ) {
2013-10-17 19:30:26 +02:00
usb_unanchor_urb ( cmdinfo - > cmd_urb ) ;
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , " cmd submit err " , err ) ;
2010-10-07 13:05:23 +02:00
return SCSI_MLQUEUE_DEVICE_BUSY ;
}
2012-09-25 10:47:04 +02:00
cmdinfo - > cmd_urb = NULL ;
2010-10-07 13:05:23 +02:00
cmdinfo - > state & = ~ SUBMIT_CMD_URB ;
2012-06-19 09:54:51 +02:00
cmdinfo - > state | = COMMAND_INFLIGHT ;
2010-10-07 13:05:23 +02:00
}
return 0 ;
}
2010-11-16 02:10:29 -05:00
static int uas_queuecommand_lck ( struct scsi_cmnd * cmnd ,
2010-10-07 13:05:23 +02:00
void ( * done ) ( struct scsi_cmnd * ) )
{
struct scsi_device * sdev = cmnd - > device ;
struct uas_dev_info * devinfo = sdev - > hostdata ;
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
2012-09-25 10:47:08 +02:00
unsigned long flags ;
2014-10-12 12:19:40 +02:00
int idx , err ;
2010-10-07 13:05:23 +02:00
BUILD_BUG_ON ( sizeof ( struct uas_cmd_info ) > sizeof ( struct scsi_pointer ) ) ;
2014-09-13 12:26:42 +02:00
/* Re-check scsi_block_requests now that we've the host-lock */
if ( cmnd - > device - > host - > host_self_blocked )
return SCSI_MLQUEUE_DEVICE_BUSY ;
2014-09-15 16:04:12 +02:00
if ( ( devinfo - > flags & US_FL_NO_ATA_1X ) & &
( cmnd - > cmnd [ 0 ] = = ATA_12 | | cmnd - > cmnd [ 0 ] = = ATA_16 ) ) {
memcpy ( cmnd - > sense_buffer , usb_stor_sense_invalidCDB ,
sizeof ( usb_stor_sense_invalidCDB ) ) ;
cmnd - > result = SAM_STAT_CHECK_CONDITION ;
cmnd - > scsi_done ( cmnd ) ;
return 0 ;
}
2013-11-13 09:24:15 +01:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2012-11-30 11:54:45 +01:00
if ( devinfo - > resetting ) {
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_ERROR ) ;
2012-11-30 11:54:45 +01:00
cmnd - > scsi_done ( cmnd ) ;
2020-09-16 11:40:25 +02:00
goto zombie ;
2012-11-30 11:54:45 +01:00
}
2014-10-12 12:19:40 +02:00
/* Find a free uas-tag */
for ( idx = 0 ; idx < devinfo - > qdepth ; idx + + ) {
if ( ! devinfo - > cmnd [ idx ] )
break ;
}
if ( idx = = devinfo - > qdepth ) {
2012-09-25 10:47:08 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2010-10-07 13:05:23 +02:00
return SCSI_MLQUEUE_DEVICE_BUSY ;
2012-09-25 10:47:08 +02:00
}
2010-10-07 13:05:23 +02:00
cmnd - > scsi_done = done ;
2014-09-13 12:26:32 +02:00
memset ( cmdinfo , 0 , sizeof ( * cmdinfo ) ) ;
2014-10-12 12:19:40 +02:00
cmdinfo - > uas_tag = idx + 1 ; /* uas-tag == usb-stream-id, so 1 based */
2014-09-13 12:26:31 +02:00
cmdinfo - > state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB ;
2010-10-07 13:05:23 +02:00
switch ( cmnd - > sc_data_direction ) {
case DMA_FROM_DEVICE :
cmdinfo - > state | = ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB ;
break ;
case DMA_BIDIRECTIONAL :
cmdinfo - > state | = ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB ;
2020-08-23 17:36:59 -05:00
fallthrough ;
2010-10-07 13:05:23 +02:00
case DMA_TO_DEVICE :
cmdinfo - > state | = ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB ;
2020-11-20 12:40:27 -06:00
break ;
2010-10-07 13:05:23 +02:00
case DMA_NONE :
break ;
}
2014-10-12 12:19:40 +02:00
if ( ! devinfo - > use_streams )
2012-06-19 09:54:49 +02:00
cmdinfo - > state & = ~ ( SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB ) ;
2010-10-07 13:05:23 +02:00
2015-11-03 16:43:17 +01:00
err = uas_submit_urbs ( cmnd , devinfo ) ;
2020-09-16 11:40:25 +02:00
/*
* in case of fatal errors the SCSI layer is peculiar
* a command that has finished is a success for the purpose
* of queueing , no matter how fatal the error
*/
if ( err = = - ENODEV ) {
2020-09-16 11:40:26 +02:00
set_host_byte ( cmnd , DID_ERROR ) ;
2020-09-16 11:40:25 +02:00
cmnd - > scsi_done ( cmnd ) ;
goto zombie ;
}
2010-10-07 13:05:23 +02:00
if ( err ) {
/* If we did nothing, give up now */
2010-12-15 15:44:04 -05:00
if ( cmdinfo - > state & SUBMIT_STATUS_URB ) {
2012-09-25 10:47:08 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2010-10-07 13:05:23 +02:00
return SCSI_MLQUEUE_DEVICE_BUSY ;
}
2013-09-13 13:27:12 +02:00
uas_add_work ( cmdinfo ) ;
2010-10-07 13:05:23 +02:00
}
2014-10-12 12:19:40 +02:00
devinfo - > cmnd [ idx ] = cmnd ;
2020-09-16 11:40:25 +02:00
zombie :
2012-09-25 10:47:08 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2010-10-07 13:05:23 +02:00
return 0 ;
}
2010-11-16 02:10:29 -05:00
static DEF_SCSI_QCMD ( uas_queuecommand )
2014-09-13 12:26:40 +02:00
/*
* For now we do not support actually sending an abort to the device , so
* this eh always fails . Still we must define it to make sure that we ' ve
* dropped all references to the cmnd in question once this function exits .
*/
static int uas_eh_abort_handler ( struct scsi_cmnd * cmnd )
2010-10-07 13:05:23 +02:00
{
2014-09-13 12:26:40 +02:00
struct uas_cmd_info * cmdinfo = ( void * ) & cmnd - > SCp ;
struct uas_dev_info * devinfo = ( void * ) cmnd - > device - > hostdata ;
struct urb * data_in_urb = NULL ;
struct urb * data_out_urb = NULL ;
2012-09-25 10:47:08 +02:00
unsigned long flags ;
2010-10-07 13:05:23 +02:00
2012-09-25 10:47:08 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2013-10-29 10:51:00 +01:00
uas: Cleanup uas_log_cmd_state usage
Instead of doing:
uas_log_cmd_state(cmnd, __func__)
scmd_printk(KERN_ERR, cmnd, "error doing foo %d\n", err)
On error, resulting in 2 log calls for a single error, make uas_log_cmd_state
take a status code, and change calls like the above to:
uas_log_cmd_state(cmnd, "error doing foo", err)
Also change various sanity checks (which should never trigger) from:
"scmd_printk(KERN_ERR, cmnd, "sanity foo failed\n")" to calling the new
uas_log_cmd_state(), so that when they do trigger we get more info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2014-09-13 12:26:49 +02:00
uas_log_cmd_state ( cmnd , __func__ , 0 ) ;
2013-11-13 09:24:15 +01:00
2014-09-13 12:26:40 +02:00
/* Ensure that try_complete does not call scsi_done */
cmdinfo - > state | = COMMAND_ABORTED ;
2013-10-29 10:51:00 +01:00
2014-09-13 12:26:40 +02:00
/* Drop all refs to this cmnd, kill data urbs to break their ref */
2014-10-12 12:19:40 +02:00
devinfo - > cmnd [ cmdinfo - > uas_tag - 1 ] = NULL ;
2014-09-13 12:26:40 +02:00
if ( cmdinfo - > state & DATA_IN_URB_INFLIGHT )
data_in_urb = usb_get_urb ( cmdinfo - > data_in_urb ) ;
if ( cmdinfo - > state & DATA_OUT_URB_INFLIGHT )
data_out_urb = usb_get_urb ( cmdinfo - > data_out_urb ) ;
2012-09-25 10:47:08 +02:00
2014-09-13 12:26:41 +02:00
uas_free_unsubmitted_urbs ( cmnd ) ;
2013-10-29 10:51:00 +01:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2014-09-13 12:26:40 +02:00
if ( data_in_urb ) {
usb_kill_urb ( data_in_urb ) ;
usb_put_urb ( data_in_urb ) ;
2013-11-13 09:24:15 +01:00
}
2014-09-13 12:26:40 +02:00
if ( data_out_urb ) {
usb_kill_urb ( data_out_urb ) ;
usb_put_urb ( data_out_urb ) ;
2012-11-30 11:54:43 +01:00
}
2010-10-07 13:05:23 +02:00
2014-09-13 12:26:40 +02:00
return FAILED ;
2010-10-07 13:05:23 +02:00
}
2017-08-25 13:57:01 +02:00
static int uas_eh_device_reset_handler ( struct scsi_cmnd * cmnd )
2010-10-07 13:05:23 +02:00
{
struct scsi_device * sdev = cmnd - > device ;
struct uas_dev_info * devinfo = sdev - > hostdata ;
struct usb_device * udev = devinfo - > udev ;
2014-09-13 12:26:30 +02:00
unsigned long flags ;
2012-06-19 09:54:54 +02:00
int err ;
2010-10-07 13:05:23 +02:00
2013-09-22 16:27:02 +02:00
err = usb_lock_device_for_reset ( udev , devinfo - > intf ) ;
if ( err ) {
shost_printk ( KERN_ERR , sdev - > host ,
" %s FAILED to get lock err %d \n " , __func__ , err ) ;
return FAILED ;
}
2013-09-13 13:27:13 +02:00
shost_printk ( KERN_INFO , sdev - > host , " %s start \n " , __func__ ) ;
2014-09-13 12:26:30 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2012-06-19 09:54:54 +02:00
devinfo - > resetting = 1 ;
2014-09-13 12:26:30 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2012-09-25 10:47:04 +02:00
usb_kill_anchored_urbs ( & devinfo - > cmd_urbs ) ;
2012-06-19 09:54:54 +02:00
usb_kill_anchored_urbs ( & devinfo - > sense_urbs ) ;
usb_kill_anchored_urbs ( & devinfo - > data_urbs ) ;
2014-09-13 12:26:36 +02:00
uas_zap_pending ( devinfo , DID_RESET ) ;
2012-06-19 09:54:54 +02:00
err = usb_reset_device ( udev ) ;
2014-09-13 12:26:30 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2012-06-19 09:54:54 +02:00
devinfo - > resetting = 0 ;
2014-09-13 12:26:30 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2010-10-07 13:05:23 +02:00
2013-09-22 16:27:02 +02:00
usb_unlock_device ( udev ) ;
2012-06-19 09:54:54 +02:00
if ( err ) {
2014-09-13 12:26:50 +02:00
shost_printk ( KERN_INFO , sdev - > host , " %s FAILED err %d \n " ,
__func__ , err ) ;
2012-06-19 09:54:54 +02:00
return FAILED ;
}
2010-10-07 13:05:23 +02:00
2012-06-19 09:54:54 +02:00
shost_printk ( KERN_INFO , sdev - > host , " %s success \n " , __func__ ) ;
return SUCCESS ;
2010-10-07 13:05:23 +02:00
}
2016-04-12 12:27:09 +02:00
static int uas_target_alloc ( struct scsi_target * starget )
{
struct uas_dev_info * devinfo = ( struct uas_dev_info * )
dev_to_shost ( starget - > dev . parent ) - > hostdata ;
if ( devinfo - > flags & US_FL_NO_REPORT_LUNS )
starget - > no_report_luns = 1 ;
return 0 ;
}
2010-10-07 13:05:23 +02:00
static int uas_slave_alloc ( struct scsi_device * sdev )
{
2015-04-21 11:20:31 +02:00
struct uas_dev_info * devinfo =
( struct uas_dev_info * ) sdev - > host - > hostdata ;
sdev - > hostdata = devinfo ;
2013-11-15 10:04:31 +01:00
2019-04-30 12:21:45 +02:00
/*
* The protocol has no requirements on alignment in the strict sense .
* Controllers may or may not have alignment restrictions .
* As this is not exported , we use an extremely conservative guess .
2013-11-15 10:04:31 +01:00
*/
blk_queue_update_dma_alignment ( sdev - > request_queue , ( 512 - 1 ) ) ;
2020-12-04 16:00:34 +01:00
if ( devinfo - > flags & US_FL_MAX_SECTORS_64 )
blk_queue_max_hw_sectors ( sdev - > request_queue , 64 ) ;
else if ( devinfo - > flags & US_FL_MAX_SECTORS_240 )
blk_queue_max_hw_sectors ( sdev - > request_queue , 240 ) ;
2010-10-07 13:05:23 +02:00
return 0 ;
}
static int uas_slave_configure ( struct scsi_device * sdev )
{
struct uas_dev_info * devinfo = sdev - > hostdata ;
2014-09-16 18:36:52 +02:00
if ( devinfo - > flags & US_FL_NO_REPORT_OPCODES )
sdev - > no_report_opcodes = 1 ;
2015-11-20 01:30:44 +01:00
/* A few buggy USB-ATA bridges don't understand FUA */
if ( devinfo - > flags & US_FL_BROKEN_FUA )
sdev - > broken_fua = 1 ;
2018-05-18 21:50:15 -07:00
/* UAS also needs to support FL_ALWAYS_SYNC */
if ( devinfo - > flags & US_FL_ALWAYS_SYNC ) {
sdev - > skip_ms_page_3f = 1 ;
sdev - > skip_ms_page_8 = 1 ;
sdev - > wce_default_on = 1 ;
}
2018-08-09 16:03:37 +02:00
2019-11-14 12:27:56 +01:00
/* Some disks cannot handle READ_CAPACITY_16 */
if ( devinfo - > flags & US_FL_NO_READ_CAPACITY_16 )
sdev - > no_read_capacity_16 = 1 ;
2020-12-09 16:26:39 +01:00
/* Some disks cannot handle WRITE_SAME */
if ( devinfo - > flags & US_FL_NO_SAME )
sdev - > no_write_same = 1 ;
2018-08-09 16:03:37 +02:00
/*
* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number .
* If this device makes that mistake , tell the sd driver .
*/
if ( devinfo - > flags & US_FL_FIX_CAPACITY )
sdev - > fix_capacity = 1 ;
2019-11-14 12:27:57 +01:00
/*
* in some cases we have to guess
*/
if ( devinfo - > flags & US_FL_CAPACITY_HEURISTICS )
sdev - > guess_capacity = 1 ;
2018-08-09 16:03:37 +02:00
/*
* Some devices don ' t like MODE SENSE with page = 0x3f ,
* which is the command used for checking if a device
* is write - protected . Now that we tell the sd driver
* to do a 192 - byte transfer with this command the
* majority of devices work fine , but a few still can ' t
* handle it . The sd driver will simply assume those
* devices are write - enabled .
*/
if ( devinfo - > flags & US_FL_NO_WP_DETECT )
sdev - > skip_ms_page_3f = 1 ;
2016-05-31 09:18:03 +02:00
scsi_change_queue_depth ( sdev , devinfo - > qdepth - 2 ) ;
2010-10-07 13:05:23 +02:00
return 0 ;
}
static struct scsi_host_template uas_host_template = {
. module = THIS_MODULE ,
. name = " uas " ,
. queuecommand = uas_queuecommand ,
2016-04-12 12:27:09 +02:00
. target_alloc = uas_target_alloc ,
2010-10-07 13:05:23 +02:00
. slave_alloc = uas_slave_alloc ,
. slave_configure = uas_slave_configure ,
. eh_abort_handler = uas_eh_abort_handler ,
2017-08-25 13:57:01 +02:00
. eh_device_reset_handler = uas_eh_device_reset_handler ,
2010-10-07 13:05:23 +02:00
. this_id = - 1 ,
. skip_settle_delay = 1 ,
2018-12-13 16:17:09 +01:00
. dma_boundary = PAGE_SIZE - 1 ,
2010-10-07 13:05:23 +02:00
} ;
2013-10-25 17:04:33 +01:00
# define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
vendorName , productName , useProtocol , useTransport , \
initFunction , flags ) \
{ USB_DEVICE_VER ( id_vendor , id_product , bcdDeviceMin , bcdDeviceMax ) , \
. driver_info = ( flags ) }
2010-10-07 13:05:23 +02:00
static struct usb_device_id uas_usb_ids [ ] = {
2013-10-25 17:04:33 +01:00
# include "unusual_uas.h"
2010-10-07 13:05:23 +02:00
{ USB_INTERFACE_INFO ( USB_CLASS_MASS_STORAGE , USB_SC_SCSI , USB_PR_BULK ) } ,
{ USB_INTERFACE_INFO ( USB_CLASS_MASS_STORAGE , USB_SC_SCSI , USB_PR_UAS ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( usb , uas_usb_ids ) ;
2013-10-25 17:04:33 +01:00
# undef UNUSUAL_DEV
2013-10-21 08:00:58 +01:00
static int uas_switch_interface ( struct usb_device * udev ,
struct usb_interface * intf )
{
2017-09-22 11:56:49 -04:00
struct usb_host_interface * alt ;
2013-10-21 08:00:58 +01:00
alt = uas_find_uas_alt_setting ( intf ) ;
2017-09-22 11:56:49 -04:00
if ( ! alt )
return - ENODEV ;
2013-10-21 08:00:58 +01:00
2017-09-22 11:56:49 -04:00
return usb_set_interface ( udev , alt - > desc . bInterfaceNumber ,
alt - > desc . bAlternateSetting ) ;
2013-10-21 08:00:58 +01:00
}
2013-10-29 10:23:26 +01:00
static int uas_configure_endpoints ( struct uas_dev_info * devinfo )
2013-10-29 08:54:48 +01:00
{
struct usb_host_endpoint * eps [ 4 ] = { } ;
struct usb_device * udev = devinfo - > udev ;
int r ;
r = uas_find_endpoints ( devinfo - > intf - > cur_altsetting , eps ) ;
2013-10-29 10:10:36 +01:00
if ( r )
return r ;
devinfo - > cmd_pipe = usb_sndbulkpipe ( udev ,
usb_endpoint_num ( & eps [ 0 ] - > desc ) ) ;
devinfo - > status_pipe = usb_rcvbulkpipe ( udev ,
usb_endpoint_num ( & eps [ 1 ] - > desc ) ) ;
devinfo - > data_in_pipe = usb_rcvbulkpipe ( udev ,
usb_endpoint_num ( & eps [ 2 ] - > desc ) ) ;
devinfo - > data_out_pipe = usb_sndbulkpipe ( udev ,
usb_endpoint_num ( & eps [ 3 ] - > desc ) ) ;
2010-10-07 13:05:23 +02:00
2014-09-13 12:26:43 +02:00
if ( udev - > speed < USB_SPEED_SUPER ) {
2014-08-01 17:33:08 +02:00
devinfo - > qdepth = 32 ;
2010-10-07 13:05:23 +02:00
devinfo - > use_streams = 0 ;
} else {
2013-10-29 10:23:26 +01:00
devinfo - > qdepth = usb_alloc_streams ( devinfo - > intf , eps + 1 ,
2014-09-13 12:26:32 +02:00
3 , MAX_CMNDS , GFP_NOIO ) ;
2013-10-29 10:23:26 +01:00
if ( devinfo - > qdepth < 0 )
return devinfo - > qdepth ;
2010-10-07 13:05:23 +02:00
devinfo - > use_streams = 1 ;
}
2013-10-29 10:23:26 +01:00
return 0 ;
2010-10-07 13:05:23 +02:00
}
2011-12-19 17:06:08 +01:00
static void uas_free_streams ( struct uas_dev_info * devinfo )
{
struct usb_device * udev = devinfo - > udev ;
struct usb_host_endpoint * eps [ 3 ] ;
eps [ 0 ] = usb_pipe_endpoint ( udev , devinfo - > status_pipe ) ;
eps [ 1 ] = usb_pipe_endpoint ( udev , devinfo - > data_in_pipe ) ;
eps [ 2 ] = usb_pipe_endpoint ( udev , devinfo - > data_out_pipe ) ;
2014-03-28 11:25:50 +01:00
usb_free_streams ( devinfo - > intf , eps , 3 , GFP_NOIO ) ;
2011-12-19 17:06:08 +01:00
}
2010-10-07 13:05:23 +02:00
static int uas_probe ( struct usb_interface * intf , const struct usb_device_id * id )
{
2013-10-17 19:00:45 +02:00
int result = - ENOMEM ;
struct Scsi_Host * shost = NULL ;
2010-10-07 13:05:23 +02:00
struct uas_dev_info * devinfo ;
struct usb_device * udev = interface_to_usbdev ( intf ) ;
2015-04-21 11:20:30 +02:00
unsigned long dev_flags ;
2010-10-07 13:05:23 +02:00
2015-04-21 11:20:30 +02:00
if ( ! uas_use_uas_driver ( intf , id , & dev_flags ) )
2013-10-25 17:04:33 +01:00
return - ENODEV ;
2010-12-15 15:44:05 -05:00
if ( uas_switch_interface ( udev , intf ) )
return - ENODEV ;
2010-10-07 13:05:23 +02:00
2013-11-13 09:32:22 +01:00
shost = scsi_host_alloc ( & uas_host_template ,
sizeof ( struct uas_dev_info ) ) ;
2010-10-07 13:05:23 +02:00
if ( ! shost )
2013-10-17 19:00:45 +02:00
goto set_alt0 ;
2010-10-07 13:05:23 +02:00
shost - > max_cmd_len = 16 + 252 ;
shost - > max_id = 1 ;
2013-01-25 15:03:36 +01:00
shost - > max_lun = 256 ;
shost - > max_channel = 0 ;
2010-10-07 13:05:23 +02:00
shost - > sg_tablesize = udev - > bus - > sg_tablesize ;
2013-11-13 09:32:22 +01:00
devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2010-10-07 13:05:23 +02:00
devinfo - > intf = intf ;
devinfo - > udev = udev ;
2012-06-19 09:54:54 +02:00
devinfo - > resetting = 0 ;
2013-11-11 11:51:42 +01:00
devinfo - > shutdown = 0 ;
2015-04-21 11:20:30 +02:00
devinfo - > flags = dev_flags ;
2012-09-25 10:47:04 +02:00
init_usb_anchor ( & devinfo - > cmd_urbs ) ;
2012-06-19 09:54:53 +02:00
init_usb_anchor ( & devinfo - > sense_urbs ) ;
init_usb_anchor ( & devinfo - > data_urbs ) ;
2012-09-25 10:47:08 +02:00
spin_lock_init ( & devinfo - > lock ) ;
2013-09-13 13:27:12 +02:00
INIT_WORK ( & devinfo - > work , uas_do_work ) ;
2020-01-30 01:25:06 -08:00
INIT_WORK ( & devinfo - > scan_work , uas_scan_work ) ;
2013-10-29 10:23:26 +01:00
result = uas_configure_endpoints ( devinfo ) ;
if ( result )
goto set_alt0 ;
2010-10-07 13:05:23 +02:00
2016-04-12 12:27:08 +02:00
/*
* 1 tag is reserved for untagged commands +
* 1 tag to avoid off by one errors in some bridge firmwares
*/
shost - > can_queue = devinfo - > qdepth - 2 ;
2014-03-28 11:29:25 +01:00
usb_set_intfdata ( intf , shost ) ;
2020-12-04 16:00:34 +01:00
result = scsi_add_host ( shost , & intf - > dev ) ;
2011-12-19 17:06:08 +01:00
if ( result )
2013-10-17 19:00:45 +02:00
goto free_streams ;
2011-12-19 17:06:08 +01:00
2020-01-30 01:25:06 -08:00
/* Submit the delayed_work for SCSI-device scanning */
schedule_work ( & devinfo - > scan_work ) ;
2010-10-07 13:05:23 +02:00
return result ;
2011-12-19 17:06:08 +01:00
2013-10-17 19:00:45 +02:00
free_streams :
2011-12-19 17:06:08 +01:00
uas_free_streams ( devinfo ) ;
2014-03-28 11:29:25 +01:00
usb_set_intfdata ( intf , NULL ) ;
2013-10-17 19:00:45 +02:00
set_alt0 :
usb_set_interface ( udev , intf - > altsetting [ 0 ] . desc . bInterfaceNumber , 0 ) ;
2010-10-07 13:05:23 +02:00
if ( shost )
scsi_host_put ( shost ) ;
return result ;
}
2014-09-13 12:26:42 +02:00
static int uas_cmnd_list_empty ( struct uas_dev_info * devinfo )
{
unsigned long flags ;
int i , r = 1 ;
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
for ( i = 0 ; i < devinfo - > qdepth ; i + + ) {
if ( devinfo - > cmnd [ i ] ) {
r = 0 ; /* Not empty */
break ;
}
}
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
return r ;
}
/*
* Wait for any pending cmnds to complete , on usb - 2 sense_urbs may temporarily
* get empty while there still is more work to do due to sense - urbs completing
* with a READ / WRITE_READY iu code , so keep waiting until the list gets empty .
*/
static int uas_wait_for_pending_cmnds ( struct uas_dev_info * devinfo )
{
unsigned long start_time ;
int r ;
start_time = jiffies ;
do {
flush_work ( & devinfo - > work ) ;
r = usb_wait_anchor_empty_timeout ( & devinfo - > sense_urbs , 5000 ) ;
if ( r = = 0 )
return - ETIME ;
r = usb_wait_anchor_empty_timeout ( & devinfo - > data_urbs , 500 ) ;
if ( r = = 0 )
return - ETIME ;
if ( time_after ( jiffies , start_time + 5 * HZ ) )
return - ETIME ;
} while ( ! uas_cmnd_list_empty ( devinfo ) ) ;
return 0 ;
}
2010-10-07 13:05:23 +02:00
static int uas_pre_reset ( struct usb_interface * intf )
{
2013-10-22 16:10:44 +01:00
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2013-10-22 16:10:44 +01:00
unsigned long flags ;
2013-11-11 11:51:42 +01:00
if ( devinfo - > shutdown )
return 0 ;
2013-10-22 16:10:44 +01:00
/* Block new requests */
spin_lock_irqsave ( shost - > host_lock , flags ) ;
scsi_block_requests ( shost ) ;
spin_unlock_irqrestore ( shost - > host_lock , flags ) ;
2014-09-13 12:26:42 +02:00
if ( uas_wait_for_pending_cmnds ( devinfo ) ! = 0 ) {
2013-10-22 16:10:44 +01:00
shost_printk ( KERN_ERR , shost , " %s: timed out \n " , __func__ ) ;
2014-09-13 12:26:42 +02:00
scsi_unblock_requests ( shost ) ;
2013-10-22 16:10:44 +01:00
return 1 ;
}
uas_free_streams ( devinfo ) ;
2010-10-07 13:05:23 +02:00
return 0 ;
}
static int uas_post_reset ( struct usb_interface * intf )
{
2013-10-22 16:10:44 +01:00
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2013-10-22 16:10:44 +01:00
unsigned long flags ;
2014-09-13 12:26:50 +02:00
int err ;
2013-10-22 16:10:44 +01:00
2013-11-11 11:51:42 +01:00
if ( devinfo - > shutdown )
return 0 ;
2014-09-13 12:26:50 +02:00
err = uas_configure_endpoints ( devinfo ) ;
2018-03-06 15:04:24 +01:00
if ( err & & err ! = - ENODEV )
2013-10-29 10:23:26 +01:00
shost_printk ( KERN_ERR , shost ,
2014-09-13 12:26:50 +02:00
" %s: alloc streams error %d after reset " ,
__func__ , err ) ;
2013-10-22 16:10:44 +01:00
2018-01-11 13:10:16 +01:00
/* we must unblock the host in every case lest we deadlock */
2013-10-22 16:10:44 +01:00
spin_lock_irqsave ( shost - > host_lock , flags ) ;
scsi_report_bus_reset ( shost , 0 ) ;
spin_unlock_irqrestore ( shost - > host_lock , flags ) ;
scsi_unblock_requests ( shost ) ;
2018-01-11 13:10:16 +01:00
return err ? 1 : 0 ;
2010-10-07 13:05:23 +02:00
}
2013-11-07 08:47:05 +01:00
static int uas_suspend ( struct usb_interface * intf , pm_message_t message )
{
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2013-11-07 08:47:05 +01:00
2014-09-13 12:26:42 +02:00
if ( uas_wait_for_pending_cmnds ( devinfo ) ! = 0 ) {
2013-11-07 08:47:05 +01:00
shost_printk ( KERN_ERR , shost , " %s: timed out \n " , __func__ ) ;
return - ETIME ;
}
return 0 ;
}
static int uas_resume ( struct usb_interface * intf )
{
return 0 ;
}
static int uas_reset_resume ( struct usb_interface * intf )
{
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2013-11-07 08:47:05 +01:00
unsigned long flags ;
2014-09-13 12:26:50 +02:00
int err ;
2013-11-07 08:47:05 +01:00
2014-09-13 12:26:50 +02:00
err = uas_configure_endpoints ( devinfo ) ;
if ( err ) {
2013-11-07 08:47:05 +01:00
shost_printk ( KERN_ERR , shost ,
2014-09-13 12:26:50 +02:00
" %s: alloc streams error %d after reset " ,
__func__ , err ) ;
2013-11-07 08:47:05 +01:00
return - EIO ;
}
spin_lock_irqsave ( shost - > host_lock , flags ) ;
scsi_report_bus_reset ( shost , 0 ) ;
spin_unlock_irqrestore ( shost - > host_lock , flags ) ;
return 0 ;
}
2010-10-07 13:05:23 +02:00
static void uas_disconnect ( struct usb_interface * intf )
{
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2014-09-13 12:26:30 +02:00
unsigned long flags ;
2010-10-07 13:05:23 +02:00
2014-09-13 12:26:30 +02:00
spin_lock_irqsave ( & devinfo - > lock , flags ) ;
2012-11-30 11:54:44 +01:00
devinfo - > resetting = 1 ;
2014-09-13 12:26:30 +02:00
spin_unlock_irqrestore ( & devinfo - > lock , flags ) ;
2013-09-13 13:27:12 +02:00
cancel_work_sync ( & devinfo - > work ) ;
2012-09-25 10:47:04 +02:00
usb_kill_anchored_urbs ( & devinfo - > cmd_urbs ) ;
2012-06-19 09:54:53 +02:00
usb_kill_anchored_urbs ( & devinfo - > sense_urbs ) ;
usb_kill_anchored_urbs ( & devinfo - > data_urbs ) ;
2014-09-13 12:26:36 +02:00
uas_zap_pending ( devinfo , DID_NO_CONNECT ) ;
2020-01-30 01:25:06 -08:00
/*
* Prevent SCSI scanning ( if it hasn ' t started yet )
* or wait for the SCSI - scanning routine to stop .
*/
cancel_work_sync ( & devinfo - > scan_work ) ;
2012-11-30 11:54:44 +01:00
scsi_remove_host ( shost ) ;
2011-12-19 17:06:08 +01:00
uas_free_streams ( devinfo ) ;
2013-11-13 09:32:22 +01:00
scsi_host_put ( shost ) ;
2010-10-07 13:05:23 +02:00
}
2013-11-11 11:51:42 +01:00
/*
* Put the device back in usb - storage mode on shutdown , as some BIOS - es
* hang on reboot when the device is still in uas mode . Note the reset is
* necessary as some devices won ' t revert to usb - storage mode without it .
*/
static void uas_shutdown ( struct device * dev )
{
struct usb_interface * intf = to_usb_interface ( dev ) ;
struct usb_device * udev = interface_to_usbdev ( intf ) ;
struct Scsi_Host * shost = usb_get_intfdata ( intf ) ;
2013-11-13 09:32:22 +01:00
struct uas_dev_info * devinfo = ( struct uas_dev_info * ) shost - > hostdata ;
2013-11-11 11:51:42 +01:00
if ( system_state ! = SYSTEM_RESTART )
return ;
devinfo - > shutdown = 1 ;
uas_free_streams ( devinfo ) ;
usb_set_interface ( udev , intf - > altsetting [ 0 ] . desc . bInterfaceNumber , 0 ) ;
usb_reset_device ( udev ) ;
}
2010-10-07 13:05:23 +02:00
static struct usb_driver uas_driver = {
. name = " uas " ,
. probe = uas_probe ,
. disconnect = uas_disconnect ,
. pre_reset = uas_pre_reset ,
. post_reset = uas_post_reset ,
2013-11-07 08:47:05 +01:00
. suspend = uas_suspend ,
. resume = uas_resume ,
. reset_resume = uas_reset_resume ,
2013-11-11 11:51:42 +01:00
. drvwrap . driver . shutdown = uas_shutdown ,
2010-10-07 13:05:23 +02:00
. id_table = uas_usb_ids ,
} ;
2020-04-15 16:17:50 +02:00
static int __init uas_init ( void )
{
int rv ;
workqueue = alloc_workqueue ( " uas " , WQ_MEM_RECLAIM , 0 ) ;
if ( ! workqueue )
return - ENOMEM ;
rv = usb_register ( & uas_driver ) ;
if ( rv ) {
destroy_workqueue ( workqueue ) ;
return - ENOMEM ;
}
return 0 ;
}
static void __exit uas_exit ( void )
{
usb_deregister ( & uas_driver ) ;
destroy_workqueue ( workqueue ) ;
}
module_init ( uas_init ) ;
module_exit ( uas_exit ) ;
2010-10-07 13:05:23 +02:00
MODULE_LICENSE ( " GPL " ) ;
2019-09-06 11:32:35 +01:00
MODULE_IMPORT_NS ( USB_STORAGE ) ;
2013-10-28 10:48:04 +00:00
MODULE_AUTHOR (
" Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp " ) ;