1e48354ceSNicholas Bellinger /******************************************************************************* 2e48354ceSNicholas Bellinger * This file contains error recovery level two functions used by 3e48354ceSNicholas Bellinger * the iSCSI Target driver. 4e48354ceSNicholas Bellinger * 5e48354ceSNicholas Bellinger * \u00a9 Copyright 2007-2011 RisingTide Systems LLC. 6e48354ceSNicholas Bellinger * 7e48354ceSNicholas Bellinger * Licensed to the Linux Foundation under the General Public License (GPL) version 2. 8e48354ceSNicholas Bellinger * 9e48354ceSNicholas Bellinger * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> 10e48354ceSNicholas Bellinger * 11e48354ceSNicholas Bellinger * This program is free software; you can redistribute it and/or modify 12e48354ceSNicholas Bellinger * it under the terms of the GNU General Public License as published by 13e48354ceSNicholas Bellinger * the Free Software Foundation; either version 2 of the License, or 14e48354ceSNicholas Bellinger * (at your option) any later version. 15e48354ceSNicholas Bellinger * 16e48354ceSNicholas Bellinger * This program is distributed in the hope that it will be useful, 17e48354ceSNicholas Bellinger * but WITHOUT ANY WARRANTY; without even the implied warranty of 18e48354ceSNicholas Bellinger * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19e48354ceSNicholas Bellinger * GNU General Public License for more details. 20e48354ceSNicholas Bellinger ******************************************************************************/ 21e48354ceSNicholas Bellinger 22e48354ceSNicholas Bellinger #include <scsi/iscsi_proto.h> 23e48354ceSNicholas Bellinger #include <target/target_core_base.h> 24c4795fb2SChristoph Hellwig #include <target/target_core_fabric.h> 25e48354ceSNicholas Bellinger 26e48354ceSNicholas Bellinger #include "iscsi_target_core.h" 27e48354ceSNicholas Bellinger #include "iscsi_target_datain_values.h" 28e48354ceSNicholas Bellinger #include "iscsi_target_util.h" 29e48354ceSNicholas Bellinger #include "iscsi_target_erl0.h" 30e48354ceSNicholas Bellinger #include "iscsi_target_erl1.h" 31e48354ceSNicholas Bellinger #include "iscsi_target_erl2.h" 32e48354ceSNicholas Bellinger #include "iscsi_target.h" 33e48354ceSNicholas Bellinger 34e48354ceSNicholas Bellinger /* 35e48354ceSNicholas Bellinger * FIXME: Does RData SNACK apply here as well? 36e48354ceSNicholas Bellinger */ 37e48354ceSNicholas Bellinger void iscsit_create_conn_recovery_datain_values( 38e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, 39e48354ceSNicholas Bellinger u32 exp_data_sn) 40e48354ceSNicholas Bellinger { 41e48354ceSNicholas Bellinger u32 data_sn = 0; 42e48354ceSNicholas Bellinger struct iscsi_conn *conn = cmd->conn; 43e48354ceSNicholas Bellinger 44e48354ceSNicholas Bellinger cmd->next_burst_len = 0; 45e48354ceSNicholas Bellinger cmd->read_data_done = 0; 46e48354ceSNicholas Bellinger 47e48354ceSNicholas Bellinger while (exp_data_sn > data_sn) { 48e48354ceSNicholas Bellinger if ((cmd->next_burst_len + 49e48354ceSNicholas Bellinger conn->conn_ops->MaxRecvDataSegmentLength) < 50e48354ceSNicholas Bellinger conn->sess->sess_ops->MaxBurstLength) { 51e48354ceSNicholas Bellinger cmd->read_data_done += 52e48354ceSNicholas Bellinger conn->conn_ops->MaxRecvDataSegmentLength; 53e48354ceSNicholas Bellinger cmd->next_burst_len += 54e48354ceSNicholas Bellinger conn->conn_ops->MaxRecvDataSegmentLength; 55e48354ceSNicholas Bellinger } else { 56e48354ceSNicholas Bellinger cmd->read_data_done += 57e48354ceSNicholas Bellinger (conn->sess->sess_ops->MaxBurstLength - 58e48354ceSNicholas Bellinger cmd->next_burst_len); 59e48354ceSNicholas Bellinger cmd->next_burst_len = 0; 60e48354ceSNicholas Bellinger } 61e48354ceSNicholas Bellinger data_sn++; 62e48354ceSNicholas Bellinger } 63e48354ceSNicholas Bellinger } 64e48354ceSNicholas Bellinger 65e48354ceSNicholas Bellinger void iscsit_create_conn_recovery_dataout_values( 66e48354ceSNicholas Bellinger struct iscsi_cmd *cmd) 67e48354ceSNicholas Bellinger { 68e48354ceSNicholas Bellinger u32 write_data_done = 0; 69e48354ceSNicholas Bellinger struct iscsi_conn *conn = cmd->conn; 70e48354ceSNicholas Bellinger 71e48354ceSNicholas Bellinger cmd->data_sn = 0; 72e48354ceSNicholas Bellinger cmd->next_burst_len = 0; 73e48354ceSNicholas Bellinger 74e48354ceSNicholas Bellinger while (cmd->write_data_done > write_data_done) { 75e48354ceSNicholas Bellinger if ((write_data_done + conn->sess->sess_ops->MaxBurstLength) <= 76e48354ceSNicholas Bellinger cmd->write_data_done) 77e48354ceSNicholas Bellinger write_data_done += conn->sess->sess_ops->MaxBurstLength; 78e48354ceSNicholas Bellinger else 79e48354ceSNicholas Bellinger break; 80e48354ceSNicholas Bellinger } 81e48354ceSNicholas Bellinger 82e48354ceSNicholas Bellinger cmd->write_data_done = write_data_done; 83e48354ceSNicholas Bellinger } 84e48354ceSNicholas Bellinger 85e48354ceSNicholas Bellinger static int iscsit_attach_active_connection_recovery_entry( 86e48354ceSNicholas Bellinger struct iscsi_session *sess, 87e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr) 88e48354ceSNicholas Bellinger { 89e48354ceSNicholas Bellinger spin_lock(&sess->cr_a_lock); 90e48354ceSNicholas Bellinger list_add_tail(&cr->cr_list, &sess->cr_active_list); 91e48354ceSNicholas Bellinger spin_unlock(&sess->cr_a_lock); 92e48354ceSNicholas Bellinger 93e48354ceSNicholas Bellinger return 0; 94e48354ceSNicholas Bellinger } 95e48354ceSNicholas Bellinger 96e48354ceSNicholas Bellinger static int iscsit_attach_inactive_connection_recovery_entry( 97e48354ceSNicholas Bellinger struct iscsi_session *sess, 98e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr) 99e48354ceSNicholas Bellinger { 100e48354ceSNicholas Bellinger spin_lock(&sess->cr_i_lock); 101e48354ceSNicholas Bellinger list_add_tail(&cr->cr_list, &sess->cr_inactive_list); 102e48354ceSNicholas Bellinger 103e48354ceSNicholas Bellinger sess->conn_recovery_count++; 104e48354ceSNicholas Bellinger pr_debug("Incremented connection recovery count to %u for" 105e48354ceSNicholas Bellinger " SID: %u\n", sess->conn_recovery_count, sess->sid); 106e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 107e48354ceSNicholas Bellinger 108e48354ceSNicholas Bellinger return 0; 109e48354ceSNicholas Bellinger } 110e48354ceSNicholas Bellinger 111e48354ceSNicholas Bellinger struct iscsi_conn_recovery *iscsit_get_inactive_connection_recovery_entry( 112e48354ceSNicholas Bellinger struct iscsi_session *sess, 113e48354ceSNicholas Bellinger u16 cid) 114e48354ceSNicholas Bellinger { 115e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr; 116e48354ceSNicholas Bellinger 117e48354ceSNicholas Bellinger spin_lock(&sess->cr_i_lock); 118e48354ceSNicholas Bellinger list_for_each_entry(cr, &sess->cr_inactive_list, cr_list) { 119e48354ceSNicholas Bellinger if (cr->cid == cid) { 120e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 121e48354ceSNicholas Bellinger return cr; 122e48354ceSNicholas Bellinger } 123e48354ceSNicholas Bellinger } 124e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 125e48354ceSNicholas Bellinger 126e48354ceSNicholas Bellinger return NULL; 127e48354ceSNicholas Bellinger } 128e48354ceSNicholas Bellinger 129e48354ceSNicholas Bellinger void iscsit_free_connection_recovery_entires(struct iscsi_session *sess) 130e48354ceSNicholas Bellinger { 131e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, *cmd_tmp; 132e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr, *cr_tmp; 133e48354ceSNicholas Bellinger 134e48354ceSNicholas Bellinger spin_lock(&sess->cr_a_lock); 135e48354ceSNicholas Bellinger list_for_each_entry_safe(cr, cr_tmp, &sess->cr_active_list, cr_list) { 136e48354ceSNicholas Bellinger list_del(&cr->cr_list); 137e48354ceSNicholas Bellinger spin_unlock(&sess->cr_a_lock); 138e48354ceSNicholas Bellinger 139e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 140e48354ceSNicholas Bellinger list_for_each_entry_safe(cmd, cmd_tmp, 1412fbb471eSAndy Grover &cr->conn_recovery_cmd_list, i_conn_node) { 142e48354ceSNicholas Bellinger 1432fbb471eSAndy Grover list_del(&cmd->i_conn_node); 144e48354ceSNicholas Bellinger cmd->conn = NULL; 145e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 146d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 147e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 148e48354ceSNicholas Bellinger } 149e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 150e48354ceSNicholas Bellinger spin_lock(&sess->cr_a_lock); 151e48354ceSNicholas Bellinger 152e48354ceSNicholas Bellinger kfree(cr); 153e48354ceSNicholas Bellinger } 154e48354ceSNicholas Bellinger spin_unlock(&sess->cr_a_lock); 155e48354ceSNicholas Bellinger 156e48354ceSNicholas Bellinger spin_lock(&sess->cr_i_lock); 157e48354ceSNicholas Bellinger list_for_each_entry_safe(cr, cr_tmp, &sess->cr_inactive_list, cr_list) { 158e48354ceSNicholas Bellinger list_del(&cr->cr_list); 159e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 160e48354ceSNicholas Bellinger 161e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 162e48354ceSNicholas Bellinger list_for_each_entry_safe(cmd, cmd_tmp, 1632fbb471eSAndy Grover &cr->conn_recovery_cmd_list, i_conn_node) { 164e48354ceSNicholas Bellinger 1652fbb471eSAndy Grover list_del(&cmd->i_conn_node); 166e48354ceSNicholas Bellinger cmd->conn = NULL; 167e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 168d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 169e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 170e48354ceSNicholas Bellinger } 171e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 172e48354ceSNicholas Bellinger spin_lock(&sess->cr_i_lock); 173e48354ceSNicholas Bellinger 174e48354ceSNicholas Bellinger kfree(cr); 175e48354ceSNicholas Bellinger } 176e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 177e48354ceSNicholas Bellinger } 178e48354ceSNicholas Bellinger 179e48354ceSNicholas Bellinger int iscsit_remove_active_connection_recovery_entry( 180e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr, 181e48354ceSNicholas Bellinger struct iscsi_session *sess) 182e48354ceSNicholas Bellinger { 183e48354ceSNicholas Bellinger spin_lock(&sess->cr_a_lock); 184e48354ceSNicholas Bellinger list_del(&cr->cr_list); 185e48354ceSNicholas Bellinger 186e48354ceSNicholas Bellinger sess->conn_recovery_count--; 187e48354ceSNicholas Bellinger pr_debug("Decremented connection recovery count to %u for" 188e48354ceSNicholas Bellinger " SID: %u\n", sess->conn_recovery_count, sess->sid); 189e48354ceSNicholas Bellinger spin_unlock(&sess->cr_a_lock); 190e48354ceSNicholas Bellinger 191e48354ceSNicholas Bellinger kfree(cr); 192e48354ceSNicholas Bellinger 193e48354ceSNicholas Bellinger return 0; 194e48354ceSNicholas Bellinger } 195e48354ceSNicholas Bellinger 196e48354ceSNicholas Bellinger int iscsit_remove_inactive_connection_recovery_entry( 197e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr, 198e48354ceSNicholas Bellinger struct iscsi_session *sess) 199e48354ceSNicholas Bellinger { 200e48354ceSNicholas Bellinger spin_lock(&sess->cr_i_lock); 201e48354ceSNicholas Bellinger list_del(&cr->cr_list); 202e48354ceSNicholas Bellinger spin_unlock(&sess->cr_i_lock); 203e48354ceSNicholas Bellinger 204e48354ceSNicholas Bellinger return 0; 205e48354ceSNicholas Bellinger } 206e48354ceSNicholas Bellinger 207e48354ceSNicholas Bellinger /* 208e48354ceSNicholas Bellinger * Called with cr->conn_recovery_cmd_lock help. 209e48354ceSNicholas Bellinger */ 210e48354ceSNicholas Bellinger int iscsit_remove_cmd_from_connection_recovery( 211e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, 212e48354ceSNicholas Bellinger struct iscsi_session *sess) 213e48354ceSNicholas Bellinger { 214e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr; 215e48354ceSNicholas Bellinger 216e48354ceSNicholas Bellinger if (!cmd->cr) { 217e48354ceSNicholas Bellinger pr_err("struct iscsi_conn_recovery pointer for ITT: 0x%08x" 218e48354ceSNicholas Bellinger " is NULL!\n", cmd->init_task_tag); 219e48354ceSNicholas Bellinger BUG(); 220e48354ceSNicholas Bellinger } 221e48354ceSNicholas Bellinger cr = cmd->cr; 222e48354ceSNicholas Bellinger 2232fbb471eSAndy Grover list_del(&cmd->i_conn_node); 224e48354ceSNicholas Bellinger return --cr->cmd_count; 225e48354ceSNicholas Bellinger } 226e48354ceSNicholas Bellinger 227e48354ceSNicholas Bellinger void iscsit_discard_cr_cmds_by_expstatsn( 228e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr, 229e48354ceSNicholas Bellinger u32 exp_statsn) 230e48354ceSNicholas Bellinger { 231e48354ceSNicholas Bellinger u32 dropped_count = 0; 232e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, *cmd_tmp; 233e48354ceSNicholas Bellinger struct iscsi_session *sess = cr->sess; 234e48354ceSNicholas Bellinger 235e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 236e48354ceSNicholas Bellinger list_for_each_entry_safe(cmd, cmd_tmp, 2372fbb471eSAndy Grover &cr->conn_recovery_cmd_list, i_conn_node) { 238e48354ceSNicholas Bellinger 239e48354ceSNicholas Bellinger if (((cmd->deferred_i_state != ISTATE_SENT_STATUS) && 240e48354ceSNicholas Bellinger (cmd->deferred_i_state != ISTATE_REMOVE)) || 241e48354ceSNicholas Bellinger (cmd->stat_sn >= exp_statsn)) { 242e48354ceSNicholas Bellinger continue; 243e48354ceSNicholas Bellinger } 244e48354ceSNicholas Bellinger 245e48354ceSNicholas Bellinger dropped_count++; 246e48354ceSNicholas Bellinger pr_debug("Dropping Acknowledged ITT: 0x%08x, StatSN:" 247e48354ceSNicholas Bellinger " 0x%08x, CID: %hu.\n", cmd->init_task_tag, 248e48354ceSNicholas Bellinger cmd->stat_sn, cr->cid); 249e48354ceSNicholas Bellinger 250e48354ceSNicholas Bellinger iscsit_remove_cmd_from_connection_recovery(cmd, sess); 251e48354ceSNicholas Bellinger 252e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 253d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 254e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 255e48354ceSNicholas Bellinger } 256e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 257e48354ceSNicholas Bellinger 258e48354ceSNicholas Bellinger pr_debug("Dropped %u total acknowledged commands on" 259e48354ceSNicholas Bellinger " CID: %hu less than old ExpStatSN: 0x%08x\n", 260e48354ceSNicholas Bellinger dropped_count, cr->cid, exp_statsn); 261e48354ceSNicholas Bellinger 262e48354ceSNicholas Bellinger if (!cr->cmd_count) { 263e48354ceSNicholas Bellinger pr_debug("No commands to be reassigned for failed" 264e48354ceSNicholas Bellinger " connection CID: %hu on SID: %u\n", 265e48354ceSNicholas Bellinger cr->cid, sess->sid); 266e48354ceSNicholas Bellinger iscsit_remove_inactive_connection_recovery_entry(cr, sess); 267e48354ceSNicholas Bellinger iscsit_attach_active_connection_recovery_entry(sess, cr); 268e48354ceSNicholas Bellinger pr_debug("iSCSI connection recovery successful for CID:" 269e48354ceSNicholas Bellinger " %hu on SID: %u\n", cr->cid, sess->sid); 270e48354ceSNicholas Bellinger iscsit_remove_active_connection_recovery_entry(cr, sess); 271e48354ceSNicholas Bellinger } else { 272e48354ceSNicholas Bellinger iscsit_remove_inactive_connection_recovery_entry(cr, sess); 273e48354ceSNicholas Bellinger iscsit_attach_active_connection_recovery_entry(sess, cr); 274e48354ceSNicholas Bellinger } 275e48354ceSNicholas Bellinger } 276e48354ceSNicholas Bellinger 277e48354ceSNicholas Bellinger int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn) 278e48354ceSNicholas Bellinger { 279e48354ceSNicholas Bellinger u32 dropped_count = 0; 280e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, *cmd_tmp; 281e48354ceSNicholas Bellinger struct iscsi_ooo_cmdsn *ooo_cmdsn, *ooo_cmdsn_tmp; 282e48354ceSNicholas Bellinger struct iscsi_session *sess = conn->sess; 283e48354ceSNicholas Bellinger 284e48354ceSNicholas Bellinger mutex_lock(&sess->cmdsn_mutex); 285e48354ceSNicholas Bellinger list_for_each_entry_safe(ooo_cmdsn, ooo_cmdsn_tmp, 286e48354ceSNicholas Bellinger &sess->sess_ooo_cmdsn_list, ooo_list) { 287e48354ceSNicholas Bellinger 288e48354ceSNicholas Bellinger if (ooo_cmdsn->cid != conn->cid) 289e48354ceSNicholas Bellinger continue; 290e48354ceSNicholas Bellinger 291e48354ceSNicholas Bellinger dropped_count++; 292e48354ceSNicholas Bellinger pr_debug("Dropping unacknowledged CmdSN:" 293e48354ceSNicholas Bellinger " 0x%08x during connection recovery on CID: %hu\n", 294e48354ceSNicholas Bellinger ooo_cmdsn->cmdsn, conn->cid); 295e48354ceSNicholas Bellinger iscsit_remove_ooo_cmdsn(sess, ooo_cmdsn); 296e48354ceSNicholas Bellinger } 297e48354ceSNicholas Bellinger mutex_unlock(&sess->cmdsn_mutex); 298e48354ceSNicholas Bellinger 299e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 3002fbb471eSAndy Grover list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { 301e48354ceSNicholas Bellinger if (!(cmd->cmd_flags & ICF_OOO_CMDSN)) 302e48354ceSNicholas Bellinger continue; 303e48354ceSNicholas Bellinger 3042fbb471eSAndy Grover list_del(&cmd->i_conn_node); 305e48354ceSNicholas Bellinger 306e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 307d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 308e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 309e48354ceSNicholas Bellinger } 310e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 311e48354ceSNicholas Bellinger 312e48354ceSNicholas Bellinger pr_debug("Dropped %u total unacknowledged commands on CID:" 313e48354ceSNicholas Bellinger " %hu for ExpCmdSN: 0x%08x.\n", dropped_count, conn->cid, 314e48354ceSNicholas Bellinger sess->exp_cmd_sn); 315e48354ceSNicholas Bellinger return 0; 316e48354ceSNicholas Bellinger } 317e48354ceSNicholas Bellinger 318e48354ceSNicholas Bellinger int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) 319e48354ceSNicholas Bellinger { 320e48354ceSNicholas Bellinger u32 cmd_count = 0; 321e48354ceSNicholas Bellinger struct iscsi_cmd *cmd, *cmd_tmp; 322e48354ceSNicholas Bellinger struct iscsi_conn_recovery *cr; 323e48354ceSNicholas Bellinger 324e48354ceSNicholas Bellinger /* 325e48354ceSNicholas Bellinger * Allocate an struct iscsi_conn_recovery for this connection. 326e48354ceSNicholas Bellinger * Each struct iscsi_cmd contains an struct iscsi_conn_recovery pointer 327e48354ceSNicholas Bellinger * (struct iscsi_cmd->cr) so we need to allocate this before preparing the 328e48354ceSNicholas Bellinger * connection's command list for connection recovery. 329e48354ceSNicholas Bellinger */ 330e48354ceSNicholas Bellinger cr = kzalloc(sizeof(struct iscsi_conn_recovery), GFP_KERNEL); 331e48354ceSNicholas Bellinger if (!cr) { 332e48354ceSNicholas Bellinger pr_err("Unable to allocate memory for" 333e48354ceSNicholas Bellinger " struct iscsi_conn_recovery.\n"); 334e48354ceSNicholas Bellinger return -1; 335e48354ceSNicholas Bellinger } 336e48354ceSNicholas Bellinger INIT_LIST_HEAD(&cr->cr_list); 337e48354ceSNicholas Bellinger INIT_LIST_HEAD(&cr->conn_recovery_cmd_list); 338e48354ceSNicholas Bellinger spin_lock_init(&cr->conn_recovery_cmd_lock); 339e48354ceSNicholas Bellinger /* 340e48354ceSNicholas Bellinger * Only perform connection recovery on ISCSI_OP_SCSI_CMD or 341e48354ceSNicholas Bellinger * ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call 3422fbb471eSAndy Grover * list_del(&cmd->i_conn_node); to release the command to the 343e48354ceSNicholas Bellinger * session pool and remove it from the connection's list. 344e48354ceSNicholas Bellinger * 345e48354ceSNicholas Bellinger * Also stop the DataOUT timer, which will be restarted after 346e48354ceSNicholas Bellinger * sending the TMR response. 347e48354ceSNicholas Bellinger */ 348e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 3492fbb471eSAndy Grover list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { 350e48354ceSNicholas Bellinger 351e48354ceSNicholas Bellinger if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) && 352e48354ceSNicholas Bellinger (cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) { 353e48354ceSNicholas Bellinger pr_debug("Not performing realligence on" 354e48354ceSNicholas Bellinger " Opcode: 0x%02x, ITT: 0x%08x, CmdSN: 0x%08x," 355e48354ceSNicholas Bellinger " CID: %hu\n", cmd->iscsi_opcode, 356e48354ceSNicholas Bellinger cmd->init_task_tag, cmd->cmd_sn, conn->cid); 357e48354ceSNicholas Bellinger 3582fbb471eSAndy Grover list_del(&cmd->i_conn_node); 359e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 360d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 361e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 362e48354ceSNicholas Bellinger continue; 363e48354ceSNicholas Bellinger } 364e48354ceSNicholas Bellinger 365e48354ceSNicholas Bellinger /* 366e48354ceSNicholas Bellinger * Special case where commands greater than or equal to 367e48354ceSNicholas Bellinger * the session's ExpCmdSN are attached to the connection 368e48354ceSNicholas Bellinger * list but not to the out of order CmdSN list. The one 369e48354ceSNicholas Bellinger * obvious case is when a command with immediate data 370e48354ceSNicholas Bellinger * attached must only check the CmdSN against ExpCmdSN 371e48354ceSNicholas Bellinger * after the data is received. The special case below 372e48354ceSNicholas Bellinger * is when the connection fails before data is received, 373e48354ceSNicholas Bellinger * but also may apply to other PDUs, so it has been 374e48354ceSNicholas Bellinger * made generic here. 375e48354ceSNicholas Bellinger */ 376e48354ceSNicholas Bellinger if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && 377e48354ceSNicholas Bellinger (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { 3782fbb471eSAndy Grover list_del(&cmd->i_conn_node); 379e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 380d270190aSNicholas Bellinger iscsit_free_cmd(cmd); 381e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 382e48354ceSNicholas Bellinger continue; 383e48354ceSNicholas Bellinger } 384e48354ceSNicholas Bellinger 385e48354ceSNicholas Bellinger cmd_count++; 386e48354ceSNicholas Bellinger pr_debug("Preparing Opcode: 0x%02x, ITT: 0x%08x," 387e48354ceSNicholas Bellinger " CmdSN: 0x%08x, StatSN: 0x%08x, CID: %hu for" 388e48354ceSNicholas Bellinger " realligence.\n", cmd->iscsi_opcode, 389e48354ceSNicholas Bellinger cmd->init_task_tag, cmd->cmd_sn, cmd->stat_sn, 390e48354ceSNicholas Bellinger conn->cid); 391e48354ceSNicholas Bellinger 392e48354ceSNicholas Bellinger cmd->deferred_i_state = cmd->i_state; 393e48354ceSNicholas Bellinger cmd->i_state = ISTATE_IN_CONNECTION_RECOVERY; 394e48354ceSNicholas Bellinger 395e48354ceSNicholas Bellinger if (cmd->data_direction == DMA_TO_DEVICE) 396e48354ceSNicholas Bellinger iscsit_stop_dataout_timer(cmd); 397e48354ceSNicholas Bellinger 398e48354ceSNicholas Bellinger cmd->sess = conn->sess; 399e48354ceSNicholas Bellinger 4002fbb471eSAndy Grover list_del(&cmd->i_conn_node); 401e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 402e48354ceSNicholas Bellinger 403e48354ceSNicholas Bellinger iscsit_free_all_datain_reqs(cmd); 404e48354ceSNicholas Bellinger 405d14921d6SNicholas Bellinger transport_wait_for_tasks(&cmd->se_cmd); 406e48354ceSNicholas Bellinger /* 407e48354ceSNicholas Bellinger * Add the struct iscsi_cmd to the connection recovery cmd list 408e48354ceSNicholas Bellinger */ 409e48354ceSNicholas Bellinger spin_lock(&cr->conn_recovery_cmd_lock); 4102fbb471eSAndy Grover list_add_tail(&cmd->i_conn_node, &cr->conn_recovery_cmd_list); 411e48354ceSNicholas Bellinger spin_unlock(&cr->conn_recovery_cmd_lock); 412e48354ceSNicholas Bellinger 413e48354ceSNicholas Bellinger spin_lock_bh(&conn->cmd_lock); 414e48354ceSNicholas Bellinger cmd->cr = cr; 415e48354ceSNicholas Bellinger cmd->conn = NULL; 416e48354ceSNicholas Bellinger } 417e48354ceSNicholas Bellinger spin_unlock_bh(&conn->cmd_lock); 418e48354ceSNicholas Bellinger /* 419e48354ceSNicholas Bellinger * Fill in the various values in the preallocated struct iscsi_conn_recovery. 420e48354ceSNicholas Bellinger */ 421e48354ceSNicholas Bellinger cr->cid = conn->cid; 422e48354ceSNicholas Bellinger cr->cmd_count = cmd_count; 423e48354ceSNicholas Bellinger cr->maxrecvdatasegmentlength = conn->conn_ops->MaxRecvDataSegmentLength; 4241c417f39SNicholas Bellinger cr->maxxmitdatasegmentlength = conn->conn_ops->MaxXmitDataSegmentLength; 425e48354ceSNicholas Bellinger cr->sess = conn->sess; 426e48354ceSNicholas Bellinger 427e48354ceSNicholas Bellinger iscsit_attach_inactive_connection_recovery_entry(conn->sess, cr); 428e48354ceSNicholas Bellinger 429e48354ceSNicholas Bellinger return 0; 430e48354ceSNicholas Bellinger } 431e48354ceSNicholas Bellinger 432e48354ceSNicholas Bellinger int iscsit_connection_recovery_transport_reset(struct iscsi_conn *conn) 433e48354ceSNicholas Bellinger { 434e48354ceSNicholas Bellinger atomic_set(&conn->connection_recovery, 1); 435e48354ceSNicholas Bellinger 436e48354ceSNicholas Bellinger if (iscsit_close_connection(conn) < 0) 437e48354ceSNicholas Bellinger return -1; 438e48354ceSNicholas Bellinger 439e48354ceSNicholas Bellinger return 0; 440e48354ceSNicholas Bellinger } 441