mirror of https://gitee.com/openkylin/linux.git
net: sfp: read eeprom in maximum 16 byte increments
Some SFP modules do not like reads longer than 16 bytes, so read the EEPROM in chunks of 16 bytes at a time. This behaviour is not specified in the SFP MSAs, which specifies: "The serial interface uses the 2-wire serial CMOS E2PROM protocol defined for the ATMEL AT24C01A/02/04 family of components." and "As long as the SFP+ receives an acknowledge, it shall serially clock out sequential data words. The sequence is terminated when the host responds with a NACK and a STOP instead of an acknowledge." We must avoid breaking a read across a 16-bit quantity in the diagnostic page, thankfully all 16-bit quantities in that page are naturally aligned. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
67c0aaa1ea
commit
28e74a7cfd
|
@ -281,6 +281,7 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
|||
{
|
||||
struct i2c_msg msgs[2];
|
||||
u8 bus_addr = a2 ? 0x51 : 0x50;
|
||||
size_t this_len;
|
||||
int ret;
|
||||
|
||||
msgs[0].addr = bus_addr;
|
||||
|
@ -292,11 +293,26 @@ static int sfp_i2c_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
|||
msgs[1].len = len;
|
||||
msgs[1].buf = buf;
|
||||
|
||||
ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
while (len) {
|
||||
this_len = len;
|
||||
if (this_len > 16)
|
||||
this_len = 16;
|
||||
|
||||
return ret == ARRAY_SIZE(msgs) ? len : 0;
|
||||
msgs[1].len = this_len;
|
||||
|
||||
ret = i2c_transfer(sfp->i2c, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret != ARRAY_SIZE(msgs))
|
||||
break;
|
||||
|
||||
msgs[1].buf += this_len;
|
||||
dev_addr += this_len;
|
||||
len -= this_len;
|
||||
}
|
||||
|
||||
return msgs[1].buf - (u8 *)buf;
|
||||
}
|
||||
|
||||
static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
|
||||
|
|
Loading…
Reference in New Issue