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