Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dfad09a6 authored by Thomas Falcon's avatar Thomas Falcon Committed by David S. Miller
Browse files

ibmvnic: Handle backing device failover and reinitialization



An upcoming feature of IBM VNIC protocol is the ability to configure
redundant backing devices for a VNIC client. In case of a failure
on the current backing device, the driver will receive a signal
from the hypervisor indicating that a failover will occur. The driver
will then wait for a message from the backing device before
establishing a new connection.

Signed-off-by: default avatarThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0180688
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
	struct device *dev = &adapter->vdev->dev;

	dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
	if (!adapter->failover)
		send_request_unmap(adapter, ltb->map_id);
}

@@ -522,6 +523,7 @@ static int ibmvnic_close(struct net_device *netdev)
	for (i = 0; i < adapter->req_rx_queues; i++)
		napi_disable(&adapter->napi[i]);

	if (!adapter->failover)
		netif_tx_stop_all_queues(netdev);

	if (adapter->bounce_buffer) {
@@ -3280,6 +3282,10 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
			rc = ibmvnic_send_crq_init(adapter);
			if (rc)
				dev_err(dev, "Error sending init rc=%ld\n", rc);
		} else if (gen_crq->cmd == IBMVNIC_DEVICE_FAILOVER) {
			dev_info(dev, "Backing device failover detected\n");
			netif_carrier_off(netdev);
			adapter->failover = true;
		} else {
			/* The adapter lost the connection */
			dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
@@ -3615,8 +3621,18 @@ static void handle_crq_init_rsp(struct work_struct *work)
	struct device *dev = &adapter->vdev->dev;
	struct net_device *netdev = adapter->netdev;
	unsigned long timeout = msecs_to_jiffies(30000);
	bool restart = false;
	int rc;

	if (adapter->failover) {
		release_sub_crqs(adapter);
		if (netif_running(netdev)) {
			netif_tx_disable(netdev);
			ibmvnic_close(netdev);
			restart = true;
		}
	}

	send_version_xchg(adapter);
	reinit_completion(&adapter->init_done);
	if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
@@ -3645,6 +3661,17 @@ static void handle_crq_init_rsp(struct work_struct *work)

	netdev->real_num_tx_queues = adapter->req_tx_queues;

	if (adapter->failover) {
		adapter->failover = false;
		if (restart) {
			rc = ibmvnic_open(netdev);
			if (rc)
				goto restart_failed;
		}
		netif_carrier_on(netdev);
		return;
	}

	rc = register_netdev(netdev);
	if (rc) {
		dev_err(dev,
@@ -3655,6 +3682,8 @@ static void handle_crq_init_rsp(struct work_struct *work)

	return;

restart_failed:
	dev_err(dev, "Failed to restart ibmvnic, rc=%d\n", rc);
register_failed:
	release_sub_crqs(adapter);
task_failed:
@@ -3692,6 +3721,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
	dev_set_drvdata(&dev->dev, netdev);
	adapter->vdev = dev;
	adapter->netdev = netdev;
	adapter->failover = false;

	ether_addr_copy(adapter->mac_addr, mac_addr_p);
	ether_addr_copy(netdev->dev_addr, adapter->mac_addr);
+2 −0
Original line number Diff line number Diff line
@@ -830,6 +830,7 @@ enum ibmvfc_crq_format {
	IBMVNIC_CRQ_INIT                 = 0x01,
	IBMVNIC_CRQ_INIT_COMPLETE        = 0x02,
	IBMVNIC_PARTITION_MIGRATED       = 0x06,
	IBMVNIC_DEVICE_FAILOVER          = 0x08,
};

struct ibmvnic_crq_queue {
@@ -1047,4 +1048,5 @@ struct ibmvnic_adapter {
	u8 map_id;

	struct work_struct vnic_crq_init;
	bool failover;
};