|
@@ -203,7 +203,8 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
|
|
struct device *dev = &adapter->vdev->dev;
|
|
struct device *dev = &adapter->vdev->dev;
|
|
|
|
|
|
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
|
|
- send_request_unmap(adapter, ltb->map_id);
|
|
|
|
|
|
+ if (!adapter->failover)
|
|
|
|
+ send_request_unmap(adapter, ltb->map_id);
|
|
}
|
|
}
|
|
|
|
|
|
static int alloc_rx_pool(struct ibmvnic_adapter *adapter,
|
|
static int alloc_rx_pool(struct ibmvnic_adapter *adapter,
|
|
@@ -522,7 +523,8 @@ static int ibmvnic_close(struct net_device *netdev)
|
|
for (i = 0; i < adapter->req_rx_queues; i++)
|
|
for (i = 0; i < adapter->req_rx_queues; i++)
|
|
napi_disable(&adapter->napi[i]);
|
|
napi_disable(&adapter->napi[i]);
|
|
|
|
|
|
- netif_tx_stop_all_queues(netdev);
|
|
|
|
|
|
+ if (!adapter->failover)
|
|
|
|
+ netif_tx_stop_all_queues(netdev);
|
|
|
|
|
|
if (adapter->bounce_buffer) {
|
|
if (adapter->bounce_buffer) {
|
|
if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
|
|
if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
|
|
@@ -3280,6 +3282,10 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
|
|
rc = ibmvnic_send_crq_init(adapter);
|
|
rc = ibmvnic_send_crq_init(adapter);
|
|
if (rc)
|
|
if (rc)
|
|
dev_err(dev, "Error sending init rc=%ld\n", 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 {
|
|
} else {
|
|
/* The adapter lost the connection */
|
|
/* The adapter lost the connection */
|
|
dev_err(dev, "Virtual Adapter failed (rc=%d)\n",
|
|
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 device *dev = &adapter->vdev->dev;
|
|
struct net_device *netdev = adapter->netdev;
|
|
struct net_device *netdev = adapter->netdev;
|
|
unsigned long timeout = msecs_to_jiffies(30000);
|
|
unsigned long timeout = msecs_to_jiffies(30000);
|
|
|
|
+ bool restart = false;
|
|
int rc;
|
|
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);
|
|
send_version_xchg(adapter);
|
|
reinit_completion(&adapter->init_done);
|
|
reinit_completion(&adapter->init_done);
|
|
if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
|
|
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;
|
|
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);
|
|
rc = register_netdev(netdev);
|
|
if (rc) {
|
|
if (rc) {
|
|
dev_err(dev,
|
|
dev_err(dev,
|
|
@@ -3655,6 +3682,8 @@ static void handle_crq_init_rsp(struct work_struct *work)
|
|
|
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+restart_failed:
|
|
|
|
+ dev_err(dev, "Failed to restart ibmvnic, rc=%d\n", rc);
|
|
register_failed:
|
|
register_failed:
|
|
release_sub_crqs(adapter);
|
|
release_sub_crqs(adapter);
|
|
task_failed:
|
|
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);
|
|
dev_set_drvdata(&dev->dev, netdev);
|
|
adapter->vdev = dev;
|
|
adapter->vdev = dev;
|
|
adapter->netdev = netdev;
|
|
adapter->netdev = netdev;
|
|
|
|
+ adapter->failover = false;
|
|
|
|
|
|
ether_addr_copy(adapter->mac_addr, mac_addr_p);
|
|
ether_addr_copy(adapter->mac_addr, mac_addr_p);
|
|
ether_addr_copy(netdev->dev_addr, adapter->mac_addr);
|
|
ether_addr_copy(netdev->dev_addr, adapter->mac_addr);
|