Subject: kern/32885: adt7463 i2c device does not always unlock i2c bus on error
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <njoly@pasteur.fr>
List: netbsd-bugs
Date: 02/20/2006 18:40:00
>Number:         32885
>Category:       kern
>Synopsis:       adt7463 i2c device does not always unlock i2c bus on error
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 20 18:40:00 +0000 2006
>Originator:     Nicolas Joly
>Release:        NetBSD 3.99.15
>Organization:
Institut Pasteur, Paris.
>Environment:
System: NetBSD lanfeust.sis.pasteur.fr 3.99.15 NetBSD 3.99.15 (LANFEUST) #7: Mon Feb 20 19:09:04 CET 2006 njoly@lanfeust.sis.pasteur.fr:/local/src/NetBSD/obj/amd64/sys/arch/amd64/compile/LANFEUST amd64
Architecture: x86_64
Machine: amd64
>Description:
While looking at the adt7463 code, i noticed that it will not unlock the i2c bus if
iic_exec() function fails ... 3 functions are involved: adt7463c_receive_1(),
adt7463c_send_1() and adt7463c_write_1().

While here add a missing newline, to make the boot messages nicer on my -current
NetBSD/amd64 workstation (Tyan S2885 motherboard):

OLD:
amdpm0 at pci0 dev 7 function 3: Advanced Micro Devices AMD8111 ACPI Controller (rev. 0x05)
iic0 at amdpm0: I2C bus
adt7463c0 at iic0 addr 0x2eamdpm0: random number generator enabled (apprx. 58ms)

NEW:
amdpm0 at pci0 dev 7 function 3: Advanced Micro Devices AMD8111 ACPI Controller (rev. 0x05)
iic0 at amdpm0: I2C bus
adt7463c0 at iic0 addr 0x2e
amdpm0: random number generator enabled (apprx. 58ms)

>How-To-Repeat:
code inspection, because amdpm(4) SMBus locking is a no-op for now.
>Fix:
Index: sys/dev/i2c/adt7463.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/adt7463.c,v
retrieving revision 1.2
diff -u -r1.2 adt7463.c
--- sys/dev/i2c/adt7463.c	19 Feb 2006 08:40:12 -0000	1.2
+++ sys/dev/i2c/adt7463.c	20 Feb 2006 18:17:26 -0000
@@ -90,6 +90,8 @@
         struct adt7463c_softc *sc = (struct adt7463c_softc *)self;
 	struct i2c_attach_args *ia = aux;
 	int i = 0;
+
+	printf("\n");
 	
 	sc->sc_tag = ia->ia_tag;
         sc->sc_address = ia->ia_addr;
@@ -359,8 +361,10 @@
 	  return (error);
 
 	if ((error = iic_exec(sc->sc_tag, I2C_OP_READ,
-			      sc->sc_address, NULL, 0, &val, 1, 0)) != 0)
+			      sc->sc_address, NULL, 0, &val, 1, 0)) != 0) {
+	  iic_release_bus(sc->sc_tag, 0);
 	  return (error);
+	}
 	
 	iic_release_bus(sc->sc_tag, 0);
 	return (val);
@@ -374,8 +378,10 @@
 	  return (error);
 
 	if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE,
-			      sc->sc_address, NULL, 0, &val, 1, 0)) != 0)
+			      sc->sc_address, NULL, 0, &val, 1, 0)) != 0) {
+	  iic_release_bus(sc->sc_tag, 0);
 	  return (error);
+	}
 	
 	iic_release_bus(sc->sc_tag, 0);
 	return (0);
@@ -389,8 +395,10 @@
 	  return (error);
 
 	if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE,
-			      sc->sc_address, &cmd, 1, &val, 1, 0)) != 0)
+			      sc->sc_address, &cmd, 1, &val, 1, 0)) != 0) {
+	  iic_release_bus(sc->sc_tag, 0);
 	  return (error);
+	}
 	
 	iic_release_bus(sc->sc_tag, 0);
 	return (0);