svn commit: r260341 - stable/10/sys/dev/isp

Alexander Motin mav at FreeBSD.org
Sun Jan 5 22:38:45 UTC 2014


Author: mav
Date: Sun Jan  5 22:38:44 2014
New Revision: 260341
URL: http://svnweb.freebsd.org/changeset/base/260341

Log:
  MFC r256705:
  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.

Modified:
  stable/10/sys/dev/isp/isp.c
  stable/10/sys/dev/isp/isp_freebsd.c
  stable/10/sys/dev/isp/isp_freebsd.h
  stable/10/sys/dev/isp/ispvar.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/isp/isp.c
==============================================================================
--- stable/10/sys/dev/isp/isp.c	Sun Jan  5 22:36:34 2014	(r260340)
+++ stable/10/sys/dev/isp/isp.c	Sun Jan  5 22:38:44 2014	(r260341)
@@ -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: stable/10/sys/dev/isp/isp_freebsd.c
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.c	Sun Jan  5 22:36:34 2014	(r260340)
+++ stable/10/sys/dev/isp/isp_freebsd.c	Sun Jan  5 22:38:44 2014	(r260341)
@@ -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: stable/10/sys/dev/isp/isp_freebsd.h
==============================================================================
--- stable/10/sys/dev/isp/isp_freebsd.h	Sun Jan  5 22:36:34 2014	(r260340)
+++ stable/10/sys/dev/isp/isp_freebsd.h	Sun Jan  5 22:38:44 2014	(r260341)
@@ -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: stable/10/sys/dev/isp/ispvar.h
==============================================================================
--- stable/10/sys/dev/isp/ispvar.h	Sun Jan  5 22:36:34 2014	(r260340)
+++ stable/10/sys/dev/isp/ispvar.h	Sun Jan  5 22:38:44 2014	(r260341)
@@ -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