brcmfmac: replace dongle command list with .preinit() callback
The bus-specific interface allowed a list of dongle commands to be provided to the common driver part. However, upcoming functionality requires a more dynamic behaviour. Hence the list is replaced by a new callback function so the bus-specific driver part can implement this behaviour. Reviewed-by: Franky Lin <frankyl@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
8dee77bab2
commit
cf4582875a
@@ -34,6 +34,7 @@ struct brcmf_bus_dcmd {
|
|||||||
/**
|
/**
|
||||||
* struct brcmf_bus_ops - bus callback operations.
|
* struct brcmf_bus_ops - bus callback operations.
|
||||||
*
|
*
|
||||||
|
* @preinit: execute bus/device specific dongle init commands (optional).
|
||||||
* @init: prepare for communication with dongle.
|
* @init: prepare for communication with dongle.
|
||||||
* @stop: clear pending frames, disable data flow.
|
* @stop: clear pending frames, disable data flow.
|
||||||
* @txdata: send a data frame to the dongle. When the data
|
* @txdata: send a data frame to the dongle. When the data
|
||||||
@@ -51,6 +52,7 @@ struct brcmf_bus_dcmd {
|
|||||||
* indicated otherwise these callbacks are mandatory.
|
* indicated otherwise these callbacks are mandatory.
|
||||||
*/
|
*/
|
||||||
struct brcmf_bus_ops {
|
struct brcmf_bus_ops {
|
||||||
|
int (*preinit)(struct device *dev);
|
||||||
int (*init)(struct device *dev);
|
int (*init)(struct device *dev);
|
||||||
void (*stop)(struct device *dev);
|
void (*stop)(struct device *dev);
|
||||||
int (*txdata)(struct device *dev, struct sk_buff *skb);
|
int (*txdata)(struct device *dev, struct sk_buff *skb);
|
||||||
@@ -85,7 +87,6 @@ struct brcmf_bus {
|
|||||||
unsigned long tx_realloc;
|
unsigned long tx_realloc;
|
||||||
u32 chip;
|
u32 chip;
|
||||||
u32 chiprev;
|
u32 chiprev;
|
||||||
struct list_head dcmd_list;
|
|
||||||
|
|
||||||
struct brcmf_bus_ops *ops;
|
struct brcmf_bus_ops *ops;
|
||||||
};
|
};
|
||||||
@@ -93,6 +94,13 @@ struct brcmf_bus {
|
|||||||
/*
|
/*
|
||||||
* callback wrappers
|
* callback wrappers
|
||||||
*/
|
*/
|
||||||
|
static inline int brcmf_bus_preinit(struct brcmf_bus *bus)
|
||||||
|
{
|
||||||
|
if (!bus->ops->preinit)
|
||||||
|
return 0;
|
||||||
|
return bus->ops->preinit(bus->dev);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int brcmf_bus_init(struct brcmf_bus *bus)
|
static inline int brcmf_bus_init(struct brcmf_bus *bus)
|
||||||
{
|
{
|
||||||
return bus->ops->init(bus->dev);
|
return bus->ops->init(bus->dev);
|
||||||
@@ -151,6 +159,8 @@ void brcmf_txflowblock(struct device *dev, bool state);
|
|||||||
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
|
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
|
||||||
|
|
||||||
int brcmf_bus_start(struct device *dev);
|
int brcmf_bus_start(struct device *dev);
|
||||||
|
s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data,
|
||||||
|
u32 len);
|
||||||
void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
|
void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
|
||||||
|
|
||||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||||
|
|||||||
@@ -257,8 +257,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||||||
u8 buf[BRCMF_DCMD_SMLEN];
|
u8 buf[BRCMF_DCMD_SMLEN];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
s32 err;
|
s32 err;
|
||||||
struct brcmf_bus_dcmd *cmdlst;
|
|
||||||
struct list_head *cur, *q;
|
|
||||||
|
|
||||||
/* retreive mac address */
|
/* retreive mac address */
|
||||||
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||||
@@ -342,17 +340,8 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
|||||||
brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
|
brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
|
||||||
0, true);
|
0, true);
|
||||||
|
|
||||||
/* set bus specific command if there is any */
|
/* do bus specific preinit here */
|
||||||
list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) {
|
err = brcmf_bus_preinit(ifp->drvr->bus_if);
|
||||||
cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
|
|
||||||
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
|
|
||||||
brcmf_fil_iovar_data_set(ifp, cmdlst->name,
|
|
||||||
cmdlst->param,
|
|
||||||
cmdlst->param_len);
|
|
||||||
}
|
|
||||||
list_del(cur);
|
|
||||||
kfree(cmdlst);
|
|
||||||
}
|
|
||||||
done:
|
done:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1048,8 +1048,6 @@ int brcmf_attach(struct device *dev)
|
|||||||
/* attach firmware event handler */
|
/* attach firmware event handler */
|
||||||
brcmf_fweh_attach(drvr);
|
brcmf_fweh_attach(drvr);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&drvr->bus_if->dcmd_list);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@@ -1206,6 +1204,14 @@ void brcmf_detach(struct device *dev)
|
|||||||
kfree(drvr);
|
kfree(drvr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)
|
||||||
|
{
|
||||||
|
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||||
|
struct brcmf_if *ifp = bus_if->drvr->iflist[0];
|
||||||
|
|
||||||
|
return brcmf_fil_iovar_data_set(ifp, name, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
|
static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
|
||||||
{
|
{
|
||||||
return atomic_read(&ifp->pend_8021x_cnt);
|
return atomic_read(&ifp->pend_8021x_cnt);
|
||||||
|
|||||||
@@ -3425,6 +3425,35 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int brcmf_sdbrcm_bus_preinit(struct device *dev)
|
||||||
|
{
|
||||||
|
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||||
|
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
|
||||||
|
struct brcmf_sdio *bus = sdiodev->bus;
|
||||||
|
u32 value;
|
||||||
|
u8 idx;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* sdio bus core specific dcmd */
|
||||||
|
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
||||||
|
if (bus->ci->c_inf[idx].rev < 12) {
|
||||||
|
/* for sdio core rev < 12, disable txgloming */
|
||||||
|
value = 0;
|
||||||
|
err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
|
||||||
|
sizeof(u32));
|
||||||
|
} else {
|
||||||
|
/* otherwise, set txglomalign */
|
||||||
|
value = 4;
|
||||||
|
if (sdiodev->pdata)
|
||||||
|
value = sdiodev->pdata->sd_sgentry_align;
|
||||||
|
/* SDIO ADMA requires at least 32 bit alignment */
|
||||||
|
value = max_t(u32, value, 4);
|
||||||
|
err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value,
|
||||||
|
sizeof(u32));
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int brcmf_sdbrcm_bus_init(struct device *dev)
|
static int brcmf_sdbrcm_bus_init(struct device *dev)
|
||||||
{
|
{
|
||||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||||
@@ -3905,6 +3934,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus)
|
|||||||
|
|
||||||
static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
|
||||||
.stop = brcmf_sdbrcm_bus_stop,
|
.stop = brcmf_sdbrcm_bus_stop,
|
||||||
|
.preinit = brcmf_sdbrcm_bus_preinit,
|
||||||
.init = brcmf_sdbrcm_bus_init,
|
.init = brcmf_sdbrcm_bus_init,
|
||||||
.txdata = brcmf_sdbrcm_bus_txdata,
|
.txdata = brcmf_sdbrcm_bus_txdata,
|
||||||
.txctl = brcmf_sdbrcm_bus_txctl,
|
.txctl = brcmf_sdbrcm_bus_txctl,
|
||||||
@@ -3916,10 +3946,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct brcmf_sdio *bus;
|
struct brcmf_sdio *bus;
|
||||||
struct brcmf_bus_dcmd *dlst;
|
|
||||||
u32 dngl_txglom;
|
|
||||||
u32 txglomalign = 0;
|
|
||||||
u8 idx;
|
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
brcmf_dbg(TRACE, "Enter\n");
|
||||||
|
|
||||||
@@ -4003,30 +4029,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)
|
|||||||
brcmf_sdio_debugfs_create(bus);
|
brcmf_sdio_debugfs_create(bus);
|
||||||
brcmf_dbg(INFO, "completed!!\n");
|
brcmf_dbg(INFO, "completed!!\n");
|
||||||
|
|
||||||
/* sdio bus core specific dcmd */
|
|
||||||
idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV);
|
|
||||||
dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL);
|
|
||||||
if (dlst) {
|
|
||||||
if (bus->ci->c_inf[idx].rev < 12) {
|
|
||||||
/* for sdio core rev < 12, disable txgloming */
|
|
||||||
dngl_txglom = 0;
|
|
||||||
dlst->name = "bus:txglom";
|
|
||||||
dlst->param = (char *)&dngl_txglom;
|
|
||||||
dlst->param_len = sizeof(u32);
|
|
||||||
} else {
|
|
||||||
/* otherwise, set txglomalign */
|
|
||||||
if (sdiodev->pdata)
|
|
||||||
txglomalign = sdiodev->pdata->sd_sgentry_align;
|
|
||||||
/* SDIO ADMA requires at least 32 bit alignment */
|
|
||||||
if (txglomalign < 4)
|
|
||||||
txglomalign = 4;
|
|
||||||
dlst->name = "bus:txglomalign";
|
|
||||||
dlst->param = (char *)&txglomalign;
|
|
||||||
dlst->param_len = sizeof(u32);
|
|
||||||
}
|
|
||||||
list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen);
|
brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen);
|
||||||
|
|
||||||
/* if firmware path present try to download and bring up bus */
|
/* if firmware path present try to download and bring up bus */
|
||||||
|
|||||||
Reference in New Issue
Block a user