Synchronize with Feral CVS repository:

Note that asking for "prefer N-port and then Loop" with the 24XX seems to
cause the f/w to crash. So, don't do that.

Firmware crashes are now considered fatal and cause the HBA to be marked dead.

Now that we've avoided the f/w crash in isp_init_24xx, we can process
toplogy options.



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@274 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Stanislaw Gruszka
2008-02-12 10:41:45 +00:00
parent c4b2403ead
commit a13eae04d2
6 changed files with 149 additions and 105 deletions
+20 -2
View File
@@ -1,4 +1,4 @@
/* $Id: isp.c,v 1.190 2008/01/07 19:07:06 mjacob Exp $ */
/* $Id: isp.c,v 1.192 2008/01/08 22:14:29 mjacob Exp $ */
/*-
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -210,6 +210,11 @@ isp_reset(ispsoftc_t *isp)
static const char dcrc[] = "Downloaded RISC Code Checksum Failure";
isp->isp_state = ISP_NILSTATE;
if (isp->isp_dead) {
isp_shutdown(isp);
ISP_DISABLE_INTS(isp);
return;
}
/*
* Basic types (SCSI, FibreChannel and PCI or SBus)
@@ -223,6 +228,7 @@ isp_reset(ispsoftc_t *isp)
ISP_DISABLE_INTS(isp);
/*
* Pick an initial maxcmds value which will be used
* to allocate xflist pointer space. It may be changed
@@ -1118,6 +1124,11 @@ isp_reset(ispsoftc_t *isp)
for (i = 0; i < isp->isp_nchan; i++) {
isp_fw_state(isp, i);
}
if (isp->isp_dead) {
isp_shutdown(isp);
ISP_DISABLE_INTS(isp);
return;
}
isp->isp_state = ISP_RESETSTATE;
@@ -1902,10 +1913,15 @@ isp_fibre_init_2400(ispsoftc_t *isp)
icbp->icb_fwoptions2 = fcp->isp_xfwoptions;
switch(isp->isp_confopts & ISP_CFG_PORT_PREF) {
#if 0
case ISP_CFG_NPORT:
/*
* XXX: This causes the f/w to crash.
*/
icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_2_LOOP;
break;
#endif
case ISP_CFG_NPORT_ONLY:
icbp->icb_fwoptions2 &= ~ICB2400_OPT2_TOPO_MASK;
icbp->icb_fwoptions2 |= ICB2400_OPT2_PTP_ONLY;
@@ -5581,6 +5597,7 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
isp_async(isp, ISPASYNC_BUS_RESET, chan);
break;
case ASYNC_SYSTEM_ERROR:
isp->isp_dead = 1;
isp->isp_state = ISP_CRASHED;
if (IS_FC(isp)) {
FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
@@ -6034,6 +6051,8 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox)
"Point-to-Point -> Loop mode (BAD LIP)");
break;
case ISP_CONN_FATAL:
isp->isp_dead = 1;
isp->isp_state = ISP_CRASHED;
isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR");
isp_async(isp, ISPASYNC_FW_CRASH);
return (-1);
@@ -7937,7 +7956,6 @@ isp_reinit(ispsoftc_t *isp)
isp_done(xs);
}
#ifdef ISP_TARGET_MODE
/* XXXXXXXXX NOT SUFFICCIENT XXXXXXXXX */
MEMZERO(isp->isp_tgtlist, isp->isp_maxcmds * sizeof (void **));
#endif
}
+3 -2
View File
@@ -1,4 +1,4 @@
/* $Id: ispvar.h,v 1.90 2008/01/04 16:46:10 mjacob Exp $ */
/* $Id: ispvar.h,v 1.91 2008/01/08 20:40:22 mjacob Exp $ */
/*-
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -563,7 +563,8 @@ struct ispsoftc {
*/
volatile uint32_t : 8,
: 3,
: 2,
isp_dead : 1,
isp_in_intr : 1,
isp_mboxbsy : 1, /* mailbox command active */
isp_state : 3,
+76 -41
View File
@@ -1,4 +1,4 @@
/* $Id: isp_cb_ops.c,v 1.83 2008/01/07 19:07:32 mjacob Exp $ */
/* $Id: isp_cb_ops.c,v 1.84 2008/01/08 18:31:21 mjacob Exp $ */
/*
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -399,7 +399,7 @@ isp_close(struct inode *ip, struct file *fp)
return (0);
}
static int isp_tur_test(ispsoftc_t *, isp_turtst_t *);
static int isp_perf_test(ispsoftc_t *, isp_perftst_t *);
static int
isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
@@ -795,15 +795,15 @@ isp_ioctl(struct inode *ip, struct file *fp, unsigned int c, unsigned long arg)
}
break;
}
case ISP_FC_TURTST:
case ISP_FC_PERFTST:
{
isp_turtst_t local, *tt = &local;
isp_perftst_t local, *tt = &local;
if (COPYIN((void *)arg, tt, sizeof (*tt))) {
rv = -EFAULT;
break;
}
rv = isp_tur_test(isp, tt);
rv = isp_perf_test(isp, tt);
break;
}
default:
@@ -1839,7 +1839,7 @@ out:
}
static int
isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
isp_perf_test(ispsoftc_t *isp, isp_perftst_t *tt)
{
struct scsi_device *dev = NULL;
Scsi_Cmnd *Cmnd = NULL;
@@ -1847,19 +1847,35 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
struct Scsi_Host *host = NULL;
uint32_t nxti, optr, handle;
uint8_t local[QENTRY_LEN];
ispreq_t *reqp = (ispreq_t *) local;
int result = 0, i;
int result = 0, i, iswrite, amt;
void *qep, *qel = local;
DECLARE_MUTEX_LOCKED(rsem);
unsigned long flags;
if (IS_SCSI(isp)) {
return (-ENODEV);
}
if (tt->target < 0 || tt->target >= MAX_FC_TARG) {
return (-ENODEV);
}
if (tt->channel < 0 || tt->channel >= isp->isp_nchan) {
return (-ENODEV);
}
iswrite = 0;
if (tt->ioszdir) {
amt = tt->ioszdir;
if (amt < 0) {
iswrite = 1;
amt = -amt;
}
if (amt > ISP_FC_SCRLEN) {
return (-ENOMEM);
}
} else {
amt = 0;
}
i = FCPARAM(isp, tt->channel)->isp_ini_map[tt->target] - 1;
if (i < 0 || i >= MAX_FC_TARG) {
return (-ENXIO);
@@ -1880,6 +1896,7 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
isp_kfree(Cmnd, sizeof (Scsi_Cmnd));
return (-ENOMEM);
}
Cmnd->device = dev;
dev->host = host;
Cmnd->scsi_done = isp_run_cmd_done;
@@ -1887,11 +1904,11 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
Cmnd->cmd_len = 6;
Cmnd->sc_data_direction = SCSI_DATA_NONE;
reqp->req_header.rqs_entry_count = 1;
if (IS_24XX(isp)) {
ispreqt7_t *t7 = (ispreqt7_t *) local;
reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
t7->req_header.rqs_entry_type = RQSTYPE_T7RQS;
t7->req_header.rqs_entry_count = 1;
t7->req_task_attribute = FCP_CMND_TASK_ATTR_SIMPLE;
t7->req_nphdl = lp->handle;
t7->req_tidlo = lp->portid;
@@ -1902,36 +1919,56 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
}
t7->req_lun[1] = tt->lun & 0xff;
t7->req_time = 30;
t7->req_seg_count = 0;
t7->req_vpidx = tt->channel;
MEMZERO(t7->req_cdb, sizeof (t7->req_cdb));
} else if (IS_FC(isp)) {
ispreqt2_t *t2 = (ispreqt2_t *) local;
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
t2->req_flags = REQFLAG_STAG;
if (ISP_CAP_2KLOGIN(isp)) {
((ispreqt2e_t *)reqp)->req_target = lp->handle;
((ispreqt2e_t *)reqp)->req_scclun = tt->lun;
} else if (ISP_CAP_SCCFW(isp)) {
t2->req_target = lp->handle;
t2->req_scclun = tt->lun;
if (amt) {
t7->req_seg_count = 1;
if (iswrite) {
t7->req_alen_datadir = FCP_CMND_DATA_WRITE;
t7->req_cdb[0] = 0xa;
} else {
t7->req_alen_datadir = FCP_CMND_DATA_READ;
t7->req_cdb[0] = 0x8;
}
t7->req_cdb[4] = amt >> 9;
t7->req_dl = amt;
t7->req_dataseg.ds_base = DMA_LO32(FCPARAM(isp, tt->channel)->isp_scdma);
t7->req_dataseg.ds_basehi = DMA_HI32(FCPARAM(isp, tt->channel)->isp_scdma);
t7->req_dataseg.ds_count = amt;
} else {
t2->req_target = lp->handle;
t2->req_lun_trn = tt->lun;
t7->req_seg_count = 0;
}
MEMZERO(t2->req_cdb, sizeof (t2->req_cdb));
t2->req_time = 30;
t7->req_vpidx = tt->channel;
} else {
reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
reqp->req_flags = REQFLAG_STAG;
reqp->req_target = tt->target;
reqp->req_target |= (tt->channel << 7);
reqp->req_lun_trn = tt->lun;
reqp->req_cdblen = 6;
MEMZERO(reqp->req_cdb, sizeof (reqp->req_cdb));
reqp->req_time = 30;
ispreqt3_t *t3 = (ispreqt3_t *) local;
t3->req_header.rqs_entry_type = RQSTYPE_T3RQS;
t3->req_header.rqs_entry_count = 1;
t3->req_flags = REQFLAG_STAG;
if (amt) {
if (iswrite) {
t3->req_flags |= REQFLAG_DATA_OUT;
t3->req_cdb[0] = 0xa;
} else {
t3->req_flags |= REQFLAG_DATA_IN;
t3->req_cdb[0] = 0x8;
}
t3->req_cdb[4] = amt >> 9;
t3->req_dataseg[0].ds_base = DMA_LO32(FCPARAM(isp, tt->channel)->isp_scdma);
t3->req_dataseg[0].ds_basehi = DMA_HI32(FCPARAM(isp, tt->channel)->isp_scdma);
t3->req_dataseg[0].ds_count = amt;
t3->req_totalcnt = amt;
}
if (ISP_CAP_2KLOGIN(isp)) {
((ispreqt3e_t *)t3)->req_target = lp->handle;
((ispreqt3e_t *)t3)->req_scclun = tt->lun;
} else if (ISP_CAP_SCCFW(isp)) {
t3->req_target = lp->handle;
t3->req_scclun = tt->lun;
} else {
t3->req_target = lp->handle;
t3->req_lun_trn = tt->lun;
}
t3->req_time = 30;
}
for (i = 0; i < tt->count; i++) {
@@ -1953,17 +1990,15 @@ isp_tur_test(ispsoftc_t *isp, isp_turtst_t *tt)
} else {
handle = ISP_SPCL_HANDLE;
}
reqp->req_handle = handle;
((ispreq_t *)local)->req_handle = handle;
if (IS_24XX(isp)) {
isp_put_request_t7(isp, qel, qep);
} else if (IS_FC(isp)) {
} else {
if (ISP_CAP_2KLOGIN(isp)) {
isp_put_request_t2e(isp, qel, qep);
} else {
isp_put_request_t2(isp, qel, qep);
}
} else {
isp_put_request(isp, qel, qep);
}
ISP_ADD_REQUEST(isp, nxti);
if (handle != ISP_SPCL_HANDLE) {
+4 -3
View File
@@ -1,4 +1,4 @@
/* $Id: isp_ioctl.h,v 1.26 2008/01/07 19:07:32 mjacob Exp $ */
/* $Id: isp_ioctl.h,v 1.27 2008/01/08 18:31:21 mjacob Exp $ */
/*
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -235,10 +235,11 @@ typedef struct {
/*
* This is a trigger for a performance test.
*/
#define ISP_FC_TURTST (ISP_IOC | 44)
#define ISP_FC_PERFTST (ISP_IOC | 44)
typedef struct {
uint32_t channel, target, lun, count;
} isp_turtst_t;
int32_t ioszdir;
} isp_perftst_t;
/*
* vim:ts=4:sw=4:expandtab
*/
+46 -40
View File
@@ -1,4 +1,4 @@
/* $Id: isp_linux.c,v 1.216 2008/01/04 18:00:20 mjacob Exp $ */
/* $Id: isp_linux.c,v 1.219 2008/01/08 22:15:01 mjacob Exp $ */
/*
* Copyright (c) 1997-2007 by Matthew Jacob
* All rights reserved.
@@ -181,7 +181,7 @@ isplinux_append_to_waitq(ispsoftc_t *isp, Scsi_Cmnd *Cmnd)
* If we're a fibre channel card and we consider the loop to be
* down, we just finish the command here and now.
*/
if (IS_FC(isp) && ISP_DATA(isp, XS_CHANNEL(Cmnd))->deadloop) {
if ((IS_FC(isp) && ISP_DATA(isp, XS_CHANNEL(Cmnd))->deadloop) || isp->isp_dead) {
XS_INITERR(Cmnd);
XS_SETERR(Cmnd, DID_NO_CONNECT);
/*
@@ -2705,8 +2705,9 @@ isp_enable_lun(ispsoftc_t *isp, uint16_t bus, uint16_t lun)
}
/*
* Validity check with our enable ruleset. We can't enable busses > 1
* without enabling bus 0 first in some kind of role.
* Validity check with our enable ruleset.
* We can't enable busses > 1 without enabling bus 0
* first in some kind of role.
*/
if (IS_FC(isp) && bus != 0 && (((FCPARAM(isp, 0)->role & ISP_ROLE_TARGET) && nolunsenabled(isp, 0)) || (FCPARAM(isp, 0)->role == ISP_ROLE_NONE))) {
isp_prt(isp, ISP_LOGWARN, "%s: must enable Chan 0 before Chan %u", __FUNCTION__, bus);
@@ -3770,21 +3771,13 @@ isplinux_get_default_id(ispsoftc_t *isp, int chan)
int
isplinux_get_default_role(ispsoftc_t *isp, int chan)
{
if (IS_FC(isp)) {
return (ISP_DATA(isp, chan)->role);
} else {
return (isp->isp_osinfo.role);
}
return (ISP_DATA(isp, chan)->role);
}
void
isplinux_set_default_role(ispsoftc_t *isp, int chan, int role)
{
if (IS_FC(isp)) {
ISP_DATA(isp, chan)->role = role;
} else {
isp->isp_osinfo.role = role;
}
ISP_DATA(isp, chan)->role = role;
}
/*
@@ -3896,14 +3889,16 @@ isplinux_timer(unsigned long arg)
ISP_ILOCK_SOFTC(isp);
isp->isp_osinfo.dogcnt++;
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
isp_intr(isp, isr, sema, mbox);
if (isp->intsok) {
ISP_ENABLE_INTS(isp);
}
if (isp->isp_dead == 0) {
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
isp_intr(isp, isr, sema, mbox);
if (isp->intsok) {
ISP_ENABLE_INTS(isp);
}
#ifdef ISP_TARGET_MODE
didintr = 1;
didintr = 1;
#endif
}
}
for (i = 0; i < isp->isp_nchan; i++) {
if (ISP_DATA(isp, i)->qfdelay) {
@@ -4021,7 +4016,7 @@ isplinux_intr(int irq, void *arg PTARG)
* roles=DEVID=role[,...]
*/
static int
isp_parse_rolearg(ispsoftc_t *isp, char *roles)
isp_parse_rolearg(ispsoftc_t *isp, int chan, char *roles)
{
char *role = roles;
@@ -4190,14 +4185,12 @@ isplinux_common_init(ispsoftc_t *isp)
}
if (IS_FC(isp)) {
if (IS_2200(isp) || IS_2300(isp)) {
if (isp_nport_only & (1 << isp->isp_unit)) {
isp->isp_confopts |= ISP_CFG_NPORT_ONLY;
} else if (isp_loop_only & (1 << isp->isp_unit)) {
isp->isp_confopts |= ISP_CFG_LPORT_ONLY;
} else {
isp->isp_confopts |= ISP_CFG_NPORT;
}
if (isp_nport_only & (1 << isp->isp_unit)) {
isp->isp_confopts |= ISP_CFG_NPORT_ONLY;
} else if (isp_loop_only & (1 << isp->isp_unit)) {
isp->isp_confopts |= ISP_CFG_LPORT_ONLY;
} else {
isp->isp_confopts |= ISP_CFG_NPORT;
}
isp->isp_osinfo.host->this_id = MAX_FC_TARG+1;
#ifdef ISP_FW_CRASH_DUMP
@@ -4228,7 +4221,6 @@ isplinux_common_init(ispsoftc_t *isp)
}
isp->isp_osinfo.host->max_id = MAX_FC_TARG;
isp->isp_osinfo.host->max_cmd_len = 16;
isp->isp_osinfo.role = isp_parse_rolearg(isp, isp_roles);
for (chan = 0; chan < isp->isp_nchan; chan++) {
isp_data *fc = ISP_DATA(isp, chan);
@@ -4247,12 +4239,17 @@ isplinux_common_init(ispsoftc_t *isp)
} else {
DEFAULT_EXEC_THROTTLE(isp) = ICB_DFLT_THROTTLE;
}
fc->role = isp->isp_osinfo.role;
fc->role = isp_parse_rolearg(isp, chan, isp_roles);
SET_DEFAULT_ROLE(isp, chan, fc->role);
}
} else {
isp->isp_osinfo.host->max_id = MAX_TARGETS;
isp->isp_osinfo.host->max_cmd_len = 12;
isp->isp_osinfo.host->this_id = 7; /* temp default */
for (chan = 0; chan < isp->isp_nchan; chan++) {
SDPARAM(isp, chan)->role = isp_parse_rolearg(isp, chan, isp_roles);
SET_DEFAULT_ROLE(isp, chan, SDPARAM(isp, chan)->role);
}
}
if (isp_own_id) {
@@ -4342,6 +4339,7 @@ isplinux_reinit(ispsoftc_t *isp)
}
isp->isp_osinfo.host->max_lun = min(maxluns, ISP_MAX_LUNS(isp));
#if 0
/*
* If we're not taking a role, set some 'defaults' and turn off lasers (for FC cards).
*/
@@ -4353,6 +4351,12 @@ isplinux_reinit(ispsoftc_t *isp)
isp_shutdown(isp);
return (0);
}
#else
isp->isp_osinfo.host->can_queue = 16;
isp->isp_osinfo.host->can_queue = 1;
isp->isp_osinfo.host->cmd_per_lun = 1;
isp->isp_osinfo.host->this_id = IS_FC(isp)? MAX_FC_TARG : 7;
#endif
isp_init(isp);
if (isp->isp_state != ISP_INITSTATE) {
@@ -4525,23 +4529,25 @@ isp_task_thread(void *arg)
break;
#endif
case ISP_THREAD_REINIT:
{
int level;
ISP_LOCKU_SOFTC(isp);
level = (isp->isp_osinfo.role == ISP_ROLE_NONE)? ISP_RESETSTATE : ISP_INITSTATE;
isp_reinit(isp);
for (i = 0; i < isp->isp_nchan; i++) {
ISP_DATA(isp, i)->blocked = 0;
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;
}
if (isp->isp_state >= level) {
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;
-17
View File
@@ -139,20 +139,6 @@ typedef struct scsi_host_template Scsi_Host_Template;
#include <linux/proc_fs.h>
#endif
/*
* These bits and pieces of keeping track of Linux versions
* and some of the various foo items for locking/unlocking
* gratefully borrowed from (amongst others) Doug Ledford
* and Gerard Roudier.
*/
#define PWRB(p, o, r) pci_write_config_byte(p->pci_dev, o, r)
#define PWRW(p, o, r) pci_write_config_word(p->pci_dev, o, r)
#define PWRL(p, o, r) pci_write_config_dword(p->pci_dev, o, r)
#define PRDW(p, o, r) pci_read_config_word(p->pci_dev, o, r)
#define PRDD(p, o, r) pci_read_config_dword(p->pci_dev, o, r)
#define PRDB(p, o, r) pci_read_config_byte(p->pci_dev, o, r)
/*
* Efficiency- get rid of SBus code && tests unless we need them.
*/
@@ -744,9 +730,6 @@ extern int api_channel;
#ifndef roundup
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#endif
#ifndef ARGSUSED
#define ARGSUSED(x) x = x
#endif
/*
* Platform specific 'inline' or support functions