#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);