Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+53 −69
Original line number Diff line number Diff line
@@ -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);