Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 158021 Details for
Bug 245939
[QLogic 4.6 bug] [2/4] Update qla2xxx driver to version 8.01.07-d1 - ref-counting
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
patch to fix ref-counting issues in qla2xxx for 4.6
QLogic_4.6_refcount2.patch (text/plain), 41.30 KB, created by
Marcus Barrow
on 2007-06-27 14:50:34 UTC
(
hide
)
Description:
patch to fix ref-counting issues in qla2xxx for 4.6
Filename:
MIME Type:
Creator:
Marcus Barrow
Created:
2007-06-27 14:50:34 UTC
Size:
41.30 KB
patch
obsolete
>From 47b02ed0d29fe9f2fa34566d7e8571de1adaee6e Mon Sep 17 00:00:00 2001 >From: Marcus Barrow <mbarrow@marcus-barrows-computer.local> >Date: Thu, 24 May 2007 15:47:47 -0400 >Subject: [PATCH] Reference counting fixes. > > 820d14e8e07be6200a669deeb5cc0a7387907287 > Correct races in command timer logic. > > c46eaf64052973f01f62a0475f75677cc76afc17 > Properly reference count SP access. > > 5974bb75a392adb69b16f3a865e89d1f52907f79 > Additional corrections to SP reference-counting fixes. > > 4711089d3482fdd56c12df3847ad5fb4a2104a14 > Correct reference-counting during EH abort processing. > > 93a333100b5dc7b1f84aa9911bbba7b1da60fb40 > Honor SRB_NO_TIMER during ISP24XX SP execution. > > 440e6f71f925c8cf1884c9f9b935ea8a66fad6dc > Prevent premature IOCTL-timeout while issuing passthru commands. > removed in "Additional SRB reference counting fixes" > > 38ffe28b38b49f753a6ade6db562fea7729a0116 > Ignore completions from firmware which have already been IOCTL completed. > > cf214b8575418967ae4b0ddc5599788823ee44ee > Additional SRB reference counting fixes. > > 8b81d27767a100d1ec74d703bb2e76d6fd9bd9c4 > Add additional logging in command-timeout and abort paths. > > a49099ed23a41854d87189d906053e403ee2f4f8 > Correct timer handling during command failover processing. > partial: took cleanup to inline.h: > > a4b12a5427f8def2f6a374ef7ff67f94251f9188 > Correct 'already-completed' command handling in EH code paths. >--- > drivers/scsi/qla2xxx/qim_xioct.c | 45 ++++++---- > drivers/scsi/qla2xxx/qla_def.h | 1 + > drivers/scsi/qla2xxx/qla_gbl.h | 4 + > drivers/scsi/qla2xxx/qla_inline.h | 17 ++-- > drivers/scsi/qla2xxx/qla_iocb.c | 8 +- > drivers/scsi/qla2xxx/qla_isr.c | 49 +++++++++-- > drivers/scsi/qla2xxx/qla_listops.h | 1 + > drivers/scsi/qla2xxx/qla_os.c | 168 ++++++++++++++++++++-------------- > drivers/scsi/qla2xxx/qla_settings.h | 1 + > 9 files changed, 187 insertions(+), 107 deletions(-) > >diff --git a/drivers/scsi/qla2xxx/qim_xioct.c b/drivers/scsi/qla2xxx/qim_xioct.c >index 55809c8..604f046 100644 >--- a/drivers/scsi/qla2xxx/qim_xioct.c >+++ b/drivers/scsi/qla2xxx/qim_xioct.c >@@ -3662,6 +3662,17 @@ qim_send_els_passthru(struct qla_host_io > return (ret); > } > >+ if ((CMD_COMPL_STATUS(pscsi_cmd) != 0 && >+ CMD_COMPL_STATUS(pscsi_cmd) != CS_DATA_UNDERRUN && >+ CMD_COMPL_STATUS(pscsi_cmd) != CS_DATA_OVERRUN)|| >+ CMD_ENTRY_STATUS(pscsi_cmd) != 0) { >+ DEBUG9_10(printk("%s(%ld): inst=%ld cmd returned error=%x.\n", >+ __func__, ha->host_no, ha->instance, >+ CMD_COMPL_STATUS(pscsi_cmd))); >+ pext->Status = EXT_STATUS_ERR; >+ return (ret); >+ } >+ > /* check on data returned */ > ptmp_stat = (uint8_t *)ha->ioctl_mem + FC_HEADER_LEN; > >@@ -3901,9 +3912,6 @@ qim_ioctl_ms_queuecommand(struct qla_hos > > pext->Status = EXT_STATUS_MS_NO_RESPONSE; > >- atomic_set(&sp->ref_count, 0); >- add_to_free_queue (dr_ha, sp); >- > return (ret); > } > >@@ -4078,17 +4086,16 @@ qim_start_ms_cmd(struct qla_host_ioctl * > > /* set flag to indicate IOCTL MSIOCB cmd in progress */ > ha->ioctl->MSIOCB_InProgress = 1; >- ha->ioctl->ioctl_tov = pkt->timeout + 1; /* 1 second more */ > > /* prepare for receiving completion. */ > qim_ioctl_sem_init(ha); > >+ sp->flags |= SRB_NO_TIMER; >+ > /* Issue command to ISP */ >+ sp->state = SRB_ACTIVE_STATE; > qim_isp_cmd(dr_ha); > >- ha->ioctl->cmpl_timer.expires = jiffies + ha->ioctl->ioctl_tov * HZ; >- add_timer(&ha->ioctl->cmpl_timer); >- > DEBUG9(printk("%s(%ld): inst=%ld releasing hardware_lock.\n", > __func__, ha->host_no, ha->instance);) > spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); >@@ -4098,8 +4105,6 @@ qim_start_ms_cmd(struct qla_host_ioctl * > > down(&ha->ioctl->cmpl_sem); > >- del_timer(&ha->ioctl->cmpl_timer); >- > if (ha->ioctl->MSIOCB_InProgress == 1) { > DEBUG9_10(printk("%s(%ld): inst=%ld timed out. exiting.\n", > __func__, ha->host_no, ha->instance);) >@@ -5340,23 +5345,24 @@ qim_cmd_timeout(srb_t *sp) > } > > static inline void >-qim_add_timer_to_cmd(srb_t *sp, int timeout) >+qim_add_timer_to_cmd(struct scsi_qla_host *dr_ha, srb_t *sp, int timeout) > { > init_timer(&sp->timer); > sp->timer.expires = jiffies + timeout * HZ; > sp->timer.data = (unsigned long) sp; > sp->timer.function = (void (*) (unsigned long))qim_cmd_timeout; > add_timer(&sp->timer); >+ sp_get(dr_ha, sp); /* take command timeout reference */ > } > > static inline void > qim_delete_timer_from_cmd(srb_t *sp) > { >- if (sp->timer.function != NULL) { >- del_timer(&sp->timer); >- sp->timer.function = NULL; >- sp->timer.data = (unsigned long) NULL; >- } >+ if (sp->flags & SRB_NO_TIMER) >+ return; >+ >+ if (del_timer(&sp->timer)) >+ sp_put((scsi_qla_host_t *)sp->cmd->device->host->hostdata, sp); > } > > static int >@@ -5573,11 +5579,12 @@ qim_ioctl_scsi_queuecommand(struct qla_h > __func__, ha->host_no, ha->instance);) > > /* Time the command via our standard driver-timer */ >- if ((pscsi_cmd->timeout_per_command / HZ) > QLA_CMD_TIMER_DELTA) >- qim_add_timer_to_cmd(sp, >- (pscsi_cmd->timeout_per_command/HZ) - QLA_CMD_TIMER_DELTA); >+ if ((pscsi_cmd->timeout_per_command / HZ) > ql2xcmdtimermin) >+ qim_add_timer_to_cmd(dr_ha, sp, >+ (pscsi_cmd->timeout_per_command/HZ) - >+ QLA_CMD_TIMER_DELTA); > else >- qim_add_timer_to_cmd(sp, pscsi_cmd->timeout_per_command/HZ); >+ sp->flags |= SRB_NO_TIMER; > > if (qim_start_scsi(sp) != QIM_SUCCESS) { > qim_delete_timer_from_cmd(sp); >diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h >index 235b698..0e2ec5e 100644 >--- a/drivers/scsi/qla2xxx/qla_def.h >+++ b/drivers/scsi/qla2xxx/qla_def.h >@@ -296,6 +296,7 @@ typedef struct srb { > #define SRB_FO_CANCEL BIT_9 /* Command don't need to do failover */ > #define SRB_IOCTL BIT_10 /* IOCTL command. */ > #define SRB_TAPE BIT_11 /* FCP2 (Tape) command. */ >+#define SRB_NO_TIMER BIT_12 > > /* > * SRB state definitions >diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h >index cdc232b..d07c4f9 100644 >--- a/drivers/scsi/qla2xxx/qla_gbl.h >+++ b/drivers/scsi/qla2xxx/qla_gbl.h >@@ -74,6 +74,7 @@ extern int extended_error_logging; > extern int ql2xfwloadbin; > extern int ql2xfdmienable; > extern int ql2xqfullrampup; >+extern int ql2xcmdtimermin; > > extern int ConfigRequired; > >@@ -105,6 +106,9 @@ extern void qla23xx_blink_led(scsi_qla_h > extern void qla24xx_blink_led(scsi_qla_host_t *); > > extern int qla2x00_down_timeout(struct semaphore *, unsigned long); >+extern void qla2x00_callback(scsi_qla_host_t *, struct scsi_cmnd *); >+extern void sp_put(struct scsi_qla_host *, srb_t *); >+extern void sp_get(struct scsi_qla_host *, srb_t *); > > /* > * Global Function Prototypes in qla_iocb.c source file. >diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h >index d178f80..95319d8 100644 >--- a/drivers/scsi/qla2xxx/qla_inline.h >+++ b/drivers/scsi/qla2xxx/qla_inline.h >@@ -257,7 +257,7 @@ qla2x00_issue_marker(scsi_qla_host_t *ha > return (QLA_SUCCESS); > } > >-static __inline__ void qla2x00_add_timer_to_cmd(srb_t *, int); >+static __inline__ void qla2x00_add_timer_to_cmd(scsi_qla_host_t *, srb_t *, int); > static __inline__ void qla2x00_delete_timer_from_cmd(srb_t *); > > /************************************************************************** >@@ -274,13 +274,14 @@ static __inline__ void qla2x00_delete_ti > * None. > **************************************************************************/ > static inline void >-qla2x00_add_timer_to_cmd(srb_t *sp, int timeout) >+qla2x00_add_timer_to_cmd(scsi_qla_host_t *ha, srb_t *sp, int timeout) > { > init_timer(&sp->timer); > sp->timer.expires = jiffies + timeout * HZ; > sp->timer.data = (unsigned long) sp; > sp->timer.function = (void (*) (unsigned long))qla2x00_cmd_timeout; > add_timer(&sp->timer); >+ sp_get(ha, sp); /* take command timeout reference */ > } > > /************************************************************************** >@@ -293,16 +294,16 @@ qla2x00_add_timer_to_cmd(srb_t *sp, int > * sp - pointer to validate > * > * Returns: >-* None. >+* 1 if we were able to detach the time. 0 means we already blew it. > **************************************************************************/ > static inline void > qla2x00_delete_timer_from_cmd(srb_t *sp) > { >- if (sp->timer.function != NULL) { >- del_timer(&sp->timer); >- sp->timer.function = NULL; >- sp->timer.data = (unsigned long) NULL; >- } >+ if (sp->flags & SRB_NO_TIMER) >+ return; >+ >+ if (del_timer(&sp->timer)) >+ sp_put((scsi_qla_host_t *)sp->cmd->device->host->hostdata, sp); > } > > static inline uint8_t *host_to_fcp_swap(uint8_t *, uint32_t); >diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c >index c31fd71..a695025 100644 >--- a/drivers/scsi/qla2xxx/qla_iocb.c >+++ b/drivers/scsi/qla2xxx/qla_iocb.c >@@ -428,13 +428,11 @@ qla2x00_start_scsi(srb_t *sp) > * Allocate at least 5 (+ QLA_CMD_TIMER_DELTA) seconds for RISC timeout. > */ > timeout = (uint32_t)(cmd->timeout_per_command / HZ); >- if (timeout > 65535) >+ if (sp->flags & SRB_NO_TIMER || timeout > FW_MAX_TIMEOUT) > cmd_pkt->timeout = __constant_cpu_to_le16(0); >- else if (timeout > 25) >+ else > cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout - > (5 + QLA_CMD_TIMER_DELTA)); >- else >- cmd_pkt->timeout = cpu_to_le16((uint16_t)timeout); > > /* Load SCSI command packet. */ > memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len); >@@ -880,7 +878,7 @@ qla24xx_start_scsi(srb_t *sp) > > /* Update timeout. */ > timeout = (uint32_t)(cmd->timeout_per_command / HZ); >- if (timeout > FW_MAX_TIMEOUT) >+ if (sp->flags & SRB_NO_TIMER || timeout > FW_MAX_TIMEOUT) > cmd_pkt->timeout = > __constant_cpu_to_le16(FW_MAX_TIMEOUT); > else if (timeout > 25) >diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c >index b71badb..7de4ca4 100644 >--- a/drivers/scsi/qla2xxx/qla_isr.c >+++ b/drivers/scsi/qla2xxx/qla_isr.c >@@ -758,6 +758,20 @@ qla2x00_process_completed_request(struct > if (ha->actthreads) > ha->actthreads--; > sp->lun_queue->out_cnt--; >+ >+ if (sp->cmd == NULL) { >+ DEBUG2(printk("scsi(%ld): Command already returned " >+ "back to caller pkt->handle=%d sp=%p " >+ "sp->state:%d\n", ha->host_no, index, sp, >+ sp->state)); >+ qla_printk(KERN_WARNING, ha, >+ "Command is NULL: already returned to caller " >+ "handle=%x sp=%p flags=%x ext_hist=%x.\n", index, >+ sp, sp->flags, sp->ext_history); >+ >+ return; >+ } >+ > CMD_COMPL_STATUS(sp->cmd) = 0L; > CMD_SCSI_STATUS(sp->cmd) = 0L; > >@@ -936,8 +950,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha > "pkt->handle=%d sp=%p sp->state:%d\n", > ha->host_no, sts->handle, sp, sp->state)); > qla_printk(KERN_WARNING, ha, >- "Command is NULL: already returned to OS (sp=%p)\n", sp); >- >+ "Command is NULL: already returned to OS " >+ "handle=%x sp=%p flags=%x ext_hist=%x.\n", sts->handle, >+ sp, sp->flags, sp->ext_history); > return; > } > >@@ -1400,10 +1415,10 @@ qla2x00_status_cont_entry(scsi_qla_host_ > if (cp == NULL) { > DEBUG2(printk("%s(): Cmd already returned back to OS " > "sp=%p sp->state:%d\n", __func__, sp, sp->state)); >- qla_printk(KERN_INFO, ha, >- "cmd is NULL: already returned to OS (sp=%p)\n", >- sp); >- >+ qla_printk(KERN_WARNING, ha, >+ "Command is NULL: already returned to OS " >+ "sp=%p flags=%x ext_hist=%x.\n", sp, sp->flags, >+ sp->ext_history); > ha->status_srb = NULL; > return; > } >@@ -1526,6 +1541,17 @@ qla2x00_ms_entry(scsi_qla_host_t *ha, ms > set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); > return; > } >+ if (sp->cmd == NULL) { >+ DEBUG2(printk("scsi(%ld): Command already returned back to MS " >+ "caller pkt->handle=%d sp=%p sp->state:%d\n", >+ ha->host_no, pkt->handle1, sp, sp->state)); >+ qla_printk(KERN_WARNING, ha, >+ "Command is NULL: already returned to MS caller " >+ "handle=%x sp=%p flags=%x ext_hist=%x.\n", pkt->handle1, >+ sp, sp->flags, sp->ext_history); >+ >+ return; >+ } > > CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status); > CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; >@@ -1796,6 +1822,17 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, st > set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); > return; > } >+ if (sp->cmd == NULL) { >+ DEBUG2(printk("scsi(%ld): Command already returned back to MS " >+ "caller pkt->handle=%d sp=%p sp->state:%d\n", >+ ha->host_no, pkt->handle, sp, sp->state)); >+ qla_printk(KERN_WARNING, ha, >+ "Command is NULL: already returned to MS caller " >+ "handle=%x sp=%p flags=%x ext_hist=%x.\n", pkt->handle, >+ sp, sp->flags, sp->ext_history); >+ >+ return; >+ } > > CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status); > CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status; >diff --git a/drivers/scsi/qla2xxx/qla_listops.h b/drivers/scsi/qla2xxx/qla_listops.h >index 266dcba..c059fcb 100644 >--- a/drivers/scsi/qla2xxx/qla_listops.h >+++ b/drivers/scsi/qla2xxx/qla_listops.h >@@ -44,6 +44,7 @@ __add_to_done_queue(struct scsi_qla_host > list_add_tail(&sp->list,&ha->done_queue); > ha->done_q_cnt++; > sp->ha = ha; >+ qla2x00_delete_timer_from_cmd(sp); > } > > static inline void >diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c >index cd70f10..d51b13f 100644 >--- a/drivers/scsi/qla2xxx/qla_os.c >+++ b/drivers/scsi/qla2xxx/qla_os.c >@@ -178,6 +178,11 @@ MODULE_PARM_DESC(ql2xqfullrampup, > "depth for a device after a queue-full condition has been " > "detected. Default is 120 seconds."); > >+int ql2xcmdtimermin = QLA_CMD_TIMER_MINIMUM; >+module_param(ql2xcmdtimermin, int, S_IRUGO|S_IWUSR); >+MODULE_PARM_DESC(ql2xcmdtimermin, >+ "Default is 30 seconds."); >+ > /* > * List of host adapters > */ >@@ -311,9 +316,6 @@ qla2x00_stop_timer(scsi_qla_host_t *ha) > > void qla2x00_cmd_timeout(srb_t *); > >-static __inline__ void qla2x00_callback(scsi_qla_host_t *, struct scsi_cmnd *); >-static __inline__ void sp_put(struct scsi_qla_host * ha, srb_t *sp); >-static __inline__ void sp_get(struct scsi_qla_host * ha, srb_t *sp); > static __inline__ void > qla2x00_delete_from_done_queue(scsi_qla_host_t *, srb_t *); > >@@ -331,7 +333,7 @@ qla2x00_delete_from_done_queue(scsi_qla_ > * back to the pool it has to be the vis_ha. > * So rely on struct scsi_cmnd to get the vis_ha and not on sp. > */ >-static inline void >+void > qla2x00_callback(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) > { > srb_t *sp = (srb_t *) CMD_SP(cmd); >@@ -354,10 +356,6 @@ qla2x00_callback(scsi_qla_host_t *ha, st > /* > * If command status is not DID_BUS_BUSY then go ahead and freed sp. > */ >- /* >- * Cancel command timeout >- */ >- qla2x00_delete_timer_from_cmd(sp); > > /* > * Put SP back in the free queue >@@ -402,7 +400,7 @@ qla2x00_callback(scsi_qla_host_t *ha, st > * Returns: > * > **************************************************************************/ >-static inline void >+void > sp_put(struct scsi_qla_host * ha, srb_t *sp) > { > if (atomic_read(&sp->ref_count) == 0) { >@@ -433,19 +431,10 @@ sp_put(struct scsi_qla_host * ha, srb_t > * Returns: > * > **************************************************************************/ >-static inline void >+void > sp_get(struct scsi_qla_host * ha, srb_t *sp) > { > atomic_inc(&sp->ref_count); >- >- if (atomic_read(&sp->ref_count) > 2) { >- qla_printk(KERN_INFO, ha, >- "%s(): **** SP->ref_count greater than two\n", >- __func__); >- DEBUG2(BUG();) >- >- return; >- } > } > > static inline void >@@ -842,10 +831,10 @@ qla2x00_queuecommand(struct scsi_cmnd *c > * aborts are called. > */ > if ((cmd->timeout_per_command / HZ) > QLA_CMD_TIMER_DELTA) >- qla2x00_add_timer_to_cmd(sp, >+ qla2x00_add_timer_to_cmd(ha, sp, > (cmd->timeout_per_command / HZ) - QLA_CMD_TIMER_DELTA); > else >- qla2x00_add_timer_to_cmd(sp, cmd->timeout_per_command / HZ); >+ sp->flags |= SRB_NO_TIMER; > > if (l >= ha->max_luns) { > cmd->result = DID_NO_CONNECT << 16; >@@ -853,6 +842,7 @@ qla2x00_queuecommand(struct scsi_cmnd *c > > spin_lock_irq(ha->host->host_lock); > >+ qla2x00_delete_timer_from_cmd(sp); > sp_put(ha, sp); > > return (0); >@@ -906,8 +896,9 @@ qla2x00_queuecommand(struct scsi_cmnd *c > cmd->result = DID_NO_CONNECT << 16; > sp->err_id = SRB_ERR_PORT; > >- spin_lock_irq(ha->host->host_lock); >+ spin_lock_irq(ha->host->host_lock); > >+ qla2x00_delete_timer_from_cmd(sp); > sp_put(ha, sp); > > return (0); >@@ -1036,9 +1027,23 @@ qla2x00_eh_wait_on_command(scsi_qla_host > } > spin_unlock_irqrestore(&ha->list_lock, flags); > >+ /* Checking to see if its returned to OS */ >+ rp = (srb_t *) CMD_SP(cmd); >+ if (rp == NULL) { >+ done++; >+ break; >+ } >+ >+ if (atomic_read(&rp->ref_count) == 1) { >+ done++; >+ break; >+ } >+ > /* Complete the cmd right away. */ > if (found) { >- qla2x00_delete_from_done_queue(ha, rp); >+ spin_lock_irqsave(&ha->list_lock, flags); >+ qla2x00_delete_from_done_queue(ha, rp); >+ spin_unlock_irqrestore(&ha->list_lock, flags); > sp_put(ha, rp); > done++; > break; >@@ -1199,6 +1204,7 @@ int > qla2xxx_eh_abort(struct scsi_cmnd *cmd) > { > int i; >+ int got_ref = 0; > int return_status = FAILED; > os_lun_t *q; > scsi_qla_host_t *ha; >@@ -1239,11 +1245,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > l = cmd->device->lun; > q = GET_LU_Q(vis_ha, t, l); > >- qla_printk(KERN_INFO, ha, >- "%s scsi(%ld:%d:%d:%d): cmd_timeout_in_sec=0x%x.\n", __func__, >- ha->host_no, (int)b, (int)t, (int)l, >- cmd->timeout_per_command / HZ); >- > /* > * if no LUN queue then something is very wrong!!! > */ >@@ -1255,10 +1256,13 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > return return_status; > } > >- DEBUG2(printk("scsi(%ld): ABORTing cmd=%p sp=%p jiffies = 0x%lx, " >- "timeout=%x, dpc_flags=%lx, vis_ha->dpc_flags=%lx q->flag=%lx\n", >- ha->host_no, cmd, sp, jiffies, cmd->timeout_per_command / HZ, >- ha->dpc_flags, vis_ha->dpc_flags, q->q_flag)); >+ qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): ABORTing cmd=%p " >+ "sp=%p flags=%x state=%x ext_hist=%x jiffies = 0x%lx, timeout=%x, " >+ "dpc_flags=%lx, vis_ha->dpc_flags=%lx q->flag=%lx\n", >+ ha->host_no, (int)b, (int)t, (int)l, cmd, sp, sp->flags, >+ sp->state, sp->ext_history, jiffies, >+ cmd->timeout_per_command / HZ, ha->dpc_flags, vis_ha->dpc_flags, >+ q->q_flag); > DEBUG2(qla2x00_print_scsi_cmd(cmd)); > > spin_unlock_irq_dump(vis_ha->host->host_lock); >@@ -1386,6 +1390,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > > /* Get a reference to the sp and drop the lock.*/ > sp_get(ha, sp); >+ got_ref++; > > spin_unlock_irqrestore(&ha->hardware_lock, flags); > >@@ -1399,8 +1404,6 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > return_status = SUCCESS; > } > >- sp_put(ha,sp); >- > spin_lock_irqsave(&ha->hardware_lock, flags); > > /* >@@ -1420,6 +1423,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > return_status = SUCCESS; > } > >+ if (got_ref) >+ sp_put(ha, sp); >+ > if (return_status == FAILED) > qla_printk(KERN_INFO, ha, > "qla2xxx_eh_abort Exiting: status=Failed\n"); >@@ -4130,6 +4136,19 @@ qla2x00_timer(scsi_qla_host_t *ha) > qla2x00_restart_timer(ha, WATCH_INTERVAL); > } > >+static inline void >+qla2x00_extend_scsi_ml_timeout(struct scsi_cmnd *cmd, int timeout) >+{ >+ srb_t *sp = (srb_t *) CMD_SP(cmd); >+ unsigned long our_jiffies; >+ >+ if (del_timer(&cmd->eh_timeout)) { >+ our_jiffies = (timeout * HZ) + cmd->eh_timeout.expires; >+ mod_timer(&cmd->eh_timeout, our_jiffies); >+ sp->ext_history |= 1; >+ } >+} >+ > /* > * qla2x00_extend_timeout > * This routine will extend the timeout to the specified value. >@@ -4144,28 +4163,23 @@ void > qla2x00_extend_timeout(struct scsi_cmnd *cmd, int timeout) > { > srb_t *sp = (srb_t *) CMD_SP(cmd); >+ unsigned long our_jiffies; > >- sp->ext_history= 0; >- sp->e_start = jiffies; >- if (del_timer(&cmd->eh_timeout)) { >- u_long our_jiffies; >+ if (sp->flags & SRB_NO_TIMER) >+ return; > >- our_jiffies = (timeout * HZ) + cmd->eh_timeout.expires; >- mod_timer(&cmd->eh_timeout,our_jiffies); >- sp->ext_history |= 1; >- } >+ sp->ext_history = 0; >+ sp->e_start = jiffies; > >- if (del_timer(&sp->timer)) { >- u_long our_jiffies; >- /* >- * Our internal timer should timeout before the midlayer has a >- * chance begin the abort process >- */ >- our_jiffies = (timeout * HZ) + sp->timer.expires; >- mod_timer(&sp->timer,our_jiffies - (QLA_CMD_TIMER_DELTA * HZ)); >+ qla2x00_extend_scsi_ml_timeout(cmd, timeout); > >- sp->ext_history |= 2; >- } >+ /* >+ * Our internal timer should timeout before the midlayer has a >+ * chance to begin the abort process. >+ */ >+ our_jiffies = (timeout * HZ) + sp->timer.expires; >+ mod_timer(&sp->timer, our_jiffies - (QLA_CMD_TIMER_DELTA * HZ)); >+ sp->ext_history |= 2; > } > > /************************************************************************** >@@ -4186,15 +4200,25 @@ qla2x00_cmd_timeout(srb_t *sp) > { > int t, l; > int processed; >+ int timer_extended = 0; > scsi_qla_host_t *vis_ha, *dest_ha; > struct scsi_cmnd *cmd; > unsigned long flags, cpu_flags; > fc_port_t *fcport; > > cmd = sp->cmd; >+ if (!cmd) { >+ qla_printk(KERN_WARNING, sp->ha, >+ "Command Timeout: command is NULL, already returned to OS " >+ "sp=%p flags=%x ext_hist=%x.\n", sp, sp->flags, >+ sp->ext_history); >+ return; >+ } >+ > vis_ha = (scsi_qla_host_t *)cmd->device->host->hostdata; > >- DEBUG3(printk("cmd_timeout: Entering sp->state = %x\n", sp->state)); >+ DEBUG2(printk("scsi(%ld): Command timeout: sp=%p sp->state=%x\n", >+ vis_ha->host_no, sp, sp->state)); > > t = cmd->device->id; > l = cmd->device->lun; >@@ -4230,6 +4254,7 @@ qla2x00_cmd_timeout(srb_t *sp) > } else { > cmd->result = DID_BUS_BUSY << 16; > } >+ sp_put(vis_ha, sp); /* release timer reference as expired */ > __add_to_done_queue(vis_ha, sp); > processed++; > } >@@ -4263,7 +4288,8 @@ qla2x00_cmd_timeout(srb_t *sp) > */ > if ((atomic_read(&fcport->state) == FCS_DEVICE_DEAD) || > atomic_read(&dest_ha->loop_state) == LOOP_DEAD) { >- qla2x00_extend_timeout(cmd, EXTEND_CMD_TIMEOUT); >+ qla2x00_extend_scsi_ml_timeout(cmd, >+ EXTEND_CMD_TIMEOUT); > cmd->result = DID_NO_CONNECT << 16; > if (atomic_read(&dest_ha->loop_state) == LOOP_DOWN) > sp->err_id = SRB_ERR_LOOP; >@@ -4273,7 +4299,8 @@ qla2x00_cmd_timeout(srb_t *sp) > cmd->result = DID_BUS_BUSY << 16; > } > >- __add_to_done_queue(dest_ha, sp); >+ sp_put(vis_ha, sp); /* release timer reference as expired */ >+ __add_to_done_queue(dest_ha, sp); > processed++; > } > spin_unlock_irqrestore(&dest_ha->list_lock, flags); >@@ -4286,13 +4313,13 @@ qla2x00_cmd_timeout(srb_t *sp) > spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); > if (sp->state == SRB_DONE_STATE) { > /* IO in done_q -- leave it */ >- DEBUG(printk("scsi(%ld): Found in Done queue pid %ld sp=%p.\n", >+ DEBUG2(printk("scsi(%ld): Found in Done queue pid %ld sp=%p.\n", > dest_ha->host_no, cmd->serial_number, sp)); > } else if (sp->state == SRB_SUSPENDED_STATE) { >- DEBUG(printk("scsi(%ld): Found SP %p in suspended state " >+ DEBUG2(printk("scsi(%ld): Found SP %p in suspended state " > "- pid %ld:\n", > dest_ha->host_no, sp, cmd->serial_number)); >- DEBUG(qla2x00_dump_buffer((uint8_t *)sp, sizeof(srb_t));) >+ DEBUG2(qla2x00_dump_buffer((uint8_t *)sp, sizeof(srb_t));) > } else if (sp->state == SRB_ACTIVE_STATE) { > /* > * IO is with ISP find the command in our active list. >@@ -4302,7 +4329,7 @@ qla2x00_cmd_timeout(srb_t *sp) > if (sp == dest_ha->outstanding_cmds[ > (unsigned long)sp->cmd->host_scribble]) { > >- DEBUG(printk("scsi(%ld): Found in ISP pid=%ld " >+ DEBUG2(printk("scsi(%ld): Found in ISP pid=%ld " > "hdl=%ld\n", dest_ha->host_no, cmd->serial_number, > (unsigned long)sp->cmd->host_scribble)); > >@@ -4313,36 +4340,39 @@ qla2x00_cmd_timeout(srb_t *sp) > * Extend the timer so that the firmware can > * properly return the IOCB. > */ >- DEBUG(printk("cmd_timeout: Extending timeout " >- "of FCP2 tape command!\n")); >+ DEBUG3(printk("scsi(%ld): Extending timeout " >+ "of command!\n", ha->host_no)); > qla2x00_extend_timeout(sp->cmd, > EXTEND_CMD_TIMEOUT); >+ timer_extended = 1; > } > sp->state = SRB_ACTIVE_TIMEOUT_STATE; > spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); > } else { > spin_unlock_irqrestore(&dest_ha->hardware_lock, flags); >- printk(KERN_INFO >- "qla_cmd_timeout: State indicates it is with " >- "ISP, But not in active array\n"); >+ qla_printk(KERN_INFO, vis_ha, >+ "cmd_timeout: State indicates it is with " >+ "ISP, But not in active array.\n"); > } > spin_lock_irqsave(&dest_ha->list_lock, cpu_flags); > } else if (sp->state == SRB_ACTIVE_TIMEOUT_STATE) { >- DEBUG(printk("qla2100%ld: Found in Active timeout state" >- "pid %ld, State = %x., \n", >+ DEBUG2(printk("scsi(%ld): Found in Active timeout state " >+ "pid %ld, State = %x.\n", > dest_ha->host_no, > sp->cmd->serial_number, sp->state);) > } else { > /* EMPTY */ >- DEBUG2(printk("cmd_timeout%ld: LOST command state = " >- "0x%x, sp=%p\n", >- vis_ha->host_no, sp->state,sp);) >+ DEBUG2(printk("scsi(%ld): LOST command state = 0x%x, sp=%p\n", >+ vis_ha->host_no, sp->state,sp)); > > qla_printk(KERN_INFO, vis_ha, > "cmd_timeout: LOST command state = 0x%x\n", sp->state); > } > spin_unlock_irqrestore(&dest_ha->list_lock, cpu_flags); > >+ if (!timer_extended) >+ sp_put(vis_ha, sp); >+ > DEBUG3(printk("cmd_timeout: Leaving\n");) > } > >diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h >index a941374..094e82c 100644 >--- a/drivers/scsi/qla2xxx/qla_settings.h >+++ b/drivers/scsi/qla2xxx/qla_settings.h >@@ -32,6 +32,7 @@ > */ > #define MAX_FAILBACKTIME 5 /* Max suspend time before fail back */ > >+#define QLA_CMD_TIMER_MINIMUM 30 > #define QLA_CMD_TIMER_DELTA 3 > > /* >-- >1.4.4.1 > >From 30b9b027489bc22793eda22727ad0ae7bf2f5006 Mon Sep 17 00:00:00 2001 >From: Marcus Barrow <mbarrow@marcus-barrows-computer.local> >Date: Tue, 26 Jun 2007 16:28:02 -0400 >Subject: [PATCH] from commit 24753cdcc1d01044234ada12b84101050c9c1bcc in std tree. > Author: Ravi Anand > Correct SRB reference counting issues during error-recovery. > > - complete commands imemdiately if command found in local queues during EH > abort. > - correct SRB leaks > - clear done-queue count while copying on the stack. >--- > drivers/scsi/qla2xxx/qim_xioct.c | 5 + > drivers/scsi/qla2xxx/qla_gbl.h | 1 - > drivers/scsi/qla2xxx/qla_listops.h | 27 ++++- > drivers/scsi/qla2xxx/qla_os.c | 244 ++++++++++++++++++++---------------- > 4 files changed, 163 insertions(+), 114 deletions(-) > >diff --git a/drivers/scsi/qla2xxx/qim_xioct.c b/drivers/scsi/qla2xxx/qim_xioct.c >index 604f046..d1a047e 100644 >--- a/drivers/scsi/qla2xxx/qim_xioct.c >+++ b/drivers/scsi/qla2xxx/qim_xioct.c >@@ -3909,6 +3909,11 @@ qim_ioctl_ms_queuecommand(struct qla_hos > /* We waited and post function did not get called */ > DEBUG9_10(printk("%s(%ld): inst=%ld command timed out.\n", > __func__, ha->host_no, ha->instance);) >+ >+ if (tmp_rval == QLA_MEMORY_ALLOC_FAILED) { >+ atomic_set(&sp->ref_count, 0); >+ add_to_free_queue (dr_ha, sp); >+ } > > pext->Status = EXT_STATUS_MS_NO_RESPONSE; > >diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h >index d07c4f9..4457e0d 100644 >--- a/drivers/scsi/qla2xxx/qla_gbl.h >+++ b/drivers/scsi/qla2xxx/qla_gbl.h >@@ -106,7 +106,6 @@ extern void qla23xx_blink_led(scsi_qla_h > extern void qla24xx_blink_led(scsi_qla_host_t *); > > extern int qla2x00_down_timeout(struct semaphore *, unsigned long); >-extern void qla2x00_callback(scsi_qla_host_t *, struct scsi_cmnd *); > extern void sp_put(struct scsi_qla_host *, srb_t *); > extern void sp_get(struct scsi_qla_host *, srb_t *); > >diff --git a/drivers/scsi/qla2xxx/qla_listops.h b/drivers/scsi/qla2xxx/qla_listops.h >index c059fcb..bf72195 100644 >--- a/drivers/scsi/qla2xxx/qla_listops.h >+++ b/drivers/scsi/qla2xxx/qla_listops.h >@@ -116,6 +116,17 @@ add_to_scsi_retry_queue(struct scsi_qla_ > spin_unlock_irqrestore(&ha->list_lock, flags); > } > >+static inline void >+qla2x00_queue_check(srb_t *sp) >+{ >+ if (!sp->cmd) { >+ printk("%s(%ld): sp->cmd==0 SP=%p sp->ha=%p state=%d, flags=%d " >+ "ext_history=%d\n", __func__, sp->ha->host_no, sp, >+ sp->ha, sp->state, sp->flags, sp->ext_history); >+ BUG_ON(!sp->cmd); >+ } >+} >+ > /* > * __del_from_retry_queue > * Function used to remove a command block from the >@@ -134,11 +145,13 @@ add_to_scsi_retry_queue(struct scsi_qla_ > static inline void > __del_from_retry_queue(struct scsi_qla_host * ha, srb_t * sp) > { >- list_del_init(&sp->list); >+ DEBUG2(qla2x00_queue_check(sp)); > >- sp->flags &= ~(SRB_WATCHDOG | SRB_BUSY); >- sp->state = SRB_NO_QUEUE_STATE; >- ha->retry_q_cnt--; >+ list_del_init(&sp->list); >+ >+ sp->flags &= ~(SRB_WATCHDOG | SRB_BUSY); >+ sp->state = SRB_NO_QUEUE_STATE; >+ ha->retry_q_cnt--; > } > > /* >@@ -155,6 +168,8 @@ __del_from_retry_queue(struct scsi_qla_h > static inline void > __del_from_scsi_retry_queue(struct scsi_qla_host * ha, srb_t * sp) > { >+ DEBUG2(qla2x00_queue_check(sp)); >+ > list_del_init(&sp->list); > > ha->scsi_retry_q_cnt--; >@@ -281,6 +296,8 @@ add_to_pending_queue_head(struct scsi_ql > static inline void > __del_from_pending_queue(struct scsi_qla_host *ha, srb_t *sp) > { >+ DEBUG2(qla2x00_queue_check(sp)); >+ > list_del_init(&sp->list); > ha->qthreads--; > sp->state = SRB_NO_QUEUE_STATE; >@@ -317,6 +334,8 @@ static inline void add_to_failover_queue > static inline void __del_from_failover_queue(struct scsi_qla_host * ha, srb_t * > sp) > { >+ DEBUG2(qla2x00_queue_check(sp)); >+ > ha->failover_cnt--; > list_del_init(&sp->list); > sp->state = SRB_NO_QUEUE_STATE; >diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c >index d51b13f..e29b789 100644 >--- a/drivers/scsi/qla2xxx/qla_os.c >+++ b/drivers/scsi/qla2xxx/qla_os.c >@@ -333,8 +333,8 @@ qla2x00_delete_from_done_queue(scsi_qla_ > * back to the pool it has to be the vis_ha. > * So rely on struct scsi_cmnd to get the vis_ha and not on sp. > */ >-void >-qla2x00_callback(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) >+static void >+qla2x00_callback(scsi_qla_host_t *ha, struct scsi_cmnd *cmd, srb_t *orig_sp) > { > srb_t *sp = (srb_t *) CMD_SP(cmd); > scsi_qla_host_t *vis_ha; >@@ -347,9 +347,15 @@ qla2x00_callback(scsi_qla_host_t *ha, st > > if (sp == NULL) { > qla_printk(KERN_INFO, ha, >- "%s(): **** CMD derives a NULL SP\n", >- __func__); >- DEBUG2(BUG();) >+ "%s(): **** CMD<%ld:%d:%d:%d> %p %ld derives a NULL SP " >+ "tmo=%d osp=%p.\n", __func__, ha->host_no, cmd->device->channel, >+ cmd->device->id, cmd->device->lun, cmd, cmd->serial_number, >+ cmd->timeout_per_command, orig_sp); >+ if (orig_sp) { >+ orig_sp->cmd = NULL; >+ add_to_free_queue(vis_ha, orig_sp); >+ } >+ > return; > } > >@@ -416,7 +422,7 @@ sp_put(struct scsi_qla_host * ha, srb_t > return; > } > >- qla2x00_callback(ha, sp->cmd); >+ qla2x00_callback(ha, sp->cmd, sp); > } > > /************************************************************************** >@@ -438,28 +444,35 @@ sp_get(struct scsi_qla_host * ha, srb_t > } > > static inline void >-qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp) >+qla2x00_cleanse_sp(scsi_qla_host_t *ha, srb_t *sp) > { >- /* remove command from done list */ >- list_del_init(&sp->list); >- dest_ha->done_q_cnt--; >- sp->state = SRB_NO_QUEUE_STATE; >- >+ qla2x00_delete_timer_from_cmd(sp); > if (sp->flags & SRB_DMA_VALID) { > sp->flags &= ~SRB_DMA_VALID; > > /* Release memory used for this I/O */ > if (sp->cmd->use_sg) { >- pci_unmap_sg(dest_ha->pdev, sp->cmd->request_buffer, >+ pci_unmap_sg(ha->pdev, sp->cmd->request_buffer, > sp->cmd->use_sg, sp->cmd->sc_data_direction); > } else if (sp->cmd->request_bufflen) { >- pci_unmap_page(dest_ha->pdev, sp->dma_handle, >+ pci_unmap_page(ha->pdev, sp->dma_handle, > sp->cmd->request_bufflen, > sp->cmd->sc_data_direction); > } > } > } > >+static inline void >+qla2x00_delete_from_done_queue(scsi_qla_host_t *dest_ha, srb_t *sp) >+{ >+ /* remove command from done list */ >+ list_del_init(&sp->list); >+ dest_ha->done_q_cnt--; >+ sp->state = SRB_NO_QUEUE_STATE; >+ >+ qla2x00_cleanse_sp(dest_ha, sp); >+} >+ > static int qla2x00_do_dpc(void *data); > static int __qla2x00_do_dpc(scsi_qla_host_t *ha); > >@@ -996,7 +1009,7 @@ qla2x00_queuecommand(struct scsi_cmnd *c > * Found : 1 > */ > static int >-qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd) >+qla2x00_eh_wait_on_command(scsi_qla_host_t *ha, struct scsi_cmnd *cmd, int got_ref) > { > #define ABORT_POLLING_PERIOD HZ > #define ABORT_WAIT_TIME ((10 * HZ) / (ABORT_POLLING_PERIOD)) >@@ -1019,9 +1032,10 @@ qla2x00_eh_wait_on_command(scsi_qla_host > * to OS. > */ > if (cmd == rp->cmd) { >- found++; > DEBUG3(printk("%s: found in done queue.\n", > __func__);) >+ qla2x00_delete_from_done_queue(ha, rp); >+ found++; > break; > } > } >@@ -1034,16 +1048,13 @@ qla2x00_eh_wait_on_command(scsi_qla_host > break; > } > >- if (atomic_read(&rp->ref_count) == 1) { >+ if (got_ref && (atomic_read(&rp->ref_count) == 1)) { > done++; > break; > } > > /* Complete the cmd right away. */ > if (found) { >- spin_lock_irqsave(&ha->list_lock, flags); >- qla2x00_delete_from_done_queue(ha, rp); >- spin_unlock_irqrestore(&ha->list_lock, flags); > sp_put(ha, rp); > done++; > break; >@@ -1258,11 +1269,11 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > > qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): ABORTing cmd=%p " > "sp=%p flags=%x state=%x ext_hist=%x jiffies = 0x%lx, timeout=%x, " >- "dpc_flags=%lx, vis_ha->dpc_flags=%lx q->flag=%lx\n", >+ "dpc_flags=%lx, vis_ha->dpc_flags=%lx q->flag=%lx ha=%p vis_ha=%p sp->ha=%p\n", > ha->host_no, (int)b, (int)t, (int)l, cmd, sp, sp->flags, > sp->state, sp->ext_history, jiffies, > cmd->timeout_per_command / HZ, ha->dpc_flags, vis_ha->dpc_flags, >- q->q_flag); >+ q->q_flag, ha, vis_ha, sp->ha); > DEBUG2(qla2x00_print_scsi_cmd(cmd)); > > spin_unlock_irq_dump(vis_ha->host->host_lock); >@@ -1285,16 +1296,16 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > * And proceed to post completion to scsi mid layer. > */ > return_status = SUCCESS; >+ qla2x00_delete_from_done_queue(ha, rp); > found++; >- qla2x00_delete_from_done_queue(ha, sp); > > break; > } /* list_for_each_safe() */ > spin_unlock_irqrestore(&ha->list_lock, flags); > > /* >- * Return immediately if the aborted command was already in the done >- * queue >+ * Found command. Remove it from done list. >+ * And proceed to post completion to scsi mid layer. > */ > if (found) { > qla_printk(KERN_INFO, ha, >@@ -1317,108 +1328,125 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) > if (cmd != rp->cmd) > continue; > >- >- DEBUG2(printk("qla2xxx_eh_abort: found " >- "in retry queue. SP=%p\n", sp);) >+ printk("%s: found in retry queue (%d). SP=%p flags=%d " >+ "sp->ha=%p ha=%p\n", __func__, ha->retry_q_cnt, sp, >+ sp->flags, sp->ha, ha); > > __del_from_retry_queue(ha, rp); >+ found++; >+ break; >+ } >+ spin_unlock_irqrestore(&ha->list_lock, flags); >+ if (found) { >+ return_status = SUCCESS; >+ qla2x00_cleanse_sp(ha, sp); > cmd->result = DID_ABORT << 16; >- __add_to_done_queue(ha, rp); >+ sp_put(ha, sp); >+ goto eh_abort_complete; >+ } > >- return_status = SUCCESS; >- found++; >+ spin_lock_irqsave(&ha->list_lock, flags); >+ list_for_each_safe(list, temp, &ha->scsi_retry_queue) { >+ rp = list_entry(list, srb_t, list); >+ if (cmd != rp->cmd) >+ continue; > >- break; >+ printk("%s: found in scsi-retry queue (%d). SP=%p " >+ "flags=%d sp->ha=%p ha=%p\n", __func__, >+ ha->scsi_retry_q_cnt, sp, sp->flags, sp->ha, ha); > >- } >+ __del_from_scsi_retry_queue(ha, rp); >+ found++; >+ break; >+ } > spin_unlock_irqrestore(&ha->list_lock, flags); >+ if (found) { >+ return_status = SUCCESS; >+ qla2x00_cleanse_sp(ha, sp); >+ cmd->result = DID_ABORT << 16; >+ sp_put(ha, sp); >+ goto eh_abort_complete; >+ } > > > /* > * Our SP pointer points at the command we want to remove from the > * pending queue providing we haven't already sent it to the adapter. > */ >- if (!found) { >- DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " >- "in pending queue.\n", sp);) >+ DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " >+ "in pending queue.\n", sp)); > >- spin_lock_irqsave(&vis_ha->list_lock, flags); >- list_for_each_safe(list, temp, &vis_ha->pending_queue) { >- rp = list_entry(list, srb_t, list); >+ spin_lock_irqsave(&vis_ha->list_lock, flags); >+ list_for_each_safe(list, temp, &vis_ha->pending_queue) { >+ rp = list_entry(list, srb_t, list); >+ if (rp->cmd != cmd) >+ continue; >+ /* Remove srb from LUN queue. */ >+ rp->flags |= SRB_ABORTED; > >- if (rp->cmd != cmd) >- continue; >+ DEBUG2(printk("qla2xxx_eh_abort: Cmd in pending queue." >+ " serial_number %ld.\n", >+ rp->cmd->serial_number)); > >- /* Remove srb from LUN queue. */ >- rp->flags |= SRB_ABORTED; >+ __del_from_pending_queue(vis_ha, rp); >+ found++; >+ break; >+ } /* list_for_each_safe() */ >+ spin_unlock_irqrestore(&vis_ha->list_lock, flags); >+ if (found) { >+ return_status = SUCCESS; >+ qla2x00_cleanse_sp(ha, sp); >+ cmd->result = DID_ABORT << 16; >+ sp_put(ha, sp); >+ goto eh_abort_complete; >+ } > >- DEBUG2(printk("qla2xxx_eh_abort: Cmd in pending queue." >- " serial_number %ld.\n", >- sp->cmd->serial_number);) >+ DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " >+ "in outstanding queue.\n", sp)); >+ spin_lock_irqsave(&ha->hardware_lock, flags); >+ for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { >+ sp = ha->outstanding_cmds[i]; > >- __del_from_pending_queue(vis_ha, rp); >- cmd->result = DID_ABORT << 16; >+ if (sp == NULL) >+ continue; >+ if (sp->cmd != cmd) >+ continue; > >- __add_to_done_queue(vis_ha, rp); >+ printk("qla2xxx_eh_abort(%ld): aborting sp %p " >+ "from RISC. pid=%ld sp->state=%x q->q_flag=%lx\n", >+ ha->host_no, sp, sp->cmd->serial_number, >+ sp->state, q->q_flag); > >- return_status = SUCCESS; >+ /* Get a reference to the sp and drop the lock.*/ >+ sp_get(ha, sp); >+ got_ref++; > >- found++; >- break; >- } /* list_for_each_safe() */ >- spin_unlock_irqrestore(&vis_ha->list_lock, flags); >- } /*End of if !found */ >+ spin_unlock_irqrestore(&ha->hardware_lock, flags); > >- if (!found) { /* find the command in our active list */ >- DEBUG3(printk("qla2xxx_eh_abort: searching sp %p " >- "in outstanding queue.\n", sp);) >+ if (qla2x00_abort_command(ha, sp)) { >+ DEBUG2(printk("qla2xxx_eh_abort: abort_command " >+ "mbx failed.\n")); >+ return_status = FAILED; >+ } else { >+ DEBUG3(printk("qla2xxx_eh_abort: abort_command " >+ " mbx success.\n")); >+ return_status = SUCCESS; >+ } > > spin_lock_irqsave(&ha->hardware_lock, flags); >- for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { >- sp = ha->outstanding_cmds[i]; >- >- if (sp == NULL) >- continue; >- >- if (sp->cmd != cmd) >- continue; >- >- DEBUG2(printk("qla2xxx_eh_abort(%ld): aborting sp %p " >- "from RISC. pid=%ld sp->state=%x q->q_flag=%lx\n", >- ha->host_no, sp, sp->cmd->serial_number, >- sp->state, q->q_flag);) >- >- /* Get a reference to the sp and drop the lock.*/ >- sp_get(ha, sp); >- got_ref++; > >- spin_unlock_irqrestore(&ha->hardware_lock, flags); >- >- if (qla2x00_abort_command(ha, sp)) { >- DEBUG2(printk("qla2xxx_eh_abort: abort_command " >- "mbx failed.\n");) >- return_status = FAILED; >- } else { >- DEBUG3(printk("qla2xxx_eh_abort: abort_command " >- " mbx success.\n");) >- return_status = SUCCESS; >- } >- >- spin_lock_irqsave(&ha->hardware_lock, flags); >- >- /* >- * Regardless of mailbox command status, go check on >- * done queue just in case the sp is already done. >- */ >- break; >- >- }/*End of for loop */ >- spin_unlock_irqrestore(&ha->hardware_lock, flags); >+ /* >+ * Regardless of mailbox command status, go check on >+ * done queue just in case the sp is already done. >+ */ >+ found++; >+ break; > >- } /*End of if !found */ >+ } /*End of for loop */ >+ spin_unlock_irqrestore(&ha->hardware_lock, flags); > > /* Waiting for our command in done_queue to be returned to OS.*/ >- if (qla2x00_eh_wait_on_command(ha, cmd) != 0) { >+ if (qla2x00_eh_wait_on_command(ha, cmd, got_ref) != 0) { > DEBUG2(printk("qla2xxx_eh_abort: cmd returned back to OS.\n");) > return_status = SUCCESS; > } >@@ -1474,7 +1502,7 @@ qla2x00_eh_wait_for_pending_target_comma > cmd = sp->cmd; > spin_unlock_irqrestore(&ha->hardware_lock, flags); > if (cmd->device->id == t) { >- if (!qla2x00_eh_wait_on_command(ha, cmd)) { >+ if (!qla2x00_eh_wait_on_command(ha, cmd, 0)) { > status = 1; > break; > } >@@ -1554,13 +1582,11 @@ qla2xxx_eh_device_reset(struct scsi_cmnd > set_bit(TQF_SUSPENDED, &tq->flags); > > qla_printk(KERN_INFO, ha, >- "scsi(%ld:%d:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, b, t, l); >- >- DEBUG2(printk(KERN_INFO >- "scsi(%ld): DEVICE_RESET cmd=%p jiffies = 0x%lx, timeout=%x, " >- "dpc_flags=%lx, status=%x allowed=%d cmd.state=%x\n", >- ha->host_no, cmd, jiffies, cmd->timeout_per_command / HZ, >- ha->dpc_flags, cmd->result, cmd->allowed, cmd->state)); >+ "scsi(%ld:%d:%d:%d): DEVICE_RESET cmd=%p jiffies = 0x%lx, " >+ "timeout=%x, dpc_flags=%lx, status=%x allowed=%d ha=%p " >+ "vis_ha=%p.\n", ha->host_no, b, t, l, cmd, jiffies, >+ cmd->timeout_per_command / HZ, ha->dpc_flags, cmd->result, >+ cmd->allowed, ha, vis_ha); > > spin_unlock_irq_dump(vis_ha->host->host_lock); > >@@ -1685,7 +1711,7 @@ qla2x00_eh_wait_for_pending_commands(scs > if (sp) { > cmd = sp->cmd; > spin_unlock_irqrestore(&ha->hardware_lock, flags); >- status = qla2x00_eh_wait_on_command(ha, cmd); >+ status = qla2x00_eh_wait_on_command(ha, cmd, 0); > if (status == 0) > break; > } >@@ -4402,13 +4428,13 @@ qla2x00_done(scsi_qla_host_t *old_ha) > */ > spin_lock_irqsave(&old_ha->list_lock, flags); > list_splice_init(&old_ha->done_queue, &local_sp_list); >+ old_ha->done_q_cnt = 0; > spin_unlock_irqrestore(&old_ha->list_lock, flags); > > /* > * All done commands are in the local queue, now do the call back. > */ > list_for_each_entry_safe(sp, sptemp, &local_sp_list, list) { >- old_ha->done_q_cnt--; > sp->state = SRB_NO_QUEUE_STATE; > > /* remove command from local list */ >-- >1.4.4.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 245939
: 158021