#define DVM_OP_MODE    0
 #define MVM_OP_MODE    1
 
+/* Protects the table contents, i.e. the ops pointer & drv list */
+static struct mutex iwlwifi_opmode_table_mtx;
 static struct iwlwifi_opmode_table {
        const char *name;                       /* name: iwldvm, iwlmvm, etc */
        const struct iwl_op_mode_ops *ops;      /* pointer to op_mode ops */
        release_firmware(ucode_raw);
        complete(&drv->request_firmware_complete);
 
+       mutex_lock(&iwlwifi_opmode_table_mtx);
        op = &iwlwifi_opmode_table[DVM_OP_MODE];
 
        /* add this device to the list of devices using this op_mode */
        } else {
                request_module_nowait("%s", op->name);
        }
+       mutex_unlock(&iwlwifi_opmode_table_mtx);
 
        return;
 
        drv->cfg = cfg;
 
        init_completion(&drv->request_firmware_complete);
+       INIT_LIST_HEAD(&drv->list);
 
        ret = iwl_request_firmware(drv, true);
 
 
        iwl_dealloc_ucode(drv);
 
+       mutex_lock(&iwlwifi_opmode_table_mtx);
+       /*
+        * List is empty (this item wasn't added)
+        * when firmware loading failed -- in that
+        * case we can't remove it from any list.
+        */
+       if (!list_empty(&drv->list))
+               list_del(&drv->list);
+       mutex_unlock(&iwlwifi_opmode_table_mtx);
+
        kfree(drv);
 }
 
        int i;
        struct iwl_drv *drv;
 
+       mutex_lock(&iwlwifi_opmode_table_mtx);
        for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
                if (strcmp(iwlwifi_opmode_table[i].name, name))
                        continue;
                list_for_each_entry(drv, &iwlwifi_opmode_table[i].drv, list)
                        drv->op_mode = ops->start(drv->trans, drv->cfg,
                                                  &drv->fw);
+               mutex_unlock(&iwlwifi_opmode_table_mtx);
                return 0;
        }
+       mutex_unlock(&iwlwifi_opmode_table_mtx);
        return -EIO;
 }
 EXPORT_SYMBOL_GPL(iwl_opmode_register);
        int i;
        struct iwl_drv *drv;
 
+       mutex_lock(&iwlwifi_opmode_table_mtx);
        for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++) {
                if (strcmp(iwlwifi_opmode_table[i].name, name))
                        continue;
                                drv->op_mode = NULL;
                        }
                }
+               mutex_unlock(&iwlwifi_opmode_table_mtx);
                return;
        }
+       mutex_unlock(&iwlwifi_opmode_table_mtx);
 }
 EXPORT_SYMBOL_GPL(iwl_opmode_deregister);
 
 {
        int i;
 
+       mutex_init(&iwlwifi_opmode_table_mtx);
+
        for (i = 0; i < ARRAY_SIZE(iwlwifi_opmode_table); i++)
                INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv);