Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Dec 2019 17:24:07 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r355494 - stable/12/sys/dev/iicbus
Message-ID:  <201912071724.xB7HO7J8022618@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Dec  7 17:24:07 2019
New Revision: 355494
URL: https://svnweb.freebsd.org/changeset/base/355494

Log:
  MFC r352338:
  
  Create a mechanism for encoding a system errno into the IIC_Exxxxx space.
  
  Errors are communicated between the i2c controller layer and upper layers
  (iicbus and slave device drivers) using a set of IIC_Exxxxxx constants which
  effectively define a private number space separate from (and having values
  that conflict with) the system errno number space. Sometimes it is necessary
  to report a plain old system error (especially EINTR) from the controller or
  bus layer and have that value make it back across the syscall interface
  intact.
  
  I initially considered replicating a few "crucial" errno values with similar
  names and new numbers, e.g., IIC_EINTR, IIC_ERESTART, etc. It seemed like
  that had the potential to grow over time until many of the errno names were
  duplicated into the IIC_Exxxxx space.
  
  So instead, this defines a mechanism to "encode" an errno into the IIC_Exxxx
  space by setting the high bit and putting the errno into the lower-order
  bits; a new errno2iic() function does this. The existing iic2errno()
  recognizes the encoded values and extracts the original errno out of the
  encoded value. An interesting wrinkle occurs with the pseudo-error values
  such as ERESTART -- they aleady have the high bit set, and turning it off
  would be the wrong thing to do. Instead, iic2errno() recognizes that lots of
  high bits are on (i.e., it's a negative number near to zero) and just
  returns that value as-is.
  
  Thus, existing drivers continue to work without needing any changes, and
  there is now a way to return errno values from the lower layers. The first
  use of that is in iicbus_poll() which does mtx_sleep() with the PCATCH flag,
  and needs to return the errno from that up the call chain.
  
  Differential Revision:	https://reviews.freebsd.org/D20975

Modified:
  stable/12/sys/dev/iicbus/iiconf.c
  stable/12/sys/dev/iicbus/iiconf.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/iicbus/iiconf.c
==============================================================================
--- stable/12/sys/dev/iicbus/iiconf.c	Sat Dec  7 17:19:36 2019	(r355493)
+++ stable/12/sys/dev/iicbus/iiconf.c	Sat Dec  7 17:24:07 2019	(r355494)
@@ -42,6 +42,18 @@ __FBSDID("$FreeBSD$");
 #include "iicbus_if.h"
 
 /*
+ * Encode a system errno value into the IIC_Exxxxx space by setting the
+ * IIC_ERRNO marker bit, so that iic2errno() can turn it back into a plain
+ * system errno value later.  This lets controller- and bus-layer code get
+ * important system errno values (such as EINTR/ERESTART) back to the caller.
+ */
+int
+errno2iic(int errno)
+{
+	return ((errno == 0) ? 0 : errno | IIC_ERRNO);
+}
+
+/*
  * Translate IIC_Exxxxx status values to vaguely-equivelent errno values.
  */
 int
@@ -59,7 +71,22 @@ iic2errno(int iic_status)
 	case IIC_ENOTSUPP:      return (EOPNOTSUPP);
 	case IIC_ENOADDR:       return (EADDRNOTAVAIL);
 	case IIC_ERESOURCE:     return (ENOMEM);
-	default:                return (EIO);
+	default:
+		/*
+		 * If the high bit is set, that means it's a system errno value
+		 * that was encoded into the IIC_Exxxxxx space by setting the
+		 * IIC_ERRNO marker bit.  If lots of high-order bits are set,
+		 * then it's one of the negative pseudo-errors such as ERESTART
+		 * and we return it as-is.  Otherwise it's a plain "small
+		 * positive integer" errno, so just remove the IIC_ERRNO marker
+		 * bit.  If it's some unknown number without the high bit set,
+		 * there isn't much we can do except call it an I/O error.
+		 */
+		if ((iic_status & IIC_ERRNO) == 0)
+			return (EIO);
+		if ((iic_status & 0xFFFF0000) != 0)
+			return (iic_status);
+		return (iic_status & ~IIC_ERRNO);
 	}
 }
 
@@ -97,7 +124,7 @@ iicbus_poll(struct iicbus_softc *sc, int how)
 		return (IIC_EBUSBSY);
 	}
 
-	return (error);
+	return (errno2iic(error));
 }
 
 /*

Modified: stable/12/sys/dev/iicbus/iiconf.h
==============================================================================
--- stable/12/sys/dev/iicbus/iiconf.h	Sat Dec  7 17:19:36 2019	(r355493)
+++ stable/12/sys/dev/iicbus/iiconf.h	Sat Dec  7 17:24:07 2019	(r355494)
@@ -96,12 +96,14 @@
 #define IIC_ENOTSUPP	0x8	/* request not supported */
 #define IIC_ENOADDR	0x9	/* no address assigned to the interface */
 #define IIC_ERESOURCE	0xa	/* resources (memory, whatever) unavailable */
+#define IIC_ERRNO	__INT_MIN /* marker bit: errno is in low-order bits */
 
 /*
  * Note that all iicbus functions return IIC_Exxxxx status values,
  * except iic2errno() (obviously) and iicbus_started() (returns bool).
  */
 extern int iic2errno(int);
+extern int errno2iic(int);
 extern int iicbus_request_bus(device_t, device_t, int);
 extern int iicbus_release_bus(device_t, device_t);
 extern device_t iicbus_alloc_bus(device_t);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912071724.xB7HO7J8022618>