@@ -234,11 +234,13 @@ static const char *sdebug_version_date = "20180128";
234234#define F_INV_OP 0x200
235235#define F_FAKE_RW 0x400
236236#define F_M_ACCESS 0x800 /* media access */
237- #define F_LONG_DELAY 0x1000
237+ #define F_SSU_DELAY 0x1000
238+ #define F_SYNC_DELAY 0x2000
238239
239240#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
240241#define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
241242#define FF_SA (F_SA_HIGH | F_SA_LOW)
243+ #define F_LONG_DELAY (F_SSU_DELAY | F_SYNC_DELAY)
242244
243245#define SDEBUG_MAX_PARTS 4
244246
@@ -510,7 +512,7 @@ static const struct opcode_info_t release_iarr[] = {
510512};
511513
512514static const struct opcode_info_t sync_cache_iarr [] = {
513- {0 , 0x91 , 0 , F_LONG_DELAY | F_M_ACCESS , resp_sync_cache , NULL ,
515+ {0 , 0x91 , 0 , F_SYNC_DELAY | F_M_ACCESS , resp_sync_cache , NULL ,
514516 {16 , 0x6 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
515517 0xff , 0xff , 0xff , 0xff , 0x3f , 0xc7 } }, /* SYNC_CACHE (16) */
516518};
@@ -553,7 +555,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
553555 resp_write_dt0 , write_iarr , /* WRITE(16) */
554556 {16 , 0xfa , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ,
555557 0xff , 0xff , 0xff , 0xff , 0xff , 0xc7 } },
556- {0 , 0x1b , 0 , F_LONG_DELAY , resp_start_stop , NULL ,/* START STOP UNIT */
558+ {0 , 0x1b , 0 , F_SSU_DELAY , resp_start_stop , NULL ,/* START STOP UNIT */
557559 {6 , 0x1 , 0 , 0xf , 0xf7 , 0xc7 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } },
558560 {ARRAY_SIZE (sa_in_16_iarr ), 0x9e , 0x10 , F_SA_LOW | F_D_IN ,
559561 resp_readcap16 , sa_in_16_iarr , /* SA_IN(16), READ CAPACITY(16) */
@@ -606,7 +608,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
606608 resp_write_same_10 , write_same_iarr , /* WRITE SAME(10) */
607609 {10 , 0xff , 0xff , 0xff , 0xff , 0xff , 0x3f , 0xff , 0xff , 0xc7 , 0 ,
608610 0 , 0 , 0 , 0 , 0 } },
609- {ARRAY_SIZE (sync_cache_iarr ), 0x35 , 0 , F_LONG_DELAY | F_M_ACCESS ,
611+ {ARRAY_SIZE (sync_cache_iarr ), 0x35 , 0 , F_SYNC_DELAY | F_M_ACCESS ,
610612 resp_sync_cache , sync_cache_iarr ,
611613 {10 , 0x7 , 0xff , 0xff , 0xff , 0xff , 0x3f , 0xff , 0xff , 0xc7 , 0 , 0 ,
612614 0 , 0 , 0 , 0 } }, /* SYNC_CACHE (10) */
@@ -667,6 +669,7 @@ static bool sdebug_strict = DEF_STRICT;
667669static bool sdebug_any_injecting_opt ;
668670static bool sdebug_verbose ;
669671static bool have_dif_prot ;
672+ static bool write_since_sync ;
670673static bool sdebug_statistics = DEF_STATISTICS ;
671674
672675static unsigned int sdebug_store_sectors ;
@@ -1607,15 +1610,20 @@ static int resp_start_stop(struct scsi_cmnd *scp,
16071610{
16081611 unsigned char * cmd = scp -> cmnd ;
16091612 int power_cond , stop ;
1613+ bool changing ;
16101614
16111615 power_cond = (cmd [4 ] & 0xf0 ) >> 4 ;
16121616 if (power_cond ) {
16131617 mk_sense_invalid_fld (scp , SDEB_IN_CDB , 4 , 7 );
16141618 return check_condition_result ;
16151619 }
16161620 stop = !(cmd [4 ] & 1 );
1621+ changing = atomic_read (& devip -> stopped ) == !stop ;
16171622 atomic_xchg (& devip -> stopped , stop );
1618- return (cmd [1 ] & 0x1 ) ? SDEG_RES_IMMED_MASK : 0 ; /* check IMMED bit */
1623+ if (!changing || cmd [1 ] & 0x1 ) /* state unchanged or IMMED set */
1624+ return SDEG_RES_IMMED_MASK ;
1625+ else
1626+ return 0 ;
16191627}
16201628
16211629static sector_t get_sdebug_capacity (void )
@@ -2473,6 +2481,7 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
24732481 if (do_write ) {
24742482 sdb = scsi_out (scmd );
24752483 dir = DMA_TO_DEVICE ;
2484+ write_since_sync = true;
24762485 } else {
24772486 sdb = scsi_in (scmd );
24782487 dir = DMA_FROM_DEVICE ;
@@ -3583,6 +3592,7 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
35833592static int resp_sync_cache (struct scsi_cmnd * scp ,
35843593 struct sdebug_dev_info * devip )
35853594{
3595+ int res = 0 ;
35863596 u64 lba ;
35873597 u32 num_blocks ;
35883598 u8 * cmd = scp -> cmnd ;
@@ -3598,7 +3608,11 @@ static int resp_sync_cache(struct scsi_cmnd *scp,
35983608 mk_sense_buffer (scp , ILLEGAL_REQUEST , LBA_OUT_OF_RANGE , 0 );
35993609 return check_condition_result ;
36003610 }
3601- return (cmd [1 ] & 0x2 ) ? SDEG_RES_IMMED_MASK : 0 ; /* check IMMED bit */
3611+ if (!write_since_sync || cmd [1 ] & 0x2 )
3612+ res = SDEG_RES_IMMED_MASK ;
3613+ else /* delay if write_since_sync and IMMED clear */
3614+ write_since_sync = false;
3615+ return res ;
36023616}
36033617
36043618#define RL_BUCKET_ELEMS 8
@@ -5777,13 +5791,14 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
57775791 return schedule_resp (scp , devip , errsts , pfp , 0 , 0 );
57785792 else if ((sdebug_jdelay || sdebug_ndelay ) && (flags & F_LONG_DELAY )) {
57795793 /*
5780- * If any delay is active, want F_LONG_DELAY to be at least 1
5794+ * If any delay is active, for F_SSU_DELAY want at least 1
57815795 * second and if sdebug_jdelay>0 want a long delay of that
5782- * many seconds.
5796+ * many seconds; for F_SYNC_DELAY want 1/20 of that .
57835797 */
57845798 int jdelay = (sdebug_jdelay < 2 ) ? 1 : sdebug_jdelay ;
5799+ int denom = (flags & F_SYNC_DELAY ) ? 20 : 1 ;
57855800
5786- jdelay = mult_frac (USER_HZ * jdelay , HZ , USER_HZ );
5801+ jdelay = mult_frac (USER_HZ * jdelay , HZ , denom * USER_HZ );
57875802 return schedule_resp (scp , devip , errsts , pfp , jdelay , 0 );
57885803 } else
57895804 return schedule_resp (scp , devip , errsts , pfp , sdebug_jdelay ,
0 commit comments