]>
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 | * | |
13 | * You should have received a copy of the GNU General Public License along | |
14 | * with this program; if not, write to the Free Software Foundation, Inc., | |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
16 | * | |
17 | * Written by: | |
18 | * Pavel Smolenskiy <pavel.smolenskiy@gmail.com> | |
19 | * Maxim Gorbachyov <maxim.gorbachev@siemens.com> | |
20 | * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | |
21 | * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> | |
22 | */ | |
23 | ||
24 | #include <linux/kernel.h> | |
25 | #include <linux/module.h> | |
26 | #include <linux/workqueue.h> | |
27 | #include <linux/netdevice.h> | |
28 | #include <linux/crc-ccitt.h> | |
29 | ||
30 | #include <net/mac802154.h> | |
31 | #include <net/ieee802154_netdev.h> | |
32 | ||
33 | #include "mac802154.h" | |
34 | ||
35 | /* The IEEE 802.15.4 standard defines 4 MAC packet types: | |
36 | * - beacon frame | |
37 | * - MAC command frame | |
38 | * - acknowledgement frame | |
39 | * - data frame | |
40 | * | |
41 | * and only the data frame should be pushed to the upper layers, other types | |
42 | * are just internal MAC layer management information. So only data packets | |
43 | * are going to be sent to the networking queue, all other will be processed | |
44 | * right here by using the device workqueue. | |
45 | */ | |
46 | struct rx_work { | |
47 | struct sk_buff *skb; | |
48 | struct work_struct work; | |
49 | struct ieee802154_dev *dev; | |
50 | u8 lqi; | |
51 | }; | |
52 | ||
53 | static void | |
54 | mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb, u8 lqi) | |
55 | { | |
56 | struct mac802154_priv *priv = mac802154_to_priv(hw); | |
57 | ||
58 | mac_cb(skb)->lqi = lqi; | |
59 | skb->protocol = htons(ETH_P_IEEE802154); | |
60 | skb_reset_mac_header(skb); | |
61 | ||
62 | BUILD_BUG_ON(sizeof(struct ieee802154_mac_cb) > sizeof(skb->cb)); | |
63 | ||
64 | if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { | |
65 | u16 crc; | |
66 | ||
67 | if (skb->len < 2) { | |
68 | pr_debug("got invalid frame\n"); | |
69 | goto out; | |
70 | } | |
71 | crc = crc_ccitt(0, skb->data, skb->len); | |
72 | if (crc) { | |
73 | pr_debug("CRC mismatch\n"); | |
74 | goto out; | |
75 | } | |
76 | skb_trim(skb, skb->len - 2); /* CRC */ | |
77 | } | |
78 | ||
0606069d | 79 | mac802154_monitors_rx(priv, skb); |
32bad7e3 | 80 | mac802154_wpans_rx(priv, skb); |
1cd829c8 | 81 | out: |
82 | dev_kfree_skb(skb); | |
83 | return; | |
84 | } | |
85 | ||
86 | static void mac802154_rx_worker(struct work_struct *work) | |
87 | { | |
88 | struct rx_work *rw = container_of(work, struct rx_work, work); | |
89 | struct sk_buff *skb = rw->skb; | |
90 | ||
91 | mac802154_subif_rx(rw->dev, skb, rw->lqi); | |
92 | kfree(rw); | |
93 | } | |
94 | ||
95 | void | |
96 | ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi) | |
97 | { | |
98 | struct mac802154_priv *priv = mac802154_to_priv(dev); | |
99 | struct rx_work *work; | |
100 | ||
101 | if (!skb) | |
102 | return; | |
103 | ||
104 | work = kzalloc(sizeof(struct rx_work), GFP_ATOMIC); | |
105 | if (!work) | |
106 | return; | |
107 | ||
108 | INIT_WORK(&work->work, mac802154_rx_worker); | |
109 | work->skb = skb; | |
110 | work->dev = dev; | |
111 | work->lqi = lqi; | |
112 | ||
113 | queue_work(priv->dev_workqueue, &work->work); | |
114 | } | |
115 | EXPORT_SYMBOL(ieee802154_rx_irqsafe); |