brcmfmac: explicitly indicate sk_buff is sent upon request credit
authorArend van Spriel <arend@broadcom.com>
Thu, 6 Jun 2013 11:17:50 +0000 (13:17 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 12 Jun 2013 19:02:17 +0000 (15:02 -0400)
Firmware can request the driver for transmit packets using two different
signals. Only for one signal a flag was set in the sk_buff control
buffer. This patch adds explicit flag for the other signal as well.

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>
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c

index a7a02473e7e991f172ceaa5c40e5158b593efa56..d080874a14abe3b45f5704d9392eda9ad09a9a0b 100644 (file)
@@ -190,13 +190,16 @@ struct brcmf_skbuff_cb {
 /*
  * sk_buff control if flags
  *
- *     b[11]  - packet sent upon firmware request.
+ *     b[12]  - packet sent upon credit request.
+ *     b[11]  - packet sent upon packet request.
  *     b[10]  - packet only contains signalling data.
  *     b[9]   - packet is a tx packet.
  *     b[8]   - packet uses FIFO credit (non-pspoll).
  *     b[7]   - interface in AP mode.
  *     b[3:0] - interface index.
  */
+#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_MASK     0x1000
+#define BRCMF_SKB_IF_FLAGS_REQ_CREDIT_SHIFT    12
 #define BRCMF_SKB_IF_FLAGS_REQUESTED_MASK      0x0800
 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT     11
 #define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK    0x0400
@@ -998,6 +1001,37 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
        return BRCMF_FWS_RET_OK_SCHEDULE;
 }
 
+static int brcmf_fws_macdesc_use_credit(struct brcmf_fws_mac_descriptor *entry,
+                                       struct sk_buff *skb)
+{
+       int use_credit = 1;
+
+       if (entry->state == BRCMF_FWS_STATE_CLOSE) {
+               if (entry->requested_credit > 0) {
+                       /*
+                        * if the packet was pulled out while destination is in
+                        * closed state but had a non-zero packets requested,
+                        * then this should not count against the FIFO credit.
+                        * That is due to the fact that the firmware will
+                        * most likely hold onto this packet until a suitable
+                        * time later to push it to the appropriate AC FIFO.
+                        */
+                       entry->requested_credit--;
+                       brcmf_skb_if_flags_set_field(skb, REQ_CREDIT, 1);
+                       use_credit = 0;
+               } else if (entry->requested_packet > 0) {
+                       entry->requested_packet--;
+                       brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
+                       use_credit = 0;
+               }
+       } else {
+               WARN_ON(entry->requested_credit);
+               WARN_ON(entry->requested_packet);
+       }
+       brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit);
+       return use_credit;
+}
+
 static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
                                     u8 fifo, u8 credits)
 {
@@ -1047,10 +1081,11 @@ static void brcmf_fws_skb_pickup_credit(struct brcmf_fws_info *fws, int fifo,
 
        if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
                brcmf_fws_return_credits(fws, fifo, 1);
-       else if (!brcmf_skb_if_flags_get_field(p, REQUESTED))
+       else if (brcmf_skb_if_flags_get_field(p, REQ_CREDIT) &&
+                entry->state == BRCMF_FWS_STATE_CLOSE)
                /*
                 * if this packet did not count against FIFO credit, it
-                * must have taken a requested_credit from the destination
+                * could have taken a requested_credit from the destination
                 * entry (for pspoll etc.)
                 */
                entry->requested_credit++;
@@ -1108,7 +1143,6 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
        struct brcmf_fws_mac_descriptor *table;
        struct brcmf_fws_mac_descriptor *entry;
        struct sk_buff *p;
-       int use_credit = 1;
        int num_nodes;
        int node_pos;
        int prec_out;
@@ -1143,26 +1177,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
                if  (p == NULL)
                        continue;
 
-               /* did the packet come from suppress sub-queue? */
-               if (entry->requested_credit > 0) {
-                       entry->requested_credit--;
-                       /*
-                        * if the packet was pulled out while destination is in
-                        * closed state but had a non-zero packets requested,
-                        * then this should not count against the FIFO credit.
-                        * That is due to the fact that the firmware will
-                        * most likely hold onto this packet until a suitable
-                        * time later to push it to the appropriate AC FIFO.
-                        */
-                       if (entry->state == BRCMF_FWS_STATE_CLOSE)
-                               use_credit = 0;
-               } else if (entry->requested_packet > 0) {
-                       entry->requested_packet--;
-                       brcmf_skb_if_flags_set_field(p, REQUESTED, 1);
-                       if (entry->state == BRCMF_FWS_STATE_CLOSE)
-                               use_credit = 0;
-               }
-               brcmf_skb_if_flags_set_field(p, CREDITCHECK, use_credit);
+               brcmf_fws_macdesc_use_credit(entry, p);
 
                /* move dequeue position to ensure fair round-robin */
                fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
@@ -1664,13 +1679,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
                        /* decrement sequence count */
                        entry->seq[fifo]--;
                }
-               /*
-               if this packet did not count against FIFO credit, it must have
-               taken a requested_credit from the firmware (for pspoll etc.)
-               */
-               if (!(brcmf_skbcb(skb)->if_flags &
-                     BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK))
-                       entry->requested_credit++;
        } else {
                brcmf_err("no mac entry linked\n");
                rc = -ENOENT;
@@ -1679,10 +1687,12 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
 
 fail:
        if (rc) {
-               brcmf_txfinalize(fws->drvr, skb, false);
+               brcmf_fws_bustxfail(fws, skb);
                fws->stats.rollback_failed++;
-       } else
+       } else {
                fws->stats.rollback_success++;
+               brcmf_fws_skb_pickup_credit(fws, fifo, skb);
+       }
 }
 
 static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
@@ -1710,30 +1720,10 @@ static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
 {
        struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
        int *credit = &fws->fifo_credit[fifo];
-       int use_credit = 1;
 
        brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit);
 
-       if (entry->requested_credit > 0) {
-               /*
-                * if the packet was pulled out while destination is in
-                * closed state but had a non-zero packets requested,
-                * then this should not count against the FIFO credit.
-                * That is due to the fact that the firmware will
-                * most likely hold onto this packet until a suitable
-                * time later to push it to the appropriate AC FIFO.
-                */
-               entry->requested_credit--;
-               if (entry->state == BRCMF_FWS_STATE_CLOSE)
-                       use_credit = 0;
-       } else if (entry->requested_packet > 0) {
-               entry->requested_packet--;
-               brcmf_skb_if_flags_set_field(skb, REQUESTED, 1);
-               if (entry->state == BRCMF_FWS_STATE_CLOSE)
-                       use_credit = 0;
-       }
-       brcmf_skb_if_flags_set_field(skb, CREDITCHECK, use_credit);
-       if (!use_credit) {
+       if (!brcmf_fws_macdesc_use_credit(entry, skb)) {
                brcmf_dbg(TRACE, "exit: no creditcheck set\n");
                return 0;
        }
@@ -1842,9 +1832,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
                drvr->fws->fifo_delay_map |= 1 << fifo;
                brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
        } else {
-               if (brcmf_fws_commit_skb(fws, fifo, skb))
-                       if (!multicast)
-                               brcmf_fws_skb_pickup_credit(fws, fifo, skb);
+               brcmf_fws_commit_skb(fws, fifo, skb);
        }
        brcmf_fws_unlock(drvr, flags);
        return 0;
@@ -1900,7 +1888,6 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
        struct sk_buff *skb;
        ulong flags;
        int fifo;
-       int credit;
 
        fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
 
@@ -1910,35 +1897,32 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
             fifo--) {
                brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo,
                          fws->fifo_credit[fifo]);
-               for (credit = 0; credit < fws->fifo_credit[fifo]; /* nop */) {
+               while (fws->fifo_credit[fifo]) {
                        skb = brcmf_fws_deq(fws, fifo);
-                       if (!skb || brcmf_fws_commit_skb(fws, fifo, skb))
+                       if (!skb)
                                break;
                        if (brcmf_skbcb(skb)->if_flags &
                            BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
-                               credit++;
+                               fws->fifo_credit[fifo]--;
+
+                       if (brcmf_fws_commit_skb(fws, fifo, skb))
+                               break;
                        if (fws->bus_flow_blocked)
                                break;
                }
                if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
-                   (credit == fws->fifo_credit[fifo]) &&
+                   (fws->fifo_credit[fifo] == 0) &&
                    (!fws->bus_flow_blocked)) {
-                       fws->fifo_credit[fifo] -= credit;
                        while (brcmf_fws_borrow_credit(fws) == 0) {
                                skb = brcmf_fws_deq(fws, fifo);
                                if (!skb) {
                                        brcmf_fws_return_credits(fws, fifo, 1);
                                        break;
                                }
-                               if (brcmf_fws_commit_skb(fws, fifo, skb)) {
-                                       brcmf_fws_return_credits(fws, fifo, 1);
-                                       break;
-                               }
+                               brcmf_fws_commit_skb(fws, fifo, skb);
                                if (fws->bus_flow_blocked)
                                        break;
                        }
-               } else {
-                       fws->fifo_credit[fifo] -= credit;
                }
        }
        brcmf_fws_unlock(fws->drvr, flags);