scsi: scsi_debug: Rework subpage code error handling
authorBart Van Assche <bvanassche@acm.org>
Tue, 30 Jan 2024 21:48:41 +0000 (13:48 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 27 Feb 2024 02:37:26 +0000 (21:37 -0500)
Move the subpage code checks into the switch statement to make it easier
to add support for new page code / subpage code combinations.

Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Tested-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-16-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_debug.c

index ba0a29e6a86df0fb9cd0fbddc01bec5a6681b043..67a8e6243e5e2976ad2900c8b7801af2c1c7827b 100644 (file)
@@ -2703,22 +2703,22 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
                ap = arr + offset;
        }
 
-       if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) {
-               /* TODO: Control Extension page */
-               mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
-               return check_condition_result;
-       }
-
        switch (pcode) {
        case 0x1:       /* Read-Write error recovery page, direct access */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                len = resp_err_recov_pg(ap, pcontrol, target);
                offset += len;
                break;
        case 0x2:       /* Disconnect-Reconnect page, all devices */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                len = resp_disconnect_pg(ap, pcontrol, target);
                offset += len;
                break;
        case 0x3:       /* Format device page, direct access */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                if (is_disk) {
                        len = resp_format_pg(ap, pcontrol, target);
                        offset += len;
@@ -2727,6 +2727,8 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
                }
                break;
        case 0x8:       /* Caching page, direct access */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                if (is_disk || is_zbc) {
                        len = resp_caching_pg(ap, pcontrol, target);
                        offset += len;
@@ -2735,14 +2737,14 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
                }
                break;
        case 0xa:       /* Control Mode page, all devices */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                len = resp_ctrl_m_pg(ap, pcontrol, target);
                offset += len;
                break;
        case 0x19:      /* if spc==1 then sas phy, control+discover */
-               if ((subpcode > 0x2) && (subpcode < 0xff)) {
-                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
-                       return check_condition_result;
-               }
+               if (subpcode > 0x2 && subpcode < 0xff)
+                       goto bad_subpcode;
                len = 0;
                if ((0x0 == subpcode) || (0xff == subpcode))
                        len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
@@ -2754,35 +2756,31 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
                offset += len;
                break;
        case 0x1c:      /* Informational Exceptions Mode page, all devices */
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
                len = resp_iec_m_pg(ap, pcontrol, target);
                offset += len;
                break;
        case 0x3f:      /* Read all Mode pages */
-               if ((0 == subpcode) || (0xff == subpcode)) {
-                       len = resp_err_recov_pg(ap, pcontrol, target);
-                       len += resp_disconnect_pg(ap + len, pcontrol, target);
-                       if (is_disk) {
-                               len += resp_format_pg(ap + len, pcontrol,
-                                                     target);
-                               len += resp_caching_pg(ap + len, pcontrol,
-                                                      target);
-                       } else if (is_zbc) {
-                               len += resp_caching_pg(ap + len, pcontrol,
-                                                      target);
-                       }
-                       len += resp_ctrl_m_pg(ap + len, pcontrol, target);
-                       len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
-                       if (0xff == subpcode) {
-                               len += resp_sas_pcd_m_spg(ap + len, pcontrol,
-                                                 target, target_dev_id);
-                               len += resp_sas_sha_m_spg(ap + len, pcontrol);
-                       }
-                       len += resp_iec_m_pg(ap + len, pcontrol, target);
-                       offset += len;
-               } else {
-                       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
-                       return check_condition_result;
+               if (subpcode > 0x0 && subpcode < 0xff)
+                       goto bad_subpcode;
+               len = resp_err_recov_pg(ap, pcontrol, target);
+               len += resp_disconnect_pg(ap + len, pcontrol, target);
+               if (is_disk) {
+                       len += resp_format_pg(ap + len, pcontrol, target);
+                       len += resp_caching_pg(ap + len, pcontrol, target);
+               } else if (is_zbc) {
+                       len += resp_caching_pg(ap + len, pcontrol, target);
+               }
+               len += resp_ctrl_m_pg(ap + len, pcontrol, target);
+               len += resp_sas_sf_m_pg(ap + len, pcontrol, target);
+               if (0xff == subpcode) {
+                       len += resp_sas_pcd_m_spg(ap + len, pcontrol, target,
+                                                 target_dev_id);
+                       len += resp_sas_sha_m_spg(ap + len, pcontrol);
                }
+               len += resp_iec_m_pg(ap + len, pcontrol, target);
+               offset += len;
                break;
        default:
                goto bad_pcode;
@@ -2796,6 +2794,10 @@ static int resp_mode_sense(struct scsi_cmnd *scp,
 bad_pcode:
        mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, 5);
        return check_condition_result;
+
+bad_subpcode:
+       mk_sense_invalid_fld(scp, SDEB_IN_CDB, 3, -1);
+       return check_condition_result;
 }
 
 #define SDEBUG_MAX_MSELECT_SZ 512