Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2007-2012 Siemens AG
0004  *
0005  * Written by:
0006  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
0007  * Sergey Lapin <slapin@ossfans.org>
0008  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
0009  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
0010  */
0011 
0012 #include <linux/netdevice.h>
0013 #include <linux/if_arp.h>
0014 #include <linux/crc-ccitt.h>
0015 #include <asm/unaligned.h>
0016 
0017 #include <net/rtnetlink.h>
0018 #include <net/ieee802154_netdev.h>
0019 #include <net/mac802154.h>
0020 #include <net/cfg802154.h>
0021 
0022 #include "ieee802154_i.h"
0023 #include "driver-ops.h"
0024 
0025 void ieee802154_xmit_worker(struct work_struct *work)
0026 {
0027     struct ieee802154_local *local =
0028         container_of(work, struct ieee802154_local, tx_work);
0029     struct sk_buff *skb = local->tx_skb;
0030     struct net_device *dev = skb->dev;
0031     int res;
0032 
0033     res = drv_xmit_sync(local, skb);
0034     if (res)
0035         goto err_tx;
0036 
0037     dev->stats.tx_packets++;
0038     dev->stats.tx_bytes += skb->len;
0039 
0040     ieee802154_xmit_complete(&local->hw, skb, false);
0041 
0042     return;
0043 
0044 err_tx:
0045     /* Restart the netif queue on each sub_if_data object. */
0046     ieee802154_wake_queue(&local->hw);
0047     kfree_skb(skb);
0048     netdev_dbg(dev, "transmission failed\n");
0049 }
0050 
0051 static netdev_tx_t
0052 ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
0053 {
0054     struct net_device *dev = skb->dev;
0055     int ret;
0056 
0057     if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
0058         struct sk_buff *nskb;
0059         u16 crc;
0060 
0061         if (unlikely(skb_tailroom(skb) < IEEE802154_FCS_LEN)) {
0062             nskb = skb_copy_expand(skb, 0, IEEE802154_FCS_LEN,
0063                            GFP_ATOMIC);
0064             if (likely(nskb)) {
0065                 consume_skb(skb);
0066                 skb = nskb;
0067             } else {
0068                 goto err_tx;
0069             }
0070         }
0071 
0072         crc = crc_ccitt(0, skb->data, skb->len);
0073         put_unaligned_le16(crc, skb_put(skb, 2));
0074     }
0075 
0076     /* Stop the netif queue on each sub_if_data object. */
0077     ieee802154_stop_queue(&local->hw);
0078 
0079     /* async is priority, otherwise sync is fallback */
0080     if (local->ops->xmit_async) {
0081         unsigned int len = skb->len;
0082 
0083         ret = drv_xmit_async(local, skb);
0084         if (ret) {
0085             ieee802154_wake_queue(&local->hw);
0086             goto err_tx;
0087         }
0088 
0089         dev->stats.tx_packets++;
0090         dev->stats.tx_bytes += len;
0091     } else {
0092         local->tx_skb = skb;
0093         queue_work(local->workqueue, &local->tx_work);
0094     }
0095 
0096     return NETDEV_TX_OK;
0097 
0098 err_tx:
0099     kfree_skb(skb);
0100     return NETDEV_TX_OK;
0101 }
0102 
0103 netdev_tx_t
0104 ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
0105 {
0106     struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0107 
0108     skb->skb_iif = dev->ifindex;
0109 
0110     return ieee802154_tx(sdata->local, skb);
0111 }
0112 
0113 netdev_tx_t
0114 ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
0115 {
0116     struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
0117     int rc;
0118 
0119     /* TODO we should move it to wpan_dev_hard_header and dev_hard_header
0120      * functions. The reason is wireshark will show a mac header which is
0121      * with security fields but the payload is not encrypted.
0122      */
0123     rc = mac802154_llsec_encrypt(&sdata->sec, skb);
0124     if (rc) {
0125         netdev_warn(dev, "encryption failed: %i\n", rc);
0126         kfree_skb(skb);
0127         return NETDEV_TX_OK;
0128     }
0129 
0130     skb->skb_iif = dev->ifindex;
0131 
0132     return ieee802154_tx(sdata->local, skb);
0133 }