aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2014-05-12 04:47:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-05-13 15:56:45 -0400
commit53e30ea42070bcb5cef0c9a2c59af8f9ce758f78 (patch)
treea2fa3b82b20687b010f5ac821a6771ef6fc271f1
parent604bf237cb3aa3e15d26254981ae7bc7968f05e5 (diff)
brcmfmac: Move out hdrpull from tx_finalize.
In tx_finalize the hdrpull is performed. For the new protocol msgbuf this is complex, because it does not use protocol headers in front of payload anymore and therefor can not determine interface index in the hdr pulll operation. Move out the hdrpull operation from tx_finalize to make msgbuf implementation easier. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c27
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c50
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);
186void brcmf_txflowblock_if(struct brcmf_if *ifp, 186void 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);
188u32 brcmf_get_chip_info(struct brcmf_if *ifp); 188u32 brcmf_get_chip_info(struct brcmf_if *ifp);
189void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, 189void 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
541void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, 541void 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++;
568done: 563done:
@@ -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
1371static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, 1371static 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 }