diff --git a/qla_isp/common/isp.c b/qla_isp/common/isp.c index 6a1649951..6caa330ef 100644 --- a/qla_isp/common/isp.c +++ b/qla_isp/common/isp.c @@ -1,4 +1,4 @@ -/* $Id: isp.c,v 1.203 2008/03/16 00:34:49 mjacob Exp $ */ +/* $Id: isp.c,v 1.204 2008/04/15 22:40:52 mjacob Exp $ */ /*- * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -5406,13 +5406,14 @@ again: uint8_t ts = completion_status & 0xff; /* * Only whine if this isn't the expected fallout of - * aborting the command. + * aborting the command or resetting the target. */ if (etype != RQSTYPE_RESPONSE) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (type 0x%x)", sp->req_handle, etype); } else if (ts != RQCS_ABORTED && + ts != RQCS_RESET_OCCURRED && sp->req_handle != ISP_SPCL_HANDLE) { isp_prt(isp, ISP_LOGERR, "cannot find handle 0x%x (status 0x%x)", diff --git a/qla_isp/common/isp_tpublic.h b/qla_isp/common/isp_tpublic.h index 08f8cd5e8..fd3c2c97e 100644 --- a/qla_isp/common/isp_tpublic.h +++ b/qla_isp/common/isp_tpublic.h @@ -1,4 +1,4 @@ -/* $Id: isp_tpublic.h,v 1.42 2008/02/27 21:00:26 mjacob Exp $ */ +/* $Id: isp_tpublic.h,v 1.43 2008/04/15 22:40:52 mjacob Exp $ */ /*- * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -114,7 +114,7 @@ typedef enum { * * The r_version tag defines the version of this API. */ -#define QR_VERSION 19 +#define QR_VERSION 20 typedef struct { /* NB: structure tags from here to r_version must never change */ void * r_identity; @@ -190,6 +190,7 @@ typedef struct tmd_notify { uint64_t nt_tagval; /* tag value */ uint32_t nt_channel; /* channel id */ tmd_ncode_t nt_ncode; /* action */ + void * nt_tmd; /* TMD for this notify */ void * nt_lreserved; void * nt_hreserved; } tmd_notify_t; diff --git a/qla_isp/linux/isp_cb_ops.c b/qla_isp/linux/isp_cb_ops.c index 28db24543..b97ad4533 100644 --- a/qla_isp/linux/isp_cb_ops.c +++ b/qla_isp/linux/isp_cb_ops.c @@ -1,4 +1,4 @@ -/* $Id: isp_cb_ops.c,v 1.88 2008/03/15 18:16:47 mjacob Exp $ */ +/* $Id: isp_cb_ops.c,v 1.89 2008/04/15 22:41:03 mjacob Exp $ */ /* * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -159,7 +159,7 @@ isplinux_proc_info(struct Scsi_Host *shp, char *buf, char **st, off_t off, int l } else if (strncmp(buf, "rescan", 6) == 0) { if (IS_FC(isp)) { for (io = 0; io < isp->isp_nchan; io++) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, io), 1, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, io), 1, __FUNCTION__, __LINE__); } io = len; } @@ -482,7 +482,7 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg) if (IS_FC(isp)) { for (i = 0; i < isp->isp_nchan; i++) { FCPARAM(isp, i)->isp_loopstate = LOOP_PDB_RCVD; - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, i), 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, i), 0, __FUNCTION__, __LINE__); } } break; diff --git a/qla_isp/linux/isp_linux.c b/qla_isp/linux/isp_linux.c index ff617e72a..369bf6340 100644 --- a/qla_isp/linux/isp_linux.c +++ b/qla_isp/linux/isp_linux.c @@ -1,4 +1,4 @@ -/* $Id: isp_linux.c,v 1.229 2008/03/15 18:16:47 mjacob Exp $ */ +/* $Id: isp_linux.c,v 1.230 2008/04/15 22:41:03 mjacob Exp $ */ /* * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -313,7 +313,7 @@ isplinux_runwaitq(ispsoftc_t *isp) */ if (IS_FC(isp)) { if (result == CMD_RQLATER && ISP_DATA(isp, XS_CHANNEL(f))->deadloop == 0) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, chan), 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, chan), 0, __FUNCTION__, __LINE__); } } @@ -485,7 +485,7 @@ isplinux_queuecommand(Scsi_Cmnd *Cmnd, void (*donecmd)(Scsi_Cmnd *)) */ isplinux_append_to_waitq(isp, Cmnd); if (IS_FC(isp) && ISP_DATA(isp, XS_CHANNEL(Cmnd))->deadloop == 0) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, XS_CHANNEL(Cmnd)), 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, XS_CHANNEL(Cmnd)), 0, __FUNCTION__, __LINE__); } result = 0; } else if (result == CMD_COMPLETE) { @@ -1190,19 +1190,21 @@ isp_taction(qact_e action, void *arg) { info_t *ip = arg; isp = ip->i_identity; - if (ip->i_type == I_FC) { + if (ip->i_channel >= isp->isp_nchan) { + ip->i_error = -ENODEV; + } else if (IS_FC(isp)) { fcparam *fcp = FCPARAM(isp, ip->i_channel); + ip->i_type = I_FC; ip->i_id.fc.wwnn_nvram = fcp->isp_wwnn_nvram; ip->i_id.fc.wwpn_nvram = fcp->isp_wwpn_nvram; ip->i_id.fc.wwnn = fcp->isp_wwnn; ip->i_id.fc.wwpn = fcp->isp_wwpn; ip->i_error = 0; - } else if (ip->i_type == I_SPI) { + } else { sdparam *sdp = SDPARAM(isp, ip->i_channel); + ip->i_type = I_SPI; ip->i_id.spi.iid = sdp->isp_initiator_id; ip->i_error = 0; - } else { - ip->i_error = -EINVAL; } break; } @@ -1297,7 +1299,7 @@ isp_taction(qact_e action, void *arg) isp_prt(isp, ISP_LOGTDEBUG1, "freeing tmd %p [%llx]", tmd, tmd->cd_tagval); if (tmd->cd_lflags & CDFL_RESRC_FILL) { if (isp_target_putback_atio(isp, tmd)) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __FUNCTION__, __LINE__); ISP_UNLK_SOFTC(isp); break; } @@ -1933,7 +1935,7 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep) isp_endcmd(isp, aep, SCSI_BUSY, 0); if (jiffies - isp->isp_osinfo.out_of_tmds > 30 * HZ) { isp_prt(isp, ISP_LOGERR, "out of TMDs too long: disabling port"); - ISP_THREAD_EVENT(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); } return; } @@ -2024,7 +2026,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) isp_endcmd(isp, aep, SCSI_BUSY, 0); if (jiffies - isp->isp_osinfo.out_of_tmds > 30 * HZ) { isp_prt(isp, ISP_LOGERR, "out of TMDs too long: disabling port"); - ISP_THREAD_EVENT(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); } return; } @@ -2119,7 +2121,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep) } else { tmd->cd_portid = PORT_NONE; isp_add_wwn_entry(isp, 0, tmd->cd_iid, tmd->cd_nphdl, PORT_NONE); - (void) ISP_THREAD_EVENT(isp, ISP_THREAD_FINDPORTID, tmd, 0, __FUNCTION__, __LINE__); + (void) isp_thread_event(isp, ISP_THREAD_FINDPORTID, tmd, 0, __FUNCTION__, __LINE__); } } } @@ -2219,7 +2221,7 @@ isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep) isp_endcmd(isp, aep, chan, SCSI_BUSY, 0); if (jiffies - isp->isp_osinfo.out_of_tmds > 30 * HZ) { isp_prt(isp, ISP_LOGERR, "out of TMDs too long: disabling port"); - ISP_THREAD_EVENT(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); } return; } @@ -2316,7 +2318,7 @@ isp_handle_platform_atio7(ispsoftc_t *isp, at7_entry_t *aep) CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); } else { isp_prt(isp, ISP_LOGTDEBUG0, "[0x%llx] asking taskthread to find iid of initiator", (unsigned long long) tmd->cd_tagval); - if (ISP_THREAD_EVENT(isp, ISP_THREAD_FINDIID, tmd, 0, __FUNCTION__, __LINE__)) { + if (isp_thread_event(isp, ISP_THREAD_FINDIID, tmd, 0, __FUNCTION__, __LINE__)) { isp_endcmd(isp, aep, nphdl, chan, SCSI_BUSY, 0); MEMZERO(tmd, TMD_SIZE); if (isp->isp_osinfo.tfreelist) { @@ -2487,7 +2489,7 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg) continue; } } - ISP_THREAD_EVENT(isp, ISP_THREAD_LOGOUT, &FCPARAM(isp, tmd->cd_channel)->portdb[i], 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_LOGOUT, &FCPARAM(isp, tmd->cd_channel)->portdb[i], 0, __FUNCTION__, __LINE__); break; } } @@ -3119,7 +3121,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) tgt = lp->ini_map_idx - 1; isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, isp_class3_roles[lp->roles], "arrived at", tgt, lp->node_wwn, lp->port_wwn); arg = tgt | (bus << 16); - ISP_THREAD_EVENT(isp, ISP_THREAD_SCSI_SCAN, (void *)arg, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_SCSI_SCAN, (void *)arg, 0, __FUNCTION__, __LINE__); } else { isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, isp_class3_roles[lp->roles], "arrived", lp->node_wwn, lp->port_wwn); } @@ -3167,7 +3169,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) lp->ini_map_idx = 0; isp_prt(isp, ISP_LOGCONFIG, prom2, bus, lp->portid, lp->handle, isp_class3_roles[lp->roles], "departed", tgt, lp->node_wwn, lp->port_wwn); arg = tgt | (bus << 16) | (1 << 31); - ISP_THREAD_EVENT(isp, ISP_THREAD_SCSI_SCAN, (void *)arg, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_SCSI_SCAN, (void *)arg, 0, __FUNCTION__, __LINE__); } else if (lp->reserved == 0) { isp_prt(isp, ISP_LOGCONFIG, prom0, bus, lp->portid, lp->handle, isp_class3_roles[lp->roles], "departed", lp->node_wwn, lp->port_wwn); } @@ -3201,7 +3203,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) isp_prt(isp, ISP_LOGINFO, "Chan %d Other Change Notify occurred", bus); } if (isp->isp_state >= ISP_INITSTATE) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, fcp, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, fcp, 0, __FUNCTION__, __LINE__); } break; } @@ -3411,6 +3413,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) ins->notify.nt_ncode = NT_ABORT_TASK; ins->notify.nt_need_ack = 1; ins->notify.nt_channel = chan; + ins->notify.nt_tmd = NULL; /* * Find the command if possible and mark it aborted and needing cleanup */ @@ -3420,6 +3423,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) if (ins->notify.nt_tagval == tmd->cd_tagval && ins->notify.nt_channel == tmd->cd_channel) { isp_prt(isp, ISP_LOGTINFO, "[0x%llx] marked as aborted", (unsigned long long) tmd->cd_tagval); tmd->cd_lflags |= CDFL_ABORTED|CDFL_NEED_CLNUP; + ins->notify.nt_tmd = tmd; break; } } @@ -3717,7 +3721,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) ISP_DATA(isp, mbox6)->blocked = 1; ISP_RESET0(isp); isp_shutdown(isp); - ISP_THREAD_EVENT(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_REINIT, NULL, 0, __FUNCTION__, __LINE__); break; } case ISPASYNC_FW_RESTARTED: @@ -3725,7 +3729,7 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, ...) if (IS_FC(isp)) { int i; for (i = 0; i < isp->isp_nchan; i++) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, i), 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, FCPARAM(isp, i), 0, __FUNCTION__, __LINE__); } } break; @@ -3913,7 +3917,7 @@ isplinux_timer(unsigned long arg) fcparam *fcp = FCPARAM(isp, i); if (fcp->role != ISP_ROLE_NONE && ISP_DATA(isp, i)->fcrswdog && ISP_DATA(isp, i)->deadloop == 0) { ISP_DATA(isp, i)->fcrswdog = 1; - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_RESCAN, fcp, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FC_RESCAN, fcp, 0, __FUNCTION__, __LINE__); } } } @@ -3931,9 +3935,9 @@ isplinux_timer(unsigned long arg) isp->isp_osinfo.waiting_t = wt->cd_next; wt->cd_next = NULL; if (wt->cd_lastoff == 0) { - ISP_THREAD_EVENT(isp, ISP_THREAD_FINDIID, wt, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_FINDIID, wt, 0, __FUNCTION__, __LINE__); } else { - ISP_THREAD_EVENT(isp, ISP_THREAD_RESTART_AT7, wt, 0, __FUNCTION__, __LINE__); + isp_thread_event(isp, ISP_THREAD_RESTART_AT7, wt, 0, __FUNCTION__, __LINE__); } } } @@ -4172,7 +4176,7 @@ isp_parse_wwnarg(ispsoftc_t *isp, int chan, char *wwns) int isplinux_common_init(ispsoftc_t *isp) { - int retval, chan; + int retval, chan, i; unsigned long flags; if (isp_nofwreload & (1 << isp->isp_unit)) { @@ -4250,7 +4254,17 @@ isplinux_common_init(ispsoftc_t *isp) ISP_TLOCK_INIT(isp); sema_init(&isp->mbox_sem, 1); sema_init(&isp->mbox_c_sem, 0); - sema_init(&isp->fcs_sem, 1); + + init_waitqueue_head(&isp->isp_osinfo.trq); + for (i = 0; i < MAX_THREAD_ACTION; i++) { + init_waitqueue_head(&isp->isp_osinfo.t_actions[i].thread_waiter); + if (i < MAX_THREAD_ACTION - 1) { + isp->isp_osinfo.t_actions[i].next = &isp->isp_osinfo.t_actions[i+1]; + } + } + isp->isp_osinfo.t_busy = NULL; + isp->isp_osinfo.t_busy_t = NULL; + isp->isp_osinfo.t_free = isp->isp_osinfo.t_actions; #ifdef ISP_TARGET_MODE /* @@ -4264,7 +4278,14 @@ isplinux_common_init(ispsoftc_t *isp) * Start watchdog timer, create FC handler thread and reinit hardware. */ if (IS_FC(isp)) { - ISP_THREAD_EXEC(isp); + isp->isp_osinfo.thread_task = kthread_run(isp_task_thread, isp, "isp%d_fc", isp->isp_unit); + if (IS_ERR(isp->isp_osinfo.thread_task)) { + isp_prt(isp, ISP_LOGERR, "unable to start FC task thread"); +#ifdef ISP_TARGET_MODE + isp_deinit_target(isp); +#endif + isp->isp_osinfo.thread_task = NULL; + } } ISP_LOCK_SOFTC(isp); @@ -4278,14 +4299,14 @@ isplinux_common_init(ispsoftc_t *isp) retval = isplinux_reinit(isp); if (retval) { - isp_prt(isp, ISP_LOGWARN, "failed to init HBA port (%d): skipping it", retval); + isp_prt(isp, ISP_LOGERR, "failed to init HBA port (%d): skipping it", retval); del_timer(&isp->isp_osinfo.timer); isp->dogactive = 0; ISP_UNLK_SOFTC(isp); #ifdef ISP_TARGET_MODE isp_deinit_target(isp); #endif - ISP_THREAD_KILL(isp); + kthread_stop(isp->isp_osinfo.thread_task); return (-1); } ISP_UNLK_SOFTC(isp); @@ -4391,23 +4412,14 @@ isplinux_reinit(ispsoftc_t *isp) int isp_thread_event(ispsoftc_t *isp, int action, void *a, int dowait, const char *file, const int line) { - DECLARE_MUTEX_LOCKED(sem); - int i; isp_thread_action_t *tap; unsigned long flags; spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); - if (isp->isp_osinfo.task_active == 0) { - spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); - isp_prt(isp, ISP_LOGERR, "thread event %d from %s:%d sent when thread gone", action, file, line); - return (-1); - } - /* * Check for duplicates */ - for (i = 0; i < isp->isp_osinfo.nt_actions; i++) { - tap = &isp->isp_osinfo.t_actions[i]; + for (tap = isp->isp_osinfo.t_busy; tap != NULL; tap = tap->next) { if (tap->thread_action == action && tap->arg == a && dowait == 0) { tap->count++; spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); @@ -4415,29 +4427,49 @@ isp_thread_event(ispsoftc_t *isp, int action, void *a, int dowait, const char *f return (0); } } - if (isp->isp_osinfo.nt_actions >= MAX_THREAD_ACTION) { + if ((tap = isp->isp_osinfo.t_free) == NULL) { spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); isp_prt(isp, ISP_LOGERR, "thread event %d from %s:%d sent with thread overflow", action, file, line); return (-1); } - tap = &isp->isp_osinfo.t_actions[isp->isp_osinfo.nt_actions++]; + isp->isp_osinfo.t_free = tap->next; + tap->next = NULL; tap->count = 1; tap->thread_action = action; tap->arg = a; + tap->done = 0; if (dowait) { - tap->thread_waiter = &sem; + tap->waiting = 1; + isp_prt(isp, ISP_LOGDEBUG0, "action %d sending from %s:%d and now waiting", action, file, line); } else { - tap->thread_waiter = 0; + tap->waiting = 0; + isp_prt(isp, ISP_LOGDEBUG0, "action %d from %s:%d sending", action, file, line); } - ISP_THREAD_WAKE(isp); - if (dowait) { - isp_prt(isp, ISP_LOGDEBUG1, "action %d sent from %s:%d and now waiting", action, file, line); - spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); - down(&sem); - isp_prt(isp, ISP_LOGDEBUG1, "action %d done", action); + if (isp->isp_osinfo.t_busy) { + isp->isp_osinfo.t_busy_t->next = tap; } else { + isp->isp_osinfo.t_busy = tap; + } + isp->isp_osinfo.t_busy_t = tap; + spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); + wake_up(&isp->isp_osinfo.trq); + if (dowait) { + while (wait_event_interruptible_timeout(tap->thread_waiter, (tap->done == 1), 100)) { + if (kthread_should_stop()) { + break; + } + } + if (kthread_should_stop()) { + tap->waiting = 0; + return (-1); + } + spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); + tap->waiting = 0; + tap->next = isp->isp_osinfo.t_free; + isp->isp_osinfo.t_free = tap; + tap->next = NULL; spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); - isp_prt(isp, ISP_LOGDEBUG1, "action %d from %s:%d sent", action, file, line); + isp_prt(isp, ISP_LOGDEBUG0, "action %d from %s:%d done", action, file, line); } return (0); } @@ -4446,372 +4478,362 @@ static int isp_task_thread(void *arg) { ispsoftc_t *isp = arg; + isp_thread_action_t *tap; unsigned long flags; - int action, nactions, i; - isp_thread_action_t curactions[MAX_THREAD_ACTION]; + int i; - lock_kernel(); - daemonize("%s_thrd%d", ISP_NAME, isp->isp_unit); - unlock_kernel(); - siginitsetinv(¤t->blocked, 0); - ISP_THREAD_IACK(isp); + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread starting"); - - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread starting"); - - for (;;) { - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread sleeping"); - ISP_THREAD_WAIT(isp); - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread running"); - spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); - if (signal_pending(current)) { - isp_prt(isp, ISP_LOGALL, "%s received signal (%d)", current->comm, signal_pending(current)); - flush_signals(current); - if (isp->isp_osinfo.task_active) { - spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); - continue; - } + while (!kthread_should_stop()) { + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread sleeping"); + if (wait_event_interruptible(isp->isp_osinfo.trq, (isp->isp_osinfo.t_busy || kthread_should_stop()))) { + continue; } - if (isp->isp_osinfo.task_active == 0) { - spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread running"); + if (kthread_should_stop()) { break; } - nactions = isp->isp_osinfo.nt_actions; - isp->isp_osinfo.nt_actions = 0; - for (action = 0; action < nactions; action++) { - curactions[action] = isp->isp_osinfo.t_actions[action]; + spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); + if ((tap = isp->isp_osinfo.t_busy) != NULL) { + if ((isp->isp_osinfo.t_busy = tap->next) == NULL) { + isp->isp_osinfo.t_busy_t = NULL; + } } spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); - - for (action = 0; action < nactions; action++) { - isp_thread_action_t *tap = &curactions[action]; - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread[%d]: action %d (%p)", action, tap->thread_action, tap->thread_waiter); - switch (tap->thread_action) { - case ISP_THREAD_NIL: - break; - case ISP_THREAD_SCSI_SCAN: - { + if (tap == NULL) { + continue; + } + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread: action %d", tap->thread_action); + switch (tap->thread_action) { + case ISP_THREAD_NIL: + break; + case ISP_THREAD_SCSI_SCAN: + { /* this gets pegged in isplinux_queuecommand, even for async scanning */ #if 0 - unsigned long arg = (unsigned long) tap->arg; - int tgt, chan, rescan; - tgt = arg & 0xffff; - chan = (arg >> 16) & 0xff; - rescan = (arg >> 31) & 1; - scsi_scan_target(&isp->isp_osinfo.host->shost_gendev, chan, tgt, SCAN_WILD_CARD, rescan); + unsigned long arg = (unsigned long) tap->arg; + int tgt, chan, rescan; + tgt = arg & 0xffff; + chan = (arg >> 16) & 0xff; + rescan = (arg >> 31) & 1; + scsi_scan_target(&isp->isp_osinfo.host->shost_gendev, chan, tgt, SCAN_WILD_CARD, rescan); #endif - break; - } - case ISP_THREAD_REINIT: - ISP_LOCKU_SOFTC(isp); - if (isp->isp_dead) { - isp_prt(isp, ISP_LOGERR, "chip marked dead- not restarting"); - isp_shutdown(isp); - ISP_DISABLE_INTS(isp); - ISP_UNLKU_SOFTC(isp); - break; - } - isp_reinit(isp); - if (isp->isp_state == ISP_RUNSTATE) { - for (i = 0; i < isp->isp_nchan; i++) { - ISP_DATA(isp, i)->blocked = 0; - } - isp_async(isp, ISPASYNC_FW_RESTARTED); - } else { - isp_prt(isp, ISP_LOGERR, "unable to restart chip"); - } + break; + } + case ISP_THREAD_REINIT: + ISP_LOCKU_SOFTC(isp); + if (isp->isp_dead) { + isp_prt(isp, ISP_LOGERR, "chip marked dead- not restarting"); + isp_shutdown(isp); + ISP_DISABLE_INTS(isp); ISP_UNLKU_SOFTC(isp); break; - case ISP_THREAD_FC_RESCAN: - { - fcparam *fcp = tap->arg; - int chan = fcp - FCPARAM(isp, 0); + } + isp_reinit(isp); + if (isp->isp_state == ISP_RUNSTATE) { + for (i = 0; i < isp->isp_nchan; i++) { + ISP_DATA(isp, i)->blocked = 0; + } + isp_async(isp, ISPASYNC_FW_RESTARTED); + } else { + isp_prt(isp, ISP_LOGERR, "unable to restart chip"); + } + ISP_UNLKU_SOFTC(isp); + break; + case ISP_THREAD_FC_RESCAN: + { + fcparam *fcp = tap->arg; + int chan = fcp - FCPARAM(isp, 0); - fcp = FCPARAM(isp, chan); - ISP_LOCKU_SOFTC(isp); - ISP_DATA(isp, chan)->fcrswdog = 0; - if (isp_fc_runstate(isp, chan, 250000) == 0) { - ISP_DATA(isp, chan)->deadloop = 0; + fcp = FCPARAM(isp, chan); + ISP_LOCKU_SOFTC(isp); + ISP_DATA(isp, chan)->fcrswdog = 0; + if (isp_fc_runstate(isp, chan, 250000) == 0) { + ISP_DATA(isp, chan)->deadloop = 0; + ISP_DATA(isp, chan)->downcount = 0; + ISP_DATA(isp, chan)->blocked = 0; + isplinux_runwaitq(isp); + } else { + if (ISP_DATA(isp, chan)->downcount == 0) { + ISP_DATA(isp, chan)->downcount = jiffies; + } + /* + * Try again in a little while. + */ + if ((jiffies - ISP_DATA(isp, chan)->downcount) > (isp_deadloop_time * HZ)) { + fcp->loop_seen_once = 0; + ISP_DATA(isp, chan)->deadloop = 1; ISP_DATA(isp, chan)->downcount = 0; ISP_DATA(isp, chan)->blocked = 0; - isplinux_runwaitq(isp); + isp_prt(isp, ISP_LOGWARN, "Chan %d assuming loop is dead", chan); + isplinux_flushwaitq(isp); } else { - if (ISP_DATA(isp, chan)->downcount == 0) { - ISP_DATA(isp, chan)->downcount = jiffies; - } - /* - * Try again in a little while. - */ - if ((jiffies - ISP_DATA(isp, chan)->downcount) > (isp_deadloop_time * HZ)) { - fcp->loop_seen_once = 0; - ISP_DATA(isp, chan)->deadloop = 1; - ISP_DATA(isp, chan)->downcount = 0; - ISP_DATA(isp, chan)->blocked = 0; - isp_prt(isp, ISP_LOGWARN, "Chan %d assuming loop is dead", chan); - isplinux_flushwaitq(isp); - } else { - ISP_DATA(isp, chan)->fcrswdog = 1; - } + ISP_DATA(isp, chan)->fcrswdog = 1; } - ISP_UNLKU_SOFTC(isp); - break; } + ISP_UNLKU_SOFTC(isp); + break; + } #ifdef ISP_TARGET_MODE - case ISP_THREAD_LOGOUT: - { - mbreg_t mbs; - union { - isp_pdb_t pdb; - int id; - } u; - fcportdb_t *lp = tap->arg; + case ISP_THREAD_LOGOUT: + { + mbreg_t mbs; + union { + isp_pdb_t pdb; + int id; + } u; + fcportdb_t *lp = tap->arg; - ISP_LOCKU_SOFTC(isp); - if (lp->state != FC_PORTDB_STATE_VALID) { - isp_prt(isp, ISP_LOGALL, "target entry no longer valid"); - ISP_UNLKU_SOFTC(isp); - break; - } - MEMZERO(&u, sizeof (u)); - u.id = lp->handle; - isp_prt(isp, ISP_LOGALL, "Doing Port Logout repair for 0x%016llx@0x%x (loop id) %u", - lp->port_wwn, lp->portid, lp->handle); - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGOUT; - if (ISP_CAP_2KLOGIN(isp)) { - mbs.param[1] = lp->handle; - mbs.obits |= (1 << 10); - } else { - mbs.param[1] = lp->handle << 8; - } - mbs.logval = MBLOGNONE; - (void) isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "failed to get logout loop id %u", lp->handle); - lp->state = FC_PORTDB_STATE_PROBATIONAL; - ISP_UNLKU_SOFTC(isp); - break; - } - MEMZERO(&mbs, sizeof (mbs)); - mbs.param[0] = MBOX_FABRIC_LOGIN; - if (ISP_CAP_2KLOGIN(isp)) { - mbs.param[1] = lp->handle; - mbs.obits |= (1 << 10); - } else { - mbs.param[1] = lp->handle << 8; - } - mbs.param[2] = lp->portid >> 16; - mbs.param[3] = lp->portid & 0xffff; - (void) isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); - if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - isp_prt(isp, ISP_LOGERR, "failed to get login port id %x at loop id %u", lp->portid, lp->handle); - lp->state = FC_PORTDB_STATE_PROBATIONAL; - ISP_UNLKU_SOFTC(isp); - break; - } - lp->state = FC_PORTDB_STATE_VALID; + ISP_LOCKU_SOFTC(isp); + if (lp->state != FC_PORTDB_STATE_VALID) { + isp_prt(isp, ISP_LOGTINFO, "target mode entry no longer valid"); ISP_UNLKU_SOFTC(isp); break; } - case ISP_THREAD_FINDIID: - { - tmd_cmd_t *tmd = tap->arg; - fcportdb_t *lp = NULL; - uint64_t iid = INI_NONE; - uint16_t nphdl = NIL_HANDLE; + MEMZERO(&u, sizeof (u)); + u.id = lp->handle; + isp_prt(isp, ISP_LOGTINFO, "Doing Port Logout repair for 0x%016llx@0x%x (loop id) %u", + lp->port_wwn, lp->portid, lp->handle); + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGOUT; + if (ISP_CAP_2KLOGIN(isp)) { + mbs.param[1] = lp->handle; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = lp->handle << 8; + } + mbs.logval = MBLOGNONE; + (void) isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, "failed to get logout loop id %u", lp->handle); + lp->state = FC_PORTDB_STATE_PROBATIONAL; + ISP_UNLKU_SOFTC(isp); + break; + } + MEMZERO(&mbs, sizeof (mbs)); + mbs.param[0] = MBOX_FABRIC_LOGIN; + if (ISP_CAP_2KLOGIN(isp)) { + mbs.param[1] = lp->handle; + mbs.obits |= (1 << 10); + } else { + mbs.param[1] = lp->handle << 8; + } + mbs.param[2] = lp->portid >> 16; + mbs.param[3] = lp->portid & 0xffff; + (void) isp_control(isp, ISPCTL_RUN_MBOXCMD, &mbs); + if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { + isp_prt(isp, ISP_LOGERR, "failed to get login port id %x at loop id %u", lp->portid, lp->handle); + lp->state = FC_PORTDB_STATE_PROBATIONAL; + ISP_UNLKU_SOFTC(isp); + break; + } + lp->state = FC_PORTDB_STATE_VALID; + ISP_UNLKU_SOFTC(isp); + break; + } + case ISP_THREAD_FINDIID: + { + tmd_cmd_t *tmd = tap->arg; + fcportdb_t *lp = NULL; + uint64_t iid = INI_NONE; + uint16_t nphdl = NIL_HANDLE; - if (tmd->cd_lflags & CDFL_ABORTED) { - isp_prt(isp, ISP_LOGTINFO, "[%llx] asking thread to terminate because it was marked aborted", (unsigned long long) tmd->cd_tagval); - ISP_THREAD_EVENT(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); - break; - } - ISP_LOCKU_SOFTC(isp); - if (isp_find_pdb_by_sid(isp, tmd->cd_channel, tmd->cd_portid, &lp)) { - if (!VALID_INI(lp->port_wwn)) { - if (lp->handle == NIL_HANDLE) { - /* - * Ooops- all we have is the port id. - */ - uint16_t nphdl, max; - isp_pdb_t pdb; + if (tmd->cd_lflags & CDFL_ABORTED) { + isp_prt(isp, ISP_LOGTINFO, "[%llx] asking thread to terminate because it was marked aborted", (unsigned long long) tmd->cd_tagval); + isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); + break; + } + ISP_LOCKU_SOFTC(isp); + if (isp_find_pdb_by_sid(isp, tmd->cd_channel, tmd->cd_portid, &lp)) { + if (!VALID_INI(lp->port_wwn)) { + if (lp->handle == NIL_HANDLE) { + /* + * Ooops- all we have is the port id. + */ + uint16_t nphdl, max; + isp_pdb_t pdb; - if (IS_24XX(isp)) { - max = NPH_MAX_2K; - } else { - max = NPH_MAX; + if (IS_24XX(isp)) { + max = NPH_MAX_2K; + } else { + max = NPH_MAX; + } + for (nphdl = 0; nphdl != max; nphdl++) { + if (isp_control(isp, ISPCTL_GET_PDB, tmd->cd_channel, nphdl, &pdb)) { + continue; } - for (nphdl = 0; nphdl != max; nphdl++) { - if (isp_control(isp, ISPCTL_GET_PDB, tmd->cd_channel, nphdl, &pdb)) { - continue; - } - isp_prt(isp, ISP_LOGTINFO, "%s: nphdl 0x%04x has portid 0x%06x", __FUNCTION__, nphdl, pdb.portid); - if (pdb.portid == tmd->cd_portid) { - lp->handle = nphdl; - break; - } - } - if (nphdl == max) { - ISP_UNLKU_SOFTC(isp); - isp_prt(isp, ISP_LOGTINFO, "[0x%llx] asking thread to terminate cmd [0x%02x] because because we can't find the N-Port handle", tmd->cd_tagval, tmd->cd_cdb[0] & 0xff); - isp_tgt_dump_pdb(isp, tmd->cd_channel); - ISP_THREAD_EVENT(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); + isp_prt(isp, ISP_LOGTINFO, "%s: nphdl 0x%04x has portid 0x%06x", __FUNCTION__, nphdl, pdb.portid); + if (pdb.portid == tmd->cd_portid) { + lp->handle = nphdl; break; } } - if (isp_control(isp, ISPCTL_GET_NAMES, tmd->cd_channel, lp->handle, NULL, &lp->port_wwn) == 0) { - nphdl = lp->handle; - iid = lp->port_wwn; - } else { - isp_prt(isp, ISP_LOGALL, "%s: Chan %d [0x%llx] failed to get name for handle 0x%02x for portid 0x%06x", __FUNCTION__, tmd->cd_channel, tmd->cd_tagval, lp->handle, tmd->cd_portid); + if (nphdl == max) { + ISP_UNLKU_SOFTC(isp); + isp_prt(isp, ISP_LOGTINFO, "[0x%llx] asking thread to terminate cmd [0x%02x] because because we can't find the N-Port handle", tmd->cd_tagval, tmd->cd_cdb[0] & 0xff); + isp_tgt_dump_pdb(isp, tmd->cd_channel); + isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); + break; } - } else { + } + if (isp_control(isp, ISPCTL_GET_NAMES, tmd->cd_channel, lp->handle, NULL, &lp->port_wwn) == 0) { nphdl = lp->handle; iid = lp->port_wwn; + } else { + isp_prt(isp, ISP_LOGALL, "%s: Chan %d [0x%llx] failed to get name for handle 0x%02x for portid 0x%06x", __FUNCTION__, tmd->cd_channel, tmd->cd_tagval, lp->handle, tmd->cd_portid); } } else { - /* - * If it's no longer in the port database, then some event between the receipt of the command and now - * has cleared it out. The command is probably already dead due to initiator port logout. - */ - ISP_UNLKU_SOFTC(isp); - isp_prt(isp, ISP_LOGTINFO, "[0x%llx] asking thread to terminate cmd [0x%02x] because PortID 0x%06x no longer in port database", tmd->cd_tagval, tmd->cd_cdb[0] & 0xff, tmd->cd_portid); - isp_tgt_dump_pdb(isp, tmd->cd_channel); - ISP_THREAD_EVENT(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); - break; + nphdl = lp->handle; + iid = lp->port_wwn; } - if (iid == INI_NONE) { - isp_prt(isp, ISP_LOGTDEBUG0, "%s: [0x%llx] trying to find IID again...", __FUNCTION__, tmd->cd_tagval); - tmd->cd_next = isp->isp_osinfo.waiting_t; - isp->isp_osinfo.waiting_t = tmd; - tmd->cd_lastoff = 0; - ISP_UNLKU_SOFTC(isp); - break; + } else { + /* + * If it's no longer in the port database, then some event between the receipt of the command and now + * has cleared it out. The command is probably already dead due to initiator port logout. + */ + ISP_UNLKU_SOFTC(isp); + isp_prt(isp, ISP_LOGTINFO, "[0x%llx] asking thread to terminate cmd [0x%02x] because PortID 0x%06x no longer in port database", tmd->cd_tagval, tmd->cd_cdb[0] & 0xff, tmd->cd_portid); + isp_tgt_dump_pdb(isp, tmd->cd_channel); + isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); + break; + } + if (iid == INI_NONE) { + isp_prt(isp, ISP_LOGTDEBUG0, "%s: [0x%llx] trying to find IID again...", __FUNCTION__, tmd->cd_tagval); + tmd->cd_next = isp->isp_osinfo.waiting_t; + isp->isp_osinfo.waiting_t = tmd; + tmd->cd_lastoff = 0; + ISP_UNLKU_SOFTC(isp); + break; + } + tmd->cd_tgt = FCPARAM(isp, tmd->cd_channel)->isp_wwpn; + tmd->cd_nphdl = nphdl; + tmd->cd_iid = iid; + isp_prt(isp, ISP_LOGTINFO, "%s: [0x%llx] Chan %d found initiator @ IID 0x%016llx N-Port Handle 0x%02x Port ID 0x%06x", __FUNCTION__, + tmd->cd_tagval, tmd->cd_channel, (unsigned long long)tmd->cd_iid, tmd->cd_nphdl, tmd->cd_portid); + CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); + ISP_UNLKU_SOFTC(isp); + isp_tgt_tq(isp); + break; + } + case ISP_THREAD_FINDPORTID: + { + tmd_cmd_t *tmd = tap->arg; + fcportdb_t *lp; + + ISP_LOCKU_SOFTC(isp); + if (isp_find_pdb_by_loopid(isp, tmd->cd_channel, tmd->cd_nphdl, &lp)) { + if (lp->portid == PORT_NONE) { + isp_pdb_t pdb; + if (isp_control(isp, ISPCTL_GET_PDB, tmd->cd_channel, tmd->cd_nphdl, &pdb) == 0) { + tmd->cd_portid = lp->portid = pdb.portid; + } + } else { + tmd->cd_portid = lp->portid; } - tmd->cd_tgt = FCPARAM(isp, tmd->cd_channel)->isp_wwpn; - tmd->cd_nphdl = nphdl; - tmd->cd_iid = iid; + } else { + isp_prt(isp, ISP_LOGTINFO, "[0x%llx] not in port database at all any more", tmd->cd_tagval); + } + if (tmd->cd_portid != PORT_NONE) { isp_prt(isp, ISP_LOGTINFO, "%s: [0x%llx] Chan %d found initiator @ IID 0x%016llx N-Port Handle 0x%02x Port ID 0x%06x", __FUNCTION__, tmd->cd_tagval, tmd->cd_channel, (unsigned long long)tmd->cd_iid, tmd->cd_nphdl, tmd->cd_portid); + } + CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); + ISP_UNLKU_SOFTC(isp); + isp_tgt_tq(isp); + break; + } + case ISP_THREAD_TERMINATE: + { + fcportdb_t *lp; + tmd_cmd_t *tmd = tap->arg; + + ISP_LOCKU_SOFTC(isp); + if (isp_find_pdb_by_sid(isp, tmd->cd_channel, tmd->cd_portid, &lp)) { + tmd->cd_iid = lp->port_wwn; + tmd->cd_nphdl = lp->handle; CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); ISP_UNLKU_SOFTC(isp); isp_tgt_tq(isp); + isp_prt(isp, ISP_LOGINFO, "Chan %d [%llx] reprieved", (int) AT2_GET_BUS(tmd->cd_tagval), (unsigned long long) tmd->cd_tagval); break; } - case ISP_THREAD_FINDPORTID: - { - tmd_cmd_t *tmd = tap->arg; - fcportdb_t *lp; - ISP_LOCKU_SOFTC(isp); - if (isp_find_pdb_by_loopid(isp, tmd->cd_channel, tmd->cd_nphdl, &lp)) { - if (lp->portid == PORT_NONE) { - isp_pdb_t pdb; - if (isp_control(isp, ISPCTL_GET_PDB, tmd->cd_channel, tmd->cd_nphdl, &pdb) == 0) { - tmd->cd_portid = lp->portid = pdb.portid; - } - } else { - tmd->cd_portid = lp->portid; - } - } else { - isp_prt(isp, ISP_LOGTINFO, "[0x%llx] not in port database at all any more", tmd->cd_tagval); - } - if (tmd->cd_portid != PORT_NONE) { - isp_prt(isp, ISP_LOGTINFO, "%s: [0x%llx] Chan %d found initiator @ IID 0x%016llx N-Port Handle 0x%02x Port ID 0x%06x", __FUNCTION__, - tmd->cd_tagval, tmd->cd_channel, (unsigned long long)tmd->cd_iid, tmd->cd_nphdl, tmd->cd_portid); - } - CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); + isp_prt(isp, ISP_LOGTINFO, "%s now terminating [%llx] from 0x%06x", __FUNCTION__, (unsigned long long) tmd->cd_tagval, tmd->cd_portid); + if (isp_terminate_cmd(isp, tmd)) { ISP_UNLKU_SOFTC(isp); - isp_tgt_tq(isp); + isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); break; } - case ISP_THREAD_TERMINATE: - { - fcportdb_t *lp; - tmd_cmd_t *tmd = tap->arg; - - ISP_LOCKU_SOFTC(isp); - if (isp_find_pdb_by_sid(isp, tmd->cd_channel, tmd->cd_portid, &lp)) { - tmd->cd_iid = lp->port_wwn; - tmd->cd_nphdl = lp->handle; - CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START); - ISP_UNLKU_SOFTC(isp); - isp_tgt_tq(isp); - isp_prt(isp, ISP_LOGINFO, "Chan %d [%llx] reprieved", (int) AT2_GET_BUS(tmd->cd_tagval), (unsigned long long) tmd->cd_tagval); - break; - } - - isp_prt(isp, ISP_LOGTINFO, "%s now terminating [%llx] from 0x%06x", __FUNCTION__, (unsigned long long) tmd->cd_tagval, tmd->cd_portid); - if (isp_terminate_cmd(isp, tmd)) { - ISP_UNLKU_SOFTC(isp); - ISP_THREAD_EVENT(isp, ISP_THREAD_TERMINATE, tmd, 0, __FUNCTION__, __LINE__); - break; - } - tmd->cd_next = NULL; - if (isp->isp_osinfo.tfreelist) { - isp->isp_osinfo.bfreelist->cd_next = tmd; - } else { - isp->isp_osinfo.tfreelist = tmd; - } - isp->isp_osinfo.bfreelist = tmd; + tmd->cd_next = NULL; + if (isp->isp_osinfo.tfreelist) { + isp->isp_osinfo.bfreelist->cd_next = tmd; + } else { + isp->isp_osinfo.tfreelist = tmd; + } + isp->isp_osinfo.bfreelist = tmd; + ISP_UNLKU_SOFTC(isp); + break; + } + case ISP_THREAD_RESTART_AT7: + { + at7_entry_t at; + tmd_cmd_t *tmd = tap->arg; + MEMCPY(&at, tmd, sizeof (at7_entry_t)); + ISP_LOCKU_SOFTC(isp); + MEMZERO(tmd, sizeof (tmd_cmd_t)); + if (isp->isp_osinfo.tfreelist) { + isp->isp_osinfo.bfreelist->cd_next = tmd; + } else { + isp->isp_osinfo.tfreelist = tmd; + } + isp->isp_osinfo.bfreelist = tmd; /* remember to move the list tail pointer */ + isp_handle_platform_atio7(isp, &at); + ISP_UNLKU_SOFTC(isp); + break; + } + case ISP_THREAD_FC_PUTBACK: + { + tmd_cmd_t *tmd = tap->arg; + ISP_LOCKU_SOFTC(isp); + isp_prt(isp, ISP_LOGTINFO, "%s: [%llx] calling putback", __FUNCTION__, tmd->cd_tagval); + if (isp_target_putback_atio(isp, tmd)) { ISP_UNLKU_SOFTC(isp); + isp_thread_event(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __FUNCTION__, __LINE__); break; } - case ISP_THREAD_RESTART_AT7: - { - at7_entry_t at; - tmd_cmd_t *tmd = tap->arg; - MEMCPY(&at, tmd, sizeof (at7_entry_t)); - ISP_LOCKU_SOFTC(isp); - MEMZERO(tmd, sizeof (tmd_cmd_t)); - if (isp->isp_osinfo.tfreelist) { - isp->isp_osinfo.bfreelist->cd_next = tmd; - } else { - isp->isp_osinfo.tfreelist = tmd; - } - isp->isp_osinfo.bfreelist = tmd; /* remember to move the list tail pointer */ - isp_handle_platform_atio7(isp, &at); - ISP_UNLKU_SOFTC(isp); - break; + if (tmd->cd_lflags & CDFL_NEED_CLNUP) { + tmd->cd_lflags ^= CDFL_NEED_CLNUP; + isp_prt(isp, ISP_LOGTINFO, "Terminating %llx too", (unsigned long long) tmd->cd_tagval); + (void) isp_terminate_cmd(isp, tmd); } - case ISP_THREAD_FC_PUTBACK: - { - tmd_cmd_t *tmd = tap->arg; - ISP_LOCKU_SOFTC(isp); - isp_prt(isp, ISP_LOGTINFO, "%s: [%llx] calling putback", __FUNCTION__, tmd->cd_tagval); - if (isp_target_putback_atio(isp, tmd)) { - ISP_UNLKU_SOFTC(isp); - ISP_THREAD_EVENT(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __FUNCTION__, __LINE__); - break; - } - if (tmd->cd_lflags & CDFL_NEED_CLNUP) { - tmd->cd_lflags ^= CDFL_NEED_CLNUP; - isp_prt(isp, ISP_LOGTINFO, "Terminating %llx too", (unsigned long long) tmd->cd_tagval); - (void) isp_terminate_cmd(isp, tmd); - } - MEMZERO(tmd, sizeof (tmd_cmd_t)); - if (isp->isp_osinfo.tfreelist) { - isp->isp_osinfo.bfreelist->cd_next = tmd; - } else { - isp->isp_osinfo.tfreelist = tmd; - } - isp->isp_osinfo.bfreelist = tmd; /* remember to move the list tail pointer */ - isp_prt(isp, ISP_LOGTDEBUG0, "DONE freeing tmd %p [%llx] after retry", tmd, tmd->cd_tagval); - ISP_UNLKU_SOFTC(isp); - break; + MEMZERO(tmd, sizeof (tmd_cmd_t)); + if (isp->isp_osinfo.tfreelist) { + isp->isp_osinfo.bfreelist->cd_next = tmd; + } else { + isp->isp_osinfo.tfreelist = tmd; } + isp->isp_osinfo.bfreelist = tmd; /* remember to move the list tail pointer */ + isp_prt(isp, ISP_LOGTDEBUG0, "DONE freeing tmd %p [%llx] after retry", tmd, tmd->cd_tagval); + ISP_UNLKU_SOFTC(isp); + break; + } #endif - default: - break; - } - - if (tap->thread_waiter) { - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread signalling %p", tap->thread_waiter); - up(tap->thread_waiter); - } + default: + break; + } + tap->done = 0; + if (tap->waiting) { + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread signalling"); + tap->waiting = 0; + wake_up(&tap->thread_waiter); + } else { + spin_lock_irqsave(&isp->isp_osinfo.tlock, flags); + tap->next = isp->isp_osinfo.t_free; + isp->isp_osinfo.t_free = tap; + spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags); } } - isp_prt(isp, ISP_LOGDEBUG1, "isp_task_thread exiting"); - ISP_THREAD_XACK(isp); + isp_prt(isp, ISP_LOGDEBUG0, "isp_task_thread exiting"); return (0); } diff --git a/qla_isp/linux/isp_linux.h b/qla_isp/linux/isp_linux.h index f07142006..ac6d3b313 100644 --- a/qla_isp/linux/isp_linux.h +++ b/qla_isp/linux/isp_linux.h @@ -1,4 +1,4 @@ -/* $Id: isp_linux.h,v 1.160 2008/03/15 18:16:47 mjacob Exp $ */ +/* $Id: isp_linux.h,v 1.161 2008/04/15 22:41:03 mjacob Exp $ */ /* * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -94,6 +94,7 @@ #include #include #include +#include #include #include #include @@ -264,7 +265,9 @@ typedef struct { #define ISP_CT_TIMEOUT 120 #endif /* ISP_TARGET_MODE */ -typedef struct { +typedef struct isp_thread_action isp_thread_action_t; +struct isp_thread_action { + isp_thread_action_t *next; enum { ISP_THREAD_NIL=1, ISP_THREAD_FC_RESCAN, @@ -279,9 +282,12 @@ typedef struct { ISP_THREAD_SCSI_SCAN, } thread_action; void * arg; - struct semaphore * thread_waiter; - int count; -} isp_thread_action_t; + wait_queue_head_t thread_waiter; + uint32_t + waiting : 1, + done : 1, + count : 30; +}; #define MAX_THREAD_ACTION 128 #define MAX_FC_CHAN 128 @@ -289,6 +295,7 @@ typedef struct { struct isposinfo { struct Scsi_Host * host; + unsigned int device_id; u32 mcorig; /* original maxcmds */ void *device; /* hardware device structure */ Scsi_Cmnd *wqnext, *wqtail; @@ -309,13 +316,12 @@ struct isposinfo { struct timer_list mbtimer; struct semaphore mbox_sem; struct semaphore mbox_c_sem; - struct semaphore fcs_sem; spinlock_t slock; unsigned volatile int : 20, dogcnt : 5, isopen : 1, - task_active : 1, + : 1, dogactive : 1, mboxcmd_done : 1, mbox_waiting : 1, @@ -323,12 +329,12 @@ struct isposinfo { intsok : 1; u16 frame_size; u16 exec_throttle; + struct task_struct *thread_task; wait_queue_head_t trq; - struct semaphore tcs; spinlock_t tlock; - unsigned int nt_actions; - unsigned int device_id; isp_thread_action_t t_actions[MAX_THREAD_ACTION]; + isp_thread_action_t *t_free; + isp_thread_action_t *t_busy, *t_busy_t; #ifdef ISP_TARGET_MODE u32 isget : 16, rstatus : 8, @@ -364,47 +370,12 @@ struct isposinfo { #define dogactive isp_osinfo.dogactive #define mbox_sem isp_osinfo.mbox_sem #define mbox_c_sem isp_osinfo.mbox_c_sem -#define fcs_sem isp_osinfo.fcs_sem #define mbintsok isp_osinfo.mbintsok #define intsok isp_osinfo.intsok #define mbox_waiting isp_osinfo.mbox_waiting #define mboxcmd_done isp_osinfo.mboxcmd_done #define isp_isopen isp_osinfo.isopen -#define ISP_THREAD_EXEC(x) \ - sema_init(&(x)->isp_osinfo.tcs, 0); \ - kernel_thread(isp_task_thread, (x), 0); \ - down(&isp->isp_osinfo.tcs) - -#define ISP_THREAD_IACK(x) \ - init_waitqueue_head(&(x)->isp_osinfo.trq); \ - (x)->isp_osinfo.task_active = 1; \ - up(&(x)->isp_osinfo.tcs) - -#define ISP_THREAD_WAIT(x) \ - wait_event_interruptible((x)->isp_osinfo.trq, (((x)->isp_osinfo.task_active == 0) || ((x)->isp_osinfo.nt_actions != 0))) - -#define ISP_THREAD_EVENT isp_thread_event - -#define ISP_THREAD_WAKE(x) wake_up_all(&(x)->isp_osinfo.trq) - -#define ISP_THREAD_KILL(x) \ - { \ - unsigned long _fl; \ - spin_lock_irqsave(&(x)->isp_osinfo.tlock, _fl); \ - if ((x)->isp_osinfo.task_active) { \ - sema_init(&(x)->isp_osinfo.tcs, 0); \ - (x)->isp_osinfo.task_active = 0; \ - wake_up_all(&(x)->isp_osinfo.trq); \ - spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \ - down(&(x)->isp_osinfo.tcs); \ - } else { \ - spin_unlock_irqrestore(&(x)->isp_osinfo.tlock, _fl); \ - } \ - } - -#define ISP_THREAD_XACK(x) up(&(x)->isp_osinfo.tcs) - /* * Locking macros... */ @@ -467,7 +438,7 @@ struct isposinfo { # endif #endif -#define MBOX_ACQUIRE mbox_acquire +#define MBOX_ACQUIRE(isp) down_trylock(&isp->mbox_sem) #define MBOX_WAIT_COMPLETE mbox_wait_complete #define MBOX_NOTIFY_COMPLETE(isp) \ if (isp->mbox_waiting) { \ @@ -668,7 +639,6 @@ static inline void _isp_usec_delay(unsigned int); static inline unsigned long _usec_to_jiffies(unsigned int); static inline unsigned long _jiffies_to_usec(unsigned long); static inline int isplinux_tagtype(Scsi_Cmnd *); -static inline int mbox_acquire(ispsoftc_t *); static inline void mbox_wait_complete(ispsoftc_t *, mbreg_t *); int isplinux_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); @@ -824,25 +794,6 @@ isplinux_tagtype(Scsi_Cmnd *Cmnd) } } -static inline int -mbox_acquire(ispsoftc_t *isp) -{ - /* - * Try and acquire semaphore the easy way first- - * with our lock already held.k - */ - if (down_trylock(&isp->mbox_sem)) { - if (ISP_ATOMIC()) { - isp_prt(isp, ISP_LOGERR, "cannot acquire MBOX sema"); - return (1); - } - ISP_DROP_LK_SOFTC(isp); - down(&isp->mbox_sem); - ISP_IGET_LK_SOFTC(isp); - } - return (0); -} - static inline void mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp) { diff --git a/qla_isp/linux/isp_pci.c b/qla_isp/linux/isp_pci.c index cf30eac63..0aaf9e1dc 100644 --- a/qla_isp/linux/isp_pci.c +++ b/qla_isp/linux/isp_pci.c @@ -1,4 +1,4 @@ -/* $Id: isp_pci.c,v 1.167 2008/03/23 17:05:10 mjacob Exp $ */ +/* $Id: isp_pci.c,v 1.168 2008/04/15 22:41:03 mjacob Exp $ */ /* * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -506,7 +506,7 @@ isplinux_pci_release(struct Scsi_Host *host) } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) /** * pci_intx - enables/disables PCI INTx for device dev * @pdev: the PCI device to operate on @@ -619,13 +619,7 @@ isplinux_pci_init_one(struct Scsi_Host *host) return (1); } - /* PCI Rev 2.3 changes */ - if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP6312 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2322) { - /* enable PCI-INTX */ - pci_intx(pdev, 1); - } - - +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7) if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) { struct msix_entry isp_msix[3]; int reg; @@ -674,7 +668,12 @@ isplinux_pci_init_one(struct Scsi_Host *host) pectl |= (5 << 12); /* 4K READ BURST */ pci_write_config_word(pdev, reg + PCI_EXP_DEVCTL, pectl); } + } else +#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) + if (pci_enable_msi(pdev) == 0) { + isp_pci->msi_enabled = 1; } +#endif /* * Disable the ROM. @@ -2845,7 +2844,7 @@ again: nxti = ISP_NXT_QENTRY((curip), RQUEST_QUEUE_LEN(isp)); if (nxti == optr) { isp_pci_dmateardown(isp, Cmnd, 0); - isp_prt(isp, ISP_LOGDEBUG0, "%s: out of space for continuations (%d of %d done)", __FUNCTION__, seg, segcnt); + isp_prt(isp, ISP_LOGDEBUG0, "%s: Chan %d out of space for continuations (did %d of %d segments)", __FUNCTION__, XS_CHANNEL(Cmnd), seg, segcnt); XS_SETERR(Cmnd, HBA_BOTCH); return (CMD_EAGAIN); } @@ -3088,7 +3087,7 @@ isp_pci_2400_dmasetup(ispsoftc_t *isp, Scsi_Cmnd *Cmnd, ispreq_t *orig_rq, uint3 nxti = ISP_NXT_QENTRY((curip), RQUEST_QUEUE_LEN(isp)); if (nxti == optr) { isp_pci_dmateardown(isp, Cmnd, 0); - isp_prt(isp, ISP_LOGWARN, "out of space for continuations (did %d of %d segments)", seg, segcnt); + isp_prt(isp, ISP_LOGDEBUG0, "%s: Chan %d out of space for continuations (did %d of %d segments)", __FUNCTION__, XS_CHANNEL(Cmnd), seg, segcnt); XS_SETERR(Cmnd, HBA_BOTCH); return (CMD_EAGAIN); } @@ -3396,7 +3395,7 @@ isplinux_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) isp->isp_osinfo.device = pdev; host->unique_id = isp_unit_seed++; sprintf(isp->isp_name, "%s%d", ISP_NAME, isp->isp_unit); - isp->isp_osinfo.device_id = ((pdev->bus->number) << 16) | (PCI_SLOT(pdev->devfn) << 8) | (PCI_FUNC(pdev->devfn)); + isp->isp_osinfo.device_id = (pci_domain_nr(pdev->bus) << 16) | ((pdev->bus->number) << 8) | (PCI_SLOT(pdev->devfn) << 3) | (PCI_FUNC(pdev->devfn)); if (isp_disable & (1 << isp->isp_unit)) { printk("%s: disabled at user request\n", isp->isp_name); scsi_host_put(host); @@ -3452,7 +3451,11 @@ isplinux_pci_remove(struct pci_dev *pdev) #ifdef ISP_TARGET_MODE isp_detach_target(isp); #endif - ISP_THREAD_KILL(isp); + if (isp->isp_osinfo.thread_task) { + wake_up(&isp->isp_osinfo.trq); + kthread_stop(isp->isp_osinfo.thread_task); + isp->isp_osinfo.thread_task = NULL; + } ISP_LOCKU_SOFTC(isp); isp_shutdown(isp); isp->dogactive = 0; diff --git a/qla_isp/linux/isp_scst.c b/qla_isp/linux/isp_scst.c index 4c0e17534..46084a9fe 100644 --- a/qla_isp/linux/isp_scst.c +++ b/qla_isp/linux/isp_scst.c @@ -150,7 +150,7 @@ static int debug = 0; module_param(debug, int, 0); #else #define SDprintk(fmt, args...) -#define SDprintk2(fmt, args...) +#define SDprintk2(fmt, args...) #endif #define Eprintk(fmt, args...) printk(KERN_ERR "isp_scst(%s): " fmt, __FUNCTION__, ##args) diff --git a/qla_isp/linux/scsi_target.c b/qla_isp/linux/scsi_target.c index fedac7fba..8aadb1c93 100644 --- a/qla_isp/linux/scsi_target.c +++ b/qla_isp/linux/scsi_target.c @@ -1,4 +1,4 @@ -/* $Id: scsi_target.c,v 1.83 2008/03/15 18:16:47 mjacob Exp $ */ +/* $Id: scsi_target.c,v 1.84 2008/04/15 22:41:03 mjacob Exp $ */ /* * Copyright (c) 1997-2008 by Matthew Jacob * All rights reserved. @@ -57,33 +57,15 @@ */ #include -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(v,p,s) (((v)<<16)+(p<<8)+s) -#endif #include #include #include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include +#include +#include #ifdef min #undef min