Synchronize with Feral CVS repository:

- use kthread
- MBOX_ACQUIRE macro redefined


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@355 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Stanislaw Gruszka
2008-04-24 06:34:08 +00:00
parent 1b384e9234
commit 9252bb3170
8 changed files with 427 additions and 467 deletions
+3 -2
View File
@@ -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)",
+3 -2
View File
@@ -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;
+3 -3
View File
@@ -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;
+380 -358
View File
@@ -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(&current->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);
}
+17 -66
View File
@@ -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 <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/stat.h>
#include <linux/pci.h>
#include <asm/dma.h>
@@ -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)
{
+16 -13
View File
@@ -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;
+1 -1
View File
@@ -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)
+4 -22
View File
@@ -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 <linux/version.h>
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(v,p,s) (((v)<<16)+(p<<8)+s)
#endif
#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/autoconf.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/stat.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <scsi/scsi.h>
#include <asm/dma.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <asm/scatterlist.h>
#include <asm/system.h>
#include <linux/kthread.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#ifdef min
#undef min