if (!vid)
                unreg_mcast = port_mask;
        dev_info(common->dev, "Adding vlan %d to vlan filter\n", vid);
-       ret = cpsw_ale_add_vlan(common->ale, vid, port_mask,
-                               unreg_mcast, port_mask, 0);
+       ret = cpsw_ale_vlan_add_modify(common->ale, vid, port_mask,
+                                      unreg_mcast, port_mask, 0);
 
        pm_runtime_put(common->dev);
        return ret;
                                             __be16 proto, u16 vid)
 {
        struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+       struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
        int ret;
 
        if (!netif_running(ndev) || !vid)
        }
 
        dev_info(common->dev, "Removing vlan %d from vlan filter\n", vid);
-       ret = cpsw_ale_del_vlan(common->ale, vid, 0);
+       ret = cpsw_ale_del_vlan(common->ale, vid,
+                               BIT(port->port_id) | ALE_PORT_HOST);
 
        pm_runtime_put(common->dev);
        return ret;
 
 int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
 {
        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
-       int idx;
+       int members, idx;
 
        idx = cpsw_ale_match_vlan(ale, vid);
        if (idx < 0)
 
        cpsw_ale_read(ale, idx, ale_entry);
 
-       if (port_mask) {
-               cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
-       } else {
+       /* if !port_mask - force remove VLAN (legacy).
+        * Check if there are other VLAN members ports
+        * if no - remove VLAN.
+        * if yes it means same VLAN was added to >1 port in multi port mode, so
+        * remove port_mask ports from VLAN ALE entry excluding Host port.
+        */
+       members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST);
+       members &= ~port_mask;
+
+       if (!port_mask || !members) {
+               /* last port or force remove - remove VLAN */
                cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+       } else {
+               port_mask &= ~ALE_PORT_HOST;
+               cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
        }
 
        cpsw_ale_write(ale, idx, ale_entry);