]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
idpf: set mac type when adding and removing MAC filters
authorEmil Tantilov <emil.s.tantilov@intel.com>
Thu, 14 Aug 2025 23:43:00 +0000 (16:43 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 9 Sep 2025 16:58:09 +0000 (18:58 +0200)
[ Upstream commit acf3a5c8be80fe238c1a7629db1c21c74a1f9dd4 ]

On control planes that allow changing the MAC address of the interface,
the driver must provide a MAC type to avoid errors such as:

idpf 0000:0a:00.0: Transaction failed (op 535)
idpf 0000:0a:00.0: Received invalid MAC filter payload (op 535) (len 0)
idpf 0000:0a:00.0: Transaction failed (op 536)

These errors occur during driver load or when changing the MAC via:
ip link set <iface> address <mac>

Add logic to set the MAC type when sending ADD/DEL (opcodes 535/536) to
the control plane. Since only one primary MAC is supported per vport, the
driver only needs to send an ADD opcode when setting it. Remove the old
address by calling __idpf_del_mac_filter(), which skips the message and
just clears the entry from the internal list. This avoids an error on DEL
as it attempts to remove an address already cleared by the preceding ADD
opcode.

Fixes: ce1b75d0635c ("idpf: add ptypes and MAC filter support")
Reported-by: Jian Liu <jianliu@redhat.com>
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Samuel Salin <Samuel.salin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/intel/idpf/idpf_lib.c
drivers/net/ethernet/intel/idpf/idpf_virtchnl.c

index 1468a0f0df2babb94ef729b602918491d94c904d..52d9caab2fcb2a489377624262ee002c849be97d 100644 (file)
@@ -2278,6 +2278,7 @@ static int idpf_set_mac(struct net_device *netdev, void *p)
        struct idpf_netdev_priv *np = netdev_priv(netdev);
        struct idpf_vport_config *vport_config;
        struct sockaddr *addr = p;
+       u8 old_mac_addr[ETH_ALEN];
        struct idpf_vport *vport;
        int err = 0;
 
@@ -2301,17 +2302,19 @@ static int idpf_set_mac(struct net_device *netdev, void *p)
        if (ether_addr_equal(netdev->dev_addr, addr->sa_data))
                goto unlock_mutex;
 
+       ether_addr_copy(old_mac_addr, vport->default_mac_addr);
+       ether_addr_copy(vport->default_mac_addr, addr->sa_data);
        vport_config = vport->adapter->vport_config[vport->idx];
        err = idpf_add_mac_filter(vport, np, addr->sa_data, false);
        if (err) {
                __idpf_del_mac_filter(vport_config, addr->sa_data);
+               ether_addr_copy(vport->default_mac_addr, netdev->dev_addr);
                goto unlock_mutex;
        }
 
-       if (is_valid_ether_addr(vport->default_mac_addr))
-               idpf_del_mac_filter(vport, np, vport->default_mac_addr, false);
+       if (is_valid_ether_addr(old_mac_addr))
+               __idpf_del_mac_filter(vport_config, old_mac_addr);
 
-       ether_addr_copy(vport->default_mac_addr, addr->sa_data);
        eth_hw_addr_set(netdev, addr->sa_data);
 
 unlock_mutex:
index 151beea20d34355c471517930c99aadaf69ee4d6..f27a8cf3816db35a063a835b839867dcc0dadd84 100644 (file)
@@ -3513,6 +3513,16 @@ u32 idpf_get_vport_id(struct idpf_vport *vport)
        return le32_to_cpu(vport_msg->vport_id);
 }
 
+static void idpf_set_mac_type(struct idpf_vport *vport,
+                             struct virtchnl2_mac_addr *mac_addr)
+{
+       bool is_primary;
+
+       is_primary = ether_addr_equal(vport->default_mac_addr, mac_addr->addr);
+       mac_addr->type = is_primary ? VIRTCHNL2_MAC_ADDR_PRIMARY :
+                                     VIRTCHNL2_MAC_ADDR_EXTRA;
+}
+
 /**
  * idpf_mac_filter_async_handler - Async callback for mac filters
  * @adapter: private data struct
@@ -3642,6 +3652,7 @@ int idpf_add_del_mac_filters(struct idpf_vport *vport,
                            list) {
                if (add && f->add) {
                        ether_addr_copy(mac_addr[i].addr, f->macaddr);
+                       idpf_set_mac_type(vport, &mac_addr[i]);
                        i++;
                        f->add = false;
                        if (i == total_filters)
@@ -3649,6 +3660,7 @@ int idpf_add_del_mac_filters(struct idpf_vport *vport,
                }
                if (!add && f->remove) {
                        ether_addr_copy(mac_addr[i].addr, f->macaddr);
+                       idpf_set_mac_type(vport, &mac_addr[i]);
                        i++;
                        f->remove = false;
                        if (i == total_filters)