Hello.

On 08/26/2016 11:01 PM, Chris Brandt wrote:

The RZ/A1 has a TSU, but since it only has one Ethernet port, it does not
have POST registers.

I'm not sure the reason is having one port... do you have the old SH manuals somewhere? :-)

Therefore, if you try to write to register index
TSU_POST1 (which will be FFFF because it does not exist), it will either
panic or corrupt memory elsewhere.

The true reason of that is that Ben Hutchings wasn't consistent with handling of SH_ETH_OFFSET_INVALID: he didn't add WARN_ON() to sh_eth_tsu_{read|wrte}() and friends. Maybe you can do this?

Reported-by: Daniel Palmer <dan...@0x0f.com>
Signed-off-by: Chris Brandt <chris.bra...@renesas.com>
---
 drivers/net/ethernet/renesas/sh_eth.c | 7 +++++++
 drivers/net/ethernet/renesas/sh_eth.h | 1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
b/drivers/net/ethernet/renesas/sh_eth.c
index 1f8240a..850a13c 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -532,6 +532,7 @@ static struct sh_eth_cpu_data r7s72100_data = {
        .no_ade         = 1,
        .hw_crc         = 1,
        .tsu            = 1,
+       .tsu_no_post    = 1,

The rest of the code seems to use sh_eth_is_rz_fast_ether() to differentiate the limited TSU implementation in the RZ/A1 SoC -- see sh_eth_tsu_init(). I'd prefer if you follow this suit. Either that or give this bitfield a different name.


        .shift_rd0      = 1,
 };

@@ -2460,6 +2461,9 @@ static void sh_eth_tsu_enable_cam_entry_post(struct 
net_device *ndev,
        u32 tmp;
        void *reg_offset;

+       if (mdp->cd->tsu_no_post)
+               return;
+
        reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);

I'd check check for SH_ETH_OFFSET_INVALID in the above function and return NULL if so; then we can check for NULL here...

        tmp = ioread32(reg_offset);
        iowrite32(tmp | sh_eth_tsu_get_post_bit(mdp, entry), reg_offset);
@@ -2472,6 +2476,9 @@ static bool sh_eth_tsu_disable_cam_entry_post(struct 
net_device *ndev,
        u32 post_mask, ref_mask, tmp;
        void *reg_offset;

+       if (mdp->cd->tsu_no_post)
+               return false;
+
        reg_offset = sh_eth_tsu_get_post_reg_offset(mdp, entry);

   ... and here.

        post_mask = sh_eth_tsu_get_post_mask(entry);
        ref_mask = sh_eth_tsu_get_post_bit(mdp, entry) & ~post_mask;
[...]

MBR, Sergei

Reply via email to