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

[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
...@@ -1254,6 +1254,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -1254,6 +1254,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
struct beiscsi_endpoint *beiscsi_ep; struct beiscsi_endpoint *beiscsi_ep;
struct beiscsi_hba *phba; struct beiscsi_hba *phba;
unsigned int tag; unsigned int tag;
uint8_t mgmt_invalidate_flag, tcp_upload_flag;
unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
beiscsi_ep = ep->dd_data; beiscsi_ep = ep->dd_data;
...@@ -1262,26 +1263,23 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -1262,26 +1263,23 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
"BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n", "BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n",
beiscsi_ep->ep_cid); beiscsi_ep->ep_cid);
if (!beiscsi_ep->conn) { if (beiscsi_ep->conn) {
beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, beiscsi_conn = beiscsi_ep->conn;
"BS_%d : In beiscsi_ep_disconnect, no " iscsi_suspend_queue(beiscsi_conn->conn);
"beiscsi_ep\n"); mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
return; tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
} else {
mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
} }
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);
tag = mgmt_invalidate_connection(phba, beiscsi_ep, tag = mgmt_invalidate_connection(phba, beiscsi_ep,
beiscsi_ep->ep_cid, 1, beiscsi_ep->ep_cid,
savecfg_flag); mgmt_invalidate_flag,
savecfg_flag);
if (!tag) { if (!tag) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : mgmt_invalidate_connection" "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
" Failed for cid=%d\n",
beiscsi_ep->ep_cid); beiscsi_ep->ep_cid);
} else { } else {
wait_event_interruptible(phba->ctrl.mcc_wait[tag], wait_event_interruptible(phba->ctrl.mcc_wait[tag],
...@@ -1289,7 +1287,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) ...@@ -1289,7 +1287,7 @@ void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
free_mcc_tag(&phba->ctrl, tag); 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_free_ep(beiscsi_ep);
beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "be_main.h" #include "be_main.h"
#include "be_iscsi.h" #include "be_iscsi.h"
#include "be_mgmt.h" #include "be_mgmt.h"
#include "be_cmds.h"
static unsigned int be_iopoll_budget = 10; static unsigned int be_iopoll_budget = 10;
static unsigned int be_max_phys_size = 64; static unsigned int be_max_phys_size = 64;
...@@ -1920,6 +1921,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -1920,6 +1921,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
struct dmsg_cqe *dmsg; struct dmsg_cqe *dmsg;
unsigned int num_processed = 0; unsigned int num_processed = 0;
unsigned int tot_nump = 0; unsigned int tot_nump = 0;
unsigned short code = 0, cid = 0;
struct beiscsi_conn *beiscsi_conn; struct beiscsi_conn *beiscsi_conn;
struct beiscsi_endpoint *beiscsi_ep; struct beiscsi_endpoint *beiscsi_ep;
struct iscsi_endpoint *ep; struct iscsi_endpoint *ep;
...@@ -1933,10 +1935,11 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -1933,10 +1935,11 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
CQE_VALID_MASK) { CQE_VALID_MASK) {
be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); be_dws_le_to_cpu(sol, sizeof(struct sol_cqe));
ep = phba->ep_array[(u32) ((sol-> cid = ((sol->dw[offsetof(struct amap_sol_cqe, cid)/32] &
dw[offsetof(struct amap_sol_cqe, cid) / 32] & CQE_CID_MASK) >> 6);
SOL_CID_MASK) >> 6) - code = (sol->dw[offsetof(struct amap_sol_cqe, code)/32] &
phba->fw_config.iscsi_cid_start]; CQE_CODE_MASK);
ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start];
beiscsi_ep = ep->dd_data; beiscsi_ep = ep->dd_data;
beiscsi_conn = beiscsi_ep->conn; beiscsi_conn = beiscsi_ep->conn;
...@@ -1948,8 +1951,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -1948,8 +1951,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
num_processed = 0; num_processed = 0;
} }
switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) / switch (code) {
32] & CQE_CODE_MASK) {
case SOL_CMD_COMPLETE: case SOL_CMD_COMPLETE:
hwi_complete_cmd(beiscsi_conn, phba, sol); hwi_complete_cmd(beiscsi_conn, phba, sol);
break; break;
...@@ -1996,11 +1998,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -1996,11 +1998,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO,
"BM_%d : CQ Error notification for cmd.. " "BM_%d : CQ Error notification for cmd.. "
"code %d cid 0x%x\n", "code %d cid 0x%x\n", code, cid);
sol->dw[offsetof(struct amap_sol_cqe,
code) / 32] & CQE_CODE_MASK,
sol->dw[offsetof(struct amap_sol_cqe,
cid) / 32] & SOL_CID_MASK);
break; break;
case UNSOL_DATA_DIGEST_ERROR_NOTIFY: case UNSOL_DATA_DIGEST_ERROR_NOTIFY:
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
...@@ -2027,12 +2025,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -2027,12 +2025,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
"BM_%d : CQ Error %d, reset CID 0x%x...\n", "BM_%d : CQ Error %d, reset CID 0x%x...\n",
sol->dw[offsetof(struct amap_sol_cqe, code, cid);
code) / 32] & CQE_CODE_MASK, if (beiscsi_conn)
sol->dw[offsetof(struct amap_sol_cqe, iscsi_conn_failure(beiscsi_conn->conn,
cid) / 32] & CQE_CID_MASK); ISCSI_ERR_CONN_FAILED);
iscsi_conn_failure(beiscsi_conn->conn,
ISCSI_ERR_CONN_FAILED);
break; break;
case CXN_KILLED_RST_SENT: case CXN_KILLED_RST_SENT:
case CXN_KILLED_RST_RCVD: case CXN_KILLED_RST_RCVD:
...@@ -2040,22 +2036,17 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) ...@@ -2040,22 +2036,17 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
"BM_%d : CQ Error %d, reset" "BM_%d : CQ Error %d, reset"
"received/sent on CID 0x%x...\n", "received/sent on CID 0x%x...\n",
sol->dw[offsetof(struct amap_sol_cqe, code, cid);
code) / 32] & CQE_CODE_MASK, if (beiscsi_conn)
sol->dw[offsetof(struct amap_sol_cqe, iscsi_conn_failure(beiscsi_conn->conn,
cid) / 32] & CQE_CID_MASK); ISCSI_ERR_CONN_FAILED);
iscsi_conn_failure(beiscsi_conn->conn,
ISCSI_ERR_CONN_FAILED);
break; break;
default: default:
beiscsi_log(phba, KERN_ERR, beiscsi_log(phba, KERN_ERR,
BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG,
"BM_%d : CQ Error Invalid code= %d " "BM_%d : CQ Error Invalid code= %d "
"received on CID 0x%x...\n", "received on CID 0x%x...\n",
sol->dw[offsetof(struct amap_sol_cqe, code, cid);
code) / 32] & CQE_CODE_MASK,
sol->dw[offsetof(struct amap_sol_cqe,
cid) / 32] & CQE_CID_MASK);
break; break;
} }
......
...@@ -108,6 +108,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl, ...@@ -108,6 +108,7 @@ unsigned int mgmt_vendor_specific_fw_cmd(struct be_ctrl_info *ctrl,
struct bsg_job *job, struct bsg_job *job,
struct be_dma_mem *nonemb_cmd); struct be_dma_mem *nonemb_cmd);
#define BEISCSI_NO_RST_ISSUE 0
struct iscsi_invalidate_connection_params_in { struct iscsi_invalidate_connection_params_in {
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
unsigned int session_handle; unsigned int session_handle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment