MFP4: Move default setting to the end of isp_reset instead of the

front of isp_init so we can read NVRAM even if we're role ISP_NONE.
Prepare for reintroduction of channels (for FC) for N-Port
Virtualization.

Fix a botch in handle assignment that caused us to nuke one device
when a new one arrives and end up with two devices with the same
identity in the virtual target mapping table.
This commit is contained in:
mjacob 2007-01-20 04:00:21 +00:00
parent 8ea92215ce
commit 31cdd06b7a
7 changed files with 138 additions and 93 deletions

View File

@ -1170,6 +1170,14 @@ isp_reset(ispsoftc_t *isp)
isp->isp_maxluns = 16;
}
}
/*
* Must do this first to get defaults established.
*/
isp_setdfltparm(isp, 0);
if (IS_DUALBUS(isp)) {
isp_setdfltparm(isp, 1);
}
}
/*
@ -1181,14 +1189,6 @@ isp_reset(ispsoftc_t *isp)
void
isp_init(ispsoftc_t *isp)
{
/*
* Must do this first to get defaults established.
*/
isp_setdfltparm(isp, 0);
if (IS_DUALBUS(isp)) {
isp_setdfltparm(isp, 1);
}
if (IS_FC(isp)) {
/*
* Do this *before* initializing the firmware.
@ -3956,6 +3956,7 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp)
static uint16_t
isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
{
int i;
if (handle == NIL_HANDLE) {
if (FCPARAM(isp)->isp_topo == TOPO_F_PORT) {
handle = 0;
@ -3982,9 +3983,16 @@ isp_nxt_handle(ispsoftc_t *isp, uint16_t handle)
}
if (handle == FCPARAM(isp)->isp_loopid) {
return (isp_nxt_handle(isp, handle));
} else {
return (handle);
}
for (i = 0; i < MAX_FC_TARG; i++) {
if (FCPARAM(isp)->portdb[i].state == FC_PORTDB_STATE_NIL) {
continue;
}
if (FCPARAM(isp)->portdb[i].handle == handle) {
return (isp_nxt_handle(isp, handle));
}
}
return (handle);
}
/*
@ -7034,15 +7042,16 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
fcp->isp_retry_count = ICB_DFLT_RCOUNT;
/* Platform specific.... */
fcp->isp_loopid = DEFAULT_LOOPID(isp);
fcp->isp_nodewwn = DEFAULT_NODEWWN(isp);
fcp->isp_portwwn = DEFAULT_PORTWWN(isp);
fcp->isp_wwnn_nvram = DEFAULT_NODEWWN(isp);
fcp->isp_wwpn_nvram = DEFAULT_PORTWWN(isp);
fcp->isp_fwoptions = 0;
fcp->isp_fwoptions |= ICBOPT_FAIRNESS;
fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE;
fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS;
fcp->isp_fwoptions |= ICBOPT_FAST_POST;
if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX)
if (isp->isp_confopts & ISP_CFG_FULL_DUPLEX) {
fcp->isp_fwoptions |= ICBOPT_FULL_DUPLEX;
}
/*
* Make sure this is turned off now until we get
@ -7052,7 +7061,7 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
/*
* Now try and read NVRAM unless told to not do so.
* This will set fcparam's isp_nodewwn && isp_portwwn.
* This will set fcparam's isp_wwnn_nvram && isp_wwpn_nvram.
*/
if ((isp->isp_confopts & ISP_CFG_NONVRAM) == 0) {
nvfail = isp_read_nvram(isp);
@ -7081,8 +7090,8 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
* We always start out with values derived
* from NVRAM or our platform default.
*/
ISP_NODEWWN(isp) = fcp->isp_nodewwn;
if (fcp->isp_nodewwn == 0) {
ISP_NODEWWN(isp) = fcp->isp_wwnn_nvram;
if (fcp->isp_wwnn_nvram == 0) {
isp_prt(isp, ISP_LOGCONFIG,
"bad WWNN- using default");
ISP_NODEWWN(isp) = DEFAULT_NODEWWN(isp);
@ -7098,8 +7107,8 @@ isp_setdfltparm(ispsoftc_t *isp, int channel)
* We always start out with values derived
* from NVRAM or our platform default.
*/
ISP_PORTWWN(isp) = fcp->isp_portwwn;
if (fcp->isp_portwwn == 0) {
ISP_PORTWWN(isp) = fcp->isp_wwpn_nvram;
if (fcp->isp_wwpn_nvram == 0) {
isp_prt(isp, ISP_LOGCONFIG,
"bad WWPN- using default");
ISP_PORTWWN(isp) = DEFAULT_PORTWWN(isp);
@ -7841,10 +7850,10 @@ isp_fix_nvram_wwns(ispsoftc_t *isp)
/*
* Make sure we have both Node and Port as non-zero values.
*/
if (fcp->isp_nodewwn != 0 && fcp->isp_portwwn == 0) {
fcp->isp_portwwn = fcp->isp_nodewwn;
} else if (fcp->isp_nodewwn == 0 && fcp->isp_portwwn != 0) {
fcp->isp_nodewwn = fcp->isp_portwwn;
if (fcp->isp_wwnn_nvram != 0 && fcp->isp_wwpn_nvram == 0) {
fcp->isp_wwpn_nvram = fcp->isp_wwnn_nvram;
} else if (fcp->isp_wwnn_nvram == 0 && fcp->isp_wwpn_nvram != 0) {
fcp->isp_wwnn_nvram = fcp->isp_wwpn_nvram;
}
/*
@ -7853,14 +7862,14 @@ isp_fix_nvram_wwns(ispsoftc_t *isp)
* make sure that there's some non-zero value in 48..56
* for the Port WWN.
*/
if (fcp->isp_nodewwn && fcp->isp_portwwn) {
if ((fcp->isp_nodewwn & (((uint64_t) 0xfff) << 48)) != 0 &&
(fcp->isp_nodewwn >> 60) == 2) {
fcp->isp_nodewwn &= ~((uint64_t) 0xfff << 48);
if (fcp->isp_wwnn_nvram && fcp->isp_wwpn_nvram) {
if ((fcp->isp_wwnn_nvram & (((uint64_t) 0xfff) << 48)) != 0 &&
(fcp->isp_wwnn_nvram >> 60) == 2) {
fcp->isp_wwnn_nvram &= ~((uint64_t) 0xfff << 48);
}
if ((fcp->isp_portwwn & (((uint64_t) 0xfff) << 48)) == 0 &&
(fcp->isp_portwwn >> 60) == 2) {
fcp->isp_portwwn |= ((uint64_t) 1 << 56);
if ((fcp->isp_wwpn_nvram & (((uint64_t) 0xfff) << 48)) == 0 &&
(fcp->isp_wwpn_nvram >> 60) == 2) {
fcp->isp_wwpn_nvram |= ((uint64_t) 1 << 56);
}
}
}
@ -7890,7 +7899,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
wwn |= (((uint64_t) 2)<< 60);
}
}
fcp->isp_portwwn = wwn;
fcp->isp_wwpn_nvram = wwn;
if (IS_2200(isp) || IS_23XX(isp)) {
wwn = ISP2100_NVRAM_NODE_NAME(nvram_data);
if (wwn) {
@ -7904,7 +7913,7 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
} else {
wwn &= ~((uint64_t) 0xfff << 48);
}
fcp->isp_nodewwn = wwn;
fcp->isp_wwnn_nvram = wwn;
isp_fix_nvram_wwns(isp);
@ -7924,8 +7933,8 @@ isp_parse_nvram_2100(ispsoftc_t *isp, uint8_t *nvram_data)
fcp->isp_fwoptions = ISP2100_NVRAM_OPTIONS(nvram_data);
isp_prt(isp, ISP_LOGDEBUG0,
"NVRAM 0x%08x%08x 0x%08x%08x maxalloc %d maxframelen %d",
(uint32_t) (fcp->isp_nodewwn >> 32), (uint32_t) fcp->isp_nodewwn,
(uint32_t) (fcp->isp_portwwn >> 32), (uint32_t) fcp->isp_portwwn,
(uint32_t) (fcp->isp_wwnn_nvram >> 32), (uint32_t) fcp->isp_wwnn_nvram,
(uint32_t) (fcp->isp_wwpn_nvram >> 32), (uint32_t) fcp->isp_wwpn_nvram,
ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data),
ISP2100_NVRAM_MAXFRAMELENGTH(nvram_data));
isp_prt(isp, ISP_LOGDEBUG0,
@ -7969,7 +7978,7 @@ isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
wwn = 0;
}
}
fcp->isp_portwwn = wwn;
fcp->isp_wwpn_nvram = wwn;
wwn = ISP2400_NVRAM_NODE_NAME(nvram_data);
if (wwn) {
@ -7977,7 +7986,7 @@ isp_parse_nvram_2400(ispsoftc_t *isp, uint8_t *nvram_data)
wwn = 0;
}
}
fcp->isp_nodewwn = wwn;
fcp->isp_wwnn_nvram = wwn;
isp_fix_nvram_wwns(isp);

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#endif
#include <cam/cam_periph.h>
#include <cam/cam_xpt_periph.h>
#if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025
#define CAM_NEW_TRAN_CODE 1
@ -485,8 +486,8 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
hba->fc_scsi_supported = 1;
hba->fc_topology = FCPARAM(isp)->isp_topo + 1;
hba->fc_loopid = FCPARAM(isp)->isp_loopid;
hba->nvram_node_wwn = FCPARAM(isp)->isp_nodewwn;
hba->nvram_port_wwn = FCPARAM(isp)->isp_portwwn;
hba->nvram_node_wwn = FCPARAM(isp)->isp_wwnn_nvram;
hba->nvram_port_wwn = FCPARAM(isp)->isp_wwpn_nvram;
hba->active_node_wwn = ISP_NODEWWN(isp);
hba->active_port_wwn = ISP_PORTWWN(isp);
}
@ -1670,7 +1671,7 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
* Construct a tag 'id' based upon tag value (which may be 0..255)
* and the handle (which we have to preserve).
*/
AT_MAKE_TAGID(atiop->tag_id, device_get_unit(isp->isp_dev), aep);
AT_MAKE_TAGID(atiop->tag_id, bus, device_get_unit(isp->isp_dev), aep);
if (aep->at_flags & AT_TQAE) {
atiop->tag_action = aep->at_tag_type;
atiop->ccb_h.status |= CAM_TAG_ACTION_VALID;

View File

@ -346,8 +346,8 @@ default: \
#define DEFAULT_LOOPID(x) (isp)->isp_osinfo.default_id
#define DEFAULT_NODEWWN(isp) (isp)->isp_osinfo.default_node_wwn
#define DEFAULT_PORTWWN(isp) (isp)->isp_osinfo.default_port_wwn
#define ISP_NODEWWN(isp) FCPARAM(isp)->isp_nodewwn
#define ISP_PORTWWN(isp) FCPARAM(isp)->isp_portwwn
#define ISP_NODEWWN(isp) FCPARAM(isp)->isp_wwnn_nvram
#define ISP_PORTWWN(isp) FCPARAM(isp)->isp_wwpn_nvram
#if BYTE_ORDER == BIG_ENDIAN
#ifdef ISP_SBUS_SUPPORTED

View File

@ -827,7 +827,7 @@ isp_got_msg(ispsoftc_t *isp, in_entry_t *inp)
nt.nt_iid = GET_IID_VAL(inp->in_iid);
nt.nt_tgt = inp->in_tgt;
nt.nt_lun = inp->in_lun;
IN_MAKE_TAGID(nt.nt_tagval, 0, inp);
IN_MAKE_TAGID(nt.nt_tagval, GET_BUS_VAL(inp->in_iid), 0, inp);
nt.nt_lreserved = inp;
if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) {
@ -875,8 +875,7 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
{
tmd_notify_t nt;
static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
static const char f2[] =
"unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
uint16_t seqid, loopid;
MEMZERO(&nt, sizeof (tmd_notify_t));
@ -896,7 +895,7 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
} else {
nt.nt_lun = inp->in_lun;
}
IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid);
IN_FC_MAKE_TAGID(nt.nt_tagval, 0, 0, seqid);
nt.nt_need_ack = 1;
nt.nt_lreserved = inp;
@ -941,9 +940,9 @@ static void
isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
{
tmd_notify_t nt;
static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x";
static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%llx";
static const char f2[] =
"unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n";
"unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%llx\n";
uint32_t sid;
MEMZERO(&nt, sizeof (tmd_notify_t));
@ -952,6 +951,9 @@ isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
nt.nt_lun =
(aep->at_cmnd.fcp_cmnd_lun[0] << 8) |
(aep->at_cmnd.fcp_cmnd_lun[1]);
/*
* XXX: VPIDX HAS TO BE DERIVED FROM DESTINATION PORT
*/
nt.nt_tagval = aep->at_rxid;
nt.nt_lreserved = aep;
sid =

View File

@ -325,13 +325,13 @@ typedef struct {
* Macros to create and fetch and test concatenated handle and tag value macros
*/
#define AT_MAKE_TAGID(tid, inst, aep) \
#define AT_MAKE_TAGID(tid, bus, inst, aep) \
tid = aep->at_handle; \
if (aep->at_flags & AT_TQAE) { \
tid |= (aep->at_tag_val << 16); \
tid |= (1 << 24); \
} \
tid |= (GET_BUS_VAL(aep->at_iid) << 25); \
tid |= (bus << 25); \
tid |= (inst << 26)
#define CT_MAKE_TAGID(tid, bus, inst, ct) \
@ -349,11 +349,11 @@ typedef struct {
#define AT_GET_BUS(val) (((val) >> 25) & 0x1)
#define AT_GET_HANDLE(val) ((val) & 0xffff)
#define IN_MAKE_TAGID(tid, inst, inp) \
#define IN_MAKE_TAGID(tid, bus, inst, inp) \
tid = inp->in_seqid; \
tid |= (inp->in_tag_val << 16); \
tid |= (1 << 24); \
tid |= (GET_BUS_VAL(inp->in_iid) << 25); \
tid |= (bus << 25); \
tid |= (inst << 26)
#define TAG_INSERT_INST(tid, inst) \
@ -423,31 +423,35 @@ typedef struct {
/*
* Macros to create and fetch and test concatenated handle and tag value macros
*/
#define AT2_MAKE_TAGID(tid, inst, aep) \
#define AT2_MAKE_TAGID(tid, bus, inst, aep) \
tid = aep->at_rxid; \
tid |= (inst << 16)
tid |= (((uint64_t)inst) << 32); \
tid |= (((uint64_t)bus) << 48)
#define CT2_MAKE_TAGID(tid, inst, ct) \
#define CT2_MAKE_TAGID(tid, bus, inst, ct) \
tid = ct->ct_rxid; \
tid |= (inst << 16)
tid |= (((uint64_t)inst) << 32); \
tid |= (((uint64_t)(bus & 0xff)) << 48)
#define AT2_HAS_TAG(val) 1
#define AT2_GET_TAG(val) ((val) & 0xffff)
#define AT2_GET_INST(val) ((val) >> 16)
#define AT2_GET_TAG(val) ((val) & 0xffffffff)
#define AT2_GET_INST(val) ((val) >> 32)
#define AT2_GET_HANDLE AT2_GET_TAG
#define AT2_GET_BUS(val) (((val) >> 48) & 0xff)
#define FC_HAS_TAG AT2_HAS_TAG
#define FC_GET_TAG AT2_GET_TAG
#define FC_GET_INST AT2_GET_INST
#define FC_GET_HANDLE AT2_GET_HANDLE
#define IN_FC_MAKE_TAGID(tid, inst, seqid) \
#define IN_FC_MAKE_TAGID(tid, bus, inst, seqid) \
tid = seqid; \
tid |= (inst << 16)
tid |= (((uint64_t)inst) << 32); \
tid |= (((uint64_t)(bus & 0xff)) << 48)
#define FC_TAG_INSERT_INST(tid, inst) \
tid &= ~0xffff; \
tid |= (inst << 16)
tid &= ~0xffff00000000ull; \
tid |= (((uint64_t)inst) << 32)
/*
* 24XX ATIO Definition

View File

@ -53,6 +53,8 @@ typedef enum {
*/
typedef enum {
QIN_HBA_REG=99, /* the argument is a pointer to a hba_register_t */
QIN_GETINFO, /* the argument is a pointer to a info_t */
QIN_SETINFO, /* the argument is a pointer to a info_t */
QIN_ENABLE, /* the argument is a pointer to a enadis_t */
QIN_DISABLE, /* the argument is a pointer to a enadis_t */
QIN_TMD_CONT, /* the argument is a pointer to a tmd_cmd_t */
@ -71,31 +73,42 @@ typedef enum {
* in, and the external module to call back with a QIN_HBA_REG that
* passes back the corresponding information.
*/
#define QR_VERSION 13
#define QR_VERSION 15
typedef struct {
/* NB: tags from here to r_version must never change */
void * r_identity;
void (*r_action)(qact_e, void *);
char r_name[8];
int r_inst;
int r_version;
struct {
enum {
R_FC,
R_SCSI
} r_type;
union {
struct {
uint64_t r_wwnn;
uint64_t r_wwpn;
} fc;
struct {
int r_iid;
} scsi;
} r_id;
} r_info;
uint32_t r_locator;
uint32_t r_nchannels;
enum { R_FC, R_SPI } r_type;
void * r_private;
} hba_register_t;
/*
* An information structure that is used to get or set per-channel
* transport layer parameters.
*/
typedef struct {
void * i_identity;
enum { I_FC, I_SPI } i_type;
int i_channel;
int i_error;
union {
struct {
uint64_t wwnn_nvram;
uint64_t wwpn_nvram;
uint64_t wwnn;
uint64_t wwpn;
} fc;
struct {
int iid;
} spi;
} i_id;
} info_t;
/*
* Notify structure
*/
@ -121,7 +134,8 @@ typedef struct tmd_notify {
uint16_t nt_lun; /* logical unit */
uint16_t : 15,
nt_need_ack : 1; /* this notify needs an ACK */
uint32_t nt_tagval; /* tag value */
uint64_t nt_tagval; /* tag value */
uint32_t nt_channel; /* channel id */
tmd_ncode_t nt_ncode; /* action */
void * nt_lreserved;
void * nt_hreserved;
@ -129,7 +143,7 @@ typedef struct tmd_notify {
#define LUN_ANY 0xffff
#define TGT_ANY ((uint64_t) -1)
#define INI_ANY ((uint64_t) -1)
#define TAG_ANY 0
#define TAG_ANY ((uint64_t) 0)
#define MATCH_TMD(tmd, iid, lun, tag) \
( \
(tmd) && \
@ -276,16 +290,16 @@ typedef struct tmd_cmd {
void * cd_data; /* 'pointer' to data */
uint64_t cd_iid; /* initiator ID */
uint64_t cd_tgt; /* target id */
uint64_t cd_lun; /* logical unit */
uint32_t cd_tagval; /* tag value */
uint8_t cd_lun[8]; /* logical unit */
uint64_t cd_tagval; /* tag value */
uint32_t cd_channel; /* channel index */
uint32_t cd_lflags; /* flags lower level sets */
uint32_t cd_hflags; /* flags higher level sets */
uint32_t cd_totlen; /* total data load */
uint32_t cd_resid; /* total data residual */
uint32_t cd_xfrlen; /* current data load */
int32_t cd_error; /* current error */
uint8_t cd_tagtype : 4,
cd_port : 4; /* port number on HBA */
uint8_t cd_tagtype; /* tag type */
uint8_t cd_scsi_status;
uint8_t cd_sense[TMD_SENSELEN];
uint8_t cd_cdb[TMD_CDBLEN];
@ -309,6 +323,21 @@ typedef struct tmd_cmd {
#define TMD_SIZE (sizeof (tmd_cmd_t))
#endif
#define L0LUN_TO_FLATLUN(lptr) ((((lptr)[0] & 0x3f) << 8) | ((lptr)[1]))
#define FLATLUN_TO_L0LUN(lptr, lun) \
(lptr)[1] = lun; \
if (sizeof (lun) == 1) { \
(lptr)[0] = 0; \
} else { \
int nl = (lun); \
if (nl < 256) { \
(lptr)[0] = 0; \
} else { \
(lptr)[0] = 0x40 | ((nl >> 8) & 0x3f); \
} \
} \
memset(&(lptr)[2], 0, 6)
/*
* Note that NODISC (obviously) doesn't apply to non-SPI transport.
*

View File

@ -380,8 +380,8 @@ typedef struct {
uint8_t isp_reserved;
uint16_t isp_maxalloc;
uint16_t isp_maxfrmlen;
uint64_t isp_nodewwn;
uint64_t isp_portwwn;
uint64_t isp_wwnn_nvram;
uint64_t isp_wwpn_nvram;
/*
* Our Port Data Base
@ -980,25 +980,25 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
*
*
* DEFAULT_IID(ispsoftc_t *) Default SCSI initiator ID
* DEFAULT_LOOPID(ispsoftc_t *) Default FC Loop ID
* DEFAULT_NODEWWN(ispsoftc_t *) Default Node WWN
* DEFAULT_PORTWWN(ispsoftc_t *) Default Port WWN
* DEFAULT_FRAMESIZE(ispsoftc_t *) Default Frame Size
* DEFAULT_LOOPID(ispsoftc_t *) Default FC Loop ID
* DEFAULT_NODEWWN(ispsoftc_t *) Default Node WWN
* DEFAULT_PORTWWN(ispsoftc_t *) Default Port WWN
* DEFAULT_FRAMESIZE(ispsoftc_t *) Default Frame Size
* DEFAULT_EXEC_THROTTLE(ispsoftc_t *) Default Execution Throttle
* These establish reasonable defaults for each platform.
* These must be available independent of card NVRAM and are
* to be used should NVRAM not be readable.
*
* ISP_NODEWWN(ispsoftc_t *) FC Node WWN to use
* ISP_PORTWWN(ispsoftc_t *) FC Port WWN to use
* ISP_NODEWWN(ispsoftc_t *) FC Node WWN to use
* ISP_PORTWWN(ispsoftc_t *) FC Port WWN to use
*
* These are to be used after NVRAM is read. The tags
* in fcparam.isp_{node,port}wwn reflect the values
* in fcparam.isp_ww{n,p}n_nvram reflect the values
* read from NVRAM (possibly corrected for card botches).
* Each platform can take that information and override
* it or ignore and return the Node and Port WWNs to be
* used when sending the Qlogic f/w the Initialization Control
* Block.
* used when sending the Qlogic f/w the Initialization
* Control Block.
*
* (XXX these do endian specific transformations- in transition XXX)
*