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:
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to