diff options
author | Arend van Spriel <arend@broadcom.com> | 2011-11-22 20:21:36 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-28 14:43:26 -0500 |
commit | 0b45bf74f91e781b74bfadb8bb08ef341b6befd3 (patch) | |
tree | 07544f2ba386262ae601cba1ba3e71092526dcfe | |
parent | e7979ac7826e3170c685e7fe6d8c594ac505a30a (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>
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 11 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 52 |
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. */ |
701 | extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, | 701 | extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, |
702 | struct sk_buff *rxp, int numpkt); | 702 | struct sk_buff_head *rxlist); |
703 | static 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 */ |
705 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); | 714 | extern 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 | ||
400 | void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, | 400 | void 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; |