aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/main.c
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2014-11-25 09:43:05 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-11-25 14:09:56 -0500
commit808bbebcc8fcbcb2b93aefd8b181a0fdccb407c6 (patch)
tree76730d24264fbea860643fe4c8706b0d45bf2418 /drivers/net/wireless/mwifiex/main.c
parent381e9fffe6b8343c2479939178ef7ded50bf32d3 (diff)
mwifiex: add Tx status support for EAPOL packets
Firmware notifies the driver through event if EAPOL data packet has been acked or not. We will inform this status to userspace listening on a socket. Signed-off-by: Cathy Luo <cluo@marvell.com> Signed-off-by: Avinash Patil <patila@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwifiex/main.c')
-rw-r--r--drivers/net/wireless/mwifiex/main.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index cf07279bf602..cf31d36a9fdd 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -608,6 +608,44 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
608 return 0; 608 return 0;
609} 609}
610 610
611static struct sk_buff *
612mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
613 struct sk_buff *skb, u8 flag)
614{
615 struct sk_buff *orig_skb = skb;
616 struct mwifiex_txinfo *tx_info, *orig_tx_info;
617
618 skb = skb_clone(skb, GFP_ATOMIC);
619 if (skb) {
620 unsigned long flags;
621 int id;
622
623 spin_lock_irqsave(&priv->ack_status_lock, flags);
624 id = idr_alloc(&priv->ack_status_frames, orig_skb,
625 1, 0xff, GFP_ATOMIC);
626 spin_unlock_irqrestore(&priv->ack_status_lock, flags);
627
628 if (id >= 0) {
629 tx_info = MWIFIEX_SKB_TXCB(skb);
630 tx_info->ack_frame_id = id;
631 tx_info->flags |= flag;
632 orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb);
633 orig_tx_info->ack_frame_id = id;
634 orig_tx_info->flags |= flag;
635 } else if (skb_shared(skb)) {
636 kfree_skb(orig_skb);
637 } else {
638 kfree_skb(skb);
639 skb = orig_skb;
640 }
641 } else {
642 /* couldn't clone -- lose tx status ... */
643 skb = orig_skb;
644 }
645
646 return skb;
647}
648
611/* 649/*
612 * CFG802.11 network device handler for data transmission. 650 * CFG802.11 network device handler for data transmission.
613 */ 651 */
@@ -617,6 +655,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
617 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 655 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
618 struct sk_buff *new_skb; 656 struct sk_buff *new_skb;
619 struct mwifiex_txinfo *tx_info; 657 struct mwifiex_txinfo *tx_info;
658 bool multicast;
620 659
621 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n", 660 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
622 jiffies, priv->bss_type, priv->bss_num); 661 jiffies, priv->bss_type, priv->bss_num);
@@ -657,6 +696,15 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
657 tx_info->bss_type = priv->bss_type; 696 tx_info->bss_type = priv->bss_type;
658 tx_info->pkt_len = skb->len; 697 tx_info->pkt_len = skb->len;
659 698
699 multicast = is_multicast_ether_addr(skb->data);
700
701 if (unlikely(!multicast && skb->sk &&
702 skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS &&
703 priv->adapter->fw_api_ver == MWIFIEX_FW_V15))
704 skb = mwifiex_clone_skb_for_tx_status(priv,
705 skb,
706 MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS);
707
660 /* Record the current time the packet was queued; used to 708 /* Record the current time the packet was queued; used to
661 * determine the amount of time the packet was queued in 709 * determine the amount of time the packet was queued in
662 * the driver before it was sent to the firmware. 710 * the driver before it was sent to the firmware.