aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-12-18 02:00:31 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-12-19 19:43:48 -0500
commit286e310f94b9459f3fa975333781c969b1041522 (patch)
treef9d2eb2d52ad5fbd38b3790e2ce8fab21e9aae5e /drivers/net/tg3.c
parentb9fc7dc514566e9788c7f064bb08f8b6e2fe6f72 (diff)
[TG3]: Endianness bugfix.
tg3_nvram_write_block_unbuffered() is reading data from nvram into allocated buffer before overwriting a part of it with user-supplied data. Then it feeds the entire page back to nvram. It should be storing the words it had read as little-endian, not as host-endian. Note that tg3_set_eeprom() does exactly that for padding the same data to full words before it gets passed down to tg3_nvram_write_block() and then to tg3_nvram_write_block_unbuffered(). Moreover, when we get to sending the entire thing back to nvram, we go through it word-by-word, doing essentially writel(swab32(le32_to_cpu(word)), ...) so if we want them to reach the card in host-independent endianness, we'd better really have all that buffer filled with fixed-endian. For user-supplied part we obviously do have that (it's an array of octets memcpy'd in), ditto for padding of user-supplied part to word boundaries (taken care of in tg3_set_eeprom()). The rest of the buffer gets filled by tg3_nvram_write_block_unbuffered() and it would damn better be consistent with that (and with tg3_get_eeprom(), while we are at it - there we also convert the words read from nvram to little-endian before returning the buffer to user). The bug should get triggered on big-endian boxen when set_eeprom is done for less than entire page. Then the words that should've been unaffected at all will actually get byteswapped in place in nvram. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a76bb3dd30f7..22eb7c8c1a25 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10251,8 +10251,7 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len,
10251 phy_addr = offset & ~pagemask; 10251 phy_addr = offset & ~pagemask;
10252 10252
10253 for (j = 0; j < pagesize; j += 4) { 10253 for (j = 0; j < pagesize; j += 4) {
10254 /* Almost certainly should be tg3_nvram_read_le */ 10254 if ((ret = tg3_nvram_read_le(tp, phy_addr + j,
10255 if ((ret = tg3_nvram_read(tp, phy_addr + j,
10256 (__le32 *) (tmp + j)))) 10255 (__le32 *) (tmp + j))))
10257 break; 10256 break;
10258 } 10257 }