svn commit: r256705 - head/sys/dev/isp
Alexander Motin
mav at FreeBSD.org
Thu Oct 17 20:19:16 UTC 2013
Author: mav
Date: Thu Oct 17 20:19:15 2013
New Revision: 256705
URL: http://svnweb.freebsd.org/changeset/base/256705
Log:
Optimize isp(4) to reduce CPU usage, especially in target mode:
- Remove two excessive and slow register reads from isp_intr(). Instead
of rereading value every time, assume that registers contain what we have
written there.
- Avoid sequential search through 4096 array elements when looking for
command tag. Use hash of lists to store active tags separately from free
ones and so greatly speedup the searches.
Reviewed by: mjacob
Modified:
head/sys/dev/isp/isp.c
head/sys/dev/isp/isp_freebsd.c
head/sys/dev/isp/isp_freebsd.h
head/sys/dev/isp/ispvar.h
Modified: head/sys/dev/isp/isp.c
==============================================================================
--- head/sys/dev/isp/isp.c Thu Oct 17 20:15:14 2013 (r256704)
+++ head/sys/dev/isp/isp.c Thu Oct 17 20:19:15 2013 (r256705)
@@ -1422,7 +1422,7 @@ isp_scsi_init(ispsoftc_t *isp)
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
- isp->isp_residx = mbs.param[5];
+ isp->isp_residx = isp->isp_resodx = mbs.param[5];
MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE_A64, MBLOGALL, 0);
mbs.param[1] = RQUEST_QUEUE_LEN(isp);
@@ -1446,7 +1446,7 @@ isp_scsi_init(ispsoftc_t *isp)
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
return;
}
- isp->isp_residx = mbs.param[5];
+ isp->isp_residx = isp->isp_resodx = mbs.param[5];
MBSINIT(&mbs, MBOX_INIT_REQ_QUEUE, MBLOGALL, 0);
mbs.param[1] = RQUEST_QUEUE_LEN(isp);
@@ -1918,6 +1918,7 @@ isp_fibre_init(ispsoftc_t *isp)
isp->isp_reqidx = 0;
isp->isp_reqodx = 0;
isp->isp_residx = 0;
+ isp->isp_resodx = 0;
/*
* Whatever happens, we're now committed to being here.
@@ -2208,6 +2209,8 @@ isp_fibre_init_2400(ispsoftc_t *isp)
isp->isp_reqidx = 0;
isp->isp_reqodx = 0;
isp->isp_residx = 0;
+ isp->isp_resodx = 0;
+ isp->isp_atioodx = 0;
/*
* Whatever happens, we're now committed to being here.
@@ -5015,7 +5018,6 @@ isp_intr(ispsoftc_t *isp, uint32_t isr,
int etype, last_etype = 0;
again:
- optr = isp->isp_residx;
/*
* Is this a mailbox related interrupt?
* The mailbox semaphore will be nonzero if so.
@@ -5067,7 +5069,9 @@ again:
/*
* Thank you very much! *Burrrp*!
*/
- ISP_WRITE(isp, isp->isp_respoutrp, ISP_READ(isp, isp->isp_respinrp));
+ isp->isp_residx = ISP_READ(isp, isp->isp_respinrp);
+ isp->isp_resodx = isp->isp_residx;
+ ISP_WRITE(isp, isp->isp_respoutrp, isp->isp_resodx);
if (IS_24XX(isp)) {
ISP_DISABLE_INTS(isp);
}
@@ -5080,7 +5084,7 @@ again:
*/
if (IS_24XX(isp)) {
iptr = ISP_READ(isp, BIU2400_ATIO_RSPINP);
- optr = ISP_READ(isp, BIU2400_ATIO_RSPOUTP);
+ optr = isp->isp_atioodx;
while (optr != iptr) {
uint8_t qe[QENTRY_LEN];
@@ -5105,7 +5109,7 @@ again:
optr = ISP_NXT_QENTRY(oop, RESULT_QUEUE_LEN(isp));
ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, optr);
}
- optr = isp->isp_residx;
+ isp->isp_atioodx = optr;
}
#endif
@@ -5114,18 +5118,19 @@ again:
*
* If we're a 2300 or 2400, we can ask what hardware what it thinks.
*/
+#if 0
if (IS_23XX(isp) || IS_24XX(isp)) {
optr = ISP_READ(isp, isp->isp_respoutrp);
/*
* Debug: to be taken out eventually
*/
- if (isp->isp_residx != optr) {
- isp_prt(isp, ISP_LOGINFO, "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_residx);
- isp->isp_residx = optr;
+ if (isp->isp_resodx != optr) {
+ isp_prt(isp, ISP_LOGINFO, "isp_intr: hard optr=%x, soft optr %x", optr, isp->isp_resodx);
+ isp->isp_resodx = optr;
}
- } else {
- optr = isp->isp_residx;
- }
+ } else
+#endif
+ optr = isp->isp_resodx;
/*
* You *must* read the Response Queue In Pointer
@@ -5147,8 +5152,6 @@ again:
} else {
iptr = ISP_READ(isp, isp->isp_respinrp);
}
- isp->isp_resodx = iptr;
-
if (optr == iptr && sema == 0) {
/*
@@ -5182,7 +5185,7 @@ again:
isp_prt(isp, ISP_LOGDEBUG1, "bogus intr- isr %x (%x) iptr %x optr %x", isr, junk, iptr, optr);
}
}
- isp->isp_resodx = iptr;
+ isp->isp_residx = iptr;
while (optr != iptr) {
uint8_t qe[QENTRY_LEN];
@@ -5552,13 +5555,9 @@ again:
*/
if (nlooked) {
ISP_WRITE(isp, isp->isp_respoutrp, optr);
- /*
- * While we're at it, read the requst queue out pointer.
- */
- isp->isp_reqodx = ISP_READ(isp, isp->isp_rqstoutrp);
- if (isp->isp_rscchiwater < ndone) {
+ isp->isp_resodx = optr;
+ if (isp->isp_rscchiwater < ndone)
isp->isp_rscchiwater = ndone;
- }
}
out:
@@ -5570,7 +5569,6 @@ out:
ISP_WRITE(isp, BIU_SEMA, 0);
}
- isp->isp_residx = optr;
for (i = 0; i < ndone; i++) {
xs = complist[i];
if (xs) {
Modified: head/sys/dev/isp/isp_freebsd.c
==============================================================================
--- head/sys/dev/isp/isp_freebsd.c Thu Oct 17 20:15:14 2013 (r256704)
+++ head/sys/dev/isp/isp_freebsd.c Thu Oct 17 20:19:15 2013 (r256705)
@@ -804,6 +804,7 @@ static ISP_INLINE tstate_t *get_lun_stat
static ISP_INLINE void rls_lun_statep(ispsoftc_t *, tstate_t *);
static ISP_INLINE inot_private_data_t *get_ntp_from_tagdata(ispsoftc_t *, uint32_t, uint32_t, tstate_t **);
static ISP_INLINE atio_private_data_t *isp_get_atpd(ispsoftc_t *, tstate_t *, uint32_t);
+static ISP_INLINE atio_private_data_t *isp_find_atpd(ispsoftc_t *, tstate_t *, uint32_t);
static ISP_INLINE void isp_put_atpd(ispsoftc_t *, tstate_t *, atio_private_data_t *);
static ISP_INLINE inot_private_data_t *isp_get_ntpd(ispsoftc_t *, tstate_t *);
static ISP_INLINE inot_private_data_t *isp_find_ntpd(ispsoftc_t *, tstate_t *, uint32_t, uint32_t);
@@ -937,8 +938,8 @@ get_lun_statep_from_tag(ispsoftc_t *isp,
for (i = 0; i < LUN_HASH_SIZE; i++) {
ISP_GET_PC_ADDR(isp, bus, lun_hash[i], lhp);
SLIST_FOREACH(tptr, lhp, next) {
- atp = isp_get_atpd(isp, tptr, tagval);
- if (atp && atp->tag == tagval) {
+ atp = isp_find_atpd(isp, tptr, tagval);
+ if (atp) {
tptr->hold++;
return (tptr);
}
@@ -1034,17 +1035,23 @@ isp_get_atpd(ispsoftc_t *isp, tstate_t *
{
atio_private_data_t *atp;
- if (tag == 0) {
- atp = tptr->atfree;
- if (atp) {
- tptr->atfree = atp->next;
- }
- return (atp);
+ atp = LIST_FIRST(&tptr->atfree);
+ if (atp) {
+ LIST_REMOVE(atp, next);
+ atp->tag = tag;
+ LIST_INSERT_HEAD(&tptr->atused[ATPDPHASH(tag)], atp, next);
}
- for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
- if (atp->tag == tag) {
+ return (atp);
+}
+
+static ISP_INLINE atio_private_data_t *
+isp_find_atpd(ispsoftc_t *isp, tstate_t *tptr, uint32_t tag)
+{
+ atio_private_data_t *atp;
+
+ LIST_FOREACH(atp, &tptr->atused[ATPDPHASH(tag)], next) {
+ if (atp->tag == tag)
return (atp);
- }
}
return (NULL);
}
@@ -1055,9 +1062,9 @@ isp_put_atpd(ispsoftc_t *isp, tstate_t *
if (atp->ests) {
isp_put_ecmd(isp, atp->ests);
}
+ LIST_REMOVE(atp, next);
memset(atp, 0, sizeof (*atp));
- atp->next = tptr->atfree;
- tptr->atfree = atp;
+ LIST_INSERT_HEAD(&tptr->atfree, atp, next);
}
static void
@@ -1067,11 +1074,8 @@ isp_dump_atpd(ispsoftc_t *isp, tstate_t
const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" };
for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
- if (atp->tag == 0) {
- continue;
- }
xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
- atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
+ atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
}
}
@@ -1137,11 +1141,13 @@ create_lun_state(ispsoftc_t *isp, int bu
SLIST_INIT(&tptr->atios);
SLIST_INIT(&tptr->inots);
TAILQ_INIT(&tptr->waitq);
- for (i = 0; i < ATPDPSIZE-1; i++) {
- tptr->atpool[i].next = &tptr->atpool[i+1];
+ LIST_INIT(&tptr->atfree);
+ for (i = ATPDPSIZE-1; i >= 0; i--)
+ LIST_INSERT_HEAD(&tptr->atfree, &tptr->atpool[i], next);
+ for (i = 0; i < ATPDPHASHSIZE; i++)
+ LIST_INIT(&tptr->atused[i]);
+ for (i = 0; i < ATPDPSIZE-1; i++)
tptr->ntpool[i].next = &tptr->ntpool[i+1];
- }
- tptr->atfree = tptr->atpool;
tptr->ntfree = tptr->ntpool;
tptr->hold = 1;
ISP_GET_PC_ADDR(isp, bus, lun_hash[LUN_HASH_FUNC(xpt_path_lun_id(tptr->owner))], lhp);
@@ -1620,7 +1626,7 @@ isp_target_start_ctio(ispsoftc_t *isp, u
}
}
- atp = isp_get_atpd(isp, tptr, cso->tag_id);
+ atp = isp_find_atpd(isp, tptr, cso->tag_id);
if (atp == NULL) {
isp_prt(isp, ISP_LOGERR, "%s: [0x%x] cannot find private data adjunct in %s", __func__, cso->tag_id, __func__);
isp_dump_atpd(isp, tptr);
@@ -2252,7 +2258,7 @@ isp_handle_platform_atio(ispsoftc_t *isp
}
}
- atp = isp_get_atpd(isp, tptr, 0);
+ atp = isp_get_atpd(isp, tptr, aep->at_handle);
atiop = (struct ccb_accept_tio *) SLIST_FIRST(&tptr->atios);
if (atiop == NULL || atp == NULL) {
/*
@@ -2272,7 +2278,6 @@ isp_handle_platform_atio(ispsoftc_t *isp
rls_lun_statep(isp, tptr);
return;
}
- atp->tag = aep->at_handle;
atp->rxid = aep->at_tag_val;
atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
@@ -2401,12 +2406,11 @@ isp_handle_platform_atio2(ispsoftc_t *is
goto noresrc;
}
- atp = isp_get_atpd(isp, tptr, 0);
+ atp = isp_get_atpd(isp, tptr, aep->at_rxid);
if (atp == NULL) {
goto noresrc;
}
- atp->tag = aep->at_rxid;
atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
@@ -2638,12 +2642,7 @@ isp_handle_platform_atio7(ispsoftc_t *is
goto noresrc;
}
- atp = isp_get_atpd(isp, tptr, 0);
- if (atp == NULL) {
- isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid);
- goto noresrc;
- }
- oatp = isp_get_atpd(isp, tptr, aep->at_rxid);
+ oatp = isp_find_atpd(isp, tptr, aep->at_rxid);
if (oatp) {
isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] tag wraparound in isp_handle_platforms_atio7 (N-Port Handle 0x%04x S_ID 0x%04x OX_ID 0x%04x) oatp state %d",
aep->at_rxid, nphdl, sid, aep->at_hdr.ox_id, oatp->state);
@@ -2652,8 +2651,12 @@ isp_handle_platform_atio7(ispsoftc_t *is
*/
goto noresrc;
}
+ atp = isp_get_atpd(isp, tptr, aep->at_rxid);
+ if (atp == NULL) {
+ isp_prt(isp, ISP_LOGTDEBUG0, "[0x%x] out of atps", aep->at_rxid);
+ goto noresrc;
+ }
atp->word3 = lp->prli_word3;
- atp->tag = aep->at_rxid;
atp->state = ATPD_STATE_ATIO;
SLIST_REMOVE_HEAD(&tptr->atios, sim_links.sle);
tptr->atio_count--;
@@ -2846,7 +2849,7 @@ isp_handle_srr_notify(ispsoftc_t *isp, v
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inot);
return;
}
- atp = isp_get_atpd(isp, tptr, tag);
+ atp = isp_find_atpd(isp, tptr, tag);
if (atp == NULL) {
rls_lun_statep(isp, tptr);
isp_prt(isp, ISP_LOGERR, "%s: cannot find adjunct for %x in SRR Notify", __func__, tag);
@@ -2905,11 +2908,11 @@ isp_handle_platform_ctio(ispsoftc_t *isp
}
if (IS_24XX(isp)) {
- atp = isp_get_atpd(isp, tptr, ((ct7_entry_t *)arg)->ct_rxid);
+ atp = isp_find_atpd(isp, tptr, ((ct7_entry_t *)arg)->ct_rxid);
} else if (IS_FC(isp)) {
- atp = isp_get_atpd(isp, tptr, ((ct2_entry_t *)arg)->ct_rxid);
+ atp = isp_find_atpd(isp, tptr, ((ct2_entry_t *)arg)->ct_rxid);
} else {
- atp = isp_get_atpd(isp, tptr, ((ct_entry_t *)arg)->ct_fwhandle);
+ atp = isp_find_atpd(isp, tptr, ((ct_entry_t *)arg)->ct_fwhandle);
}
if (atp == NULL) {
rls_lun_statep(isp, tptr);
@@ -3093,7 +3096,7 @@ isp_handle_platform_notify_fc(ispsoftc_t
return;
}
}
- atp = isp_get_atpd(isp, tptr, inp->in_seqid);
+ atp = isp_find_atpd(isp, tptr, inp->in_seqid);
if (atp) {
inot = (struct ccb_immediate_notify *) SLIST_FIRST(&tptr->inots);
@@ -3516,7 +3519,7 @@ isp_target_mark_aborted(ispsoftc_t *isp,
}
}
- atp = isp_get_atpd(isp, tptr, accb->atio.tag_id);
+ atp = isp_find_atpd(isp, tptr, accb->atio.tag_id);
if (atp == NULL) {
ccb->ccb_h.status = CAM_REQ_INVALID;
} else {
@@ -5005,7 +5008,7 @@ isp_action(struct cam_sim *sim, union cc
if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
if (ccb->atio.tag_id) {
- atio_private_data_t *atp = isp_get_atpd(isp, tptr, ccb->atio.tag_id);
+ atio_private_data_t *atp = isp_find_atpd(isp, tptr, ccb->atio.tag_id);
if (atp) {
isp_put_atpd(isp, tptr, atp);
}
Modified: head/sys/dev/isp/isp_freebsd.h
==============================================================================
--- head/sys/dev/isp/isp_freebsd.h Thu Oct 17 20:15:14 2013 (r256704)
+++ head/sys/dev/isp/isp_freebsd.h Thu Oct 17 20:19:15 2013 (r256705)
@@ -95,11 +95,13 @@ void isp_put_ecmd(struct ispsoftc *, is
#define ISP_TARGET_FUNCTIONS 1
#define ATPDPSIZE 4096
+#define ATPDPHASHSIZE 16
+#define ATPDPHASH(x) ((((x) >> 24) ^ ((x) >> 16) ^ ((x) >> 8) ^ (x)) & \
+ ((ATPDPHASHSIZE) - 1))
#include <dev/isp/isp_target.h>
-
-typedef struct {
- void * next;
+typedef struct atio_private_data {
+ LIST_ENTRY(atio_private_data) next;
uint32_t orig_datalen;
uint32_t bytes_xfered;
uint32_t bytes_in_transit;
@@ -173,7 +175,8 @@ typedef struct tstate {
inot_private_data_t * restart_queue;
inot_private_data_t * ntfree;
inot_private_data_t ntpool[ATPDPSIZE];
- atio_private_data_t * atfree;
+ LIST_HEAD(, atio_private_data) atfree;
+ LIST_HEAD(, atio_private_data) atused[ATPDPHASHSIZE];
atio_private_data_t atpool[ATPDPSIZE];
} tstate_t;
Modified: head/sys/dev/isp/ispvar.h
==============================================================================
--- head/sys/dev/isp/ispvar.h Thu Oct 17 20:15:14 2013 (r256704)
+++ head/sys/dev/isp/ispvar.h Thu Oct 17 20:19:15 2013 (r256705)
@@ -614,8 +614,9 @@ struct ispsoftc {
volatile mbreg_t isp_curmbx; /* currently active mailbox command */
volatile uint32_t isp_reqodx; /* index of last ISP pickup */
volatile uint32_t isp_reqidx; /* index of next request */
- volatile uint32_t isp_residx; /* index of next result */
+ volatile uint32_t isp_residx; /* index of last ISP write */
volatile uint32_t isp_resodx; /* index of next result */
+ volatile uint32_t isp_atioodx; /* index of next ATIO */
volatile uint32_t isp_obits; /* mailbox command output */
volatile uint32_t isp_serno; /* rolling serial number */
volatile uint16_t isp_mboxtmp[MAX_MAILBOX];
More information about the svn-src-all
mailing list