mlxsw: spectrum_switchdev: Check success of FDB add operation
authorShalom Toledo <shalomt@mellanox.com>
Thu, 1 Mar 2018 10:37:05 +0000 (11:37 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 4 Mar 2018 23:12:44 +0000 (18:12 -0500)
Until now, we assumed that in case of error when adding FDB entries, the
write operation will fail, but this is not the case. Instead, we need to
check that the number of entries reported in the response is equal to
the number of entries specified in the request.

Fixes: 56ade8fe3fe1 ("mlxsw: spectrum: Add initial support for Spectrum ASIC")
Reported-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Shalom Toledo <shalomt@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

index 593ad31be7490d6af8abf3f5c3929de925c0ca77..161bcdc012f07652eac9165e42e299457da05c7b 100644 (file)
@@ -1203,6 +1203,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                     bool dynamic)
 {
        char *sfd_pl;
+       u8 num_rec;
        int err;
 
        sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
@@ -1212,9 +1213,16 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
        mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
        mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
                              mac, fid, action, local_port);
+       num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
-       kfree(sfd_pl);
+       if (err)
+               goto out;
+
+       if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
+               err = -EBUSY;
 
+out:
+       kfree(sfd_pl);
        return err;
 }
 
@@ -1239,6 +1247,7 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
                                       bool adding, bool dynamic)
 {
        char *sfd_pl;
+       u8 num_rec;
        int err;
 
        sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
@@ -1249,9 +1258,16 @@ static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
        mlxsw_reg_sfd_uc_lag_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
                                  mac, fid, MLXSW_REG_SFD_REC_ACTION_NOP,
                                  lag_vid, lag_id);
+       num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
-       kfree(sfd_pl);
+       if (err)
+               goto out;
+
+       if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
+               err = -EBUSY;
 
+out:
+       kfree(sfd_pl);
        return err;
 }
 
@@ -1296,6 +1312,7 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
                                u16 fid, u16 mid_idx, bool adding)
 {
        char *sfd_pl;
+       u8 num_rec;
        int err;
 
        sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
@@ -1305,7 +1322,15 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
        mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
        mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid,
                              MLXSW_REG_SFD_REC_ACTION_NOP, mid_idx);
+       num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
+       if (err)
+               goto out;
+
+       if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
+               err = -EBUSY;
+
+out:
        kfree(sfd_pl);
        return err;
 }