Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a513dd8 authored by John Soni Jose's avatar John Soni Jose Committed by James Bottomley
Browse files

[SCSI] be2iscsi: Fix a kernel panic because of TCP RST/FIN received.



A TCP RST/FIN can be received even before the connection specific
structures are initialized.This fix checks for the conn structure
is intialized or not  when RST/FIN is received.

Signed-off-by: default avatarJohn Soni Jose <sony.john-n@emulex.com>
Signed-off-by: default avatarJayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 6f72238e
Loading
Loading
Loading
Loading
+14 −16
Original line number Diff line number Diff line
@@ -1254,6 +1254,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
	struct beiscsi_endpoint *beiscsi_ep;
	struct beiscsi_hba *phba;
	unsigned int tag;
	uint8_t mgmt_invalidate_flag, tcp_upload_flag;
	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;

	beiscsi_ep = ep->dd_data;
@@ -1262,26 +1263,23 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
		    "BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n",
		    beiscsi_ep->ep_cid);

	if (!beiscsi_ep->conn) {
		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
			    "BS_%d : In beiscsi_ep_disconnect, no "
			    "beiscsi_ep\n");
		return;
	}
	if (beiscsi_ep->conn) {
		beiscsi_conn = beiscsi_ep->conn;
		iscsi_suspend_queue(beiscsi_conn->conn);

	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
		    "BS_%d : In beiscsi_ep_disconnect ep_cid = %d\n",
		    beiscsi_ep->ep_cid);
		mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
		tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
	} else {
		mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
		tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
	}

	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
					    beiscsi_ep->ep_cid, 1,
					  beiscsi_ep->ep_cid,
					  mgmt_invalidate_flag,
					  savecfg_flag);
	if (!tag) {
		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
			    "BS_%d : mgmt_invalidate_connection"
			    " Failed for cid=%d\n",
			    "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
			    beiscsi_ep->ep_cid);
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
@@ -1289,7 +1287,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
		free_mcc_tag(&phba->ctrl, tag);
	}

	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
	beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
	beiscsi_free_ep(beiscsi_ep);
	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
+18 −27
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "be_main.h"
#include "be_iscsi.h"
#include "be_mgmt.h"
#include "be_cmds.h"

static unsigned int be_iopoll_budget = 10;
static unsigned int be_max_phys_size = 64;
@@ -1920,6 +1921,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
	struct dmsg_cqe *dmsg;
	unsigned int num_processed = 0;
	unsigned int tot_nump = 0;
	unsigned short code = 0, cid = 0;
	struct beiscsi_conn *beiscsi_conn;
	struct beiscsi_endpoint *beiscsi_ep;
	struct iscsi_endpoint *ep;
@@ -1933,10 +1935,11 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
	       CQE_VALID_MASK) {
		be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));

		ep = phba->ep_array[(u32) ((sol->
				   dw[offsetof(struct amap_sol_cqe, cid) / 32] &
				   SOL_CID_MASK) >> 6) -
				   phba->fw_config.iscsi_cid_start];
		cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] &
		      CQE_CID_MASK) >> 6);
		code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] &
		       CQE_CODE_MASK);
		ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];

		beiscsi_ep = ep->dd_data;
		beiscsi_conn = beiscsi_ep->conn;
@@ -1948,8 +1951,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
			num_processed = 0;
		}

		switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) /
			32] & CQE_CODE_MASK) {
		switch (code) {
		case SOL_CMD_COMPLETE:
			hwi_complete_cmd(beiscsi_conn, phba, sol);
			break;
@@ -1996,11 +1998,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
			beiscsi_log(phba, KERN_ERR,
				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
				    "BM_%d : CQ Error notification for cmd.. "
				    "code %d cid 0x%x\n",
				    sol->dw[offsetof(struct amap_sol_cqe,
				    code) / 32] & CQE_CODE_MASK,
				    sol->dw[offsetof(struct amap_sol_cqe,
				    cid) / 32] & SOL_CID_MASK);
				    "code %d cid 0x%x\n", code, cid);
			break;
		case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
			beiscsi_log(phba, KERN_ERR,
@@ -2027,10 +2025,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
			beiscsi_log(phba, KERN_ERR,
				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
				    "BM_%d : CQ Error %d, reset CID 0x%x...\n",
				    sol->dw[offsetof(struct amap_sol_cqe,
				    code) / 32] & CQE_CODE_MASK,
				    sol->dw[offsetof(struct amap_sol_cqe,
				    cid) / 32] & CQE_CID_MASK);
				    code, cid);
			if (beiscsi_conn)
				iscsi_conn_failure(beiscsi_conn->conn,
						   ISCSI_ERR_CONN_FAILED);
			break;
@@ -2040,10 +2036,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
				    "BM_%d : CQ Error %d, reset"
				    "received/sent on CID 0x%x...\n",
				    sol->dw[offsetof(struct amap_sol_cqe,
					code) / 32] & CQE_CODE_MASK,
				    sol->dw[offsetof(struct amap_sol_cqe,
					cid) / 32] & CQE_CID_MASK);
				    code, cid);
			if (beiscsi_conn)
				iscsi_conn_failure(beiscsi_conn->conn,
						   ISCSI_ERR_CONN_FAILED);
			break;
@@ -2052,10 +2046,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
				    "BM_%d : CQ Error Invalid code= %d "
				    "received on CID 0x%x...\n",
				    sol->dw[offsetof(struct amap_sol_cqe,
				    code) / 32] & CQE_CODE_MASK,
				    sol->dw[offsetof(struct amap_sol_cqe,
				    cid) / 32] & CQE_CID_MASK);
				    code, cid);
			break;
		}

+1 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
					 struct bsg_job *job,
					 struct be_dma_mem *nonemb_cmd);

#define BEISCSI_NO_RST_ISSUE	0
struct iscsi_invalidate_connection_params_in {
	struct be_cmd_req_hdr hdr;
	unsigned int session_handle;