Skip to content

Commit

Permalink
ibmvnic: Fix failover case for non-redundant configuration
Browse files Browse the repository at this point in the history
There is a failover case for a non-redundant pseries VNIC
configuration that was not being handled properly. The current
implementation assumes that the driver will always have a redandant
device to communicate with following a failover notification. There
are cases, however, when a non-redundant configuration can receive
a failover request. If that happens, the driver should wait until
it receives a signal that the device is ready for operation.

The driver is agnostic of its backing hardware configuration,
so this fix necessarily affects all device failover management.
The driver needs to wait until it receives a signal that the device
is ready for resetting. A flag is introduced to track this intermediary
state where the driver is waiting for an active device.

Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
tlfalcon authored and davem330 committed Apr 8, 2018
1 parent af894d2 commit 5a18e1e
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 8 deletions.
37 changes: 29 additions & 8 deletions drivers/net/ethernet/ibm/ibmvnic.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,11 @@ static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
adapter->replenish_add_buff_failure++;
atomic_add(buffers_added, &pool->available);

if (lpar_rc == H_CLOSED) {
if (lpar_rc == H_CLOSED || adapter->failover_pending) {
/* Disable buffer pool replenishment and report carrier off if
* queue is closed. Firmware guarantees that a signal will
* be sent to the driver, triggering a reset.
* queue is closed or pending failover.
* Firmware guarantees that a signal will be sent to the
* driver, triggering a reset.
*/
deactivate_rx_pools(adapter);
netif_carrier_off(adapter->netdev);
Expand Down Expand Up @@ -1068,6 +1069,14 @@ static int ibmvnic_open(struct net_device *netdev)
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
int rc;

/* If device failover is pending, just set device state and return.
* Device operation will be handled by reset routine.
*/
if (adapter->failover_pending) {
adapter->state = VNIC_OPEN;
return 0;
}

mutex_lock(&adapter->reset_lock);

if (adapter->state != VNIC_CLOSED) {
Expand Down Expand Up @@ -1225,6 +1234,14 @@ static int ibmvnic_close(struct net_device *netdev)
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
int rc;

/* If device failover is pending, just set device state and return.
* Device operation will be handled by reset routine.
*/
if (adapter->failover_pending) {
adapter->state = VNIC_CLOSED;
return 0;
}

mutex_lock(&adapter->reset_lock);
rc = __ibmvnic_close(netdev);
mutex_unlock(&adapter->reset_lock);
Expand Down Expand Up @@ -1559,8 +1576,9 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
dev_kfree_skb_any(skb);
tx_buff->skb = NULL;

if (lpar_rc == H_CLOSED) {
/* Disable TX and report carrier off if queue is closed.
if (lpar_rc == H_CLOSED || adapter->failover_pending) {
/* Disable TX and report carrier off if queue is closed
* or pending failover.
* Firmware guarantees that a signal will be sent to the
* driver, triggering a reset or some other action.
*/
Expand Down Expand Up @@ -1884,9 +1902,10 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
int ret;

if (adapter->state == VNIC_REMOVING ||
adapter->state == VNIC_REMOVED) {
adapter->state == VNIC_REMOVED ||
adapter->failover_pending) {
ret = EBUSY;
netdev_dbg(netdev, "Adapter removing, skipping reset\n");
netdev_dbg(netdev, "Adapter removing or pending failover, skipping reset\n");
goto err;
}

Expand Down Expand Up @@ -4162,7 +4181,9 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
case IBMVNIC_CRQ_INIT:
dev_info(dev, "Partner initialized\n");
adapter->from_passive_init = true;
adapter->failover_pending = false;
complete(&adapter->init_done);
ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
break;
case IBMVNIC_CRQ_INIT_COMPLETE:
dev_info(dev, "Partner initialization complete\n");
Expand All @@ -4179,7 +4200,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
ibmvnic_reset(adapter, VNIC_RESET_MOBILITY);
} else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) {
dev_info(dev, "Backing device failover detected\n");
ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
adapter->failover_pending = true;
} else {
/* The adapter lost the connection */
dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/ibm/ibmvnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,7 @@ struct ibmvnic_adapter {
bool napi_enabled, from_passive_init;

bool mac_change_pending;
bool failover_pending;

struct ibmvnic_tunables desired;
struct ibmvnic_tunables fallback;
Expand Down

0 comments on commit 5a18e1e

Please sign in to comment.