root/drivers/w1/w1_family.c

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

DEFINITIONS

This source file includes following definitions.
  1. w1_register_family
  2. w1_unregister_family
  3. w1_family_registered
  4. __w1_family_put
  5. w1_family_put
  6. w1_family_get
  7. __w1_family_get

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
   4  */
   5 
   6 #include <linux/spinlock.h>
   7 #include <linux/list.h>
   8 #include <linux/sched/signal.h>
   9 #include <linux/delay.h>
  10 #include <linux/export.h>
  11 
  12 #include "w1_internal.h"
  13 
  14 DEFINE_SPINLOCK(w1_flock);
  15 static LIST_HEAD(w1_families);
  16 
  17 /**
  18  * w1_register_family() - register a device family driver
  19  * @newf:       family to register
  20  */
  21 int w1_register_family(struct w1_family *newf)
  22 {
  23         struct list_head *ent, *n;
  24         struct w1_family *f;
  25         int ret = 0;
  26 
  27         spin_lock(&w1_flock);
  28         list_for_each_safe(ent, n, &w1_families) {
  29                 f = list_entry(ent, struct w1_family, family_entry);
  30 
  31                 if (f->fid == newf->fid) {
  32                         ret = -EEXIST;
  33                         break;
  34                 }
  35         }
  36 
  37         if (!ret) {
  38                 atomic_set(&newf->refcnt, 0);
  39                 list_add_tail(&newf->family_entry, &w1_families);
  40         }
  41         spin_unlock(&w1_flock);
  42 
  43         /* check default devices against the new set of drivers */
  44         w1_reconnect_slaves(newf, 1);
  45 
  46         return ret;
  47 }
  48 EXPORT_SYMBOL(w1_register_family);
  49 
  50 /**
  51  * w1_unregister_family() - unregister a device family driver
  52  * @fent:       family to unregister
  53  */
  54 void w1_unregister_family(struct w1_family *fent)
  55 {
  56         struct list_head *ent, *n;
  57         struct w1_family *f;
  58 
  59         spin_lock(&w1_flock);
  60         list_for_each_safe(ent, n, &w1_families) {
  61                 f = list_entry(ent, struct w1_family, family_entry);
  62 
  63                 if (f->fid == fent->fid) {
  64                         list_del(&fent->family_entry);
  65                         break;
  66                 }
  67         }
  68         spin_unlock(&w1_flock);
  69 
  70         /* deatch devices using this family code */
  71         w1_reconnect_slaves(fent, 0);
  72 
  73         while (atomic_read(&fent->refcnt)) {
  74                 pr_info("Waiting for family %u to become free: refcnt=%d.\n",
  75                                 fent->fid, atomic_read(&fent->refcnt));
  76 
  77                 if (msleep_interruptible(1000))
  78                         flush_signals(current);
  79         }
  80 }
  81 EXPORT_SYMBOL(w1_unregister_family);
  82 
  83 /*
  84  * Should be called under w1_flock held.
  85  */
  86 struct w1_family * w1_family_registered(u8 fid)
  87 {
  88         struct list_head *ent, *n;
  89         struct w1_family *f = NULL;
  90         int ret = 0;
  91 
  92         list_for_each_safe(ent, n, &w1_families) {
  93                 f = list_entry(ent, struct w1_family, family_entry);
  94 
  95                 if (f->fid == fid) {
  96                         ret = 1;
  97                         break;
  98                 }
  99         }
 100 
 101         return (ret) ? f : NULL;
 102 }
 103 
 104 static void __w1_family_put(struct w1_family *f)
 105 {
 106         atomic_dec(&f->refcnt);
 107 }
 108 
 109 void w1_family_put(struct w1_family *f)
 110 {
 111         spin_lock(&w1_flock);
 112         __w1_family_put(f);
 113         spin_unlock(&w1_flock);
 114 }
 115 
 116 #if 0
 117 void w1_family_get(struct w1_family *f)
 118 {
 119         spin_lock(&w1_flock);
 120         __w1_family_get(f);
 121         spin_unlock(&w1_flock);
 122 }
 123 #endif  /*  0  */
 124 
 125 void __w1_family_get(struct w1_family *f)
 126 {
 127         smp_mb__before_atomic();
 128         atomic_inc(&f->refcnt);
 129         smp_mb__after_atomic();
 130 }

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