Lines Matching +full:function +full:- +full:mask

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()
184 * can_send - transmit a CAN frame (optional with local loopback)
192 * -ENETDOWN when the selected interface is down
193 * -ENOBUFS on full driver queue (see net_xmit_errno())
194 * -ENOMEM when local loopback failed at calling skb_clone()
195 * -EPERM when trying to send on a non-CAN interface
196 * -EMSGSIZE CAN frame size is bigger than CAN interface MTU
197 * -EINVAL when the skb->data does not contain a valid CAN frame
202 struct can_pkg_stats *pkg_stats = dev_net(skb->dev)->can.pkg_stats; in can_send()
203 int err = -EINVAL; in can_send()
206 skb->protocol = htons(ETH_P_CANXL); in can_send()
208 skb->protocol = htons(ETH_P_CAN); in can_send()
210 struct canfd_frame *cfd = (struct canfd_frame *)skb->data; in can_send()
212 skb->protocol = htons(ETH_P_CANFD); in can_send()
215 cfd->flags |= CANFD_FDF; in can_send()
221 if (unlikely(skb->len > skb->dev->mtu)) { in can_send()
222 err = -EMSGSIZE; in can_send()
226 if (unlikely(skb->dev->type != ARPHRD_CAN)) { in can_send()
227 err = -EPERM; in can_send()
231 if (unlikely(!(skb->dev->flags & IFF_UP))) { in can_send()
232 err = -ENETDOWN; in can_send()
236 skb->ip_summed = CHECKSUM_UNNECESSARY; in can_send()
246 skb->pkt_type = PACKET_LOOPBACK; in can_send()
251 * Therefore we have to ensure that skb->sk remains the in can_send()
252 * reference to the originating sock by restoring skb->sk in can_send()
256 if (!(skb->dev->flags & IFF_ECHO)) { in can_send()
263 return -ENOMEM; in can_send()
266 can_skb_set_owner(newskb, skb->sk); in can_send()
267 newskb->ip_summed = CHECKSUM_UNNECESSARY; in can_send()
268 newskb->pkt_type = PACKET_BROADCAST; in can_send()
272 skb->pkt_type = PACKET_HOST; in can_send()
289 pkg_stats->tx_frames++; in can_send()
290 pkg_stats->tx_frames_delta++; in can_send()
307 return &can_ml->dev_rcv_lists; in can_dev_rcv_lists_find()
309 return net->can.rx_alldev_list; in can_dev_rcv_lists_find()
314 * effhash - hash function for 29 bit CAN identifier reduction
323 * Hash value from 0x000 - 0x3FF ( enforced by CAN_EFF_RCV_HASH_BITS mask )
333 return hash & ((1 << CAN_EFF_RCV_HASH_BITS) - 1); in effhash()
337 * can_rcv_list_find - determine optimal filterlist inside device filter struct
339 * @mask: pointer to CAN mask of a given can_filter
344 * receive path. This function is called by service functions that need
349 * <received_can_id> & mask == can_id & mask
351 * so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe
355 * filter for error messages (CAN_ERR_FLAG bit set in mask). For error msg
359 * Pointer to optimal filterlist for the given can_id/mask pair.
360 * Consistency checked mask.
363 static struct hlist_head *can_rcv_list_find(canid_t *can_id, canid_t *mask, in can_rcv_list_find() argument
369 if (*mask & CAN_ERR_FLAG) { in can_rcv_list_find()
371 *mask &= CAN_ERR_MASK; in can_rcv_list_find()
372 return &dev_rcv_lists->rx[RX_ERR]; in can_rcv_list_find()
375 /* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */ in can_rcv_list_find()
380 if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG)) in can_rcv_list_find()
381 *mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS); in can_rcv_list_find()
384 *can_id &= *mask; in can_rcv_list_find()
388 return &dev_rcv_lists->rx[RX_INV]; in can_rcv_list_find()
390 /* mask == 0 => no condition testing at receive time */ in can_rcv_list_find()
391 if (!(*mask)) in can_rcv_list_find()
392 return &dev_rcv_lists->rx[RX_ALL]; in can_rcv_list_find()
394 /* extra filterlists for the subscription of a single non-RTR can_id */ in can_rcv_list_find()
395 if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) && in can_rcv_list_find()
398 if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) in can_rcv_list_find()
399 return &dev_rcv_lists->rx_eff[effhash(*can_id)]; in can_rcv_list_find()
401 if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS)) in can_rcv_list_find()
402 return &dev_rcv_lists->rx_sff[*can_id]; in can_rcv_list_find()
407 return &dev_rcv_lists->rx[RX_FIL]; in can_rcv_list_find()
411 * can_rx_register - subscribe CAN frames from a specific interface
415 * @mask: CAN mask (see description)
416 * @func: callback function on filter match
417 * @data: returned parameter for callback function
422 * Invokes the callback function with the received sk_buff and the given
425 * <received_can_id> & mask == can_id & mask
428 * filter for error message frames (CAN_ERR_FLAG bit set in mask).
431 * the callback function is running. The callback function must *not* free
433 * needed after the end of the callback function it must be cloned inside
434 * the callback function with skb_clone().
438 * -ENOMEM on missing cache mem to create subscription entry
439 * -ENODEV unknown device
442 canid_t mask, void (*func)(struct sk_buff *, void *), in can_rx_register() argument
448 struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; in can_rx_register()
450 /* insert new receiver (dev,canid,mask) -> (func,data) */ in can_rx_register()
452 if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev))) in can_rx_register()
453 return -ENODEV; in can_rx_register()
456 return -ENODEV; in can_rx_register()
460 return -ENOMEM; in can_rx_register()
462 spin_lock_bh(&net->can.rcvlists_lock); in can_rx_register()
465 rcv_list = can_rcv_list_find(&can_id, &mask, dev_rcv_lists); in can_rx_register()
467 rcv->can_id = can_id; in can_rx_register()
468 rcv->mask = mask; in can_rx_register()
469 rcv->matches = 0; in can_rx_register()
470 rcv->func = func; in can_rx_register()
471 rcv->data = data; in can_rx_register()
472 rcv->ident = ident; in can_rx_register()
473 rcv->sk = sk; in can_rx_register()
475 hlist_add_head_rcu(&rcv->list, rcv_list); in can_rx_register()
476 dev_rcv_lists->entries++; in can_rx_register()
478 rcv_lists_stats->rcv_entries++; in can_rx_register()
479 rcv_lists_stats->rcv_entries_max = max(rcv_lists_stats->rcv_entries_max, in can_rx_register()
480 rcv_lists_stats->rcv_entries); in can_rx_register()
481 spin_unlock_bh(&net->can.rcvlists_lock); in can_rx_register()
487 /* can_rx_delete_receiver - rcu callback for single receiver entry removal */
491 struct sock *sk = rcv->sk; in can_rx_delete_receiver()
499 * can_rx_unregister - unsubscribe CAN frames from a specific interface
503 * @mask: CAN mask
504 * @func: callback function on filter match
505 * @data: returned parameter for callback function
511 canid_t mask, void (*func)(struct sk_buff *, void *), in can_rx_unregister() argument
516 struct can_rcv_lists_stats *rcv_lists_stats = net->can.rcv_lists_stats; in can_rx_unregister()
519 if (dev && dev->type != ARPHRD_CAN) in can_rx_unregister()
525 spin_lock_bh(&net->can.rcvlists_lock); in can_rx_unregister()
528 rcv_list = can_rcv_list_find(&can_id, &mask, dev_rcv_lists); in can_rx_unregister()
535 if (rcv->can_id == can_id && rcv->mask == mask && in can_rx_unregister()
536 rcv->func == func && rcv->data == data) in can_rx_unregister()
547 pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n", in can_rx_unregister()
548 DNAME(dev), can_id, mask); in can_rx_unregister()
552 hlist_del_rcu(&rcv->list); in can_rx_unregister()
553 dev_rcv_lists->entries--; in can_rx_unregister()
555 if (rcv_lists_stats->rcv_entries > 0) in can_rx_unregister()
556 rcv_lists_stats->rcv_entries--; in can_rx_unregister()
559 spin_unlock_bh(&net->can.rcvlists_lock); in can_rx_unregister()
563 if (rcv->sk) in can_rx_unregister()
564 sock_hold(rcv->sk); in can_rx_unregister()
565 call_rcu(&rcv->rcu, can_rx_delete_receiver); in can_rx_unregister()
572 rcv->func(skb, rcv->data); in deliver()
573 rcv->matches++; in deliver()
580 struct can_frame *cf = (struct can_frame *)skb->data; in can_rcv_filter()
581 canid_t can_id = cf->can_id; in can_rcv_filter()
583 if (dev_rcv_lists->entries == 0) in can_rcv_filter()
588 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ERR], list) { in can_rcv_filter()
589 if (can_id & rcv->mask) { in can_rcv_filter()
598 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_ALL], list) { in can_rcv_filter()
603 /* check for can_id/mask entries */ in can_rcv_filter()
604 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_FIL], list) { in can_rcv_filter()
605 if ((can_id & rcv->mask) == rcv->can_id) { in can_rcv_filter()
611 /* check for inverted can_id/mask entries */ in can_rcv_filter()
612 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx[RX_INV], list) { in can_rcv_filter()
613 if ((can_id & rcv->mask) != rcv->can_id) { in can_rcv_filter()
619 /* check filterlists for single non-RTR can_ids */ in can_rcv_filter()
624 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_eff[effhash(can_id)], list) { in can_rcv_filter()
625 if (rcv->can_id == can_id) { in can_rcv_filter()
632 hlist_for_each_entry_rcu(rcv, &dev_rcv_lists->rx_sff[can_id], list) { in can_rcv_filter()
645 struct can_pkg_stats *pkg_stats = net->can.pkg_stats; in can_receive()
649 pkg_stats->rx_frames++; in can_receive()
650 pkg_stats->rx_frames_delta++; in can_receive()
652 /* create non-zero unique skb identifier together with *skb */ in can_receive()
653 while (!(can_skb_prv(skb)->skbcnt)) in can_receive()
654 can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter); in can_receive()
659 matches = can_rcv_filter(net->can.rx_alldev_list, skb); in can_receive()
671 pkg_stats->matches++; in can_receive()
672 pkg_stats->matches_delta++; in can_receive()
679 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) { in can_rcv()
681 dev->type, skb->len); in can_rcv()
694 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) { in canfd_rcv()
696 dev->type, skb->len); in canfd_rcv()
709 if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) { in canxl_rcv()
711 dev->type, skb->len); in canxl_rcv()
724 * can_proto_register - register CAN transport protocol
729 * -EINVAL invalid (out of range) protocol number
730 * -EBUSY protocol already in use
731 * -ENOBUF if proto_register() fails
735 int proto = cp->protocol; in can_proto_register()
740 return -EINVAL; in can_proto_register()
743 err = proto_register(cp->prot, 0); in can_proto_register()
751 err = -EBUSY; in can_proto_register()
759 proto_unregister(cp->prot); in can_proto_register()
766 * can_proto_unregister - unregister CAN transport protocol
771 int proto = cp->protocol; in can_proto_unregister()
780 proto_unregister(cp->prot); in can_proto_unregister()
786 spin_lock_init(&net->can.rcvlists_lock); in can_pernet_init()
787 net->can.rx_alldev_list = in can_pernet_init()
788 kzalloc(sizeof(*net->can.rx_alldev_list), GFP_KERNEL); in can_pernet_init()
789 if (!net->can.rx_alldev_list) in can_pernet_init()
791 net->can.pkg_stats = kzalloc(sizeof(*net->can.pkg_stats), GFP_KERNEL); in can_pernet_init()
792 if (!net->can.pkg_stats) in can_pernet_init()
794 net->can.rcv_lists_stats = kzalloc(sizeof(*net->can.rcv_lists_stats), GFP_KERNEL); in can_pernet_init()
795 if (!net->can.rcv_lists_stats) in can_pernet_init()
801 timer_setup(&net->can.stattimer, can_stat_update, in can_pernet_init()
803 mod_timer(&net->can.stattimer, in can_pernet_init()
806 net->can.pkg_stats->jiffies_init = jiffies; in can_pernet_init()
813 kfree(net->can.pkg_stats); in can_pernet_init()
815 kfree(net->can.rx_alldev_list); in can_pernet_init()
817 return -ENOMEM; in can_pernet_init()
825 del_timer_sync(&net->can.stattimer); in can_pernet_exit()
828 kfree(net->can.rx_alldev_list); in can_pernet_exit()
829 kfree(net->can.pkg_stats); in can_pernet_exit()
830 kfree(net->can.rcv_lists_stats); in can_pernet_exit()
876 return -ENOMEM; in can_init()