struct list_head list;
 };
 
+#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG   0x2
+
 /**
  * struct nfp_tun_mac_addr_offload - configure MAC address of tunnel EP on NFP
- * @reserved:  reserved for future use
+ * @flags:     MAC address offload options
  * @count:     number of MAC addresses in the message (should be 1)
  * @index:     index of MAC address in the lookup table
  * @addr:      interface MAC address
  */
 struct nfp_tun_mac_addr_offload {
-       __be16 reserved;
+       __be16 flags;
        __be16 count;
        __be16 index;
        u8 addr[ETH_ALEN];
 };
 
+enum nfp_flower_mac_offload_cmd {
+       NFP_TUNNEL_MAC_OFFLOAD_ADD =            0,
+       NFP_TUNNEL_MAC_OFFLOAD_DEL =            1,
+};
+
 #define NFP_MAX_MAC_INDEX       0xff
 
 /**
        mutex_unlock(&priv->tun.mac_index_lock);
 }
 
-static int __nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx)
+static int
+__nfp_tunnel_offload_mac(struct nfp_app *app, u8 *mac, u16 idx, bool del)
 {
        struct nfp_tun_mac_addr_offload payload;
 
        memset(&payload, 0, sizeof(payload));
 
+       if (del)
+               payload.flags = cpu_to_be16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
+
        /* FW supports multiple MACs per cmsg but restrict to single. */
        payload.count = cpu_to_be16(1);
        payload.index = cpu_to_be16(idx);
 }
 
 static int
-nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev)
+nfp_tunnel_get_mac_idx_from_port(struct nfp_app *app, struct net_device *netdev,
+                                int port, u16 *nfp_mac_idx)
 {
-       u16 nfp_mac_idx;
-       int port = 0;
-
-       if (nfp_netdev_is_nfp_repr(netdev))
-               port = nfp_repr_get_port_id(netdev);
-       else if (!nfp_fl_is_netdev_to_offload(netdev))
-               return 0;
-
-       if (!is_valid_ether_addr(netdev->dev_addr))
-               return -EINVAL;
-
        if (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port) ==
            NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT) {
-               nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;
+               *nfp_mac_idx = port << 8 | NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT;
        } else if (!port) {
                /* Must assign our own unique 8-bit index. */
                int idx = nfp_tun_get_mac_idx(app, netdev->ifindex);
                if (idx < 0)
                        return idx;
 
-               nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
+               *nfp_mac_idx = idx << 8 | NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT;
+       } else {
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int
+nfp_tunnel_offload_mac(struct nfp_app *app, struct net_device *netdev,
+                      enum nfp_flower_mac_offload_cmd cmd)
+{
+       bool non_repr = false;
+       int err, port = 0;
+       u16 nfp_mac_idx;
+
+       if (nfp_netdev_is_nfp_repr(netdev)) {
+               struct nfp_repr *repr;
+
+               repr = netdev_priv(netdev);
+               if (repr->app != app)
+                       return 0;
+
+               port = nfp_repr_get_port_id(netdev);
+       } else if (nfp_fl_is_netdev_to_offload(netdev)) {
+               non_repr = true;
        } else {
                return 0;
        }
 
-       return __nfp_tunnel_offload_mac(app, netdev->dev_addr, nfp_mac_idx);
+       if (!is_valid_ether_addr(netdev->dev_addr))
+               return -EINVAL;
+
+       switch (cmd) {
+       case NFP_TUNNEL_MAC_OFFLOAD_ADD:
+               err = nfp_tunnel_get_mac_idx_from_port(app, netdev, port,
+                                                      &nfp_mac_idx);
+               if (err)
+                       return err;
+
+               return __nfp_tunnel_offload_mac(app, netdev->dev_addr,
+                                               nfp_mac_idx, false);
+       case NFP_TUNNEL_MAC_OFFLOAD_DEL:
+               if (non_repr)
+                       nfp_tun_del_mac_idx(app, netdev->ifindex);
+
+               return __nfp_tunnel_offload_mac(app, netdev->dev_addr, 0, true);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 int nfp_tunnel_mac_event_handler(struct nfp_app *app,
 {
        int err;
 
-       if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER) {
-               /* If non-nfp netdev then free its offload index. */
-               if (nfp_fl_is_netdev_to_offload(netdev))
-                       nfp_tun_del_mac_idx(app, netdev->ifindex);
-       } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR ||
-                  event == NETDEV_REGISTER) {
-               err = nfp_tunnel_offload_mac(app, netdev);
+       if (event == NETDEV_DOWN) {
+               err = nfp_tunnel_offload_mac(app, netdev,
+                                            NFP_TUNNEL_MAC_OFFLOAD_DEL);
+               if (err)
+                       nfp_flower_cmsg_warn(app, "Failed to delete offload MAC on %s.\n",
+                                            netdev_name(netdev));
+       } else if (event == NETDEV_UP || event == NETDEV_CHANGEADDR) {
+               err = nfp_tunnel_offload_mac(app, netdev,
+                                            NFP_TUNNEL_MAC_OFFLOAD_ADD);
                if (err)
                        nfp_flower_cmsg_warn(app, "Failed to offload MAC on %s.\n",
                                             netdev_name(netdev));