root/net/can/j1939/bus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __j1939_ecu_release
  2. j1939_ecu_put
  3. j1939_ecu_get
  4. j1939_ecu_is_mapped_locked
  5. j1939_ecu_map_locked
  6. j1939_ecu_unmap_locked
  7. j1939_ecu_unmap
  8. j1939_ecu_unmap_all
  9. j1939_ecu_timer_start
  10. j1939_ecu_timer_cancel
  11. j1939_ecu_timer_handler
  12. j1939_ecu_create_locked
  13. j1939_ecu_find_by_addr_locked
  14. j1939_ecu_get_by_addr_locked
  15. j1939_ecu_get_by_addr
  16. j1939_ecu_find_by_name_locked
  17. j1939_ecu_get_by_name_locked
  18. j1939_ecu_get_by_name
  19. j1939_name_to_addr
  20. j1939_local_ecu_get
  21. j1939_local_ecu_put

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

/* [<][>][^][v][top][bottom][index][help] */