3737#include "libata.h"
3838#include "libata-transport.h"
3939
40- #define ATA_SCSI_RBUF_SIZE 576
40+ #define ATA_SCSI_RBUF_SIZE 2048
4141
4242static DEFINE_SPINLOCK (ata_scsi_rbuf_lock );
4343static u8 ata_scsi_rbuf [ATA_SCSI_RBUF_SIZE ];
@@ -55,6 +55,9 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
5555#define CONTROL_MPAGE_LEN 12
5656#define ALL_MPAGES 0x3f
5757#define ALL_SUB_MPAGES 0xff
58+ #define CDL_T2A_SUB_MPAGE 0x07
59+ #define CDL_T2B_SUB_MPAGE 0x08
60+ #define CDL_T2_SUB_MPAGE_LEN 232
5861
5962static const u8 def_rw_recovery_mpage [RW_RECOVERY_MPAGE_LEN ] = {
6063 RW_RECOVERY_MPAGE ,
@@ -2196,10 +2199,98 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
21962199 return sizeof (def_cache_mpage );
21972200}
21982201
2202+ /*
2203+ * Simulate MODE SENSE control mode page, sub-page 0.
2204+ */
2205+ static unsigned int ata_msense_control_spg0 (struct ata_device * dev , u8 * buf ,
2206+ bool changeable )
2207+ {
2208+ modecpy (buf , def_control_mpage ,
2209+ sizeof (def_control_mpage ), changeable );
2210+ if (changeable ) {
2211+ /* ata_mselect_control() */
2212+ buf [2 ] |= (1 << 2 );
2213+ } else {
2214+ bool d_sense = (dev -> flags & ATA_DFLAG_D_SENSE );
2215+
2216+ /* descriptor format sense data */
2217+ buf [2 ] |= (d_sense << 2 );
2218+ }
2219+
2220+ return sizeof (def_control_mpage );
2221+ }
2222+
2223+ /*
2224+ * Translate an ATA duration limit in microseconds to a SCSI duration limit
2225+ * using the t2cdlunits 0xa (10ms). Since the SCSI duration limits are 2-bytes
2226+ * only, take care of overflows.
2227+ */
2228+ static inline u16 ata_xlat_cdl_limit (u8 * buf )
2229+ {
2230+ u32 limit = get_unaligned_le32 (buf );
2231+
2232+ return min_t (u32 , limit / 10000 , 65535 );
2233+ }
2234+
2235+ /*
2236+ * Simulate MODE SENSE control mode page, sub-pages 07h and 08h
2237+ * (command duration limits T2A and T2B mode pages).
2238+ */
2239+ static unsigned int ata_msense_control_spgt2 (struct ata_device * dev , u8 * buf ,
2240+ u8 spg )
2241+ {
2242+ u8 * b , * cdl = dev -> cdl , * desc ;
2243+ u32 policy ;
2244+ int i ;
2245+
2246+ /*
2247+ * Fill the subpage. The first four bytes of the T2A/T2B mode pages
2248+ * are a header. The PAGE LENGTH field is the size of the page
2249+ * excluding the header.
2250+ */
2251+ buf [0 ] = CONTROL_MPAGE ;
2252+ buf [1 ] = spg ;
2253+ put_unaligned_be16 (CDL_T2_SUB_MPAGE_LEN - 4 , & buf [2 ]);
2254+ if (spg == CDL_T2A_SUB_MPAGE ) {
2255+ /*
2256+ * Read descriptors map to the T2A page:
2257+ * set perf_vs_duration_guidleine.
2258+ */
2259+ buf [7 ] = (cdl [0 ] & 0x03 ) << 4 ;
2260+ desc = cdl + 64 ;
2261+ } else {
2262+ /* Write descriptors map to the T2B page */
2263+ desc = cdl + 288 ;
2264+ }
2265+
2266+ /* Fill the T2 page descriptors */
2267+ b = & buf [8 ];
2268+ policy = get_unaligned_le32 (& cdl [0 ]);
2269+ for (i = 0 ; i < 7 ; i ++ , b += 32 , desc += 32 ) {
2270+ /* t2cdlunits: fixed to 10ms */
2271+ b [0 ] = 0x0a ;
2272+
2273+ /* Max inactive time and its policy */
2274+ put_unaligned_be16 (ata_xlat_cdl_limit (& desc [8 ]), & b [2 ]);
2275+ b [6 ] = ((policy >> 8 ) & 0x0f ) << 4 ;
2276+
2277+ /* Max active time and its policy */
2278+ put_unaligned_be16 (ata_xlat_cdl_limit (& desc [4 ]), & b [4 ]);
2279+ b [6 ] |= (policy >> 4 ) & 0x0f ;
2280+
2281+ /* Command duration guideline and its policy */
2282+ put_unaligned_be16 (ata_xlat_cdl_limit (& desc [16 ]), & b [10 ]);
2283+ b [14 ] = policy & 0x0f ;
2284+ }
2285+
2286+ return CDL_T2_SUB_MPAGE_LEN ;
2287+ }
2288+
21992289/**
22002290 * ata_msense_control - Simulate MODE SENSE control mode page
22012291 * @dev: ATA device of interest
22022292 * @buf: output buffer
2293+ * @spg: sub-page code
22032294 * @changeable: whether changeable parameters are requested
22042295 *
22052296 * Generate a generic MODE SENSE control mode page.
@@ -2208,17 +2299,24 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
22082299 * None.
22092300 */
22102301static unsigned int ata_msense_control (struct ata_device * dev , u8 * buf ,
2211- bool changeable )
2302+ u8 spg , bool changeable )
22122303{
2213- modecpy (buf , def_control_mpage , sizeof (def_control_mpage ), changeable );
2214- if (changeable ) {
2215- buf [2 ] |= (1 << 2 ); /* ata_mselect_control() */
2216- } else {
2217- bool d_sense = (dev -> flags & ATA_DFLAG_D_SENSE );
2218-
2219- buf [2 ] |= (d_sense << 2 ); /* descriptor format sense data */
2304+ unsigned int n ;
2305+
2306+ switch (spg ) {
2307+ case 0 :
2308+ return ata_msense_control_spg0 (dev , buf , changeable );
2309+ case CDL_T2A_SUB_MPAGE :
2310+ case CDL_T2B_SUB_MPAGE :
2311+ return ata_msense_control_spgt2 (dev , buf , spg );
2312+ case ALL_SUB_MPAGES :
2313+ n = ata_msense_control_spg0 (dev , buf , changeable );
2314+ n += ata_msense_control_spgt2 (dev , buf + n , CDL_T2A_SUB_MPAGE );
2315+ n += ata_msense_control_spgt2 (dev , buf + n , CDL_T2A_SUB_MPAGE );
2316+ return n ;
2317+ default :
2318+ return 0 ;
22202319 }
2221- return sizeof (def_control_mpage );
22222320}
22232321
22242322/**
@@ -2291,13 +2389,24 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
22912389
22922390 pg = scsicmd [2 ] & 0x3f ;
22932391 spg = scsicmd [3 ];
2392+
22942393 /*
2295- * No mode subpages supported (yet) but asking for _all_
2296- * subpages may be valid
2394+ * Supported subpages: all subpages and sub-pages 07h and 08h of
2395+ * the control page.
22972396 */
2298- if (spg && (spg != ALL_SUB_MPAGES )) {
2299- fp = 3 ;
2300- goto invalid_fld ;
2397+ if (spg ) {
2398+ switch (spg ) {
2399+ case ALL_SUB_MPAGES :
2400+ break ;
2401+ case CDL_T2A_SUB_MPAGE :
2402+ case CDL_T2B_SUB_MPAGE :
2403+ if (dev -> flags & ATA_DFLAG_CDL && pg == CONTROL_MPAGE )
2404+ break ;
2405+ fallthrough ;
2406+ default :
2407+ fp = 3 ;
2408+ goto invalid_fld ;
2409+ }
23012410 }
23022411
23032412 switch (pg ) {
@@ -2310,13 +2419,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
23102419 break ;
23112420
23122421 case CONTROL_MPAGE :
2313- p += ata_msense_control (args -> dev , p , page_control == 1 );
2422+ p += ata_msense_control (args -> dev , p , spg , page_control == 1 );
23142423 break ;
23152424
23162425 case ALL_MPAGES :
23172426 p += ata_msense_rw_recovery (p , page_control == 1 );
23182427 p += ata_msense_caching (args -> id , p , page_control == 1 );
2319- p += ata_msense_control (args -> dev , p , page_control == 1 );
2428+ p += ata_msense_control (args -> dev , p , spg , page_control == 1 );
23202429 break ;
23212430
23222431 default : /* invalid page code */
@@ -2335,10 +2444,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
23352444 memcpy (rbuf + 4 , sat_blk_desc , sizeof (sat_blk_desc ));
23362445 }
23372446 } else {
2338- unsigned int output_len = p - rbuf - 2 ;
2339-
2340- rbuf [0 ] = output_len >> 8 ;
2341- rbuf [1 ] = output_len ;
2447+ put_unaligned_be16 (p - rbuf - 2 , & rbuf [0 ]);
23422448 rbuf [3 ] |= dpofua ;
23432449 if (ebd ) {
23442450 rbuf [7 ] = sizeof (sat_blk_desc );
@@ -3637,7 +3743,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
36373743 /*
36383744 * Check that read-only bits are not modified.
36393745 */
3640- ata_msense_control (dev , mpage , false);
3746+ ata_msense_control_spg0 (dev , mpage , false);
36413747 for (i = 0 ; i < CONTROL_MPAGE_LEN - 2 ; i ++ ) {
36423748 if (i == 0 )
36433749 continue ;
0 commit comments