sh_eth: WARN on access to a register not implemented in a particular chip
authorBen Hutchings <ben.hutchings@codethink.co.uk>
Thu, 26 Feb 2015 20:34:14 +0000 (20:34 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Mar 2015 20:40:54 +0000 (15:40 -0500)
Currently we may silently read/write a register at offset 0.  Change
this to WARN and then ignore the write or read-back all-ones.

Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
Acked-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h

index 8e35ccba6259fff1ca2123eb81ae733cf50752b9..64e72ebdf8c51609746f636cd86f83983acc4751 100644 (file)
                NETIF_MSG_RX_ERR| \
                NETIF_MSG_TX_ERR)
 
+#define SH_ETH_OFFSET_DEFAULTS                 \
+       [0 ... SH_ETH_MAX_REGISTER_OFFSET - 1] = SH_ETH_OFFSET_INVALID
+
 static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+       SH_ETH_OFFSET_DEFAULTS,
+
        [EDSR]          = 0x0000,
        [EDMR]          = 0x0400,
        [EDTRR]         = 0x0408,
@@ -151,6 +156,8 @@ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
 };
 
 static const u16 sh_eth_offset_fast_rz[SH_ETH_MAX_REGISTER_OFFSET] = {
+       SH_ETH_OFFSET_DEFAULTS,
+
        [EDSR]          = 0x0000,
        [EDMR]          = 0x0400,
        [EDTRR]         = 0x0408,
@@ -210,6 +217,8 @@ static const u16 sh_eth_offset_fast_rz[SH_ETH_MAX_REGISTER_OFFSET] = {
 };
 
 static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
+       SH_ETH_OFFSET_DEFAULTS,
+
        [ECMR]          = 0x0300,
        [RFLR]          = 0x0308,
        [ECSR]          = 0x0310,
@@ -256,6 +265,8 @@ static const u16 sh_eth_offset_fast_rcar[SH_ETH_MAX_REGISTER_OFFSET] = {
 };
 
 static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
+       SH_ETH_OFFSET_DEFAULTS,
+
        [ECMR]          = 0x0100,
        [RFLR]          = 0x0108,
        [ECSR]          = 0x0110,
@@ -308,6 +319,8 @@ static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
 };
 
 static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+       SH_ETH_OFFSET_DEFAULTS,
+
        [EDMR]          = 0x0000,
        [EDTRR]         = 0x0004,
        [EDRRR]         = 0x0008,
@@ -1544,7 +1557,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        /* If we don't need to check status, don't. -KDU */
        if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R)) {
                /* fix the values for the next receiving if RDE is set */
-               if (intr_status & EESR_RDE && mdp->reg_offset[RDFAR] != 0) {
+               if (intr_status & EESR_RDE &&
+                   mdp->reg_offset[RDFAR] != SH_ETH_OFFSET_INVALID) {
                        u32 count = (sh_eth_read(ndev, RDFAR) -
                                     sh_eth_read(ndev, RDLAR)) >> 4;
 
index 259d03f353e109709abfbaac4a447d9f4af82026..33a360c4fd108ee5c521081ad3ce7e6abed6ae45 100644 (file)
@@ -543,19 +543,29 @@ static inline void sh_eth_soft_swap(char *src, int len)
 #endif
 }
 
+#define SH_ETH_OFFSET_INVALID  ((u16) ~0)
+
 static inline void sh_eth_write(struct net_device *ndev, u32 data,
                                int enum_index)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
+       u16 offset = mdp->reg_offset[enum_index];
+
+       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+               return;
 
-       iowrite32(data, mdp->addr + mdp->reg_offset[enum_index]);
+       iowrite32(data, mdp->addr + offset);
 }
 
 static inline u32 sh_eth_read(struct net_device *ndev, int enum_index)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
+       u16 offset = mdp->reg_offset[enum_index];
+
+       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+               return ~0U;
 
-       return ioread32(mdp->addr + mdp->reg_offset[enum_index]);
+       return ioread32(mdp->addr + offset);
 }
 
 static inline void *sh_eth_tsu_get_offset(struct sh_eth_private *mdp,