Changeset 4014

Show
Ignore:
Timestamp:
11/05/05 18:06:20 (3 years ago)
Author:
khali
Message:

Backport SMBus PEC support rewrite from Linux 2.6:

This is my rewrite of the SMBus PEC support. The original
implementation was known to have bugs (credits go to Hideki Iwamoto
for reporting many of them recently), and was incomplete due to a
conceptual limitation.

The rewrite affects only software PEC. Hardware PEC needs very little
code and is mostly untouched.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • i2c/trunk/kernel/i2c-core.c

    r4004 r4014  
    2020/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. 
    2121   All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> 
    22    SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */ 
     22   SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and 
     23   Jean Delvare <khali@linux-fr.org> */ 
    2324 
    2425/* i2c-core.c,v 1.91.2.2 2003/01/21 10:00:19 kmalkki Exp */ 
     
    943944} 
    944945 
    945 /* CRC over count bytes in the first array plus the bytes in the rest 
    946    array if it is non-null. rest[0] is the (length of rest) - 1 
    947    and is included. */ 
    948 u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest) 
     946/* Incremental CRC8 over count bytes in the array pointed to by p */ 
     947static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) 
    949948{ 
    950949        int i; 
    951950 
    952951        for(i = 0; i < count; i++) 
    953                 crc = crc8((crc ^ first[i]) << 8); 
    954         if(rest != NULL) 
    955                 for(i = 0; i <= rest[0]; i++) 
    956                         crc = crc8((crc ^ rest[i]) << 8); 
     952                crc = crc8((crc ^ p[i]) << 8); 
    957953        return crc; 
    958954} 
    959955 
    960 u8 i2c_smbus_pec(int count, u8 *first, u8 *rest) 
    961 
    962         return i2c_smbus_partial_pec(0, count, first, rest); 
    963 
    964  
    965 /* Returns new "size" (transaction type) 
    966    Note that we convert byte to byte_data and byte_data to word_data 
    967    rather than invent new xxx_PEC transactions. */ 
    968 int i2c_smbus_add_pec(u16 addr, u8 command, int size, 
    969                       union i2c_smbus_data *data) 
    970 
    971         u8 buf[3]; 
    972  
    973         buf[0] = addr << 1; 
    974         buf[1] = command; 
    975         switch(size) { 
    976                 case I2C_SMBUS_BYTE: 
    977                         data->byte = i2c_smbus_pec(2, buf, NULL); 
    978                         size = I2C_SMBUS_BYTE_DATA; 
    979                         break; 
    980                 case I2C_SMBUS_BYTE_DATA: 
    981                         buf[2] = data->byte; 
    982                         data->word = buf[2] | 
    983                                     (i2c_smbus_pec(3, buf, NULL) << 8); 
    984                         size = I2C_SMBUS_WORD_DATA; 
    985                         break; 
    986                 case I2C_SMBUS_WORD_DATA: 
    987                         /* unsupported */ 
    988                         break; 
    989                 case I2C_SMBUS_BLOCK_DATA: 
    990                         data->block[data->block[0] + 1] = 
    991                                      i2c_smbus_pec(2, buf, data->block); 
    992                         size = I2C_SMBUS_BLOCK_DATA_PEC; 
    993                         break; 
    994         } 
    995         return size;     
    996 
    997  
    998 int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial, 
    999                         union i2c_smbus_data *data) 
    1000 
    1001         u8 buf[3], rpec, cpec; 
    1002  
    1003         buf[1] = command; 
    1004         switch(size) { 
    1005                 case I2C_SMBUS_BYTE_DATA: 
    1006                         buf[0] = (addr << 1) | 1; 
    1007                         cpec = i2c_smbus_pec(2, buf, NULL); 
    1008                         rpec = data->byte; 
    1009                         break; 
    1010                 case I2C_SMBUS_WORD_DATA: 
    1011                         buf[0] = (addr << 1) | 1; 
    1012                         buf[2] = data->word & 0xff; 
    1013                         cpec = i2c_smbus_pec(3, buf, NULL); 
    1014                         rpec = data->word >> 8; 
    1015                         break; 
    1016                 case I2C_SMBUS_WORD_DATA_PEC: 
    1017                         /* unsupported */ 
    1018                         cpec = rpec = 0; 
    1019                         break; 
    1020                 case I2C_SMBUS_PROC_CALL_PEC: 
    1021                         /* unsupported */ 
    1022                         cpec = rpec = 0; 
    1023                         break; 
    1024                 case I2C_SMBUS_BLOCK_DATA_PEC: 
    1025                         buf[0] = (addr << 1); 
    1026                         buf[2] = (addr << 1) | 1; 
    1027                         cpec = i2c_smbus_pec(3, buf, data->block); 
    1028                         rpec = data->block[data->block[0] + 1]; 
    1029                         break; 
    1030                 case I2C_SMBUS_BLOCK_PROC_CALL_PEC: 
    1031                         buf[0] = (addr << 1) | 1; 
    1032                         rpec = i2c_smbus_partial_pec(partial, 1, 
    1033                                                      buf, data->block); 
    1034                         cpec = data->block[data->block[0] + 1]; 
    1035                         break; 
    1036                 default: 
    1037                         cpec = rpec = 0; 
    1038                         break; 
    1039         } 
     956/* Assume a 7-bit address, which is reasonable for SMBus */ 
     957static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) 
     958
     959        /* The address will be sent first */ 
     960        u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); 
     961        pec = i2c_smbus_pec(pec, &addr, 1); 
     962 
     963        /* The data buffer follows */ 
     964        return i2c_smbus_pec(pec, msg->buf, msg->len); 
     965
     966 
     967/* Used for write only transactions */ 
     968static inline void i2c_smbus_add_pec(struct i2c_msg *msg) 
     969
     970        msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg); 
     971        msg->len++; 
     972
     973 
     974/* Return <0 on CRC error 
     975   If there was a write before this read (most cases) we need to take the 
     976   partial CRC from the write part into account. 
     977   Note that this function does modify the message (we need to decrease the 
     978   message length to hide the CRC byte from the caller). */ 
     979int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) 
     980
     981        u8 rpec = msg->buf[--msg->len]; 
     982        cpec = i2c_smbus_msg_pec(cpec, msg); 
     983 
    1040984        if(rpec != cpec) { 
    1041985                DEB(printk(KERN_DEBUG "i2c-core.o: Bad PEC 0x%02x vs. 0x%02x\n", 
     
    10641008extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value) 
    10651009{ 
    1066         union i2c_smbus_data data;      /* only for PEC */ 
    10671010        return i2c_smbus_xfer(client->adapter,client->addr,client->flags, 
    1068                               I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data); 
     1011                              I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); 
    10691012} 
    10701013 
     
    12241167                                }; 
    12251168        int i, len; 
     1169        u8 partial_pec = 0; 
    12261170 
    12271171        msgbuf0[0] = command; 
     
    12661210                break; 
    12671211        case I2C_SMBUS_BLOCK_DATA: 
    1268         case I2C_SMBUS_BLOCK_DATA_PEC: 
    12691212                if (read_write == I2C_SMBUS_READ) { 
    12701213                        /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_READ_BLOCK_DATA */ 
     
    12791222                        msg[1].flags |= I2C_M_RECV_LEN; 
    12801223                        msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; 
    1281                         if (size == I2C_SMBUS_BLOCK_DATA_PEC) { 
    1282                                 msg[1].len++; 
     1224                        if (flags & I2C_CLIENT_PEC) 
    12831225                                msg[1].flags |= I2C_M_RECV_PEC; 
    1284                         } 
    12851226                } else { 
    12861227                        msg[0].len = data->block[0] + 2; 
     
    12911232                                return -1; 
    12921233                        } 
    1293                         if(size == I2C_SMBUS_BLOCK_DATA_PEC) 
    1294                                 (msg[0].len)++; 
    12951234                        for (i = 1; i < msg[0].len; i++) 
    12961235                                msgbuf0[i] = data->block[i-1]; 
     
    12981237                break; 
    12991238        case I2C_SMBUS_BLOCK_PROC_CALL: 
    1300         case I2C_SMBUS_BLOCK_PROC_CALL_PEC: 
    13011239                /* I2C_FUNC_SMBUS_EMUL doesn't include I2C_FUNC_SMBUS_BLOCK_PROC_CALL */ 
    13021240                if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_PROC_CALL)) { 
     
    13221260                msg[1].flags |= I2C_M_RECV_LEN; 
    13231261                msg[1].len = I2C_SMBUS_BLOCK_MAX + 1; 
    1324                 if (size == I2C_SMBUS_BLOCK_PROC_CALL_PEC) { 
    1325                         msg[1].len++; 
     1262                if (flags & I2C_CLIENT_PEC) 
    13261263                        msg[1].flags |= I2C_M_RECV_PEC; 
    1327                 } 
    13281264                break; 
    13291265        case I2C_SMBUS_I2C_BLOCK_DATA: 
     
    13481284        } 
    13491285 
     1286        i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK 
     1287                                      && size != I2C_SMBUS_I2C_BLOCK_DATA); 
     1288        if (i) { 
     1289                /* Compute PEC if first message is a write */ 
     1290                if (!(msg[0].flags & I2C_M_RD)) { 
     1291                        if (num == 1) /* Write only */ 
     1292                                i2c_smbus_add_pec(&msg[0]); 
     1293                        else /* Write followed by read */ 
     1294                                partial_pec = i2c_smbus_msg_pec(0, &msg[0]); 
     1295                } 
     1296                /* Ask for PEC if last message is a read */ 
     1297                if (msg[num-1].flags & I2C_M_RD) 
     1298                        msg[num-1].len++; 
     1299        } 
     1300 
    13501301        if (i2c_transfer(adapter, msg, num) < 0) 
    13511302                return -1; 
     1303 
     1304        /* Check PEC if last message is a read */ 
     1305        if (i && (msg[num-1].flags & I2C_M_RD)) { 
     1306                if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) 
     1307                        return -1; 
     1308        } 
    13521309 
    13531310        if (read_write == I2C_SMBUS_READ) 
     
    13711328                        case I2C_SMBUS_BLOCK_DATA: 
    13721329                        case I2C_SMBUS_BLOCK_PROC_CALL: 
    1373                         case I2C_SMBUS_BLOCK_DATA_PEC: 
    1374                         case I2C_SMBUS_BLOCK_PROC_CALL_PEC: 
    13751330                                len = msgbuf1[0] + 1; 
    1376                                 if(size == I2C_SMBUS_BLOCK_DATA_PEC || 
    1377                                    size == I2C_SMBUS_BLOCK_PROC_CALL_PEC) 
    1378                                         len++; 
    13791331                                for (i = 0; i < len; i++) 
    13801332                                        data->block[i] = msgbuf1[i]; 
     
    13901342{ 
    13911343        s32 res; 
    1392         int swpec = 0; 
    1393         u8 partial = 0; 
    13941344 
    13951345        flags &= I2C_M_TEN | I2C_CLIENT_PEC; 
    1396         if((flags & I2C_CLIENT_PEC) && 
    1397            !(i2c_check_functionality(adap, I2C_FUNC_SMBUS_HWPEC_CALC))) { 
    1398                 swpec = 1; 
    1399                 if(read_write == I2C_SMBUS_READ && 
    1400                    size == I2C_SMBUS_BLOCK_DATA) 
    1401                         size = I2C_SMBUS_BLOCK_DATA_PEC; 
    1402                 else if(size == I2C_SMBUS_PROC_CALL) 
    1403                         size = I2C_SMBUS_PROC_CALL_PEC; 
    1404                 else if(size == I2C_SMBUS_BLOCK_PROC_CALL) { 
    1405                         i2c_smbus_add_pec(addr, command, 
    1406                                           I2C_SMBUS_BLOCK_DATA, data); 
    1407                         partial = data->block[data->block[0] + 1]; 
    1408                         size = I2C_SMBUS_BLOCK_PROC_CALL_PEC; 
    1409                 } else if(read_write == I2C_SMBUS_WRITE && 
    1410                           size != I2C_SMBUS_QUICK && 
    1411                           size != I2C_SMBUS_I2C_BLOCK_DATA) 
    1412                         size = i2c_smbus_add_pec(addr, command, size, data); 
    1413         } 
    14141346 
    14151347        if (adap->algo->smbus_xfer) { 
     
    14221354                                              command,size,data); 
    14231355 
    1424         if(res >= 0 && swpec && 
    1425            size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA && 
    1426            (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC || 
    1427             size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) { 
    1428                 if(i2c_smbus_check_pec(addr, command, size, partial, data)) 
    1429                         return -1; 
    1430         } 
    14311356        return res; 
    14321357}