diff options
author | Thomas Falcon <tlfalcon@linux.vnet.ibm.com> | 2018-01-29 14:45:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-29 18:03:24 -0500 |
commit | f813614f531114db796ad66ced75c5dc8db7aa3a (patch) | |
tree | f02d6f9194a193821a6c72ad06617af505b93d63 | |
parent | 233ac3891607f501f08879134d623b303838f478 (diff) |
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>
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 8f2a77ecf4fb..8c3058d5d191 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c | |||
@@ -1548,15 +1548,19 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p) | |||
1548 | crq.change_mac_addr.first = IBMVNIC_CRQ_CMD; | 1548 | crq.change_mac_addr.first = IBMVNIC_CRQ_CMD; |
1549 | crq.change_mac_addr.cmd = CHANGE_MAC_ADDR; | 1549 | crq.change_mac_addr.cmd = CHANGE_MAC_ADDR; |
1550 | ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data); | 1550 | ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data); |
1551 | |||
1552 | init_completion(&adapter->fw_done); | ||
1551 | ibmvnic_send_crq(adapter, &crq); | 1553 | ibmvnic_send_crq(adapter, &crq); |
1554 | wait_for_completion(&adapter->fw_done); | ||
1552 | /* netdev->dev_addr is changed in handle_change_mac_rsp function */ | 1555 | /* netdev->dev_addr is changed in handle_change_mac_rsp function */ |
1553 | return 0; | 1556 | return adapter->fw_done_rc ? -EIO : 0; |
1554 | } | 1557 | } |
1555 | 1558 | ||
1556 | static int ibmvnic_set_mac(struct net_device *netdev, void *p) | 1559 | static int ibmvnic_set_mac(struct net_device *netdev, void *p) |
1557 | { | 1560 | { |
1558 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); | 1561 | struct ibmvnic_adapter *adapter = netdev_priv(netdev); |
1559 | struct sockaddr *addr = p; | 1562 | struct sockaddr *addr = p; |
1563 | int rc; | ||
1560 | 1564 | ||
1561 | if (adapter->state == VNIC_PROBED) { | 1565 | if (adapter->state == VNIC_PROBED) { |
1562 | memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr)); | 1566 | memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr)); |
@@ -1564,9 +1568,9 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p) | |||
1564 | return 0; | 1568 | return 0; |
1565 | } | 1569 | } |
1566 | 1570 | ||
1567 | __ibmvnic_set_mac(netdev, addr); | 1571 | rc = __ibmvnic_set_mac(netdev, addr); |
1568 | 1572 | ||
1569 | return 0; | 1573 | return rc; |
1570 | } | 1574 | } |
1571 | 1575 | ||
1572 | /** | 1576 | /** |
@@ -3569,8 +3573,8 @@ static void handle_error_indication(union ibmvnic_crq *crq, | |||
3569 | ibmvnic_reset(adapter, VNIC_RESET_NON_FATAL); | 3573 | ibmvnic_reset(adapter, VNIC_RESET_NON_FATAL); |
3570 | } | 3574 | } |
3571 | 3575 | ||
3572 | static void handle_change_mac_rsp(union ibmvnic_crq *crq, | 3576 | static int handle_change_mac_rsp(union ibmvnic_crq *crq, |
3573 | struct ibmvnic_adapter *adapter) | 3577 | struct ibmvnic_adapter *adapter) |
3574 | { | 3578 | { |
3575 | struct net_device *netdev = adapter->netdev; | 3579 | struct net_device *netdev = adapter->netdev; |
3576 | struct device *dev = &adapter->vdev->dev; | 3580 | struct device *dev = &adapter->vdev->dev; |
@@ -3579,10 +3583,13 @@ static void handle_change_mac_rsp(union ibmvnic_crq *crq, | |||
3579 | rc = crq->change_mac_addr_rsp.rc.code; | 3583 | rc = crq->change_mac_addr_rsp.rc.code; |
3580 | if (rc) { | 3584 | if (rc) { |
3581 | dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc); | 3585 | dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc); |
3582 | return; | 3586 | goto out; |
3583 | } | 3587 | } |
3584 | memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0], | 3588 | memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0], |
3585 | ETH_ALEN); | 3589 | ETH_ALEN); |
3590 | out: | ||
3591 | complete(&adapter->fw_done); | ||
3592 | return rc; | ||
3586 | } | 3593 | } |
3587 | 3594 | ||
3588 | static void handle_request_cap_rsp(union ibmvnic_crq *crq, | 3595 | static void handle_request_cap_rsp(union ibmvnic_crq *crq, |
@@ -4042,7 +4049,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, | |||
4042 | break; | 4049 | break; |
4043 | case CHANGE_MAC_ADDR_RSP: | 4050 | case CHANGE_MAC_ADDR_RSP: |
4044 | netdev_dbg(netdev, "Got MAC address change Response\n"); | 4051 | netdev_dbg(netdev, "Got MAC address change Response\n"); |
4045 | handle_change_mac_rsp(crq, adapter); | 4052 | adapter->fw_done_rc = handle_change_mac_rsp(crq, adapter); |
4046 | break; | 4053 | break; |
4047 | case ERROR_INDICATION: | 4054 | case ERROR_INDICATION: |
4048 | netdev_dbg(netdev, "Got Error Indication\n"); | 4055 | netdev_dbg(netdev, "Got Error Indication\n"); |