mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 17:12:06 +00:00
[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: John Soni Jose <sony.john-n@emulex.com> Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
parent
6f72238e77
commit
0a513dd873
@ -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);
|
||||
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;
|
||||
}
|
||||
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,
|
||||
beiscsi_ep->ep_cid, 1,
|
||||
savecfg_flag);
|
||||
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);
|
||||
|
@ -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,12 +2025,10 @@ 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);
|
||||
iscsi_conn_failure(beiscsi_conn->conn,
|
||||
ISCSI_ERR_CONN_FAILED);
|
||||
code, cid);
|
||||
if (beiscsi_conn)
|
||||
iscsi_conn_failure(beiscsi_conn->conn,
|
||||
ISCSI_ERR_CONN_FAILED);
|
||||
break;
|
||||
case CXN_KILLED_RST_SENT:
|
||||
case CXN_KILLED_RST_RCVD:
|
||||
@ -2040,22 +2036,17 @@ 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);
|
||||
iscsi_conn_failure(beiscsi_conn->conn,
|
||||
ISCSI_ERR_CONN_FAILED);
|
||||
code, cid);
|
||||
if (beiscsi_conn)
|
||||
iscsi_conn_failure(beiscsi_conn->conn,
|
||||
ISCSI_ERR_CONN_FAILED);
|
||||
break;
|
||||
default:
|
||||
beiscsi_log(phba, KERN_ERR,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user