diff options
author | Arend van Spriel <arend@broadcom.com> | 2013-04-03 06:40:38 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-04-03 15:07:05 -0400 |
commit | e2432b6787a15e0b3c255a017d16033ba30204c0 (patch) | |
tree | 120ec7a56fd856db6b7e34b17939e7c8c5990ba1 /drivers/net/wireless | |
parent | 6971280aefe437262f6d52339b0b2d5d64ab4e15 (diff) |
brcmfmac: add optional bus callback definition for tx queue cleanup
Add a callback to obtain packet queue from the bus-specific code
used to cleanup packet buffers from firmware-signalling code.
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Piotr Haber <phaber@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | 13 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 36 |
3 files changed, 56 insertions, 3 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 883ef9063e8a..080395f49fa5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -39,10 +39,12 @@ struct brcmf_bus_dcmd { | |||
39 | * @txdata: send a data frame to the dongle (callee disposes skb). | 39 | * @txdata: send a data frame to the dongle (callee disposes skb). |
40 | * @txctl: transmit a control request message to dongle. | 40 | * @txctl: transmit a control request message to dongle. |
41 | * @rxctl: receive a control response message from dongle. | 41 | * @rxctl: receive a control response message from dongle. |
42 | * @gettxq: obtain a reference of bus transmit queue (optional). | ||
42 | * | 43 | * |
43 | * This structure provides an abstract interface towards the | 44 | * This structure provides an abstract interface towards the |
44 | * bus specific driver. For control messages to common driver | 45 | * bus specific driver. For control messages to common driver |
45 | * will assure there is only one active transaction. | 46 | * will assure there is only one active transaction. Unless |
47 | * indicated otherwise these callbacks are mandatory. | ||
46 | */ | 48 | */ |
47 | struct brcmf_bus_ops { | 49 | struct brcmf_bus_ops { |
48 | int (*init)(struct device *dev); | 50 | int (*init)(struct device *dev); |
@@ -50,6 +52,7 @@ struct brcmf_bus_ops { | |||
50 | int (*txdata)(struct device *dev, struct sk_buff *skb); | 52 | int (*txdata)(struct device *dev, struct sk_buff *skb); |
51 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); | 53 | int (*txctl)(struct device *dev, unsigned char *msg, uint len); |
52 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); | 54 | int (*rxctl)(struct device *dev, unsigned char *msg, uint len); |
55 | struct pktq * (*gettxq)(struct device *dev); | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | /** | 58 | /** |
@@ -115,6 +118,14 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len) | |||
115 | return bus->ops->rxctl(bus->dev, msg, len); | 118 | return bus->ops->rxctl(bus->dev, msg, len); |
116 | } | 119 | } |
117 | 120 | ||
121 | static inline | ||
122 | struct pktq *brcmf_bus_gettxq(struct brcmf_bus *bus) | ||
123 | { | ||
124 | if (!bus->ops->gettxq) | ||
125 | return ERR_PTR(-ENOENT); | ||
126 | |||
127 | return bus->ops->gettxq(bus->dev); | ||
128 | } | ||
118 | /* | 129 | /* |
119 | * interface functions from common layer | 130 | * interface functions from common layer |
120 | */ | 131 | */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index f5f04ba65e8c..a5354e731eaa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -2293,6 +2293,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2293 | } | 2293 | } |
2294 | } | 2294 | } |
2295 | 2295 | ||
2296 | static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev) | ||
2297 | { | ||
2298 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
2299 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
2300 | struct brcmf_sdio *bus = sdiodev->bus; | ||
2301 | |||
2302 | return &bus->txq; | ||
2303 | } | ||
2304 | |||
2296 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2305 | static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) |
2297 | { | 2306 | { |
2298 | int ret = -EBADE; | 2307 | int ret = -EBADE; |
@@ -3834,6 +3843,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3834 | .txdata = brcmf_sdbrcm_bus_txdata, | 3843 | .txdata = brcmf_sdbrcm_bus_txdata, |
3835 | .txctl = brcmf_sdbrcm_bus_txctl, | 3844 | .txctl = brcmf_sdbrcm_bus_txctl, |
3836 | .rxctl = brcmf_sdbrcm_bus_rxctl, | 3845 | .rxctl = brcmf_sdbrcm_bus_rxctl, |
3846 | .gettxq = brcmf_sdbrcm_bus_gettxq, | ||
3837 | }; | 3847 | }; |
3838 | 3848 | ||
3839 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) | 3849 | void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index a6443c667e33..2afd850f22c6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
26 | #include "dhd.h" | 26 | #include "dhd.h" |
27 | #include "dhd_dbg.h" | 27 | #include "dhd_dbg.h" |
28 | #include "dhd_bus.h" | ||
28 | #include "fwil.h" | 29 | #include "fwil.h" |
29 | #include "fweh.h" | 30 | #include "fweh.h" |
30 | #include "fwsignal.h" | 31 | #include "fwsignal.h" |
@@ -236,11 +237,11 @@ struct brcmf_skbuff_cb { | |||
236 | #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 | 237 | #define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0 |
237 | 238 | ||
238 | #define brcmf_skb_htod_tag_set_field(skb, field, value) \ | 239 | #define brcmf_skb_htod_tag_set_field(skb, field, value) \ |
239 | brcmu_maskset32(&(brcmf_skbcb(skb)->htod_tag), \ | 240 | brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \ |
240 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | 241 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ |
241 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value)) | 242 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT, (value)) |
242 | #define brcmf_skb_htod_tag_get_field(skb, field) \ | 243 | #define brcmf_skb_htod_tag_get_field(skb, field) \ |
243 | brcmu_maskget32(brcmf_skbcb(skb)->htod_tag, \ | 244 | brcmu_maskget32(brcmf_skbcb(skb)->htod, \ |
244 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ | 245 | BRCMF_SKB_HTOD_TAG_ ## field ## _MASK, \ |
245 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) | 246 | BRCMF_SKB_HTOD_TAG_ ## field ## _SHIFT) |
246 | 247 | ||
@@ -548,6 +549,36 @@ static void brcmf_fws_mac_desc_cleanup(struct brcmf_fws_mac_descriptor *entry, | |||
548 | } | 549 | } |
549 | } | 550 | } |
550 | 551 | ||
552 | static void brcmf_fws_bus_txq_cleanup(struct brcmf_fws_info *fws, | ||
553 | bool (*fn)(struct sk_buff *, void *), | ||
554 | int ifidx) | ||
555 | { | ||
556 | struct brcmf_fws_hanger_item *hi; | ||
557 | struct pktq *txq; | ||
558 | struct sk_buff *skb; | ||
559 | int prec; | ||
560 | u32 hslot; | ||
561 | |||
562 | brcmf_dbg(TRACE, "enter: ifidx=%d\n", ifidx); | ||
563 | txq = brcmf_bus_gettxq(fws->drvr->bus_if); | ||
564 | if (IS_ERR(txq)) { | ||
565 | brcmf_dbg(TRACE, "no txq to clean up\n"); | ||
566 | return; | ||
567 | } | ||
568 | |||
569 | for (prec = 0; prec < txq->num_prec; prec++) { | ||
570 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
571 | while (skb) { | ||
572 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | ||
573 | hi = &fws->hanger.items[hslot]; | ||
574 | WARN_ON(skb != hi->pkt); | ||
575 | hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; | ||
576 | brcmu_pkt_buf_free_skb(skb); | ||
577 | skb = brcmu_pktq_pdeq_match(txq, prec, fn, &ifidx); | ||
578 | } | ||
579 | } | ||
580 | } | ||
581 | |||
551 | static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) | 582 | static bool brcmf_fws_ifidx_match(struct sk_buff *skb, void *arg) |
552 | { | 583 | { |
553 | u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); | 584 | u32 ifidx = brcmf_skb_if_flags_get_field(skb, INDEX); |
@@ -573,6 +604,7 @@ static void brcmf_fws_cleanup(struct brcmf_fws_info *fws, int ifidx) | |||
573 | brcmf_fws_mac_desc_cleanup(&table[i], matchfn, ifidx); | 604 | brcmf_fws_mac_desc_cleanup(&table[i], matchfn, ifidx); |
574 | 605 | ||
575 | brcmf_fws_mac_desc_cleanup(&fws->other, matchfn, ifidx); | 606 | brcmf_fws_mac_desc_cleanup(&fws->other, matchfn, ifidx); |
607 | brcmf_fws_bus_txq_cleanup(fws, matchfn, ifidx); | ||
576 | brcmf_fws_hanger_cleanup(&fws->hanger, matchfn, ifidx); | 608 | brcmf_fws_hanger_cleanup(&fws->hanger, matchfn, ifidx); |
577 | } | 609 | } |
578 | 610 | ||