summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
diff options
context:
space:
mode:
authorHante Meuleman2013-06-06 13:17:53 +0200
committerJohn W. Linville2013-06-12 21:02:18 +0200
commitbe4910adf1817d357bfb20d28e0f8b6b0fecd945 (patch)
treeb10e7b0257a9b206121777d4fd9d92cc4dffedca /drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
parentbrcmfmac: On bus flow control use fw signalling or netif. (diff)
downloadkernel-qcow2-linux-be4910adf1817d357bfb20d28e0f8b6b0fecd945.tar.gz
kernel-qcow2-linux-be4910adf1817d357bfb20d28e0f8b6b0fecd945.tar.xz
kernel-qcow2-linux-be4910adf1817d357bfb20d28e0f8b6b0fecd945.zip
brcmfmac: For FW signalling it is necessary to track gen bit.
Store gen bit on suppressed packet per entry and use latest stored version for each packet which gets transmitted to fw. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@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/brcm80211/brcmfmac/fwsignal.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c92
1 files changed, 29 insertions, 63 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 73e3e1dc073a..682ac62459ea 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -246,7 +246,7 @@ struct brcmf_skbuff_cb {
#define BRCMF_SKB_HTOD_TAG_HSLOT_MASK 0x00ffff00
#define BRCMF_SKB_HTOD_TAG_HSLOT_SHIFT 8
#define BRCMF_SKB_HTOD_TAG_FREERUN_MASK 0x000000ff
-#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0
+#define BRCMF_SKB_HTOD_TAG_FREERUN_SHIFT 0
#define brcmf_skb_htod_tag_set_field(skb, field, value) \
brcmu_maskset32(&(brcmf_skbcb(skb)->htod), \
@@ -384,12 +384,10 @@ enum brcmf_fws_hanger_item_state {
* struct brcmf_fws_hanger_item - single entry for tx pending packet.
*
* @state: entry is either free or occupied.
- * @gen: generation.
* @pkt: packet itself.
*/
struct brcmf_fws_hanger_item {
enum brcmf_fws_hanger_item_state state;
- u8 gen;
struct sk_buff *pkt;
};
@@ -537,7 +535,7 @@ done:
}
static int brcmf_fws_hanger_pushpkt(struct brcmf_fws_hanger *h,
- struct sk_buff *pkt, u32 slot_id)
+ struct sk_buff *pkt, u32 slot_id)
{
if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
return -ENOENT;
@@ -571,20 +569,17 @@ static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h,
if (remove_item) {
h->items[slot_id].state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
h->items[slot_id].pkt = NULL;
- h->items[slot_id].gen = 0xff;
h->popped++;
}
return 0;
}
static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
- u32 slot_id, u8 gen)
+ u32 slot_id)
{
if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
return -ENOENT;
- h->items[slot_id].gen = gen;
-
if (h->items[slot_id].state != BRCMF_FWS_HANGER_ITEM_STATE_INUSE) {
brcmf_err("entry not in use\n");
return -EINVAL;
@@ -594,24 +589,6 @@ static int brcmf_fws_hanger_mark_suppressed(struct brcmf_fws_hanger *h,
return 0;
}
-static int brcmf_fws_hanger_get_genbit(struct brcmf_fws_hanger *hanger,
- struct sk_buff *pkt, u32 slot_id,
- int *gen)
-{
- *gen = 0xff;
-
- if (slot_id >= BRCMF_FWS_HANGER_MAXITEMS)
- return -ENOENT;
-
- if (hanger->items[slot_id].state == BRCMF_FWS_HANGER_ITEM_STATE_FREE) {
- brcmf_err("slot not in use\n");
- return -EINVAL;
- }
-
- *gen = hanger->items[slot_id].gen;
- return 0;
-}
-
static void brcmf_fws_hanger_cleanup(struct brcmf_fws_info *fws,
bool (*fn)(struct sk_buff *, void *),
int ifidx)
@@ -838,9 +815,6 @@ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq,
if (WARN_ON(!ifp))
return;
- brcmf_dbg(TRACE,
- "enter: bssidx=%d, ifidx=%d\n", ifp->bssidx, ifp->ifidx);
-
if ((ifp->netif_stop & BRCMF_NETIF_STOP_REASON_FWS_FC) &&
pq->len <= BRCMF_FWS_FLOWCONTROL_LOWATER)
brcmf_txflowblock_if(ifp,
@@ -1220,7 +1194,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
/* this packet was suppressed */
- if (!entry->suppressed || entry->generation != genbit) {
+ if (!entry->suppressed) {
entry->suppressed = true;
entry->suppress_count = brcmu_pktq_mlen(&entry->psq,
1 << (fifo * 2 + 1));
@@ -1242,8 +1216,7 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
* Mark suppressed to avoid a double free during
* wlfc cleanup
*/
- brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot,
- genbit);
+ brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
entry->suppress_count++;
}
@@ -1573,15 +1546,34 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
struct brcmf_fws_mac_descriptor *entry = skcb->mac;
int rc = 0;
- bool header_needed;
+ bool first_time;
int hslot = BRCMF_FWS_HANGER_MAXITEMS;
u8 free_ctr;
u8 ifidx;
u8 flags;
- header_needed = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
+ first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
- if (header_needed) {
+ if (!first_time) {
+ rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p);
+ if (rc) {
+ brcmf_err("hdrpull failed\n");
+ return rc;
+ }
+ }
+ brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
+ brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
+ brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
+ flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
+ if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) {
+ /*
+ * Indicate that this packet is being sent in response to an
+ * explicit request from the firmware side.
+ */
+ flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
+ }
+ brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
+ if (first_time) {
/* obtaining free slot may fail, but that will be caught
* by the hanger push. This assures the packet has a BDC
* header upon return.
@@ -1590,40 +1582,14 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
free_ctr = entry->seq[fifo];
brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
- brcmf_skb_htod_tag_set_field(p, GENERATION, 1);
entry->transit_count++;
}
- brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
- brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
- flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
- if (!(skcb->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)) {
- /*
- Indicate that this packet is being sent in response to an
- explicit request from the firmware side.
- */
- flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
- }
- brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
- if (header_needed) {
- brcmf_fws_hdrpush(fws, p);
+ brcmf_fws_hdrpush(fws, p);
+ if (first_time) {
rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
if (rc)
brcmf_err("hanger push failed: rc=%d\n", rc);
- } else {
- int gen;
-
- /* remove old header */
- rc = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, p);
- if (rc == 0) {
- hslot = brcmf_skb_htod_tag_get_field(p, HSLOT);
- brcmf_fws_hanger_get_genbit(&fws->hanger, p,
- hslot, &gen);
- brcmf_skb_htod_tag_set_field(p, GENERATION, gen);
-
- /* push new header */
- brcmf_fws_hdrpush(fws, p);
- }
}
return rc;