Commit 18acfa2597d57c19249346d130fc3334244557b4
Committed by
Jeff Garzik
1 parent
1fa989e80a
Exists in
master
and in
7 other branches
net/ucc_geth: Fix oops in uec_get_ethtool_stats()
p_{tx,rx}_fw_statistics_pram are special: they're available only when a device is open. If the device is closed, we should just fill the data with zeroes. Fixes the following oops: root@b1:~# ifconfig eth1 down root@b1:~# ethtool -S eth1 Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc01e1dcc Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c01e1dcc] uec_get_ethtool_stats+0x98/0x124 LR [c0287cc8] ethtool_get_stats+0xfc/0x23c Call Trace: [cfaadde0] [c0287ca8] ethtool_get_stats+0xdc/0x23c (unreliable) [cfaade20] [c0288340] dev_ethtool+0x2fc/0x588 [cfaade50] [c0285648] dev_ioctl+0x290/0x33c [cfaadea0] [c0272238] sock_ioctl+0x80/0x2ec [cfaadec0] [c00b5ae4] vfs_ioctl+0x40/0xc0 [cfaadee0] [c00b5fa8] do_vfs_ioctl+0x78/0x20c [cfaadf10] [c00b617c] sys_ioctl+0x40/0x74 [cfaadf40] [c00142d8] ret_from_syscall+0x0/0x38 [...] ---[ end trace b941007b2dfb9759 ]--- Segmentation fault p.s. While at it, also remove u64 casts, they aren't needed. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Showing 1 changed file with 3 additions and 3 deletions Side-by-side Diff
drivers/net/ucc_geth_ethtool.c
... | ... | @@ -323,17 +323,17 @@ |
323 | 323 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { |
324 | 324 | base = (u32 __iomem *)&ugeth->ug_regs->tx64; |
325 | 325 | for (i = 0; i < UEC_HW_STATS_LEN; i++) |
326 | - data[j++] = (u64)in_be32(&base[i]); | |
326 | + data[j++] = in_be32(&base[i]); | |
327 | 327 | } |
328 | 328 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { |
329 | 329 | base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; |
330 | 330 | for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) |
331 | - data[j++] = (u64)in_be32(&base[i]); | |
331 | + data[j++] = base ? in_be32(&base[i]) : 0; | |
332 | 332 | } |
333 | 333 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { |
334 | 334 | base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; |
335 | 335 | for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) |
336 | - data[j++] = (u64)in_be32(&base[i]); | |
336 | + data[j++] = base ? in_be32(&base[i]) : 0; | |
337 | 337 | } |
338 | 338 | } |
339 | 339 |