diff options
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | 50 |
3 files changed, 37 insertions, 42 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 939d6b132922..16f9ab2568a8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -186,7 +186,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); | |||
186 | void brcmf_txflowblock_if(struct brcmf_if *ifp, | 186 | void brcmf_txflowblock_if(struct brcmf_if *ifp, |
187 | enum brcmf_netif_stop_reason reason, bool state); | 187 | enum brcmf_netif_stop_reason reason, bool state); |
188 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); | 188 | u32 brcmf_get_chip_info(struct brcmf_if *ifp); |
189 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 189 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
190 | bool success); | 190 | bool success); |
191 | 191 | ||
192 | /* Sets dongle media info (drv_version, mac address). */ | 192 | /* Sets dongle media info (drv_version, mac address). */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 7d28cd385092..6056efd02fcd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -538,31 +538,26 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb) | |||
538 | brcmf_netif_rx(ifp, skb); | 538 | brcmf_netif_rx(ifp, skb); |
539 | } | 539 | } |
540 | 540 | ||
541 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, | 541 | void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, |
542 | bool success) | 542 | bool success) |
543 | { | 543 | { |
544 | struct brcmf_if *ifp; | 544 | struct brcmf_if *ifp; |
545 | struct ethhdr *eh; | 545 | struct ethhdr *eh; |
546 | u8 ifidx; | ||
547 | u16 type; | 546 | u16 type; |
548 | int res; | ||
549 | |||
550 | res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp); | ||
551 | 547 | ||
552 | ifp = drvr->iflist[ifidx]; | 548 | ifp = drvr->iflist[ifidx]; |
553 | if (!ifp) | 549 | if (!ifp) |
554 | goto done; | 550 | goto done; |
555 | 551 | ||
556 | if (res == 0) { | 552 | eh = (struct ethhdr *)(txp->data); |
557 | eh = (struct ethhdr *)(txp->data); | 553 | type = ntohs(eh->h_proto); |
558 | type = ntohs(eh->h_proto); | ||
559 | 554 | ||
560 | if (type == ETH_P_PAE) { | 555 | if (type == ETH_P_PAE) { |
561 | atomic_dec(&ifp->pend_8021x_cnt); | 556 | atomic_dec(&ifp->pend_8021x_cnt); |
562 | if (waitqueue_active(&ifp->pend_8021x_wait)) | 557 | if (waitqueue_active(&ifp->pend_8021x_wait)) |
563 | wake_up(&ifp->pend_8021x_wait); | 558 | wake_up(&ifp->pend_8021x_wait); |
564 | } | ||
565 | } | 559 | } |
560 | |||
566 | if (!success) | 561 | if (!success) |
567 | ifp->stats.tx_errors++; | 562 | ifp->stats.tx_errors++; |
568 | done: | 563 | done: |
@@ -573,13 +568,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) | |||
573 | { | 568 | { |
574 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 569 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
575 | struct brcmf_pub *drvr = bus_if->drvr; | 570 | struct brcmf_pub *drvr = bus_if->drvr; |
571 | u8 ifidx; | ||
576 | 572 | ||
577 | /* await txstatus signal for firmware if active */ | 573 | /* await txstatus signal for firmware if active */ |
578 | if (brcmf_fws_fc_active(drvr->fws)) { | 574 | if (brcmf_fws_fc_active(drvr->fws)) { |
579 | if (!success) | 575 | if (!success) |
580 | brcmf_fws_bustxfail(drvr->fws, txp); | 576 | brcmf_fws_bustxfail(drvr->fws, txp); |
581 | } else { | 577 | } else { |
582 | brcmf_txfinalize(drvr, txp, success); | 578 | if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) |
579 | brcmu_pkt_buf_free_skb(txp); | ||
580 | else | ||
581 | brcmf_txfinalize(drvr, txp, ifidx, success); | ||
583 | } | 582 | } |
584 | } | 583 | } |
585 | 584 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index c3e7d76dbf35..bfe7c9aab65c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -1369,13 +1369,12 @@ done: | |||
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | 1371 | static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, |
1372 | struct sk_buff *skb, u32 genbit, | 1372 | struct sk_buff *skb, u8 ifidx, |
1373 | u16 seq) | 1373 | u32 genbit, u16 seq) |
1374 | { | 1374 | { |
1375 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; | 1375 | struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; |
1376 | u32 hslot; | 1376 | u32 hslot; |
1377 | int ret; | 1377 | int ret; |
1378 | u8 ifidx; | ||
1379 | 1378 | ||
1380 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); | 1379 | hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); |
1381 | 1380 | ||
@@ -1389,29 +1388,21 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, | |||
1389 | 1388 | ||
1390 | entry->generation = genbit; | 1389 | entry->generation = genbit; |
1391 | 1390 | ||
1392 | ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); | 1391 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); |
1393 | if (ret == 0) { | 1392 | brcmf_skbcb(skb)->htod_seq = seq; |
1394 | brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit); | 1393 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { |
1395 | brcmf_skbcb(skb)->htod_seq = seq; | 1394 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); |
1396 | if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) { | 1395 | brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); |
1397 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1); | 1396 | } else { |
1398 | brcmf_skb_htod_seq_set_field(skb, FROMFW, 0); | 1397 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); |
1399 | } else { | ||
1400 | brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0); | ||
1401 | } | ||
1402 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, | ||
1403 | skb); | ||
1404 | } | 1398 | } |
1399 | ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb); | ||
1405 | 1400 | ||
1406 | if (ret != 0) { | 1401 | if (ret != 0) { |
1407 | /* suppress q is full or hdrpull failed, drop this packet */ | 1402 | /* suppress q is full drop this packet */ |
1408 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, | 1403 | brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true); |
1409 | true); | ||
1410 | } else { | 1404 | } else { |
1411 | /* | 1405 | /* Mark suppressed to avoid a double free during wlfc cleanup */ |
1412 | * Mark suppressed to avoid a double free during | ||
1413 | * wlfc cleanup | ||
1414 | */ | ||
1415 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); | 1406 | brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot); |
1416 | } | 1407 | } |
1417 | 1408 | ||
@@ -1428,6 +1419,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
1428 | struct sk_buff *skb; | 1419 | struct sk_buff *skb; |
1429 | struct brcmf_skbuff_cb *skcb; | 1420 | struct brcmf_skbuff_cb *skcb; |
1430 | struct brcmf_fws_mac_descriptor *entry = NULL; | 1421 | struct brcmf_fws_mac_descriptor *entry = NULL; |
1422 | u8 ifidx; | ||
1431 | 1423 | ||
1432 | brcmf_dbg(DATA, "flags %d\n", flags); | 1424 | brcmf_dbg(DATA, "flags %d\n", flags); |
1433 | 1425 | ||
@@ -1476,12 +1468,15 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot, | |||
1476 | } | 1468 | } |
1477 | brcmf_fws_macdesc_return_req_credit(skb); | 1469 | brcmf_fws_macdesc_return_req_credit(skb); |
1478 | 1470 | ||
1471 | if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { | ||
1472 | brcmu_pkt_buf_free_skb(skb); | ||
1473 | return -EINVAL; | ||
1474 | } | ||
1479 | if (!remove_from_hanger) | 1475 | if (!remove_from_hanger) |
1480 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit, | 1476 | ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, |
1481 | seq); | 1477 | genbit, seq); |
1482 | |||
1483 | if (remove_from_hanger || ret) | 1478 | if (remove_from_hanger || ret) |
1484 | brcmf_txfinalize(fws->drvr, skb, true); | 1479 | brcmf_txfinalize(fws->drvr, skb, ifidx, true); |
1485 | 1480 | ||
1486 | return 0; | 1481 | return 0; |
1487 | } | 1482 | } |
@@ -1982,7 +1977,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker) | |||
1982 | ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); | 1977 | ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); |
1983 | brcmf_fws_lock(fws); | 1978 | brcmf_fws_lock(fws); |
1984 | if (ret < 0) | 1979 | if (ret < 0) |
1985 | brcmf_txfinalize(drvr, skb, false); | 1980 | brcmf_txfinalize(drvr, skb, ifidx, |
1981 | false); | ||
1986 | if (fws->bus_flow_blocked) | 1982 | if (fws->bus_flow_blocked) |
1987 | break; | 1983 | break; |
1988 | } | 1984 | } |