struct ibmvnic_adapter *adapter = netdev_priv(netdev);
        int rc;
 
-       /* If device failover is pending, just set device state and return.
-        * Device operation will be handled by reset routine.
+       ASSERT_RTNL();
+
+       /* If device failover is pending or we are about to reset, just set
+        * device state and return. Device operation will be handled by reset
+        * routine.
+        *
+        * It should be safe to overwrite the adapter->state here. Since
+        * we hold the rtnl, either the reset has not actually started or
+        * the rtnl got dropped during the set_link_state() in do_reset().
+        * In the former case, no one else is changing the state (again we
+        * have the rtnl) and in the latter case, do_reset() will detect and
+        * honor our setting below.
         */
-       if (adapter->failover_pending) {
+       if (adapter->failover_pending || (test_bit(0, &adapter->resetting))) {
+               netdev_dbg(netdev, "[S:%d FOP:%d] Resetting, deferring open\n",
+                          adapter->state, adapter->failover_pending);
                adapter->state = VNIC_OPEN;
-               return 0;
+               rc = 0;
+               goto out;
        }
 
        if (adapter->state != VNIC_CLOSED) {
        rc = __ibmvnic_open(netdev);
 
 out:
-       /* If open fails due to a pending failover, set device state and
-        * return. Device operation will be handled by reset routine.
+       /* If open failed and there is a pending failover or in-progress reset,
+        * set device state and return. Device operation will be handled by
+        * reset routine. See also comments above regarding rtnl.
         */
-       if (rc && adapter->failover_pending) {
+       if (rc &&
+           (adapter->failover_pending || (test_bit(0, &adapter->resetting)))) {
                adapter->state = VNIC_OPEN;
                rc = 0;
        }
        if (rwi->reset_reason == VNIC_RESET_FAILOVER)
                adapter->failover_pending = false;
 
+       /* read the state and check (again) after getting rtnl */
+       reset_state = adapter->state;
+
+       if (reset_state == VNIC_REMOVING || reset_state == VNIC_REMOVED) {
+               rc = -EBUSY;
+               goto out;
+       }
+
        netif_carrier_off(netdev);
 
        old_num_rx_queues = adapter->req_rx_queues;
                        if (rc)
                                goto out;
 
+                       if (adapter->state == VNIC_OPEN) {
+                               /* When we dropped rtnl, ibmvnic_open() got
+                                * it and noticed that we are resetting and
+                                * set the adapter state to OPEN. Update our
+                                * new "target" state, and resume the reset
+                                * from VNIC_CLOSING state.
+                                */
+                               netdev_dbg(netdev,
+                                          "Open changed state from %d, updating.\n",
+                                          reset_state);
+                               reset_state = VNIC_OPEN;
+                               adapter->state = VNIC_CLOSING;
+                       }
+
                        if (adapter->state != VNIC_CLOSING) {
+                               /* If someone else changed the adapter state
+                                * when we dropped the rtnl, fail the reset
+                                */
                                rc = -1;
                                goto out;
                        }
-
                        adapter->state = VNIC_CLOSED;
                }
        }
        netdev_dbg(adapter->netdev, "Hard resetting driver (%d)\n",
                   rwi->reset_reason);
 
+       /* read the state and check (again) after getting rtnl */
+       reset_state = adapter->state;
+
+       if (reset_state == VNIC_REMOVING || reset_state == VNIC_REMOVED) {
+               rc = -EBUSY;
+               goto out;
+       }
+
        netif_carrier_off(netdev);
        adapter->reset_reason = rwi->reset_reason;