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

ibmvnic: Fix failover case for non-redundant configuration

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: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent af894d23
......@@ -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);
......@@ -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) {
......@@ -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);
......@@ -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.
*/
......@@ -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;
}
......@@ -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");
......@@ -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",
......
......@@ -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;
......
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