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

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

brcm80211: fmac: cleanup receive path using proper skb_queue functions



In the receive path there was still code using the next pointer to
access all packets in skb_queue. This patch fixes that.

Reported-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarAlwin Beukers <alwin@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarFranky Lin <frankyl@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e7979ac7
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -699,7 +699,16 @@ extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,

/* Receive frame for delivery to OS.  Callee disposes of rxp. */
extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
			 struct sk_buff *rxp, int numpkt);
			   struct sk_buff_head *rxlist);
static inline void brcmf_rx_packet(struct brcmf_pub *drvr, int ifidx,
				   struct sk_buff *pkt)
{
	struct sk_buff_head q;

	skb_queue_head_init(&q);
	skb_queue_tail(&q, pkt);
	brcmf_rx_frame(drvr, ifidx, &q);
}

/* Return pointer to interface name */
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
+5 −10
Original line number Diff line number Diff line
@@ -397,26 +397,21 @@ static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
	return bcmerror;
}

void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
		  int numpkt)
void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
		    struct sk_buff_head *skb_list)
{
	struct brcmf_info *drvr_priv = drvr->info;
	unsigned char *eth;
	uint len;
	void *data;
	struct sk_buff *pnext, *save_pktbuf;
	int i;
	struct sk_buff *skb, *pnext;
	struct brcmf_if *ifp;
	struct brcmf_event_msg event;

	brcmf_dbg(TRACE, "Enter\n");

	save_pktbuf = skb;

	for (i = 0; skb && i < numpkt; i++, skb = pnext) {

		pnext = skb->next;
		skb->next = NULL;
	skb_queue_walk_safe(skb_list, skb, pnext) {
		skb_unlink(skb, skb_list);

		/* Get the protocol, maintain skb around eth_type_trans()
		 * The main reason for this hack is for the limitation of
+21 −31
Original line number Diff line number Diff line
@@ -1120,7 +1120,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
	u8 *dptr, num = 0;

	u16 sublen, check;
	struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
	struct sk_buff *pfirst, *pnext;

	int errcode;
	u8 chan, seq, doff, sfdoff;
@@ -1137,7 +1137,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)

	/* If there's a descriptor, generate the packet chain */
	if (bus->glomd) {
		pfirst = plast = pnext = NULL;
		pfirst = pnext = NULL;
		dlen = (u16) (bus->glomd->len);
		dptr = bus->glomd->data;
		if (!dlen || (dlen & 1)) {
@@ -1338,10 +1338,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
		/* Remove superframe header, remember offset */
		skb_pull(pfirst, doff);
		sfdoff = doff;
		num = 0;

		/* Validate all the subframe headers */
		for (num = 0, pnext = pfirst; pnext && !errcode;
		     num++, pnext = pnext->next) {
		skb_queue_walk(&bus->glom, pnext) {
			/* leave when invalid subframe is found */
			if (errcode)
				break;

			dptr = (u8 *) (pnext->data);
			dlen = (u16) (pnext->len);
			sublen = get_unaligned_le16(dptr);
@@ -1374,6 +1378,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
					  num, doff, sublen, SDPCM_HDRLEN);
				errcode = -1;
			}
			/* increase the subframe count */
			num++;
		}

		if (errcode) {
@@ -1394,13 +1400,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
		}

		/* Basic SD framing looks ok - process each packet (header) */
		save_pfirst = pfirst;
		plast = NULL;

		for (num = 0; pfirst; rxseq++, pfirst = pnext) {
			pnext = pfirst->next;
			pfirst->next = NULL;

		skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
			dptr = (u8 *) (pfirst->data);
			sublen = get_unaligned_le16(dptr);
			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -1420,6 +1421,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
				bus->rx_badseq++;
				rxseq = seq;
			}
			rxseq++;

#ifdef BCMDBG
			if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
				printk(KERN_DEBUG "Rx Subframe Data:\n");
@@ -1432,36 +1435,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
			skb_pull(pfirst, doff);

			if (pfirst->len == 0) {
				skb_unlink(pfirst, &bus->glom);
				brcmu_pkt_buf_free_skb(pfirst);
				if (plast)
					plast->next = pnext;
				else
					save_pfirst = pnext;

				continue;
			} else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
						       pfirst) != 0) {
				brcmf_dbg(ERROR, "rx protocol error\n");
				bus->drvr->rx_errors++;
				skb_unlink(pfirst, &bus->glom);
				brcmu_pkt_buf_free_skb(pfirst);
				if (plast)
					plast->next = pnext;
				else
					save_pfirst = pnext;

				continue;
			}

			/* this packet will go up, link back into
				 chain and count it */
			pfirst->next = pnext;
			plast = pfirst;
			num++;

#ifdef BCMDBG
			if (BRCMF_GLOM_ON()) {
				brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
					  num, pfirst, pfirst->data,
					  bus->glom.qlen, pfirst, pfirst->data,
					  pfirst->len, pfirst->next,
					  pfirst->prev);
				print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
@@ -1470,14 +1459,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
			}
#endif				/* BCMDBG */
		}
		if (num) {
		/* sent any remaining packets up */
		if (bus->glom.qlen) {
			up(&bus->sdsem);
			brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num);
			brcmf_rx_frame(bus->drvr, ifidx, &bus->glom);
			down(&bus->sdsem);
		}

		bus->rxglomframes++;
		bus->rxglompkts += num;
		bus->rxglompkts += bus->glom.qlen;
	}
	return num;
}
@@ -2075,7 +2065,7 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)

		/* Unlock during rx call */
		up(&bus->sdsem);
		brcmf_rx_frame(bus->drvr, ifidx, pkt, 1);
		brcmf_rx_packet(bus->drvr, ifidx, pkt);
		down(&bus->sdsem);
	}
	rxcount = maxframes - rxleft;