Date: Tue, 3 Sep 2013 21:00:19 GMT From: Brooks Davis <brooks@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 570822 for review Message-ID: <201309032100.r83L0Jdm014586@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@570822?ac=10 Change 570822 by brooks@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309032100.r83L0Jdm014586>