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: Thomas Falcon <tlfalcon@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
233ac38916
commit
f813614f53
@ -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.first = IBMVNIC_CRQ_CMD;
|
||||||
crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
|
crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
|
||||||
ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);
|
ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data);
|
||||||
|
|
||||||
|
init_completion(&adapter->fw_done);
|
||||||
ibmvnic_send_crq(adapter, &crq);
|
ibmvnic_send_crq(adapter, &crq);
|
||||||
|
wait_for_completion(&adapter->fw_done);
|
||||||
/* netdev->dev_addr is changed in handle_change_mac_rsp function */
|
/* 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)
|
static int ibmvnic_set_mac(struct net_device *netdev, void *p)
|
||||||
{
|
{
|
||||||
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
|
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
|
||||||
struct sockaddr *addr = p;
|
struct sockaddr *addr = p;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (adapter->state == VNIC_PROBED) {
|
if (adapter->state == VNIC_PROBED) {
|
||||||
memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__ibmvnic_set_mac(netdev, addr);
|
rc = __ibmvnic_set_mac(netdev, addr);
|
||||||
|
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3569,8 +3573,8 @@ static void handle_error_indication(union ibmvnic_crq *crq,
|
|||||||
ibmvnic_reset(adapter, VNIC_RESET_NON_FATAL);
|
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 ibmvnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct net_device *netdev = adapter->netdev;
|
struct net_device *netdev = adapter->netdev;
|
||||||
struct device *dev = &adapter->vdev->dev;
|
struct device *dev = &adapter->vdev->dev;
|
||||||
@ -3579,10 +3583,13 @@ static void handle_change_mac_rsp(union ibmvnic_crq *crq,
|
|||||||
rc = crq->change_mac_addr_rsp.rc.code;
|
rc = crq->change_mac_addr_rsp.rc.code;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", 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],
|
memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0],
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
|
out:
|
||||||
|
complete(&adapter->fw_done);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_request_cap_rsp(union ibmvnic_crq *crq,
|
static void handle_request_cap_rsp(union ibmvnic_crq *crq,
|
||||||
@ -4042,7 +4049,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
|
|||||||
break;
|
break;
|
||||||
case CHANGE_MAC_ADDR_RSP:
|
case CHANGE_MAC_ADDR_RSP:
|
||||||
netdev_dbg(netdev, "Got MAC address change Response\n");
|
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;
|
break;
|
||||||
case ERROR_INDICATION:
|
case ERROR_INDICATION:
|
||||||
netdev_dbg(netdev, "Got Error Indication\n");
|
netdev_dbg(netdev, "Got Error Indication\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user