xref: /OK3568_Linux_fs/kernel/net/can/j1939/bus.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2010-2011 EIA Electronics,
3*4882a593Smuzhiyun //                         Kurt Van Dijck <kurt.van.dijck@eia.be>
4*4882a593Smuzhiyun // Copyright (c) 2017-2019 Pengutronix,
5*4882a593Smuzhiyun //                         Marc Kleine-Budde <kernel@pengutronix.de>
6*4882a593Smuzhiyun // Copyright (c) 2017-2019 Pengutronix,
7*4882a593Smuzhiyun //                         Oleksij Rempel <kernel@pengutronix.de>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun /* bus for j1939 remote devices
10*4882a593Smuzhiyun  * Since rtnetlink, no real bus is used.
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <net/sock.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include "j1939-priv.h"
16*4882a593Smuzhiyun 
__j1939_ecu_release(struct kref * kref)17*4882a593Smuzhiyun static void __j1939_ecu_release(struct kref *kref)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun 	struct j1939_ecu *ecu = container_of(kref, struct j1939_ecu, kref);
20*4882a593Smuzhiyun 	struct j1939_priv *priv = ecu->priv;
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 	list_del(&ecu->list);
23*4882a593Smuzhiyun 	kfree(ecu);
24*4882a593Smuzhiyun 	j1939_priv_put(priv);
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun 
j1939_ecu_put(struct j1939_ecu * ecu)27*4882a593Smuzhiyun void j1939_ecu_put(struct j1939_ecu *ecu)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun 	kref_put(&ecu->kref, __j1939_ecu_release);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun 
j1939_ecu_get(struct j1939_ecu * ecu)32*4882a593Smuzhiyun static void j1939_ecu_get(struct j1939_ecu *ecu)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	kref_get(&ecu->kref);
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
j1939_ecu_is_mapped_locked(struct j1939_ecu * ecu)37*4882a593Smuzhiyun static bool j1939_ecu_is_mapped_locked(struct j1939_ecu *ecu)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	struct j1939_priv *priv = ecu->priv;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	return j1939_ecu_find_by_addr_locked(priv, ecu->addr) == ecu;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /* ECU device interface */
47*4882a593Smuzhiyun /* map ECU to a bus address space */
j1939_ecu_map_locked(struct j1939_ecu * ecu)48*4882a593Smuzhiyun static void j1939_ecu_map_locked(struct j1939_ecu *ecu)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	struct j1939_priv *priv = ecu->priv;
51*4882a593Smuzhiyun 	struct j1939_addr_ent *ent;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (!j1939_address_is_unicast(ecu->addr))
56*4882a593Smuzhiyun 		return;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	ent = &priv->ents[ecu->addr];
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (ent->ecu) {
61*4882a593Smuzhiyun 		netdev_warn(priv->ndev, "Trying to map already mapped ECU, addr: 0x%02x, name: 0x%016llx. Skip it.\n",
62*4882a593Smuzhiyun 			    ecu->addr, ecu->name);
63*4882a593Smuzhiyun 		return;
64*4882a593Smuzhiyun 	}
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	j1939_ecu_get(ecu);
67*4882a593Smuzhiyun 	ent->ecu = ecu;
68*4882a593Smuzhiyun 	ent->nusers += ecu->nusers;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* unmap ECU from a bus address space */
j1939_ecu_unmap_locked(struct j1939_ecu * ecu)72*4882a593Smuzhiyun void j1939_ecu_unmap_locked(struct j1939_ecu *ecu)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	struct j1939_priv *priv = ecu->priv;
75*4882a593Smuzhiyun 	struct j1939_addr_ent *ent;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (!j1939_address_is_unicast(ecu->addr))
80*4882a593Smuzhiyun 		return;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	if (!j1939_ecu_is_mapped_locked(ecu))
83*4882a593Smuzhiyun 		return;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	ent = &priv->ents[ecu->addr];
86*4882a593Smuzhiyun 	ent->ecu = NULL;
87*4882a593Smuzhiyun 	ent->nusers -= ecu->nusers;
88*4882a593Smuzhiyun 	j1939_ecu_put(ecu);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
j1939_ecu_unmap(struct j1939_ecu * ecu)91*4882a593Smuzhiyun void j1939_ecu_unmap(struct j1939_ecu *ecu)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	write_lock_bh(&ecu->priv->lock);
94*4882a593Smuzhiyun 	j1939_ecu_unmap_locked(ecu);
95*4882a593Smuzhiyun 	write_unlock_bh(&ecu->priv->lock);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
j1939_ecu_unmap_all(struct j1939_priv * priv)98*4882a593Smuzhiyun void j1939_ecu_unmap_all(struct j1939_priv *priv)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun 	int i;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	write_lock_bh(&priv->lock);
103*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(priv->ents); i++)
104*4882a593Smuzhiyun 		if (priv->ents[i].ecu)
105*4882a593Smuzhiyun 			j1939_ecu_unmap_locked(priv->ents[i].ecu);
106*4882a593Smuzhiyun 	write_unlock_bh(&priv->lock);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
j1939_ecu_timer_start(struct j1939_ecu * ecu)109*4882a593Smuzhiyun void j1939_ecu_timer_start(struct j1939_ecu *ecu)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	/* The ECU is held here and released in the
112*4882a593Smuzhiyun 	 * j1939_ecu_timer_handler() or j1939_ecu_timer_cancel().
113*4882a593Smuzhiyun 	 */
114*4882a593Smuzhiyun 	j1939_ecu_get(ecu);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	/* Schedule timer in 250 msec to commit address change. */
117*4882a593Smuzhiyun 	hrtimer_start(&ecu->ac_timer, ms_to_ktime(250),
118*4882a593Smuzhiyun 		      HRTIMER_MODE_REL_SOFT);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
j1939_ecu_timer_cancel(struct j1939_ecu * ecu)121*4882a593Smuzhiyun void j1939_ecu_timer_cancel(struct j1939_ecu *ecu)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	if (hrtimer_cancel(&ecu->ac_timer))
124*4882a593Smuzhiyun 		j1939_ecu_put(ecu);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
j1939_ecu_timer_handler(struct hrtimer * hrtimer)127*4882a593Smuzhiyun static enum hrtimer_restart j1939_ecu_timer_handler(struct hrtimer *hrtimer)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	struct j1939_ecu *ecu =
130*4882a593Smuzhiyun 		container_of(hrtimer, struct j1939_ecu, ac_timer);
131*4882a593Smuzhiyun 	struct j1939_priv *priv = ecu->priv;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	write_lock_bh(&priv->lock);
134*4882a593Smuzhiyun 	/* TODO: can we test if ecu->addr is unicast before starting
135*4882a593Smuzhiyun 	 * the timer?
136*4882a593Smuzhiyun 	 */
137*4882a593Smuzhiyun 	j1939_ecu_map_locked(ecu);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	/* The corresponding j1939_ecu_get() is in
140*4882a593Smuzhiyun 	 * j1939_ecu_timer_start().
141*4882a593Smuzhiyun 	 */
142*4882a593Smuzhiyun 	j1939_ecu_put(ecu);
143*4882a593Smuzhiyun 	write_unlock_bh(&priv->lock);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	return HRTIMER_NORESTART;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
j1939_ecu_create_locked(struct j1939_priv * priv,name_t name)148*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_create_locked(struct j1939_priv *priv, name_t name)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	ecu = kzalloc(sizeof(*ecu), gfp_any());
155*4882a593Smuzhiyun 	if (!ecu)
156*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
157*4882a593Smuzhiyun 	kref_init(&ecu->kref);
158*4882a593Smuzhiyun 	ecu->addr = J1939_IDLE_ADDR;
159*4882a593Smuzhiyun 	ecu->name = name;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	hrtimer_init(&ecu->ac_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
162*4882a593Smuzhiyun 	ecu->ac_timer.function = j1939_ecu_timer_handler;
163*4882a593Smuzhiyun 	INIT_LIST_HEAD(&ecu->list);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	j1939_priv_get(priv);
166*4882a593Smuzhiyun 	ecu->priv = priv;
167*4882a593Smuzhiyun 	list_add_tail(&ecu->list, &priv->ecus);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return ecu;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
j1939_ecu_find_by_addr_locked(struct j1939_priv * priv,u8 addr)172*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_find_by_addr_locked(struct j1939_priv *priv,
173*4882a593Smuzhiyun 						u8 addr)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	return priv->ents[addr].ecu;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
j1939_ecu_get_by_addr_locked(struct j1939_priv * priv,u8 addr)180*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_get_by_addr_locked(struct j1939_priv *priv, u8 addr)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (!j1939_address_is_unicast(addr))
187*4882a593Smuzhiyun 		return NULL;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	ecu = j1939_ecu_find_by_addr_locked(priv, addr);
190*4882a593Smuzhiyun 	if (ecu)
191*4882a593Smuzhiyun 		j1939_ecu_get(ecu);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	return ecu;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
j1939_ecu_get_by_addr(struct j1939_priv * priv,u8 addr)196*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_get_by_addr(struct j1939_priv *priv, u8 addr)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	read_lock_bh(&priv->lock);
201*4882a593Smuzhiyun 	ecu = j1939_ecu_get_by_addr_locked(priv, addr);
202*4882a593Smuzhiyun 	read_unlock_bh(&priv->lock);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	return ecu;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun /* get pointer to ecu without increasing ref counter */
j1939_ecu_find_by_name_locked(struct j1939_priv * priv,name_t name)208*4882a593Smuzhiyun static struct j1939_ecu *j1939_ecu_find_by_name_locked(struct j1939_priv *priv,
209*4882a593Smuzhiyun 						       name_t name)
210*4882a593Smuzhiyun {
211*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	list_for_each_entry(ecu, &priv->ecus, list) {
216*4882a593Smuzhiyun 		if (ecu->name == name)
217*4882a593Smuzhiyun 			return ecu;
218*4882a593Smuzhiyun 	}
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	return NULL;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun 
j1939_ecu_get_by_name_locked(struct j1939_priv * priv,name_t name)223*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_get_by_name_locked(struct j1939_priv *priv,
224*4882a593Smuzhiyun 					       name_t name)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	lockdep_assert_held(&priv->lock);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	if (!name)
231*4882a593Smuzhiyun 		return NULL;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	ecu = j1939_ecu_find_by_name_locked(priv, name);
234*4882a593Smuzhiyun 	if (ecu)
235*4882a593Smuzhiyun 		j1939_ecu_get(ecu);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	return ecu;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
j1939_ecu_get_by_name(struct j1939_priv * priv,name_t name)240*4882a593Smuzhiyun struct j1939_ecu *j1939_ecu_get_by_name(struct j1939_priv *priv, name_t name)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	read_lock_bh(&priv->lock);
245*4882a593Smuzhiyun 	ecu = j1939_ecu_get_by_name_locked(priv, name);
246*4882a593Smuzhiyun 	read_unlock_bh(&priv->lock);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return ecu;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun 
j1939_name_to_addr(struct j1939_priv * priv,name_t name)251*4882a593Smuzhiyun u8 j1939_name_to_addr(struct j1939_priv *priv, name_t name)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
254*4882a593Smuzhiyun 	int addr = J1939_IDLE_ADDR;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	if (!name)
257*4882a593Smuzhiyun 		return J1939_NO_ADDR;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	read_lock_bh(&priv->lock);
260*4882a593Smuzhiyun 	ecu = j1939_ecu_find_by_name_locked(priv, name);
261*4882a593Smuzhiyun 	if (ecu && j1939_ecu_is_mapped_locked(ecu))
262*4882a593Smuzhiyun 		/* ecu's SA is registered */
263*4882a593Smuzhiyun 		addr = ecu->addr;
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	read_unlock_bh(&priv->lock);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return addr;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun /* TX addr/name accounting
271*4882a593Smuzhiyun  * Transport protocol needs to know if a SA is local or not
272*4882a593Smuzhiyun  * These functions originate from userspace manipulating sockets,
273*4882a593Smuzhiyun  * so locking is straigforward
274*4882a593Smuzhiyun  */
275*4882a593Smuzhiyun 
j1939_local_ecu_get(struct j1939_priv * priv,name_t name,u8 sa)276*4882a593Smuzhiyun int j1939_local_ecu_get(struct j1939_priv *priv, name_t name, u8 sa)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
279*4882a593Smuzhiyun 	int err = 0;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	write_lock_bh(&priv->lock);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	if (j1939_address_is_unicast(sa))
284*4882a593Smuzhiyun 		priv->ents[sa].nusers++;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if (!name)
287*4882a593Smuzhiyun 		goto done;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	ecu = j1939_ecu_get_by_name_locked(priv, name);
290*4882a593Smuzhiyun 	if (!ecu)
291*4882a593Smuzhiyun 		ecu = j1939_ecu_create_locked(priv, name);
292*4882a593Smuzhiyun 	err = PTR_ERR_OR_ZERO(ecu);
293*4882a593Smuzhiyun 	if (err)
294*4882a593Smuzhiyun 		goto done;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	ecu->nusers++;
297*4882a593Smuzhiyun 	/* TODO: do we care if ecu->addr != sa? */
298*4882a593Smuzhiyun 	if (j1939_ecu_is_mapped_locked(ecu))
299*4882a593Smuzhiyun 		/* ecu's sa is active already */
300*4882a593Smuzhiyun 		priv->ents[ecu->addr].nusers++;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun  done:
303*4882a593Smuzhiyun 	write_unlock_bh(&priv->lock);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	return err;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
j1939_local_ecu_put(struct j1939_priv * priv,name_t name,u8 sa)308*4882a593Smuzhiyun void j1939_local_ecu_put(struct j1939_priv *priv, name_t name, u8 sa)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	struct j1939_ecu *ecu;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	write_lock_bh(&priv->lock);
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	if (j1939_address_is_unicast(sa))
315*4882a593Smuzhiyun 		priv->ents[sa].nusers--;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	if (!name)
318*4882a593Smuzhiyun 		goto done;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	ecu = j1939_ecu_find_by_name_locked(priv, name);
321*4882a593Smuzhiyun 	if (WARN_ON_ONCE(!ecu))
322*4882a593Smuzhiyun 		goto done;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	ecu->nusers--;
325*4882a593Smuzhiyun 	/* TODO: do we care if ecu->addr != sa? */
326*4882a593Smuzhiyun 	if (j1939_ecu_is_mapped_locked(ecu))
327*4882a593Smuzhiyun 		/* ecu's sa is active already */
328*4882a593Smuzhiyun 		priv->ents[ecu->addr].nusers--;
329*4882a593Smuzhiyun 	j1939_ecu_put(ecu);
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun  done:
332*4882a593Smuzhiyun 	write_unlock_bh(&priv->lock);
333*4882a593Smuzhiyun }
334