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

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
...@@ -1548,15 +1548,19 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p) ...@@ -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) ...@@ -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,7 +3573,7 @@ static void handle_error_indication(union ibmvnic_crq *crq, ...@@ -3569,7 +3573,7 @@ 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;
...@@ -3579,10 +3583,13 @@ static void handle_change_mac_rsp(union ibmvnic_crq *crq, ...@@ -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, ...@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment