From baa4b4ee290e3a2fb052f3c7f06bf0205b8d6242 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 23 Jul 2010 07:38:15 +0000 Subject: [PATCH] Fixed a bug that caused trouble while handling send completions for failed data transfer commands. An example of the call stack that could be logged: WARNING: at srpt/src/ib_srpt.c:2908 srpt_unmap_sg_to_ib_sge+0xcb/0x13e [ib_srpt]() [ ... ] Call Trace: [] ? srpt_unmap_sg_to_ib_sge+0xcb/0x13e [ib_srpt] [] ? warn_slowpath_common+0x77/0x8e [] ? srpt_unmap_sg_to_ib_sge+0xcb/0x13e [ib_srpt] [] ? srpt_handle_send_comp+0x57/0x7d [ib_srpt] [] ? srpt_send_completion+0x82/0xca [ib_srpt] [] ? mlx4_cq_completion+0x21/0x62 [mlx4_core] [] ? mlx4_eq_int+0x55/0x2a4 [mlx4_core] [] ? mlx4_msi_x_interrupt+0xf/0x17 [mlx4_core] [] ? tasklet_action+0x64/0xb5 [] ? handle_IRQ_event+0x53/0x105 [] ? handle_edge_irq+0xda/0x11a [] ? handle_irq+0x81/0x8a [] ? do_IRQ+0x57/0xbf [] ? ret_from_intr+0x0/0xa [] ? mwait_idle+0xa3/0xd1 [] ? notifier_call_chain+0x29/0x4c [] ? cpu_idle+0x40/0x5e ---[ end trace fef4d0c17ebda700 ]--- ------------[ cut here ]------------ kernel BUG at /usr/src/redhat/BUILD/kernel-2.6.30.10/arch/x86/include/asm/dma-mapping.h:104! invalid opcode: 0000 [#1] SMP [ ... ] git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1866 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 19 ++++++++++++++++--- srpt/src/ib_srpt.h | 8 ++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index d3372f808..a11906e0c 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -2729,6 +2729,12 @@ static int srpt_map_sg_to_ib_sge(struct srpt_rdma_ch *ch, scat = scst_cmd_get_sg(scmnd); WARN_ON(!scat); dir = scst_cmd_get_data_direction(scmnd); + BUG_ON(dir == SCST_DATA_NONE); + /* + * Cache 'dir' because it is needed in srpt_unmap_sg_to_ib_sge() + * and because scst_set_cmd_error_status() resets scmnd->data_direction. + */ + ioctx->dir = dir; count = ib_dma_map_sg(ch->sport->sdev->device, scat, scst_cmd_get_sg_cnt(scmnd), scst_to_tgt_dma_dir(dir)); @@ -2904,8 +2910,8 @@ static void srpt_unmap_sg_to_ib_sge(struct srpt_rdma_ch *ch, WARN_ON(ioctx != scst_cmd_get_tgt_priv(scmnd)); scat = scst_cmd_get_sg(scmnd); WARN_ON(!scat); - dir = scst_cmd_get_data_direction(scmnd); - WARN_ON(dir == SCST_DATA_NONE); + dir = ioctx->dir; + BUG_ON(dir == SCST_DATA_NONE); ib_dma_unmap_sg(ch->sport->sdev->device, scat, scst_cmd_get_sg_cnt(scmnd), scst_to_tgt_dma_dir(dir)); @@ -3113,7 +3119,7 @@ static int srpt_xmit_response(struct scst_cmd *scmnd) enum srpt_command_state new_state; s32 req_lim_delta; int ret; - int dir; + scst_data_direction dir; int resp_len; ioctx = scst_cmd_get_tgt_priv(scmnd); @@ -3931,3 +3937,10 @@ static void __exit srpt_cleanup_module(void) module_init(srpt_init_module); module_exit(srpt_cleanup_module); + +/* + * Local variables: + * c-basic-offset: 8 + * indent-tabs-mode: t + * End: + */ diff --git a/srpt/src/ib_srpt.h b/srpt/src/ib_srpt.h index c0d39dadf..76ffe1467 100644 --- a/srpt/src/ib_srpt.h +++ b/srpt/src/ib_srpt.h @@ -187,6 +187,7 @@ struct srpt_ioctx { struct list_head comp_list; struct srpt_rdma_ch *ch; struct scst_cmd *scmnd; + scst_data_direction dir; atomic_t state; }; @@ -318,3 +319,10 @@ struct srpt_device { }; #endif /* IB_SRPT_H */ + +/* + * Local variables: + * c-basic-offset: 8 + * indent-tabs-mode: t + * End: + */