return ret;
 }
 
+static sense_reason_t
+target_try_pr_out_pt(struct se_cmd *cmd, u8 sa, u64 res_key, u64 sa_res_key,
+                    u8 type, bool aptpl, bool all_tg_pt, bool spec_i_pt)
+{
+       struct exec_cmd_ops *ops = cmd->protocol_data;
+
+       if (!cmd->se_sess || !cmd->se_lun) {
+               pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
+
+       if (!ops->execute_pr_out) {
+               pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n");
+               return TCM_UNSUPPORTED_SCSI_OPCODE;
+       }
+
+       return ops->execute_pr_out(cmd, sa, res_key, sa_res_key, type, aptpl);
+}
+
 /*
  * See spc4r17 section 6.14 Table 170
  */
                return TCM_PARAMETER_LIST_LENGTH_ERROR;
        }
 
+       if (dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) {
+               ret = target_try_pr_out_pt(cmd, sa, res_key, sa_res_key, type,
+                                          aptpl, all_tg_pt, spec_i_pt);
+               goto done;
+       }
+
        /*
         * (core_scsi3_emulate_pro_* function parameters
         * are defined by spc4r17 Table 174:
                return TCM_INVALID_CDB_FIELD;
        }
 
+done:
        if (!ret)
                target_complete_cmd(cmd, SAM_STAT_GOOD);
        return ret;
        return 0;
 }
 
+static sense_reason_t target_try_pr_in_pt(struct se_cmd *cmd, u8 sa)
+{
+       struct exec_cmd_ops *ops = cmd->protocol_data;
+       unsigned char *buf;
+       sense_reason_t ret;
+
+       if (cmd->data_length < 8) {
+               pr_err("PRIN SA SCSI Data Length: %u too small\n",
+                      cmd->data_length);
+               return TCM_INVALID_CDB_FIELD;
+       }
+
+       if (!ops->execute_pr_in) {
+               pr_err("SPC-3 PR: Device has been configured for PR passthrough but it's not supported by the backend.\n");
+               return TCM_UNSUPPORTED_SCSI_OPCODE;
+       }
+
+       buf = transport_kmap_data_sg(cmd);
+       if (!buf)
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+       ret = ops->execute_pr_in(cmd, sa, buf);
+
+       transport_kunmap_data_sg(cmd);
+       return ret;
+}
+
 sense_reason_t
 target_scsi3_emulate_pr_in(struct se_cmd *cmd)
 {
+       u8 sa = cmd->t_task_cdb[1] & 0x1f;
        sense_reason_t ret;
 
        /*
                return TCM_RESERVATION_CONFLICT;
        }
 
-       switch (cmd->t_task_cdb[1] & 0x1f) {
+       if (cmd->se_dev->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR) {
+               ret = target_try_pr_in_pt(cmd, sa);
+               goto done;
+       }
+
+       switch (sa) {
        case PRI_READ_KEYS:
                ret = core_scsi3_pri_read_keys(cmd);
                break;
                return TCM_INVALID_CDB_FIELD;
        }
 
+done:
        if (!ret)
                target_complete_cmd(cmd, SAM_STAT_GOOD);
        return ret;
 
        sense_reason_t (*execute_write_same)(struct se_cmd *cmd);
        sense_reason_t (*execute_unmap)(struct se_cmd *cmd,
                                sector_t lba, sector_t nolb);
+       sense_reason_t (*execute_pr_out)(struct se_cmd *cmd, u8 sa, u64 key,
+                                        u64 sa_key, u8 type, bool aptpl);
+       sense_reason_t (*execute_pr_in)(struct se_cmd *cmd, u8 sa,
+                                       unsigned char *param_data);
 };
 
 int    transport_backend_register(const struct target_backend_ops *);