Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f813614f authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller
Browse files

ibmvnic: Wait for device response when changing MAC



Wait for a response from the VNIC server before exiting after setting
the MAC address. The resolves an issue with bonding a VNIC client in
ALB or TLB modes. The bonding driver was changing the MAC address more
rapidly than the device could respond, causing the following errors.

"bond0: the hw address of slave eth2 is in use by the bond;
couldn't find a slave with a free hw address to give it
(this should not have happened)"

If the function waits until the change is finalized, these errors are
avoided.

Signed-off-by: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 233ac389
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -1548,15 +1548,19 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p)
	crq.change_mac_addr.first = IBMVNIC_CRQ_CMD;
	crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
	ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);

	init_completion(&adapter->fw_done);
	ibmvnic_send_crq(adapter, &crq);
	wait_for_completion(&adapter->fw_done);
	/* netdev->dev_addr is changed in handle_change_mac_rsp function */
	return 0;
	return adapter->fw_done_rc ? -EIO : 0;
}

static int ibmvnic_set_mac(struct net_device *netdev, void *p)
{
	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
	struct sockaddr *addr = p;
	int rc;

	if (adapter->state == VNIC_PROBED) {
		memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr));
@@ -1564,9 +1568,9 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p)
		return 0;
	}

	__ibmvnic_set_mac(netdev, addr);
	rc = __ibmvnic_set_mac(netdev, addr);

	return 0;
	return rc;
}

/**
@@ -3569,7 +3573,7 @@ static void handle_error_indication(union ibmvnic_crq *crq,
		ibmvnic_reset(adapter, VNIC_RESET_NON_FATAL);
}

static void handle_change_mac_rsp(union ibmvnic_crq *crq,
static int handle_change_mac_rsp(union ibmvnic_crq *crq,
				 struct ibmvnic_adapter *adapter)
{
	struct net_device *netdev = adapter->netdev;
@@ -3579,10 +3583,13 @@ static void handle_change_mac_rsp(union ibmvnic_crq *crq,
	rc = crq->change_mac_addr_rsp.rc.code;
	if (rc) {
		dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc);
		return;
		goto out;
	}
	memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0],
	       ETH_ALEN);
out:
	complete(&adapter->fw_done);
	return rc;
}

static void handle_request_cap_rsp(union ibmvnic_crq *crq,
@@ -4042,7 +4049,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
		break;
	case CHANGE_MAC_ADDR_RSP:
		netdev_dbg(netdev, "Got MAC address change Response\n");
		handle_change_mac_rsp(crq, adapter);
		adapter->fw_done_rc = handle_change_mac_rsp(crq, adapter);
		break;
	case ERROR_INDICATION:
		netdev_dbg(netdev, "Got Error Indication\n");