]> 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 17:02:24 +0000 (19:02 +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 e9f8da9f7979bebc0199cc6c1d54b01099a932e3..5fc6147ecd93ccd793f12bdcb6ea42841d39ce90 100644 (file)
@@ -2277,6 +2277,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;
 
@@ -2300,17 +2301,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 24febaaa8fbb8338dcfd10ee66dd43114bbde5e3..cb9a27307670ee9ad91b90a7d07b790f4c05f1b4 100644 (file)
@@ -3507,6 +3507,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
@@ -3636,6 +3646,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)
@@ -3643,6 +3654,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)