1 /* 2 * Copyright (C) 2007-2012 Siemens AG 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * Written by: 14 * Pavel Smolenskiy <pavel.smolenskiy@gmail.com> 15 * Maxim Gorbachyov <maxim.gorbachev@siemens.com> 16 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 17 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> 18 */ 19 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/workqueue.h> 23 #include <linux/netdevice.h> 24 #include <linux/crc-ccitt.h> 25 26 #include <net/mac802154.h> 27 #include <net/ieee802154_netdev.h> 28 29 #include "ieee802154_i.h" 30 31 /* The IEEE 802.15.4 standard defines 4 MAC packet types: 32 * - beacon frame 33 * - MAC command frame 34 * - acknowledgement frame 35 * - data frame 36 * 37 * and only the data frame should be pushed to the upper layers, other types 38 * are just internal MAC layer management information. So only data packets 39 * are going to be sent to the networking queue, all other will be processed 40 * right here by using the device workqueue. 41 */ 42 struct rx_work { 43 struct sk_buff *skb; 44 struct work_struct work; 45 struct ieee802154_hw *hw; 46 u8 lqi; 47 }; 48 49 static void 50 mac802154_subif_rx(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi) 51 { 52 struct ieee802154_local *local = hw_to_local(hw); 53 54 mac_cb(skb)->lqi = lqi; 55 skb->protocol = htons(ETH_P_IEEE802154); 56 skb_reset_mac_header(skb); 57 58 if (!(local->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { 59 u16 crc; 60 61 if (skb->len < 2) { 62 pr_debug("got invalid frame\n"); 63 goto fail; 64 } 65 crc = crc_ccitt(0, skb->data, skb->len); 66 if (crc) { 67 pr_debug("CRC mismatch\n"); 68 goto fail; 69 } 70 skb_trim(skb, skb->len - 2); /* CRC */ 71 } 72 73 mac802154_monitors_rx(local, skb); 74 mac802154_wpans_rx(local, skb); 75 76 return; 77 78 fail: 79 kfree_skb(skb); 80 } 81 82 static void mac802154_rx_worker(struct work_struct *work) 83 { 84 struct rx_work *rw = container_of(work, struct rx_work, work); 85 86 mac802154_subif_rx(rw->hw, rw->skb, rw->lqi); 87 kfree(rw); 88 } 89 90 void 91 ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi) 92 { 93 struct ieee802154_local *local = hw_to_local(hw); 94 struct rx_work *work; 95 96 if (!skb) 97 return; 98 99 work = kzalloc(sizeof(*work), GFP_ATOMIC); 100 if (!work) 101 return; 102 103 INIT_WORK(&work->work, mac802154_rx_worker); 104 work->skb = skb; 105 work->hw = hw; 106 work->lqi = lqi; 107 108 queue_work(local->dev_workqueue, &work->work); 109 } 110 EXPORT_SYMBOL(ieee802154_rx_irqsafe); 111