@@ -307,7 +307,6 @@ static const unsigned char opcode_ind_arr[256] = {
307
307
#define FF_SA (F_SA_HIGH | F_SA_LOW)
308
308
309
309
struct sdebug_dev_info ;
310
- static int scsi_debug_queuecommand (struct scsi_cmnd * scp );
311
310
static int resp_inquiry (struct scsi_cmnd * , struct sdebug_dev_info * );
312
311
static int resp_report_luns (struct scsi_cmnd * , struct sdebug_dev_info * );
313
312
static int resp_requests (struct scsi_cmnd * , struct sdebug_dev_info * );
@@ -322,9 +321,12 @@ static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
322
321
static int resp_get_lba_status (struct scsi_cmnd * , struct sdebug_dev_info * );
323
322
static int resp_report_tgtpgs (struct scsi_cmnd * , struct sdebug_dev_info * );
324
323
static int resp_unmap (struct scsi_cmnd * , struct sdebug_dev_info * );
324
+ static int resp_rsup_opcodes (struct scsi_cmnd * , struct sdebug_dev_info * );
325
+ static int resp_rsup_tmfs (struct scsi_cmnd * , struct sdebug_dev_info * );
325
326
static int resp_write_same_10 (struct scsi_cmnd * , struct sdebug_dev_info * );
326
327
static int resp_write_same_16 (struct scsi_cmnd * , struct sdebug_dev_info * );
327
328
static int resp_xdwriteread_10 (struct scsi_cmnd * , struct sdebug_dev_info * );
329
+ static int resp_comp_write (struct scsi_cmnd * , struct sdebug_dev_info * );
328
330
329
331
struct opcode_info_t {
330
332
u8 num_attached ; /* 0 if this is it (i.e. a leaf); use 0xff
@@ -383,10 +385,10 @@ static const struct opcode_info_t vl_iarr[1] = { /* VARIABLE LENGTH */
383
385
};
384
386
385
387
static const struct opcode_info_t maint_in_iarr [2 ] = {
386
- {0 , 0xa3 , 0xc , F_SA_LOW | F_D_IN , NULL , NULL ,
388
+ {0 , 0xa3 , 0xc , F_SA_LOW | F_D_IN , resp_rsup_opcodes , NULL ,
387
389
{12 , 0xc , 0x87 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0 ,
388
390
0xc7 , 0 , 0 , 0 , 0 } },
389
- {0 , 0xa3 , 0xd , F_SA_LOW | F_D_IN , NULL , NULL ,
391
+ {0 , 0xa3 , 0xd , F_SA_LOW | F_D_IN , resp_rsup_tmfs , NULL ,
390
392
{12 , 0xd , 0x80 , 0 , 0 , 0 , 0xff , 0xff , 0xff , 0xff , 0 , 0xc7 , 0 , 0 ,
391
393
0 , 0 } },
392
394
};
@@ -487,7 +489,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
487
489
{0 , 0x35 , 0 , F_DELAY_OVERR | FF_DIRECT_IO , NULL , NULL , /* SYNC_CACHE */
488
490
{10 , 0x7 , 0xff , 0xff , 0xff , 0xff , 0x1f , 0xff , 0xff , 0xc7 , 0 , 0 ,
489
491
0 , 0 , 0 , 0 } },
490
- {0 , 0x89 , 0 , F_D_OUT | FF_DIRECT_IO , NULL , NULL ,
492
+ {0 , 0x89 , 0 , F_D_OUT | FF_DIRECT_IO , resp_comp_write , NULL ,
491
493
{16 , 0xf8 , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0 , 0 ,
492
494
0 , 0xff , 0x1f , 0xc7 } }, /* COMPARE AND WRITE */
493
495
@@ -1603,6 +1605,184 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp,
1603
1605
return ret ;
1604
1606
}
1605
1607
1608
+ static int
1609
+ resp_rsup_opcodes (struct scsi_cmnd * scp , struct sdebug_dev_info * devip )
1610
+ {
1611
+ bool rctd ;
1612
+ u8 reporting_opts , req_opcode , sdeb_i , supp ;
1613
+ u16 req_sa , u ;
1614
+ u32 alloc_len , a_len ;
1615
+ int k , offset , len , errsts , count , bump , na ;
1616
+ const struct opcode_info_t * oip ;
1617
+ const struct opcode_info_t * r_oip ;
1618
+ u8 * arr ;
1619
+ u8 * cmd = scp -> cmnd ;
1620
+
1621
+ rctd = !!(cmd [2 ] & 0x80 );
1622
+ reporting_opts = cmd [2 ] & 0x7 ;
1623
+ req_opcode = cmd [3 ];
1624
+ req_sa = get_unaligned_be16 (cmd + 4 );
1625
+ alloc_len = get_unaligned_be32 (cmd + 6 );
1626
+ if (alloc_len < 4 && alloc_len > 0xffff ) {
1627
+ mk_sense_invalid_fld (scp , SDEB_IN_CDB , 6 , -1 );
1628
+ return check_condition_result ;
1629
+ }
1630
+ if (alloc_len > 8192 )
1631
+ a_len = 8192 ;
1632
+ else
1633
+ a_len = alloc_len ;
1634
+ arr = kzalloc ((a_len < 256 ) ? 320 : a_len + 64 , GFP_KERNEL );
1635
+ if (NULL == arr ) {
1636
+ mk_sense_buffer (scp , ILLEGAL_REQUEST , INSUFF_RES_ASC ,
1637
+ INSUFF_RES_ASCQ );
1638
+ return check_condition_result ;
1639
+ }
1640
+ switch (reporting_opts ) {
1641
+ case 0 : /* all commands */
1642
+ /* count number of commands */
1643
+ for (count = 0 , oip = opcode_info_arr ;
1644
+ oip -> num_attached != 0xff ; ++ oip ) {
1645
+ if (F_INV_OP & oip -> flags )
1646
+ continue ;
1647
+ count += (oip -> num_attached + 1 );
1648
+ }
1649
+ bump = rctd ? 20 : 8 ;
1650
+ put_unaligned_be32 (count * bump , arr );
1651
+ for (offset = 4 , oip = opcode_info_arr ;
1652
+ oip -> num_attached != 0xff && offset < a_len ; ++ oip ) {
1653
+ if (F_INV_OP & oip -> flags )
1654
+ continue ;
1655
+ na = oip -> num_attached ;
1656
+ arr [offset ] = oip -> opcode ;
1657
+ put_unaligned_be16 (oip -> sa , arr + offset + 2 );
1658
+ if (rctd )
1659
+ arr [offset + 5 ] |= 0x2 ;
1660
+ if (FF_SA & oip -> flags )
1661
+ arr [offset + 5 ] |= 0x1 ;
1662
+ put_unaligned_be16 (oip -> len_mask [0 ], arr + offset + 6 );
1663
+ if (rctd )
1664
+ put_unaligned_be16 (0xa , arr + offset + 8 );
1665
+ r_oip = oip ;
1666
+ for (k = 0 , oip = oip -> arrp ; k < na ; ++ k , ++ oip ) {
1667
+ if (F_INV_OP & oip -> flags )
1668
+ continue ;
1669
+ offset += bump ;
1670
+ arr [offset ] = oip -> opcode ;
1671
+ put_unaligned_be16 (oip -> sa , arr + offset + 2 );
1672
+ if (rctd )
1673
+ arr [offset + 5 ] |= 0x2 ;
1674
+ if (FF_SA & oip -> flags )
1675
+ arr [offset + 5 ] |= 0x1 ;
1676
+ put_unaligned_be16 (oip -> len_mask [0 ],
1677
+ arr + offset + 6 );
1678
+ if (rctd )
1679
+ put_unaligned_be16 (0xa ,
1680
+ arr + offset + 8 );
1681
+ }
1682
+ oip = r_oip ;
1683
+ offset += bump ;
1684
+ }
1685
+ break ;
1686
+ case 1 : /* one command: opcode only */
1687
+ case 2 : /* one command: opcode plus service action */
1688
+ case 3 : /* one command: if sa==0 then opcode only else opcode+sa */
1689
+ sdeb_i = opcode_ind_arr [req_opcode ];
1690
+ oip = & opcode_info_arr [sdeb_i ];
1691
+ if (F_INV_OP & oip -> flags ) {
1692
+ supp = 1 ;
1693
+ offset = 4 ;
1694
+ } else {
1695
+ if (1 == reporting_opts ) {
1696
+ if (FF_SA & oip -> flags ) {
1697
+ mk_sense_invalid_fld (scp , SDEB_IN_CDB ,
1698
+ 2 , 2 );
1699
+ kfree (arr );
1700
+ return check_condition_result ;
1701
+ }
1702
+ req_sa = 0 ;
1703
+ } else if (2 == reporting_opts &&
1704
+ 0 == (FF_SA & oip -> flags )) {
1705
+ mk_sense_invalid_fld (scp , SDEB_IN_CDB , 4 , -1 );
1706
+ kfree (arr ); /* point at requested sa */
1707
+ return check_condition_result ;
1708
+ }
1709
+ if (0 == (FF_SA & oip -> flags ) &&
1710
+ req_opcode == oip -> opcode )
1711
+ supp = 3 ;
1712
+ else if (0 == (FF_SA & oip -> flags )) {
1713
+ na = oip -> num_attached ;
1714
+ for (k = 0 , oip = oip -> arrp ; k < na ;
1715
+ ++ k , ++ oip ) {
1716
+ if (req_opcode == oip -> opcode )
1717
+ break ;
1718
+ }
1719
+ supp = (k >= na ) ? 1 : 3 ;
1720
+ } else if (req_sa != oip -> sa ) {
1721
+ na = oip -> num_attached ;
1722
+ for (k = 0 , oip = oip -> arrp ; k < na ;
1723
+ ++ k , ++ oip ) {
1724
+ if (req_sa == oip -> sa )
1725
+ break ;
1726
+ }
1727
+ supp = (k >= na ) ? 1 : 3 ;
1728
+ } else
1729
+ supp = 3 ;
1730
+ if (3 == supp ) {
1731
+ u = oip -> len_mask [0 ];
1732
+ put_unaligned_be16 (u , arr + 2 );
1733
+ arr [4 ] = oip -> opcode ;
1734
+ for (k = 1 ; k < u ; ++ k )
1735
+ arr [4 + k ] = (k < 16 ) ?
1736
+ oip -> len_mask [k ] : 0xff ;
1737
+ offset = 4 + u ;
1738
+ } else
1739
+ offset = 4 ;
1740
+ }
1741
+ arr [1 ] = (rctd ? 0x80 : 0 ) | supp ;
1742
+ if (rctd ) {
1743
+ put_unaligned_be16 (0xa , arr + offset );
1744
+ offset += 12 ;
1745
+ }
1746
+ break ;
1747
+ default :
1748
+ mk_sense_invalid_fld (scp , SDEB_IN_CDB , 2 , 2 );
1749
+ kfree (arr );
1750
+ return check_condition_result ;
1751
+ }
1752
+ offset = (offset < a_len ) ? offset : a_len ;
1753
+ len = (offset < alloc_len ) ? offset : alloc_len ;
1754
+ errsts = fill_from_dev_buffer (scp , arr , len );
1755
+ kfree (arr );
1756
+ return errsts ;
1757
+ }
1758
+
1759
+ static int
1760
+ resp_rsup_tmfs (struct scsi_cmnd * scp , struct sdebug_dev_info * devip )
1761
+ {
1762
+ bool repd ;
1763
+ u32 alloc_len , len ;
1764
+ u8 arr [16 ];
1765
+ u8 * cmd = scp -> cmnd ;
1766
+
1767
+ memset (arr , 0 , sizeof (arr ));
1768
+ repd = !!(cmd [2 ] & 0x80 );
1769
+ alloc_len = get_unaligned_be32 (cmd + 6 );
1770
+ if (alloc_len < 4 ) {
1771
+ mk_sense_invalid_fld (scp , SDEB_IN_CDB , 6 , -1 );
1772
+ return check_condition_result ;
1773
+ }
1774
+ arr [0 ] = 0xc8 ; /* ATS | ATSS | LURS */
1775
+ arr [1 ] = 0x1 ; /* ITNRS */
1776
+ if (repd ) {
1777
+ arr [3 ] = 0xc ;
1778
+ len = 16 ;
1779
+ } else
1780
+ len = 4 ;
1781
+
1782
+ len = (len < alloc_len ) ? len : alloc_len ;
1783
+ return fill_from_dev_buffer (scp , arr , len );
1784
+ }
1785
+
1606
1786
/* <<Following mode page info copied from ST318451LW>> */
1607
1787
1608
1788
static int resp_err_recov_pg (unsigned char * p , int pcontrol , int target )
@@ -2165,6 +2345,38 @@ do_device_access(struct scsi_cmnd *scmd, u64 lba, u32 num, bool do_write)
2165
2345
return ret ;
2166
2346
}
2167
2347
2348
+ /* If fake_store(lba,num) compares equal to arr(num), then copy top half of
2349
+ * arr into fake_store(lba,num) and return true. If comparison fails then
2350
+ * return false. */
2351
+ static bool
2352
+ comp_write_worker (u64 lba , u32 num , const u8 * arr )
2353
+ {
2354
+ bool res ;
2355
+ u64 block , rest = 0 ;
2356
+ u32 store_blks = sdebug_store_sectors ;
2357
+ u32 lb_size = scsi_debug_sector_size ;
2358
+
2359
+ block = do_div (lba , store_blks );
2360
+ if (block + num > store_blks )
2361
+ rest = block + num - store_blks ;
2362
+
2363
+ res = !memcmp (fake_storep + (block * lb_size ), arr ,
2364
+ (num - rest ) * lb_size );
2365
+ if (!res )
2366
+ return res ;
2367
+ if (rest )
2368
+ res = memcmp (fake_storep , arr + ((num - rest ) * lb_size ),
2369
+ rest * lb_size );
2370
+ if (!res )
2371
+ return res ;
2372
+ arr += num * lb_size ;
2373
+ memcpy (fake_storep + (block * lb_size ), arr , (num - rest ) * lb_size );
2374
+ if (rest )
2375
+ memcpy (fake_storep , arr + ((num - rest ) * lb_size ),
2376
+ rest * lb_size );
2377
+ return res ;
2378
+ }
2379
+
2168
2380
static __be16 dif_compute_csum (const void * buf , int len )
2169
2381
{
2170
2382
__be16 csum ;
@@ -2821,6 +3033,82 @@ resp_write_same_16(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
2821
3033
return resp_write_same (scp , lba , num , ei_lba , unmap , ndob );
2822
3034
}
2823
3035
3036
+ static int
3037
+ resp_comp_write (struct scsi_cmnd * scp , struct sdebug_dev_info * devip )
3038
+ {
3039
+ u8 * cmd = scp -> cmnd ;
3040
+ u8 * arr ;
3041
+ u8 * fake_storep_hold ;
3042
+ u64 lba ;
3043
+ u32 dnum ;
3044
+ u32 lb_size = scsi_debug_sector_size ;
3045
+ u8 num ;
3046
+ unsigned long iflags ;
3047
+ int ret ;
3048
+
3049
+ lba = get_unaligned_be32 (cmd + 2 );
3050
+ num = cmd [13 ]; /* 1 to a maximum of 255 logical blocks */
3051
+ if (0 == num )
3052
+ return 0 ; /* degenerate case, not an error */
3053
+ dnum = 2 * num ;
3054
+ arr = kzalloc (dnum * lb_size , GFP_ATOMIC );
3055
+ if (NULL == arr ) {
3056
+ mk_sense_buffer (scp , ILLEGAL_REQUEST , INSUFF_RES_ASC ,
3057
+ INSUFF_RES_ASCQ );
3058
+ return check_condition_result ;
3059
+ }
3060
+ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
3061
+ (cmd [1 ] & 0xe0 )) {
3062
+ mk_sense_invalid_opcode (scp );
3063
+ return check_condition_result ;
3064
+ }
3065
+ if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
3066
+ scsi_debug_dif == SD_DIF_TYPE3_PROTECTION ) &&
3067
+ (cmd [1 ] & 0xe0 ) == 0 )
3068
+ sdev_printk (KERN_ERR , scp -> device , "Unprotected WR "
3069
+ "to DIF device\n" );
3070
+
3071
+ /* inline check_device_access_params() */
3072
+ if (lba + num > sdebug_capacity ) {
3073
+ mk_sense_buffer (scp , ILLEGAL_REQUEST , LBA_OUT_OF_RANGE , 0 );
3074
+ return check_condition_result ;
3075
+ }
3076
+ /* transfer length excessive (tie in to block limits VPD page) */
3077
+ if (num > sdebug_store_sectors ) {
3078
+ /* needs work to find which cdb byte 'num' comes from */
3079
+ mk_sense_buffer (scp , ILLEGAL_REQUEST , INVALID_FIELD_IN_CDB , 0 );
3080
+ return check_condition_result ;
3081
+ }
3082
+
3083
+ write_lock_irqsave (& atomic_rw , iflags );
3084
+
3085
+ /* trick do_device_access() to fetch both compare and write buffers
3086
+ * from data-in into arr. Safe (atomic) since write_lock held. */
3087
+ fake_storep_hold = fake_storep ;
3088
+ fake_storep = arr ;
3089
+ ret = do_device_access (scp , 0 , dnum , true);
3090
+ fake_storep = fake_storep_hold ;
3091
+ if (ret == -1 ) {
3092
+ write_unlock_irqrestore (& atomic_rw , iflags );
3093
+ kfree (arr );
3094
+ return DID_ERROR << 16 ;
3095
+ } else if ((ret < (dnum * lb_size )) &&
3096
+ (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts ))
3097
+ sdev_printk (KERN_INFO , scp -> device , "%s: compare_write: cdb "
3098
+ "indicated=%u, IO sent=%d bytes\n" , my_name ,
3099
+ dnum * lb_size , ret );
3100
+ if (!comp_write_worker (lba , num , arr )) {
3101
+ write_unlock_irqrestore (& atomic_rw , iflags );
3102
+ kfree (arr );
3103
+ mk_sense_buffer (scp , MISCOMPARE , MISCOMPARE_VERIFY_ASC , 0 );
3104
+ return check_condition_result ;
3105
+ }
3106
+ if (scsi_debug_lbp ())
3107
+ map_region (lba , num );
3108
+ write_unlock_irqrestore (& atomic_rw , iflags );
3109
+ return 0 ;
3110
+ }
3111
+
2824
3112
struct unmap_block_desc {
2825
3113
__be64 lba ;
2826
3114
__be32 blocks ;
@@ -4668,21 +4956,6 @@ static void sdebug_remove_adapter(void)
4668
4956
-- scsi_debug_add_host ;
4669
4957
}
4670
4958
4671
- static int
4672
- sdebug_queuecommand_lock_or_not (struct Scsi_Host * shost , struct scsi_cmnd * cmd )
4673
- {
4674
- if (scsi_debug_host_lock ) {
4675
- unsigned long iflags ;
4676
- int rc ;
4677
-
4678
- spin_lock_irqsave (shost -> host_lock , iflags );
4679
- rc = scsi_debug_queuecommand (cmd );
4680
- spin_unlock_irqrestore (shost -> host_lock , iflags );
4681
- return rc ;
4682
- } else
4683
- return scsi_debug_queuecommand (cmd );
4684
- }
4685
-
4686
4959
static int
4687
4960
sdebug_change_qdepth (struct scsi_device * sdev , int qdepth )
4688
4961
{
@@ -4912,6 +5185,21 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp)
4912
5185
return schedule_resp (scp , devip , check_condition_result , 0 );
4913
5186
}
4914
5187
5188
+ static int
5189
+ sdebug_queuecommand_lock_or_not (struct Scsi_Host * shost , struct scsi_cmnd * cmd )
5190
+ {
5191
+ if (scsi_debug_host_lock ) {
5192
+ unsigned long iflags ;
5193
+ int rc ;
5194
+
5195
+ spin_lock_irqsave (shost -> host_lock , iflags );
5196
+ rc = scsi_debug_queuecommand (cmd );
5197
+ spin_unlock_irqrestore (shost -> host_lock , iflags );
5198
+ return rc ;
5199
+ } else
5200
+ return scsi_debug_queuecommand (cmd );
5201
+ }
5202
+
4915
5203
static struct scsi_host_template sdebug_driver_template = {
4916
5204
.show_info = scsi_debug_show_info ,
4917
5205
.write_info = scsi_debug_write_info ,
0 commit comments