Skip to content

Commit

Permalink
brcmfmac: Move out hdrpull from tx_finalize.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hante Meuleman authored and John W. Linville committed May 13, 2014
1 parent 604bf23 commit 53e30ea
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 42 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/brcm80211/brcmfmac/dhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
u32 brcmf_get_chip_info(struct brcmf_if *ifp);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success);

/* Sets dongle media info (drv_version, mac address). */
Expand Down
27 changes: 13 additions & 14 deletions drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,31 +538,26 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
brcmf_netif_rx(ifp, skb);
}

void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success)
{
struct brcmf_if *ifp;
struct ethhdr *eh;
u8 ifidx;
u16 type;
int res;

res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);

ifp = drvr->iflist[ifidx];
if (!ifp)
goto done;

if (res == 0) {
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);
eh = (struct ethhdr *)(txp->data);
type = ntohs(eh->h_proto);

if (type == ETH_P_PAE) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}
if (type == ETH_P_PAE) {
atomic_dec(&ifp->pend_8021x_cnt);
if (waitqueue_active(&ifp->pend_8021x_wait))
wake_up(&ifp->pend_8021x_wait);
}

if (!success)
ifp->stats.tx_errors++;
done:
Expand All @@ -573,13 +568,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
u8 ifidx;

/* await txstatus signal for firmware if active */
if (brcmf_fws_fc_active(drvr->fws)) {
if (!success)
brcmf_fws_bustxfail(drvr->fws, txp);
} else {
brcmf_txfinalize(drvr, txp, success);
if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
brcmu_pkt_buf_free_skb(txp);
else
brcmf_txfinalize(drvr, txp, ifidx, success);
}
}

Expand Down
50 changes: 23 additions & 27 deletions drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1369,13 +1369,12 @@ static struct sk_buff *brcmf_fws_deq(struct brcmf_fws_info *fws, int fifo)
}

static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
struct sk_buff *skb, u32 genbit,
u16 seq)
struct sk_buff *skb, u8 ifidx,
u32 genbit, u16 seq)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
u32 hslot;
int ret;
u8 ifidx;

hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);

Expand All @@ -1389,29 +1388,21 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,

entry->generation = genbit;

ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
if (ret == 0) {
brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
brcmf_skbcb(skb)->htod_seq = seq;
if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
} else {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
}
ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
skb);
brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
brcmf_skbcb(skb)->htod_seq = seq;
if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
} else {
brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
}
ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);

if (ret != 0) {
/* suppress q is full or hdrpull failed, drop this packet */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
true);
/* suppress q is full drop this packet */
brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
} else {
/*
* Mark suppressed to avoid a double free during
* wlfc cleanup
*/
/* Mark suppressed to avoid a double free during wlfc cleanup */
brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
}

Expand All @@ -1428,6 +1419,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
struct sk_buff *skb;
struct brcmf_skbuff_cb *skcb;
struct brcmf_fws_mac_descriptor *entry = NULL;
u8 ifidx;

brcmf_dbg(DATA, "flags %d\n", flags);

Expand Down Expand Up @@ -1476,12 +1468,15 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
}
brcmf_fws_macdesc_return_req_credit(skb);

if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
brcmu_pkt_buf_free_skb(skb);
return -EINVAL;
}
if (!remove_from_hanger)
ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit,
seq);

ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
genbit, seq);
if (remove_from_hanger || ret)
brcmf_txfinalize(fws->drvr, skb, true);
brcmf_txfinalize(fws->drvr, skb, ifidx, true);

return 0;
}
Expand Down Expand Up @@ -1982,7 +1977,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
brcmf_fws_lock(fws);
if (ret < 0)
brcmf_txfinalize(drvr, skb, false);
brcmf_txfinalize(drvr, skb, ifidx,
false);
if (fws->bus_flow_blocked)
break;
}
Expand Down

0 comments on commit 53e30ea

Please sign in to comment.