| @@ -2946,14 +2946,71 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv, · 2945 unmodified lines |
| 2946 | 2946 | return 0; |
| 2947 | 2947 | } |
| 2948 | 2948 | |
| 2949 | +static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv, |
| 2950 | + struct mlx5e_priv *peer_priv) |
| 2951 | +{ |
| 2952 | + struct mlx5_core_dev *peer_mdev = peer_priv->mdev; |
| 2953 | + struct mlx5e_hairpin_entry *hpe; |
| 2954 | + u16 peer_vhca_id; |
| 2955 | + int bkt; |
| 2956 | + |
| 2957 | + if (!same_hw_devs(priv, peer_priv)) |
| 2958 | + return; |
| 2959 | + |
| 2960 | + peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id); |
| 2961 | + |
| 2962 | + hash_for_each(priv->fs.tc.hairpin_tbl, bkt, hpe, hairpin_hlist) { |
| 2963 | + if (hpe->peer_vhca_id == peer_vhca_id) |
| 2964 | + hpe->hp->pair->peer_gone = true; |
| 2965 | + } |
| 2966 | +} |
| 2967 | + |
| 2968 | +static int mlx5e_tc_netdev_event(struct notifier_block *this, |
| 2969 | + unsigned long event, void *ptr) |
| 2970 | +{ |
| 2971 | + struct net_device *ndev = netdev_notifier_info_to_dev(ptr); |
| 2972 | + struct mlx5e_flow_steering *fs; |
| 2973 | + struct mlx5e_priv *peer_priv; |
| 2974 | + struct mlx5e_tc_table *tc; |
| 2975 | + struct mlx5e_priv *priv; |
| 2976 | + |
| 2977 | + if (ndev->netdev_ops != &mlx5e_netdev_ops || |
| 2978 | + event != NETDEV_UNREGISTER || |
| 2979 | + ndev->reg_state == NETREG_REGISTERED) |
| 2980 | + return NOTIFY_DONE; |
| 2981 | + |
| 2982 | + tc = container_of(this, struct mlx5e_tc_table, netdevice_nb); |
| 2983 | + fs = container_of(tc, struct mlx5e_flow_steering, tc); |
| 2984 | + priv = container_of(fs, struct mlx5e_priv, fs); |
| 2985 | + peer_priv = netdev_priv(ndev); |
| 2986 | + if (priv == peer_priv || |
| 2987 | + !(priv->netdev->features & NETIF_F_HW_TC)) |
| 2988 | + return NOTIFY_DONE; |
| 2989 | + |
| 2990 | + mlx5e_tc_hairpin_update_dead_peer(priv, peer_priv); |
| 2991 | + |
| 2992 | + return NOTIFY_DONE; |
| 2993 | +} |
| 2994 | + |
| 2949 | 2995 | int mlx5e_tc_nic_init(struct mlx5e_priv *priv) |
| 2950 | 2996 | { |
| 2951 | 2997 | struct mlx5e_tc_table *tc = &priv->fs.tc; |
| 2998 | + int err; |
| 2952 | 2999 | |
| 2953 | 3000 | hash_init(tc->mod_hdr_tbl); |
| 2954 | 3001 | hash_init(tc->hairpin_tbl); |
| 2955 | 3002 | |
| 2956 | | − return rhashtable_init(&tc->ht, &tc_ht_params); |
| 3003 | + err = rhashtable_init(&tc->ht, &tc_ht_params); |
| 3004 | + if (err) |
| 3005 | + return err; |
| 3006 | + |
| 3007 | + tc->netdevice_nb.notifier_call = mlx5e_tc_netdev_event; |
| 3008 | + if (register_netdevice_notifier(&tc->netdevice_nb)) { |
| 3009 | + tc->netdevice_nb.notifier_call = NULL; |
| 3010 | + mlx5_core_warn(priv->mdev, "Failed to register netdev notifier\n"); |
| 3011 | + } |
| 3012 | + |
| 3013 | + return err; |
| 2957 | 3014 | } |
| 2958 | 3015 | |
| 2959 | 3016 | static void _mlx5e_tc_del_flow(void *ptr, void *arg) |
| @@ -2969,6 +3026,9 @@ void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv) · 9 unmodified lines |
| 2969 | 3026 | { |
| 2970 | 3027 | struct mlx5e_tc_table *tc = &priv->fs.tc; |
| 2971 | 3028 | |
| 3029 | + if (tc->netdevice_nb.notifier_call) |
| 3030 | + unregister_netdevice_notifier(&tc->netdevice_nb); |
| 3031 | + |
| 2972 | 3032 | rhashtable_free_and_destroy(&tc->ht, _mlx5e_tc_del_flow, NULL); |
| 2973 | 3033 | |
| 2974 | 3034 | if (!IS_ERR_OR_NULL(tc->t)) { |