From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/infiniband/ulp/isert/ib_isert.c

Change-Id: Ia3ecdd9622e54e8a4166b6a4fb82e5be67e83f9c
---
 drivers/infiniband/ulp/isert/ib_isert.c | 123 +++++++++++++++++++++++-
 1 file changed, 120 insertions(+), 3 deletions(-)

--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1077,8 +1077,14 @@ isert_handle_scsi_cmd(struct isert_conn
 	unsol_data = cmd->unsolicited_data;
 	data_len = cmd->se_cmd.data_length;
 
+#ifdef HAVE_SE_CMD_TRANSPORT_COMPLETE_CALLBACK_HAS_THREE_PARAM
 	if (imm_data && imm_data_len == data_len)
 		cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+#else
+	if (imm_data && imm_data_len == data_len &&
+            !(cmd->se_cmd.se_cmd_flags & SCF_COMPARE_AND_WRITE))
+		cmd->se_cmd.se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+#endif
 	rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
 	if (rc < 0) {
 		return 0;
@@ -1090,7 +1096,12 @@ isert_handle_scsi_cmd(struct isert_conn
 	if (!imm_data)
 		return 0;
 
+#ifdef HAVE_SE_CMD_TRANSPORT_COMPLETE_CALLBACK_HAS_THREE_PARAM
 	if (imm_data_len != data_len) {
+#else
+	if (imm_data_len != data_len ||
+            (cmd->se_cmd.se_cmd_flags & SCF_COMPARE_AND_WRITE)) {
+#endif
 		sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
 		sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
 				    isert_get_data(rx_desc), imm_data_len);
@@ -1119,9 +1130,17 @@ sequence_cmd:
 	rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
 
 	if (!rc && !dump_payload && unsol_data)
+#ifdef HAVE_ISCSIT_SET_UNSOLICITED_DATAOUT
 		iscsit_set_unsolicited_dataout(cmd);
+#else
+		iscsit_set_unsoliticed_dataout(cmd);
+#endif
 	else if (dump_payload && imm_data)
+#ifdef HAVE_TARGET_PUT_SESS_CMD_HAS_1_PARAM
 		target_put_sess_cmd(&cmd->se_cmd);
+#else
+		target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
+#endif
 
 	return 0;
 }
@@ -1468,8 +1487,11 @@ isert_put_cmd(struct isert_cmd *isert_cm
 			if (comp_err &&
 			    cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING) {
 				struct se_cmd *se_cmd = &cmd->se_cmd;
-
+#ifdef HAVE_TARGET_PUT_SESS_CMD_HAS_1_PARAM
 				target_put_sess_cmd(se_cmd);
+#else
+				target_put_sess_cmd(se_cmd->se_sess, se_cmd);
+#endif
 			}
 		}
 
@@ -1570,12 +1592,20 @@ isert_check_pi_status(struct se_cmd *se_
 		}
 		sec_offset_err = mr_status.sig_err.sig_err_offset;
 		do_div(sec_offset_err, block_size);
+#ifdef HAVE_SE_CMD_HAS_SENSE_INFO
 		se_cmd->sense_info = sec_offset_err + se_cmd->t_task_lba;
+#else
+		se_cmd->bad_sector = sec_offset_err + se_cmd->t_task_lba;
+#endif
 
 		isert_err("PI error found type %d at sector 0x%llx "
 			  "expected 0x%x vs actual 0x%x\n",
 			  mr_status.sig_err.err_type,
+#ifdef HAVE_SE_CMD_HAS_SENSE_INFO
 			  (unsigned long long)se_cmd->sense_info,
+#else
+			  (unsigned long long)se_cmd->bad_sector,
+#endif
 			  mr_status.sig_err.expected,
 			  mr_status.sig_err.actual);
 		ret = 1;
@@ -1862,16 +1892,27 @@ isert_get_sup_prot_ops(struct iscsi_conn
 {
 	struct isert_conn *isert_conn = conn->context;
 	struct isert_device *device = isert_conn->device;
-
+/*
+ * In older versions of the kernel conn->tpg->tpg_attrib.t10_pi is not
+ * initialized before calling this function. And there is no option to
+ * test it in rdma.m4 because the behavior is hide in the iscsi_target_mod
+ * module. See the commit 23a548ee656c ("iscsi,iser-target: Expose
+ * supported protection ops according to t10_pi") in the upstream kernel.
+ */
+#if defined(CONFIG_COMPAT_RHEL_7_2) \
+    || (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
 	if (conn->tpg->tpg_attrib.t10_pi) {
+#endif
 		if (device->pi_capable) {
 			isert_info("conn %p PI offload enabled\n", isert_conn);
 			isert_conn->pi_support = true;
 			isert_conn->sig_pipeline = device->sig_pipeline;
 			return TARGET_PROT_ALL;
 		}
+#if defined(CONFIG_COMPAT_RHEL_7_2) \
+    || (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
 	}
-
+#endif
 	isert_info("conn %p PI offload disabled\n", isert_conn);
 	isert_conn->pi_support = false;
 	isert_conn->sig_pipeline = false;
@@ -2425,11 +2466,47 @@ isert_set_conn_info(struct iscsi_np *np,
 {
 	struct rdma_cm_id *cm_id = isert_conn->cm_id;
 	struct rdma_route *cm_route = &cm_id->route;
+#ifndef HAVE_ISCSI_CONN_LOGIN_SOCKADDR
+	struct sockaddr_in *sock_in;
+	struct sockaddr_in6 *sock_in6;
+#endif
 
 	conn->login_family = np->np_sockaddr.ss_family;
 
+#ifdef HAVE_ISCSI_CONN_LOGIN_SOCKADDR
 	conn->login_sockaddr = cm_route->addr.dst_addr;
 	conn->local_sockaddr = cm_route->addr.src_addr;
+#else
+	if (np->np_sockaddr.ss_family == AF_INET6) {
+		sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.dst_addr;
+		snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
+		         &sock_in6->sin6_addr.in6_u);
+		conn->login_port = ntohs(sock_in6->sin6_port);
+
+		sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.src_addr;
+#ifdef HAVE_ISCSI_CONN_LOCAL_SOCKADDR
+		memcpy(&conn->local_sockaddr , &sock_in6, sizeof(sock_in6));
+#else
+		snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
+		         &sock_in6->sin6_addr.in6_u);
+		conn->local_port = ntohs(sock_in6->sin6_port);
+#endif /* HAVE_ISCSI_CONN_LOCAL_SOCKADDR */
+	} else {
+		sock_in = (struct sockaddr_in *)&cm_route->addr.dst_addr;
+		sprintf(conn->login_ip, "%pI4",
+		        &sock_in->sin_addr.s_addr);
+		conn->login_port = ntohs(sock_in->sin_port);
+
+		sock_in = (struct sockaddr_in *)&cm_route->addr.src_addr;
+#ifdef HAVE_ISCSI_CONN_LOCAL_SOCKADDR
+		memcpy(&conn->local_sockaddr , &sock_in, sizeof(sock_in));
+#else
+		sprintf(conn->local_ip, "%pI4",
+		        &sock_in->sin_addr.s_addr);
+		conn->local_port = ntohs(sock_in->sin_port);
+#endif /* HAVE_ISCSI_CONN_LOCAL_SOCKADDR */
+	}
+#endif /* HAVE_ISCSI_CONN_LOGIN_SOCKADDR */
 }
 
 static int
@@ -2558,7 +2635,11 @@ isert_wait4cmds(struct iscsi_conn *conn)
 	isert_info("iscsi_conn %p\n", conn);
 
 	if (conn->sess) {
+#ifdef HAVE_TARGET_STOP_SESSION
 		target_stop_session(conn->sess->se_sess);
+#else
+		target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+#endif
 		target_wait_for_sess_cmds(conn->sess->se_sess);
 	}
 }
@@ -2598,6 +2679,7 @@ isert_put_unsol_pending_cmds(struct iscs
 	}
 }
 
+#ifdef CONFIG_COMPAT_ISCSIT_WAIT_CONN
 static void isert_wait_conn(struct iscsi_conn *conn)
 {
 	struct isert_conn *isert_conn = conn->context;
@@ -2615,15 +2697,40 @@ static void isert_wait_conn(struct iscsi
 
 	queue_work(isert_release_wq, &isert_conn->release_work);
 }
+#endif
 
 static void isert_free_conn(struct iscsi_conn *conn)
 {
 	struct isert_conn *isert_conn = conn->context;
 
+#ifndef CONFIG_COMPAT_ISCSIT_WAIT_CONN
+	mutex_lock(&isert_conn->mutex);
+	if (isert_conn->state == ISER_CONN_INIT) {
+		mutex_unlock(&isert_conn->mutex);
+		goto out;
+	}
+	isert_conn_terminate(isert_conn);
+	mutex_unlock(&isert_conn->mutex);
+
+	/*
+	 * Only drain qp if the isert_conn made it
+	 * into full feature phase..
+	 */
+	if (isert_conn->state == ISER_CONN_FULL_FEATURE) {
+		ib_drain_qp(isert_conn->qp);
+		isert_put_unsol_pending_cmds(conn);
+		isert_wait4cmds(conn);
+		isert_wait4logout(isert_conn);
+	}
+	queue_work(isert_release_wq, &isert_conn->release_work);
+out:
+#else
 	ib_drain_qp(isert_conn->qp);
+#endif
 	isert_put_conn(isert_conn);
 }
 
+#ifdef HAVE_ISCSIT_TRANSPORT_ISCSIT_GET_RX_PDU
 static void isert_get_rx_pdu(struct iscsi_conn *conn)
 {
 	struct completion comp;
@@ -2632,17 +2739,22 @@ static void isert_get_rx_pdu(struct iscs
 
 	wait_for_completion_interruptible(&comp);
 }
+#endif
 
 static struct iscsit_transport iser_target_transport = {
 	.name			= "IB/iSER",
 	.transport_type		= ISCSI_INFINIBAND,
+#ifdef HAVE_ISCSIT_TRANSPORT_RDMA_SHUTDOWN
 	.rdma_shutdown		= true,
+#endif
 	.priv_size		= sizeof(struct isert_cmd),
 	.owner			= THIS_MODULE,
 	.iscsit_setup_np	= isert_setup_np,
 	.iscsit_accept_np	= isert_accept_np,
 	.iscsit_free_np		= isert_free_np,
+#ifdef CONFIG_COMPAT_ISCSIT_WAIT_CONN
 	.iscsit_wait_conn	= isert_wait_conn,
+#endif
 	.iscsit_free_conn	= isert_free_conn,
 	.iscsit_get_login_rx	= isert_get_login_rx,
 	.iscsit_put_login_tx	= isert_put_login_tx,
@@ -2652,7 +2764,9 @@ static struct iscsit_transport iser_targ
 	.iscsit_queue_data_in	= isert_put_datain,
 	.iscsit_queue_status	= isert_put_response,
 	.iscsit_aborted_task	= isert_aborted_task,
+#ifdef HAVE_ISCSIT_TRANSPORT_ISCSIT_GET_RX_PDU
 	.iscsit_get_rx_pdu	= isert_get_rx_pdu,
+#endif
 	.iscsit_get_sup_prot_ops = isert_get_sup_prot_ops,
 };
 
@@ -2698,6 +2812,9 @@ static void __exit isert_exit(void)
 MODULE_DESCRIPTION("iSER-Target for mainline target infrastructure");
 MODULE_AUTHOR("nab@Linux-iSCSI.org");
 MODULE_LICENSE("GPL");
+#ifdef RETPOLINE_MLNX
+MODULE_INFO(retpoline, "Y");
+#endif
 
 module_init(isert_init);
 module_exit(isert_exit);
