drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c
Extension
.c
Size
4541 bytes
Lines
201
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct brcmf_fwvid_entry {
	const char *name;
	const struct brcmf_fwvid_ops *vops;
	struct list_head drvr_list;
#if IS_MODULE(CONFIG_BRCMFMAC)
	struct module *vmod;
	struct completion reg_done;
#endif
};

static DEFINE_MUTEX(fwvid_list_lock);

#if IS_MODULE(CONFIG_BRCMFMAC)
#define FWVID_ENTRY_INIT(_vid, _name) \
	[BRCMF_FWVENDOR_ ## _vid] = { \
		.name = #_name, \
		.reg_done = COMPLETION_INITIALIZER(fwvid_list[BRCMF_FWVENDOR_ ## _vid].reg_done), \
		.drvr_list = LIST_HEAD_INIT(fwvid_list[BRCMF_FWVENDOR_ ## _vid].drvr_list), \
	}
#else
#define FWVID_ENTRY_INIT(_vid, _name) \
	[BRCMF_FWVENDOR_ ## _vid] = { \
		.name = #_name, \
		.drvr_list = LIST_HEAD_INIT(fwvid_list[BRCMF_FWVENDOR_ ## _vid].drvr_list), \
		.vops = _vid ## _VOPS \
	}
#endif /* IS_MODULE(CONFIG_BRCMFMAC) */

static struct brcmf_fwvid_entry fwvid_list[BRCMF_FWVENDOR_NUM] = {
	FWVID_ENTRY_INIT(WCC, wcc),
	FWVID_ENTRY_INIT(CYW, cyw),
	FWVID_ENTRY_INIT(BCA, bca),
};

#if IS_MODULE(CONFIG_BRCMFMAC)
static int brcmf_fwvid_request_module(enum brcmf_fwvendor fwvid)
{
	int ret;

	if (!fwvid_list[fwvid].vmod) {
		struct completion *reg_done = &fwvid_list[fwvid].reg_done;

		mutex_unlock(&fwvid_list_lock);

		ret = request_module("brcmfmac-%s", fwvid_list[fwvid].name);
		if (ret)
			goto fail;

		ret = wait_for_completion_interruptible(reg_done);
		if (ret)
			goto fail;

		mutex_lock(&fwvid_list_lock);
	}
	return 0;

fail:
	brcmf_err("mod=%s: failed %d\n", fwvid_list[fwvid].name, ret);
	return ret;
}

int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *vmod,
				const struct brcmf_fwvid_ops *vops)
{
	if (fwvid >= BRCMF_FWVENDOR_NUM)
		return -ERANGE;

	if (WARN_ON(!vmod) || WARN_ON(!vops) ||
	    WARN_ON(!vops->alloc_fweh_info))
		return -EINVAL;

	if (WARN_ON(fwvid_list[fwvid].vmod))
		return -EEXIST;

	brcmf_dbg(TRACE, "mod=%s: enter\n", fwvid_list[fwvid].name);

	mutex_lock(&fwvid_list_lock);

	fwvid_list[fwvid].vmod = vmod;
	fwvid_list[fwvid].vops = vops;

	mutex_unlock(&fwvid_list_lock);

	complete_all(&fwvid_list[fwvid].reg_done);

	return 0;
}
BRCMF_EXPORT_SYMBOL_GPL(brcmf_fwvid_register_vendor);

int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod)

Annotation

Implementation Notes