{
        struct ib_device *dev = container_of(device, struct ib_device, dev);
 
-       ib_cache_release_one(dev);
-       kfree(dev->port_immutable);
+       WARN_ON(dev->reg_state == IB_DEV_REGISTERED);
+       if (dev->reg_state == IB_DEV_UNREGISTERED) {
+               /*
+                * In IB_DEV_UNINITIALIZED state, cache or port table
+                * is not even created. Free cache and port table only when
+                * device reaches UNREGISTERED state.
+                */
+               ib_cache_release_one(dev);
+               kfree(dev->port_immutable);
+       }
        kfree(dev);
 }
 
        ret = ib_cache_setup_one(device);
        if (ret) {
                pr_warn("Couldn't set up InfiniBand P_Key/GID cache\n");
-               goto out;
+               goto port_cleanup;
        }
 
        ret = ib_device_register_rdmacg(device);
        if (ret) {
                pr_warn("Couldn't register device with rdma cgroup\n");
-               ib_cache_cleanup_one(device);
-               goto out;
+               goto cache_cleanup;
        }
 
        memset(&device->attrs, 0, sizeof(device->attrs));
        ret = device->query_device(device, &device->attrs, &uhw);
        if (ret) {
                pr_warn("Couldn't query the device attributes\n");
-               ib_device_unregister_rdmacg(device);
-               ib_cache_cleanup_one(device);
-               goto out;
+               goto cache_cleanup;
        }
 
        ret = ib_device_register_sysfs(device, port_callback);
        if (ret) {
                pr_warn("Couldn't register device %s with driver model\n",
                        device->name);
-               ib_device_unregister_rdmacg(device);
-               ib_cache_cleanup_one(device);
-               goto out;
+               goto cache_cleanup;
        }
 
        device->reg_state = IB_DEV_REGISTERED;
        down_write(&lists_rwsem);
        list_add_tail(&device->core_list, &device_list);
        up_write(&lists_rwsem);
+       mutex_unlock(&device_mutex);
+       return 0;
+
+cache_cleanup:
+       ib_cache_cleanup_one(device);
+       ib_cache_release_one(device);
+port_cleanup:
+       kfree(device->port_immutable);
 out:
        mutex_unlock(&device_mutex);
        return ret;