diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-11-29 05:48:15 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-12-02 14:25:17 -0500 |
commit | cf4582875a77c13adf8fec79b8ab3896d2b38e97 (patch) | |
tree | 5b56d455abcc3043325897a17a4c6684dc8a3b04 | |
parent | 8dee77bab2eda24b48bfb8aecf5ac1370e424416 (diff) |
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>
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 58 |
4 files changed, 51 insertions, 44 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index a129d21498ff..6a54905528be 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -34,6 +34,7 @@ struct brcmf_bus_dcmd { | |||
34 | /** | 34 | /** |
35 | * struct brcmf_bus_ops - bus callback operations. | 35 | * struct brcmf_bus_ops - bus callback operations. |
36 | * | 36 | * |
37 | * @preinit: execute bus/device specific dongle init commands (optional). | ||
37 | * @init: prepare for communication with dongle. | 38 | * @init: prepare for communication with dongle. |
38 | * @stop: clear pending frames, disable data flow. | 39 | * @stop: clear pending frames, disable data flow. |
39 | * @txdata: send a data frame to the dongle. When the data | 40 | * @txdata: send a data frame to the dongle. When the data |
@@ -51,6 +52,7 @@ struct brcmf_bus_dcmd { | |||
51 | * indicated otherwise these callbacks are mandatory. | 52 | * indicated otherwise these callbacks are mandatory. |
52 | */ | 53 | */ |
53 | struct brcmf_bus_ops { | 54 | struct brcmf_bus_ops { |
55 | int (*preinit)(struct device *dev); | ||
54 | int (*init)(struct device *dev); | 56 | int (*init)(struct device *dev); |
55 | void (*stop)(struct device *dev); | 57 | void (*stop)(struct device *dev); |
56 | int (*txdata)(struct device *dev, struct sk_buff *skb); | 58 | int (*txdata)(struct device *dev, struct sk_buff *skb); |
@@ -85,7 +87,6 @@ struct brcmf_bus { | |||
85 | unsigned long tx_realloc; | 87 | unsigned long tx_realloc; |
86 | u32 chip; | 88 | u32 chip; |
87 | u32 chiprev; | 89 | u32 chiprev; |
88 | struct list_head dcmd_list; | ||
89 | 90 | ||
90 | struct brcmf_bus_ops *ops; | 91 | struct brcmf_bus_ops *ops; |
91 | }; | 92 | }; |
@@ -93,6 +94,13 @@ struct brcmf_bus { | |||
93 | /* | 94 | /* |
94 | * callback wrappers | 95 | * callback wrappers |
95 | */ | 96 | */ |
97 | static inline int brcmf_bus_preinit(struct brcmf_bus *bus) | ||
98 | { | ||
99 | if (!bus->ops->preinit) | ||
100 | return 0; | ||
101 | return bus->ops->preinit(bus->dev); | ||
102 | } | ||
103 | |||
96 | static inline int brcmf_bus_init(struct brcmf_bus *bus) | 104 | static inline int brcmf_bus_init(struct brcmf_bus *bus) |
97 | { | 105 | { |
98 | return bus->ops->init(bus->dev); | 106 | return bus->ops->init(bus->dev); |
@@ -151,6 +159,8 @@ void brcmf_txflowblock(struct device *dev, bool state); | |||
151 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); | 159 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
152 | 160 | ||
153 | int brcmf_bus_start(struct device *dev); | 161 | int brcmf_bus_start(struct device *dev); |
162 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, | ||
163 | u32 len); | ||
154 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); | 164 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); |
155 | 165 | ||
156 | #ifdef CONFIG_BRCMFMAC_SDIO | 166 | #ifdef CONFIG_BRCMFMAC_SDIO |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 9431af2465f3..5c0c9191b794 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -257,8 +257,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |||
257 | u8 buf[BRCMF_DCMD_SMLEN]; | 257 | u8 buf[BRCMF_DCMD_SMLEN]; |
258 | char *ptr; | 258 | char *ptr; |
259 | s32 err; | 259 | s32 err; |
260 | struct brcmf_bus_dcmd *cmdlst; | ||
261 | struct list_head *cur, *q; | ||
262 | 260 | ||
263 | /* retreive mac address */ | 261 | /* retreive mac address */ |
264 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | 262 | 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) | |||
342 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | 340 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, |
343 | 0, true); | 341 | 0, true); |
344 | 342 | ||
345 | /* set bus specific command if there is any */ | 343 | /* do bus specific preinit here */ |
346 | list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) { | 344 | err = brcmf_bus_preinit(ifp->drvr->bus_if); |
347 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); | ||
348 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { | ||
349 | brcmf_fil_iovar_data_set(ifp, cmdlst->name, | ||
350 | cmdlst->param, | ||
351 | cmdlst->param_len); | ||
352 | } | ||
353 | list_del(cur); | ||
354 | kfree(cmdlst); | ||
355 | } | ||
356 | done: | 345 | done: |
357 | return err; | 346 | return err; |
358 | } | 347 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 0c4c2306647d..ab207e22e515 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -1048,8 +1048,6 @@ int brcmf_attach(struct device *dev) | |||
1048 | /* attach firmware event handler */ | 1048 | /* attach firmware event handler */ |
1049 | brcmf_fweh_attach(drvr); | 1049 | brcmf_fweh_attach(drvr); |
1050 | 1050 | ||
1051 | INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); | ||
1052 | |||
1053 | return ret; | 1051 | return ret; |
1054 | 1052 | ||
1055 | fail: | 1053 | fail: |
@@ -1206,6 +1204,14 @@ void brcmf_detach(struct device *dev) | |||
1206 | kfree(drvr); | 1204 | kfree(drvr); |
1207 | } | 1205 | } |
1208 | 1206 | ||
1207 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len) | ||
1208 | { | ||
1209 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1210 | struct brcmf_if *ifp = bus_if->drvr->iflist[0]; | ||
1211 | |||
1212 | return brcmf_fil_iovar_data_set(ifp, name, data, len); | ||
1213 | } | ||
1214 | |||
1209 | static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) | 1215 | static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) |
1210 | { | 1216 | { |
1211 | return atomic_read(&ifp->pend_8021x_cnt); | 1217 | return atomic_read(&ifp->pend_8021x_cnt); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 928983be800b..2597a534e694 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -3425,6 +3425,35 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) | |||
3425 | return ret; | 3425 | return ret; |
3426 | } | 3426 | } |
3427 | 3427 | ||
3428 | static int brcmf_sdbrcm_bus_preinit(struct device *dev) | ||
3429 | { | ||
3430 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
3431 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
3432 | struct brcmf_sdio *bus = sdiodev->bus; | ||
3433 | u32 value; | ||
3434 | u8 idx; | ||
3435 | int err; | ||
3436 | |||
3437 | /* sdio bus core specific dcmd */ | ||
3438 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
3439 | if (bus->ci->c_inf[idx].rev < 12) { | ||
3440 | /* for sdio core rev < 12, disable txgloming */ | ||
3441 | value = 0; | ||
3442 | err = brcmf_iovar_data_set(dev, "bus:txglom", &value, | ||
3443 | sizeof(u32)); | ||
3444 | } else { | ||
3445 | /* otherwise, set txglomalign */ | ||
3446 | value = 4; | ||
3447 | if (sdiodev->pdata) | ||
3448 | value = sdiodev->pdata->sd_sgentry_align; | ||
3449 | /* SDIO ADMA requires at least 32 bit alignment */ | ||
3450 | value = max_t(u32, value, 4); | ||
3451 | err = brcmf_iovar_data_set(dev, "bus:txglomalign", &value, | ||
3452 | sizeof(u32)); | ||
3453 | } | ||
3454 | return err; | ||
3455 | } | ||
3456 | |||
3428 | static int brcmf_sdbrcm_bus_init(struct device *dev) | 3457 | static int brcmf_sdbrcm_bus_init(struct device *dev) |
3429 | { | 3458 | { |
3430 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 3459 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
@@ -3905,6 +3934,7 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) | |||
3905 | 3934 | ||
3906 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | 3935 | static struct brcmf_bus_ops brcmf_sdio_bus_ops = { |
3907 | .stop = brcmf_sdbrcm_bus_stop, | 3936 | .stop = brcmf_sdbrcm_bus_stop, |
3937 | .preinit = brcmf_sdbrcm_bus_preinit, | ||
3908 | .init = brcmf_sdbrcm_bus_init, | 3938 | .init = brcmf_sdbrcm_bus_init, |
3909 | .txdata = brcmf_sdbrcm_bus_txdata, | 3939 | .txdata = brcmf_sdbrcm_bus_txdata, |
3910 | .txctl = brcmf_sdbrcm_bus_txctl, | 3940 | .txctl = brcmf_sdbrcm_bus_txctl, |
@@ -3916,10 +3946,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
3916 | { | 3946 | { |
3917 | int ret; | 3947 | int ret; |
3918 | struct brcmf_sdio *bus; | 3948 | struct brcmf_sdio *bus; |
3919 | struct brcmf_bus_dcmd *dlst; | ||
3920 | u32 dngl_txglom; | ||
3921 | u32 txglomalign = 0; | ||
3922 | u8 idx; | ||
3923 | 3949 | ||
3924 | brcmf_dbg(TRACE, "Enter\n"); | 3950 | brcmf_dbg(TRACE, "Enter\n"); |
3925 | 3951 | ||
@@ -4003,30 +4029,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | |||
4003 | brcmf_sdio_debugfs_create(bus); | 4029 | brcmf_sdio_debugfs_create(bus); |
4004 | brcmf_dbg(INFO, "completed!!\n"); | 4030 | brcmf_dbg(INFO, "completed!!\n"); |
4005 | 4031 | ||
4006 | /* sdio bus core specific dcmd */ | ||
4007 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | ||
4008 | dlst = kzalloc(sizeof(struct brcmf_bus_dcmd), GFP_KERNEL); | ||
4009 | if (dlst) { | ||
4010 | if (bus->ci->c_inf[idx].rev < 12) { | ||
4011 | /* for sdio core rev < 12, disable txgloming */ | ||
4012 | dngl_txglom = 0; | ||
4013 | dlst->name = "bus:txglom"; | ||
4014 | dlst->param = (char *)&dngl_txglom; | ||
4015 | dlst->param_len = sizeof(u32); | ||
4016 | } else { | ||
4017 | /* otherwise, set txglomalign */ | ||
4018 | if (sdiodev->pdata) | ||
4019 | txglomalign = sdiodev->pdata->sd_sgentry_align; | ||
4020 | /* SDIO ADMA requires at least 32 bit alignment */ | ||
4021 | if (txglomalign < 4) | ||
4022 | txglomalign = 4; | ||
4023 | dlst->name = "bus:txglomalign"; | ||
4024 | dlst->param = (char *)&txglomalign; | ||
4025 | dlst->param_len = sizeof(u32); | ||
4026 | } | ||
4027 | list_add(&dlst->list, &bus->sdiodev->bus_if->dcmd_list); | ||
4028 | } | ||
4029 | |||
4030 | brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); | 4032 | brcmf_bus_add_txhdrlen(bus->sdiodev->dev, bus->tx_hdrlen); |
4031 | 4033 | ||
4032 | /* if firmware path present try to download and bring up bus */ | 4034 | /* if firmware path present try to download and bring up bus */ |