ibmvnic: Insert header on VLAN tagged received frame
[linux-2.6-microblaze.git] / drivers / net / ethernet / ibm / ibmvnic.c
index b23d654..0f35954 100644 (file)
@@ -65,7 +65,6 @@
 #include <linux/irq.h>
 #include <linux/kthread.h>
 #include <linux/seq_file.h>
-#include <linux/debugfs.h>
 #include <linux/interrupt.h>
 #include <net/net_namespace.h>
 #include <asm/hvcall.h>
@@ -75,6 +74,7 @@
 #include <linux/uaccess.h>
 #include <asm/firmware.h>
 #include <linux/workqueue.h>
+#include <linux/if_vlan.h>
 
 #include "ibmvnic.h"
 
@@ -89,7 +89,6 @@ MODULE_VERSION(IBMVNIC_DRIVER_VERSION);
 static int ibmvnic_version = IBMVNIC_INITIAL_VERSION;
 static int ibmvnic_remove(struct vio_dev *);
 static void release_sub_crqs(struct ibmvnic_adapter *);
-static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *);
 static int ibmvnic_reset_crq(struct ibmvnic_adapter *);
 static int ibmvnic_send_crq_init(struct ibmvnic_adapter *);
 static int ibmvnic_reenable_crq_queue(struct ibmvnic_adapter *);
@@ -110,6 +109,11 @@ static int ibmvnic_poll(struct napi_struct *napi, int data);
 static void send_map_query(struct ibmvnic_adapter *adapter);
 static void send_request_map(struct ibmvnic_adapter *, dma_addr_t, __be32, u8);
 static void send_request_unmap(struct ibmvnic_adapter *, u8);
+static void send_login(struct ibmvnic_adapter *adapter);
+static void send_cap_queries(struct ibmvnic_adapter *adapter);
+static int init_sub_crq_irqs(struct ibmvnic_adapter *adapter);
+static int ibmvnic_init(struct ibmvnic_adapter *);
+static void release_crq_queue(struct ibmvnic_adapter *);
 
 struct ibmvnic_stat {
        char name[ETH_GSTRING_LEN];
@@ -159,21 +163,6 @@ static long h_reg_sub_crq(unsigned long unit_address, unsigned long token,
        return rc;
 }
 
-/* net_device_ops functions */
-
-static void init_rx_pool(struct ibmvnic_adapter *adapter,
-                        struct ibmvnic_rx_pool *rx_pool, int num, int index,
-                        int buff_size, int active)
-{
-       netdev_dbg(adapter->netdev,
-                  "Initializing rx_pool %d, %d buffs, %d bytes each\n",
-                  index, num, buff_size);
-       rx_pool->size = num;
-       rx_pool->index = index;
-       rx_pool->buff_size = buff_size;
-       rx_pool->active = active;
-}
-
 static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
                                struct ibmvnic_long_term_buff *ltb, int size)
 {
@@ -202,45 +191,12 @@ 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 (!ltb->buff)
+               return;
+
        if (!adapter->failover)
                send_request_unmap(adapter, ltb->map_id);
-}
-
-static int alloc_rx_pool(struct ibmvnic_adapter *adapter,
-                        struct ibmvnic_rx_pool *pool)
-{
-       struct device *dev = &adapter->vdev->dev;
-       int i;
-
-       pool->free_map = kcalloc(pool->size, sizeof(int), GFP_KERNEL);
-       if (!pool->free_map)
-               return -ENOMEM;
-
-       pool->rx_buff = kcalloc(pool->size, sizeof(struct ibmvnic_rx_buff),
-                               GFP_KERNEL);
-
-       if (!pool->rx_buff) {
-               dev_err(dev, "Couldn't alloc rx buffers\n");
-               kfree(pool->free_map);
-               return -ENOMEM;
-       }
-
-       if (alloc_long_term_buff(adapter, &pool->long_term_buff,
-                                pool->size * pool->buff_size)) {
-               kfree(pool->free_map);
-               kfree(pool->rx_buff);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < pool->size; ++i)
-               pool->free_map[i] = i;
-
-       atomic_set(&pool->available, 0);
-       pool->next_alloc = 0;
-       pool->next_free = 0;
-
-       return 0;
+       dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
 }
 
 static void replenish_rx_pool(struct ibmvnic_adapter *adapter,
@@ -347,93 +303,195 @@ static void replenish_pools(struct ibmvnic_adapter *adapter)
        }
 }
 
-static void free_rx_pool(struct ibmvnic_adapter *adapter,
-                        struct ibmvnic_rx_pool *pool)
+static void release_stats_token(struct ibmvnic_adapter *adapter)
 {
-       int i;
+       struct device *dev = &adapter->vdev->dev;
+
+       if (!adapter->stats_token)
+               return;
+
+       dma_unmap_single(dev, adapter->stats_token,
+                        sizeof(struct ibmvnic_statistics),
+                        DMA_FROM_DEVICE);
+       adapter->stats_token = 0;
+}
+
+static int init_stats_token(struct ibmvnic_adapter *adapter)
+{
+       struct device *dev = &adapter->vdev->dev;
+       dma_addr_t stok;
+
+       stok = dma_map_single(dev, &adapter->stats,
+                             sizeof(struct ibmvnic_statistics),
+                             DMA_FROM_DEVICE);
+       if (dma_mapping_error(dev, stok)) {
+               dev_err(dev, "Couldn't map stats buffer\n");
+               return -1;
+       }
+
+       adapter->stats_token = stok;
+       return 0;
+}
 
-       kfree(pool->free_map);
-       pool->free_map = NULL;
+static void release_rx_pools(struct ibmvnic_adapter *adapter)
+{
+       struct ibmvnic_rx_pool *rx_pool;
+       int rx_scrqs;
+       int i, j;
 
-       if (!pool->rx_buff)
+       if (!adapter->rx_pool)
                return;
 
-       for (i = 0; i < pool->size; i++) {
-               if (pool->rx_buff[i].skb) {
-                       dev_kfree_skb_any(pool->rx_buff[i].skb);
-                       pool->rx_buff[i].skb = NULL;
+       rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
+       for (i = 0; i < rx_scrqs; i++) {
+               rx_pool = &adapter->rx_pool[i];
+
+               kfree(rx_pool->free_map);
+               free_long_term_buff(adapter, &rx_pool->long_term_buff);
+
+               if (!rx_pool->rx_buff)
+               continue;
+
+               for (j = 0; j < rx_pool->size; j++) {
+                       if (rx_pool->rx_buff[j].skb) {
+                               dev_kfree_skb_any(rx_pool->rx_buff[i].skb);
+                               rx_pool->rx_buff[i].skb = NULL;
+                       }
                }
+
+               kfree(rx_pool->rx_buff);
        }
-       kfree(pool->rx_buff);
-       pool->rx_buff = NULL;
+
+       kfree(adapter->rx_pool);
+       adapter->rx_pool = NULL;
 }
 
-static int ibmvnic_open(struct net_device *netdev)
+static int init_rx_pools(struct net_device *netdev)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
        struct device *dev = &adapter->vdev->dev;
-       struct ibmvnic_tx_pool *tx_pool;
-       union ibmvnic_crq crq;
+       struct ibmvnic_rx_pool *rx_pool;
        int rxadd_subcrqs;
        u64 *size_array;
-       int tx_subcrqs;
        int i, j;
 
        rxadd_subcrqs =
-           be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
-       tx_subcrqs =
-           be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
+               be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
        size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
-                                 be32_to_cpu(adapter->login_rsp_buf->
-                                             off_rxadd_buff_size));
-       adapter->map_id = 1;
-       adapter->napi = kcalloc(adapter->req_rx_queues,
-                               sizeof(struct napi_struct), GFP_KERNEL);
-       if (!adapter->napi)
-               goto alloc_napi_failed;
-       for (i = 0; i < adapter->req_rx_queues; i++) {
-               netif_napi_add(netdev, &adapter->napi[i], ibmvnic_poll,
-                              NAPI_POLL_WEIGHT);
-               napi_enable(&adapter->napi[i]);
+               be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
+
+       adapter->rx_pool = kcalloc(rxadd_subcrqs,
+                                  sizeof(struct ibmvnic_rx_pool),
+                                  GFP_KERNEL);
+       if (!adapter->rx_pool) {
+               dev_err(dev, "Failed to allocate rx pools\n");
+               return -1;
        }
-       adapter->rx_pool =
-           kcalloc(rxadd_subcrqs, sizeof(struct ibmvnic_rx_pool), GFP_KERNEL);
 
-       if (!adapter->rx_pool)
-               goto rx_pool_arr_alloc_failed;
-       send_map_query(adapter);
        for (i = 0; i < rxadd_subcrqs; i++) {
-               init_rx_pool(adapter, &adapter->rx_pool[i],
-                            adapter->req_rx_add_entries_per_subcrq, i,
-                            be64_to_cpu(size_array[i]), 1);
-               if (alloc_rx_pool(adapter, &adapter->rx_pool[i])) {
-                       dev_err(dev, "Couldn't alloc rx pool\n");
-                       goto rx_pool_alloc_failed;
+               rx_pool = &adapter->rx_pool[i];
+
+               netdev_dbg(adapter->netdev,
+                          "Initializing rx_pool %d, %lld buffs, %lld bytes each\n",
+                          i, adapter->req_rx_add_entries_per_subcrq,
+                          be64_to_cpu(size_array[i]));
+
+               rx_pool->size = adapter->req_rx_add_entries_per_subcrq;
+               rx_pool->index = i;
+               rx_pool->buff_size = be64_to_cpu(size_array[i]);
+               rx_pool->active = 1;
+
+               rx_pool->free_map = kcalloc(rx_pool->size, sizeof(int),
+                                           GFP_KERNEL);
+               if (!rx_pool->free_map) {
+                       release_rx_pools(adapter);
+                       return -1;
+               }
+
+               rx_pool->rx_buff = kcalloc(rx_pool->size,
+                                          sizeof(struct ibmvnic_rx_buff),
+                                          GFP_KERNEL);
+               if (!rx_pool->rx_buff) {
+                       dev_err(dev, "Couldn't alloc rx buffers\n");
+                       release_rx_pools(adapter);
+                       return -1;
+               }
+
+               if (alloc_long_term_buff(adapter, &rx_pool->long_term_buff,
+                                        rx_pool->size * rx_pool->buff_size)) {
+                       release_rx_pools(adapter);
+                       return -1;
                }
+
+               for (j = 0; j < rx_pool->size; ++j)
+                       rx_pool->free_map[j] = j;
+
+               atomic_set(&rx_pool->available, 0);
+               rx_pool->next_alloc = 0;
+               rx_pool->next_free = 0;
+       }
+
+       return 0;
+}
+
+static void release_tx_pools(struct ibmvnic_adapter *adapter)
+{
+       struct ibmvnic_tx_pool *tx_pool;
+       int i, tx_scrqs;
+
+       if (!adapter->tx_pool)
+               return;
+
+       tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
+       for (i = 0; i < tx_scrqs; i++) {
+               tx_pool = &adapter->tx_pool[i];
+               kfree(tx_pool->tx_buff);
+               free_long_term_buff(adapter, &tx_pool->long_term_buff);
+               kfree(tx_pool->free_map);
        }
-       adapter->tx_pool =
-           kcalloc(tx_subcrqs, sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
 
+       kfree(adapter->tx_pool);
+       adapter->tx_pool = NULL;
+}
+
+static int init_tx_pools(struct net_device *netdev)
+{
+       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       struct device *dev = &adapter->vdev->dev;
+       struct ibmvnic_tx_pool *tx_pool;
+       int tx_subcrqs;
+       int i, j;
+
+       tx_subcrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
+       adapter->tx_pool = kcalloc(tx_subcrqs,
+                                  sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
        if (!adapter->tx_pool)
-               goto tx_pool_arr_alloc_failed;
+               return -1;
+
        for (i = 0; i < tx_subcrqs; i++) {
                tx_pool = &adapter->tx_pool[i];
-               tx_pool->tx_buff =
-                   kcalloc(adapter->req_tx_entries_per_subcrq,
-                           sizeof(struct ibmvnic_tx_buff), GFP_KERNEL);
-               if (!tx_pool->tx_buff)
-                       goto tx_pool_alloc_failed;
+               tx_pool->tx_buff = kcalloc(adapter->req_tx_entries_per_subcrq,
+                                          sizeof(struct ibmvnic_tx_buff),
+                                          GFP_KERNEL);
+               if (!tx_pool->tx_buff) {
+                       dev_err(dev, "tx pool buffer allocation failed\n");
+                       release_tx_pools(adapter);
+                       return -1;
+               }
 
                if (alloc_long_term_buff(adapter, &tx_pool->long_term_buff,
                                         adapter->req_tx_entries_per_subcrq *
-                                        adapter->req_mtu))
-                       goto tx_ltb_alloc_failed;
+                                        adapter->req_mtu)) {
+                       release_tx_pools(adapter);
+                       return -1;
+               }
 
-               tx_pool->free_map =
-                   kcalloc(adapter->req_tx_entries_per_subcrq,
-                           sizeof(int), GFP_KERNEL);
-               if (!tx_pool->free_map)
-                       goto tx_fm_alloc_failed;
+               tx_pool->free_map = kcalloc(adapter->req_tx_entries_per_subcrq,
+                                           sizeof(int), GFP_KERNEL);
+               if (!tx_pool->free_map) {
+                       release_tx_pools(adapter);
+                       return -1;
+               }
 
                for (j = 0; j < adapter->req_tx_entries_per_subcrq; j++)
                        tx_pool->free_map[j] = j;
@@ -441,20 +499,135 @@ static int ibmvnic_open(struct net_device *netdev)
                tx_pool->consumer_index = 0;
                tx_pool->producer_index = 0;
        }
-       adapter->bounce_buffer_size =
-           (netdev->mtu + ETH_HLEN - 1) / PAGE_SIZE + 1;
-       adapter->bounce_buffer = kmalloc(adapter->bounce_buffer_size,
-                                        GFP_KERNEL);
-       if (!adapter->bounce_buffer)
-               goto bounce_alloc_failed;
 
-       adapter->bounce_buffer_dma = dma_map_single(dev, adapter->bounce_buffer,
-                                                   adapter->bounce_buffer_size,
-                                                   DMA_TO_DEVICE);
-       if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
-               dev_err(dev, "Couldn't map tx bounce buffer\n");
-               goto bounce_map_failed;
+       return 0;
+}
+
+static void release_error_buffers(struct ibmvnic_adapter *adapter)
+{
+       struct device *dev = &adapter->vdev->dev;
+       struct ibmvnic_error_buff *error_buff, *tmp;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->error_list_lock, flags);
+       list_for_each_entry_safe(error_buff, tmp, &adapter->errors, list) {
+               list_del(&error_buff->list);
+               dma_unmap_single(dev, error_buff->dma, error_buff->len,
+                                DMA_FROM_DEVICE);
+               kfree(error_buff->buff);
+               kfree(error_buff);
+       }
+       spin_unlock_irqrestore(&adapter->error_list_lock, flags);
+}
+
+static int ibmvnic_login(struct net_device *netdev)
+{
+       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       unsigned long timeout = msecs_to_jiffies(30000);
+       struct device *dev = &adapter->vdev->dev;
+
+       do {
+               if (adapter->renegotiate) {
+                       adapter->renegotiate = false;
+                       release_sub_crqs(adapter);
+
+                       reinit_completion(&adapter->init_done);
+                       send_cap_queries(adapter);
+                       if (!wait_for_completion_timeout(&adapter->init_done,
+                                                        timeout)) {
+                               dev_err(dev, "Capabilities query timeout\n");
+                               return -1;
+                       }
+               }
+
+               reinit_completion(&adapter->init_done);
+               send_login(adapter);
+               if (!wait_for_completion_timeout(&adapter->init_done,
+                                                timeout)) {
+                       dev_err(dev, "Login timeout\n");
+                       return -1;
+               }
+       } while (adapter->renegotiate);
+
+       return 0;
+}
+
+static void release_resources(struct ibmvnic_adapter *adapter)
+{
+       release_tx_pools(adapter);
+       release_rx_pools(adapter);
+
+       release_stats_token(adapter);
+       release_error_buffers(adapter);
+}
+
+static int set_real_num_queues(struct net_device *netdev)
+{
+       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       int rc;
+
+       rc = netif_set_real_num_tx_queues(netdev, adapter->req_tx_queues);
+       if (rc) {
+               netdev_err(netdev, "failed to set the number of tx queues\n");
+               return rc;
+       }
+
+       rc = netif_set_real_num_rx_queues(netdev, adapter->req_rx_queues);
+       if (rc)
+               netdev_err(netdev, "failed to set the number of rx queues\n");
+
+       return rc;
+}
+
+static int ibmvnic_open(struct net_device *netdev)
+{
+       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
+       struct device *dev = &adapter->vdev->dev;
+       union ibmvnic_crq crq;
+       int rc = 0;
+       int i;
+
+       if (adapter->is_closed) {
+               rc = ibmvnic_init(adapter);
+               if (rc)
+                       return rc;
+       }
+
+       rc = ibmvnic_login(netdev);
+       if (rc)
+               return rc;
+
+       rc = set_real_num_queues(netdev);
+       if (rc)
+               return rc;
+
+       rc = init_sub_crq_irqs(adapter);
+       if (rc) {
+               dev_err(dev, "failed to initialize sub crq irqs\n");
+               return -1;
+       }
+
+       adapter->map_id = 1;
+       adapter->napi = kcalloc(adapter->req_rx_queues,
+                               sizeof(struct napi_struct), GFP_KERNEL);
+       if (!adapter->napi)
+               goto ibmvnic_open_fail;
+       for (i = 0; i < adapter->req_rx_queues; i++) {
+               netif_napi_add(netdev, &adapter->napi[i], ibmvnic_poll,
+                              NAPI_POLL_WEIGHT);
+               napi_enable(&adapter->napi[i]);
        }
+
+       send_map_query(adapter);
+
+       rc = init_rx_pools(netdev);
+       if (rc)
+               goto ibmvnic_open_fail;
+
+       rc = init_tx_pools(netdev);
+       if (rc)
+               goto ibmvnic_open_fail;
+
        replenish_pools(adapter);
 
        /* We're ready to receive frames, enable the sub-crq interrupts and
@@ -473,52 +646,42 @@ static int ibmvnic_open(struct net_device *netdev)
        ibmvnic_send_crq(adapter, &crq);
 
        netif_tx_start_all_queues(netdev);
+       adapter->is_closed = false;
 
        return 0;
 
-bounce_map_failed:
-       kfree(adapter->bounce_buffer);
-bounce_alloc_failed:
-       i = tx_subcrqs - 1;
-       kfree(adapter->tx_pool[i].free_map);
-tx_fm_alloc_failed:
-       free_long_term_buff(adapter, &adapter->tx_pool[i].long_term_buff);
-tx_ltb_alloc_failed:
-       kfree(adapter->tx_pool[i].tx_buff);
-tx_pool_alloc_failed:
-       for (j = 0; j < i; j++) {
-               kfree(adapter->tx_pool[j].tx_buff);
-               free_long_term_buff(adapter,
-                                   &adapter->tx_pool[j].long_term_buff);
-               kfree(adapter->tx_pool[j].free_map);
-       }
-       kfree(adapter->tx_pool);
-       adapter->tx_pool = NULL;
-tx_pool_arr_alloc_failed:
-       i = rxadd_subcrqs;
-rx_pool_alloc_failed:
-       for (j = 0; j < i; j++) {
-               free_rx_pool(adapter, &adapter->rx_pool[j]);
-               free_long_term_buff(adapter,
-                                   &adapter->rx_pool[j].long_term_buff);
-       }
-       kfree(adapter->rx_pool);
-       adapter->rx_pool = NULL;
-rx_pool_arr_alloc_failed:
+ibmvnic_open_fail:
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_disable(&adapter->napi[i]);
-alloc_napi_failed:
+       release_resources(adapter);
        return -ENOMEM;
 }
 
+static void disable_sub_crqs(struct ibmvnic_adapter *adapter)
+{
+       int i;
+
+       if (adapter->tx_scrq) {
+               for (i = 0; i < adapter->req_tx_queues; i++)
+                       if (adapter->tx_scrq[i])
+                               disable_irq(adapter->tx_scrq[i]->irq);
+       }
+
+       if (adapter->rx_scrq) {
+               for (i = 0; i < adapter->req_rx_queues; i++)
+                       if (adapter->rx_scrq[i])
+                               disable_irq(adapter->rx_scrq[i]->irq);
+       }
+}
+
 static int ibmvnic_close(struct net_device *netdev)
 {
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-       struct device *dev = &adapter->vdev->dev;
        union ibmvnic_crq crq;
        int i;
 
        adapter->closing = true;
+       disable_sub_crqs(adapter);
 
        for (i = 0; i < adapter->req_rx_queues; i++)
                napi_disable(&adapter->napi[i]);
@@ -526,45 +689,16 @@ static int ibmvnic_close(struct net_device *netdev)
        if (!adapter->failover)
                netif_tx_stop_all_queues(netdev);
 
-       if (adapter->bounce_buffer) {
-               if (!dma_mapping_error(dev, adapter->bounce_buffer_dma)) {
-                       dma_unmap_single(&adapter->vdev->dev,
-                                        adapter->bounce_buffer_dma,
-                                        adapter->bounce_buffer_size,
-                                        DMA_BIDIRECTIONAL);
-                       adapter->bounce_buffer_dma = DMA_ERROR_CODE;
-               }
-               kfree(adapter->bounce_buffer);
-               adapter->bounce_buffer = NULL;
-       }
-
        memset(&crq, 0, sizeof(crq));
        crq.logical_link_state.first = IBMVNIC_CRQ_CMD;
        crq.logical_link_state.cmd = LOGICAL_LINK_STATE;
        crq.logical_link_state.link_state = IBMVNIC_LOGICAL_LNK_DN;
        ibmvnic_send_crq(adapter, &crq);
 
-       for (i = 0; i < be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
-            i++) {
-               kfree(adapter->tx_pool[i].tx_buff);
-               free_long_term_buff(adapter,
-                                   &adapter->tx_pool[i].long_term_buff);
-               kfree(adapter->tx_pool[i].free_map);
-       }
-       kfree(adapter->tx_pool);
-       adapter->tx_pool = NULL;
-
-       for (i = 0; i < be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
-            i++) {
-               free_rx_pool(adapter, &adapter->rx_pool[i]);
-               free_long_term_buff(adapter,
-                                   &adapter->rx_pool[i].long_term_buff);
-       }
-       kfree(adapter->rx_pool);
-       adapter->rx_pool = NULL;
+       release_resources(adapter);
 
+       adapter->is_closed = true;
        adapter->closing = false;
-
        return 0;
 }
 
@@ -714,7 +848,6 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        unsigned int tx_bytes = 0;
        dma_addr_t data_dma_addr;
        struct netdev_queue *txq;
-       bool used_bounce = false;
        unsigned long lpar_rc;
        union sub_crq tx_crq;
        unsigned int offset;
@@ -755,7 +888,6 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
        tx_buff->index = index;
        tx_buff->pool_index = queue_num;
        tx_buff->last_frag = true;
-       tx_buff->used_bounce = used_bounce;
 
        memset(&tx_crq, 0, sizeof(tx_crq));
        tx_crq.v1.first = IBMVNIC_CRQ_CMD;
@@ -829,9 +961,8 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
                goto out;
        }
 
-       atomic_inc(&tx_scrq->used);
-
-       if (atomic_read(&tx_scrq->used) >= adapter->req_tx_entries_per_subcrq) {
+       if (atomic_inc_return(&tx_scrq->used)
+                                       >= adapter->req_tx_entries_per_subcrq) {
                netdev_info(netdev, "Stopping queue %d\n", queue_num);
                netif_stop_subqueue(netdev, queue_num);
        }
@@ -975,7 +1106,15 @@ restart_poll:
                skb = rx_buff->skb;
                skb_copy_to_linear_data(skb, rx_buff->data + offset,
                                        length);
-               skb->vlan_tci = be16_to_cpu(next->rx_comp.vlan_tci);
+
+               /* VLAN Header has been stripped by the system firmware and
+                * needs to be inserted by the driver
+                */
+               if (adapter->rx_vlan_header_insertion &&
+                   (flags & IBMVNIC_VLAN_STRIPPED))
+                       __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+                                              ntohs(next->rx_comp.vlan_tci));
+
                /* free the entry */
                next->rx_comp.first = 0;
                remove_buff_from_pool(adapter, rx_buff);
@@ -1176,6 +1315,12 @@ static void release_sub_crq_queue(struct ibmvnic_adapter *adapter,
                                        scrq->crq_num);
        } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 
+       if (rc) {
+               netdev_err(adapter->netdev,
+                          "Failed to release sub-CRQ %16lx, rc = %ld\n",
+                          scrq->crq_num, rc);
+       }
+
        dma_unmap_single(dev, scrq->msg_token, 4 * PAGE_SIZE,
                         DMA_BIDIRECTIONAL);
        free_pages((unsigned long)scrq->msgs, 2);
@@ -1189,12 +1334,12 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
        struct ibmvnic_sub_crq_queue *scrq;
        int rc;
 
-       scrq = kmalloc(sizeof(*scrq), GFP_ATOMIC);
+       scrq = kzalloc(sizeof(*scrq), GFP_ATOMIC);
        if (!scrq)
                return NULL;
 
-       scrq->msgs = (union sub_crq *)__get_free_pages(GFP_ATOMIC, 2);
-       memset(scrq->msgs, 0, 4 * PAGE_SIZE);
+       scrq->msgs =
+               (union sub_crq *)__get_free_pages(GFP_ATOMIC | __GFP_ZERO, 2);
        if (!scrq->msgs) {
                dev_warn(dev, "Couldn't allocate crq queue messages page\n");
                goto zero_page_failed;
@@ -1222,9 +1367,6 @@ static struct ibmvnic_sub_crq_queue *init_sub_crq_queue(struct ibmvnic_adapter
 
        scrq->adapter = adapter;
        scrq->size = 4 * PAGE_SIZE / sizeof(*scrq->msgs);
-       scrq->cur = 0;
-       atomic_set(&scrq->used, 0);
-       scrq->rx_skb_top = NULL;
        spin_lock_init(&scrq->lock);
 
        netdev_dbg(adapter->netdev,
@@ -1249,58 +1391,49 @@ static void release_sub_crqs(struct ibmvnic_adapter *adapter)
        int i;
 
        if (adapter->tx_scrq) {
-               for (i = 0; i < adapter->req_tx_queues; i++)
-                       if (adapter->tx_scrq[i]) {
+               for (i = 0; i < adapter->req_tx_queues; i++) {
+                       if (!adapter->tx_scrq[i])
+                               continue;
+
+                       if (adapter->tx_scrq[i]->irq) {
                                free_irq(adapter->tx_scrq[i]->irq,
                                         adapter->tx_scrq[i]);
                                irq_dispose_mapping(adapter->tx_scrq[i]->irq);
-                               release_sub_crq_queue(adapter,
-                                                     adapter->tx_scrq[i]);
+                               adapter->tx_scrq[i]->irq = 0;
                        }
+
+                       release_sub_crq_queue(adapter, adapter->tx_scrq[i]);
+               }
+
                kfree(adapter->tx_scrq);
                adapter->tx_scrq = NULL;
        }
 
        if (adapter->rx_scrq) {
-               for (i = 0; i < adapter->req_rx_queues; i++)
-                       if (adapter->rx_scrq[i]) {
+               for (i = 0; i < adapter->req_rx_queues; i++) {
+                       if (!adapter->rx_scrq[i])
+                               continue;
+
+                       if (adapter->rx_scrq[i]->irq) {
                                free_irq(adapter->rx_scrq[i]->irq,
                                         adapter->rx_scrq[i]);
                                irq_dispose_mapping(adapter->rx_scrq[i]->irq);
-                               release_sub_crq_queue(adapter,
-                                                     adapter->rx_scrq[i]);
+                               adapter->rx_scrq[i]->irq = 0;
                        }
+
+                       release_sub_crq_queue(adapter, adapter->rx_scrq[i]);
+               }
+
                kfree(adapter->rx_scrq);
                adapter->rx_scrq = NULL;
        }
 }
 
-static void release_sub_crqs_no_irqs(struct ibmvnic_adapter *adapter)
+static int disable_scrq_irq(struct ibmvnic_adapter *adapter,
+                           struct ibmvnic_sub_crq_queue *scrq)
 {
-       int i;
-
-       if (adapter->tx_scrq) {
-               for (i = 0; i < adapter->req_tx_queues; i++)
-                       if (adapter->tx_scrq[i])
-                               release_sub_crq_queue(adapter,
-                                                     adapter->tx_scrq[i]);
-               adapter->tx_scrq = NULL;
-       }
-
-       if (adapter->rx_scrq) {
-               for (i = 0; i < adapter->req_rx_queues; i++)
-                       if (adapter->rx_scrq[i])
-                               release_sub_crq_queue(adapter,
-                                                     adapter->rx_scrq[i]);
-               adapter->rx_scrq = NULL;
-       }
-}
-
-static int disable_scrq_irq(struct ibmvnic_adapter *adapter,
-                           struct ibmvnic_sub_crq_queue *scrq)
-{
-       struct device *dev = &adapter->vdev->dev;
-       unsigned long rc;
+       struct device *dev = &adapter->vdev->dev;
+       unsigned long rc;
 
        rc = plpar_hcall_norets(H_VIOCTL, adapter->vdev->unit_address,
                                H_DISABLE_VIO_INTERRUPT, scrq->hw_irq, 0, 0);
@@ -1358,7 +1491,6 @@ restart_loop:
                                        continue;
 
                                txbuff->data_dma[j] = 0;
-                               txbuff->used_bounce = false;
                        }
                        /* if sub_crq was sent indirectly */
                        first = txbuff->indir_arr[0].generic.first;
@@ -1369,9 +1501,8 @@ restart_loop:
                        }
 
                        if (txbuff->last_frag) {
-                               atomic_dec(&scrq->used);
-
-                               if (atomic_read(&scrq->used) <=
+                               if (atomic_sub_return(next->tx_comp.num_comps,
+                                                     &scrq->used) <=
                                    (adapter->req_tx_entries_per_subcrq / 2) &&
                                    netif_subqueue_stopped(adapter->netdev,
                                                           txbuff->skb)) {
@@ -1487,7 +1618,7 @@ req_tx_irq_failed:
                free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]);
                irq_dispose_mapping(adapter->rx_scrq[j]->irq);
        }
-       release_sub_crqs_no_irqs(adapter);
+       release_sub_crqs(adapter);
        return rc;
 }
 
@@ -1829,13 +1960,11 @@ static void send_login(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_login_rsp_buffer *login_rsp_buffer;
        struct ibmvnic_login_buffer *login_buffer;
-       struct ibmvnic_inflight_cmd *inflight_cmd;
        struct device *dev = &adapter->vdev->dev;
        dma_addr_t rsp_buffer_token;
        dma_addr_t buffer_token;
        size_t rsp_buffer_size;
        union ibmvnic_crq crq;
-       unsigned long flags;
        size_t buffer_size;
        __be64 *tx_list_p;
        __be64 *rx_list_p;
@@ -1872,11 +2001,7 @@ static void send_login(struct ibmvnic_adapter *adapter)
                dev_err(dev, "Couldn't map login rsp buffer\n");
                goto buf_rsp_map_failed;
        }
-       inflight_cmd = kmalloc(sizeof(*inflight_cmd), GFP_ATOMIC);
-       if (!inflight_cmd) {
-               dev_err(dev, "Couldn't allocate inflight_cmd\n");
-               goto inflight_alloc_failed;
-       }
+
        adapter->login_buf = login_buffer;
        adapter->login_buf_token = buffer_token;
        adapter->login_buf_sz = buffer_size;
@@ -1927,20 +2052,10 @@ static void send_login(struct ibmvnic_adapter *adapter)
        crq.login.cmd = LOGIN;
        crq.login.ioba = cpu_to_be32(buffer_token);
        crq.login.len = cpu_to_be32(buffer_size);
-
-       memcpy(&inflight_cmd->crq, &crq, sizeof(crq));
-
-       spin_lock_irqsave(&adapter->inflight_lock, flags);
-       list_add_tail(&inflight_cmd->list, &adapter->inflight);
-       spin_unlock_irqrestore(&adapter->inflight_lock, flags);
-
        ibmvnic_send_crq(adapter, &crq);
 
        return;
 
-inflight_alloc_failed:
-       dma_unmap_single(dev, rsp_buffer_token, rsp_buffer_size,
-                        DMA_FROM_DEVICE);
 buf_rsp_map_failed:
        kfree(login_rsp_buffer);
 buf_rsp_alloc_failed:
@@ -2064,6 +2179,10 @@ static void send_cap_queries(struct ibmvnic_adapter *adapter)
        atomic_inc(&adapter->running_cap_crqs);
        ibmvnic_send_crq(adapter, &crq);
 
+       crq.query_capability.capability = cpu_to_be16(RX_VLAN_HEADER_INSERTION);
+       atomic_inc(&adapter->running_cap_crqs);
+       ibmvnic_send_crq(adapter, &crq);
+
        crq.query_capability.capability = cpu_to_be16(MAX_TX_SG_ENTRIES);
        atomic_inc(&adapter->running_cap_crqs);
        ibmvnic_send_crq(adapter, &crq);
@@ -2242,62 +2361,10 @@ static void handle_error_info_rsp(union ibmvnic_crq *crq,
        kfree(error_buff);
 }
 
-static void handle_dump_size_rsp(union ibmvnic_crq *crq,
-                                struct ibmvnic_adapter *adapter)
-{
-       int len = be32_to_cpu(crq->request_dump_size_rsp.len);
-       struct ibmvnic_inflight_cmd *inflight_cmd;
-       struct device *dev = &adapter->vdev->dev;
-       union ibmvnic_crq newcrq;
-       unsigned long flags;
-
-       /* allocate and map buffer */
-       adapter->dump_data = kmalloc(len, GFP_KERNEL);
-       if (!adapter->dump_data) {
-               complete(&adapter->fw_done);
-               return;
-       }
-
-       adapter->dump_data_token = dma_map_single(dev, adapter->dump_data, len,
-                                                 DMA_FROM_DEVICE);
-
-       if (dma_mapping_error(dev, adapter->dump_data_token)) {
-               if (!firmware_has_feature(FW_FEATURE_CMO))
-                       dev_err(dev, "Couldn't map dump data\n");
-               kfree(adapter->dump_data);
-               complete(&adapter->fw_done);
-               return;
-       }
-
-       inflight_cmd = kmalloc(sizeof(*inflight_cmd), GFP_ATOMIC);
-       if (!inflight_cmd) {
-               dma_unmap_single(dev, adapter->dump_data_token, len,
-                                DMA_FROM_DEVICE);
-               kfree(adapter->dump_data);
-               complete(&adapter->fw_done);
-               return;
-       }
-
-       memset(&newcrq, 0, sizeof(newcrq));
-       newcrq.request_dump.first = IBMVNIC_CRQ_CMD;
-       newcrq.request_dump.cmd = REQUEST_DUMP;
-       newcrq.request_dump.ioba = cpu_to_be32(adapter->dump_data_token);
-       newcrq.request_dump.len = cpu_to_be32(adapter->dump_data_size);
-
-       memcpy(&inflight_cmd->crq, &newcrq, sizeof(newcrq));
-
-       spin_lock_irqsave(&adapter->inflight_lock, flags);
-       list_add_tail(&inflight_cmd->list, &adapter->inflight);
-       spin_unlock_irqrestore(&adapter->inflight_lock, flags);
-
-       ibmvnic_send_crq(adapter, &newcrq);
-}
-
 static void handle_error_indication(union ibmvnic_crq *crq,
                                    struct ibmvnic_adapter *adapter)
 {
        int detail_len = be32_to_cpu(crq->error_indication.detail_error_sz);
-       struct ibmvnic_inflight_cmd *inflight_cmd;
        struct device *dev = &adapter->vdev->dev;
        struct ibmvnic_error_buff *error_buff;
        union ibmvnic_crq new_crq;
@@ -2329,15 +2396,6 @@ static void handle_error_indication(union ibmvnic_crq *crq,
                return;
        }
 
-       inflight_cmd = kmalloc(sizeof(*inflight_cmd), GFP_ATOMIC);
-       if (!inflight_cmd) {
-               dma_unmap_single(dev, error_buff->dma, detail_len,
-                                DMA_FROM_DEVICE);
-               kfree(error_buff->buff);
-               kfree(error_buff);
-               return;
-       }
-
        error_buff->len = detail_len;
        error_buff->error_id = crq->error_indication.error_id;
 
@@ -2351,13 +2409,6 @@ static void handle_error_indication(union ibmvnic_crq *crq,
        new_crq.request_error_info.ioba = cpu_to_be32(error_buff->dma);
        new_crq.request_error_info.len = cpu_to_be32(detail_len);
        new_crq.request_error_info.error_id = crq->error_indication.error_id;
-
-       memcpy(&inflight_cmd->crq, &crq, sizeof(crq));
-
-       spin_lock_irqsave(&adapter->inflight_lock, flags);
-       list_add_tail(&inflight_cmd->list, &adapter->inflight);
-       spin_unlock_irqrestore(&adapter->inflight_lock, flags);
-
        ibmvnic_send_crq(adapter, &new_crq);
 }
 
@@ -2428,7 +2479,7 @@ static void handle_request_cap_rsp(union ibmvnic_crq *crq,
                         *req_value,
                         (long int)be64_to_cpu(crq->request_capability_rsp.
                                               number), name);
-               release_sub_crqs_no_irqs(adapter);
+               release_sub_crqs(adapter);
                *req_value = be64_to_cpu(crq->request_capability_rsp.number);
                init_sub_crqs(adapter, 1);
                return;
@@ -2473,7 +2524,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        struct device *dev = &adapter->vdev->dev;
        struct ibmvnic_login_rsp_buffer *login_rsp = adapter->login_rsp_buf;
        struct ibmvnic_login_buffer *login = adapter->login_buf;
-       union ibmvnic_crq crq;
        int i;
 
        dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
@@ -2508,11 +2558,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        }
        complete(&adapter->init_done);
 
-       memset(&crq, 0, sizeof(crq));
-       crq.request_ras_comp_num.first = IBMVNIC_CRQ_CMD;
-       crq.request_ras_comp_num.cmd = REQUEST_RAS_COMP_NUM;
-       ibmvnic_send_crq(adapter, &crq);
-
        return 0;
 }
 
@@ -2687,6 +2732,12 @@ static void handle_query_cap_rsp(union ibmvnic_crq *crq,
                netdev_dbg(netdev, "vlan_header_insertion = %lld\n",
                           adapter->vlan_header_insertion);
                break;
+       case RX_VLAN_HEADER_INSERTION:
+               adapter->rx_vlan_header_insertion =
+                   be64_to_cpu(crq->query_capability.number);
+               netdev_dbg(netdev, "rx_vlan_header_insertion = %lld\n",
+                          adapter->rx_vlan_header_insertion);
+               break;
        case MAX_TX_SG_ENTRIES:
                adapter->max_tx_sg_entries =
                    be64_to_cpu(crq->query_capability.number);
@@ -2748,521 +2799,6 @@ out:
        }
 }
 
-static void handle_control_ras_rsp(union ibmvnic_crq *crq,
-                                  struct ibmvnic_adapter *adapter)
-{
-       u8 correlator = crq->control_ras_rsp.correlator;
-       struct device *dev = &adapter->vdev->dev;
-       bool found = false;
-       int i;
-
-       if (crq->control_ras_rsp.rc.code) {
-               dev_warn(dev, "Control ras failed rc=%d\n",
-                        crq->control_ras_rsp.rc.code);
-               return;
-       }
-
-       for (i = 0; i < adapter->ras_comp_num; i++) {
-               if (adapter->ras_comps[i].correlator == correlator) {
-                       found = true;
-                       break;
-               }
-       }
-
-       if (!found) {
-               dev_warn(dev, "Correlator not found on control_ras_rsp\n");
-               return;
-       }
-
-       switch (crq->control_ras_rsp.op) {
-       case IBMVNIC_TRACE_LEVEL:
-               adapter->ras_comps[i].trace_level = crq->control_ras.level;
-               break;
-       case IBMVNIC_ERROR_LEVEL:
-               adapter->ras_comps[i].error_check_level =
-                   crq->control_ras.level;
-               break;
-       case IBMVNIC_TRACE_PAUSE:
-               adapter->ras_comp_int[i].paused = 1;
-               break;
-       case IBMVNIC_TRACE_RESUME:
-               adapter->ras_comp_int[i].paused = 0;
-               break;
-       case IBMVNIC_TRACE_ON:
-               adapter->ras_comps[i].trace_on = 1;
-               break;
-       case IBMVNIC_TRACE_OFF:
-               adapter->ras_comps[i].trace_on = 0;
-               break;
-       case IBMVNIC_CHG_TRACE_BUFF_SZ:
-               /* trace_buff_sz is 3 bytes, stuff it into an int */
-               ((u8 *)(&adapter->ras_comps[i].trace_buff_size))[0] = 0;
-               ((u8 *)(&adapter->ras_comps[i].trace_buff_size))[1] =
-                   crq->control_ras_rsp.trace_buff_sz[0];
-               ((u8 *)(&adapter->ras_comps[i].trace_buff_size))[2] =
-                   crq->control_ras_rsp.trace_buff_sz[1];
-               ((u8 *)(&adapter->ras_comps[i].trace_buff_size))[3] =
-                   crq->control_ras_rsp.trace_buff_sz[2];
-               break;
-       default:
-               dev_err(dev, "invalid op %d on control_ras_rsp",
-                       crq->control_ras_rsp.op);
-       }
-}
-
-static ssize_t trace_read(struct file *file, char __user *user_buf, size_t len,
-                         loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       struct device *dev = &adapter->vdev->dev;
-       struct ibmvnic_fw_trace_entry *trace;
-       int num = ras_comp_int->num;
-       union ibmvnic_crq crq;
-       dma_addr_t trace_tok;
-
-       if (*ppos >= be32_to_cpu(adapter->ras_comps[num].trace_buff_size))
-               return 0;
-
-       trace =
-           dma_alloc_coherent(dev,
-                              be32_to_cpu(adapter->ras_comps[num].
-                                          trace_buff_size), &trace_tok,
-                              GFP_KERNEL);
-       if (!trace) {
-               dev_err(dev, "Couldn't alloc trace buffer\n");
-               return 0;
-       }
-
-       memset(&crq, 0, sizeof(crq));
-       crq.collect_fw_trace.first = IBMVNIC_CRQ_CMD;
-       crq.collect_fw_trace.cmd = COLLECT_FW_TRACE;
-       crq.collect_fw_trace.correlator = adapter->ras_comps[num].correlator;
-       crq.collect_fw_trace.ioba = cpu_to_be32(trace_tok);
-       crq.collect_fw_trace.len = adapter->ras_comps[num].trace_buff_size;
-
-       init_completion(&adapter->fw_done);
-       ibmvnic_send_crq(adapter, &crq);
-       wait_for_completion(&adapter->fw_done);
-
-       if (*ppos + len > be32_to_cpu(adapter->ras_comps[num].trace_buff_size))
-               len =
-                   be32_to_cpu(adapter->ras_comps[num].trace_buff_size) -
-                   *ppos;
-
-       copy_to_user(user_buf, &((u8 *)trace)[*ppos], len);
-
-       dma_free_coherent(dev,
-                         be32_to_cpu(adapter->ras_comps[num].trace_buff_size),
-                         trace, trace_tok);
-       *ppos += len;
-       return len;
-}
-
-static const struct file_operations trace_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = trace_read,
-};
-
-static ssize_t paused_read(struct file *file, char __user *user_buf, size_t len,
-                          loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       char buff[5]; /*  1 or 0 plus \n and \0 */
-       int size;
-
-       size = sprintf(buff, "%d\n", adapter->ras_comp_int[num].paused);
-
-       if (*ppos >= size)
-               return 0;
-
-       copy_to_user(user_buf, buff, size);
-       *ppos += size;
-       return size;
-}
-
-static ssize_t paused_write(struct file *file, const char __user *user_buf,
-                           size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       union ibmvnic_crq crq;
-       unsigned long val;
-       char buff[9]; /* decimal max int plus \n and \0 */
-
-       copy_from_user(buff, user_buf, sizeof(buff));
-       val = kstrtoul(buff, 10, NULL);
-
-       adapter->ras_comp_int[num].paused = val ? 1 : 0;
-
-       memset(&crq, 0, sizeof(crq));
-       crq.control_ras.first = IBMVNIC_CRQ_CMD;
-       crq.control_ras.cmd = CONTROL_RAS;
-       crq.control_ras.correlator = adapter->ras_comps[num].correlator;
-       crq.control_ras.op = val ? IBMVNIC_TRACE_PAUSE : IBMVNIC_TRACE_RESUME;
-       ibmvnic_send_crq(adapter, &crq);
-
-       return len;
-}
-
-static const struct file_operations paused_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = paused_read,
-       .write          = paused_write,
-};
-
-static ssize_t tracing_read(struct file *file, char __user *user_buf,
-                           size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       char buff[5]; /*  1 or 0 plus \n and \0 */
-       int size;
-
-       size = sprintf(buff, "%d\n", adapter->ras_comps[num].trace_on);
-
-       if (*ppos >= size)
-               return 0;
-
-       copy_to_user(user_buf, buff, size);
-       *ppos += size;
-       return size;
-}
-
-static ssize_t tracing_write(struct file *file, const char __user *user_buf,
-                            size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       union ibmvnic_crq crq;
-       unsigned long val;
-       char buff[9]; /* decimal max int plus \n and \0 */
-
-       copy_from_user(buff, user_buf, sizeof(buff));
-       val = kstrtoul(buff, 10, NULL);
-
-       memset(&crq, 0, sizeof(crq));
-       crq.control_ras.first = IBMVNIC_CRQ_CMD;
-       crq.control_ras.cmd = CONTROL_RAS;
-       crq.control_ras.correlator = adapter->ras_comps[num].correlator;
-       crq.control_ras.op = val ? IBMVNIC_TRACE_ON : IBMVNIC_TRACE_OFF;
-
-       return len;
-}
-
-static const struct file_operations tracing_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = tracing_read,
-       .write          = tracing_write,
-};
-
-static ssize_t error_level_read(struct file *file, char __user *user_buf,
-                               size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       char buff[5]; /* decimal max char plus \n and \0 */
-       int size;
-
-       size = sprintf(buff, "%d\n", adapter->ras_comps[num].error_check_level);
-
-       if (*ppos >= size)
-               return 0;
-
-       copy_to_user(user_buf, buff, size);
-       *ppos += size;
-       return size;
-}
-
-static ssize_t error_level_write(struct file *file, const char __user *user_buf,
-                                size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       union ibmvnic_crq crq;
-       unsigned long val;
-       char buff[9]; /* decimal max int plus \n and \0 */
-
-       copy_from_user(buff, user_buf, sizeof(buff));
-       val = kstrtoul(buff, 10, NULL);
-
-       if (val > 9)
-               val = 9;
-
-       memset(&crq, 0, sizeof(crq));
-       crq.control_ras.first = IBMVNIC_CRQ_CMD;
-       crq.control_ras.cmd = CONTROL_RAS;
-       crq.control_ras.correlator = adapter->ras_comps[num].correlator;
-       crq.control_ras.op = IBMVNIC_ERROR_LEVEL;
-       crq.control_ras.level = val;
-       ibmvnic_send_crq(adapter, &crq);
-
-       return len;
-}
-
-static const struct file_operations error_level_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = error_level_read,
-       .write          = error_level_write,
-};
-
-static ssize_t trace_level_read(struct file *file, char __user *user_buf,
-                               size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       char buff[5]; /* decimal max char plus \n and \0 */
-       int size;
-
-       size = sprintf(buff, "%d\n", adapter->ras_comps[num].trace_level);
-       if (*ppos >= size)
-               return 0;
-
-       copy_to_user(user_buf, buff, size);
-       *ppos += size;
-       return size;
-}
-
-static ssize_t trace_level_write(struct file *file, const char __user *user_buf,
-                                size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       union ibmvnic_crq crq;
-       unsigned long val;
-       char buff[9]; /* decimal max int plus \n and \0 */
-
-       copy_from_user(buff, user_buf, sizeof(buff));
-       val = kstrtoul(buff, 10, NULL);
-       if (val > 9)
-               val = 9;
-
-       memset(&crq, 0, sizeof(crq));
-       crq.control_ras.first = IBMVNIC_CRQ_CMD;
-       crq.control_ras.cmd = CONTROL_RAS;
-       crq.control_ras.correlator =
-           adapter->ras_comps[ras_comp_int->num].correlator;
-       crq.control_ras.op = IBMVNIC_TRACE_LEVEL;
-       crq.control_ras.level = val;
-       ibmvnic_send_crq(adapter, &crq);
-
-       return len;
-}
-
-static const struct file_operations trace_level_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = trace_level_read,
-       .write          = trace_level_write,
-};
-
-static ssize_t trace_buff_size_read(struct file *file, char __user *user_buf,
-                                   size_t len, loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       int num = ras_comp_int->num;
-       char buff[9]; /* decimal max int plus \n and \0 */
-       int size;
-
-       size = sprintf(buff, "%d\n", adapter->ras_comps[num].trace_buff_size);
-       if (*ppos >= size)
-               return 0;
-
-       copy_to_user(user_buf, buff, size);
-       *ppos += size;
-       return size;
-}
-
-static ssize_t trace_buff_size_write(struct file *file,
-                                    const char __user *user_buf, size_t len,
-                                    loff_t *ppos)
-{
-       struct ibmvnic_fw_comp_internal *ras_comp_int = file->private_data;
-       struct ibmvnic_adapter *adapter = ras_comp_int->adapter;
-       union ibmvnic_crq crq;
-       unsigned long val;
-       char buff[9]; /* decimal max int plus \n and \0 */
-
-       copy_from_user(buff, user_buf, sizeof(buff));
-       val = kstrtoul(buff, 10, NULL);
-
-       memset(&crq, 0, sizeof(crq));
-       crq.control_ras.first = IBMVNIC_CRQ_CMD;
-       crq.control_ras.cmd = CONTROL_RAS;
-       crq.control_ras.correlator =
-           adapter->ras_comps[ras_comp_int->num].correlator;
-       crq.control_ras.op = IBMVNIC_CHG_TRACE_BUFF_SZ;
-       /* trace_buff_sz is 3 bytes, stuff an int into it */
-       crq.control_ras.trace_buff_sz[0] = ((u8 *)(&val))[5];
-       crq.control_ras.trace_buff_sz[1] = ((u8 *)(&val))[6];
-       crq.control_ras.trace_buff_sz[2] = ((u8 *)(&val))[7];
-       ibmvnic_send_crq(adapter, &crq);
-
-       return len;
-}
-
-static const struct file_operations trace_size_ops = {
-       .owner          = THIS_MODULE,
-       .open           = simple_open,
-       .read           = trace_buff_size_read,
-       .write          = trace_buff_size_write,
-};
-
-static void handle_request_ras_comps_rsp(union ibmvnic_crq *crq,
-                                        struct ibmvnic_adapter *adapter)
-{
-       struct device *dev = &adapter->vdev->dev;
-       struct dentry *dir_ent;
-       struct dentry *ent;
-       int i;
-
-       debugfs_remove_recursive(adapter->ras_comps_ent);
-
-       adapter->ras_comps_ent = debugfs_create_dir("ras_comps",
-                                                   adapter->debugfs_dir);
-       if (!adapter->ras_comps_ent || IS_ERR(adapter->ras_comps_ent)) {
-               dev_info(dev, "debugfs create ras_comps dir failed\n");
-               return;
-       }
-
-       for (i = 0; i < adapter->ras_comp_num; i++) {
-               dir_ent = debugfs_create_dir(adapter->ras_comps[i].name,
-                                            adapter->ras_comps_ent);
-               if (!dir_ent || IS_ERR(dir_ent)) {
-                       dev_info(dev, "debugfs create %s dir failed\n",
-                                adapter->ras_comps[i].name);
-                       continue;
-               }
-
-               adapter->ras_comp_int[i].adapter = adapter;
-               adapter->ras_comp_int[i].num = i;
-               adapter->ras_comp_int[i].desc_blob.data =
-                   &adapter->ras_comps[i].description;
-               adapter->ras_comp_int[i].desc_blob.size =
-                   sizeof(adapter->ras_comps[i].description);
-
-               /* Don't need to remember the dentry's because the debugfs dir
-                * gets removed recursively
-                */
-               ent = debugfs_create_blob("description", S_IRUGO, dir_ent,
-                                         &adapter->ras_comp_int[i].desc_blob);
-               ent = debugfs_create_file("trace_buf_size", S_IRUGO | S_IWUSR,
-                                         dir_ent, &adapter->ras_comp_int[i],
-                                         &trace_size_ops);
-               ent = debugfs_create_file("trace_level",
-                                         S_IRUGO |
-                                         (adapter->ras_comps[i].trace_level !=
-                                          0xFF  ? S_IWUSR : 0),
-                                          dir_ent, &adapter->ras_comp_int[i],
-                                          &trace_level_ops);
-               ent = debugfs_create_file("error_level",
-                                         S_IRUGO |
-                                         (adapter->
-                                          ras_comps[i].error_check_level !=
-                                          0xFF ? S_IWUSR : 0),
-                                         dir_ent, &adapter->ras_comp_int[i],
-                                         &trace_level_ops);
-               ent = debugfs_create_file("tracing", S_IRUGO | S_IWUSR,
-                                         dir_ent, &adapter->ras_comp_int[i],
-                                         &tracing_ops);
-               ent = debugfs_create_file("paused", S_IRUGO | S_IWUSR,
-                                         dir_ent, &adapter->ras_comp_int[i],
-                                         &paused_ops);
-               ent = debugfs_create_file("trace", S_IRUGO, dir_ent,
-                                         &adapter->ras_comp_int[i],
-                                         &trace_ops);
-       }
-}
-
-static void handle_request_ras_comp_num_rsp(union ibmvnic_crq *crq,
-                                           struct ibmvnic_adapter *adapter)
-{
-       int len = adapter->ras_comp_num * sizeof(struct ibmvnic_fw_component);
-       struct device *dev = &adapter->vdev->dev;
-       union ibmvnic_crq newcrq;
-
-       adapter->ras_comps = dma_alloc_coherent(dev, len,
-                                               &adapter->ras_comps_tok,
-                                               GFP_KERNEL);
-       if (!adapter->ras_comps) {
-               if (!firmware_has_feature(FW_FEATURE_CMO))
-                       dev_err(dev, "Couldn't alloc fw comps buffer\n");
-               return;
-       }
-
-       adapter->ras_comp_int = kmalloc(adapter->ras_comp_num *
-                                       sizeof(struct ibmvnic_fw_comp_internal),
-                                       GFP_KERNEL);
-       if (!adapter->ras_comp_int)
-               dma_free_coherent(dev, len, adapter->ras_comps,
-                                 adapter->ras_comps_tok);
-
-       memset(&newcrq, 0, sizeof(newcrq));
-       newcrq.request_ras_comps.first = IBMVNIC_CRQ_CMD;
-       newcrq.request_ras_comps.cmd = REQUEST_RAS_COMPS;
-       newcrq.request_ras_comps.ioba = cpu_to_be32(adapter->ras_comps_tok);
-       newcrq.request_ras_comps.len = cpu_to_be32(len);
-       ibmvnic_send_crq(adapter, &newcrq);
-}
-
-static void ibmvnic_free_inflight(struct ibmvnic_adapter *adapter)
-{
-       struct ibmvnic_inflight_cmd *inflight_cmd, *tmp1;
-       struct device *dev = &adapter->vdev->dev;
-       struct ibmvnic_error_buff *error_buff, *tmp2;
-       unsigned long flags;
-       unsigned long flags2;
-
-       spin_lock_irqsave(&adapter->inflight_lock, flags);
-       list_for_each_entry_safe(inflight_cmd, tmp1, &adapter->inflight, list) {
-               switch (inflight_cmd->crq.generic.cmd) {
-               case LOGIN:
-                       dma_unmap_single(dev, adapter->login_buf_token,
-                                        adapter->login_buf_sz,
-                                        DMA_BIDIRECTIONAL);
-                       dma_unmap_single(dev, adapter->login_rsp_buf_token,
-                                        adapter->login_rsp_buf_sz,
-                                        DMA_BIDIRECTIONAL);
-                       kfree(adapter->login_rsp_buf);
-                       kfree(adapter->login_buf);
-                       break;
-               case REQUEST_DUMP:
-                       complete(&adapter->fw_done);
-                       break;
-               case REQUEST_ERROR_INFO:
-                       spin_lock_irqsave(&adapter->error_list_lock, flags2);
-                       list_for_each_entry_safe(error_buff, tmp2,
-                                                &adapter->errors, list) {
-                               dma_unmap_single(dev, error_buff->dma,
-                                                error_buff->len,
-                                                DMA_FROM_DEVICE);
-                               kfree(error_buff->buff);
-                               list_del(&error_buff->list);
-                               kfree(error_buff);
-                       }
-                       spin_unlock_irqrestore(&adapter->error_list_lock,
-                                              flags2);
-                       break;
-               }
-               list_del(&inflight_cmd->list);
-               kfree(inflight_cmd);
-       }
-       spin_unlock_irqrestore(&adapter->inflight_lock, flags);
-}
-
 static void ibmvnic_xport_event(struct work_struct *work)
 {
        struct ibmvnic_adapter *adapter = container_of(work,
@@ -3271,7 +2807,6 @@ static void ibmvnic_xport_event(struct work_struct *work)
        struct device *dev = &adapter->vdev->dev;
        long rc;
 
-       ibmvnic_free_inflight(adapter);
        release_sub_crqs(adapter);
        if (adapter->migrated) {
                rc = ibmvnic_reenable_crq_queue(adapter);
@@ -3290,11 +2825,12 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
        struct ibmvnic_generic_crq *gen_crq = &crq->generic;
        struct net_device *netdev = adapter->netdev;
        struct device *dev = &adapter->vdev->dev;
+       u64 *u64_crq = (u64 *)crq;
        long rc;
 
        netdev_dbg(netdev, "Handling CRQ: %016lx %016lx\n",
-                  ((unsigned long int *)crq)[0],
-                  ((unsigned long int *)crq)[1]);
+                  (unsigned long int)cpu_to_be64(u64_crq[0]),
+                  (unsigned long int)cpu_to_be64(u64_crq[1]));
        switch (gen_crq->first) {
        case IBMVNIC_CRQ_INIT_RSP:
                switch (gen_crq->cmd) {
@@ -3401,14 +2937,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                netdev_dbg(netdev, "Got Statistics Response\n");
                complete(&adapter->stats_done);
                break;
-       case REQUEST_DUMP_SIZE_RSP:
-               netdev_dbg(netdev, "Got Request Dump Size Response\n");
-               handle_dump_size_rsp(crq, adapter);
-               break;
-       case REQUEST_DUMP_RSP:
-               netdev_dbg(netdev, "Got Request Dump Response\n");
-               complete(&adapter->fw_done);
-               break;
        case QUERY_IP_OFFLOAD_RSP:
                netdev_dbg(netdev, "Got Query IP offload Response\n");
                handle_query_ip_offload_rsp(adapter);
@@ -3421,26 +2949,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                dma_unmap_single(dev, adapter->ip_offload_ctrl_tok,
                                 sizeof(adapter->ip_offload_ctrl),
                                 DMA_TO_DEVICE);
-               /* We're done with the queries, perform the login */
-               send_login(adapter);
-               break;
-       case REQUEST_RAS_COMP_NUM_RSP:
-               netdev_dbg(netdev, "Got Request RAS Comp Num Response\n");
-               if (crq->request_ras_comp_num_rsp.rc.code == 10) {
-                       netdev_dbg(netdev, "Request RAS Comp Num not supported\n");
-                       break;
-               }
-               adapter->ras_comp_num =
-                   be32_to_cpu(crq->request_ras_comp_num_rsp.num_components);
-               handle_request_ras_comp_num_rsp(crq, adapter);
-               break;
-       case REQUEST_RAS_COMPS_RSP:
-               netdev_dbg(netdev, "Got Request RAS Comps Response\n");
-               handle_request_ras_comps_rsp(crq, adapter);
-               break;
-       case CONTROL_RAS_RSP:
-               netdev_dbg(netdev, "Got Control RAS Response\n");
-               handle_control_ras_rsp(crq, adapter);
+               complete(&adapter->init_done);
                break;
        case COLLECT_FW_TRACE_RSP:
                netdev_dbg(netdev, "Got Collect firmware trace Response\n");
@@ -3455,12 +2964,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
 static irqreturn_t ibmvnic_interrupt(int irq, void *instance)
 {
        struct ibmvnic_adapter *adapter = instance;
-       unsigned long flags;
 
-       spin_lock_irqsave(&adapter->crq.lock, flags);
-       vio_disable_interrupts(adapter->vdev);
        tasklet_schedule(&adapter->tasklet);
-       spin_unlock_irqrestore(&adapter->crq.lock, flags);
        return IRQ_HANDLED;
 }
 
@@ -3468,32 +2973,23 @@ static void ibmvnic_tasklet(void *data)
 {
        struct ibmvnic_adapter *adapter = data;
        struct ibmvnic_crq_queue *queue = &adapter->crq;
-       struct vio_dev *vdev = adapter->vdev;
        union ibmvnic_crq *crq;
        unsigned long flags;
        bool done = false;
 
        spin_lock_irqsave(&queue->lock, flags);
-       vio_disable_interrupts(vdev);
        while (!done) {
                /* Pull all the valid messages off the CRQ */
                while ((crq = ibmvnic_next_crq(adapter)) != NULL) {
                        ibmvnic_handle_crq(crq, adapter);
                        crq->generic.first = 0;
                }
-               vio_enable_interrupts(vdev);
-               crq = ibmvnic_next_crq(adapter);
-               if (crq) {
-                       vio_disable_interrupts(vdev);
-                       ibmvnic_handle_crq(crq, adapter);
-                       crq->generic.first = 0;
-               } else {
-                       /* remain in tasklet until all
-                        * capabilities responses are received
-                        */
-                       if (!adapter->wait_capability)
-                               done = true;
-               }
+
+               /* remain in tasklet until all
+                * capabilities responses are received
+                */
+               if (!adapter->wait_capability)
+                       done = true;
        }
        /* if capabilities CRQ's were sent in this tasklet, the following
         * tasklet must wait until all responses are received
@@ -3547,12 +3043,15 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter)
        return rc;
 }
 
-static void ibmvnic_release_crq_queue(struct ibmvnic_adapter *adapter)
+static void release_crq_queue(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_crq_queue *crq = &adapter->crq;
        struct vio_dev *vdev = adapter->vdev;
        long rc;
 
+       if (!crq->msgs)
+               return;
+
        netdev_dbg(adapter->netdev, "Releasing CRQ\n");
        free_irq(vdev->irq, adapter);
        tasklet_kill(&adapter->tasklet);
@@ -3563,15 +3062,19 @@ static void ibmvnic_release_crq_queue(struct ibmvnic_adapter *adapter)
        dma_unmap_single(&vdev->dev, crq->msg_token, PAGE_SIZE,
                         DMA_BIDIRECTIONAL);
        free_page((unsigned long)crq->msgs);
+       crq->msgs = NULL;
 }
 
-static int ibmvnic_init_crq_queue(struct ibmvnic_adapter *adapter)
+static int init_crq_queue(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_crq_queue *crq = &adapter->crq;
        struct device *dev = &adapter->vdev->dev;
        struct vio_dev *vdev = adapter->vdev;
        int rc, retrc = -ENOMEM;
 
+       if (crq->msgs)
+               return 0;
+
        crq->msgs = (union ibmvnic_crq *)get_zeroed_page(GFP_KERNEL);
        /* Should we allocate more than one page? */
 
@@ -3633,48 +3136,10 @@ reg_crq_failed:
        dma_unmap_single(dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
 map_failed:
        free_page((unsigned long)crq->msgs);
+       crq->msgs = NULL;
        return retrc;
 }
 
-/* debugfs for dump */
-static int ibmvnic_dump_show(struct seq_file *seq, void *v)
-{
-       struct net_device *netdev = seq->private;
-       struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-       struct device *dev = &adapter->vdev->dev;
-       union ibmvnic_crq crq;
-
-       memset(&crq, 0, sizeof(crq));
-       crq.request_dump_size.first = IBMVNIC_CRQ_CMD;
-       crq.request_dump_size.cmd = REQUEST_DUMP_SIZE;
-
-       init_completion(&adapter->fw_done);
-       ibmvnic_send_crq(adapter, &crq);
-       wait_for_completion(&adapter->fw_done);
-
-       seq_write(seq, adapter->dump_data, adapter->dump_data_size);
-
-       dma_unmap_single(dev, adapter->dump_data_token, adapter->dump_data_size,
-                        DMA_BIDIRECTIONAL);
-
-       kfree(adapter->dump_data);
-
-       return 0;
-}
-
-static int ibmvnic_dump_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ibmvnic_dump_show, inode->i_private);
-}
-
-static const struct file_operations ibmvnic_dump_ops = {
-       .owner          = THIS_MODULE,
-       .open           = ibmvnic_dump_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
 static void handle_crq_init_rsp(struct work_struct *work)
 {
        struct ibmvnic_adapter *adapter = container_of(work,
@@ -3702,26 +3167,6 @@ static void handle_crq_init_rsp(struct work_struct *work)
                goto task_failed;
        }
 
-       do {
-               if (adapter->renegotiate) {
-                       adapter->renegotiate = false;
-                       release_sub_crqs_no_irqs(adapter);
-
-                       reinit_completion(&adapter->init_done);
-                       send_cap_queries(adapter);
-                       if (!wait_for_completion_timeout(&adapter->init_done,
-                                                        timeout)) {
-                               dev_err(dev, "Passive init timeout\n");
-                               goto task_failed;
-                       }
-               }
-       } while (adapter->renegotiate);
-       rc = init_sub_crq_irqs(adapter);
-
-       if (rc)
-               goto task_failed;
-
-       netdev->real_num_tx_queues = adapter->req_tx_queues;
        netdev->mtu = adapter->req_mtu - ETH_HLEN;
 
        if (adapter->failover) {
@@ -3753,14 +3198,40 @@ task_failed:
        dev_err(dev, "Passive initialization was not successful\n");
 }
 
-static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+static int ibmvnic_init(struct ibmvnic_adapter *adapter)
 {
+       struct device *dev = &adapter->vdev->dev;
        unsigned long timeout = msecs_to_jiffies(30000);
+       int rc;
+
+       rc = init_crq_queue(adapter);
+       if (rc) {
+               dev_err(dev, "Couldn't initialize crq. rc=%d\n", rc);
+               return rc;
+       }
+
+       rc = init_stats_token(adapter);
+       if (rc) {
+               release_crq_queue(adapter);
+               return rc;
+       }
+
+       init_completion(&adapter->init_done);
+       ibmvnic_send_crq_init(adapter);
+       if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
+               dev_err(dev, "Initialization sequence timed out\n");
+               release_crq_queue(adapter);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
+{
        struct ibmvnic_adapter *adapter;
        struct net_device *netdev;
        unsigned char *mac_addr_p;
-       struct dentry *ent;
-       char buf[17]; /* debugfs name buf */
        int rc;
 
        dev_dbg(&dev->dev, "entering ibmvnic_probe for UA 0x%x\n",
@@ -3798,91 +3269,27 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        spin_lock_init(&adapter->stats_lock);
 
-       rc = ibmvnic_init_crq_queue(adapter);
-       if (rc) {
-               dev_err(&dev->dev, "Couldn't initialize crq. rc=%d\n", rc);
-               goto free_netdev;
-       }
-
        INIT_LIST_HEAD(&adapter->errors);
-       INIT_LIST_HEAD(&adapter->inflight);
        spin_lock_init(&adapter->error_list_lock);
-       spin_lock_init(&adapter->inflight_lock);
-
-       adapter->stats_token = dma_map_single(&dev->dev, &adapter->stats,
-                                             sizeof(struct ibmvnic_statistics),
-                                             DMA_FROM_DEVICE);
-       if (dma_mapping_error(&dev->dev, adapter->stats_token)) {
-               if (!firmware_has_feature(FW_FEATURE_CMO))
-                       dev_err(&dev->dev, "Couldn't map stats buffer\n");
-               rc = -ENOMEM;
-               goto free_crq;
-       }
-
-       snprintf(buf, sizeof(buf), "ibmvnic_%x", dev->unit_address);
-       ent = debugfs_create_dir(buf, NULL);
-       if (!ent || IS_ERR(ent)) {
-               dev_info(&dev->dev, "debugfs create directory failed\n");
-               adapter->debugfs_dir = NULL;
-       } else {
-               adapter->debugfs_dir = ent;
-               ent = debugfs_create_file("dump", S_IRUGO, adapter->debugfs_dir,
-                                         netdev, &ibmvnic_dump_ops);
-               if (!ent || IS_ERR(ent)) {
-                       dev_info(&dev->dev,
-                                "debugfs create dump file failed\n");
-                       adapter->debugfs_dump = NULL;
-               } else {
-                       adapter->debugfs_dump = ent;
-               }
-       }
-
-       init_completion(&adapter->init_done);
-       ibmvnic_send_crq_init(adapter);
-       if (!wait_for_completion_timeout(&adapter->init_done, timeout))
-               return 0;
-
-       do {
-               if (adapter->renegotiate) {
-                       adapter->renegotiate = false;
-                       release_sub_crqs_no_irqs(adapter);
 
-                       reinit_completion(&adapter->init_done);
-                       send_cap_queries(adapter);
-                       if (!wait_for_completion_timeout(&adapter->init_done,
-                                                        timeout))
-                               return 0;
-               }
-       } while (adapter->renegotiate);
-
-       rc = init_sub_crq_irqs(adapter);
+       rc = ibmvnic_init(adapter);
        if (rc) {
-               dev_err(&dev->dev, "failed to initialize sub crq irqs\n");
-               goto free_debugfs;
+               free_netdev(netdev);
+               return rc;
        }
 
-       netdev->real_num_tx_queues = adapter->req_tx_queues;
        netdev->mtu = adapter->req_mtu - ETH_HLEN;
+       adapter->is_closed = false;
 
        rc = register_netdev(netdev);
        if (rc) {
                dev_err(&dev->dev, "failed to register netdev rc=%d\n", rc);
-               goto free_sub_crqs;
+               free_netdev(netdev);
+               return rc;
        }
        dev_info(&dev->dev, "ibmvnic registered\n");
 
        return 0;
-
-free_sub_crqs:
-       release_sub_crqs(adapter);
-free_debugfs:
-       if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir))
-               debugfs_remove_recursive(adapter->debugfs_dir);
-free_crq:
-       ibmvnic_release_crq_queue(adapter);
-free_netdev:
-       free_netdev(netdev);
-       return rc;
 }
 
 static int ibmvnic_remove(struct vio_dev *dev)
@@ -3892,23 +3299,9 @@ static int ibmvnic_remove(struct vio_dev *dev)
 
        unregister_netdev(netdev);
 
+       release_resources(adapter);
        release_sub_crqs(adapter);
-
-       ibmvnic_release_crq_queue(adapter);
-
-       if (adapter->debugfs_dir && !IS_ERR(adapter->debugfs_dir))
-               debugfs_remove_recursive(adapter->debugfs_dir);
-
-       dma_unmap_single(&dev->dev, adapter->stats_token,
-                        sizeof(struct ibmvnic_statistics), DMA_FROM_DEVICE);
-
-       if (adapter->ras_comps)
-               dma_free_coherent(&dev->dev,
-                                 adapter->ras_comp_num *
-                                 sizeof(struct ibmvnic_fw_component),
-                                 adapter->ras_comps, adapter->ras_comps_tok);
-
-       kfree(adapter->ras_comp_int);
+       release_crq_queue(adapter);
 
        free_netdev(netdev);
        dev_set_drvdata(&dev->dev, NULL);
@@ -3933,7 +3326,6 @@ static unsigned long ibmvnic_get_desired_dma(struct vio_dev *vdev)
        adapter = netdev_priv(netdev);
 
        ret += PAGE_SIZE; /* the crq message queue */
-       ret += adapter->bounce_buffer_size;
        ret += IOMMU_PAGE_ALIGN(sizeof(struct ibmvnic_statistics), tbl);
 
        for (i = 0; i < adapter->req_tx_queues + adapter->req_rx_queues; i++)