mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
Major rewrite of DMA mapping code to reduce code duplication
and to allow some debug and enhancements that will be easier soon. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@679 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -4316,12 +4316,12 @@ int
|
||||
isp_start(XS_T *xs)
|
||||
{
|
||||
ispsoftc_t *isp;
|
||||
uint32_t nxti, optr, handle;
|
||||
uint32_t handle;
|
||||
uint8_t local[QENTRY_LEN];
|
||||
ispreq_t *reqp, *qep;
|
||||
void *cdbp;
|
||||
ispreq_t *reqp;
|
||||
void *cdbp, *qep;
|
||||
uint16_t *tptr;
|
||||
int target, i, hdlidx = 0;
|
||||
int target, dmaresult, hdlidx = 0;
|
||||
|
||||
XS_INITERR(xs);
|
||||
isp = XS_ISP(xs);
|
||||
@@ -4344,9 +4344,7 @@ isp_start(XS_T *xs)
|
||||
*/
|
||||
|
||||
if (XS_CDBLEN(xs) > (IS_FC(isp)? 16 : 44) || XS_CDBLEN(xs) == 0) {
|
||||
isp_prt(isp, ISP_LOGERR,
|
||||
"unsupported cdb length (%d, CDB[0]=0x%x)",
|
||||
XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
|
||||
isp_prt(isp, ISP_LOGERR, "unsupported cdb length (%d, CDB[0]=0x%x)", XS_CDBLEN(xs), XS_CDBP(xs)[0] & 0xff);
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
return (CMD_COMPLETE);
|
||||
}
|
||||
@@ -4378,8 +4376,7 @@ isp_start(XS_T *xs)
|
||||
}
|
||||
|
||||
hdlidx = fcp->isp_dev_map[XS_TGT(xs)] - 1;
|
||||
isp_prt(isp, ISP_LOGDEBUG1, "XS_TGT(xs)=%d- hdlidx value %d",
|
||||
XS_TGT(xs), hdlidx);
|
||||
isp_prt(isp, ISP_LOGDEBUG2, "XS_TGT(xs)=%d- hdlidx value %d", XS_TGT(xs), hdlidx);
|
||||
if (hdlidx < 0 || hdlidx >= MAX_FC_TARG) {
|
||||
XS_SETERR(xs, HBA_SELTIMEOUT);
|
||||
return (CMD_COMPLETE);
|
||||
@@ -4405,11 +4402,13 @@ isp_start(XS_T *xs)
|
||||
|
||||
start_again:
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, (void *)&qep)) {
|
||||
qep = isp_getrqentry(isp);
|
||||
if (qep == NULL) {
|
||||
isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow");
|
||||
XS_SETERR(xs, HBA_BOTCH);
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
XS_SETERR(xs, HBA_NOERROR);
|
||||
|
||||
/*
|
||||
* Now see if we need to synchronize the ISP with respect to anything.
|
||||
@@ -4417,39 +4416,38 @@ isp_start(XS_T *xs)
|
||||
* than which we got here to send a command to.
|
||||
*/
|
||||
reqp = (ispreq_t *) local;
|
||||
ISP_MEMZERO(local, QENTRY_LEN);
|
||||
if (ISP_TST_SENDMARKER(isp, XS_CHANNEL(xs))) {
|
||||
if (IS_24XX(isp)) {
|
||||
isp_marker_24xx_t *m = (isp_marker_24xx_t *) qep;
|
||||
ISP_MEMZERO(m, QENTRY_LEN);
|
||||
isp_marker_24xx_t *m = (isp_marker_24xx_t *) reqp;
|
||||
m->mrk_header.rqs_entry_count = 1;
|
||||
m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
|
||||
m->mrk_modifier = SYNC_ALL;
|
||||
isp_put_marker_24xx(isp, m, (isp_marker_24xx_t *)qep);
|
||||
isp_put_marker_24xx(isp, m, qep);
|
||||
} else {
|
||||
isp_marker_t *m = (isp_marker_t *) qep;
|
||||
ISP_MEMZERO(m, QENTRY_LEN);
|
||||
isp_marker_t *m = (isp_marker_t *) reqp;
|
||||
m->mrk_header.rqs_entry_count = 1;
|
||||
m->mrk_header.rqs_entry_type = RQSTYPE_MARKER;
|
||||
m->mrk_target = (XS_CHANNEL(xs) << 7); /* bus # */
|
||||
m->mrk_modifier = SYNC_ALL;
|
||||
isp_put_marker(isp, m, (isp_marker_t *) qep);
|
||||
isp_put_marker(isp, m, qep);
|
||||
}
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
ISP_SET_SENDMARKER(isp, XS_CHANNEL(xs), 0);
|
||||
goto start_again;
|
||||
}
|
||||
|
||||
ISP_MEMZERO((void *)reqp, QENTRY_LEN);
|
||||
reqp->req_header.rqs_entry_count = 1;
|
||||
if (IS_24XX(isp)) {
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_T7RQS;
|
||||
} else if (IS_FC(isp)) {
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS;
|
||||
} else {
|
||||
if (XS_CDBLEN(xs) > 12)
|
||||
if (XS_CDBLEN(xs) > 12) {
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_CMDONLY;
|
||||
else
|
||||
} else {
|
||||
reqp->req_header.rqs_entry_type = RQSTYPE_REQUEST;
|
||||
}
|
||||
}
|
||||
/* reqp->req_header.rqs_flags = 0; */
|
||||
/* reqp->req_header.rqs_seqno = 0; */
|
||||
@@ -4497,8 +4495,7 @@ isp_start(XS_T *xs)
|
||||
}
|
||||
} else {
|
||||
sdparam *sdp = SDPARAM(isp, XS_CHANNEL(xs));
|
||||
if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) &&
|
||||
XS_TAG_P(xs)) {
|
||||
if ((sdp->isp_devparam[target].actv_flags & DPARM_TQING) && XS_TAG_P(xs)) {
|
||||
reqp->req_flags = XS_TAG_TYPE(xs);
|
||||
}
|
||||
}
|
||||
@@ -4553,24 +4550,21 @@ isp_start(XS_T *xs)
|
||||
reqp->req_handle = handle;
|
||||
|
||||
/*
|
||||
* Set up DMA and/or do any bus swizzling of the request entry
|
||||
* Set up DMA and/or do any platform dependent swizzling of the request entry
|
||||
* so that the Qlogic F/W understands what is being asked of it.
|
||||
*
|
||||
* The callee is responsible for adding all requests at this point.
|
||||
*/
|
||||
i = ISP_DMASETUP(isp, xs, reqp, &nxti, optr);
|
||||
if (i != CMD_QUEUED) {
|
||||
dmaresult = ISP_DMASETUP(isp, xs, reqp);
|
||||
if (dmaresult != CMD_QUEUED) {
|
||||
isp_destroy_handle(isp, handle);
|
||||
/*
|
||||
* dmasetup sets actual error in packet, and
|
||||
* return what we were given to return.
|
||||
*/
|
||||
return (i);
|
||||
return (dmaresult);
|
||||
}
|
||||
XS_SETERR(xs, HBA_NOERROR);
|
||||
isp_prt(isp, ISP_LOGDEBUG0,
|
||||
"START cmd for %d.%d.%d cmd 0x%x datalen %ld",
|
||||
XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0],
|
||||
(long) XS_XFRLEN(xs));
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
isp_prt(isp, ISP_LOGDEBUG0, "START cmd for %d.%d.%d cmd 0x%x datalen %ld", XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs), XS_CDBP(xs)[0], (long) XS_XFRLEN(xs));
|
||||
isp->isp_nactive++;
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,200 @@ const char *isp_class3_roles[4] = {
|
||||
"None", "Target", "Initiator", "Target/Initiator"
|
||||
};
|
||||
|
||||
/*
|
||||
* Command shipping- finish off first queue entry and do dma mapping and
|
||||
* additional segments as needed.
|
||||
*
|
||||
* Called with the first queue entry at least partially filled out.
|
||||
*/
|
||||
int
|
||||
isp_send_cmd(ispsoftc_t *isp, void *fqe, void *segp, uint32_t nsegs, uint32_t totalcnt, isp_ddir_t ddir)
|
||||
{
|
||||
uint8_t storage[QENTRY_LEN];
|
||||
uint8_t type, nqe;
|
||||
uint32_t seg, curseg, seglim, nxt, nxtnxt, ddf;
|
||||
ispds_t *dsp = NULL;
|
||||
ispds64_t *dsp64 = NULL;
|
||||
void *qe0, *qe1;
|
||||
|
||||
qe0 = isp_getrqentry(isp);
|
||||
if (qe0 == NULL) {
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
nxt = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp));
|
||||
|
||||
type = ((isphdr_t *)fqe)->rqs_entry_type;
|
||||
nqe = 1;
|
||||
|
||||
/*
|
||||
* If we have no data to transmit, just copy the first IOCB and start it up.
|
||||
*/
|
||||
if (ddir == ISP_NOXFR) {
|
||||
if (type == RQSTYPE_T2RQS || type == RQSTYPE_T3RQS) {
|
||||
ddf = CT2_NO_DATA;
|
||||
} else {
|
||||
ddf = 0;
|
||||
}
|
||||
goto copy_and_sync;
|
||||
}
|
||||
|
||||
/*
|
||||
* First figure out how many pieces of data to transfer and what kind and how many we can put into the first queue entry.
|
||||
*/
|
||||
switch (type) {
|
||||
case RQSTYPE_REQUEST:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
|
||||
dsp = ((ispreq_t *)fqe)->req_dataseg;
|
||||
seglim = ISP_RQDSEG;
|
||||
break;
|
||||
case RQSTYPE_CMDONLY:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
|
||||
seglim = 0;
|
||||
break;
|
||||
case RQSTYPE_T2RQS:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
|
||||
dsp = ((ispreqt2_t *)fqe)->req_dataseg;
|
||||
seglim = ISP_RQDSEG_T2;
|
||||
break;
|
||||
case RQSTYPE_A64:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? REQFLAG_DATA_OUT : REQFLAG_DATA_IN;
|
||||
dsp64 = ((ispreqt3_t *)fqe)->req_dataseg;
|
||||
seglim = ISP_RQDSEG_T3;
|
||||
break;
|
||||
case RQSTYPE_T3RQS:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? CT2_DATA_OUT : CT2_DATA_IN;
|
||||
dsp64 = ((ispreqt3_t *)fqe)->req_dataseg;
|
||||
seglim = ISP_RQDSEG_T3;
|
||||
break;
|
||||
case RQSTYPE_T7RQS:
|
||||
ddf = (ddir == ISP_TO_DEVICE)? FCP_CMND_DATA_WRITE : FCP_CMND_DATA_READ;
|
||||
dsp64 = &((ispreqt7_t *)fqe)->req_dataseg;
|
||||
seglim = 1;
|
||||
break;
|
||||
default:
|
||||
return (CMD_COMPLETE);
|
||||
}
|
||||
|
||||
if (seglim > nsegs) {
|
||||
seglim = nsegs;
|
||||
}
|
||||
|
||||
for (seg = curseg = 0; curseg < seglim; curseg++) {
|
||||
if (dsp64) {
|
||||
XS_GET_DMA64_SEG(dsp64++, segp, seg++);
|
||||
} else {
|
||||
XS_GET_DMA_SEG(dsp++, segp, seg++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Second, start building additional continuation segments as needed.
|
||||
*/
|
||||
while (seg < nsegs) {
|
||||
nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
|
||||
if (nxtnxt == isp->isp_reqodx) {
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
ISP_MEMZERO(storage, QENTRY_LEN);
|
||||
qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
|
||||
nxt = nxtnxt;
|
||||
if (dsp64) {
|
||||
ispcontreq64_t *crq = (ispcontreq64_t *) storage;
|
||||
seglim = ISP_CDSEG64;
|
||||
crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
|
||||
crq->req_header.rqs_entry_count = 1;
|
||||
dsp64 = crq->req_dataseg;
|
||||
} else {
|
||||
ispcontreq_t *crq = (ispcontreq_t *) storage;
|
||||
seglim = ISP_CDSEG;
|
||||
crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
|
||||
crq->req_header.rqs_entry_count = 1;
|
||||
dsp = crq->req_dataseg;
|
||||
}
|
||||
if (seg + seglim > nsegs) {
|
||||
seglim = nsegs - seg;
|
||||
}
|
||||
for (curseg = 0; curseg < seglim; curseg++) {
|
||||
if (dsp64) {
|
||||
XS_GET_DMA64_SEG(dsp64++, segp, seg++);
|
||||
} else {
|
||||
XS_GET_DMA_SEG(dsp++, segp, seg++);
|
||||
}
|
||||
}
|
||||
if (dsp64) {
|
||||
isp_put_cont64_req(isp, (ispcontreq64_t *)storage, qe1);
|
||||
} else {
|
||||
isp_put_cont_req(isp, (ispcontreq_t *)storage, qe1);
|
||||
}
|
||||
if (isp->isp_dblev & ISP_LOGDEBUG1) {
|
||||
isp_print_bytes(isp, "additional queue entry", QENTRY_LEN, storage);
|
||||
}
|
||||
nqe++;
|
||||
}
|
||||
|
||||
copy_and_sync:
|
||||
((isphdr_t *)fqe)->rqs_entry_count = nqe;
|
||||
switch (type) {
|
||||
case RQSTYPE_REQUEST:
|
||||
((ispreq_t *)fqe)->req_flags |= ddf;
|
||||
/*
|
||||
* This is historical and not clear whether really needed.
|
||||
*/
|
||||
if (nsegs == 0) {
|
||||
nsegs = 1;
|
||||
}
|
||||
((ispreq_t *)fqe)->req_seg_count = nsegs;
|
||||
isp_put_request(isp, fqe, qe0);
|
||||
break;
|
||||
case RQSTYPE_CMDONLY:
|
||||
((ispreq_t *)fqe)->req_flags |= ddf;
|
||||
/*
|
||||
* This is historical and not clear whether really needed.
|
||||
*/
|
||||
if (nsegs == 0) {
|
||||
nsegs = 1;
|
||||
}
|
||||
((ispextreq_t *)fqe)->req_seg_count = nsegs;
|
||||
isp_put_extended_request(isp, fqe, qe0);
|
||||
break;
|
||||
case RQSTYPE_T2RQS:
|
||||
((ispreqt2_t *)fqe)->req_flags |= ddf;
|
||||
((ispreqt2_t *)fqe)->req_seg_count = nsegs;
|
||||
((ispreqt2_t *)fqe)->req_totalcnt = totalcnt;
|
||||
if (ISP_CAP_SCCFW(isp)) {
|
||||
isp_put_request_t2e(isp, fqe, qe0);
|
||||
} else {
|
||||
isp_put_request_t2(isp, fqe, qe0);
|
||||
}
|
||||
break;
|
||||
case RQSTYPE_A64:
|
||||
case RQSTYPE_T3RQS:
|
||||
((ispreqt3_t *)fqe)->req_flags |= ddf;
|
||||
((ispreqt3_t *)fqe)->req_seg_count = nsegs;
|
||||
((ispreqt3_t *)fqe)->req_totalcnt = totalcnt;
|
||||
if (ISP_CAP_SCCFW(isp)) {
|
||||
isp_put_request_t3e(isp, fqe, qe0);
|
||||
} else {
|
||||
isp_put_request_t3(isp, fqe, qe0);
|
||||
}
|
||||
break;
|
||||
case RQSTYPE_T7RQS:
|
||||
((ispreqt7_t *)fqe)->req_alen_datadir = ddf;
|
||||
((ispreqt7_t *)fqe)->req_seg_count = nsegs;
|
||||
((ispreqt7_t *)fqe)->req_dl = totalcnt;
|
||||
isp_put_request_t7(isp, fqe, qe0);
|
||||
break;
|
||||
default:
|
||||
return (CMD_COMPLETE);
|
||||
}
|
||||
if (isp->isp_dblev & ISP_LOGDEBUG1) {
|
||||
isp_print_bytes(isp, "first queue entry", QENTRY_LEN, fqe);
|
||||
}
|
||||
ISP_ADD_REQUEST(isp, nxt);
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
int
|
||||
isp_save_xs(ispsoftc_t *isp, XS_T *xs, uint32_t *handlep)
|
||||
{
|
||||
@@ -142,24 +336,20 @@ isp_destroy_handle(ispsoftc_t *isp, uint32_t handle)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
isp_getrqentry(ispsoftc_t *isp, uint32_t *iptrp,
|
||||
uint32_t *optrp, void **resultp)
|
||||
/*
|
||||
* Make sure we have space to put something on the request queue.
|
||||
* Return a pointer to that entry if we do. A side effect of this
|
||||
* function is to update the output index. The input index
|
||||
* stays the same.
|
||||
*/
|
||||
void *
|
||||
isp_getrqentry(ispsoftc_t *isp)
|
||||
{
|
||||
volatile uint32_t iptr, optr;
|
||||
|
||||
optr = isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
|
||||
iptr = isp->isp_reqidx;
|
||||
*resultp = ISP_QUEUE_ENTRY(isp->isp_rquest, iptr);
|
||||
iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN(isp));
|
||||
if (iptr == optr) {
|
||||
return (1);
|
||||
isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
|
||||
if (ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp)) == isp->isp_reqodx) {
|
||||
return (NULL);
|
||||
}
|
||||
if (optrp)
|
||||
*optrp = optr;
|
||||
if (iptrp)
|
||||
*iptrp = iptr;
|
||||
return (0);
|
||||
return (ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx));
|
||||
}
|
||||
|
||||
#define TBA (4 * (((QENTRY_LEN >> 2) * 3) + 1) + 1)
|
||||
@@ -1718,6 +1908,253 @@ isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
|
||||
}
|
||||
|
||||
#ifdef ISP_TARGET_MODE
|
||||
|
||||
/*
|
||||
* Command shipping- finish off first queue entry and do dma mapping and
|
||||
* additional segments as needed.
|
||||
*
|
||||
* Called with the first queue entry at least partially filled out.
|
||||
*/
|
||||
int
|
||||
isp_send_tgt_cmd(ispsoftc_t *isp, void *fqe, void *segp, uint32_t nsegs, uint32_t totalcnt, isp_ddir_t ddir, void *snsptr, uint32_t snslen)
|
||||
{
|
||||
uint8_t storage[QENTRY_LEN], storage2[QENTRY_LEN];
|
||||
uint8_t type, nqe;
|
||||
uint32_t seg, curseg, seglim, nxt, nxtnxt;
|
||||
ispds_t *dsp = NULL;
|
||||
ispds64_t *dsp64 = NULL;
|
||||
void *qe0, *qe1, *sqe = NULL;
|
||||
|
||||
qe0 = isp_getrqentry(isp);
|
||||
if (qe0 == NULL) {
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
nxt = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp));
|
||||
|
||||
type = ((isphdr_t *)fqe)->rqs_entry_type;
|
||||
nqe = 1;
|
||||
seglim = 0;
|
||||
|
||||
/*
|
||||
* If we have no data to transmit, just copy the first IOCB and start it up.
|
||||
*/
|
||||
if (ddir != ISP_NOXFR) {
|
||||
/*
|
||||
* First, figure out how many pieces of data to transfer and what kind and how many we can put into the first queue entry.
|
||||
*/
|
||||
switch (type) {
|
||||
case RQSTYPE_CTIO:
|
||||
dsp = ((ct_entry_t *)fqe)->ct_dataseg;
|
||||
seglim = ISP_RQDSEG;
|
||||
break;
|
||||
case RQSTYPE_CTIO2:
|
||||
case RQSTYPE_CTIO3:
|
||||
{
|
||||
ct2_entry_t *ct = fqe, *ct2 = (ct2_entry_t *) storage2;
|
||||
uint16_t swd = ct->rsp.m0.ct_scsi_status & 0xff;
|
||||
|
||||
if ((ct->ct_flags & CT2_SENDSTATUS) && (swd || ct->ct_resid)) {
|
||||
memcpy(ct2, ct, QENTRY_LEN);
|
||||
/*
|
||||
* Clear fields from first CTIO2 that now need to be cleared
|
||||
*/
|
||||
ct->ct_header.rqs_seqno = 0;
|
||||
ct->ct_flags &= ~(CT2_SENDSTATUS|CT2_CCINCR|CT2_FASTPOST);
|
||||
ct->ct_resid = 0;
|
||||
ct->ct_syshandle = 0;
|
||||
ct->rsp.m0.ct_scsi_status = 0;
|
||||
|
||||
/*
|
||||
* Reset fields in the second CTIO2 as appropriate.
|
||||
*/
|
||||
ct2->ct_flags &= ~(CT2_FLAG_MMASK|CT2_DATAMASK|CT2_FASTPOST);
|
||||
ct2->ct_flags |= CT2_NO_DATA|CT2_FLAG_MODE1;
|
||||
ct2->ct_seg_count = 0;
|
||||
ct2->ct_reloff = 0;
|
||||
memset(&ct2->rsp, 0, sizeof (ct2->rsp));
|
||||
if (swd == SCSI_CHECK && snsptr && snslen) {
|
||||
ct2->rsp.m1.ct_senselen = min(snslen, MAXRESPLEN);
|
||||
memcpy(ct2->rsp.m1.ct_resp, snsptr, ct2->rsp.m1.ct_senselen);
|
||||
swd |= CT2_SNSLEN_VALID;
|
||||
}
|
||||
if (ct2->ct_resid > 0) {
|
||||
swd |= CT2_DATA_UNDER;
|
||||
} else if (ct2->ct_resid < 0) {
|
||||
swd |= CT2_DATA_OVER;
|
||||
}
|
||||
ct2->rsp.m1.ct_scsi_status = swd;
|
||||
sqe = storage2;
|
||||
}
|
||||
if (type == RQSTYPE_CTIO2) {
|
||||
dsp = ct->rsp.m0.u.ct_dataseg;
|
||||
seglim = ISP_RQDSEG_T2;
|
||||
} else {
|
||||
dsp64 = ct->rsp.m0.u.ct_dataseg64;
|
||||
seglim = ISP_RQDSEG_T3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RQSTYPE_CTIO7:
|
||||
{
|
||||
ct7_entry_t *ct = fqe, *ct2 = (ct7_entry_t *)storage2;
|
||||
uint16_t swd = ct->ct_scsi_status & 0xff;
|
||||
|
||||
dsp64 = &ct->rsp.m0.ds;
|
||||
seglim = 1;
|
||||
if ((ct->ct_flags & CT7_SENDSTATUS) && (swd || ct->ct_resid)) {
|
||||
memcpy(ct2, ct, sizeof (ct7_entry_t));
|
||||
|
||||
/*
|
||||
* Clear fields from first CTIO7 that now need to be cleared
|
||||
*/
|
||||
ct->ct_header.rqs_seqno = 0;
|
||||
ct->ct_flags &= ~CT7_SENDSTATUS;
|
||||
ct->ct_resid = 0;
|
||||
ct->ct_syshandle = 0;
|
||||
ct->ct_scsi_status = 0;
|
||||
|
||||
/*
|
||||
* Reset fields in the second CTIO7 as appropriate.
|
||||
*/
|
||||
ct2->ct_flags &= ~(CT7_FLAG_MMASK|CT7_DATAMASK);
|
||||
ct2->ct_flags |= CT7_NO_DATA|CT7_NO_DATA|CT7_FLAG_MODE1;
|
||||
ct2->ct_seg_count = 0;
|
||||
memset(&ct2->rsp, 0, sizeof (ct2->rsp));
|
||||
if (swd == SCSI_CHECK && snsptr && snslen) {
|
||||
ct2->rsp.m1.ct_resplen = min(snslen, MAXRESPLEN_24XX);
|
||||
memcpy(ct2->rsp.m1.ct_resp, snsptr, ct2->rsp.m1.ct_resplen);
|
||||
swd |= (FCP_SNSLEN_VALID << 8);
|
||||
}
|
||||
if (ct2->ct_resid < 0) {
|
||||
swd |= (FCP_RESID_OVERFLOW << 8);
|
||||
} else if (ct2->ct_resid > 0) {
|
||||
swd |= (FCP_RESID_UNDERFLOW << 8);
|
||||
}
|
||||
ct2->ct_scsi_status = swd;
|
||||
sqe = storage2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return (CMD_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill out the data transfer stuff in the first queue entry
|
||||
*/
|
||||
if (seglim > nsegs) {
|
||||
seglim = nsegs;
|
||||
}
|
||||
|
||||
for (seg = curseg = 0; curseg < seglim; curseg++) {
|
||||
if (dsp64) {
|
||||
XS_GET_DMA64_SEG(dsp64++, segp, seg++);
|
||||
} else {
|
||||
XS_GET_DMA_SEG(dsp++, segp, seg++);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* First, if we are sending status with data and we have a non-zero
|
||||
* status or non-zero residual, we have to make a synthetic extra CTIO
|
||||
* that contains the status that we'll ship separately (FC cards only).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Second, start building additional continuation segments as needed.
|
||||
*/
|
||||
while (seg < nsegs) {
|
||||
nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
|
||||
if (nxtnxt == isp->isp_reqodx) {
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
ISP_MEMZERO(storage, QENTRY_LEN);
|
||||
qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
|
||||
nxt = nxtnxt;
|
||||
if (dsp64) {
|
||||
ispcontreq64_t *crq = (ispcontreq64_t *) storage;
|
||||
seglim = ISP_CDSEG64;
|
||||
crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
|
||||
crq->req_header.rqs_entry_count = 1;
|
||||
dsp64 = crq->req_dataseg;
|
||||
} else {
|
||||
ispcontreq_t *crq = (ispcontreq_t *) storage;
|
||||
seglim = ISP_CDSEG;
|
||||
crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
|
||||
crq->req_header.rqs_entry_count = 1;
|
||||
dsp = crq->req_dataseg;
|
||||
}
|
||||
if (seg + seglim > nsegs) {
|
||||
seglim = nsegs - seg;
|
||||
}
|
||||
for (curseg = 0; curseg < seglim; curseg++) {
|
||||
if (dsp64) {
|
||||
XS_GET_DMA64_SEG(dsp64++, segp, seg++);
|
||||
} else {
|
||||
XS_GET_DMA_SEG(dsp++, segp, seg++);
|
||||
}
|
||||
}
|
||||
if (dsp64) {
|
||||
isp_put_cont64_req(isp, (ispcontreq64_t *)storage, qe1);
|
||||
} else {
|
||||
isp_put_cont_req(isp, (ispcontreq_t *)storage, qe1);
|
||||
}
|
||||
if (isp->isp_dblev & ISP_LOGTDEBUG1) {
|
||||
isp_print_bytes(isp, "additional queue entry", QENTRY_LEN, storage);
|
||||
}
|
||||
nqe++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a synthetic queue entry to complete things, do it here.
|
||||
*/
|
||||
if (sqe) {
|
||||
nxtnxt = ISP_NXT_QENTRY(nxt, RQUEST_QUEUE_LEN(isp));
|
||||
if (nxtnxt == isp->isp_reqodx) {
|
||||
return (CMD_EAGAIN);
|
||||
}
|
||||
qe1 = ISP_QUEUE_ENTRY(isp->isp_rquest, nxt);
|
||||
nxt = nxtnxt;
|
||||
if (type == RQSTYPE_CTIO7) {
|
||||
isp_put_ctio7(isp, sqe, qe1);
|
||||
} else {
|
||||
isp_put_ctio2(isp, sqe, qe1);
|
||||
}
|
||||
if (isp->isp_dblev & ISP_LOGTDEBUG1) {
|
||||
isp_print_bytes(isp, "synthetic final queue entry", QENTRY_LEN, storage2);
|
||||
}
|
||||
}
|
||||
|
||||
((isphdr_t *)fqe)->rqs_entry_count = nqe;
|
||||
switch (type) {
|
||||
case RQSTYPE_CTIO:
|
||||
((ct_entry_t *)fqe)->ct_seg_count = nsegs;
|
||||
isp_put_ctio(isp, fqe, qe0);
|
||||
break;
|
||||
case RQSTYPE_CTIO2:
|
||||
case RQSTYPE_CTIO3:
|
||||
((ct2_entry_t *)fqe)->ct_seg_count = nsegs;
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
isp_put_ctio2e(isp, fqe, qe0);
|
||||
} else {
|
||||
isp_put_ctio2(isp, fqe, qe0);
|
||||
}
|
||||
break;
|
||||
case RQSTYPE_CTIO7:
|
||||
((ct7_entry_t *)fqe)->ct_seg_count = nsegs;
|
||||
isp_put_ctio7(isp, fqe, qe0);
|
||||
break;
|
||||
default:
|
||||
return (CMD_COMPLETE);
|
||||
}
|
||||
if (isp->isp_dblev & ISP_LOGTDEBUG1) {
|
||||
isp_print_bytes(isp, "first queue entry", QENTRY_LEN, fqe);
|
||||
}
|
||||
ISP_ADD_REQUEST(isp, nxt);
|
||||
return (CMD_QUEUED);
|
||||
}
|
||||
|
||||
int
|
||||
isp_save_xs_tgt(ispsoftc_t *isp, void *xs, uint32_t *handlep)
|
||||
{
|
||||
|
||||
@@ -54,24 +54,59 @@
|
||||
*/
|
||||
#ifndef _ISP_LIBRARY_H
|
||||
#define _ISP_LIBRARY_H
|
||||
extern const char *isp_class3_roles[4];
|
||||
|
||||
/* XXXXXX BARF - CLEAN UP THIS MESS XXXXXXXX*/
|
||||
/*
|
||||
* Common command shipping routine.
|
||||
*
|
||||
* This used to be platform specific, but basically once you get the segment
|
||||
* stuff figured out, you can make all the code in one spot.
|
||||
*/
|
||||
typedef enum { ISP_TO_DEVICE, ISP_FROM_DEVICE, ISP_NOXFR} isp_ddir_t;
|
||||
int isp_send_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t);
|
||||
|
||||
/*
|
||||
* Handle management functions.
|
||||
*
|
||||
* These handles are associate with a command.
|
||||
*/
|
||||
int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
|
||||
XS_T * isp_find_xs(ispsoftc_t *, uint32_t);
|
||||
uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
|
||||
uint32_t isp_handle_index(uint32_t);
|
||||
void isp_destroy_handle(ispsoftc_t *, uint32_t);
|
||||
int isp_getrqentry(ispsoftc_t *, uint32_t *, uint32_t *, void **);
|
||||
|
||||
/*
|
||||
* Request Queue allocation
|
||||
*/
|
||||
void *isp_getrqentry(ispsoftc_t *);
|
||||
|
||||
/*
|
||||
* Queue Entry debug functions
|
||||
*/
|
||||
void isp_print_qentry (ispsoftc_t *, const char *, int, void *);
|
||||
void isp_print_bytes(ispsoftc_t *, const char *, int, void *);
|
||||
|
||||
/*
|
||||
* Fibre Channel specific routines and data.
|
||||
*/
|
||||
extern const char *isp_class3_roles[4];
|
||||
int isp_fc_runstate(ispsoftc_t *, int, int);
|
||||
void isp_dump_portdb(ispsoftc_t *, int);
|
||||
|
||||
|
||||
/*
|
||||
* Common chip shutdown function
|
||||
*/
|
||||
void isp_shutdown(ispsoftc_t *);
|
||||
|
||||
/*
|
||||
* Put/Get routines to push from CPU view to device view
|
||||
* or to pull from device view to CPU view for various
|
||||
* data structures (IOCB)
|
||||
*/
|
||||
void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
|
||||
void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
|
||||
int isp_get_response_type(ispsoftc_t *, isphdr_t *);
|
||||
|
||||
void isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *);
|
||||
void isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *);
|
||||
void isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *);
|
||||
@@ -134,6 +169,8 @@ void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
|
||||
#include "isp_target.h"
|
||||
#endif
|
||||
|
||||
int isp_send_tgt_cmd(ispsoftc_t *, void *, void *, uint32_t, uint32_t, isp_ddir_t, void *, uint32_t);
|
||||
|
||||
#define IS_TARGET_HANDLE(x) ((x) & 0x8000)
|
||||
|
||||
int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_target.c,v 1.83 2009/02/01 23:49:49 mjacob Exp $ */
|
||||
/* $Id: isp_target.c,v 1.84 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -468,7 +468,6 @@ int
|
||||
isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cnt)
|
||||
{
|
||||
lun_entry_t el;
|
||||
uint32_t nxti, optr;
|
||||
void *outp;
|
||||
|
||||
ISP_MEMZERO(&el, sizeof (el));
|
||||
@@ -503,25 +502,25 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int lun, int cmd_cnt, int inot_cn
|
||||
}
|
||||
el.le_timeout = 30;
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
|
||||
outp = isp_getrqentry(isp);
|
||||
if (outp == NULL) {
|
||||
isp_prt(isp, ISP_LOGERR, rqo, __func__);
|
||||
return (-1);
|
||||
}
|
||||
ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el);
|
||||
isp_put_enable_lun(isp, &el, outp);
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_TDQE(isp, "isp_lun_cmd", isp->isp_reqidx, &el);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
isp_target_put_entry(ispsoftc_t *isp, void *ap)
|
||||
{
|
||||
void *outp;
|
||||
uint32_t nxti, optr;
|
||||
uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
|
||||
outp = isp_getrqentry(isp);
|
||||
if (outp == NULL) {
|
||||
isp_prt(isp, ISP_LOGWARN, rqo, __func__);
|
||||
return (-1);
|
||||
}
|
||||
@@ -553,8 +552,8 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap)
|
||||
isp_prt(isp, ISP_LOGERR, "%s: Unknown type 0x%x", __func__, etype);
|
||||
return (-1);
|
||||
}
|
||||
ISP_TDQE(isp, __func__, (int) optr, ap);
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_TDQE(isp, __func__, isp->isp_reqidx, ap);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1041,7 +1040,6 @@ int
|
||||
isp_notify_ack(ispsoftc_t *isp, void *arg)
|
||||
{
|
||||
char storage[QENTRY_LEN];
|
||||
uint32_t nxti, optr;
|
||||
void *outp;
|
||||
|
||||
/*
|
||||
@@ -1052,7 +1050,8 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
|
||||
return (isp_endcmd(isp, aep, NIL_HANDLE, 0, 0, 0));
|
||||
}
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
|
||||
outp = isp_getrqentry(isp);
|
||||
if (outp == NULL) {
|
||||
isp_prt(isp, ISP_LOGWARN, rqo, __func__);
|
||||
return (1);
|
||||
}
|
||||
@@ -1139,11 +1138,10 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
|
||||
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
|
||||
na->na_header.rqs_entry_count = 1;
|
||||
isp_put_notify_ack(isp, na, (na_entry_t *)outp);
|
||||
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
|
||||
na->na_seqid, na->na_event);
|
||||
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event);
|
||||
}
|
||||
ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1155,7 +1153,6 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
|
||||
uint8_t tmpb;
|
||||
abts_t *abts = arg;
|
||||
abts_rsp_t *rsp = (abts_rsp_t *) storage;
|
||||
uint32_t nxti, optr;
|
||||
void *outp;
|
||||
|
||||
if (!IS_24XX(isp)) {
|
||||
@@ -1168,7 +1165,8 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
|
||||
outp = isp_getrqentry(isp);
|
||||
if (outp == NULL) {
|
||||
isp_prt(isp, ISP_LOGWARN, rqo, __func__);
|
||||
return (1);
|
||||
}
|
||||
@@ -1221,8 +1219,8 @@ isp_acknak_abts(ispsoftc_t *isp, void *arg, int errno)
|
||||
* in the ABTS structure just before calling us.
|
||||
*/
|
||||
isp_put_abts_rsp(isp, rsp, (abts_rsp_t *)outp);
|
||||
ISP_TDQE(isp, "isp_acknak_abts", (int) optr, storage);
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_TDQE(isp, "isp_acknak_abts", isp->isp_reqidx, storage);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_target.h,v 1.63 2009/02/01 23:49:49 mjacob Exp $ */
|
||||
/* $Id: isp_target.h,v 1.64 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_tpublic.h,v 1.44 2008/12/03 18:35:05 mjacob Exp $ */
|
||||
/* $Id: isp_tpublic.h,v 1.45 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: ispvar.h,v 1.103 2009/02/01 23:49:49 mjacob Exp $ */
|
||||
/* $Id: ispvar.h,v 1.104 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -76,7 +76,7 @@
|
||||
#include "ispmbox.h"
|
||||
#endif
|
||||
|
||||
#define ISP_CORE_VERSION_MAJOR 5
|
||||
#define ISP_CORE_VERSION_MAJOR 6
|
||||
#define ISP_CORE_VERSION_MINOR 0
|
||||
|
||||
/*
|
||||
@@ -84,13 +84,11 @@
|
||||
*/
|
||||
typedef struct ispsoftc ispsoftc_t;
|
||||
struct ispmdvec {
|
||||
int (*dv_rd_isr)
|
||||
(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
|
||||
int (*dv_rd_isr) (ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
|
||||
uint32_t (*dv_rd_reg) (ispsoftc_t *, int);
|
||||
void (*dv_wr_reg) (ispsoftc_t *, int, uint32_t);
|
||||
int (*dv_mbxdma) (ispsoftc_t *);
|
||||
int (*dv_dmaset)
|
||||
(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
|
||||
int (*dv_dmaset) (ispsoftc_t *, XS_T *, void *);
|
||||
void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t);
|
||||
void (*dv_reset0) (ispsoftc_t *);
|
||||
void (*dv_reset1) (ispsoftc_t *);
|
||||
@@ -126,8 +124,8 @@ struct ispmdvec {
|
||||
#define ISP_MBOXDMASETUP(isp) \
|
||||
(*(isp)->isp_mdvec->dv_mbxdma)((isp))
|
||||
|
||||
#define ISP_DMASETUP(isp, xs, req, iptrp, optr) \
|
||||
(*(isp)->isp_mdvec->dv_dmaset)((isp), (xs), (req), (iptrp), (optr))
|
||||
#define ISP_DMASETUP(isp, xs, req) \
|
||||
(*(isp)->isp_mdvec->dv_dmaset)((isp), (xs), (req))
|
||||
|
||||
#define ISP_DMAFREE(isp, xs, hndl) \
|
||||
if ((isp)->isp_mdvec->dv_dmaclr) \
|
||||
@@ -187,6 +185,11 @@ struct ispmdvec {
|
||||
ISP_WRITE(isp, isp->isp_rqstinrp, nxti); \
|
||||
isp->isp_reqidx = nxti
|
||||
|
||||
#define ISP_SYNC_REQUEST(isp) \
|
||||
MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN); \
|
||||
isp->isp_reqidx = ISP_NXT_QENTRY(isp->isp_reqidx, RQUEST_QUEUE_LEN(isp)); \
|
||||
ISP_WRITE(isp, isp->isp_rqstinrp, isp->isp_reqidx)
|
||||
|
||||
/*
|
||||
* SCSI Specific Host Adapter Parameters- per bus, per target
|
||||
*/
|
||||
@@ -975,25 +978,27 @@ void isp_async(ispsoftc_t *, ispasync_t, ...);
|
||||
* SCSI_BUSY SCSI 'Busy' Status
|
||||
* SCSI_QFULL SCSI 'Queue Full' Status
|
||||
*
|
||||
* XS_T Platform SCSI transaction type (i.e., command for HBA)
|
||||
* XS_DMA_ADDR_T Platform PCI DMA Address Type
|
||||
* XS_ISP(xs) gets an instance out of an XS_T
|
||||
* XS_CHANNEL(xs) gets the channel (bus # for DUALBUS cards) ""
|
||||
* XS_TGT(xs) gets the target ""
|
||||
* XS_LUN(xs) gets the lun ""
|
||||
* XS_CDBP(xs) gets a pointer to the scsi CDB ""
|
||||
* XS_CDBLEN(xs) gets the CDB's length ""
|
||||
* XS_XFRLEN(xs) gets the associated data transfer length ""
|
||||
* XS_TIME(xs) gets the time (in milliseconds) for this command
|
||||
* XS_T Platform SCSI transaction type (i.e., command for HBA)
|
||||
* XS_DMA_ADDR_T Platform PCI DMA Address Type
|
||||
* XS_GET_DMA_SEG(..) Get 32 bit dma segment list value
|
||||
* XS_GET_DMA64_SEG(..) Get 64 bit dma segment list value
|
||||
* XS_ISP(xs) gets an instance out of an XS_T
|
||||
* XS_CHANNEL(xs) gets the channel (bus # for DUALBUS cards) ""
|
||||
* XS_TGT(xs) gets the target ""
|
||||
* XS_LUN(xs) gets the lun ""
|
||||
* XS_CDBP(xs) gets a pointer to the scsi CDB ""
|
||||
* XS_CDBLEN(xs) gets the CDB's length ""
|
||||
* XS_XFRLEN(xs) gets the associated data transfer length ""
|
||||
* XS_TIME(xs) gets the time (in milliseconds) for this command
|
||||
* XS_GET_RESID(xs) gets the current residual count
|
||||
* XS_GET_RESID(xs, resid) sets the current residual count
|
||||
* XS_STSP(xs) gets a pointer to the SCSI status byte ""
|
||||
* XS_SNSP(xs) gets a pointer to the associate sense data
|
||||
* XS_SNSLEN(xs) gets the length of sense data storage
|
||||
* XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key
|
||||
* XS_TAG_P(xs) predicate of whether this command should be tagged
|
||||
* XS_TAG_TYPE(xs) which type of tag to use
|
||||
* XS_SETERR(xs) set error state
|
||||
* XS_STSP(xs) gets a pointer to the SCSI status byte ""
|
||||
* XS_SNSP(xs) gets a pointer to the associate sense data
|
||||
* XS_SNSLEN(xs) gets the length of sense data storage
|
||||
* XS_SNSKEY(xs) dereferences XS_SNSP to get the current stored Sense Key
|
||||
* XS_TAG_P(xs) predicate of whether this command should be tagged
|
||||
* XS_TAG_TYPE(xs) which type of tag to use
|
||||
* XS_SETERR(xs) set error state
|
||||
*
|
||||
* HBA_NOERROR command has no erros
|
||||
* HBA_BOTCH hba botched something
|
||||
|
||||
@@ -767,9 +767,10 @@ isp_run_cmd(ispsoftc_t *isp, isp_xcmd_t *cmd)
|
||||
struct scsi_device *dev = NULL;
|
||||
struct scsi_cmnd *Cmnd = NULL;
|
||||
struct Scsi_Host *host = NULL;
|
||||
uint32_t nxti, optr, handle;
|
||||
uint32_t handle;
|
||||
uint8_t local[QENTRY_LEN];
|
||||
ispreq_t *reqp;
|
||||
void *qep;
|
||||
int time, result = 0;
|
||||
struct semaphore rsem;
|
||||
unsigned long flags;
|
||||
@@ -800,7 +801,8 @@ isp_run_cmd(ispsoftc_t *isp, isp_xcmd_t *cmd)
|
||||
sema_init(&rsem, 0);
|
||||
|
||||
ISP_LOCKU_SOFTC(isp);
|
||||
if (isp_getrqentry(isp, &nxti, &optr, (void *)&reqp)) {
|
||||
qep = isp_getrqentry(isp);
|
||||
if (qep == NULL) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
isp_prt(isp, ISP_LOGDEBUG0, "%s: Request Queue Overflow", __func__);
|
||||
result = -ENOMEM;
|
||||
@@ -881,7 +883,7 @@ isp_run_cmd(ispsoftc_t *isp, isp_xcmd_t *cmd)
|
||||
Cmnd->sc_data_direction = SCSI_DATA_NONE;
|
||||
}
|
||||
|
||||
result = ISP_DMASETUP(isp, Cmnd, reqp, &nxti, optr);
|
||||
result = ISP_DMASETUP(isp, Cmnd, reqp);
|
||||
switch (result) {
|
||||
default:
|
||||
isp_prt(isp, ISP_LOGWARN, "isp_run_cmd: dma setup returned %d", result);
|
||||
@@ -891,7 +893,7 @@ isp_run_cmd(ispsoftc_t *isp, isp_xcmd_t *cmd)
|
||||
result = -ENOMEM;
|
||||
break;
|
||||
case CMD_QUEUED:
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
isp->isp_nactive++;
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_linux.c,v 1.240 2009/02/01 23:49:55 mjacob Exp $ */
|
||||
/* $Id: isp_linux.c,v 1.241 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -1511,7 +1511,6 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
{
|
||||
void *qe;
|
||||
uint32_t handle, orig_xfrlen = 0;
|
||||
uint32_t nxti, optr;
|
||||
uint8_t local[QENTRY_LEN];
|
||||
unsigned long flags;
|
||||
int32_t resid;
|
||||
@@ -1533,6 +1532,12 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
orig_xfrlen = xact->td_xfrlen;
|
||||
tmd->cd_moved += orig_xfrlen;
|
||||
|
||||
/*
|
||||
* Set the residual to be equal to the total length less the amount previously moved plus this transfer size
|
||||
*/
|
||||
resid = tmd->cd_totlen - tmd->cd_moved;
|
||||
|
||||
|
||||
/*
|
||||
* Check for commands that are already dead
|
||||
*/
|
||||
@@ -1575,11 +1580,6 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
|
||||
memset(local, 0, QENTRY_LEN);
|
||||
|
||||
/*
|
||||
* Set the residual to be equal to the total length less the amount previously moved plus this transfer size
|
||||
*/
|
||||
resid = tmd->cd_totlen - tmd->cd_moved;
|
||||
|
||||
/*
|
||||
* We're either moving data or completing a command here (or both).
|
||||
*/
|
||||
@@ -1589,6 +1589,7 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
|
||||
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
|
||||
cto->ct_header.rqs_entry_count = 1;
|
||||
cto->ct_header.rqs_seqno = 1;
|
||||
cto->ct_nphdl = tmd->cd_nphdl;
|
||||
cto->ct_rxid = tmd->cd_tagval;
|
||||
cto->ct_iid_lo = tmd->cd_portid;
|
||||
@@ -1625,6 +1626,8 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
cto->ct_scsi_status |= (FCP_SNSLEN_VALID << 8);
|
||||
}
|
||||
} else {
|
||||
cto->rsp.m0.ct_xfrlen = xact->td_xfrlen;
|
||||
cto->rsp.m0.reloff = tmd->cd_moved - orig_xfrlen;
|
||||
cto->ct_flags |= CT7_FLAG_MODE0;
|
||||
if (xact->td_hflags & TDFH_DATA_IN) {
|
||||
cto->ct_flags |= CT7_DATA_IN;
|
||||
@@ -1651,6 +1654,7 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
|
||||
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
|
||||
cto->ct_header.rqs_entry_count = 1;
|
||||
cto->ct_header.rqs_seqno = 1;
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
((ct2e_entry_t *)cto)->ct_iid = tmd->cd_nphdl;
|
||||
} else {
|
||||
@@ -1683,6 +1687,7 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID;
|
||||
}
|
||||
} else {
|
||||
cto->ct_reloff = tmd->cd_moved - orig_xfrlen;
|
||||
cto->ct_flags |= CT2_FLAG_MODE0;
|
||||
if (xact->td_hflags & TDFH_DATA_IN) {
|
||||
cto->ct_flags |= CT2_DATA_IN;
|
||||
@@ -1717,6 +1722,7 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
|
||||
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO;
|
||||
cto->ct_header.rqs_entry_count = 1;
|
||||
cto->ct_header.rqs_seqno = 1;
|
||||
cto->ct_iid = tmd->cd_iid;
|
||||
cto->ct_tgt = tmd->cd_tgt;
|
||||
cto->ct_lun = L0LUN_TO_FLATLUN(tmd->cd_lun);
|
||||
@@ -1755,7 +1761,8 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
isp_prt(isp, ISP_LOGTDEBUG0, "CTIO[%llx] scsi sts %x resid %d cd_lflags %x", (ull) tmd->cd_tagval, tmd->cd_scsi_status, resid, xact->td_hflags);
|
||||
}
|
||||
|
||||
if (isp_getrqentry(isp, &nxti, &optr, &qe)) {
|
||||
qe = isp_getrqentry(isp);
|
||||
if (qe == NULL) {
|
||||
isp_prt(isp, ISP_LOGWARN, "%s: request queue overflow", __func__);
|
||||
xact->td_error = -ENOMEM;
|
||||
goto out;
|
||||
@@ -1784,9 +1791,8 @@ isp_target_start_ctio(ispsoftc_t *isp, tmd_xact_t *xact)
|
||||
* format.
|
||||
*/
|
||||
|
||||
switch (ISP_DMASETUP(isp, (XS_T *)xact, (ispreq_t *) local, &nxti, optr)) {
|
||||
switch (ISP_DMASETUP(isp, (XS_T *)xact, local)) {
|
||||
case CMD_QUEUED:
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
tmd->cd_req_cnt += 1;
|
||||
ISP_UNLK_SOFTC(isp);
|
||||
return;
|
||||
@@ -2534,7 +2540,6 @@ isp_handle_platform_ctio(ispsoftc_t *isp, void *arg)
|
||||
static int
|
||||
isp_target_putback_atio(ispsoftc_t *isp, tmd_cmd_t *tmd)
|
||||
{
|
||||
uint32_t nxti;
|
||||
uint8_t local[QENTRY_LEN];
|
||||
void *qe;
|
||||
|
||||
@@ -2542,7 +2547,8 @@ isp_target_putback_atio(ispsoftc_t *isp, tmd_cmd_t *tmd)
|
||||
if (IS_24XX(isp)) {
|
||||
return (0);
|
||||
}
|
||||
if (isp_getrqentry(isp, &nxti, NULL, &qe)) {
|
||||
qe = isp_getrqentry(isp);
|
||||
if (qe == NULL) {
|
||||
isp_prt(isp, ISP_LOGWARN, "%s: Request Queue Overflow", __func__);
|
||||
return (-ENOMEM);
|
||||
}
|
||||
@@ -2579,7 +2585,7 @@ isp_target_putback_atio(ispsoftc_t *isp, tmd_cmd_t *tmd)
|
||||
isp_put_atio(isp, at, qe);
|
||||
}
|
||||
ISP_TDQE(isp, "isp_target_putback_atio", isp->isp_reqidx, qe);
|
||||
ISP_ADD_REQUEST(isp, nxti);
|
||||
ISP_SYNC_REQUEST(isp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -4456,6 +4462,7 @@ isp_thread_event(ispsoftc_t *isp, int action, void *a, int dowait, const char *f
|
||||
if (tap->thread_action == action && tap->arg == a && dowait == 0) {
|
||||
tap->count++;
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags);
|
||||
wake_up(&isp->isp_osinfo.trq);
|
||||
isp_prt(isp, ISP_LOGDEBUG1, "async thread event %d from %s:%d now has count %d", action, file, line, tap->count);
|
||||
return (0);
|
||||
}
|
||||
@@ -4527,350 +4534,351 @@ isp_task_thread(void *arg)
|
||||
break;
|
||||
}
|
||||
spin_lock_irqsave(&isp->isp_osinfo.tlock, flags);
|
||||
if ((tap = isp->isp_osinfo.t_busy) != NULL) {
|
||||
while ((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);
|
||||
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:
|
||||
{
|
||||
unsigned long arg = (unsigned long) tap->arg;
|
||||
int tgt, chan, rescan;
|
||||
tgt = arg & 0xffff;
|
||||
chan = (arg >> 16) & 0xff;
|
||||
rescan = (arg >> 31) & 1;
|
||||
if (rescan == 0) {
|
||||
scsi_scan_target(&isp->isp_osinfo.host->shost_gendev, chan, tgt, 0, rescan);
|
||||
} else {
|
||||
struct scsi_device *sdev;
|
||||
sdev = scsi_device_lookup(isp->isp_osinfo.host, 0, tgt, 0);
|
||||
if (sdev) {
|
||||
scsi_remove_device(sdev);
|
||||
scsi_device_put(sdev);
|
||||
}
|
||||
}
|
||||
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);
|
||||
spin_unlock_irqrestore(&isp->isp_osinfo.tlock, flags);
|
||||
if (tap == NULL) {
|
||||
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_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:
|
||||
{
|
||||
unsigned long arg = (unsigned long) tap->arg;
|
||||
int tgt, chan, rescan;
|
||||
tgt = arg & 0xffff;
|
||||
chan = (arg >> 16) & 0xff;
|
||||
rescan = (arg >> 31) & 1;
|
||||
if (rescan == 0) {
|
||||
scsi_scan_target(&isp->isp_osinfo.host->shost_gendev, chan, tgt, 0, rescan);
|
||||
} else {
|
||||
struct scsi_device *sdev;
|
||||
sdev = scsi_device_lookup(isp->isp_osinfo.host, 0, tgt, 0);
|
||||
if (sdev) {
|
||||
scsi_remove_device(sdev);
|
||||
scsi_device_put(sdev);
|
||||
}
|
||||
}
|
||||
isp_async(isp, ISPASYNC_FW_RESTARTED);
|
||||
} else {
|
||||
isp_prt(isp, ISP_LOGERR, "unable to restart chip");
|
||||
break;
|
||||
}
|
||||
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)->nextscan = 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;
|
||||
isp_prt(isp, ISP_LOGWARN, "Chan %d assuming loop is dead", chan);
|
||||
isplinux_flushwaitq(isp);
|
||||
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_DATA(isp, chan)->nextscan = jiffies + HZ;
|
||||
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)->nextscan = 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;
|
||||
isp_prt(isp, ISP_LOGWARN, "Chan %d assuming loop is dead", chan);
|
||||
isplinux_flushwaitq(isp);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
break;
|
||||
}
|
||||
ISP_DATA(isp, chan)->nextscan = jiffies + HZ;
|
||||
}
|
||||
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_LOGTINFO, "target mode entry no longer valid");
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
break;
|
||||
}
|
||||
memset(&u, 0, sizeof (u));
|
||||
u.id = lp->handle;
|
||||
isp_prt(isp, ISP_LOGTINFO, "Doing Port Logout repair for 0x%016llx@0x%x (loop id) %u", (ull) lp->port_wwn, lp->portid, lp->handle);
|
||||
memset(&mbs, 0, sizeof (mbs));
|
||||
mbs.param[0] = MBOX_FABRIC_LOGOUT;
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
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;
|
||||
}
|
||||
memset(&u, 0, sizeof (u));
|
||||
u.id = lp->handle;
|
||||
isp_prt(isp, ISP_LOGTINFO, "Doing Port Logout repair for 0x%016llx@0x%x (loop id) %u", (ull) lp->port_wwn, lp->portid, lp->handle);
|
||||
memset(&mbs, 0, 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;
|
||||
}
|
||||
memset(&mbs, 0, sizeof (mbs));
|
||||
mbs.param[0] = MBOX_FABRIC_LOGIN;
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
} 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;
|
||||
}
|
||||
memset(&mbs, 0, sizeof (mbs));
|
||||
mbs.param[0] = MBOX_FABRIC_LOGIN;
|
||||
if (ISP_CAP_2KLOGIN(isp)) {
|
||||
mbs.param[1] = lp->handle;
|
||||
mbs.obits |= (1 << 10);
|
||||
} else {
|
||||
} 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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", (ull) tmd->cd_tagval);
|
||||
isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __func__, __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", (ull) tmd->cd_tagval);
|
||||
isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __func__, __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;
|
||||
}
|
||||
for (nphdl = 0; nphdl != max; nphdl++) {
|
||||
if (isp_control(isp, ISPCTL_GET_PDB, tmd->cd_channel, nphdl, &pdb)) {
|
||||
continue;
|
||||
if (IS_24XX(isp)) {
|
||||
max = NPH_MAX_2K;
|
||||
} else {
|
||||
max = NPH_MAX;
|
||||
}
|
||||
isp_prt(isp, ISP_LOGTINFO, "%s: nphdl 0x%04x has portid 0x%06x", __func__, nphdl, pdb.portid);
|
||||
if (pdb.portid == tmd->cd_portid) {
|
||||
lp->handle = nphdl;
|
||||
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", __func__, 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", (ull) 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, __func__, __LINE__);
|
||||
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", (ull) 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, __func__, __LINE__);
|
||||
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", __func__, tmd->cd_channel, (ull) tmd->cd_tagval, lp->handle, tmd->cd_portid);
|
||||
}
|
||||
}
|
||||
if (isp_control(isp, ISPCTL_GET_NAMES, tmd->cd_channel, lp->handle, NULL, &lp->port_wwn) == 0) {
|
||||
} else {
|
||||
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", __func__, tmd->cd_channel, (ull) tmd->cd_tagval, lp->handle, tmd->cd_portid);
|
||||
}
|
||||
} else {
|
||||
nphdl = lp->handle;
|
||||
iid = lp->port_wwn;
|
||||
/*
|
||||
* 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", (ull) 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, __func__, __LINE__);
|
||||
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", (ull) 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, __func__, __LINE__);
|
||||
break;
|
||||
}
|
||||
if (iid == INI_NONE) {
|
||||
isp_prt(isp, ISP_LOGTDEBUG0, "%s: [0x%llx] trying to find IID again...", __func__, (ull) 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", __func__,
|
||||
(ull) tmd->cd_tagval, tmd->cd_channel, (ull)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;
|
||||
if (iid == INI_NONE) {
|
||||
isp_prt(isp, ISP_LOGTDEBUG0, "%s: [0x%llx] trying to find IID again...", __func__, (ull) 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 {
|
||||
isp_prt(isp, ISP_LOGTINFO, "[0x%llx] not in port database at all any more", (ull) tmd->cd_tagval);
|
||||
}
|
||||
if (tmd->cd_portid != PORT_NONE) {
|
||||
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", __func__,
|
||||
(ull) tmd->cd_tagval, tmd->cd_channel, (ull)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", tmd->cd_channel, (ull) tmd->cd_tagval);
|
||||
break;
|
||||
}
|
||||
case ISP_THREAD_FINDPORTID:
|
||||
{
|
||||
tmd_cmd_t *tmd = tap->arg;
|
||||
fcportdb_t *lp;
|
||||
|
||||
isp_prt(isp, ISP_LOGTINFO, "%s now terminating [%llx] from 0x%06x", __func__, (ull) tmd->cd_tagval, tmd->cd_portid);
|
||||
if (isp_terminate_cmd(isp, tmd)) {
|
||||
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", (ull) 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", __func__,
|
||||
(ull) tmd->cd_tagval, tmd->cd_channel, (ull)tmd->cd_iid, tmd->cd_nphdl, tmd->cd_portid);
|
||||
}
|
||||
CALL_PARENT_TMD(isp, tmd, QOUT_TMD_START);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
isp_thread_event(isp, ISP_THREAD_TERMINATE, tmd, 0, __func__, __LINE__);
|
||||
isp_tgt_tq(isp);
|
||||
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;
|
||||
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);
|
||||
memset(tmd, 0, 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", __func__, (ull) tmd->cd_tagval);
|
||||
if (isp_target_putback_atio(isp, tmd)) {
|
||||
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", tmd->cd_channel, (ull) tmd->cd_tagval);
|
||||
break;
|
||||
}
|
||||
|
||||
isp_prt(isp, ISP_LOGTINFO, "%s now terminating [%llx] from 0x%06x", __func__, (ull) 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, __func__, __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;
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
isp_thread_event(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __func__, __LINE__);
|
||||
break;
|
||||
}
|
||||
if (tmd->cd_lflags & CDFL_NEED_CLNUP) {
|
||||
tmd->cd_lflags ^= CDFL_NEED_CLNUP;
|
||||
isp_prt(isp, ISP_LOGTINFO, "Terminating %llx too", (ull) tmd->cd_tagval);
|
||||
(void) isp_terminate_cmd(isp, tmd);
|
||||
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);
|
||||
memset(tmd, 0, 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;
|
||||
}
|
||||
memset(tmd, 0, sizeof (tmd_cmd_t));
|
||||
if (isp->isp_osinfo.tfreelist) {
|
||||
isp->isp_osinfo.bfreelist->cd_next = tmd;
|
||||
} else {
|
||||
isp->isp_osinfo.tfreelist = 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", __func__, (ull) tmd->cd_tagval);
|
||||
if (isp_target_putback_atio(isp, tmd)) {
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
isp_thread_event(isp, ISP_THREAD_FC_PUTBACK, tmd, 0, __func__, __LINE__);
|
||||
break;
|
||||
}
|
||||
if (tmd->cd_lflags & CDFL_NEED_CLNUP) {
|
||||
tmd->cd_lflags ^= CDFL_NEED_CLNUP;
|
||||
isp_prt(isp, ISP_LOGTINFO, "Terminating %llx too", (ull) tmd->cd_tagval);
|
||||
(void) isp_terminate_cmd(isp, tmd);
|
||||
}
|
||||
memset(tmd, 0, 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, (ull) tmd->cd_tagval);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
break;
|
||||
}
|
||||
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, (ull) tmd->cd_tagval);
|
||||
ISP_UNLKU_SOFTC(isp);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
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);
|
||||
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);
|
||||
spin_lock_irqsave(&isp->isp_osinfo.tlock, flags);
|
||||
} 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_LOGDEBUG0, "isp_task_thread exiting");
|
||||
return (0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $Id: isp_linux.h,v 1.168 2009/01/24 17:55:55 mjacob Exp $ */
|
||||
/* $Id: isp_linux.h,v 1.169 2009/02/13 23:58:38 mjacob Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1997-2008 by Matthew Jacob
|
||||
* All rights reserved.
|
||||
@@ -331,11 +331,10 @@ struct isposinfo {
|
||||
wait_queue_head_t mboxwq;
|
||||
struct semaphore mbox_c_sem;
|
||||
spinlock_t slock;
|
||||
unsigned volatile int
|
||||
: 20,
|
||||
uint32_t
|
||||
dogcnt : 5,
|
||||
isopen : 1,
|
||||
: 1,
|
||||
is_64bit_dma : 1,
|
||||
dogactive : 1,
|
||||
mboxcmd_done : 1,
|
||||
mbintsok : 1,
|
||||
@@ -413,10 +412,6 @@ struct isposinfo {
|
||||
* Required Macros/Defines
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_HIGHMEM64G) || defined(CONFIG_X86_64) /* BOGUS */
|
||||
#define ISP_DAC_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
#define ISP_FC_SCRLEN 0x1000
|
||||
|
||||
#define ISP_MEMZERO(b, a) memset(b, 0, a)
|
||||
@@ -477,7 +472,8 @@ struct isposinfo {
|
||||
|
||||
#define XS_T Scsi_Cmnd
|
||||
#define XS_DMA_ADDR_T dma_addr_t
|
||||
|
||||
#define XS_GET_DMA64_SEG isp_get_dma64_seg
|
||||
#define XS_GET_DMA_SEG isp_get_dma_seg
|
||||
#define XS_HOST(Cmnd) Cmnd->device->host
|
||||
#define XS_CHANNEL(Cmnd) (Cmnd)->device->channel
|
||||
#define XS_TGT(Cmnd) (Cmnd)->device->id
|
||||
@@ -913,6 +909,23 @@ isp_kzalloc(size_t size, int flags)
|
||||
#define COPYIN(uarg, karg, amt) copy_from_user(karg, uarg, amt)
|
||||
#define COPYOUT(karg, uarg, amt) copy_to_user(uarg, karg, amt)
|
||||
|
||||
static __inline void
|
||||
isp_get_dma64_seg(ispds64_t *dsp, struct scatterlist *sg, uint32_t sgidx)
|
||||
{
|
||||
sg += sgidx;
|
||||
dsp->ds_base = DMA_LO32(sg_dma_address(sg));
|
||||
dsp->ds_basehi = DMA_HI32(sg_dma_address(sg));
|
||||
dsp->ds_count = sg_dma_len(sg);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
isp_get_dma_seg(ispds_t *dsp, struct scatterlist *sg, uint32_t sgidx)
|
||||
{
|
||||
sg += sgidx;
|
||||
dsp->ds_base = sg_dma_address(sg);
|
||||
dsp->ds_count = sg_dma_len(sg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common inline functions
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user