}
 };
 
+static int sd_scsi_to_pr_err(struct scsi_sense_hdr *sshdr, int result)
+{
+       switch (host_byte(result)) {
+       case DID_TRANSPORT_MARGINAL:
+       case DID_TRANSPORT_DISRUPTED:
+       case DID_BUS_BUSY:
+               return PR_STS_RETRY_PATH_FAILURE;
+       case DID_NO_CONNECT:
+               return PR_STS_PATH_FAILED;
+       case DID_TRANSPORT_FAILFAST:
+               return PR_STS_PATH_FAST_FAILED;
+       }
+
+       switch (status_byte(result)) {
+       case SAM_STAT_RESERVATION_CONFLICT:
+               return PR_STS_RESERVATION_CONFLICT;
+       case SAM_STAT_CHECK_CONDITION:
+               if (!scsi_sense_valid(sshdr))
+                       return PR_STS_IOERR;
+
+               if (sshdr->sense_key == ILLEGAL_REQUEST &&
+                   (sshdr->asc == 0x26 || sshdr->asc == 0x24))
+                       return -EINVAL;
+
+               fallthrough;
+       default:
+               return PR_STS_IOERR;
+       }
+}
+
 static int sd_pr_command(struct block_device *bdev, u8 sa,
                u64 key, u64 sa_key, u8 type, u8 flags)
 {
                scsi_print_sense_hdr(sdev, NULL, &sshdr);
        }
 
-       return result;
+       if (result <= 0)
+               return result;
+
+       return sd_scsi_to_pr_err(&sshdr, result);
 }
 
 static int sd_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
 
  *      msg_byte    (unused)
  *      host_byte   = set by low-level driver to indicate status.
  */
+#define status_byte(result) (result & 0xff)
 #define host_byte(result)   (((result) >> 16) & 0xff)
 
 #define sense_class(sense)  (((sense) >> 4) & 0x7)