Lines Matching +full:inverted +full:- +full:rx

1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 /* af_can.c - Protocol family CAN core module
5 * Copyright (c) 2002-2017 Volkswagen Group Electronic Research
61 #include <linux/can/can-ml.h>
91 skb_queue_purge(&sk->sk_receive_queue); in can_sock_destruct()
92 skb_queue_purge(&sk->sk_error_queue); in can_sock_destruct()
102 if (cp && !try_module_get(cp->prot->owner)) in can_get_proto()
111 module_put(cp->prot->owner); in can_put_proto()
121 sock->state = SS_UNCONNECTED; in can_create()
124 return -EINVAL; in can_create()
132 err = request_module("can-proto-%d", protocol); in can_create()
136 * return -EPROTONOSUPPORT in can_create()
139 pr_err_ratelimited("can: request_module (can-proto-%d) failed.\n", in can_create()
149 return -EPROTONOSUPPORT; in can_create()
151 if (cp->type != sock->type) { in can_create()
152 err = -EPROTOTYPE; in can_create()
156 sock->ops = cp->ops; in can_create()
158 sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot, kern); in can_create()
160 err = -ENOMEM; in can_create()
165 sk->sk_destruct = can_sock_destruct; in can_create()
167 if (sk->sk_prot->init) in can_create()
168 err = sk->sk_prot->init(sk); in can_create()
174 sock->sk = NULL; in can_create()
185 * can_send - transmit a CAN frame (optional with local loopback)
193 * -ENETDOWN when the selected interface is down
194 * -ENOBUFS on full driver queue (see net_xmit_errno())
195 * -ENOMEM when local loopback failed at calling skb_clone()
196 * -EPERM when trying to send on a non-CAN interface
197 * -EMSGSIZE CAN frame size is bigger than CAN interface MTU
198 * -EINVAL when the skb->data does not contain a valid CAN frame
203 struct can_pkg_stats *pkg_stats = dev_net(skb->dev)->can.pkg_stats; in can_send()
204 int err = -EINVAL; in can_send()
207 skb->protocol = htons(ETH_P_CANXL); in can_send()
209 skb->protocol = htons(ETH_P_CAN); in can_send()
211 struct canfd_frame *cfd = (struct canfd_frame *)skb->data; in can_send()
213 skb->protocol = htons(ETH_P_CANFD); in can_send()
216 cfd->flags |= CANFD_FDF; in can_send()
222 if (unlikely(skb->len > skb->dev->mtu)) { in can_send()
223 err = -EMSGSIZE; in can_send()
227 if (unlikely(skb->dev->type != ARPHRD_CAN)) { in can_send()
228 err = -EPERM; in can_send()
232 if (unlikely(!(skb->dev->flags & IFF_UP))) { in can_send()
233 err = -ENETDOWN; in can_send()
237 skb->ip_summed = CHECKSUM_UNNECESSARY; in can_send()
247 skb->pkt_type = PACKET_LOOPBACK; in can_send()
252 * Therefore we have to ensure that skb->sk remains the in can_send()
253 * reference to the originating sock by restoring skb->sk in can_send()
257 if (!(skb->dev->flags & IFF_ECHO)) { in can_send()
264 return -ENOMEM; in can_send()
267 can_skb_set_owner(newskb, skb->sk); in can_send()
268 newskb->ip_summed = CHECKSUM_UNNECESSARY; in can_send()
269 newskb->pkt_type = PACKET_BROADCAST; in can_send()
273 skb->pkt_type = PACKET_HOST; in can_send()
290 atomic_long_inc(&pkg_stats->tx_frames); in can_send()
291 atomic_long_inc(&pkg_stats->tx_frames_delta); in can_send()
301 /* af_can rx path */
308 return &can_ml->dev_rcv_lists; in can_dev_rcv_lists_find()
310 return net->can.rx_alldev_list; in can_dev_rcv_lists_find()
315 * effhash - hash function for 29 bit CAN identifier reduction
324 * Hash value from 0x000 - 0x3FF ( enforced by CAN_EFF_RCV_HASH_BITS mask )
334 return hash & ((1 << CAN_EFF_RCV_HASH_BITS) - 1); in effhash()
338 * can_rcv_list_find - determine optimal filterlist inside device filter struct
355 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
357 * frames there is a special filterlist and a special rx path filter handling.
373 return &dev_rcv_lists->rx[RX_ERR]; in can_rcv_list_find()
389 return &dev_rcv_lists->rx[RX_INV]; in can_rcv_list_find()
393 return &dev_rcv_lists->rx[RX_ALL]; in can_rcv_list_find()
395 /* extra filterlists for the subscription of a single non-RTR can_id */ in can_rcv_list_find()
400 return &dev_rcv_lists->rx_eff[effhash(*can_id)]; in can_rcv_list_find()
403 return &dev_rcv_lists->rx_sff[*can_id]; in can_rcv_list_find()
408 return &dev_rcv_lists->rx[RX_FIL]; in can_rcv_list_find()
412 * can_rx_register - subscribe CAN frames from a specific interface
428 * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
439 * -ENOMEM on missing cache mem to create subscription entry
440 * -ENODEV unknown device
449 struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; in can_rx_register()
451 /* insert new receiver (dev,canid,mask) -> (func,data) */ in can_rx_register()
453 if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev))) in can_rx_register()
454 return -ENODEV; in can_rx_register()
457 return -ENODEV; in can_rx_register()
461 return -ENOMEM; in can_rx_register()
463 spin_lock_bh(&net->can.rcvlists_lock); in can_rx_register()
468 rcv->can_id = can_id; in can_rx_register()
469 rcv->mask = mask; in can_rx_register()
470 rcv->matches = 0; in can_rx_register()
471 rcv->func = func; in can_rx_register()
472 rcv->data = data; in can_rx_register()
473 rcv->ident = ident; in can_rx_register()
474 rcv->sk = sk; in can_rx_register()
476 hlist_add_head_rcu(&rcv->list, rcv_list); in can_rx_register()
477 dev_rcv_lists->entries++; in can_rx_register()
479 rcv_lists_stats->rcv_entries++; in can_rx_register()
480 rcv_lists_stats->rcv_entries_max = max(rcv_lists_stats->rcv_entries_max, in can_rx_register()
481 rcv_lists_stats->rcv_entries); in can_rx_register()
482 spin_unlock_bh(&net->can.rcvlists_lock); in can_rx_register()
488 /* can_rx_delete_receiver - rcu callback for single receiver entry removal */
492 struct sock *sk = rcv->sk; in can_rx_delete_receiver()
500 * can_rx_unregister - unsubscribe CAN frames from a specific interface
517 struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; in can_rx_unregister()
520 if (dev && dev->type != ARPHRD_CAN) in can_rx_unregister()
526 spin_lock_bh(&net->can.rcvlists_lock); in can_rx_unregister()
536 if (rcv->can_id == can_id && rcv->mask == mask && in can_rx_unregister()
537 rcv->func == func && rcv->data == data) in can_rx_unregister()
553 hlist_del_rcu(&rcv->list); in can_rx_unregister()
554 dev_rcv_lists->entries--; in can_rx_unregister()
556 if (rcv_lists_stats->rcv_entries > 0) in can_rx_unregister()
557 rcv_lists_stats->rcv_entries--; in can_rx_unregister()
560 spin_unlock_bh(&net->can.rcvlists_lock); in can_rx_unregister()
564 if (rcv->sk) in can_rx_unregister()
565 sock_hold(rcv->sk); in can_rx_unregister()
566 call_rcu(&rcv->rcu, can_rx_delete_receiver); in can_rx_unregister()
573 rcv->func(skb, rcv->data); in deliver()
574 rcv->matches++; in deliver()
581 struct can_frame *cf = (struct can_frame *)skb->data; in can_rcv_filter()
582 canid_t can_id = cf->can_id; in can_rcv_filter()
584 if (dev_rcv_lists->entries == 0) in can_rcv_filter()
589 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ERR], list) { in can_rcv_filter()
590 if (can_id & rcv->mask) { in can_rcv_filter()
599 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ALL], list) { in can_rcv_filter()
605 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_FIL], list) { in can_rcv_filter()
606 if ((can_id & rcv->mask) == rcv->can_id) { in can_rcv_filter()
612 /* check for inverted can_id/mask entries */ in can_rcv_filter()
613 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_INV], list) { in can_rcv_filter()
614 if ((can_id & rcv->mask) != rcv->can_id) { in can_rcv_filter()
620 /* check filterlists for single non-RTR can_ids */ in can_rcv_filter()
625 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_eff[effhash(can_id)], list) { in can_rcv_filter()
626 if (rcv->can_id == can_id) { in can_rcv_filter()
633 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_sff[can_id], list) { in can_rcv_filter()
646 struct can_pkg_stats *pkg_stats = net->can.pkg_stats; in can_receive()
650 atomic_long_inc(&pkg_stats->rx_frames); in can_receive()
651 atomic_long_inc(&pkg_stats->rx_frames_delta); in can_receive()
653 /* create non-zero unique skb identifier together with *skb */ in can_receive()
654 while (!(can_skb_prv(skb)->skbcnt)) in can_receive()
655 can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter); in can_receive()
660 matches = can_rcv_filter(net->can.rx_alldev_list, skb); in can_receive()
672 atomic_long_inc(&pkg_stats->matches); in can_receive()
673 atomic_long_inc(&pkg_stats->matches_delta); in can_receive()
680 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) { in can_rcv()
682 dev->type, skb->len); in can_rcv()
695 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) { in canfd_rcv()
697 dev->type, skb->len); in canfd_rcv()
710 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) { in canxl_rcv()
712 dev->type, skb->len); in canxl_rcv()
725 * can_proto_register - register CAN transport protocol
730 * -EINVAL invalid (out of range) protocol number
731 * -EBUSY protocol already in use
732 * -ENOBUF if proto_register() fails
736 int proto = cp->protocol; in can_proto_register()
741 return -EINVAL; in can_proto_register()
744 err = proto_register(cp->prot, 0); in can_proto_register()
752 err = -EBUSY; in can_proto_register()
760 proto_unregister(cp->prot); in can_proto_register()
767 * can_proto_unregister - unregister CAN transport protocol
772 int proto = cp->protocol; in can_proto_unregister()
781 proto_unregister(cp->prot); in can_proto_unregister()
787 spin_lock_init(&net->can.rcvlists_lock); in can_pernet_init()
788 net->can.rx_alldev_list = in can_pernet_init()
789 kzalloc(sizeof(*net->can.rx_alldev_list), GFP_KERNEL); in can_pernet_init()
790 if (!net->can.rx_alldev_list) in can_pernet_init()
792 net->can.pkg_stats = kzalloc(sizeof(*net->can.pkg_stats), GFP_KERNEL); in can_pernet_init()
793 if (!net->can.pkg_stats) in can_pernet_init()
795 net->can.rcv_lists_stats = kzalloc(sizeof(*net->can.rcv_lists_stats), GFP_KERNEL); in can_pernet_init()
796 if (!net->can.rcv_lists_stats) in can_pernet_init()
802 timer_setup(&net->can.stattimer, can_stat_update, in can_pernet_init()
804 mod_timer(&net->can.stattimer, in can_pernet_init()
807 net->can.pkg_stats->jiffies_init = jiffies; in can_pernet_init()
814 kfree(net->can.pkg_stats); in can_pernet_init()
816 kfree(net->can.rx_alldev_list); in can_pernet_init()
818 return -ENOMEM; in can_pernet_init()
826 del_timer_sync(&net->can.stattimer); in can_pernet_exit()
829 kfree(net->can.rx_alldev_list); in can_pernet_exit()
830 kfree(net->can.pkg_stats); in can_pernet_exit()
831 kfree(net->can.rcv_lists_stats); in can_pernet_exit()
879 return -ENOMEM; in can_init()