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:
{
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);
}
}
}
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);
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);
}
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);
}
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;
}
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;
}