Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Jun 2011 09:25:59 +0000 (UTC)
From:      Andreas Tobler <andreast@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222675 - head/sys/powerpc/powermac
Message-ID:  <201106040925.p549PxwC003019@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andreast
Date: Sat Jun  4 09:25:59 2011
New Revision: 222675
URL: http://svn.freebsd.org/changeset/base/222675

Log:
  - Improve error handling.
  - Add retry loops for the i2c read/write functions.
  
  Approved by:	nwhitehorn (mentor)

Modified:
  head/sys/powerpc/powermac/fcu.c

Modified: head/sys/powerpc/powermac/fcu.c
==============================================================================
--- head/sys/powerpc/powermac/fcu.c	Sat Jun  4 09:23:54 2011	(r222674)
+++ head/sys/powerpc/powermac/fcu.c	Sat Jun  4 09:25:59 2011	(r222675)
@@ -138,6 +138,8 @@ fcu_write(device_t dev, uint32_t addr, u
 	  int len)
 {
 	unsigned char buf[4];
+	int try = 0;
+
 	struct iic_msg msg[] = {
 		{ addr, IIC_M_WR, 0, buf }
 	};
@@ -145,33 +147,46 @@ fcu_write(device_t dev, uint32_t addr, u
 	msg[0].len = len + 1;
 	buf[0] = reg;
 	memcpy(buf + 1, buff, len);
-	if (iicbus_transfer(dev, msg, 1) != 0) {
-		device_printf(dev, "iicbus write failed\n");
-		return (EIO);
-	}
 
-	return (0);
+	for (;;)
+	{
+		if (iicbus_transfer(dev, msg, 1) == 0)
+			return (0);
 
+		if (++try > 5) {
+			device_printf(dev, "iicbus write failed\n");
+			return (-1);
+		}
+		pause("fcu_write", hz);
+	}
 }
 
 static int
 fcu_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
 {
 	uint8_t buf[4];
+	int err, try = 0;
 
 	struct iic_msg msg[2] = {
 	    { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
 	    { addr, IIC_M_RD, 1, buf },
 	};
 
-	if (iicbus_transfer(dev, msg, 2) != 0) {
-		device_printf(dev, "iicbus read failed\n");
-		return (EIO);
+	for (;;)
+	{
+		  err = iicbus_transfer(dev, msg, 2);
+		  if (err != 0)
+			  goto retry;
+
+		  *data = *((uint8_t*)buf);
+		  return (0);
+	retry:
+		  if (++try > 5) {
+			  device_printf(dev, "iicbus read failed\n");
+			  return (-1);
+		  }
+		  pause("fcu_read_1", hz);
 	}
-
-	*data = *((uint8_t*)buf);
-
-	return (0);
 }
 
 static int
@@ -267,13 +282,14 @@ fcu_fan_set_rpm(struct fcu_fan *fan, int
 		fan->setpoint = rpm;
 	} else {
 		device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
-		return (EIO);
+		return (-1);
 	}
 
 	buf[0] = rpm >> (8 - fcu_rpm_shift);
 	buf[1] = rpm << fcu_rpm_shift;
 
-	fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2);
+	if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2) < 0)
+		return (-1);
 
 	return (0);
 }
@@ -292,7 +308,8 @@ fcu_fan_get_rpm(struct fcu_fan *fan)
 	if (fan->type == FCU_FAN_RPM) {
 		/* Check if the fan is available. */
 		reg = FCU_RPM_AVAILABLE;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+			return (-1);
 		if ((avail & (1 << fan->id)) == 0) {
 			device_printf(fan->dev,
 			    "RPM Fan not available ID: %d\n", fan->id);
@@ -300,7 +317,8 @@ fcu_fan_get_rpm(struct fcu_fan *fan)
 		}
 		/* Check if we have a failed fan. */
 		reg = FCU_RPM_FAIL;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+			return (-1);
 		if ((fail & (1 << fan->id)) != 0) {
 			device_printf(fan->dev,
 			    "RPM Fan failed ID: %d\n", fan->id);
@@ -308,7 +326,8 @@ fcu_fan_get_rpm(struct fcu_fan *fan)
 		}
 		/* Check if fan is active. */
 		reg = FCU_RPM_ACTIVE;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+			return (-1);
 		if ((active & (1 << fan->id)) == 0) {
 			device_printf(fan->dev, "RPM Fan not active ID: %d\n",
 				      fan->id);
@@ -322,7 +341,8 @@ fcu_fan_get_rpm(struct fcu_fan *fan)
 	}
 
 	/* It seems that we can read the fans rpm. */
-	fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buff);
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buff) < 0)
+		return (-1);
 
 	rpm = (buff[0] << (8 - fcu_rpm_shift)) | buff[1] >> fcu_rpm_shift;
 
@@ -356,8 +376,8 @@ fcu_fan_set_pwm(struct fcu_fan *fan, int
 
 	buf[0] = (pwm * 2550) / 1000;
 
-	fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1);
-
+	if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1) < 0)
+		return (-1);
 	return (0);
 }
 
@@ -374,26 +394,29 @@ fcu_fan_get_pwm(device_t dev, struct fcu
 	if (fan->type == FCU_FAN_PWM) {
 		/* Check if the fan is available. */
 		reg = FCU_PWM_AVAILABLE;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+			return (-1);
 		if ((avail & (1 << fan->id)) == 0) {
 			device_printf(dev, "PWM Fan not available ID: %d\n",
 				      fan->id);
-			return (EIO);
+			return (-1);
 		}
 		/* Check if we have a failed fan. */
 		reg = FCU_PWM_FAIL;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+			return (-1);
 		if ((fail & (1 << fan->id)) != 0) {
 			device_printf(dev, "PWM Fan failed ID: %d\n", fan->id);
-			return (EIO);
+			return (-1);
 		}
 		/* Check if fan is active. */
 		reg = FCU_PWM_ACTIVE;
-		fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active);
+		if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+			return (-1);
 		if ((active & (1 << fan->id)) == 0) {
 			device_printf(dev, "PWM Fan not active ID: %d\n",
 				      fan->id);
-			return (ENXIO);
+			return (-1);
 		}
 		reg = FCU_PWM_SGET(fan->id);
 	} else {
@@ -402,13 +425,16 @@ fcu_fan_get_pwm(device_t dev, struct fcu
 	}
 
 	/* It seems that we can read the fans pwm. */
-	fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf);
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+		return (-1);
 
 	*pwm = (buf[0] * 1000) / 2550;
 
 	/* Now read the rpm. */
 	reg = FCU_PWM_RPM(fan->id);
-	fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf);
+	if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+		return (-1);
+
 	*rpm = (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 
 	return (0);
@@ -502,16 +528,20 @@ fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
 	device_t fcu;
 	struct fcu_softc *sc;
 	struct fcu_fan *fan;
-	int rpm = 0, pwm = 0, error;
+	int rpm = 0, pwm = 0, error = 0;
 
 	fcu = arg1;
 	sc = device_get_softc(fcu);
 	fan = &sc->sc_fans[arg2 & 0x00ff];
 	if (fan->type == FCU_FAN_RPM) {
 		rpm = fcu_fan_get_rpm(fan);
+		if (rpm < 0)
+			return (-1);
 		error = sysctl_handle_int(oidp, &rpm, 0, req);
 	} else {
-		fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
+		error = fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
+		if (error < 0)
+			return (-1);
 
 		switch (arg2 & 0xff00) {
 		case FCU_PWM_SYSCTL_PWM:



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