diff options
author | Thomas Falcon <tlfalcon@linux.ibm.com> | 2019-05-10 07:13:43 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-05-11 01:11:43 +0300 |
commit | 62740e97881c78b45a117a358a866fb32975def6 (patch) | |
tree | f37a3d666a3061c3b13c7d01bd987f9b1490894f /drivers/net | |
parent | b96a54154be10f8d4f79d5d1cbfee7176947ad64 (diff) | |
download | linux-62740e97881c78b45a117a358a866fb32975def6.tar.xz |
net/ibmvnic: Update MAC address settings after adapter reset
It was discovered in testing that the underlying hardware MAC
address will revert to initial settings following a device reset,
but the driver fails to resend the current OS MAC settings. This
oversight can result in dropped packets should the scenario occur.
Fix this by informing hardware of current MAC address settings
following any adapter initialization or resets.
Signed-off-by: Thomas Falcon <tlfalcon@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 53 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.h | 2 |
2 files changed, 28 insertions, 27 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index b398d6c94dbd..2be3bcd0192f 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -118,7 +118,7 @@ static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter); static int ibmvnic_init(struct ibmvnic_adapter *); static int ibmvnic_reset_init(struct ibmvnic_adapter *); static void release_crq_queue(struct ibmvnic_adapter *); -static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p); +static int __ibmvnic_set_mac(struct net_device *, u8 *); static int init_crq_queue(struct ibmvnic_adapter *adapter); static int send_query_phys_parms(struct ibmvnic_adapter *adapter); @@ -849,11 +849,7 @@ static int ibmvnic_login(struct net_device *netdev) } } while (retry); - /* handle pending MAC address changes after successful login */ - if (adapter->mac_change_pending) { - __ibmvnic_set_mac(netdev, &adapter->desired.mac); - adapter->mac_change_pending = false; - } + __ibmvnic_set_mac(netdev, adapter->mac_addr); return 0; } @@ -1686,28 +1682,40 @@ static void ibmvnic_set_multi(struct net_device *netdev) } } -static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p) +static int __ibmvnic_set_mac(struct net_device *netdev, u8 *dev_addr) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; union ibmvnic_crq crq; int rc; - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; + if (!is_valid_ether_addr(dev_addr)) { + rc = -EADDRNOTAVAIL; + goto err; + } memset(&crq, 0, sizeof(crq)); 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); + ether_addr_copy(&crq.change_mac_addr.mac_addr[0], dev_addr); init_completion(&adapter->fw_done); rc = ibmvnic_send_crq(adapter, &crq); - if (rc) - return rc; + if (rc) { + rc = -EIO; + goto err; + } + wait_for_completion(&adapter->fw_done); /* netdev->dev_addr is changed in handle_change_mac_rsp function */ - return adapter->fw_done_rc ? -EIO : 0; + if (adapter->fw_done_rc) { + rc = -EIO; + goto err; + } + + return 0; +err: + ether_addr_copy(adapter->mac_addr, netdev->dev_addr); + return rc; } static int ibmvnic_set_mac(struct net_device *netdev, void *p) @@ -1716,13 +1724,10 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p) struct sockaddr *addr = p; int rc; - if (adapter->state == VNIC_PROBED) { - memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr)); - adapter->mac_change_pending = true; - return 0; - } - - rc = __ibmvnic_set_mac(netdev, addr); + rc = 0; + ether_addr_copy(adapter->mac_addr, addr->sa_data); + if (adapter->state != VNIC_PROBED) + rc = __ibmvnic_set_mac(netdev, addr->sa_data); return rc; } @@ -3937,8 +3942,8 @@ static int handle_change_mac_rsp(union ibmvnic_crq *crq, dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc); goto out; } - memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0], - ETH_ALEN); + ether_addr_copy(netdev->dev_addr, + &crq->change_mac_addr_rsp.mac_addr[0]); out: complete(&adapter->fw_done); return rc; @@ -4852,8 +4857,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) init_completion(&adapter->init_done); adapter->resetting = false; - adapter->mac_change_pending = false; - do { rc = init_crq_queue(adapter); if (rc) { diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index cffdac372a33..dcf2eb6d9290 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -969,7 +969,6 @@ struct ibmvnic_tunables { u64 rx_entries; u64 tx_entries; u64 mtu; - struct sockaddr mac; }; struct ibmvnic_adapter { @@ -1091,7 +1090,6 @@ struct ibmvnic_adapter { bool resetting; bool napi_enabled, from_passive_init; - bool mac_change_pending; bool failover_pending; bool force_reset_recovery; |