Commit | Line | Data |
---|---|---|
1cd829c8 | 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 | * | |
1cd829c8 | 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 | ||
0f1556bc | 29 | #include "ieee802154_i.h" |
1cd829c8 | 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_dev *dev; | |
46 | u8 lqi; | |
47 | }; | |
48 | ||
49 | static void | |
50 | mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb, u8 lqi) | |
51 | { | |
52 | struct mac802154_priv *priv = mac802154_to_priv(hw); | |
53 | ||
54 | mac_cb(skb)->lqi = lqi; | |
55 | skb->protocol = htons(ETH_P_IEEE802154); | |
56 | skb_reset_mac_header(skb); | |
57 | ||
1cd829c8 | 58 | if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { |
59 | u16 crc; | |
60 | ||
61 | if (skb->len < 2) { | |
62 | pr_debug("got invalid frame\n"); | |
2d3b5b0a | 63 | goto fail; |
1cd829c8 | 64 | } |
65 | crc = crc_ccitt(0, skb->data, skb->len); | |
66 | if (crc) { | |
67 | pr_debug("CRC mismatch\n"); | |
2d3b5b0a | 68 | goto fail; |
1cd829c8 | 69 | } |
70 | skb_trim(skb, skb->len - 2); /* CRC */ | |
71 | } | |
72 | ||
0606069d | 73 | mac802154_monitors_rx(priv, skb); |
32bad7e3 | 74 | mac802154_wpans_rx(priv, skb); |
2d3b5b0a PB |
75 | |
76 | return; | |
77 | ||
78 | fail: | |
79 | kfree_skb(skb); | |
1cd829c8 | 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); | |
1cd829c8 | 85 | |
24bbd44a | 86 | mac802154_subif_rx(rw->dev, rw->skb, rw->lqi); |
1cd829c8 | 87 | kfree(rw); |
88 | } | |
89 | ||
90 | void | |
91 | ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi) | |
92 | { | |
93 | struct mac802154_priv *priv = mac802154_to_priv(dev); | |
94 | struct rx_work *work; | |
95 | ||
96 | if (!skb) | |
97 | return; | |
98 | ||
24bbd44a | 99 | work = kzalloc(sizeof(*work), GFP_ATOMIC); |
1cd829c8 | 100 | if (!work) |
101 | return; | |
102 | ||
103 | INIT_WORK(&work->work, mac802154_rx_worker); | |
104 | work->skb = skb; | |
105 | work->dev = dev; | |
106 | work->lqi = lqi; | |
107 | ||
108 | queue_work(priv->dev_workqueue, &work->work); | |
109 | } | |
110 | EXPORT_SYMBOL(ieee802154_rx_irqsafe); |