Commit acf3a5c8 authored by Emil Tantilov's avatar Emil Tantilov Committed by Tony Nguyen
Browse files

idpf: set mac type when adding and removing MAC filters



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: ce1b75d0 ("idpf: add ptypes and MAC filter support")
Reported-by: default avatarJian Liu <jianliu@redhat.com>
Signed-off-by: default avatarEmil Tantilov <emil.s.tantilov@intel.com>
Reviewed-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: default avatarPaul Menzel <pmenzel@molgen.mpg.de>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Tested-by: default avatarSamuel Salin <Samuel.salin@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 65637c3a
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -2344,6 +2344,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;

@@ -2367,17 +2368,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:
+12 −0
Original line number Diff line number Diff line
@@ -3765,6 +3765,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
@@ -3894,6 +3904,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)
@@ -3901,6 +3912,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)