xref: /OK3568_Linux_fs/kernel/net/can/bcm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * bcm.c - Broadcast Manager to filter/send (cyclic) CAN content
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2002-2017 Volkswagen Group Electronic Research
6*4882a593Smuzhiyun  * All rights reserved.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
9*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
10*4882a593Smuzhiyun  * are met:
11*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
12*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer.
13*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce the above copyright
14*4882a593Smuzhiyun  *    notice, this list of conditions and the following disclaimer in the
15*4882a593Smuzhiyun  *    documentation and/or other materials provided with the distribution.
16*4882a593Smuzhiyun  * 3. Neither the name of Volkswagen nor the names of its contributors
17*4882a593Smuzhiyun  *    may be used to endorse or promote products derived from this software
18*4882a593Smuzhiyun  *    without specific prior written permission.
19*4882a593Smuzhiyun  *
20*4882a593Smuzhiyun  * Alternatively, provided that this notice is retained in full, this
21*4882a593Smuzhiyun  * software may be distributed under the terms of the GNU General
22*4882a593Smuzhiyun  * Public License ("GPL") version 2, in which case the provisions of the
23*4882a593Smuzhiyun  * GPL apply INSTEAD OF those given above.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * The provided data structures and external interfaces from this code
26*4882a593Smuzhiyun  * are not restricted to be used by modules with a GPL compatible license.
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29*4882a593Smuzhiyun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30*4882a593Smuzhiyun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31*4882a593Smuzhiyun  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32*4882a593Smuzhiyun  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33*4882a593Smuzhiyun  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34*4882a593Smuzhiyun  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35*4882a593Smuzhiyun  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36*4882a593Smuzhiyun  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38*4882a593Smuzhiyun  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39*4882a593Smuzhiyun  * DAMAGE.
40*4882a593Smuzhiyun  *
41*4882a593Smuzhiyun  */
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #include <linux/module.h>
44*4882a593Smuzhiyun #include <linux/init.h>
45*4882a593Smuzhiyun #include <linux/interrupt.h>
46*4882a593Smuzhiyun #include <linux/hrtimer.h>
47*4882a593Smuzhiyun #include <linux/list.h>
48*4882a593Smuzhiyun #include <linux/proc_fs.h>
49*4882a593Smuzhiyun #include <linux/seq_file.h>
50*4882a593Smuzhiyun #include <linux/uio.h>
51*4882a593Smuzhiyun #include <linux/net.h>
52*4882a593Smuzhiyun #include <linux/netdevice.h>
53*4882a593Smuzhiyun #include <linux/socket.h>
54*4882a593Smuzhiyun #include <linux/if_arp.h>
55*4882a593Smuzhiyun #include <linux/skbuff.h>
56*4882a593Smuzhiyun #include <linux/can.h>
57*4882a593Smuzhiyun #include <linux/can/core.h>
58*4882a593Smuzhiyun #include <linux/can/skb.h>
59*4882a593Smuzhiyun #include <linux/can/bcm.h>
60*4882a593Smuzhiyun #include <linux/slab.h>
61*4882a593Smuzhiyun #include <net/sock.h>
62*4882a593Smuzhiyun #include <net/net_namespace.h>
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /*
65*4882a593Smuzhiyun  * To send multiple CAN frame content within TX_SETUP or to filter
66*4882a593Smuzhiyun  * CAN messages with multiplex index within RX_SETUP, the number of
67*4882a593Smuzhiyun  * different filters is limited to 256 due to the one byte index value.
68*4882a593Smuzhiyun  */
69*4882a593Smuzhiyun #define MAX_NFRAMES 256
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* limit timers to 400 days for sending/timeouts */
72*4882a593Smuzhiyun #define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* use of last_frames[index].flags */
75*4882a593Smuzhiyun #define RX_RECV    0x40 /* received data for this element */
76*4882a593Smuzhiyun #define RX_THR     0x80 /* element not been sent due to throttle feature */
77*4882a593Smuzhiyun #define BCM_CAN_FLAGS_MASK 0x3F /* to clean private flags after usage */
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun /* get best masking value for can_rx_register() for a given single can_id */
80*4882a593Smuzhiyun #define REGMASK(id) ((id & CAN_EFF_FLAG) ? \
81*4882a593Smuzhiyun 		     (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
82*4882a593Smuzhiyun 		     (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
85*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
86*4882a593Smuzhiyun MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
87*4882a593Smuzhiyun MODULE_ALIAS("can-proto-2");
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #define BCM_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_ifindex)
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /*
92*4882a593Smuzhiyun  * easy access to the first 64 bit of can(fd)_frame payload. cp->data is
93*4882a593Smuzhiyun  * 64 bit aligned so the offset has to be multiples of 8 which is ensured
94*4882a593Smuzhiyun  * by the only callers in bcm_rx_cmp_to_index() bcm_rx_handler().
95*4882a593Smuzhiyun  */
get_u64(const struct canfd_frame * cp,int offset)96*4882a593Smuzhiyun static inline u64 get_u64(const struct canfd_frame *cp, int offset)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	return *(u64 *)(cp->data + offset);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun struct bcm_op {
102*4882a593Smuzhiyun 	struct list_head list;
103*4882a593Smuzhiyun 	struct rcu_head rcu;
104*4882a593Smuzhiyun 	int ifindex;
105*4882a593Smuzhiyun 	canid_t can_id;
106*4882a593Smuzhiyun 	u32 flags;
107*4882a593Smuzhiyun 	unsigned long frames_abs, frames_filtered;
108*4882a593Smuzhiyun 	struct bcm_timeval ival1, ival2;
109*4882a593Smuzhiyun 	struct hrtimer timer, thrtimer;
110*4882a593Smuzhiyun 	ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
111*4882a593Smuzhiyun 	int rx_ifindex;
112*4882a593Smuzhiyun 	int cfsiz;
113*4882a593Smuzhiyun 	u32 count;
114*4882a593Smuzhiyun 	u32 nframes;
115*4882a593Smuzhiyun 	u32 currframe;
116*4882a593Smuzhiyun 	/* void pointers to arrays of struct can[fd]_frame */
117*4882a593Smuzhiyun 	void *frames;
118*4882a593Smuzhiyun 	void *last_frames;
119*4882a593Smuzhiyun 	struct canfd_frame sframe;
120*4882a593Smuzhiyun 	struct canfd_frame last_sframe;
121*4882a593Smuzhiyun 	struct sock *sk;
122*4882a593Smuzhiyun 	struct net_device *rx_reg_dev;
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun struct bcm_sock {
126*4882a593Smuzhiyun 	struct sock sk;
127*4882a593Smuzhiyun 	int bound;
128*4882a593Smuzhiyun 	int ifindex;
129*4882a593Smuzhiyun 	struct list_head notifier;
130*4882a593Smuzhiyun 	struct list_head rx_ops;
131*4882a593Smuzhiyun 	struct list_head tx_ops;
132*4882a593Smuzhiyun 	unsigned long dropped_usr_msgs;
133*4882a593Smuzhiyun 	struct proc_dir_entry *bcm_proc_read;
134*4882a593Smuzhiyun 	char procname [32]; /* inode number in decimal with \0 */
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun static LIST_HEAD(bcm_notifier_list);
138*4882a593Smuzhiyun static DEFINE_SPINLOCK(bcm_notifier_lock);
139*4882a593Smuzhiyun static struct bcm_sock *bcm_busy_notifier;
140*4882a593Smuzhiyun 
bcm_sk(const struct sock * sk)141*4882a593Smuzhiyun static inline struct bcm_sock *bcm_sk(const struct sock *sk)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	return (struct bcm_sock *)sk;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
bcm_timeval_to_ktime(struct bcm_timeval tv)146*4882a593Smuzhiyun static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun 	return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /* check limitations for timeval provided by user */
bcm_is_invalid_tv(struct bcm_msg_head * msg_head)152*4882a593Smuzhiyun static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	if ((msg_head->ival1.tv_sec < 0) ||
155*4882a593Smuzhiyun 	    (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
156*4882a593Smuzhiyun 	    (msg_head->ival1.tv_usec < 0) ||
157*4882a593Smuzhiyun 	    (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
158*4882a593Smuzhiyun 	    (msg_head->ival2.tv_sec < 0) ||
159*4882a593Smuzhiyun 	    (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
160*4882a593Smuzhiyun 	    (msg_head->ival2.tv_usec < 0) ||
161*4882a593Smuzhiyun 	    (msg_head->ival2.tv_usec >= USEC_PER_SEC))
162*4882a593Smuzhiyun 		return true;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return false;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
168*4882a593Smuzhiyun #define OPSIZ sizeof(struct bcm_op)
169*4882a593Smuzhiyun #define MHSIZ sizeof(struct bcm_msg_head)
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun /*
172*4882a593Smuzhiyun  * procfs functions
173*4882a593Smuzhiyun  */
174*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_PROC_FS)
bcm_proc_getifname(struct net * net,char * result,int ifindex)175*4882a593Smuzhiyun static char *bcm_proc_getifname(struct net *net, char *result, int ifindex)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	struct net_device *dev;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (!ifindex)
180*4882a593Smuzhiyun 		return "any";
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	rcu_read_lock();
183*4882a593Smuzhiyun 	dev = dev_get_by_index_rcu(net, ifindex);
184*4882a593Smuzhiyun 	if (dev)
185*4882a593Smuzhiyun 		strcpy(result, dev->name);
186*4882a593Smuzhiyun 	else
187*4882a593Smuzhiyun 		strcpy(result, "???");
188*4882a593Smuzhiyun 	rcu_read_unlock();
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	return result;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
bcm_proc_show(struct seq_file * m,void * v)193*4882a593Smuzhiyun static int bcm_proc_show(struct seq_file *m, void *v)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun 	char ifname[IFNAMSIZ];
196*4882a593Smuzhiyun 	struct net *net = m->private;
197*4882a593Smuzhiyun 	struct sock *sk = (struct sock *)PDE_DATA(m->file->f_inode);
198*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
199*4882a593Smuzhiyun 	struct bcm_op *op;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	seq_printf(m, ">>> socket %pK", sk->sk_socket);
202*4882a593Smuzhiyun 	seq_printf(m, " / sk %pK", sk);
203*4882a593Smuzhiyun 	seq_printf(m, " / bo %pK", bo);
204*4882a593Smuzhiyun 	seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
205*4882a593Smuzhiyun 	seq_printf(m, " / bound %s", bcm_proc_getifname(net, ifname, bo->ifindex));
206*4882a593Smuzhiyun 	seq_printf(m, " <<<\n");
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	list_for_each_entry(op, &bo->rx_ops, list) {
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		unsigned long reduction;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		/* print only active entries & prevent division by zero */
213*4882a593Smuzhiyun 		if (!op->frames_abs)
214*4882a593Smuzhiyun 			continue;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 		seq_printf(m, "rx_op: %03X %-5s ", op->can_id,
217*4882a593Smuzhiyun 			   bcm_proc_getifname(net, ifname, op->ifindex));
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 		if (op->flags & CAN_FD_FRAME)
220*4882a593Smuzhiyun 			seq_printf(m, "(%u)", op->nframes);
221*4882a593Smuzhiyun 		else
222*4882a593Smuzhiyun 			seq_printf(m, "[%u]", op->nframes);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 		seq_printf(m, "%c ", (op->flags & RX_CHECK_DLC) ? 'd' : ' ');
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 		if (op->kt_ival1)
227*4882a593Smuzhiyun 			seq_printf(m, "timeo=%lld ",
228*4882a593Smuzhiyun 				   (long long)ktime_to_us(op->kt_ival1));
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 		if (op->kt_ival2)
231*4882a593Smuzhiyun 			seq_printf(m, "thr=%lld ",
232*4882a593Smuzhiyun 				   (long long)ktime_to_us(op->kt_ival2));
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 		seq_printf(m, "# recv %ld (%ld) => reduction: ",
235*4882a593Smuzhiyun 			   op->frames_filtered, op->frames_abs);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		reduction = 100 - (op->frames_filtered * 100) / op->frames_abs;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 		seq_printf(m, "%s%ld%%\n",
240*4882a593Smuzhiyun 			   (reduction == 100) ? "near " : "", reduction);
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	list_for_each_entry(op, &bo->tx_ops, list) {
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 		seq_printf(m, "tx_op: %03X %s ", op->can_id,
246*4882a593Smuzhiyun 			   bcm_proc_getifname(net, ifname, op->ifindex));
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		if (op->flags & CAN_FD_FRAME)
249*4882a593Smuzhiyun 			seq_printf(m, "(%u) ", op->nframes);
250*4882a593Smuzhiyun 		else
251*4882a593Smuzhiyun 			seq_printf(m, "[%u] ", op->nframes);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 		if (op->kt_ival1)
254*4882a593Smuzhiyun 			seq_printf(m, "t1=%lld ",
255*4882a593Smuzhiyun 				   (long long)ktime_to_us(op->kt_ival1));
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 		if (op->kt_ival2)
258*4882a593Smuzhiyun 			seq_printf(m, "t2=%lld ",
259*4882a593Smuzhiyun 				   (long long)ktime_to_us(op->kt_ival2));
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 		seq_printf(m, "# sent %ld\n", op->frames_abs);
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 	seq_putc(m, '\n');
264*4882a593Smuzhiyun 	return 0;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /*
269*4882a593Smuzhiyun  * bcm_can_tx - send the (next) CAN frame to the appropriate CAN interface
270*4882a593Smuzhiyun  *              of the given bcm tx op
271*4882a593Smuzhiyun  */
bcm_can_tx(struct bcm_op * op)272*4882a593Smuzhiyun static void bcm_can_tx(struct bcm_op *op)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun 	struct sk_buff *skb;
275*4882a593Smuzhiyun 	struct net_device *dev;
276*4882a593Smuzhiyun 	struct canfd_frame *cf = op->frames + op->cfsiz * op->currframe;
277*4882a593Smuzhiyun 	int err;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	/* no target device? => exit */
280*4882a593Smuzhiyun 	if (!op->ifindex)
281*4882a593Smuzhiyun 		return;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	dev = dev_get_by_index(sock_net(op->sk), op->ifindex);
284*4882a593Smuzhiyun 	if (!dev) {
285*4882a593Smuzhiyun 		/* RFC: should this bcm_op remove itself here? */
286*4882a593Smuzhiyun 		return;
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	skb = alloc_skb(op->cfsiz + sizeof(struct can_skb_priv), gfp_any());
290*4882a593Smuzhiyun 	if (!skb)
291*4882a593Smuzhiyun 		goto out;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	can_skb_reserve(skb);
294*4882a593Smuzhiyun 	can_skb_prv(skb)->ifindex = dev->ifindex;
295*4882a593Smuzhiyun 	can_skb_prv(skb)->skbcnt = 0;
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	skb_put_data(skb, cf, op->cfsiz);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	/* send with loopback */
300*4882a593Smuzhiyun 	skb->dev = dev;
301*4882a593Smuzhiyun 	can_skb_set_owner(skb, op->sk);
302*4882a593Smuzhiyun 	err = can_send(skb, 1);
303*4882a593Smuzhiyun 	if (!err)
304*4882a593Smuzhiyun 		op->frames_abs++;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	op->currframe++;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	/* reached last frame? */
309*4882a593Smuzhiyun 	if (op->currframe >= op->nframes)
310*4882a593Smuzhiyun 		op->currframe = 0;
311*4882a593Smuzhiyun out:
312*4882a593Smuzhiyun 	dev_put(dev);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun /*
316*4882a593Smuzhiyun  * bcm_send_to_user - send a BCM message to the userspace
317*4882a593Smuzhiyun  *                    (consisting of bcm_msg_head + x CAN frames)
318*4882a593Smuzhiyun  */
bcm_send_to_user(struct bcm_op * op,struct bcm_msg_head * head,struct canfd_frame * frames,int has_timestamp)319*4882a593Smuzhiyun static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
320*4882a593Smuzhiyun 			     struct canfd_frame *frames, int has_timestamp)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct sk_buff *skb;
323*4882a593Smuzhiyun 	struct canfd_frame *firstframe;
324*4882a593Smuzhiyun 	struct sockaddr_can *addr;
325*4882a593Smuzhiyun 	struct sock *sk = op->sk;
326*4882a593Smuzhiyun 	unsigned int datalen = head->nframes * op->cfsiz;
327*4882a593Smuzhiyun 	int err;
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	skb = alloc_skb(sizeof(*head) + datalen, gfp_any());
330*4882a593Smuzhiyun 	if (!skb)
331*4882a593Smuzhiyun 		return;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	skb_put_data(skb, head, sizeof(*head));
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (head->nframes) {
336*4882a593Smuzhiyun 		/* CAN frames starting here */
337*4882a593Smuzhiyun 		firstframe = (struct canfd_frame *)skb_tail_pointer(skb);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 		skb_put_data(skb, frames, datalen);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun 		/*
342*4882a593Smuzhiyun 		 * the BCM uses the flags-element of the canfd_frame
343*4882a593Smuzhiyun 		 * structure for internal purposes. This is only
344*4882a593Smuzhiyun 		 * relevant for updates that are generated by the
345*4882a593Smuzhiyun 		 * BCM, where nframes is 1
346*4882a593Smuzhiyun 		 */
347*4882a593Smuzhiyun 		if (head->nframes == 1)
348*4882a593Smuzhiyun 			firstframe->flags &= BCM_CAN_FLAGS_MASK;
349*4882a593Smuzhiyun 	}
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (has_timestamp) {
352*4882a593Smuzhiyun 		/* restore rx timestamp */
353*4882a593Smuzhiyun 		skb->tstamp = op->rx_stamp;
354*4882a593Smuzhiyun 	}
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	/*
357*4882a593Smuzhiyun 	 *  Put the datagram to the queue so that bcm_recvmsg() can
358*4882a593Smuzhiyun 	 *  get it from there.  We need to pass the interface index to
359*4882a593Smuzhiyun 	 *  bcm_recvmsg().  We pass a whole struct sockaddr_can in skb->cb
360*4882a593Smuzhiyun 	 *  containing the interface index.
361*4882a593Smuzhiyun 	 */
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	sock_skb_cb_check_size(sizeof(struct sockaddr_can));
364*4882a593Smuzhiyun 	addr = (struct sockaddr_can *)skb->cb;
365*4882a593Smuzhiyun 	memset(addr, 0, sizeof(*addr));
366*4882a593Smuzhiyun 	addr->can_family  = AF_CAN;
367*4882a593Smuzhiyun 	addr->can_ifindex = op->rx_ifindex;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	err = sock_queue_rcv_skb(sk, skb);
370*4882a593Smuzhiyun 	if (err < 0) {
371*4882a593Smuzhiyun 		struct bcm_sock *bo = bcm_sk(sk);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 		kfree_skb(skb);
374*4882a593Smuzhiyun 		/* don't care about overflows in this statistic */
375*4882a593Smuzhiyun 		bo->dropped_usr_msgs++;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
bcm_tx_set_expiry(struct bcm_op * op,struct hrtimer * hrt)379*4882a593Smuzhiyun static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	ktime_t ival;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (op->kt_ival1 && op->count)
384*4882a593Smuzhiyun 		ival = op->kt_ival1;
385*4882a593Smuzhiyun 	else if (op->kt_ival2)
386*4882a593Smuzhiyun 		ival = op->kt_ival2;
387*4882a593Smuzhiyun 	else
388*4882a593Smuzhiyun 		return false;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
391*4882a593Smuzhiyun 	return true;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
bcm_tx_start_timer(struct bcm_op * op)394*4882a593Smuzhiyun static void bcm_tx_start_timer(struct bcm_op *op)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	if (bcm_tx_set_expiry(op, &op->timer))
397*4882a593Smuzhiyun 		hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS_SOFT);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun /* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
bcm_tx_timeout_handler(struct hrtimer * hrtimer)401*4882a593Smuzhiyun static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
404*4882a593Smuzhiyun 	struct bcm_msg_head msg_head;
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	if (op->kt_ival1 && (op->count > 0)) {
407*4882a593Smuzhiyun 		op->count--;
408*4882a593Smuzhiyun 		if (!op->count && (op->flags & TX_COUNTEVT)) {
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 			/* create notification to user */
411*4882a593Smuzhiyun 			memset(&msg_head, 0, sizeof(msg_head));
412*4882a593Smuzhiyun 			msg_head.opcode  = TX_EXPIRED;
413*4882a593Smuzhiyun 			msg_head.flags   = op->flags;
414*4882a593Smuzhiyun 			msg_head.count   = op->count;
415*4882a593Smuzhiyun 			msg_head.ival1   = op->ival1;
416*4882a593Smuzhiyun 			msg_head.ival2   = op->ival2;
417*4882a593Smuzhiyun 			msg_head.can_id  = op->can_id;
418*4882a593Smuzhiyun 			msg_head.nframes = 0;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 			bcm_send_to_user(op, &msg_head, NULL, 0);
421*4882a593Smuzhiyun 		}
422*4882a593Smuzhiyun 		bcm_can_tx(op);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	} else if (op->kt_ival2) {
425*4882a593Smuzhiyun 		bcm_can_tx(op);
426*4882a593Smuzhiyun 	}
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	return bcm_tx_set_expiry(op, &op->timer) ?
429*4882a593Smuzhiyun 		HRTIMER_RESTART : HRTIMER_NORESTART;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun /*
433*4882a593Smuzhiyun  * bcm_rx_changed - create a RX_CHANGED notification due to changed content
434*4882a593Smuzhiyun  */
bcm_rx_changed(struct bcm_op * op,struct canfd_frame * data)435*4882a593Smuzhiyun static void bcm_rx_changed(struct bcm_op *op, struct canfd_frame *data)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	struct bcm_msg_head head;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	/* update statistics */
440*4882a593Smuzhiyun 	op->frames_filtered++;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	/* prevent statistics overflow */
443*4882a593Smuzhiyun 	if (op->frames_filtered > ULONG_MAX/100)
444*4882a593Smuzhiyun 		op->frames_filtered = op->frames_abs = 0;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	/* this element is not throttled anymore */
447*4882a593Smuzhiyun 	data->flags &= (BCM_CAN_FLAGS_MASK|RX_RECV);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	memset(&head, 0, sizeof(head));
450*4882a593Smuzhiyun 	head.opcode  = RX_CHANGED;
451*4882a593Smuzhiyun 	head.flags   = op->flags;
452*4882a593Smuzhiyun 	head.count   = op->count;
453*4882a593Smuzhiyun 	head.ival1   = op->ival1;
454*4882a593Smuzhiyun 	head.ival2   = op->ival2;
455*4882a593Smuzhiyun 	head.can_id  = op->can_id;
456*4882a593Smuzhiyun 	head.nframes = 1;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	bcm_send_to_user(op, &head, data, 1);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun  * bcm_rx_update_and_send - process a detected relevant receive content change
463*4882a593Smuzhiyun  *                          1. update the last received data
464*4882a593Smuzhiyun  *                          2. send a notification to the user (if possible)
465*4882a593Smuzhiyun  */
bcm_rx_update_and_send(struct bcm_op * op,struct canfd_frame * lastdata,const struct canfd_frame * rxdata)466*4882a593Smuzhiyun static void bcm_rx_update_and_send(struct bcm_op *op,
467*4882a593Smuzhiyun 				   struct canfd_frame *lastdata,
468*4882a593Smuzhiyun 				   const struct canfd_frame *rxdata)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	memcpy(lastdata, rxdata, op->cfsiz);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	/* mark as used and throttled by default */
473*4882a593Smuzhiyun 	lastdata->flags |= (RX_RECV|RX_THR);
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	/* throttling mode inactive ? */
476*4882a593Smuzhiyun 	if (!op->kt_ival2) {
477*4882a593Smuzhiyun 		/* send RX_CHANGED to the user immediately */
478*4882a593Smuzhiyun 		bcm_rx_changed(op, lastdata);
479*4882a593Smuzhiyun 		return;
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	/* with active throttling timer we are just done here */
483*4882a593Smuzhiyun 	if (hrtimer_active(&op->thrtimer))
484*4882a593Smuzhiyun 		return;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	/* first reception with enabled throttling mode */
487*4882a593Smuzhiyun 	if (!op->kt_lastmsg)
488*4882a593Smuzhiyun 		goto rx_changed_settime;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	/* got a second frame inside a potential throttle period? */
491*4882a593Smuzhiyun 	if (ktime_us_delta(ktime_get(), op->kt_lastmsg) <
492*4882a593Smuzhiyun 	    ktime_to_us(op->kt_ival2)) {
493*4882a593Smuzhiyun 		/* do not send the saved data - only start throttle timer */
494*4882a593Smuzhiyun 		hrtimer_start(&op->thrtimer,
495*4882a593Smuzhiyun 			      ktime_add(op->kt_lastmsg, op->kt_ival2),
496*4882a593Smuzhiyun 			      HRTIMER_MODE_ABS_SOFT);
497*4882a593Smuzhiyun 		return;
498*4882a593Smuzhiyun 	}
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun 	/* the gap was that big, that throttling was not needed here */
501*4882a593Smuzhiyun rx_changed_settime:
502*4882a593Smuzhiyun 	bcm_rx_changed(op, lastdata);
503*4882a593Smuzhiyun 	op->kt_lastmsg = ktime_get();
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun /*
507*4882a593Smuzhiyun  * bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly
508*4882a593Smuzhiyun  *                       received data stored in op->last_frames[]
509*4882a593Smuzhiyun  */
bcm_rx_cmp_to_index(struct bcm_op * op,unsigned int index,const struct canfd_frame * rxdata)510*4882a593Smuzhiyun static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index,
511*4882a593Smuzhiyun 				const struct canfd_frame *rxdata)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun 	struct canfd_frame *cf = op->frames + op->cfsiz * index;
514*4882a593Smuzhiyun 	struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
515*4882a593Smuzhiyun 	int i;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	/*
518*4882a593Smuzhiyun 	 * no one uses the MSBs of flags for comparison,
519*4882a593Smuzhiyun 	 * so we use it here to detect the first time of reception
520*4882a593Smuzhiyun 	 */
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	if (!(lcf->flags & RX_RECV)) {
523*4882a593Smuzhiyun 		/* received data for the first time => send update to user */
524*4882a593Smuzhiyun 		bcm_rx_update_and_send(op, lcf, rxdata);
525*4882a593Smuzhiyun 		return;
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	/* do a real check in CAN frame data section */
529*4882a593Smuzhiyun 	for (i = 0; i < rxdata->len; i += 8) {
530*4882a593Smuzhiyun 		if ((get_u64(cf, i) & get_u64(rxdata, i)) !=
531*4882a593Smuzhiyun 		    (get_u64(cf, i) & get_u64(lcf, i))) {
532*4882a593Smuzhiyun 			bcm_rx_update_and_send(op, lcf, rxdata);
533*4882a593Smuzhiyun 			return;
534*4882a593Smuzhiyun 		}
535*4882a593Smuzhiyun 	}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	if (op->flags & RX_CHECK_DLC) {
538*4882a593Smuzhiyun 		/* do a real check in CAN frame length */
539*4882a593Smuzhiyun 		if (rxdata->len != lcf->len) {
540*4882a593Smuzhiyun 			bcm_rx_update_and_send(op, lcf, rxdata);
541*4882a593Smuzhiyun 			return;
542*4882a593Smuzhiyun 		}
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /*
547*4882a593Smuzhiyun  * bcm_rx_starttimer - enable timeout monitoring for CAN frame reception
548*4882a593Smuzhiyun  */
bcm_rx_starttimer(struct bcm_op * op)549*4882a593Smuzhiyun static void bcm_rx_starttimer(struct bcm_op *op)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	if (op->flags & RX_NO_AUTOTIMER)
552*4882a593Smuzhiyun 		return;
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	if (op->kt_ival1)
555*4882a593Smuzhiyun 		hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL_SOFT);
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun /* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
bcm_rx_timeout_handler(struct hrtimer * hrtimer)559*4882a593Smuzhiyun static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
560*4882a593Smuzhiyun {
561*4882a593Smuzhiyun 	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
562*4882a593Smuzhiyun 	struct bcm_msg_head msg_head;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	/* if user wants to be informed, when cyclic CAN-Messages come back */
565*4882a593Smuzhiyun 	if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
566*4882a593Smuzhiyun 		/* clear received CAN frames to indicate 'nothing received' */
567*4882a593Smuzhiyun 		memset(op->last_frames, 0, op->nframes * op->cfsiz);
568*4882a593Smuzhiyun 	}
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	/* create notification to user */
571*4882a593Smuzhiyun 	memset(&msg_head, 0, sizeof(msg_head));
572*4882a593Smuzhiyun 	msg_head.opcode  = RX_TIMEOUT;
573*4882a593Smuzhiyun 	msg_head.flags   = op->flags;
574*4882a593Smuzhiyun 	msg_head.count   = op->count;
575*4882a593Smuzhiyun 	msg_head.ival1   = op->ival1;
576*4882a593Smuzhiyun 	msg_head.ival2   = op->ival2;
577*4882a593Smuzhiyun 	msg_head.can_id  = op->can_id;
578*4882a593Smuzhiyun 	msg_head.nframes = 0;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	bcm_send_to_user(op, &msg_head, NULL, 0);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	return HRTIMER_NORESTART;
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun /*
586*4882a593Smuzhiyun  * bcm_rx_do_flush - helper for bcm_rx_thr_flush
587*4882a593Smuzhiyun  */
bcm_rx_do_flush(struct bcm_op * op,unsigned int index)588*4882a593Smuzhiyun static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun 	struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	if ((op->last_frames) && (lcf->flags & RX_THR)) {
593*4882a593Smuzhiyun 		bcm_rx_changed(op, lcf);
594*4882a593Smuzhiyun 		return 1;
595*4882a593Smuzhiyun 	}
596*4882a593Smuzhiyun 	return 0;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun /*
600*4882a593Smuzhiyun  * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
601*4882a593Smuzhiyun  */
bcm_rx_thr_flush(struct bcm_op * op)602*4882a593Smuzhiyun static int bcm_rx_thr_flush(struct bcm_op *op)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	int updated = 0;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (op->nframes > 1) {
607*4882a593Smuzhiyun 		unsigned int i;
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 		/* for MUX filter we start at index 1 */
610*4882a593Smuzhiyun 		for (i = 1; i < op->nframes; i++)
611*4882a593Smuzhiyun 			updated += bcm_rx_do_flush(op, i);
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	} else {
614*4882a593Smuzhiyun 		/* for RX_FILTER_ID and simple filter */
615*4882a593Smuzhiyun 		updated += bcm_rx_do_flush(op, 0);
616*4882a593Smuzhiyun 	}
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	return updated;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun /*
622*4882a593Smuzhiyun  * bcm_rx_thr_handler - the time for blocked content updates is over now:
623*4882a593Smuzhiyun  *                      Check for throttled data and send it to the userspace
624*4882a593Smuzhiyun  */
bcm_rx_thr_handler(struct hrtimer * hrtimer)625*4882a593Smuzhiyun static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun 	struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun 	if (bcm_rx_thr_flush(op)) {
630*4882a593Smuzhiyun 		hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
631*4882a593Smuzhiyun 		return HRTIMER_RESTART;
632*4882a593Smuzhiyun 	} else {
633*4882a593Smuzhiyun 		/* rearm throttle handling */
634*4882a593Smuzhiyun 		op->kt_lastmsg = 0;
635*4882a593Smuzhiyun 		return HRTIMER_NORESTART;
636*4882a593Smuzhiyun 	}
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun /*
640*4882a593Smuzhiyun  * bcm_rx_handler - handle a CAN frame reception
641*4882a593Smuzhiyun  */
bcm_rx_handler(struct sk_buff * skb,void * data)642*4882a593Smuzhiyun static void bcm_rx_handler(struct sk_buff *skb, void *data)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun 	struct bcm_op *op = (struct bcm_op *)data;
645*4882a593Smuzhiyun 	const struct canfd_frame *rxframe = (struct canfd_frame *)skb->data;
646*4882a593Smuzhiyun 	unsigned int i;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	if (op->can_id != rxframe->can_id)
649*4882a593Smuzhiyun 		return;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 	/* make sure to handle the correct frame type (CAN / CAN FD) */
652*4882a593Smuzhiyun 	if (skb->len != op->cfsiz)
653*4882a593Smuzhiyun 		return;
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	/* disable timeout */
656*4882a593Smuzhiyun 	hrtimer_cancel(&op->timer);
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	/* save rx timestamp */
659*4882a593Smuzhiyun 	op->rx_stamp = skb->tstamp;
660*4882a593Smuzhiyun 	/* save originator for recvfrom() */
661*4882a593Smuzhiyun 	op->rx_ifindex = skb->dev->ifindex;
662*4882a593Smuzhiyun 	/* update statistics */
663*4882a593Smuzhiyun 	op->frames_abs++;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	if (op->flags & RX_RTR_FRAME) {
666*4882a593Smuzhiyun 		/* send reply for RTR-request (placed in op->frames[0]) */
667*4882a593Smuzhiyun 		bcm_can_tx(op);
668*4882a593Smuzhiyun 		return;
669*4882a593Smuzhiyun 	}
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	if (op->flags & RX_FILTER_ID) {
672*4882a593Smuzhiyun 		/* the easiest case */
673*4882a593Smuzhiyun 		bcm_rx_update_and_send(op, op->last_frames, rxframe);
674*4882a593Smuzhiyun 		goto rx_starttimer;
675*4882a593Smuzhiyun 	}
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (op->nframes == 1) {
678*4882a593Smuzhiyun 		/* simple compare with index 0 */
679*4882a593Smuzhiyun 		bcm_rx_cmp_to_index(op, 0, rxframe);
680*4882a593Smuzhiyun 		goto rx_starttimer;
681*4882a593Smuzhiyun 	}
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	if (op->nframes > 1) {
684*4882a593Smuzhiyun 		/*
685*4882a593Smuzhiyun 		 * multiplex compare
686*4882a593Smuzhiyun 		 *
687*4882a593Smuzhiyun 		 * find the first multiplex mask that fits.
688*4882a593Smuzhiyun 		 * Remark: The MUX-mask is stored in index 0 - but only the
689*4882a593Smuzhiyun 		 * first 64 bits of the frame data[] are relevant (CAN FD)
690*4882a593Smuzhiyun 		 */
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 		for (i = 1; i < op->nframes; i++) {
693*4882a593Smuzhiyun 			if ((get_u64(op->frames, 0) & get_u64(rxframe, 0)) ==
694*4882a593Smuzhiyun 			    (get_u64(op->frames, 0) &
695*4882a593Smuzhiyun 			     get_u64(op->frames + op->cfsiz * i, 0))) {
696*4882a593Smuzhiyun 				bcm_rx_cmp_to_index(op, i, rxframe);
697*4882a593Smuzhiyun 				break;
698*4882a593Smuzhiyun 			}
699*4882a593Smuzhiyun 		}
700*4882a593Smuzhiyun 	}
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun rx_starttimer:
703*4882a593Smuzhiyun 	bcm_rx_starttimer(op);
704*4882a593Smuzhiyun }
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun /*
707*4882a593Smuzhiyun  * helpers for bcm_op handling: find & delete bcm [rx|tx] op elements
708*4882a593Smuzhiyun  */
bcm_find_op(struct list_head * ops,struct bcm_msg_head * mh,int ifindex)709*4882a593Smuzhiyun static struct bcm_op *bcm_find_op(struct list_head *ops,
710*4882a593Smuzhiyun 				  struct bcm_msg_head *mh, int ifindex)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun 	struct bcm_op *op;
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	list_for_each_entry(op, ops, list) {
715*4882a593Smuzhiyun 		if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
716*4882a593Smuzhiyun 		    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME))
717*4882a593Smuzhiyun 			return op;
718*4882a593Smuzhiyun 	}
719*4882a593Smuzhiyun 
720*4882a593Smuzhiyun 	return NULL;
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun 
bcm_free_op_rcu(struct rcu_head * rcu_head)723*4882a593Smuzhiyun static void bcm_free_op_rcu(struct rcu_head *rcu_head)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun 	struct bcm_op *op = container_of(rcu_head, struct bcm_op, rcu);
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	if ((op->frames) && (op->frames != &op->sframe))
728*4882a593Smuzhiyun 		kfree(op->frames);
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun 	if ((op->last_frames) && (op->last_frames != &op->last_sframe))
731*4882a593Smuzhiyun 		kfree(op->last_frames);
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	kfree(op);
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun 
bcm_remove_op(struct bcm_op * op)736*4882a593Smuzhiyun static void bcm_remove_op(struct bcm_op *op)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun 	hrtimer_cancel(&op->timer);
739*4882a593Smuzhiyun 	hrtimer_cancel(&op->thrtimer);
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	call_rcu(&op->rcu, bcm_free_op_rcu);
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun 
bcm_rx_unreg(struct net_device * dev,struct bcm_op * op)744*4882a593Smuzhiyun static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
745*4882a593Smuzhiyun {
746*4882a593Smuzhiyun 	if (op->rx_reg_dev == dev) {
747*4882a593Smuzhiyun 		can_rx_unregister(dev_net(dev), dev, op->can_id,
748*4882a593Smuzhiyun 				  REGMASK(op->can_id), bcm_rx_handler, op);
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 		/* mark as removed subscription */
751*4882a593Smuzhiyun 		op->rx_reg_dev = NULL;
752*4882a593Smuzhiyun 	} else
753*4882a593Smuzhiyun 		printk(KERN_ERR "can-bcm: bcm_rx_unreg: registered device "
754*4882a593Smuzhiyun 		       "mismatch %p %p\n", op->rx_reg_dev, dev);
755*4882a593Smuzhiyun }
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun /*
758*4882a593Smuzhiyun  * bcm_delete_rx_op - find and remove a rx op (returns number of removed ops)
759*4882a593Smuzhiyun  */
bcm_delete_rx_op(struct list_head * ops,struct bcm_msg_head * mh,int ifindex)760*4882a593Smuzhiyun static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
761*4882a593Smuzhiyun 			    int ifindex)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun 	struct bcm_op *op, *n;
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	list_for_each_entry_safe(op, n, ops, list) {
766*4882a593Smuzhiyun 		if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
767*4882a593Smuzhiyun 		    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) {
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 			/* disable automatic timer on frame reception */
770*4882a593Smuzhiyun 			op->flags |= RX_NO_AUTOTIMER;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 			/*
773*4882a593Smuzhiyun 			 * Don't care if we're bound or not (due to netdev
774*4882a593Smuzhiyun 			 * problems) can_rx_unregister() is always a save
775*4882a593Smuzhiyun 			 * thing to do here.
776*4882a593Smuzhiyun 			 */
777*4882a593Smuzhiyun 			if (op->ifindex) {
778*4882a593Smuzhiyun 				/*
779*4882a593Smuzhiyun 				 * Only remove subscriptions that had not
780*4882a593Smuzhiyun 				 * been removed due to NETDEV_UNREGISTER
781*4882a593Smuzhiyun 				 * in bcm_notifier()
782*4882a593Smuzhiyun 				 */
783*4882a593Smuzhiyun 				if (op->rx_reg_dev) {
784*4882a593Smuzhiyun 					struct net_device *dev;
785*4882a593Smuzhiyun 
786*4882a593Smuzhiyun 					dev = dev_get_by_index(sock_net(op->sk),
787*4882a593Smuzhiyun 							       op->ifindex);
788*4882a593Smuzhiyun 					if (dev) {
789*4882a593Smuzhiyun 						bcm_rx_unreg(dev, op);
790*4882a593Smuzhiyun 						dev_put(dev);
791*4882a593Smuzhiyun 					}
792*4882a593Smuzhiyun 				}
793*4882a593Smuzhiyun 			} else
794*4882a593Smuzhiyun 				can_rx_unregister(sock_net(op->sk), NULL,
795*4882a593Smuzhiyun 						  op->can_id,
796*4882a593Smuzhiyun 						  REGMASK(op->can_id),
797*4882a593Smuzhiyun 						  bcm_rx_handler, op);
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 			list_del(&op->list);
800*4882a593Smuzhiyun 			bcm_remove_op(op);
801*4882a593Smuzhiyun 			return 1; /* done */
802*4882a593Smuzhiyun 		}
803*4882a593Smuzhiyun 	}
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	return 0; /* not found */
806*4882a593Smuzhiyun }
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun /*
809*4882a593Smuzhiyun  * bcm_delete_tx_op - find and remove a tx op (returns number of removed ops)
810*4882a593Smuzhiyun  */
bcm_delete_tx_op(struct list_head * ops,struct bcm_msg_head * mh,int ifindex)811*4882a593Smuzhiyun static int bcm_delete_tx_op(struct list_head *ops, struct bcm_msg_head *mh,
812*4882a593Smuzhiyun 			    int ifindex)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun 	struct bcm_op *op, *n;
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	list_for_each_entry_safe(op, n, ops, list) {
817*4882a593Smuzhiyun 		if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
818*4882a593Smuzhiyun 		    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME)) {
819*4882a593Smuzhiyun 			list_del(&op->list);
820*4882a593Smuzhiyun 			bcm_remove_op(op);
821*4882a593Smuzhiyun 			return 1; /* done */
822*4882a593Smuzhiyun 		}
823*4882a593Smuzhiyun 	}
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	return 0; /* not found */
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun /*
829*4882a593Smuzhiyun  * bcm_read_op - read out a bcm_op and send it to the user (for bcm_sendmsg)
830*4882a593Smuzhiyun  */
bcm_read_op(struct list_head * ops,struct bcm_msg_head * msg_head,int ifindex)831*4882a593Smuzhiyun static int bcm_read_op(struct list_head *ops, struct bcm_msg_head *msg_head,
832*4882a593Smuzhiyun 		       int ifindex)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun 	struct bcm_op *op = bcm_find_op(ops, msg_head, ifindex);
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun 	if (!op)
837*4882a593Smuzhiyun 		return -EINVAL;
838*4882a593Smuzhiyun 
839*4882a593Smuzhiyun 	/* put current values into msg_head */
840*4882a593Smuzhiyun 	msg_head->flags   = op->flags;
841*4882a593Smuzhiyun 	msg_head->count   = op->count;
842*4882a593Smuzhiyun 	msg_head->ival1   = op->ival1;
843*4882a593Smuzhiyun 	msg_head->ival2   = op->ival2;
844*4882a593Smuzhiyun 	msg_head->nframes = op->nframes;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	bcm_send_to_user(op, msg_head, op->frames, 0);
847*4882a593Smuzhiyun 
848*4882a593Smuzhiyun 	return MHSIZ;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun /*
852*4882a593Smuzhiyun  * bcm_tx_setup - create or update a bcm tx op (for bcm_sendmsg)
853*4882a593Smuzhiyun  */
bcm_tx_setup(struct bcm_msg_head * msg_head,struct msghdr * msg,int ifindex,struct sock * sk)854*4882a593Smuzhiyun static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
855*4882a593Smuzhiyun 			int ifindex, struct sock *sk)
856*4882a593Smuzhiyun {
857*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
858*4882a593Smuzhiyun 	struct bcm_op *op;
859*4882a593Smuzhiyun 	struct canfd_frame *cf;
860*4882a593Smuzhiyun 	unsigned int i;
861*4882a593Smuzhiyun 	int err;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	/* we need a real device to send frames */
864*4882a593Smuzhiyun 	if (!ifindex)
865*4882a593Smuzhiyun 		return -ENODEV;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	/* check nframes boundaries - we need at least one CAN frame */
868*4882a593Smuzhiyun 	if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
869*4882a593Smuzhiyun 		return -EINVAL;
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	/* check timeval limitations */
872*4882a593Smuzhiyun 	if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
873*4882a593Smuzhiyun 		return -EINVAL;
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 	/* check the given can_id */
876*4882a593Smuzhiyun 	op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
877*4882a593Smuzhiyun 	if (op) {
878*4882a593Smuzhiyun 		/* update existing BCM operation */
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 		/*
881*4882a593Smuzhiyun 		 * Do we need more space for the CAN frames than currently
882*4882a593Smuzhiyun 		 * allocated? -> This is a _really_ unusual use-case and
883*4882a593Smuzhiyun 		 * therefore (complexity / locking) it is not supported.
884*4882a593Smuzhiyun 		 */
885*4882a593Smuzhiyun 		if (msg_head->nframes > op->nframes)
886*4882a593Smuzhiyun 			return -E2BIG;
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 		/* update CAN frames content */
889*4882a593Smuzhiyun 		for (i = 0; i < msg_head->nframes; i++) {
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 			cf = op->frames + op->cfsiz * i;
892*4882a593Smuzhiyun 			err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 			if (op->flags & CAN_FD_FRAME) {
895*4882a593Smuzhiyun 				if (cf->len > 64)
896*4882a593Smuzhiyun 					err = -EINVAL;
897*4882a593Smuzhiyun 			} else {
898*4882a593Smuzhiyun 				if (cf->len > 8)
899*4882a593Smuzhiyun 					err = -EINVAL;
900*4882a593Smuzhiyun 			}
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 			if (err < 0)
903*4882a593Smuzhiyun 				return err;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun 			if (msg_head->flags & TX_CP_CAN_ID) {
906*4882a593Smuzhiyun 				/* copy can_id into frame */
907*4882a593Smuzhiyun 				cf->can_id = msg_head->can_id;
908*4882a593Smuzhiyun 			}
909*4882a593Smuzhiyun 		}
910*4882a593Smuzhiyun 		op->flags = msg_head->flags;
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun 	} else {
913*4882a593Smuzhiyun 		/* insert new BCM operation for the given can_id */
914*4882a593Smuzhiyun 
915*4882a593Smuzhiyun 		op = kzalloc(OPSIZ, GFP_KERNEL);
916*4882a593Smuzhiyun 		if (!op)
917*4882a593Smuzhiyun 			return -ENOMEM;
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 		op->can_id = msg_head->can_id;
920*4882a593Smuzhiyun 		op->cfsiz = CFSIZ(msg_head->flags);
921*4882a593Smuzhiyun 		op->flags = msg_head->flags;
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun 		/* create array for CAN frames and copy the data */
924*4882a593Smuzhiyun 		if (msg_head->nframes > 1) {
925*4882a593Smuzhiyun 			op->frames = kmalloc_array(msg_head->nframes,
926*4882a593Smuzhiyun 						   op->cfsiz,
927*4882a593Smuzhiyun 						   GFP_KERNEL);
928*4882a593Smuzhiyun 			if (!op->frames) {
929*4882a593Smuzhiyun 				kfree(op);
930*4882a593Smuzhiyun 				return -ENOMEM;
931*4882a593Smuzhiyun 			}
932*4882a593Smuzhiyun 		} else
933*4882a593Smuzhiyun 			op->frames = &op->sframe;
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 		for (i = 0; i < msg_head->nframes; i++) {
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 			cf = op->frames + op->cfsiz * i;
938*4882a593Smuzhiyun 			err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 			if (op->flags & CAN_FD_FRAME) {
941*4882a593Smuzhiyun 				if (cf->len > 64)
942*4882a593Smuzhiyun 					err = -EINVAL;
943*4882a593Smuzhiyun 			} else {
944*4882a593Smuzhiyun 				if (cf->len > 8)
945*4882a593Smuzhiyun 					err = -EINVAL;
946*4882a593Smuzhiyun 			}
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 			if (err < 0) {
949*4882a593Smuzhiyun 				if (op->frames != &op->sframe)
950*4882a593Smuzhiyun 					kfree(op->frames);
951*4882a593Smuzhiyun 				kfree(op);
952*4882a593Smuzhiyun 				return err;
953*4882a593Smuzhiyun 			}
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 			if (msg_head->flags & TX_CP_CAN_ID) {
956*4882a593Smuzhiyun 				/* copy can_id into frame */
957*4882a593Smuzhiyun 				cf->can_id = msg_head->can_id;
958*4882a593Smuzhiyun 			}
959*4882a593Smuzhiyun 		}
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 		/* tx_ops never compare with previous received messages */
962*4882a593Smuzhiyun 		op->last_frames = NULL;
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun 		/* bcm_can_tx / bcm_tx_timeout_handler needs this */
965*4882a593Smuzhiyun 		op->sk = sk;
966*4882a593Smuzhiyun 		op->ifindex = ifindex;
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 		/* initialize uninitialized (kzalloc) structure */
969*4882a593Smuzhiyun 		hrtimer_init(&op->timer, CLOCK_MONOTONIC,
970*4882a593Smuzhiyun 			     HRTIMER_MODE_REL_SOFT);
971*4882a593Smuzhiyun 		op->timer.function = bcm_tx_timeout_handler;
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 		/* currently unused in tx_ops */
974*4882a593Smuzhiyun 		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
975*4882a593Smuzhiyun 			     HRTIMER_MODE_REL_SOFT);
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun 		/* add this bcm_op to the list of the tx_ops */
978*4882a593Smuzhiyun 		list_add(&op->list, &bo->tx_ops);
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun 	} /* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	if (op->nframes != msg_head->nframes) {
983*4882a593Smuzhiyun 		op->nframes   = msg_head->nframes;
984*4882a593Smuzhiyun 		/* start multiple frame transmission with index 0 */
985*4882a593Smuzhiyun 		op->currframe = 0;
986*4882a593Smuzhiyun 	}
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	/* check flags */
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun 	if (op->flags & TX_RESET_MULTI_IDX) {
991*4882a593Smuzhiyun 		/* start multiple frame transmission with index 0 */
992*4882a593Smuzhiyun 		op->currframe = 0;
993*4882a593Smuzhiyun 	}
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun 	if (op->flags & SETTIMER) {
996*4882a593Smuzhiyun 		/* set timer values */
997*4882a593Smuzhiyun 		op->count = msg_head->count;
998*4882a593Smuzhiyun 		op->ival1 = msg_head->ival1;
999*4882a593Smuzhiyun 		op->ival2 = msg_head->ival2;
1000*4882a593Smuzhiyun 		op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
1001*4882a593Smuzhiyun 		op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun 		/* disable an active timer due to zero values? */
1004*4882a593Smuzhiyun 		if (!op->kt_ival1 && !op->kt_ival2)
1005*4882a593Smuzhiyun 			hrtimer_cancel(&op->timer);
1006*4882a593Smuzhiyun 	}
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun 	if (op->flags & STARTTIMER) {
1009*4882a593Smuzhiyun 		hrtimer_cancel(&op->timer);
1010*4882a593Smuzhiyun 		/* spec: send CAN frame when starting timer */
1011*4882a593Smuzhiyun 		op->flags |= TX_ANNOUNCE;
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (op->flags & TX_ANNOUNCE) {
1015*4882a593Smuzhiyun 		bcm_can_tx(op);
1016*4882a593Smuzhiyun 		if (op->count)
1017*4882a593Smuzhiyun 			op->count--;
1018*4882a593Smuzhiyun 	}
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	if (op->flags & STARTTIMER)
1021*4882a593Smuzhiyun 		bcm_tx_start_timer(op);
1022*4882a593Smuzhiyun 
1023*4882a593Smuzhiyun 	return msg_head->nframes * op->cfsiz + MHSIZ;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun /*
1027*4882a593Smuzhiyun  * bcm_rx_setup - create or update a bcm rx op (for bcm_sendmsg)
1028*4882a593Smuzhiyun  */
bcm_rx_setup(struct bcm_msg_head * msg_head,struct msghdr * msg,int ifindex,struct sock * sk)1029*4882a593Smuzhiyun static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
1030*4882a593Smuzhiyun 			int ifindex, struct sock *sk)
1031*4882a593Smuzhiyun {
1032*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
1033*4882a593Smuzhiyun 	struct bcm_op *op;
1034*4882a593Smuzhiyun 	int do_rx_register;
1035*4882a593Smuzhiyun 	int err = 0;
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	if ((msg_head->flags & RX_FILTER_ID) || (!(msg_head->nframes))) {
1038*4882a593Smuzhiyun 		/* be robust against wrong usage ... */
1039*4882a593Smuzhiyun 		msg_head->flags |= RX_FILTER_ID;
1040*4882a593Smuzhiyun 		/* ignore trailing garbage */
1041*4882a593Smuzhiyun 		msg_head->nframes = 0;
1042*4882a593Smuzhiyun 	}
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun 	/* the first element contains the mux-mask => MAX_NFRAMES + 1  */
1045*4882a593Smuzhiyun 	if (msg_head->nframes > MAX_NFRAMES + 1)
1046*4882a593Smuzhiyun 		return -EINVAL;
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun 	if ((msg_head->flags & RX_RTR_FRAME) &&
1049*4882a593Smuzhiyun 	    ((msg_head->nframes != 1) ||
1050*4882a593Smuzhiyun 	     (!(msg_head->can_id & CAN_RTR_FLAG))))
1051*4882a593Smuzhiyun 		return -EINVAL;
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	/* check timeval limitations */
1054*4882a593Smuzhiyun 	if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
1055*4882a593Smuzhiyun 		return -EINVAL;
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun 	/* check the given can_id */
1058*4882a593Smuzhiyun 	op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
1059*4882a593Smuzhiyun 	if (op) {
1060*4882a593Smuzhiyun 		/* update existing BCM operation */
1061*4882a593Smuzhiyun 
1062*4882a593Smuzhiyun 		/*
1063*4882a593Smuzhiyun 		 * Do we need more space for the CAN frames than currently
1064*4882a593Smuzhiyun 		 * allocated? -> This is a _really_ unusual use-case and
1065*4882a593Smuzhiyun 		 * therefore (complexity / locking) it is not supported.
1066*4882a593Smuzhiyun 		 */
1067*4882a593Smuzhiyun 		if (msg_head->nframes > op->nframes)
1068*4882a593Smuzhiyun 			return -E2BIG;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 		if (msg_head->nframes) {
1071*4882a593Smuzhiyun 			/* update CAN frames content */
1072*4882a593Smuzhiyun 			err = memcpy_from_msg(op->frames, msg,
1073*4882a593Smuzhiyun 					      msg_head->nframes * op->cfsiz);
1074*4882a593Smuzhiyun 			if (err < 0)
1075*4882a593Smuzhiyun 				return err;
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 			/* clear last_frames to indicate 'nothing received' */
1078*4882a593Smuzhiyun 			memset(op->last_frames, 0, msg_head->nframes * op->cfsiz);
1079*4882a593Smuzhiyun 		}
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 		op->nframes = msg_head->nframes;
1082*4882a593Smuzhiyun 		op->flags = msg_head->flags;
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun 		/* Only an update -> do not call can_rx_register() */
1085*4882a593Smuzhiyun 		do_rx_register = 0;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	} else {
1088*4882a593Smuzhiyun 		/* insert new BCM operation for the given can_id */
1089*4882a593Smuzhiyun 		op = kzalloc(OPSIZ, GFP_KERNEL);
1090*4882a593Smuzhiyun 		if (!op)
1091*4882a593Smuzhiyun 			return -ENOMEM;
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun 		op->can_id = msg_head->can_id;
1094*4882a593Smuzhiyun 		op->nframes = msg_head->nframes;
1095*4882a593Smuzhiyun 		op->cfsiz = CFSIZ(msg_head->flags);
1096*4882a593Smuzhiyun 		op->flags = msg_head->flags;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 		if (msg_head->nframes > 1) {
1099*4882a593Smuzhiyun 			/* create array for CAN frames and copy the data */
1100*4882a593Smuzhiyun 			op->frames = kmalloc_array(msg_head->nframes,
1101*4882a593Smuzhiyun 						   op->cfsiz,
1102*4882a593Smuzhiyun 						   GFP_KERNEL);
1103*4882a593Smuzhiyun 			if (!op->frames) {
1104*4882a593Smuzhiyun 				kfree(op);
1105*4882a593Smuzhiyun 				return -ENOMEM;
1106*4882a593Smuzhiyun 			}
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 			/* create and init array for received CAN frames */
1109*4882a593Smuzhiyun 			op->last_frames = kcalloc(msg_head->nframes,
1110*4882a593Smuzhiyun 						  op->cfsiz,
1111*4882a593Smuzhiyun 						  GFP_KERNEL);
1112*4882a593Smuzhiyun 			if (!op->last_frames) {
1113*4882a593Smuzhiyun 				kfree(op->frames);
1114*4882a593Smuzhiyun 				kfree(op);
1115*4882a593Smuzhiyun 				return -ENOMEM;
1116*4882a593Smuzhiyun 			}
1117*4882a593Smuzhiyun 
1118*4882a593Smuzhiyun 		} else {
1119*4882a593Smuzhiyun 			op->frames = &op->sframe;
1120*4882a593Smuzhiyun 			op->last_frames = &op->last_sframe;
1121*4882a593Smuzhiyun 		}
1122*4882a593Smuzhiyun 
1123*4882a593Smuzhiyun 		if (msg_head->nframes) {
1124*4882a593Smuzhiyun 			err = memcpy_from_msg(op->frames, msg,
1125*4882a593Smuzhiyun 					      msg_head->nframes * op->cfsiz);
1126*4882a593Smuzhiyun 			if (err < 0) {
1127*4882a593Smuzhiyun 				if (op->frames != &op->sframe)
1128*4882a593Smuzhiyun 					kfree(op->frames);
1129*4882a593Smuzhiyun 				if (op->last_frames != &op->last_sframe)
1130*4882a593Smuzhiyun 					kfree(op->last_frames);
1131*4882a593Smuzhiyun 				kfree(op);
1132*4882a593Smuzhiyun 				return err;
1133*4882a593Smuzhiyun 			}
1134*4882a593Smuzhiyun 		}
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun 		/* bcm_can_tx / bcm_tx_timeout_handler needs this */
1137*4882a593Smuzhiyun 		op->sk = sk;
1138*4882a593Smuzhiyun 		op->ifindex = ifindex;
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun 		/* ifindex for timeout events w/o previous frame reception */
1141*4882a593Smuzhiyun 		op->rx_ifindex = ifindex;
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun 		/* initialize uninitialized (kzalloc) structure */
1144*4882a593Smuzhiyun 		hrtimer_init(&op->timer, CLOCK_MONOTONIC,
1145*4882a593Smuzhiyun 			     HRTIMER_MODE_REL_SOFT);
1146*4882a593Smuzhiyun 		op->timer.function = bcm_rx_timeout_handler;
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun 		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC,
1149*4882a593Smuzhiyun 			     HRTIMER_MODE_REL_SOFT);
1150*4882a593Smuzhiyun 		op->thrtimer.function = bcm_rx_thr_handler;
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 		/* add this bcm_op to the list of the rx_ops */
1153*4882a593Smuzhiyun 		list_add(&op->list, &bo->rx_ops);
1154*4882a593Smuzhiyun 
1155*4882a593Smuzhiyun 		/* call can_rx_register() */
1156*4882a593Smuzhiyun 		do_rx_register = 1;
1157*4882a593Smuzhiyun 
1158*4882a593Smuzhiyun 	} /* if ((op = bcm_find_op(&bo->rx_ops, msg_head->can_id, ifindex))) */
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun 	/* check flags */
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun 	if (op->flags & RX_RTR_FRAME) {
1163*4882a593Smuzhiyun 		struct canfd_frame *frame0 = op->frames;
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun 		/* no timers in RTR-mode */
1166*4882a593Smuzhiyun 		hrtimer_cancel(&op->thrtimer);
1167*4882a593Smuzhiyun 		hrtimer_cancel(&op->timer);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 		/*
1170*4882a593Smuzhiyun 		 * funny feature in RX(!)_SETUP only for RTR-mode:
1171*4882a593Smuzhiyun 		 * copy can_id into frame BUT without RTR-flag to
1172*4882a593Smuzhiyun 		 * prevent a full-load-loopback-test ... ;-]
1173*4882a593Smuzhiyun 		 */
1174*4882a593Smuzhiyun 		if ((op->flags & TX_CP_CAN_ID) ||
1175*4882a593Smuzhiyun 		    (frame0->can_id == op->can_id))
1176*4882a593Smuzhiyun 			frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
1177*4882a593Smuzhiyun 
1178*4882a593Smuzhiyun 	} else {
1179*4882a593Smuzhiyun 		if (op->flags & SETTIMER) {
1180*4882a593Smuzhiyun 
1181*4882a593Smuzhiyun 			/* set timer value */
1182*4882a593Smuzhiyun 			op->ival1 = msg_head->ival1;
1183*4882a593Smuzhiyun 			op->ival2 = msg_head->ival2;
1184*4882a593Smuzhiyun 			op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
1185*4882a593Smuzhiyun 			op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun 			/* disable an active timer due to zero value? */
1188*4882a593Smuzhiyun 			if (!op->kt_ival1)
1189*4882a593Smuzhiyun 				hrtimer_cancel(&op->timer);
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 			/*
1192*4882a593Smuzhiyun 			 * In any case cancel the throttle timer, flush
1193*4882a593Smuzhiyun 			 * potentially blocked msgs and reset throttle handling
1194*4882a593Smuzhiyun 			 */
1195*4882a593Smuzhiyun 			op->kt_lastmsg = 0;
1196*4882a593Smuzhiyun 			hrtimer_cancel(&op->thrtimer);
1197*4882a593Smuzhiyun 			bcm_rx_thr_flush(op);
1198*4882a593Smuzhiyun 		}
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun 		if ((op->flags & STARTTIMER) && op->kt_ival1)
1201*4882a593Smuzhiyun 			hrtimer_start(&op->timer, op->kt_ival1,
1202*4882a593Smuzhiyun 				      HRTIMER_MODE_REL_SOFT);
1203*4882a593Smuzhiyun 	}
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 	/* now we can register for can_ids, if we added a new bcm_op */
1206*4882a593Smuzhiyun 	if (do_rx_register) {
1207*4882a593Smuzhiyun 		if (ifindex) {
1208*4882a593Smuzhiyun 			struct net_device *dev;
1209*4882a593Smuzhiyun 
1210*4882a593Smuzhiyun 			dev = dev_get_by_index(sock_net(sk), ifindex);
1211*4882a593Smuzhiyun 			if (dev) {
1212*4882a593Smuzhiyun 				err = can_rx_register(sock_net(sk), dev,
1213*4882a593Smuzhiyun 						      op->can_id,
1214*4882a593Smuzhiyun 						      REGMASK(op->can_id),
1215*4882a593Smuzhiyun 						      bcm_rx_handler, op,
1216*4882a593Smuzhiyun 						      "bcm", sk);
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun 				op->rx_reg_dev = dev;
1219*4882a593Smuzhiyun 				dev_put(dev);
1220*4882a593Smuzhiyun 			}
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 		} else
1223*4882a593Smuzhiyun 			err = can_rx_register(sock_net(sk), NULL, op->can_id,
1224*4882a593Smuzhiyun 					      REGMASK(op->can_id),
1225*4882a593Smuzhiyun 					      bcm_rx_handler, op, "bcm", sk);
1226*4882a593Smuzhiyun 		if (err) {
1227*4882a593Smuzhiyun 			/* this bcm rx op is broken -> remove it */
1228*4882a593Smuzhiyun 			list_del(&op->list);
1229*4882a593Smuzhiyun 			bcm_remove_op(op);
1230*4882a593Smuzhiyun 			return err;
1231*4882a593Smuzhiyun 		}
1232*4882a593Smuzhiyun 	}
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	return msg_head->nframes * op->cfsiz + MHSIZ;
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun /*
1238*4882a593Smuzhiyun  * bcm_tx_send - send a single CAN frame to the CAN interface (for bcm_sendmsg)
1239*4882a593Smuzhiyun  */
bcm_tx_send(struct msghdr * msg,int ifindex,struct sock * sk,int cfsiz)1240*4882a593Smuzhiyun static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk,
1241*4882a593Smuzhiyun 		       int cfsiz)
1242*4882a593Smuzhiyun {
1243*4882a593Smuzhiyun 	struct sk_buff *skb;
1244*4882a593Smuzhiyun 	struct net_device *dev;
1245*4882a593Smuzhiyun 	int err;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	/* we need a real device to send frames */
1248*4882a593Smuzhiyun 	if (!ifindex)
1249*4882a593Smuzhiyun 		return -ENODEV;
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun 	skb = alloc_skb(cfsiz + sizeof(struct can_skb_priv), GFP_KERNEL);
1252*4882a593Smuzhiyun 	if (!skb)
1253*4882a593Smuzhiyun 		return -ENOMEM;
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun 	can_skb_reserve(skb);
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun 	err = memcpy_from_msg(skb_put(skb, cfsiz), msg, cfsiz);
1258*4882a593Smuzhiyun 	if (err < 0) {
1259*4882a593Smuzhiyun 		kfree_skb(skb);
1260*4882a593Smuzhiyun 		return err;
1261*4882a593Smuzhiyun 	}
1262*4882a593Smuzhiyun 
1263*4882a593Smuzhiyun 	dev = dev_get_by_index(sock_net(sk), ifindex);
1264*4882a593Smuzhiyun 	if (!dev) {
1265*4882a593Smuzhiyun 		kfree_skb(skb);
1266*4882a593Smuzhiyun 		return -ENODEV;
1267*4882a593Smuzhiyun 	}
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun 	can_skb_prv(skb)->ifindex = dev->ifindex;
1270*4882a593Smuzhiyun 	can_skb_prv(skb)->skbcnt = 0;
1271*4882a593Smuzhiyun 	skb->dev = dev;
1272*4882a593Smuzhiyun 	can_skb_set_owner(skb, sk);
1273*4882a593Smuzhiyun 	err = can_send(skb, 1); /* send with loopback */
1274*4882a593Smuzhiyun 	dev_put(dev);
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun 	if (err)
1277*4882a593Smuzhiyun 		return err;
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun 	return cfsiz + MHSIZ;
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun 
1282*4882a593Smuzhiyun /*
1283*4882a593Smuzhiyun  * bcm_sendmsg - process BCM commands (opcodes) from the userspace
1284*4882a593Smuzhiyun  */
bcm_sendmsg(struct socket * sock,struct msghdr * msg,size_t size)1285*4882a593Smuzhiyun static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
1286*4882a593Smuzhiyun {
1287*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
1288*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
1289*4882a593Smuzhiyun 	int ifindex = bo->ifindex; /* default ifindex for this bcm_op */
1290*4882a593Smuzhiyun 	struct bcm_msg_head msg_head;
1291*4882a593Smuzhiyun 	int cfsiz;
1292*4882a593Smuzhiyun 	int ret; /* read bytes or error codes as return value */
1293*4882a593Smuzhiyun 
1294*4882a593Smuzhiyun 	if (!bo->bound)
1295*4882a593Smuzhiyun 		return -ENOTCONN;
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	/* check for valid message length from userspace */
1298*4882a593Smuzhiyun 	if (size < MHSIZ)
1299*4882a593Smuzhiyun 		return -EINVAL;
1300*4882a593Smuzhiyun 
1301*4882a593Smuzhiyun 	/* read message head information */
1302*4882a593Smuzhiyun 	ret = memcpy_from_msg((u8 *)&msg_head, msg, MHSIZ);
1303*4882a593Smuzhiyun 	if (ret < 0)
1304*4882a593Smuzhiyun 		return ret;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	cfsiz = CFSIZ(msg_head.flags);
1307*4882a593Smuzhiyun 	if ((size - MHSIZ) % cfsiz)
1308*4882a593Smuzhiyun 		return -EINVAL;
1309*4882a593Smuzhiyun 
1310*4882a593Smuzhiyun 	/* check for alternative ifindex for this bcm_op */
1311*4882a593Smuzhiyun 
1312*4882a593Smuzhiyun 	if (!ifindex && msg->msg_name) {
1313*4882a593Smuzhiyun 		/* no bound device as default => check msg_name */
1314*4882a593Smuzhiyun 		DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name);
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun 		if (msg->msg_namelen < BCM_MIN_NAMELEN)
1317*4882a593Smuzhiyun 			return -EINVAL;
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun 		if (addr->can_family != AF_CAN)
1320*4882a593Smuzhiyun 			return -EINVAL;
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun 		/* ifindex from sendto() */
1323*4882a593Smuzhiyun 		ifindex = addr->can_ifindex;
1324*4882a593Smuzhiyun 
1325*4882a593Smuzhiyun 		if (ifindex) {
1326*4882a593Smuzhiyun 			struct net_device *dev;
1327*4882a593Smuzhiyun 
1328*4882a593Smuzhiyun 			dev = dev_get_by_index(sock_net(sk), ifindex);
1329*4882a593Smuzhiyun 			if (!dev)
1330*4882a593Smuzhiyun 				return -ENODEV;
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 			if (dev->type != ARPHRD_CAN) {
1333*4882a593Smuzhiyun 				dev_put(dev);
1334*4882a593Smuzhiyun 				return -ENODEV;
1335*4882a593Smuzhiyun 			}
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 			dev_put(dev);
1338*4882a593Smuzhiyun 		}
1339*4882a593Smuzhiyun 	}
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 	lock_sock(sk);
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	switch (msg_head.opcode) {
1344*4882a593Smuzhiyun 
1345*4882a593Smuzhiyun 	case TX_SETUP:
1346*4882a593Smuzhiyun 		ret = bcm_tx_setup(&msg_head, msg, ifindex, sk);
1347*4882a593Smuzhiyun 		break;
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 	case RX_SETUP:
1350*4882a593Smuzhiyun 		ret = bcm_rx_setup(&msg_head, msg, ifindex, sk);
1351*4882a593Smuzhiyun 		break;
1352*4882a593Smuzhiyun 
1353*4882a593Smuzhiyun 	case TX_DELETE:
1354*4882a593Smuzhiyun 		if (bcm_delete_tx_op(&bo->tx_ops, &msg_head, ifindex))
1355*4882a593Smuzhiyun 			ret = MHSIZ;
1356*4882a593Smuzhiyun 		else
1357*4882a593Smuzhiyun 			ret = -EINVAL;
1358*4882a593Smuzhiyun 		break;
1359*4882a593Smuzhiyun 
1360*4882a593Smuzhiyun 	case RX_DELETE:
1361*4882a593Smuzhiyun 		if (bcm_delete_rx_op(&bo->rx_ops, &msg_head, ifindex))
1362*4882a593Smuzhiyun 			ret = MHSIZ;
1363*4882a593Smuzhiyun 		else
1364*4882a593Smuzhiyun 			ret = -EINVAL;
1365*4882a593Smuzhiyun 		break;
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	case TX_READ:
1368*4882a593Smuzhiyun 		/* reuse msg_head for the reply to TX_READ */
1369*4882a593Smuzhiyun 		msg_head.opcode  = TX_STATUS;
1370*4882a593Smuzhiyun 		ret = bcm_read_op(&bo->tx_ops, &msg_head, ifindex);
1371*4882a593Smuzhiyun 		break;
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun 	case RX_READ:
1374*4882a593Smuzhiyun 		/* reuse msg_head for the reply to RX_READ */
1375*4882a593Smuzhiyun 		msg_head.opcode  = RX_STATUS;
1376*4882a593Smuzhiyun 		ret = bcm_read_op(&bo->rx_ops, &msg_head, ifindex);
1377*4882a593Smuzhiyun 		break;
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	case TX_SEND:
1380*4882a593Smuzhiyun 		/* we need exactly one CAN frame behind the msg head */
1381*4882a593Smuzhiyun 		if ((msg_head.nframes != 1) || (size != cfsiz + MHSIZ))
1382*4882a593Smuzhiyun 			ret = -EINVAL;
1383*4882a593Smuzhiyun 		else
1384*4882a593Smuzhiyun 			ret = bcm_tx_send(msg, ifindex, sk, cfsiz);
1385*4882a593Smuzhiyun 		break;
1386*4882a593Smuzhiyun 
1387*4882a593Smuzhiyun 	default:
1388*4882a593Smuzhiyun 		ret = -EINVAL;
1389*4882a593Smuzhiyun 		break;
1390*4882a593Smuzhiyun 	}
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun 	release_sock(sk);
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun 	return ret;
1395*4882a593Smuzhiyun }
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun /*
1398*4882a593Smuzhiyun  * notification handler for netdevice status changes
1399*4882a593Smuzhiyun  */
bcm_notify(struct bcm_sock * bo,unsigned long msg,struct net_device * dev)1400*4882a593Smuzhiyun static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
1401*4882a593Smuzhiyun 		       struct net_device *dev)
1402*4882a593Smuzhiyun {
1403*4882a593Smuzhiyun 	struct sock *sk = &bo->sk;
1404*4882a593Smuzhiyun 	struct bcm_op *op;
1405*4882a593Smuzhiyun 	int notify_enodev = 0;
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	if (!net_eq(dev_net(dev), sock_net(sk)))
1408*4882a593Smuzhiyun 		return;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	switch (msg) {
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	case NETDEV_UNREGISTER:
1413*4882a593Smuzhiyun 		lock_sock(sk);
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun 		/* remove device specific receive entries */
1416*4882a593Smuzhiyun 		list_for_each_entry(op, &bo->rx_ops, list)
1417*4882a593Smuzhiyun 			if (op->rx_reg_dev == dev)
1418*4882a593Smuzhiyun 				bcm_rx_unreg(dev, op);
1419*4882a593Smuzhiyun 
1420*4882a593Smuzhiyun 		/* remove device reference, if this is our bound device */
1421*4882a593Smuzhiyun 		if (bo->bound && bo->ifindex == dev->ifindex) {
1422*4882a593Smuzhiyun 			bo->bound   = 0;
1423*4882a593Smuzhiyun 			bo->ifindex = 0;
1424*4882a593Smuzhiyun 			notify_enodev = 1;
1425*4882a593Smuzhiyun 		}
1426*4882a593Smuzhiyun 
1427*4882a593Smuzhiyun 		release_sock(sk);
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 		if (notify_enodev) {
1430*4882a593Smuzhiyun 			sk->sk_err = ENODEV;
1431*4882a593Smuzhiyun 			if (!sock_flag(sk, SOCK_DEAD))
1432*4882a593Smuzhiyun 				sk->sk_error_report(sk);
1433*4882a593Smuzhiyun 		}
1434*4882a593Smuzhiyun 		break;
1435*4882a593Smuzhiyun 
1436*4882a593Smuzhiyun 	case NETDEV_DOWN:
1437*4882a593Smuzhiyun 		if (bo->bound && bo->ifindex == dev->ifindex) {
1438*4882a593Smuzhiyun 			sk->sk_err = ENETDOWN;
1439*4882a593Smuzhiyun 			if (!sock_flag(sk, SOCK_DEAD))
1440*4882a593Smuzhiyun 				sk->sk_error_report(sk);
1441*4882a593Smuzhiyun 		}
1442*4882a593Smuzhiyun 	}
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun 
bcm_notifier(struct notifier_block * nb,unsigned long msg,void * ptr)1445*4882a593Smuzhiyun static int bcm_notifier(struct notifier_block *nb, unsigned long msg,
1446*4882a593Smuzhiyun 			void *ptr)
1447*4882a593Smuzhiyun {
1448*4882a593Smuzhiyun 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun 	if (dev->type != ARPHRD_CAN)
1451*4882a593Smuzhiyun 		return NOTIFY_DONE;
1452*4882a593Smuzhiyun 	if (msg != NETDEV_UNREGISTER && msg != NETDEV_DOWN)
1453*4882a593Smuzhiyun 		return NOTIFY_DONE;
1454*4882a593Smuzhiyun 	if (unlikely(bcm_busy_notifier)) /* Check for reentrant bug. */
1455*4882a593Smuzhiyun 		return NOTIFY_DONE;
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun 	spin_lock(&bcm_notifier_lock);
1458*4882a593Smuzhiyun 	list_for_each_entry(bcm_busy_notifier, &bcm_notifier_list, notifier) {
1459*4882a593Smuzhiyun 		spin_unlock(&bcm_notifier_lock);
1460*4882a593Smuzhiyun 		bcm_notify(bcm_busy_notifier, msg, dev);
1461*4882a593Smuzhiyun 		spin_lock(&bcm_notifier_lock);
1462*4882a593Smuzhiyun 	}
1463*4882a593Smuzhiyun 	bcm_busy_notifier = NULL;
1464*4882a593Smuzhiyun 	spin_unlock(&bcm_notifier_lock);
1465*4882a593Smuzhiyun 	return NOTIFY_DONE;
1466*4882a593Smuzhiyun }
1467*4882a593Smuzhiyun 
1468*4882a593Smuzhiyun /*
1469*4882a593Smuzhiyun  * initial settings for all BCM sockets to be set at socket creation time
1470*4882a593Smuzhiyun  */
bcm_init(struct sock * sk)1471*4882a593Smuzhiyun static int bcm_init(struct sock *sk)
1472*4882a593Smuzhiyun {
1473*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun 	bo->bound            = 0;
1476*4882a593Smuzhiyun 	bo->ifindex          = 0;
1477*4882a593Smuzhiyun 	bo->dropped_usr_msgs = 0;
1478*4882a593Smuzhiyun 	bo->bcm_proc_read    = NULL;
1479*4882a593Smuzhiyun 
1480*4882a593Smuzhiyun 	INIT_LIST_HEAD(&bo->tx_ops);
1481*4882a593Smuzhiyun 	INIT_LIST_HEAD(&bo->rx_ops);
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	/* set notifier */
1484*4882a593Smuzhiyun 	spin_lock(&bcm_notifier_lock);
1485*4882a593Smuzhiyun 	list_add_tail(&bo->notifier, &bcm_notifier_list);
1486*4882a593Smuzhiyun 	spin_unlock(&bcm_notifier_lock);
1487*4882a593Smuzhiyun 
1488*4882a593Smuzhiyun 	return 0;
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun 
1491*4882a593Smuzhiyun /*
1492*4882a593Smuzhiyun  * standard socket functions
1493*4882a593Smuzhiyun  */
bcm_release(struct socket * sock)1494*4882a593Smuzhiyun static int bcm_release(struct socket *sock)
1495*4882a593Smuzhiyun {
1496*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
1497*4882a593Smuzhiyun 	struct net *net;
1498*4882a593Smuzhiyun 	struct bcm_sock *bo;
1499*4882a593Smuzhiyun 	struct bcm_op *op, *next;
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun 	if (!sk)
1502*4882a593Smuzhiyun 		return 0;
1503*4882a593Smuzhiyun 
1504*4882a593Smuzhiyun 	net = sock_net(sk);
1505*4882a593Smuzhiyun 	bo = bcm_sk(sk);
1506*4882a593Smuzhiyun 
1507*4882a593Smuzhiyun 	/* remove bcm_ops, timer, rx_unregister(), etc. */
1508*4882a593Smuzhiyun 
1509*4882a593Smuzhiyun 	spin_lock(&bcm_notifier_lock);
1510*4882a593Smuzhiyun 	while (bcm_busy_notifier == bo) {
1511*4882a593Smuzhiyun 		spin_unlock(&bcm_notifier_lock);
1512*4882a593Smuzhiyun 		schedule_timeout_uninterruptible(1);
1513*4882a593Smuzhiyun 		spin_lock(&bcm_notifier_lock);
1514*4882a593Smuzhiyun 	}
1515*4882a593Smuzhiyun 	list_del(&bo->notifier);
1516*4882a593Smuzhiyun 	spin_unlock(&bcm_notifier_lock);
1517*4882a593Smuzhiyun 
1518*4882a593Smuzhiyun 	lock_sock(sk);
1519*4882a593Smuzhiyun 
1520*4882a593Smuzhiyun 	list_for_each_entry_safe(op, next, &bo->tx_ops, list)
1521*4882a593Smuzhiyun 		bcm_remove_op(op);
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun 	list_for_each_entry_safe(op, next, &bo->rx_ops, list) {
1524*4882a593Smuzhiyun 		/*
1525*4882a593Smuzhiyun 		 * Don't care if we're bound or not (due to netdev problems)
1526*4882a593Smuzhiyun 		 * can_rx_unregister() is always a save thing to do here.
1527*4882a593Smuzhiyun 		 */
1528*4882a593Smuzhiyun 		if (op->ifindex) {
1529*4882a593Smuzhiyun 			/*
1530*4882a593Smuzhiyun 			 * Only remove subscriptions that had not
1531*4882a593Smuzhiyun 			 * been removed due to NETDEV_UNREGISTER
1532*4882a593Smuzhiyun 			 * in bcm_notifier()
1533*4882a593Smuzhiyun 			 */
1534*4882a593Smuzhiyun 			if (op->rx_reg_dev) {
1535*4882a593Smuzhiyun 				struct net_device *dev;
1536*4882a593Smuzhiyun 
1537*4882a593Smuzhiyun 				dev = dev_get_by_index(net, op->ifindex);
1538*4882a593Smuzhiyun 				if (dev) {
1539*4882a593Smuzhiyun 					bcm_rx_unreg(dev, op);
1540*4882a593Smuzhiyun 					dev_put(dev);
1541*4882a593Smuzhiyun 				}
1542*4882a593Smuzhiyun 			}
1543*4882a593Smuzhiyun 		} else
1544*4882a593Smuzhiyun 			can_rx_unregister(net, NULL, op->can_id,
1545*4882a593Smuzhiyun 					  REGMASK(op->can_id),
1546*4882a593Smuzhiyun 					  bcm_rx_handler, op);
1547*4882a593Smuzhiyun 
1548*4882a593Smuzhiyun 	}
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun 	synchronize_rcu();
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun 	list_for_each_entry_safe(op, next, &bo->rx_ops, list)
1553*4882a593Smuzhiyun 		bcm_remove_op(op);
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_PROC_FS)
1556*4882a593Smuzhiyun 	/* remove procfs entry */
1557*4882a593Smuzhiyun 	if (net->can.bcmproc_dir && bo->bcm_proc_read)
1558*4882a593Smuzhiyun 		remove_proc_entry(bo->procname, net->can.bcmproc_dir);
1559*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
1560*4882a593Smuzhiyun 
1561*4882a593Smuzhiyun 	/* remove device reference */
1562*4882a593Smuzhiyun 	if (bo->bound) {
1563*4882a593Smuzhiyun 		bo->bound   = 0;
1564*4882a593Smuzhiyun 		bo->ifindex = 0;
1565*4882a593Smuzhiyun 	}
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	sock_orphan(sk);
1568*4882a593Smuzhiyun 	sock->sk = NULL;
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun 	release_sock(sk);
1571*4882a593Smuzhiyun 	sock_put(sk);
1572*4882a593Smuzhiyun 
1573*4882a593Smuzhiyun 	return 0;
1574*4882a593Smuzhiyun }
1575*4882a593Smuzhiyun 
bcm_connect(struct socket * sock,struct sockaddr * uaddr,int len,int flags)1576*4882a593Smuzhiyun static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
1577*4882a593Smuzhiyun 		       int flags)
1578*4882a593Smuzhiyun {
1579*4882a593Smuzhiyun 	struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
1580*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
1581*4882a593Smuzhiyun 	struct bcm_sock *bo = bcm_sk(sk);
1582*4882a593Smuzhiyun 	struct net *net = sock_net(sk);
1583*4882a593Smuzhiyun 	int ret = 0;
1584*4882a593Smuzhiyun 
1585*4882a593Smuzhiyun 	if (len < BCM_MIN_NAMELEN)
1586*4882a593Smuzhiyun 		return -EINVAL;
1587*4882a593Smuzhiyun 
1588*4882a593Smuzhiyun 	lock_sock(sk);
1589*4882a593Smuzhiyun 
1590*4882a593Smuzhiyun 	if (bo->bound) {
1591*4882a593Smuzhiyun 		ret = -EISCONN;
1592*4882a593Smuzhiyun 		goto fail;
1593*4882a593Smuzhiyun 	}
1594*4882a593Smuzhiyun 
1595*4882a593Smuzhiyun 	/* bind a device to this socket */
1596*4882a593Smuzhiyun 	if (addr->can_ifindex) {
1597*4882a593Smuzhiyun 		struct net_device *dev;
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun 		dev = dev_get_by_index(net, addr->can_ifindex);
1600*4882a593Smuzhiyun 		if (!dev) {
1601*4882a593Smuzhiyun 			ret = -ENODEV;
1602*4882a593Smuzhiyun 			goto fail;
1603*4882a593Smuzhiyun 		}
1604*4882a593Smuzhiyun 		if (dev->type != ARPHRD_CAN) {
1605*4882a593Smuzhiyun 			dev_put(dev);
1606*4882a593Smuzhiyun 			ret = -ENODEV;
1607*4882a593Smuzhiyun 			goto fail;
1608*4882a593Smuzhiyun 		}
1609*4882a593Smuzhiyun 
1610*4882a593Smuzhiyun 		bo->ifindex = dev->ifindex;
1611*4882a593Smuzhiyun 		dev_put(dev);
1612*4882a593Smuzhiyun 
1613*4882a593Smuzhiyun 	} else {
1614*4882a593Smuzhiyun 		/* no interface reference for ifindex = 0 ('any' CAN device) */
1615*4882a593Smuzhiyun 		bo->ifindex = 0;
1616*4882a593Smuzhiyun 	}
1617*4882a593Smuzhiyun 
1618*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_PROC_FS)
1619*4882a593Smuzhiyun 	if (net->can.bcmproc_dir) {
1620*4882a593Smuzhiyun 		/* unique socket address as filename */
1621*4882a593Smuzhiyun 		sprintf(bo->procname, "%lu", sock_i_ino(sk));
1622*4882a593Smuzhiyun 		bo->bcm_proc_read = proc_create_net_single(bo->procname, 0644,
1623*4882a593Smuzhiyun 						     net->can.bcmproc_dir,
1624*4882a593Smuzhiyun 						     bcm_proc_show, sk);
1625*4882a593Smuzhiyun 		if (!bo->bcm_proc_read) {
1626*4882a593Smuzhiyun 			ret = -ENOMEM;
1627*4882a593Smuzhiyun 			goto fail;
1628*4882a593Smuzhiyun 		}
1629*4882a593Smuzhiyun 	}
1630*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun 	bo->bound = 1;
1633*4882a593Smuzhiyun 
1634*4882a593Smuzhiyun fail:
1635*4882a593Smuzhiyun 	release_sock(sk);
1636*4882a593Smuzhiyun 
1637*4882a593Smuzhiyun 	return ret;
1638*4882a593Smuzhiyun }
1639*4882a593Smuzhiyun 
bcm_recvmsg(struct socket * sock,struct msghdr * msg,size_t size,int flags)1640*4882a593Smuzhiyun static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
1641*4882a593Smuzhiyun 		       int flags)
1642*4882a593Smuzhiyun {
1643*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
1644*4882a593Smuzhiyun 	struct sk_buff *skb;
1645*4882a593Smuzhiyun 	int error = 0;
1646*4882a593Smuzhiyun 	int noblock;
1647*4882a593Smuzhiyun 	int err;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 	noblock =  flags & MSG_DONTWAIT;
1650*4882a593Smuzhiyun 	flags   &= ~MSG_DONTWAIT;
1651*4882a593Smuzhiyun 	skb = skb_recv_datagram(sk, flags, noblock, &error);
1652*4882a593Smuzhiyun 	if (!skb)
1653*4882a593Smuzhiyun 		return error;
1654*4882a593Smuzhiyun 
1655*4882a593Smuzhiyun 	if (skb->len < size)
1656*4882a593Smuzhiyun 		size = skb->len;
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 	err = memcpy_to_msg(msg, skb->data, size);
1659*4882a593Smuzhiyun 	if (err < 0) {
1660*4882a593Smuzhiyun 		skb_free_datagram(sk, skb);
1661*4882a593Smuzhiyun 		return err;
1662*4882a593Smuzhiyun 	}
1663*4882a593Smuzhiyun 
1664*4882a593Smuzhiyun 	sock_recv_ts_and_drops(msg, sk, skb);
1665*4882a593Smuzhiyun 
1666*4882a593Smuzhiyun 	if (msg->msg_name) {
1667*4882a593Smuzhiyun 		__sockaddr_check_size(BCM_MIN_NAMELEN);
1668*4882a593Smuzhiyun 		msg->msg_namelen = BCM_MIN_NAMELEN;
1669*4882a593Smuzhiyun 		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
1670*4882a593Smuzhiyun 	}
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun 	skb_free_datagram(sk, skb);
1673*4882a593Smuzhiyun 
1674*4882a593Smuzhiyun 	return size;
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun 
bcm_sock_no_ioctlcmd(struct socket * sock,unsigned int cmd,unsigned long arg)1677*4882a593Smuzhiyun static int bcm_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd,
1678*4882a593Smuzhiyun 				unsigned long arg)
1679*4882a593Smuzhiyun {
1680*4882a593Smuzhiyun 	/* no ioctls for socket layer -> hand it down to NIC layer */
1681*4882a593Smuzhiyun 	return -ENOIOCTLCMD;
1682*4882a593Smuzhiyun }
1683*4882a593Smuzhiyun 
1684*4882a593Smuzhiyun static const struct proto_ops bcm_ops = {
1685*4882a593Smuzhiyun 	.family        = PF_CAN,
1686*4882a593Smuzhiyun 	.release       = bcm_release,
1687*4882a593Smuzhiyun 	.bind          = sock_no_bind,
1688*4882a593Smuzhiyun 	.connect       = bcm_connect,
1689*4882a593Smuzhiyun 	.socketpair    = sock_no_socketpair,
1690*4882a593Smuzhiyun 	.accept        = sock_no_accept,
1691*4882a593Smuzhiyun 	.getname       = sock_no_getname,
1692*4882a593Smuzhiyun 	.poll          = datagram_poll,
1693*4882a593Smuzhiyun 	.ioctl         = bcm_sock_no_ioctlcmd,
1694*4882a593Smuzhiyun 	.gettstamp     = sock_gettstamp,
1695*4882a593Smuzhiyun 	.listen        = sock_no_listen,
1696*4882a593Smuzhiyun 	.shutdown      = sock_no_shutdown,
1697*4882a593Smuzhiyun 	.sendmsg       = bcm_sendmsg,
1698*4882a593Smuzhiyun 	.recvmsg       = bcm_recvmsg,
1699*4882a593Smuzhiyun 	.mmap          = sock_no_mmap,
1700*4882a593Smuzhiyun 	.sendpage      = sock_no_sendpage,
1701*4882a593Smuzhiyun };
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun static struct proto bcm_proto __read_mostly = {
1704*4882a593Smuzhiyun 	.name       = "CAN_BCM",
1705*4882a593Smuzhiyun 	.owner      = THIS_MODULE,
1706*4882a593Smuzhiyun 	.obj_size   = sizeof(struct bcm_sock),
1707*4882a593Smuzhiyun 	.init       = bcm_init,
1708*4882a593Smuzhiyun };
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun static const struct can_proto bcm_can_proto = {
1711*4882a593Smuzhiyun 	.type       = SOCK_DGRAM,
1712*4882a593Smuzhiyun 	.protocol   = CAN_BCM,
1713*4882a593Smuzhiyun 	.ops        = &bcm_ops,
1714*4882a593Smuzhiyun 	.prot       = &bcm_proto,
1715*4882a593Smuzhiyun };
1716*4882a593Smuzhiyun 
canbcm_pernet_init(struct net * net)1717*4882a593Smuzhiyun static int canbcm_pernet_init(struct net *net)
1718*4882a593Smuzhiyun {
1719*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_PROC_FS)
1720*4882a593Smuzhiyun 	/* create /proc/net/can-bcm directory */
1721*4882a593Smuzhiyun 	net->can.bcmproc_dir = proc_net_mkdir(net, "can-bcm", net->proc_net);
1722*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
1723*4882a593Smuzhiyun 
1724*4882a593Smuzhiyun 	return 0;
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun 
canbcm_pernet_exit(struct net * net)1727*4882a593Smuzhiyun static void canbcm_pernet_exit(struct net *net)
1728*4882a593Smuzhiyun {
1729*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_PROC_FS)
1730*4882a593Smuzhiyun 	/* remove /proc/net/can-bcm directory */
1731*4882a593Smuzhiyun 	if (net->can.bcmproc_dir)
1732*4882a593Smuzhiyun 		remove_proc_entry("can-bcm", net->proc_net);
1733*4882a593Smuzhiyun #endif /* CONFIG_PROC_FS */
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun 
1736*4882a593Smuzhiyun static struct pernet_operations canbcm_pernet_ops __read_mostly = {
1737*4882a593Smuzhiyun 	.init = canbcm_pernet_init,
1738*4882a593Smuzhiyun 	.exit = canbcm_pernet_exit,
1739*4882a593Smuzhiyun };
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun static struct notifier_block canbcm_notifier = {
1742*4882a593Smuzhiyun 	.notifier_call = bcm_notifier
1743*4882a593Smuzhiyun };
1744*4882a593Smuzhiyun 
bcm_module_init(void)1745*4882a593Smuzhiyun static int __init bcm_module_init(void)
1746*4882a593Smuzhiyun {
1747*4882a593Smuzhiyun 	int err;
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun 	pr_info("can: broadcast manager protocol\n");
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun 	err = can_proto_register(&bcm_can_proto);
1752*4882a593Smuzhiyun 	if (err < 0) {
1753*4882a593Smuzhiyun 		printk(KERN_ERR "can: registration of bcm protocol failed\n");
1754*4882a593Smuzhiyun 		return err;
1755*4882a593Smuzhiyun 	}
1756*4882a593Smuzhiyun 
1757*4882a593Smuzhiyun 	register_pernet_subsys(&canbcm_pernet_ops);
1758*4882a593Smuzhiyun 	register_netdevice_notifier(&canbcm_notifier);
1759*4882a593Smuzhiyun 	return 0;
1760*4882a593Smuzhiyun }
1761*4882a593Smuzhiyun 
bcm_module_exit(void)1762*4882a593Smuzhiyun static void __exit bcm_module_exit(void)
1763*4882a593Smuzhiyun {
1764*4882a593Smuzhiyun 	can_proto_unregister(&bcm_can_proto);
1765*4882a593Smuzhiyun 	unregister_netdevice_notifier(&canbcm_notifier);
1766*4882a593Smuzhiyun 	unregister_pernet_subsys(&canbcm_pernet_ops);
1767*4882a593Smuzhiyun }
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun module_init(bcm_module_init);
1770*4882a593Smuzhiyun module_exit(bcm_module_exit);
1771