forked from deepin-community/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wifi: brcmfmac: add support for vendor-specific firmware api
The driver is being used by multiple vendors who develop the firmware api independently. So far the firmware api as used by the driver has not diverged (yet). This change adds framework for supporting multiple firmware apis. The vendor-specific support code has to provide a number of callback operations. Right now it is only attach and detach callbacks so no real functionality as the api is still common. This code only adds WCC variant anyway, which is selected for all devices right now. The vendor-specific part will be built in a separate module when the driver is configured to be built as a module through Kconfig, ie. when CONFIG_BRCMFMAC=m. Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com> Reviewed-by: Franky Lin <franky.lin@broadcom.com> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20221129135446.151065-4-arend.vanspriel@broadcom.com
- Loading branch information
Arend van Spriel
authored and
Kalle Valo
committed
Dec 8, 2022
1 parent
da6d9c8
commit d6a5c56
Showing
10 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
190 changes: 190 additions & 0 deletions
190
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
// SPDX-License-Identifier: ISC | ||
/* | ||
* Copyright (c) 2022 Broadcom Corporation | ||
*/ | ||
#include <linux/errno.h> | ||
#include <linux/export.h> | ||
#include <linux/module.h> | ||
#include <linux/kmod.h> | ||
#include <linux/list.h> | ||
#include <linux/completion.h> | ||
#include <linux/mutex.h> | ||
#include <linux/printk.h> | ||
#include <linux/jiffies.h> | ||
#include <linux/workqueue.h> | ||
|
||
#include "core.h" | ||
#include "bus.h" | ||
#include "debug.h" | ||
#include "fwvid.h" | ||
|
||
#include "wcc/vops.h" | ||
|
||
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), | ||
}; | ||
|
||
#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->attach) || WARN_ON(!vops->detach)) | ||
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; | ||
} | ||
EXPORT_SYMBOL(brcmf_fwvid_register_vendor); | ||
|
||
int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod) | ||
{ | ||
struct brcmf_bus *bus, *tmp; | ||
|
||
if (fwvid >= BRCMF_FWVENDOR_NUM) | ||
return -ERANGE; | ||
|
||
if (WARN_ON(fwvid_list[fwvid].vmod != mod)) | ||
return -ENOENT; | ||
|
||
mutex_lock(&fwvid_list_lock); | ||
|
||
list_for_each_entry_safe(bus, tmp, &fwvid_list[fwvid].drvr_list, list) { | ||
mutex_unlock(&fwvid_list_lock); | ||
|
||
brcmf_dbg(INFO, "mod=%s: removing %s\n", fwvid_list[fwvid].name, | ||
dev_name(bus->dev)); | ||
brcmf_bus_remove(bus); | ||
|
||
mutex_lock(&fwvid_list_lock); | ||
} | ||
|
||
fwvid_list[fwvid].vmod = NULL; | ||
fwvid_list[fwvid].vops = NULL; | ||
reinit_completion(&fwvid_list[fwvid].reg_done); | ||
|
||
brcmf_dbg(TRACE, "mod=%s: exit\n", fwvid_list[fwvid].name); | ||
mutex_unlock(&fwvid_list_lock); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL(brcmf_fwvid_unregister_vendor); | ||
#else | ||
static inline int brcmf_fwvid_request_module(enum brcmf_fwvendor fwvid) | ||
{ | ||
return 0; | ||
} | ||
#endif | ||
|
||
int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr) | ||
{ | ||
enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid; | ||
int ret; | ||
|
||
if (fwvid >= ARRAY_SIZE(fwvid_list)) | ||
return -ERANGE; | ||
|
||
brcmf_dbg(TRACE, "mod=%s: enter: dev %s\n", fwvid_list[fwvid].name, | ||
dev_name(drvr->bus_if->dev)); | ||
|
||
mutex_lock(&fwvid_list_lock); | ||
|
||
ret = brcmf_fwvid_request_module(fwvid); | ||
if (ret) | ||
return ret; | ||
|
||
drvr->vops = fwvid_list[fwvid].vops; | ||
list_add(&drvr->bus_if->list, &fwvid_list[fwvid].drvr_list); | ||
|
||
mutex_unlock(&fwvid_list_lock); | ||
|
||
return ret; | ||
} | ||
|
||
void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr) | ||
{ | ||
enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid; | ||
|
||
if (fwvid >= ARRAY_SIZE(fwvid_list)) | ||
return; | ||
|
||
brcmf_dbg(TRACE, "mod=%s: enter: dev %s\n", fwvid_list[fwvid].name, | ||
dev_name(drvr->bus_if->dev)); | ||
|
||
mutex_lock(&fwvid_list_lock); | ||
|
||
drvr->vops = NULL; | ||
list_del(&drvr->bus_if->list); | ||
|
||
mutex_unlock(&fwvid_list_lock); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* SPDX-License-Identifier: ISC */ | ||
/* | ||
* Copyright (c) 2022 Broadcom Corporation | ||
*/ | ||
#ifndef FWVID_H_ | ||
#define FWVID_H_ | ||
|
||
#include "firmware.h" | ||
|
||
struct brcmf_pub; | ||
|
||
struct brcmf_fwvid_ops { | ||
int (*attach)(struct brcmf_pub *drvr); | ||
void (*detach)(struct brcmf_pub *drvr); | ||
}; | ||
|
||
/* exported functions */ | ||
int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *mod, | ||
const struct brcmf_fwvid_ops *ops); | ||
int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod); | ||
|
||
/* core driver functions */ | ||
int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr); | ||
void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr); | ||
|
||
static inline int brcmf_fwvid_attach(struct brcmf_pub *drvr) | ||
{ | ||
int ret; | ||
|
||
ret = brcmf_fwvid_attach_ops(drvr); | ||
if (ret) | ||
return ret; | ||
|
||
return drvr->vops->attach(drvr); | ||
} | ||
|
||
static inline void brcmf_fwvid_detach(struct brcmf_pub *drvr) | ||
{ | ||
if (!drvr->vops) | ||
return; | ||
|
||
drvr->vops->detach(drvr); | ||
brcmf_fwvid_detach_ops(drvr); | ||
} | ||
|
||
#endif /* FWVID_H_ */ |
12 changes: 12 additions & 0 deletions
12
drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# SPDX-License-Identifier: ISC | ||
# | ||
# Copyright (c) 2022 Broadcom Corporation | ||
|
||
ccflags-y += \ | ||
-I $(srctree)/$(src) \ | ||
-I $(srctree)/$(src)/.. \ | ||
-I $(srctree)/$(src)/../../include | ||
|
||
obj-m += brcmfmac-wcc.o | ||
brcmfmac-wcc-objs += \ | ||
core.o module.o |
27 changes: 27 additions & 0 deletions
27
drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// SPDX-License-Identifier: ISC | ||
/* | ||
* Copyright (c) 2022 Broadcom Corporation | ||
*/ | ||
#include <linux/errno.h> | ||
#include <linux/types.h> | ||
#include <core.h> | ||
#include <bus.h> | ||
#include <fwvid.h> | ||
|
||
#include "vops.h" | ||
|
||
static int brcmf_wcc_attach(struct brcmf_pub *drvr) | ||
{ | ||
pr_err("%s: executing\n", __func__); | ||
return 0; | ||
} | ||
|
||
static void brcmf_wcc_detach(struct brcmf_pub *drvr) | ||
{ | ||
pr_err("%s: executing\n", __func__); | ||
} | ||
|
||
const struct brcmf_fwvid_ops brcmf_wcc_ops = { | ||
.attach = brcmf_wcc_attach, | ||
.detach = brcmf_wcc_detach, | ||
}; |
26 changes: 26 additions & 0 deletions
26
drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-License-Identifier: ISC | ||
/* | ||
* Copyright (c) 2022 Broadcom Corporation | ||
*/ | ||
#include <linux/module.h> | ||
#include <bus.h> | ||
#include <core.h> | ||
#include <fwvid.h> | ||
|
||
#include "vops.h" | ||
|
||
static int __init brcmf_wcc_init(void) | ||
{ | ||
return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE, | ||
&brcmf_wcc_ops); | ||
} | ||
|
||
static void __exit brcmf_wcc_exit(void) | ||
{ | ||
brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_WCC, THIS_MODULE); | ||
} | ||
|
||
MODULE_LICENSE("Dual BSD/GPL"); | ||
|
||
module_init(brcmf_wcc_init); | ||
module_exit(brcmf_wcc_exit); |
11 changes: 11 additions & 0 deletions
11
drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/vops.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/* SPDX-License-Identifier: ISC */ | ||
/* | ||
* Copyright (c) 2022 Broadcom Corporation | ||
*/ | ||
#ifndef _BRCMFMAC_WCC_VOPS_H | ||
#define _BRCMFMAC_WCC_VOPS_H | ||
|
||
extern const struct brcmf_fwvid_ops brcmf_wcc_ops; | ||
#define WCC_VOPS (&brcmf_wcc_ops) | ||
|
||
#endif /* _BRCMFMAC_WCC_VOPS_H */ |