Skip to content

Commit 7733111

Browse files
javed-hmartinkpetersen
authored andcommitted
scsi: bnx2fc: Process the RQE with CQE in interrupt context
Filesystem goes to read-only after continuous error injection because RQE was handled in deferred context, leading to mismatch between CQE and RQE. Specifically, this patch makes the following changes: - Process the RQE with CQE in interrupt context, before putting it into the work queue. - Producer and consumer indices are also updated in the interrupt context to guarantee the the order of processing. [mkp: fixed bad indentation] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Javed Hasan <[email protected]> Signed-off-by: Saurav Kashyap <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent b92fcfc commit 7733111

File tree

4 files changed

+96
-54
lines changed

4 files changed

+96
-54
lines changed

drivers/scsi/bnx2fc/bnx2fc.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,10 @@ struct io_bdt {
482482
struct bnx2fc_work {
483483
struct list_head list;
484484
struct bnx2fc_rport *tgt;
485+
struct fcoe_task_ctx_entry *task;
486+
unsigned char rq_data[BNX2FC_RQ_BUF_SZ];
485487
u16 wqe;
488+
u8 num_rq;
486489
};
487490
struct bnx2fc_unsol_els {
488491
struct fc_lport *lport;
@@ -550,7 +553,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
550553
enum fc_rport_event event);
551554
void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
552555
struct fcoe_task_ctx_entry *task,
553-
u8 num_rq);
556+
u8 num_rq, unsigned char *rq_data);
554557
void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
555558
struct fcoe_task_ctx_entry *task,
556559
u8 num_rq);
@@ -559,7 +562,7 @@ void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
559562
u8 num_rq);
560563
void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
561564
struct fcoe_task_ctx_entry *task,
562-
u8 num_rq);
565+
u8 num_rq, unsigned char *rq_data);
563566
void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
564567
struct fcoe_task_ctx_entry *task,
565568
u8 num_rq);
@@ -577,7 +580,9 @@ struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
577580
void *arg, u32 timeout);
578581
void bnx2fc_arm_cq(struct bnx2fc_rport *tgt);
579582
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
580-
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
583+
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe,
584+
unsigned char *rq_data, u8 num_rq,
585+
struct fcoe_task_ctx_entry *task);
581586
struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
582587
u32 port_id);
583588
void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,

drivers/scsi/bnx2fc/bnx2fc_fcoe.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,10 @@ static int bnx2fc_percpu_io_thread(void *arg)
660660

661661
list_for_each_entry_safe(work, tmp, &work_list, list) {
662662
list_del_init(&work->list);
663-
bnx2fc_process_cq_compl(work->tgt, work->wqe);
663+
bnx2fc_process_cq_compl(work->tgt, work->wqe,
664+
work->rq_data,
665+
work->num_rq,
666+
work->task);
664667
kfree(work);
665668
}
666669

@@ -2655,7 +2658,8 @@ static int bnx2fc_cpu_offline(unsigned int cpu)
26552658
/* Free all work in the list */
26562659
list_for_each_entry_safe(work, tmp, &p->work_list, list) {
26572660
list_del_init(&work->list);
2658-
bnx2fc_process_cq_compl(work->tgt, work->wqe);
2661+
bnx2fc_process_cq_compl(work->tgt, work->wqe, work->rq_data,
2662+
work->num_rq, work->task);
26592663
kfree(work);
26602664
}
26612665

drivers/scsi/bnx2fc/bnx2fc_hwi.c

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -863,36 +863,22 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
863863
}
864864
}
865865

866-
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
866+
void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe,
867+
unsigned char *rq_data, u8 num_rq,
868+
struct fcoe_task_ctx_entry *task)
867869
{
868-
struct fcoe_task_ctx_entry *task;
869-
struct fcoe_task_ctx_entry *task_page;
870870
struct fcoe_port *port = tgt->port;
871871
struct bnx2fc_interface *interface = port->priv;
872872
struct bnx2fc_hba *hba = interface->hba;
873873
struct bnx2fc_cmd *io_req;
874-
int task_idx, index;
874+
875875
u16 xid;
876876
u8 cmd_type;
877877
u8 rx_state = 0;
878-
u8 num_rq;
879878

880879
spin_lock_bh(&tgt->tgt_lock);
881-
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
882-
if (xid >= hba->max_tasks) {
883-
printk(KERN_ERR PFX "ERROR:xid out of range\n");
884-
spin_unlock_bh(&tgt->tgt_lock);
885-
return;
886-
}
887-
task_idx = xid / BNX2FC_TASKS_PER_PAGE;
888-
index = xid % BNX2FC_TASKS_PER_PAGE;
889-
task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
890-
task = &(task_page[index]);
891-
892-
num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
893-
FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
894-
FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
895880

881+
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
896882
io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
897883

898884
if (io_req == NULL) {
@@ -912,7 +898,8 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
912898
switch (cmd_type) {
913899
case BNX2FC_SCSI_CMD:
914900
if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
915-
bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
901+
bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq,
902+
rq_data);
916903
spin_unlock_bh(&tgt->tgt_lock);
917904
return;
918905
}
@@ -929,7 +916,7 @@ void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
929916

930917
case BNX2FC_TASK_MGMT_CMD:
931918
BNX2FC_IO_DBG(io_req, "Processing TM complete\n");
932-
bnx2fc_process_tm_compl(io_req, task, num_rq);
919+
bnx2fc_process_tm_compl(io_req, task, num_rq, rq_data);
933920
break;
934921

935922
case BNX2FC_ABTS:
@@ -987,7 +974,9 @@ void bnx2fc_arm_cq(struct bnx2fc_rport *tgt)
987974

988975
}
989976

990-
static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
977+
static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe,
978+
unsigned char *rq_data, u8 num_rq,
979+
struct fcoe_task_ctx_entry *task)
991980
{
992981
struct bnx2fc_work *work;
993982
work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC);
@@ -997,29 +986,87 @@ static struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
997986
INIT_LIST_HEAD(&work->list);
998987
work->tgt = tgt;
999988
work->wqe = wqe;
989+
work->num_rq = num_rq;
990+
work->task = task;
991+
if (rq_data)
992+
memcpy(work->rq_data, rq_data, BNX2FC_RQ_BUF_SZ);
993+
1000994
return work;
1001995
}
1002996

1003997
/* Pending work request completion */
1004-
static void bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe)
998+
static bool bnx2fc_pending_work(struct bnx2fc_rport *tgt, unsigned int wqe)
1005999
{
10061000
unsigned int cpu = wqe % num_possible_cpus();
10071001
struct bnx2fc_percpu_s *fps;
10081002
struct bnx2fc_work *work;
1003+
struct fcoe_task_ctx_entry *task;
1004+
struct fcoe_task_ctx_entry *task_page;
1005+
struct fcoe_port *port = tgt->port;
1006+
struct bnx2fc_interface *interface = port->priv;
1007+
struct bnx2fc_hba *hba = interface->hba;
1008+
unsigned char *rq_data = NULL;
1009+
unsigned char rq_data_buff[BNX2FC_RQ_BUF_SZ];
1010+
int task_idx, index;
1011+
unsigned char *dummy;
1012+
u16 xid;
1013+
u8 num_rq;
1014+
int i;
1015+
1016+
xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
1017+
if (xid >= hba->max_tasks) {
1018+
pr_err(PFX "ERROR:xid out of range\n");
1019+
return 0;
1020+
}
1021+
1022+
task_idx = xid / BNX2FC_TASKS_PER_PAGE;
1023+
index = xid % BNX2FC_TASKS_PER_PAGE;
1024+
task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
1025+
task = &task_page[index];
1026+
1027+
num_rq = ((task->rxwr_txrd.var_ctx.rx_flags &
1028+
FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE) >>
1029+
FCOE_TCE_RX_WR_TX_RD_VAR_NUM_RQ_WQE_SHIFT);
1030+
1031+
memset(rq_data_buff, 0, BNX2FC_RQ_BUF_SZ);
1032+
1033+
if (!num_rq)
1034+
goto num_rq_zero;
1035+
1036+
rq_data = bnx2fc_get_next_rqe(tgt, 1);
1037+
1038+
if (num_rq > 1) {
1039+
/* We do not need extra sense data */
1040+
for (i = 1; i < num_rq; i++)
1041+
dummy = bnx2fc_get_next_rqe(tgt, 1);
1042+
}
1043+
1044+
if (rq_data)
1045+
memcpy(rq_data_buff, rq_data, BNX2FC_RQ_BUF_SZ);
1046+
1047+
/* return RQ entries */
1048+
for (i = 0; i < num_rq; i++)
1049+
bnx2fc_return_rqe(tgt, 1);
1050+
1051+
num_rq_zero:
10091052

10101053
fps = &per_cpu(bnx2fc_percpu, cpu);
10111054
spin_lock_bh(&fps->fp_work_lock);
10121055
if (fps->iothread) {
1013-
work = bnx2fc_alloc_work(tgt, wqe);
1056+
work = bnx2fc_alloc_work(tgt, wqe, rq_data_buff,
1057+
num_rq, task);
10141058
if (work) {
10151059
list_add_tail(&work->list, &fps->work_list);
10161060
wake_up_process(fps->iothread);
10171061
spin_unlock_bh(&fps->fp_work_lock);
1018-
return;
1062+
return 1;
10191063
}
10201064
}
10211065
spin_unlock_bh(&fps->fp_work_lock);
1022-
bnx2fc_process_cq_compl(tgt, wqe);
1066+
bnx2fc_process_cq_compl(tgt, wqe,
1067+
rq_data_buff, num_rq, task);
1068+
1069+
return 1;
10231070
}
10241071

10251072
int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
@@ -1056,8 +1103,8 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
10561103
/* Unsolicited event notification */
10571104
bnx2fc_process_unsol_compl(tgt, wqe);
10581105
} else {
1059-
bnx2fc_pending_work(tgt, wqe);
1060-
num_free_sqes++;
1106+
if (bnx2fc_pending_work(tgt, wqe))
1107+
num_free_sqes++;
10611108
}
10621109
cqe++;
10631110
tgt->cq_cons_idx++;

drivers/scsi/bnx2fc/bnx2fc_io.c

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
2424
static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
2525
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
2626
struct fcoe_fcp_rsp_payload *fcp_rsp,
27-
u8 num_rq);
27+
u8 num_rq, unsigned char *rq_data);
2828

2929
void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
3030
unsigned int timer_msec)
@@ -1518,7 +1518,8 @@ static void bnx2fc_tgt_reset_cmpl(struct bnx2fc_cmd *io_req)
15181518
}
15191519

15201520
void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
1521-
struct fcoe_task_ctx_entry *task, u8 num_rq)
1521+
struct fcoe_task_ctx_entry *task, u8 num_rq,
1522+
unsigned char *rq_data)
15221523
{
15231524
struct bnx2fc_mp_req *tm_req;
15241525
struct fc_frame_header *fc_hdr;
@@ -1557,7 +1558,7 @@ void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
15571558
if (fc_hdr->fh_r_ctl == FC_RCTL_DD_CMD_STATUS) {
15581559
bnx2fc_parse_fcp_rsp(io_req,
15591560
(struct fcoe_fcp_rsp_payload *)
1560-
rsp_buf, num_rq);
1561+
rsp_buf, num_rq, rq_data);
15611562
if (io_req->fcp_rsp_code == 0) {
15621563
/* TM successful */
15631564
if (tm_req->tm_flags & FCP_TMF_LUN_RESET)
@@ -1755,15 +1756,11 @@ void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
17551756

17561757
static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
17571758
struct fcoe_fcp_rsp_payload *fcp_rsp,
1758-
u8 num_rq)
1759+
u8 num_rq, unsigned char *rq_data)
17591760
{
17601761
struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
1761-
struct bnx2fc_rport *tgt = io_req->tgt;
17621762
u8 rsp_flags = fcp_rsp->fcp_flags.flags;
17631763
u32 rq_buff_len = 0;
1764-
int i;
1765-
unsigned char *rq_data;
1766-
unsigned char *dummy;
17671764
int fcp_sns_len = 0;
17681765
int fcp_rsp_len = 0;
17691766

@@ -1809,14 +1806,6 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
18091806
rq_buff_len = num_rq * BNX2FC_RQ_BUF_SZ;
18101807
}
18111808

1812-
rq_data = bnx2fc_get_next_rqe(tgt, 1);
1813-
1814-
if (num_rq > 1) {
1815-
/* We do not need extra sense data */
1816-
for (i = 1; i < num_rq; i++)
1817-
dummy = bnx2fc_get_next_rqe(tgt, 1);
1818-
}
1819-
18201809
/* fetch fcp_rsp_code */
18211810
if ((fcp_rsp_len == 4) || (fcp_rsp_len == 8)) {
18221811
/* Only for task management function */
@@ -1837,9 +1826,6 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
18371826
if (fcp_sns_len)
18381827
memcpy(sc_cmd->sense_buffer, rq_data, fcp_sns_len);
18391828

1840-
/* return RQ entries */
1841-
for (i = 0; i < num_rq; i++)
1842-
bnx2fc_return_rqe(tgt, 1);
18431829
}
18441830
}
18451831

@@ -1918,7 +1904,7 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
19181904

19191905
void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
19201906
struct fcoe_task_ctx_entry *task,
1921-
u8 num_rq)
1907+
u8 num_rq, unsigned char *rq_data)
19221908
{
19231909
struct fcoe_fcp_rsp_payload *fcp_rsp;
19241910
struct bnx2fc_rport *tgt = io_req->tgt;
@@ -1950,7 +1936,7 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
19501936
&(task->rxwr_only.union_ctx.comp_info.fcp_rsp.payload);
19511937

19521938
/* parse fcp_rsp and obtain sense data from RQ if available */
1953-
bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
1939+
bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq, rq_data);
19541940

19551941
if (!sc_cmd->SCp.ptr) {
19561942
printk(KERN_ERR PFX "SCp.ptr is NULL\n");

0 commit comments

Comments
 (0)