PERFORCE change 570822 for review

Brooks Davis brooks at FreeBSD.org
Tue Sep 3 21:00:20 UTC 2013


http://p4web.freebsd.org/@@570822?ac=10

Change 570822 by brooks at brooks_zenith on 2013/09/03 20:59:40

	Sync CFI driver with FreeBSD/BERI.

Affected files ...

.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_bus_nexus.c#4 integrate
.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_core.c#8 integrate
.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_dev.c#5 integrate
.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_disk.c#7 integrate
.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_reg.h#6 integrate
.. //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_var.h#6 integrate

Differences ...

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_bus_nexus.c#4 (text+ko) ====

@@ -4,6 +4,11 @@
  * Copyright (c) 2009 Sam Leffler, Errno Consulting
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_core.c#8 (text+ko) ====

@@ -1,7 +1,13 @@
 /*-
  * Copyright (c) 2007, Juniper Networks, Inc.
+ * Copyright (c) 2012-2013, SRI International
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -49,6 +55,8 @@
 #include <dev/cfi/cfi_reg.h>
 #include <dev/cfi/cfi_var.h>
 
+static void cfi_add_sysctls(struct cfi_softc *);
+
 extern struct cdevsw cfi_cdevsw;
 
 char cfi_driver_name[] = "cfi";
@@ -260,9 +268,9 @@
 cfi_attach(device_t dev) 
 {
 	struct cfi_softc *sc;
-	struct timeval tv;
 	u_int blksz, blocks;
-	u_int r, u, usec;
+	u_int r, u;
+	uint64_t mtoexp, ttoexp;
 #ifdef CFI_SUPPORT_STRATAFLASH
 	uint64_t ppr;
 	char name[KENV_MNAMELEN], value[32];
@@ -281,38 +289,74 @@
 	sc->sc_handle = rman_get_bushandle(sc->sc_res);
 
 	/* Get time-out values for erase, write, and buffer write. */
-	bintime_clear(&sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE]);
-	usec = 1000 * (1 << cfi_read_qry(sc, CFI_QRY_TTO_ERASE));
-	tv.tv_sec = usec / 1000000;
-	tv.tv_usec = usec % 1000000;
-	timeval2bintime(&tv, &sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE]);
+	ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_ERASE);
+	mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_ERASE);
+	if (ttoexp == 0) {
+		device_printf(dev, "erase timeout == 0, using 2^16ms\n");
+		ttoexp = 16;
+	}
+	if (ttoexp > 41) {
+		device_printf(dev, "insane timeout: 2^%jdms\n", ttoexp);
+		return (EINVAL);
+	}
+	if (mtoexp == 0) {
+		device_printf(dev, "max erase timeout == 0, using 2^%jdms\n",
+		    ttoexp + 4);
+		mtoexp = 4;
+	}
+	if (ttoexp + mtoexp > 41) {
+		device_printf(dev, "insane max erase timeout: 2^%jd\n",
+		    ttoexp + mtoexp);
+		return (EINVAL);
+	}
+	sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE] = SBT_1MS * (1ULL << ttoexp);
 	sc->sc_max_timeouts[CFI_TIMEOUT_ERASE] =
-	    sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE];
-	bintime_mul(&sc->sc_max_timeouts[CFI_TIMEOUT_ERASE],
-	    1 << cfi_read_qry(sc, CFI_QRY_MTO_ERASE));
+	    sc->sc_typical_timeouts[CFI_TIMEOUT_ERASE] * (1ULL << mtoexp);
 
-	bintime_clear(&sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE]);
-	usec = 1 << cfi_read_qry(sc, CFI_QRY_TTO_WRITE);
-	tv.tv_sec = usec / 1000000;
-	tv.tv_usec = usec % 1000000;
-	timeval2bintime(&tv, &sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE]);
+	ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_WRITE);
+	mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_WRITE);
+	if (ttoexp == 0) {
+		device_printf(dev, "write timeout == 0, using 2^18ns\n");
+		ttoexp = 18;
+	}
+	if (ttoexp > 51) {
+		device_printf(dev, "insane write timeout: 2^%jdus\n", ttoexp);
+		return (EINVAL);
+	}
+	if (mtoexp == 0) {
+		device_printf(dev, "max write timeout == 0, using 2^%jdms\n",
+		    ttoexp + 4);
+		mtoexp = 4;
+	}
+	if (ttoexp + mtoexp > 51) {
+		device_printf(dev, "insane max write timeout: 2^%jdus\n",
+		    ttoexp + mtoexp);
+		return (EINVAL);
+	}
+	sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE] = SBT_1US * (1ULL << ttoexp);
 	sc->sc_max_timeouts[CFI_TIMEOUT_WRITE] =
-	    sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE];
-	bintime_mul(&sc->sc_max_timeouts[CFI_TIMEOUT_WRITE],
-	    1 << cfi_read_qry(sc, CFI_QRY_MTO_WRITE));
+	    sc->sc_typical_timeouts[CFI_TIMEOUT_WRITE] * (1ULL << mtoexp);
 
-	bintime_clear(&sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE]);
-	usec = 1 << cfi_read_qry(sc, CFI_QRY_TTO_BUFWRITE);
-	tv.tv_sec = usec / 1000000;
-	tv.tv_usec = usec % 1000000;
-	timeval2bintime(&tv, &sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE]);
+	ttoexp = cfi_read_qry(sc, CFI_QRY_TTO_BUFWRITE);
+	mtoexp = cfi_read_qry(sc, CFI_QRY_MTO_BUFWRITE);
+	/* Don't check for 0, it means not-supported. */
+	if (ttoexp > 51) {
+		device_printf(dev, "insane write timeout: 2^%jdus\n", ttoexp);
+		return (EINVAL);
+	}
+	if (ttoexp + mtoexp > 51) {
+		device_printf(dev, "insane max write timeout: 2^%jdus\n",
+		    ttoexp + mtoexp);
+		return (EINVAL);
+	}
+	sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] =
+	    SBT_1US * (1ULL << cfi_read_qry(sc, CFI_QRY_TTO_BUFWRITE));
 	sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE] =
-	    sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE];
-	bintime_mul(&sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE],
-	    1 << cfi_read_qry(sc, CFI_QRY_MTO_BUFWRITE));
+	    sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] *
+	    (1ULL << cfi_read_qry(sc, CFI_QRY_MTO_BUFWRITE));
 
 	/* Get the maximum size of a multibyte program */
-	if (bintime_isset(&sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE]))
+	if (sc->sc_typical_timeouts[CFI_TIMEOUT_BUFWRITE] != 0)
 		sc->sc_maxbuf = 1 << (cfi_read_qry(sc, CFI_QRY_MAXBUF) |
 		    cfi_read_qry(sc, CFI_QRY_MAXBUF) << 8);
 	else
@@ -350,6 +394,8 @@
 	    "%s%u", cfi_driver_name, u);
 	sc->sc_nod->si_drv1 = sc;
 
+	cfi_add_sysctls(sc);
+
 #ifdef CFI_SUPPORT_STRATAFLASH
 	/*
 	 * Store the Intel factory PPR in the environment.  In some
@@ -370,6 +416,45 @@
 	return (0);
 }
 
+static void
+cfi_add_sysctls(struct cfi_softc *sc)
+{
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid_list *children;
+
+	ctx = device_get_sysctl_ctx(sc->sc_dev);
+	children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev));
+
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+	    "typical_erase_timout_count",
+	    CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_ERASE],
+	    0, "Number of times the typical erase timeout was exceeded");
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+	    "max_erase_timout_count",
+	    CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_ERASE], 0,
+	    "Number of times the maximum erase timeout was exceeded");
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+	    "typical_write_timout_count",
+	    CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_WRITE], 0,
+	    "Number of times the typical write timeout was exceeded");
+	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+	    "max_write_timout_count",
+	    CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_WRITE], 0,
+	    "Number of times the maximum write timeout was exceeded");
+	if (sc->sc_maxbuf > 0) {
+		SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+		    "typical_bufwrite_timout_count",
+		    CTLFLAG_RD, &sc->sc_tto_counts[CFI_TIMEOUT_BUFWRITE], 0,
+		    "Number of times the typical buffered write timeout was "
+		    "exceeded");
+		SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
+		    "max_bufwrite_timout_count",
+		    CTLFLAG_RD, &sc->sc_mto_counts[CFI_TIMEOUT_BUFWRITE], 0,
+		    "Number of times the maximum buffered write timeout was "
+		    "exceeded");
+	}
+}
+
 int
 cfi_detach(device_t dev)
 {
@@ -384,21 +469,23 @@
 }
 
 static int
-cfi_wait_ready(struct cfi_softc *sc, u_int ofs, struct bintime *start,
+cfi_wait_ready(struct cfi_softc *sc, u_int ofs, sbintime_t start,
     enum cfi_wait_cmd cmd)
 {
 	int done, error, tto_exceeded;
 	uint32_t st0 = 0, st = 0;
-	struct bintime mend, now, tend;
+	sbintime_t now;
 
-	tend = mend = *start;
-	bintime_add(&tend, &sc->sc_typical_timeouts[cmd]);
-	bintime_add(&mend, &sc->sc_max_timeouts[cmd]);
-
 	done = 0;
 	error = 0;
 	tto_exceeded = 0;
 	while (!done && !error) {
+		/*
+		 * Save time before we start so we always do one check
+		 * after the timeout has expired.
+		 */
+		now = sbinuptime();
+
 		switch (sc->sc_cmdset) {
 		case CFI_VEND_INTEL_ECS:
 		case CFI_VEND_INTEL_SCS:
@@ -427,24 +514,25 @@
 			break;
 		}
 
-		binuptime(&now);
-		if (tto_exceeded || bintime_cmp(&now, &tend, >)) {
-			if (!tto_exceeded)
+		if (tto_exceeded ||
+		    now > start + sc->sc_typical_timeouts[cmd]) {
+			if (!tto_exceeded) {
 				tto_exceeded = 1;
-			if (bintime_cmp(&now, &mend, >)) {
+				sc->sc_tto_counts[cmd]++;
+#ifdef CFI_DEBUG_TIMEOUT
+				device_printf(sc->sc_dev,
+				    "typical timeout exceeded (cmd %d)", cmd);
+#endif
+			}
+			if (now > start + sc->sc_max_timeouts[cmd]) {
+				sc->sc_mto_counts[cmd]++;
 #ifdef CFI_DEBUG_TIMEOUT
 				device_printf(sc->sc_dev,
 				    "max timeout exceeded (cmd %d)", cmd);
 #endif
-				break;
 			}
 		}
 	}
-#ifdef CFI_DEBUG_TIMEOUT
-	if (tto_exceeded)
-		device_printf(sc->sc_dev,
-		    "typical timeout exceeded (cmd %d)", cmd);
-#endif
 	if (!done && !error)
 		error = ETIMEDOUT;
 	if (error)
@@ -464,7 +552,7 @@
 	int error, i, neederase = 0;
 	uint32_t st;
 	u_int wlen;
-	struct bintime start;
+	sbintime_t start;
 
 	/* Intel flash must be unlocked before modification */
 	switch (sc->sc_cmdset) {
@@ -476,15 +564,6 @@
 		break;
 	}
 
-	switch (sc->sc_cmdset) {
-	case CFI_VEND_INTEL_ECS:
-	case CFI_VEND_INTEL_SCS:
-		cfi_write(sc, sc->sc_wrofs, CFI_INTEL_LBS);
-		cfi_write(sc, sc->sc_wrofs, CFI_INTEL_UB);
-		cfi_write(sc, sc->sc_wrofs, CFI_BCS_READ_ARRAY);
-		break;
-	}
-
 	/* Check if an erase is required. */
 	for (i = 0; i < sc->sc_wrbufsz; i++)
 		if ((sc->sc_wrbuf[i] & sc->sc_wrbufcpy[i]) != sc->sc_wrbuf[i]) {
@@ -494,7 +573,7 @@
 
 	if (neederase) {
 		intr = intr_disable();
-		binuptime(&start);
+		start = sbinuptime();
 		/* Erase the block. */
 		switch (sc->sc_cmdset) {
 		case CFI_VEND_INTEL_ECS:
@@ -514,7 +593,7 @@
 			return (ENODEV);
 		}
 		intr_restore(intr);
-		error = cfi_wait_ready(sc, sc->sc_wrofs, &start, 
+		error = cfi_wait_ready(sc, sc->sc_wrofs, start, 
 		    CFI_TIMEOUT_ERASE);
 		if (error)
 			goto out;
@@ -533,11 +612,14 @@
 
 				intr = intr_disable();
 
-				binuptime(&start);
+				start = sbinuptime();
 				do {
 					cfi_write(sc, sc->sc_wrofs + i,
 					    CFI_BCS_BUF_PROG_SETUP);
-					/* XXX: do some timeout management */
+					if (sbinuptime() > start + sc->sc_max_timeouts[CFI_TIMEOUT_BUFWRITE]) {
+						error = ETIMEDOUT;
+						goto out;
+					}
 					st = cfi_read(sc, sc->sc_wrofs + i);
 				} while (! (st & CFI_INTEL_STATUS_WSMS));
 
@@ -567,7 +649,9 @@
 				intr_restore(intr);
 
 				error = cfi_wait_ready(sc, sc->sc_wrofs + i,
-				    &start, CFI_TIMEOUT_BUFWRITE);
+				    start, CFI_TIMEOUT_BUFWRITE);
+				if (error != 0)
+					goto out;
 			}
 			goto out;
 		default:
@@ -605,7 +689,7 @@
 		 */
 		intr = intr_disable();
 
-		binuptime(&start);
+		start = sbinuptime();
 		switch (sc->sc_cmdset) {
 		case CFI_VEND_INTEL_ECS:
 		case CFI_VEND_INTEL_SCS:
@@ -633,7 +717,7 @@
 		
 		intr_restore(intr);
 
-		error = cfi_wait_ready(sc, sc->sc_wrofs, &start,
+		error = cfi_wait_ready(sc, sc->sc_wrofs, start,
 		   CFI_TIMEOUT_WRITE);
 		if (error)
 			goto out;
@@ -732,7 +816,7 @@
 #ifdef CFI_ARMEDANDDANGEROUS
 	register_t intr;
 	int i, error;
-	struct bintime start;
+	sbintime_t start;
 #endif
 
 	if (sc->sc_cmdset != CFI_VEND_INTEL_ECS)
@@ -742,11 +826,11 @@
 #ifdef CFI_ARMEDANDDANGEROUS
 	for (i = 7; i >= 4; i--, id >>= 16) {
 		intr = intr_disable();
-		binuptime(&start);
+		start = sbinuptime();
 		cfi_write(sc, 0, CFI_INTEL_PP_SETUP);
 		cfi_put16(sc, CFI_INTEL_PR(i), id&0xffff);
 		intr_restore(intr);
-		error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, &start,
+		error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, start,
 		    CFI_TIMEOUT_WRITE);
 		if (error)
 			break;
@@ -787,7 +871,7 @@
 #ifdef CFI_ARMEDANDDANGEROUS
 	register_t intr;
 	int error;
-	struct bintime start;
+	sbintime_t start;
 #endif
 	if (sc->sc_cmdset != CFI_VEND_INTEL_ECS)
 		return EOPNOTSUPP;
@@ -801,7 +885,7 @@
 	cfi_write(sc, 0, CFI_INTEL_PP_SETUP);
 	cfi_put16(sc, CFI_INTEL_PLR, 0xFFFD);
 	intr_restore(intr);
-	error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, &start,
+	error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, start,
 	    CFI_TIMEOUT_WRITE);
 	cfi_write(sc, 0, CFI_BCS_READ_ARRAY);
 	return error;

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_dev.c#5 (text+ko) ====

@@ -1,7 +1,13 @@
 /*-
  * Copyright (c) 2007, Juniper Networks, Inc.
+ * Copyright (c) 2012-2013, SRI International
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_disk.c#7 (text+ko) ====

@@ -1,7 +1,13 @@
 /*-
  * Copyright (c) 2009 Sam Leffler, Errno Consulting
+ * Copyright (c) 2012-2013, SRI International
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -69,7 +75,6 @@
 static void cfi_disk_strategy(struct bio *);
 static int cfi_disk_ioctl(struct disk *, u_long, void *, int, struct thread *);
 
-
 static int
 cfi_disk_probe(device_t dev)
 {

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_reg.h#6 (text+ko) ====

@@ -1,7 +1,13 @@
 /*-
  * Copyright (c) 2007, Juniper Networks, Inc.
+ * Copyright (c) 2012-2013, SRI International
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:

==== //depot/projects/ctsrd/cheribsd/src/sys/dev/cfi/cfi_var.h#6 (text+ko) ====

@@ -1,7 +1,13 @@
 /*-
  * Copyright (c) 2007, Juniper Networks, Inc.
+ * Copyright (c) 2012-2013, SRI International
  * All rights reserved.
  *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * (FA8750-10-C-0237) ("CTSRD"), as part of the DARPA CRASH research
+ * programme.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -57,8 +63,10 @@
 	struct cfi_region *sc_region;	/* Array of region info. */
 
 	u_int		sc_cmdset;
-	struct bintime	sc_typical_timeouts[3];
-	struct bintime	sc_max_timeouts[3];
+	sbintime_t	sc_typical_timeouts[3];
+	sbintime_t	sc_max_timeouts[3];
+	u_int		sc_tto_counts[3];
+	u_int		sc_mto_counts[3];
 
 	u_int		sc_maxbuf;
 


More information about the p4-projects mailing list