Re: Intel ICHx bus driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Jean,

On Tue, Mar 2, 2010 at 11:22 PM, Jean Delvare <khali@xxxxxxxxxxxx> wrote:
>
> Hi Felix,
>
> On Wed, 24 Feb 2010 14:01:56 +0200, Felix Rubinstein wrote:
> > Here is my code:
> >
> > ------------
> > #include <stdio.h>
> > #include <unistd.h>
> > #include <sys/types.h>
> > #include <sys/stat.h>
> > #include <fcntl.h>
> > #include <sys/ioctl.h>
> > #include <stdlib.h>
> >
> > #include "i2c-dev.h"
> > #include "i2cbusses.h"
> > #include "util.h"
> >
> > /* actually smbus allows up to 32 and i2c even more */
> > #define I2CRWL_MAX_PARAMS 10
> > #define I2CRWL_PARAMS_SHIFT 3
> >
> > static int i2c_writel(int fd, int datac, char *datav[])
> > {
> >         int i;
> >         unsigned char buf[I2CRWL_MAX_PARAMS];
> >         unsigned int data;
> >
> >         for (i = 0; i < datac && i < I2CRWL_MAX_PARAMS; i++) {
> >                 sscanf(datav[i], "%x", &data);
> >                 buf[i] = (unsigned char)data;
> >         }
> >
> >         if (i2c_smbus_write_i2c_block_data(fd, buf[0], datac - 1,
> > &buf[1]) < 0) {
> >                 perror("\n");
>
> You'd rather use:
>
>                perror("i2c_smbus_write_i2c_block_data");
>
> so that error messages are clearer.
>
> >                 return 1;
> >         }
> >
> >         return 0;
> > }
> >
> >
> > static void help(const char *progname)
> > {
> >         fprintf(stderr,
> >                         "Usage: %s I2CBUS CHIP-ADDRESS DATA0 [DATA1
> > ... DATAn]\n"
> >                         "  I2CBUS is an integer or an I2C bus name\n"
> >                         "  CHIP-ADDRESS is an integer (0x03 - 0x77)\n"
> >                         "  DATAx is data to be written to the chip,
> > where 0 <= x <= n\n\n", progname);
> >         exit(1);
> > }
> >
> > int main(int argc, char *argv[])
> > {
> >         int fd, i2cbus, addr, ret = 0;
> >         char filename[20];
> >
> >         if ((argc < I2CRWL_PARAMS_SHIFT + 1) || (I2CRWL_MAX_PARAMS +
> > I2CRWL_PARAMS_SHIFT < argc))
> >                 help(argv[0]);
> >
> >         i2cbus = lookup_i2c_bus(argv[1]);
> >         if (i2cbus < 0)
> >                 help(argv[0]);
> >
> >         addr = parse_i2c_address(argv[2]);
> >         if (addr < 0)
> >                 help(argv[0]);
> >
> >         fd = open_i2c_dev(i2cbus, filename, 0);
> >         if (fd < 0)
> >                 exit(1);
> >
> >         if (ioctl(fd, I2C_SLAVE, addr) < 0) {
> >                 ret = 1;
> >                 perror("");
>
> Same here, perror("ioctl(I2C_SLAVE)") or similar.
>
> >                 goto out;
> >         }
> >
> >
> >         if (i2c_writel(fd, argc - I2CRWL_PARAMS_SHIFT,
> > &argv[I2CRWL_PARAMS_SHIFT])) {
> >                 ret = 1;
> >                 goto out;
> >         }
> >
> >
> > out:
> >         close(fd);
> >
> >         return ret;
> > }
> > ------------
> >
> > BTW, I've disabled the FEATURE_BLOCK_BUFFER
> >
> > --- i2c-i801.c     2010-02-24 10:50:50.060209638 +0200
> > +++ i2c-i801.c.orig    2010-02-24 13:55:29.664070673 +0200
> > @@ -603,7 +603,6 @@
> >                 /* fall through */
> >         case PCI_DEVICE_ID_INTEL_82801DB_3:
> >                 i801_features |= FEATURE_SMBUS_PEC;
> > -               i801_features |= FEATURE_BLOCK_BUFFER;
> >                 break;
> >         }
> >
> > and now everything works smoothly. I2C write transaction of arbitrary
> > length are seen even by scope :)
> >
> > In case if I don't, here is what I get:
> >
> > $ dmesg | tail
> > Transaction timeout
> > Terminating the current operation
> > Failed terminating the transaction
> > Failed clearing status flags at end of transaction ...
>
> Obviously, if disabling the block buffer makes the same transaction
> work, then it has to be a bug in the driver. And the good news is: I
> was able to reproduce the bug using your test program, on an ICH5
> running kernel 2.6.27.45. On the same system, I can get SMBus block
> reads to work with or without the block buffer, so block buffer support
> is not entirely broken (if it was, we'd certainly have noticed earlier.)
>
> Now ideally we need to figure out whether SMBus block writes are
> affected as well. We already know that SMBus block reads are not, and
> I2C block writes are. As I2C block reads are excluded (the block buffer
> can not be used for them according to the datasheet, and the driver
> already does the right thing), checking whether SMBus block writes are
> affected will tell us whether all block writes are affected, or if I2C
> block writes only are affected. This should help us find out where and
> what the bug could be.

Ok, here is what I did.
I run the code with  i2c_smbus_write_block_data with E32B enabled,
i.e. the original version of the driver and SMBus multi-byte write
transactions were successful (I also verified it against the scope
analyzer).

But what I run the code with i2c_smbus_write_i2c_block_data, here is what I got:

# ./i2c_wl 0 0x28 0x1 0xff 0xff

i2c_smbus_write_i2c_block_data: Operation not permitted
l# ./i2c_wl 0 0x28 0x1 0xff 0xff 0xff 0xff
Success ...
# dmesg | tail
[  430.580131] i801_smbus 0000:00:1f.3: Transaction (post): CNT=14,
CMD=01, ADD=50, DAT0=02, DAT1=00
[  430.580312] i2c-adapter i2c-0: ioctl, cmd=0x708, arg=0x01
[  464.280155] i2c-adapter i2c-0: ioctl, cmd=0x703, arg=0x28
[  464.280155] i2c-adapter i2c-0: ioctl, cmd=0x708, arg=0x00
[  464.280155] i2c-adapter i2c-0: ioctl, cmd=0x720, arg=0xbfdaa63c
[  464.280155] i801_smbus 0000:00:1f.3: Transaction (pre): CNT=14,
CMD=01, ADD=50, DAT0=04, DAT1=00
[  464.280155] i801_smbus 0000:00:1f.3: SMBus busy (14). Resetting...
[  464.280155] i801_smbus 0000:00:1f.3: Successful!
[  464.287033] i801_smbus 0000:00:1f.3: Transaction (post): CNT=14,
CMD=01, ADD=50, DAT0=04, DAT1=00
[  464.287080] i2c-adapter i2c-0: ioctl, cmd=0x708, arg=0x01

In addition, the scope analyzer showed me that (when I run this
command ./i2c_wl 0 0x28 0x1 0xff 0xff) the last byte 0xff wasn't sent
on the bus. In contrary, every byte was on the bus with
i2c_smbus_write_block_data.

Thanks,
Felix R.

>
> --
> Jean Delvare
> http://khali.linux-fr.org/wishlist.html
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux