|
@@ -1905,6 +1905,21 @@ static void transport_handle_queue_full(
|
|
|
schedule_work(&cmd->se_dev->qf_work_queue);
|
|
|
}
|
|
|
|
|
|
+static bool target_check_read_strip(struct se_cmd *cmd)
|
|
|
+{
|
|
|
+ sense_reason_t rc;
|
|
|
+
|
|
|
+ if (!(cmd->se_sess->sup_prot_ops & TARGET_PROT_DIN_STRIP)) {
|
|
|
+ rc = sbc_dif_read_strip(cmd);
|
|
|
+ if (rc) {
|
|
|
+ cmd->pi_err = rc;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static void target_complete_ok_work(struct work_struct *work)
|
|
|
{
|
|
|
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
|
|
@@ -1969,6 +1984,22 @@ static void target_complete_ok_work(struct work_struct *work)
|
|
|
cmd->data_length;
|
|
|
}
|
|
|
spin_unlock(&cmd->se_lun->lun_sep_lock);
|
|
|
+ /*
|
|
|
+ * Perform READ_STRIP of PI using software emulation when
|
|
|
+ * backend had PI enabled, if the transport will not be
|
|
|
+ * performing hardware READ_STRIP offload.
|
|
|
+ */
|
|
|
+ if (cmd->prot_op == TARGET_PROT_DIN_STRIP &&
|
|
|
+ target_check_read_strip(cmd)) {
|
|
|
+ ret = transport_send_check_condition_and_sense(cmd,
|
|
|
+ cmd->pi_err, 0);
|
|
|
+ if (ret == -EAGAIN || ret == -ENOMEM)
|
|
|
+ goto queue_full;
|
|
|
+
|
|
|
+ transport_lun_remove_cmd(cmd);
|
|
|
+ transport_cmd_check_stop_to_fabric(cmd);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
trace_target_cmd_complete(cmd);
|
|
|
ret = cmd->se_tfo->queue_data_in(cmd);
|