Commit 289ec1c7 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville

brcmfmac: explicitly indicate sk_buff is sent upon request credit

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: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent fe353b24
...@@ -190,13 +190,16 @@ struct brcmf_skbuff_cb { ...@@ -190,13 +190,16 @@ struct brcmf_skbuff_cb {
/* /*
* sk_buff control if flags * 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[10] - packet only contains signalling data.
* b[9] - packet is a tx packet. * b[9] - packet is a tx packet.
* b[8] - packet uses FIFO credit (non-pspoll). * b[8] - packet uses FIFO credit (non-pspoll).
* b[7] - interface in AP mode. * b[7] - interface in AP mode.
* b[3:0] - interface index. * 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_MASK 0x0800
#define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11 #define BRCMF_SKB_IF_FLAGS_REQUESTED_SHIFT 11
#define BRCMF_SKB_IF_FLAGS_SIGNAL_ONLY_MASK 0x0400 #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, ...@@ -998,6 +1001,37 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
return BRCMF_FWS_RET_OK_SCHEDULE; 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, static void brcmf_fws_return_credits(struct brcmf_fws_info *fws,
u8 fifo, u8 credits) u8 fifo, u8 credits)
{ {
...@@ -1047,10 +1081,11 @@ static void brcmf_fws_skb_pickup_credit(struct brcmf_fws_info *fws, int fifo, ...@@ -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) if (brcmf_skbcb(p)->if_flags & BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK)
brcmf_fws_return_credits(fws, fifo, 1); 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 * 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 (for pspoll etc.)
*/ */
entry->requested_credit++; entry->requested_credit++;
...@@ -1108,7 +1143,6 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) ...@@ -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 *table;
struct brcmf_fws_mac_descriptor *entry; struct brcmf_fws_mac_descriptor *entry;
struct sk_buff *p; struct sk_buff *p;
int use_credit = 1;
int num_nodes; int num_nodes;
int node_pos; int node_pos;
int prec_out; int prec_out;
...@@ -1143,26 +1177,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo) ...@@ -1143,26 +1177,7 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
if (p == NULL) if (p == NULL)
continue; continue;
/* did the packet come from suppress sub-queue? */ brcmf_fws_macdesc_use_credit(entry, p);
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);
/* move dequeue position to ensure fair round-robin */ /* move dequeue position to ensure fair round-robin */
fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes; fws->deq_node_pos[fifo] = (node_pos + i + 1) % num_nodes;
...@@ -1664,13 +1679,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, ...@@ -1664,13 +1679,6 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
/* decrement sequence count */ /* decrement sequence count */
entry->seq[fifo]--; 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 { } else {
brcmf_err("no mac entry linked\n"); brcmf_err("no mac entry linked\n");
rc = -ENOENT; rc = -ENOENT;
...@@ -1679,10 +1687,12 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws, ...@@ -1679,10 +1687,12 @@ brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
fail: fail:
if (rc) { if (rc) {
brcmf_txfinalize(fws->drvr, skb, false); brcmf_fws_bustxfail(fws, skb);
fws->stats.rollback_failed++; fws->stats.rollback_failed++;
} else } else {
fws->stats.rollback_success++; fws->stats.rollback_success++;
brcmf_fws_skb_pickup_credit(fws, fifo, skb);
}
} }
static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws) 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, ...@@ -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; struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
int *credit = &fws->fifo_credit[fifo]; int *credit = &fws->fifo_credit[fifo];
int use_credit = 1;
brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit); brcmf_dbg(TRACE, "enter: ac=%d, credits=%d\n", fifo, *credit);
if (entry->requested_credit > 0) { if (!brcmf_fws_macdesc_use_credit(entry, skb)) {
/*
* 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) {
brcmf_dbg(TRACE, "exit: no creditcheck set\n"); brcmf_dbg(TRACE, "exit: no creditcheck set\n");
return 0; return 0;
} }
...@@ -1842,9 +1832,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) ...@@ -1842,9 +1832,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
drvr->fws->fifo_delay_map |= 1 << fifo; drvr->fws->fifo_delay_map |= 1 << fifo;
brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb); brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
} else { } else {
if (brcmf_fws_commit_skb(fws, fifo, skb)) brcmf_fws_commit_skb(fws, fifo, skb);
if (!multicast)
brcmf_fws_skb_pickup_credit(fws, fifo, skb);
} }
brcmf_fws_unlock(drvr, flags); brcmf_fws_unlock(drvr, flags);
return 0; return 0;
...@@ -1900,7 +1888,6 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) ...@@ -1900,7 +1888,6 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
struct sk_buff *skb; struct sk_buff *skb;
ulong flags; ulong flags;
int fifo; int fifo;
int credit;
fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work); 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) ...@@ -1910,35 +1897,32 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
fifo--) { fifo--) {
brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo, brcmf_dbg(TRACE, "fifo %d credit %d\n", fifo,
fws->fifo_credit[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); skb = brcmf_fws_deq(fws, fifo);
if (!skb || brcmf_fws_commit_skb(fws, fifo, skb)) if (!skb)
break; break;
if (brcmf_skbcb(skb)->if_flags & if (brcmf_skbcb(skb)->if_flags &
BRCMF_SKB_IF_FLAGS_CREDITCHECK_MASK) 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) if (fws->bus_flow_blocked)
break; break;
} }
if ((fifo == BRCMF_FWS_FIFO_AC_BE) && if ((fifo == BRCMF_FWS_FIFO_AC_BE) &&
(credit == fws->fifo_credit[fifo]) && (fws->fifo_credit[fifo] == 0) &&
(!fws->bus_flow_blocked)) { (!fws->bus_flow_blocked)) {
fws->fifo_credit[fifo] -= credit;
while (brcmf_fws_borrow_credit(fws) == 0) { while (brcmf_fws_borrow_credit(fws) == 0) {
skb = brcmf_fws_deq(fws, fifo); skb = brcmf_fws_deq(fws, fifo);
if (!skb) { if (!skb) {
brcmf_fws_return_credits(fws, fifo, 1); brcmf_fws_return_credits(fws, fifo, 1);
break; break;
} }
if (brcmf_fws_commit_skb(fws, fifo, skb)) { brcmf_fws_commit_skb(fws, fifo, skb);
brcmf_fws_return_credits(fws, fifo, 1);
break;
}
if (fws->bus_flow_blocked) if (fws->bus_flow_blocked)
break; break;
} }
} else {
fws->fifo_credit[fifo] -= credit;
} }
} }
brcmf_fws_unlock(fws->drvr, flags); brcmf_fws_unlock(fws->drvr, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment