aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac802154/rx.c
diff options
context:
space:
mode:
authorAlexander Aring <alex.aring@gmail.com>2014-10-29 16:34:36 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-10-29 18:07:45 -0400
commitb7889497d306df0be52300b3060ebc12b4194f9a (patch)
treeee2f0a995b2e5579f63960a47f2f519dbffa326e /net/mac802154/rx.c
parent08c511a7331cf6edb28895d7f46c3039180b30cb (diff)
mac802154: rx: simplify crc receive handling
This patch change the actual crc handling while receive. Currently the IEEE802154_HW_RX_OMIT_CKSUM flag is used to filter a frame with a bad crc. This patch changes the behaviour of IEEE802154_HW_RX_OMIT_CKSUM to add a crc while receiving for the monitor interface. After monitor receiving we remove the crc for frame parsing. This affect the driver layer because all drivers sets IEEE802154_HW_RX_OMIT_CKSUM and deliver without checksum. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/mac802154/rx.c')
-rw-r--r--net/mac802154/rx.c34
1 files changed, 12 insertions, 22 deletions
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index 51a55d9200cb..b6a4bbfdbf90 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -21,6 +21,7 @@
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/netdevice.h> 22#include <linux/netdevice.h>
23#include <linux/crc-ccitt.h> 23#include <linux/crc-ccitt.h>
24#include <asm/unaligned.h>
24 25
25#include <net/mac802154.h> 26#include <net/mac802154.h>
26#include <net/ieee802154_netdev.h> 27#include <net/ieee802154_netdev.h>
@@ -225,8 +226,6 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
225{ 226{
226 struct sk_buff *skb2; 227 struct sk_buff *skb2;
227 struct ieee802154_sub_if_data *sdata; 228 struct ieee802154_sub_if_data *sdata;
228 u16 crc = crc_ccitt(0, skb->data, skb->len);
229 u8 *data;
230 229
231 skb_reset_mac_header(skb); 230 skb_reset_mac_header(skb);
232 skb->ip_summed = CHECKSUM_UNNECESSARY; 231 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -241,9 +240,6 @@ ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
241 skb2 = skb_clone(skb, GFP_ATOMIC); 240 skb2 = skb_clone(skb, GFP_ATOMIC);
242 skb2->dev = sdata->dev; 241 skb2->dev = sdata->dev;
243 skb2->pkt_type = PACKET_HOST; 242 skb2->pkt_type = PACKET_HOST;
244 data = skb_put(skb2, 2);
245 data[0] = crc & 0xff;
246 data[1] = crc >> 8;
247 243
248 netif_rx_ni(skb2); 244 netif_rx_ni(skb2);
249 } 245 }
@@ -255,32 +251,26 @@ void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
255 251
256 WARN_ON_ONCE(softirq_count() == 0); 252 WARN_ON_ONCE(softirq_count() == 0);
257 253
258 if (!(local->hw.flags & IEEE802154_HW_RX_OMIT_CKSUM)) { 254 /* TODO: When a transceiver omits the checksum here, we
259 u16 crc; 255 * add an own calculated one. This is currently an ugly
256 * solution because the monitor needs a crc here.
257 */
258 if (local->hw.flags & IEEE802154_HW_RX_OMIT_CKSUM) {
259 u16 crc = crc_ccitt(0, skb->data, skb->len);
260 260
261 if (skb->len < 2) { 261 put_unaligned_le16(crc, skb_put(skb, 2));
262 pr_debug("got invalid frame\n");
263 goto fail;
264 }
265 crc = crc_ccitt(0, skb->data, skb->len);
266 if (crc) {
267 pr_debug("CRC mismatch\n");
268 goto fail;
269 }
270 skb_trim(skb, skb->len - 2); /* CRC */
271 } 262 }
272 263
273 rcu_read_lock(); 264 rcu_read_lock();
274 265
275 ieee802154_monitors_rx(local, skb); 266 ieee802154_monitors_rx(local, skb);
276 __ieee802154_rx_handle_packet(local, skb);
277 267
278 rcu_read_unlock(); 268 /* remove crc */
269 skb_trim(skb, skb->len - 2);
279 270
280 return; 271 __ieee802154_rx_handle_packet(local, skb);
281 272
282fail: 273 rcu_read_unlock();
283 kfree_skb(skb);
284} 274}
285EXPORT_SYMBOL(ieee802154_rx); 275EXPORT_SYMBOL(ieee802154_rx);
286 276