aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2011-11-22 20:21:36 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-28 14:43:26 -0500
commit0b45bf74f91e781b74bfadb8bb08ef341b6befd3 (patch)
tree07544f2ba386262ae601cba1ba3e71092526dcfe /drivers
parente7979ac7826e3170c685e7fe6d8c594ac505a30a (diff)
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: Johannes Berg <johannes@sipsolutions.net> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Alwin Beukers <alwin@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Franky Lin <frankyl@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h11
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c15
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c52
3 files changed, 36 insertions, 42 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 6da519e7578f..7962f645c5b6 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -699,7 +699,16 @@ extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q,
699 699
700/* Receive frame for delivery to OS. Callee disposes of rxp. */ 700/* Receive frame for delivery to OS. Callee disposes of rxp. */
701extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, 701extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
702 struct sk_buff *rxp, int numpkt); 702 struct sk_buff_head *rxlist);
703static inline void brcmf_rx_packet(struct brcmf_pub *drvr, int ifidx,
704 struct sk_buff *pkt)
705{
706 struct sk_buff_head q;
707
708 skb_queue_head_init(&q);
709 skb_queue_tail(&q, pkt);
710 brcmf_rx_frame(drvr, ifidx, &q);
711}
703 712
704/* Return pointer to interface name */ 713/* Return pointer to interface name */
705extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); 714extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 719fd9397eb6..97211745fe36 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -397,26 +397,21 @@ static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx,
397 return bcmerror; 397 return bcmerror;
398} 398}
399 399
400void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, 400void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx,
401 int numpkt) 401 struct sk_buff_head *skb_list)
402{ 402{
403 struct brcmf_info *drvr_priv = drvr->info; 403 struct brcmf_info *drvr_priv = drvr->info;
404 unsigned char *eth; 404 unsigned char *eth;
405 uint len; 405 uint len;
406 void *data; 406 void *data;
407 struct sk_buff *pnext, *save_pktbuf; 407 struct sk_buff *skb, *pnext;
408 int i;
409 struct brcmf_if *ifp; 408 struct brcmf_if *ifp;
410 struct brcmf_event_msg event; 409 struct brcmf_event_msg event;
411 410
412 brcmf_dbg(TRACE, "Enter\n"); 411 brcmf_dbg(TRACE, "Enter\n");
413 412
414 save_pktbuf = skb; 413 skb_queue_walk_safe(skb_list, skb, pnext) {
415 414 skb_unlink(skb, skb_list);
416 for (i = 0; skb && i < numpkt; i++, skb = pnext) {
417
418 pnext = skb->next;
419 skb->next = NULL;
420 415
421 /* Get the protocol, maintain skb around eth_type_trans() 416 /* Get the protocol, maintain skb around eth_type_trans()
422 * The main reason for this hack is for the limitation of 417 * The main reason for this hack is for the limitation of
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 22913af26db8..10b9247ec539 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1120,7 +1120,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1120 u8 *dptr, num = 0; 1120 u8 *dptr, num = 0;
1121 1121
1122 u16 sublen, check; 1122 u16 sublen, check;
1123 struct sk_buff *pfirst, *plast, *pnext, *save_pfirst; 1123 struct sk_buff *pfirst, *pnext;
1124 1124
1125 int errcode; 1125 int errcode;
1126 u8 chan, seq, doff, sfdoff; 1126 u8 chan, seq, doff, sfdoff;
@@ -1137,7 +1137,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1137 1137
1138 /* If there's a descriptor, generate the packet chain */ 1138 /* If there's a descriptor, generate the packet chain */
1139 if (bus->glomd) { 1139 if (bus->glomd) {
1140 pfirst = plast = pnext = NULL; 1140 pfirst = pnext = NULL;
1141 dlen = (u16) (bus->glomd->len); 1141 dlen = (u16) (bus->glomd->len);
1142 dptr = bus->glomd->data; 1142 dptr = bus->glomd->data;
1143 if (!dlen || (dlen & 1)) { 1143 if (!dlen || (dlen & 1)) {
@@ -1338,10 +1338,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1338 /* Remove superframe header, remember offset */ 1338 /* Remove superframe header, remember offset */
1339 skb_pull(pfirst, doff); 1339 skb_pull(pfirst, doff);
1340 sfdoff = doff; 1340 sfdoff = doff;
1341 num = 0;
1341 1342
1342 /* Validate all the subframe headers */ 1343 /* Validate all the subframe headers */
1343 for (num = 0, pnext = pfirst; pnext && !errcode; 1344 skb_queue_walk(&bus->glom, pnext) {
1344 num++, pnext = pnext->next) { 1345 /* leave when invalid subframe is found */
1346 if (errcode)
1347 break;
1348
1345 dptr = (u8 *) (pnext->data); 1349 dptr = (u8 *) (pnext->data);
1346 dlen = (u16) (pnext->len); 1350 dlen = (u16) (pnext->len);
1347 sublen = get_unaligned_le16(dptr); 1351 sublen = get_unaligned_le16(dptr);
@@ -1374,6 +1378,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1374 num, doff, sublen, SDPCM_HDRLEN); 1378 num, doff, sublen, SDPCM_HDRLEN);
1375 errcode = -1; 1379 errcode = -1;
1376 } 1380 }
1381 /* increase the subframe count */
1382 num++;
1377 } 1383 }
1378 1384
1379 if (errcode) { 1385 if (errcode) {
@@ -1394,13 +1400,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1394 } 1400 }
1395 1401
1396 /* Basic SD framing looks ok - process each packet (header) */ 1402 /* Basic SD framing looks ok - process each packet (header) */
1397 save_pfirst = pfirst;
1398 plast = NULL;
1399
1400 for (num = 0; pfirst; rxseq++, pfirst = pnext) {
1401 pnext = pfirst->next;
1402 pfirst->next = NULL;
1403 1403
1404 skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
1404 dptr = (u8 *) (pfirst->data); 1405 dptr = (u8 *) (pfirst->data);
1405 sublen = get_unaligned_le16(dptr); 1406 sublen = get_unaligned_le16(dptr);
1406 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); 1407 chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -1420,6 +1421,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1420 bus->rx_badseq++; 1421 bus->rx_badseq++;
1421 rxseq = seq; 1422 rxseq = seq;
1422 } 1423 }
1424 rxseq++;
1425
1423#ifdef BCMDBG 1426#ifdef BCMDBG
1424 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { 1427 if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) {
1425 printk(KERN_DEBUG "Rx Subframe Data:\n"); 1428 printk(KERN_DEBUG "Rx Subframe Data:\n");
@@ -1432,36 +1435,22 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1432 skb_pull(pfirst, doff); 1435 skb_pull(pfirst, doff);
1433 1436
1434 if (pfirst->len == 0) { 1437 if (pfirst->len == 0) {
1438 skb_unlink(pfirst, &bus->glom);
1435 brcmu_pkt_buf_free_skb(pfirst); 1439 brcmu_pkt_buf_free_skb(pfirst);
1436 if (plast)
1437 plast->next = pnext;
1438 else
1439 save_pfirst = pnext;
1440
1441 continue; 1440 continue;
1442 } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx, 1441 } else if (brcmf_proto_hdrpull(bus->drvr, &ifidx,
1443 pfirst) != 0) { 1442 pfirst) != 0) {
1444 brcmf_dbg(ERROR, "rx protocol error\n"); 1443 brcmf_dbg(ERROR, "rx protocol error\n");
1445 bus->drvr->rx_errors++; 1444 bus->drvr->rx_errors++;
1445 skb_unlink(pfirst, &bus->glom);
1446 brcmu_pkt_buf_free_skb(pfirst); 1446 brcmu_pkt_buf_free_skb(pfirst);
1447 if (plast)
1448 plast->next = pnext;
1449 else
1450 save_pfirst = pnext;
1451
1452 continue; 1447 continue;
1453 } 1448 }
1454 1449
1455 /* this packet will go up, link back into
1456 chain and count it */
1457 pfirst->next = pnext;
1458 plast = pfirst;
1459 num++;
1460
1461#ifdef BCMDBG 1450#ifdef BCMDBG
1462 if (BRCMF_GLOM_ON()) { 1451 if (BRCMF_GLOM_ON()) {
1463 brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n", 1452 brcmf_dbg(GLOM, "subframe %d to stack, %p (%p/%d) nxt/lnk %p/%p\n",
1464 num, pfirst, pfirst->data, 1453 bus->glom.qlen, pfirst, pfirst->data,
1465 pfirst->len, pfirst->next, 1454 pfirst->len, pfirst->next,
1466 pfirst->prev); 1455 pfirst->prev);
1467 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, 1456 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
@@ -1470,14 +1459,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
1470 } 1459 }
1471#endif /* BCMDBG */ 1460#endif /* BCMDBG */
1472 } 1461 }
1473 if (num) { 1462 /* sent any remaining packets up */
1463 if (bus->glom.qlen) {
1474 up(&bus->sdsem); 1464 up(&bus->sdsem);
1475 brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num); 1465 brcmf_rx_frame(bus->drvr, ifidx, &bus->glom);
1476 down(&bus->sdsem); 1466 down(&bus->sdsem);
1477 } 1467 }
1478 1468
1479 bus->rxglomframes++; 1469 bus->rxglomframes++;
1480 bus->rxglompkts += num; 1470 bus->rxglompkts += bus->glom.qlen;
1481 } 1471 }
1482 return num; 1472 return num;
1483} 1473}
@@ -2075,7 +2065,7 @@ deliver:
2075 2065
2076 /* Unlock during rx call */ 2066 /* Unlock during rx call */
2077 up(&bus->sdsem); 2067 up(&bus->sdsem);
2078 brcmf_rx_frame(bus->drvr, ifidx, pkt, 1); 2068 brcmf_rx_packet(bus->drvr, ifidx, pkt);
2079 down(&bus->sdsem); 2069 down(&bus->sdsem);
2080 } 2070 }
2081 rxcount = maxframes - rxleft; 2071 rxcount = maxframes - rxleft;