int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
 void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);
 
+int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter);
+void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter);
+
+void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter);
 void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter);
 void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter);
 
 
        for (i = 0; i < nrds_rings; i++) {
 
                rds_ring = &recv_ctx->rds_rings[i];
+               rds_ring->producer = 0;
 
                prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
                prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc);
        for (i = 0; i < nsds_rings; i++) {
 
                sds_ring = &recv_ctx->sds_rings[i];
+               sds_ring->consumer = 0;
+               memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring));
 
                prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr);
                prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc);
        dma_addr_t      rq_phys_addr, rsp_phys_addr;
        struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
 
+       /* reset host resources */
+       tx_ring->producer = 0;
+       tx_ring->sw_consumer = 0;
+       *(tx_ring->hw_consumer) = 0;
+
        rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
        rq_addr = pci_alloc_consistent(adapter->pdev,
                rq_size, &rq_phys_addr);
                sds_ring->desc_head = (struct status_desc *)addr;
        }
 
-
-       err = qlcnic_fw_cmd_create_rx_ctx(adapter);
-       if (err)
-               goto err_out_free;
-       err = qlcnic_fw_cmd_create_tx_ctx(adapter);
-       if (err)
-               goto err_out_free;
-
-       set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
        return 0;
 
 err_out_free:
        return err;
 }
 
-void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
+
+int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
 {
-       struct qlcnic_recv_context *recv_ctx;
-       struct qlcnic_host_rds_ring *rds_ring;
-       struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_host_tx_ring *tx_ring;
-       int ring;
+       int err;
+
+       err = qlcnic_fw_cmd_create_rx_ctx(adapter);
+       if (err)
+               return err;
 
+       err = qlcnic_fw_cmd_create_tx_ctx(adapter);
+       if (err) {
+               qlcnic_fw_cmd_destroy_rx_ctx(adapter);
+               return err;
+       }
+
+       set_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
+       return 0;
+}
 
+void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
+{
        if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
                qlcnic_fw_cmd_destroy_rx_ctx(adapter);
                qlcnic_fw_cmd_destroy_tx_ctx(adapter);
                /* Allow dma queues to drain after context reset */
                msleep(20);
        }
+}
+
+void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_recv_context *recv_ctx;
+       struct qlcnic_host_rds_ring *rds_ring;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_host_tx_ring *tx_ring;
+       int ring;
 
        recv_ctx = &adapter->recv_ctx;
 
 
        for (i = 0; diag_registers[i] != -1; i++)
                regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                return;
 
        regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
        struct qlcnic_adapter *adapter = netdev_priv(dev);
        int ret;
 
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               return -EIO;
+
        ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
        if (ret) {
                dev_err(&adapter->pdev->dev,
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                return -EINVAL;
 
        /*
 
 
        i = 0;
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
                return -EIO;
 
        tx_ring = adapter->tx_ring;
        u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
        u32 mode = VPORT_MISS_MODE_DROP;
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state))
                return;
 
        qlcnic_nic_add_mac(adapter, adapter->mac_addr);
 
        }
 }
 
+void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_recv_context *recv_ctx;
+       struct qlcnic_host_rds_ring *rds_ring;
+       struct qlcnic_rx_buffer *rx_buf;
+       int i, ring;
+
+       recv_ctx = &adapter->recv_ctx;
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &recv_ctx->rds_rings[ring];
+
+               spin_lock(&rds_ring->lock);
+
+               INIT_LIST_HEAD(&rds_ring->free_list);
+
+               rx_buf = rds_ring->rx_buf_arr;
+               for (i = 0; i < rds_ring->num_desc; i++) {
+                       list_add_tail(&rx_buf->list,
+                                       &rds_ring->free_list);
+                       rx_buf++;
+               }
+
+               spin_unlock(&rds_ring->lock);
+       }
+}
+
 void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_cmd_buffer *cmd_buf;
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EINVAL;
 
-       if (netif_running(netdev)) {
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
                netif_device_detach(netdev);
                qlcnic_napi_disable(adapter);
        }
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        qlcnic_set_multi(adapter->netdev);
 
-       if (netif_running(netdev)) {
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
                netif_device_attach(netdev);
                qlcnic_napi_enable(adapter);
        }
 static int
 __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
 {
+       int ring;
+       struct qlcnic_host_rds_ring *rds_ring;
+
        if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
                return -EIO;
 
+       if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               return 0;
+
+       if (qlcnic_fw_create_ctx(adapter))
+               return -EIO;
+
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &adapter->recv_ctx.rds_rings[ring];
+               qlcnic_post_rx_buffers(adapter, ring, rds_ring);
+       }
+
        qlcnic_set_multi(netdev);
        qlcnic_fw_cmd_set_mtu(adapter, netdev->mtu);
 
 
        qlcnic_napi_disable(adapter);
 
+       qlcnic_fw_destroy_ctx(adapter);
+
+       qlcnic_reset_rx_buffers_list(adapter);
        qlcnic_release_tx_buffers(adapter);
        spin_unlock(&adapter->tx_clean_lock);
 }
 {
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
-       int err, ring;
-       struct qlcnic_host_rds_ring *rds_ring;
+       int err;
 
        if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC)
                return 0;
 
-
        err = qlcnic_napi_add(adapter, netdev);
        if (err)
                return err;
        err = qlcnic_alloc_sw_resources(adapter);
        if (err) {
                dev_err(&pdev->dev, "Error in setting sw resources\n");
-               return err;
+               goto err_out_napi_del;
        }
 
        err = qlcnic_alloc_hw_resources(adapter);
                goto err_out_free_sw;
        }
 
-
-       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-               rds_ring = &adapter->recv_ctx.rds_rings[ring];
-               qlcnic_post_rx_buffers(adapter, ring, rds_ring);
-       }
-
        err = qlcnic_request_irq(adapter);
        if (err) {
                dev_err(&pdev->dev, "failed to setup interrupt\n");
-               goto err_out_free_rxbuf;
+               goto err_out_free_hw;
        }
 
        qlcnic_init_coalesce_defaults(adapter);
        adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC;
        return 0;
 
-err_out_free_rxbuf:
-       qlcnic_release_rx_buffers(adapter);
+err_out_free_hw:
        qlcnic_free_hw_resources(adapter);
 err_out_free_sw:
        qlcnic_free_sw_resources(adapter);
+err_out_napi_del:
+       qlcnic_napi_del(adapter);
        return err;
 }
 
                }
        }
 
+       qlcnic_fw_destroy_ctx(adapter);
+
        qlcnic_detach(adapter);
 
        adapter->diag_test = 0;
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_host_rds_ring *rds_ring;
        int ring;
        int ret;
 
                return ret;
        }
 
+       ret = qlcnic_fw_create_ctx(adapter);
+       if (ret) {
+               qlcnic_detach(adapter);
+               return ret;
+       }
+
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &adapter->recv_ctx.rds_rings[ring];
+               qlcnic_post_rx_buffers(adapter, ring, rds_ring);
+       }
+
        if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx.sds_rings[ring];
        if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
                goto err_out;
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                goto err_out;
 
        if (strict_strtoul(buf, 2, &new))
        if (!adapter)
                goto done;
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                goto done;
 
        qlcnic_config_indev_addr(dev, event);
        if (!adapter)
                goto done;
 
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
                goto done;
 
        switch (event) {