Add in an ioctl entry point so scsictl mediated bus resets will work.
Redo how we start commands- do a 'slow' start function which then looks to see when we're done the configuration process at which point it *then* enables sync/wide mode. Set the max openings amount to the true max openings- not a synthetic. Add a timeout driven command requeue function so that Loop Down events well freeze things until a later point in time where they might be restarted.
This commit is contained in:
parent
2b760bfd7b
commit
02911581bb
|
@ -1,5 +1,4 @@
|
|||
/* $NetBSD: isp_netbsd.c,v 1.16 1999/09/30 23:06:18 thorpej Exp $ */
|
||||
/* release_6_5_99 */
|
||||
/* $NetBSD: isp_netbsd.c,v 1.17 1999/10/14 02:31:11 mjacob Exp $ */
|
||||
/*
|
||||
* Platform (NetBSD) dependent common attachment code for Qlogic adapters.
|
||||
* Matthew Jacob <mjacob@nas.nasa.gov>
|
||||
|
@ -32,18 +31,20 @@
|
|||
*/
|
||||
|
||||
#include <dev/ic/isp_netbsd.h>
|
||||
#include <sys/scsiio.h>
|
||||
|
||||
static void ispminphys __P((struct buf *));
|
||||
static int32_t ispcmd_slow __P((ISP_SCSI_XFER_T *));
|
||||
static int32_t ispcmd __P((ISP_SCSI_XFER_T *));
|
||||
static int
|
||||
ispioctl __P((struct scsipi_link *, u_long, caddr_t, int, struct proc *));
|
||||
|
||||
static struct scsipi_device isp_dev = { NULL, NULL, NULL, NULL };
|
||||
static int isp_poll __P((struct ispsoftc *, ISP_SCSI_XFER_T *, int));
|
||||
static void isp_watch __P((void *));
|
||||
static void isp_command_requeue __P((void *));
|
||||
static void isp_internal_restart __P((void *));
|
||||
|
||||
#define FC_OPENINGS RQUEST_QUEUE_LEN / (MAX_FC_TARG-1)
|
||||
#define PI_OPENINGS RQUEST_QUEUE_LEN / (MAX_TARGETS-1)
|
||||
|
||||
/*
|
||||
* Complete attachment of hardware, include subdevices.
|
||||
*/
|
||||
|
@ -52,14 +53,15 @@ isp_attach(isp)
|
|||
struct ispsoftc *isp;
|
||||
{
|
||||
|
||||
isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
|
||||
isp->isp_osinfo._adapter.scsipi_minphys = ispminphys;
|
||||
isp->isp_osinfo._adapter.scsipi_ioctl = ispioctl;
|
||||
|
||||
isp->isp_state = ISP_RUNSTATE;
|
||||
isp->isp_osinfo._link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
|
||||
isp->isp_osinfo._link.adapter_softc = isp;
|
||||
isp->isp_osinfo._link.device = &isp_dev;
|
||||
isp->isp_osinfo._link.adapter = &isp->isp_osinfo._adapter;
|
||||
isp->isp_osinfo._link.openings = isp->isp_maxcmds;
|
||||
TAILQ_INIT(&isp->isp_osinfo.waitq);
|
||||
|
||||
if (IS_FC(isp)) {
|
||||
|
@ -67,6 +69,7 @@ isp_attach(isp)
|
|||
* Give it another chance here to come alive...
|
||||
*/
|
||||
fcparam *fcp = isp->isp_param;
|
||||
isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
|
||||
if (fcp->isp_fwstate != FW_READY) {
|
||||
(void) isp_control(isp, ISPCTL_FCLINK_TEST, NULL);
|
||||
}
|
||||
|
@ -79,12 +82,11 @@ isp_attach(isp)
|
|||
#else
|
||||
isp->isp_osinfo._link.scsipi_scsi.max_lun = 15;
|
||||
#endif
|
||||
isp->isp_osinfo._link.openings = FC_OPENINGS;
|
||||
isp->isp_osinfo._link.scsipi_scsi.adapter_target =
|
||||
((fcparam *)isp->isp_param)->isp_loopid;
|
||||
} else {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
isp->isp_osinfo._link.openings = PI_OPENINGS;
|
||||
isp->isp_osinfo._adapter.scsipi_cmd = ispcmd_slow;
|
||||
isp->isp_osinfo._link.scsipi_scsi.max_target = MAX_TARGETS-1;
|
||||
if (isp->isp_bustype == ISP_BT_SBUS) {
|
||||
isp->isp_osinfo._link.scsipi_scsi.max_lun = 7;
|
||||
|
@ -101,6 +103,8 @@ isp_attach(isp)
|
|||
}
|
||||
isp->isp_osinfo._link.scsipi_scsi.adapter_target =
|
||||
sdp->isp_initiator_id;
|
||||
isp->isp_osinfo.discovered[0] = 1 << sdp->isp_initiator_id;
|
||||
isp->isp_osinfo.discovered[1] = 1 << sdp->isp_initiator_id;
|
||||
if (IS_12X0(isp)) {
|
||||
isp->isp_osinfo._link_b = isp->isp_osinfo._link;
|
||||
sdp++;
|
||||
|
@ -109,15 +113,12 @@ isp_attach(isp)
|
|||
isp->isp_osinfo._link_b.scsipi_scsi.channel = 1;
|
||||
}
|
||||
}
|
||||
if (isp->isp_osinfo._link.openings < 2)
|
||||
isp->isp_osinfo._link.openings = 2;
|
||||
isp->isp_osinfo._link.type = BUS_SCSI;
|
||||
|
||||
/*
|
||||
* Send a SCSI Bus Reset (used to be done as part of attach,
|
||||
* but now left to the OS outer layers).
|
||||
*/
|
||||
|
||||
if (IS_SCSI(isp)) {
|
||||
int bus = 0;
|
||||
(void) isp_control(isp, ISPCTL_RESET_BUS, &bus);
|
||||
|
@ -132,7 +133,7 @@ isp_attach(isp)
|
|||
* Start the watchdog.
|
||||
*/
|
||||
isp->isp_dogactive = 1;
|
||||
timeout(isp_watch, isp, 30 * hz);
|
||||
timeout(isp_watch, isp, WATCH_INTERVAL * hz);
|
||||
|
||||
/*
|
||||
* And attach children (if any).
|
||||
|
@ -164,44 +165,86 @@ ispminphys(bp)
|
|||
minphys(bp);
|
||||
}
|
||||
|
||||
static int
|
||||
static int32_t
|
||||
ispcmd_slow(xs)
|
||||
ISP_SCSI_XFER_T *xs;
|
||||
{
|
||||
/*
|
||||
* Have we completed discovery for this adapter?
|
||||
*/
|
||||
if ((xs->xs_control & XS_CTL_DISCOVERY) == 0) {
|
||||
struct ispsoftc *isp = XS_ISP(xs);
|
||||
sdparam *sdp = isp->isp_param;
|
||||
int s = splbio();
|
||||
int chan = XS_CHANNEL(xs), chmax = IS_12X0(isp)? 2 : 1;
|
||||
u_int16_t f = DPARM_DEFAULT;
|
||||
|
||||
sdp += chan;
|
||||
if (xs->sc_link->quirks & SDEV_NOSYNC) {
|
||||
f ^= DPARM_SYNC;
|
||||
}
|
||||
if (xs->sc_link->quirks & SDEV_NOWIDE) {
|
||||
f ^= DPARM_WIDE;
|
||||
}
|
||||
if (xs->sc_link->quirks & SDEV_NOTAG) {
|
||||
f ^= DPARM_TQING;
|
||||
}
|
||||
sdp->isp_devparam[XS_TGT(xs)].dev_flags = f;
|
||||
sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
|
||||
isp->isp_osinfo.discovered[chan] |= (1 << XS_TGT(xs));
|
||||
f = 0xffff ^ (1 << sdp->isp_initiator_id);
|
||||
for (chan = 0; chan < chmax; chan++) {
|
||||
if (isp->isp_osinfo.discovered[chan] == f)
|
||||
break;
|
||||
}
|
||||
if (chan == chmax) {
|
||||
isp->isp_osinfo._adapter.scsipi_cmd = ispcmd;
|
||||
isp->isp_update = 1;
|
||||
if (IS_12X0(isp))
|
||||
isp->isp_update |= 2;
|
||||
}
|
||||
(void) splx(s);
|
||||
}
|
||||
return (ispcmd(xs));
|
||||
}
|
||||
|
||||
static int
|
||||
ispioctl(sc_link, cmd, addr, flag, p)
|
||||
struct scsipi_link *sc_link;
|
||||
u_long cmd;
|
||||
caddr_t addr;
|
||||
int flag;
|
||||
struct proc *p;
|
||||
{
|
||||
struct ispsoftc *isp = sc_link->adapter_softc;
|
||||
int s, chan, retval = ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
case SCBUSIORESET:
|
||||
chan = sc_link->scsipi_scsi.channel;
|
||||
s = splbio();
|
||||
if (isp_control(isp, ISPCTL_RESET_BUS, &chan))
|
||||
retval = EIO;
|
||||
else
|
||||
retval = 0;
|
||||
(void) splx(s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
||||
static int32_t
|
||||
ispcmd(xs)
|
||||
ISP_SCSI_XFER_T *xs;
|
||||
{
|
||||
struct ispsoftc *isp;
|
||||
int result;
|
||||
int s;
|
||||
int result, s;
|
||||
|
||||
isp = XS_ISP(xs);
|
||||
s = splbio();
|
||||
/*
|
||||
* This is less efficient than I would like in that the
|
||||
* majority of cases will have to do some pointer deferences
|
||||
* to find out that things don't need to be updated.
|
||||
*/
|
||||
#if 0 /* XXX THORPEJ */
|
||||
if ((xs->xs_control & XS_CTL_DISCOVERY) == 0 &&
|
||||
(isp->isp_type & ISP_HA_SCSI)) {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
sdp += XS_CHANNEL(xs);
|
||||
if (sdp->isp_devparam[XS_TGT(xs)].dev_flags !=
|
||||
sdp->isp_devparam[XS_TGT(xs)].cur_dflags) {
|
||||
u_int16_t f = DPARM_WIDE|DPARM_SYNC|DPARM_TQING;
|
||||
if (xs->sc_link->quirks & SDEV_NOSYNC)
|
||||
f &= ~DPARM_SYNC;
|
||||
if (xs->sc_link->quirks & SDEV_NOWIDE)
|
||||
f &= ~DPARM_WIDE;
|
||||
if (xs->sc_link->quirks & SDEV_NOTAG)
|
||||
f &= ~DPARM_TQING;
|
||||
sdp->isp_devparam[XS_TGT(xs)].dev_flags &=
|
||||
~(DPARM_WIDE|DPARM_SYNC|DPARM_TQING);
|
||||
sdp->isp_devparam[XS_TGT(xs)].dev_flags |= f;
|
||||
sdp->isp_devparam[XS_TGT(xs)].dev_update = 1;
|
||||
isp->isp_update |= (1 << XS_CHANNEL(xs));
|
||||
}
|
||||
}
|
||||
#endif /* XXX THORPEJ */
|
||||
|
||||
if (isp->isp_state < ISP_RUNSTATE) {
|
||||
DISABLE_INTS(isp);
|
||||
isp_init(isp);
|
||||
|
@ -209,7 +252,7 @@ ispcmd(xs)
|
|||
ENABLE_INTS(isp);
|
||||
(void) splx(s);
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
return (CMD_COMPLETE);
|
||||
return (COMPLETE);
|
||||
}
|
||||
isp->isp_state = ISP_RUNSTATE;
|
||||
ENABLE_INTS(isp);
|
||||
|
@ -218,7 +261,6 @@ ispcmd(xs)
|
|||
/*
|
||||
* Check for queue blockage...
|
||||
*/
|
||||
|
||||
if (isp->isp_osinfo.blocked) {
|
||||
if (xs->xs_control & XS_CTL_POLL) {
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
|
@ -227,37 +269,70 @@ ispcmd(xs)
|
|||
}
|
||||
TAILQ_INSERT_TAIL(&isp->isp_osinfo.waitq, xs, adapter_q);
|
||||
splx(s);
|
||||
return (CMD_QUEUED);
|
||||
return (SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
|
||||
DISABLE_INTS(isp);
|
||||
result = ispscsicmd(xs);
|
||||
ENABLE_INTS(isp);
|
||||
if (result != CMD_QUEUED || (xs->xs_control & XS_CTL_POLL) == 0) {
|
||||
|
||||
if ((xs->xs_control & XS_CTL_POLL) == 0) {
|
||||
switch (result) {
|
||||
case CMD_QUEUED:
|
||||
result = SUCCESSFULLY_QUEUED;
|
||||
break;
|
||||
case CMD_EAGAIN:
|
||||
result = TRY_AGAIN_LATER;
|
||||
break;
|
||||
case CMD_RQLATER:
|
||||
result = SUCCESSFULLY_QUEUED;
|
||||
timeout(isp_command_requeue, xs, hz);
|
||||
break;
|
||||
case CMD_COMPLETE:
|
||||
result = COMPLETE;
|
||||
break;
|
||||
}
|
||||
(void) splx(s);
|
||||
return (result);
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
case CMD_QUEUED:
|
||||
result = SUCCESSFULLY_QUEUED;
|
||||
break;
|
||||
case CMD_RQLATER:
|
||||
case CMD_EAGAIN:
|
||||
if (XS_NOERR(xs)) {
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
result = TRY_AGAIN_LATER;
|
||||
break;
|
||||
case CMD_COMPLETE:
|
||||
result = COMPLETE;
|
||||
break;
|
||||
|
||||
}
|
||||
/*
|
||||
* If we can't use interrupts, poll on completion.
|
||||
*/
|
||||
if (isp_poll(isp, xs, XS_TIME(xs))) {
|
||||
/*
|
||||
* If no other error occurred but we didn't finish,
|
||||
* something bad happened.
|
||||
*/
|
||||
if (XS_IS_CMD_DONE(xs) == 0) {
|
||||
isp->isp_nactive--;
|
||||
if (isp->isp_nactive < 0)
|
||||
isp->isp_nactive = 0;
|
||||
if (XS_NOERR(xs)) {
|
||||
isp_lostcmd(isp, xs);
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
if (result == SUCCESSFULLY_QUEUED) {
|
||||
if (isp_poll(isp, xs, XS_TIME(xs))) {
|
||||
/*
|
||||
* If no other error occurred but we didn't finish,
|
||||
* something bad happened.
|
||||
*/
|
||||
if (XS_IS_CMD_DONE(xs) == 0) {
|
||||
if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
|
||||
isp_restart(isp);
|
||||
}
|
||||
if (XS_NOERR(xs)) {
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
}
|
||||
}
|
||||
result = COMPLETE;
|
||||
}
|
||||
(void) splx(s);
|
||||
return (CMD_COMPLETE);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -287,30 +362,31 @@ isp_watch(arg)
|
|||
{
|
||||
int i;
|
||||
struct ispsoftc *isp = arg;
|
||||
ISP_SCSI_XFER_T *xs;
|
||||
ISP_ILOCKVAL_DECL;
|
||||
struct scsipi_xfer *xs;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* Look for completely dead commands (but not polled ones).
|
||||
*/
|
||||
ISP_ILOCK(isp);
|
||||
for (i = 0; i < RQUEST_QUEUE_LEN; i++) {
|
||||
if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) {
|
||||
s = splbio();
|
||||
for (i = 0; i < isp->isp_maxcmds; i++) {
|
||||
xs = isp->isp_xflist[i];
|
||||
if (xs == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (XS_TIME(xs) == 0) {
|
||||
if (xs->timeout == 0 || (xs->xs_control & XS_CTL_POLL)) {
|
||||
continue;
|
||||
}
|
||||
XS_TIME(xs) -= (WATCH_INTERVAL * 1000);
|
||||
xs->timeout -= (WATCH_INTERVAL * 1000);
|
||||
/*
|
||||
* Avoid later thinking that this
|
||||
* transaction is not being timed.
|
||||
* Then give ourselves to watchdog
|
||||
* periods of grace.
|
||||
*/
|
||||
if (XS_TIME(xs) == 0) {
|
||||
XS_TIME(xs) = 1;
|
||||
} else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) {
|
||||
if (xs->timeout == 0) {
|
||||
xs->timeout = 1;
|
||||
} else if (xs->timeout > -(2 * WATCH_INTERVAL * 1000)) {
|
||||
continue;
|
||||
}
|
||||
if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) {
|
||||
|
@ -322,7 +398,7 @@ isp_watch(arg)
|
|||
}
|
||||
timeout(isp_watch, isp, WATCH_INTERVAL * hz);
|
||||
isp->isp_dogactive = 1;
|
||||
ISP_IUNLOCK(isp);
|
||||
(void) splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -354,6 +430,35 @@ isp_uninit(isp)
|
|||
ISP_IUNLOCK(isp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart function for a command to be requeued later.
|
||||
*/
|
||||
static void
|
||||
isp_command_requeue(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct scsipi_xfer *xs = arg;
|
||||
struct ispsoftc *isp = XS_ISP(xs);
|
||||
int s = splbio();
|
||||
switch (ispcmd_slow(xs)) {
|
||||
case SUCCESSFULLY_QUEUED:
|
||||
printf("%s: isp_command_reque: queued %d.%d\n",
|
||||
isp->isp_name, XS_TGT(xs), XS_LUN(xs));
|
||||
break;
|
||||
case TRY_AGAIN_LATER:
|
||||
printf("%s: EAGAIN for %d.%d\n",
|
||||
isp->isp_name, XS_TGT(xs), XS_LUN(xs));
|
||||
/* FALLTHROUGH */
|
||||
case COMPLETE:
|
||||
xs->xs_status |= XS_STS_DONE;
|
||||
if (XS_NOERR(xs)) {
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
}
|
||||
scsipi_done(xs);
|
||||
break;
|
||||
}
|
||||
(void) splx(s);
|
||||
}
|
||||
/*
|
||||
* Restart function after a LOOP UP event (e.g.),
|
||||
* done as a timeout for some hysteresis.
|
||||
|
@ -398,64 +503,64 @@ isp_async(isp, cmd, arg)
|
|||
int s = splbio();
|
||||
switch (cmd) {
|
||||
case ISPASYNC_NEW_TGT_PARAMS:
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
char *wt;
|
||||
int mhz, flags, period;
|
||||
if (IS_SCSI(isp) && isp->isp_dblev) {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
char *wt;
|
||||
int mhz, flags, period;
|
||||
|
||||
tgt = *((int *) arg);
|
||||
bus = (tgt >> 16) & 0xffff;
|
||||
tgt &= 0xffff;
|
||||
tgt = *((int *) arg);
|
||||
bus = (tgt >> 16) & 0xffff;
|
||||
tgt &= 0xffff;
|
||||
|
||||
flags = sdp->isp_devparam[tgt].cur_dflags;
|
||||
period = sdp->isp_devparam[tgt].cur_period;
|
||||
if ((flags & DPARM_SYNC) && period &&
|
||||
(sdp->isp_devparam[tgt].cur_offset) != 0) {
|
||||
if (sdp->isp_lvdmode) {
|
||||
switch (period) {
|
||||
case 0xa:
|
||||
mhz = 40;
|
||||
break;
|
||||
case 0xb:
|
||||
mhz = 33;
|
||||
break;
|
||||
case 0xc:
|
||||
mhz = 25;
|
||||
break;
|
||||
default:
|
||||
mhz = 1000 / (period * 4);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
flags = sdp->isp_devparam[tgt].cur_dflags;
|
||||
period = sdp->isp_devparam[tgt].cur_period;
|
||||
if ((flags & DPARM_SYNC) && period &&
|
||||
(sdp->isp_devparam[tgt].cur_offset) != 0) {
|
||||
if (sdp->isp_lvdmode) {
|
||||
switch (period) {
|
||||
case 0xa:
|
||||
mhz = 40;
|
||||
break;
|
||||
case 0xb:
|
||||
mhz = 33;
|
||||
break;
|
||||
case 0xc:
|
||||
mhz = 25;
|
||||
break;
|
||||
default:
|
||||
mhz = 1000 / (period * 4);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
mhz = 0;
|
||||
}
|
||||
switch (flags & (DPARM_WIDE|DPARM_TQING)) {
|
||||
case DPARM_WIDE:
|
||||
wt = ", 16 bit wide\n";
|
||||
break;
|
||||
case DPARM_TQING:
|
||||
wt = ", Tagged Queueing Enabled\n";
|
||||
break;
|
||||
case DPARM_WIDE|DPARM_TQING:
|
||||
wt = ", 16 bit wide, Tagged Queueing Enabled\n";
|
||||
break;
|
||||
default:
|
||||
wt = "\n";
|
||||
break;
|
||||
}
|
||||
if (mhz) {
|
||||
printf("%s: Bus %d Target %d at %dMHz Max "
|
||||
"Offset %d%s", isp->isp_name, bus, tgt, mhz,
|
||||
sdp->isp_devparam[tgt].cur_offset, wt);
|
||||
} else {
|
||||
printf("%s: Bus %d Target %d Async Mode%s",
|
||||
isp->isp_name, bus, tgt, wt);
|
||||
mhz = 1000 / (period * 4);
|
||||
}
|
||||
} else {
|
||||
mhz = 0;
|
||||
}
|
||||
switch (flags & (DPARM_WIDE|DPARM_TQING)) {
|
||||
case DPARM_WIDE:
|
||||
wt = ", 16 bit wide\n";
|
||||
break;
|
||||
case DPARM_TQING:
|
||||
wt = ", Tagged Queueing Enabled\n";
|
||||
break;
|
||||
case DPARM_WIDE|DPARM_TQING:
|
||||
wt = ", 16 bit wide, Tagged Queueing Enabled\n";
|
||||
break;
|
||||
default:
|
||||
wt = "\n";
|
||||
break;
|
||||
}
|
||||
if (mhz) {
|
||||
printf("%s: Bus %d Target %d at %dMHz Max "
|
||||
"Offset %d%s", isp->isp_name, bus, tgt, mhz,
|
||||
sdp->isp_devparam[tgt].cur_offset, wt);
|
||||
} else {
|
||||
printf("%s: Bus %d Target %d Async Mode%s",
|
||||
isp->isp_name, bus, tgt, wt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ISPASYNC_BUS_RESET:
|
||||
if (arg)
|
||||
bus = *((int *) arg);
|
||||
|
@ -477,7 +582,7 @@ isp_async(isp, cmd, arg)
|
|||
printf("%s: Loop UP\n", isp->isp_name);
|
||||
break;
|
||||
case ISPASYNC_PDB_CHANGED:
|
||||
if (IS_FC(isp)) {
|
||||
if (IS_FC(isp) && isp->isp_dblev) {
|
||||
const char *fmt = "%s: Target %d (Loop 0x%x) Port ID 0x%x "
|
||||
"role %s %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x\n";
|
||||
const static char *roles[4] = {
|
||||
|
|
Loading…
Reference in New Issue