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>
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) {
base = (u32 __iomem *)&ugeth->ug_regs->tx64;
for (i = 0; i < UEC_HW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = in_be32(&base[i]);
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram;
for (i = 0; i < UEC_TX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram;
for (i = 0; i < UEC_RX_FW_STATS_LEN; i++)
- data[j++] = (u64)in_be32(&base[i]);
+ data[j++] = base ? in_be32(&base[i]) : 0;
}
}