0001
0002
0003
0004
0005
0006 #include <linux/spinlock.h>
0007 #include <linux/list.h>
0008 #include <linux/sched/signal.h>
0009 #include <linux/delay.h>
0010 #include <linux/export.h>
0011
0012 #include "w1_internal.h"
0013
0014 DEFINE_SPINLOCK(w1_flock);
0015 static LIST_HEAD(w1_families);
0016
0017
0018
0019
0020
0021 int w1_register_family(struct w1_family *newf)
0022 {
0023 struct list_head *ent, *n;
0024 struct w1_family *f;
0025 int ret = 0;
0026
0027 spin_lock(&w1_flock);
0028 list_for_each_safe(ent, n, &w1_families) {
0029 f = list_entry(ent, struct w1_family, family_entry);
0030
0031 if (f->fid == newf->fid) {
0032 ret = -EEXIST;
0033 break;
0034 }
0035 }
0036
0037 if (!ret) {
0038 atomic_set(&newf->refcnt, 0);
0039 list_add_tail(&newf->family_entry, &w1_families);
0040 }
0041 spin_unlock(&w1_flock);
0042
0043
0044 w1_reconnect_slaves(newf, 1);
0045
0046 return ret;
0047 }
0048 EXPORT_SYMBOL(w1_register_family);
0049
0050
0051
0052
0053
0054 void w1_unregister_family(struct w1_family *fent)
0055 {
0056 struct list_head *ent, *n;
0057 struct w1_family *f;
0058
0059 spin_lock(&w1_flock);
0060 list_for_each_safe(ent, n, &w1_families) {
0061 f = list_entry(ent, struct w1_family, family_entry);
0062
0063 if (f->fid == fent->fid) {
0064 list_del(&fent->family_entry);
0065 break;
0066 }
0067 }
0068 spin_unlock(&w1_flock);
0069
0070
0071 w1_reconnect_slaves(fent, 0);
0072
0073 while (atomic_read(&fent->refcnt)) {
0074 pr_info("Waiting for family %u to become free: refcnt=%d.\n",
0075 fent->fid, atomic_read(&fent->refcnt));
0076
0077 if (msleep_interruptible(1000))
0078 flush_signals(current);
0079 }
0080 }
0081 EXPORT_SYMBOL(w1_unregister_family);
0082
0083
0084
0085
0086 struct w1_family * w1_family_registered(u8 fid)
0087 {
0088 struct list_head *ent, *n;
0089 struct w1_family *f = NULL;
0090 int ret = 0;
0091
0092 list_for_each_safe(ent, n, &w1_families) {
0093 f = list_entry(ent, struct w1_family, family_entry);
0094
0095 if (f->fid == fid) {
0096 ret = 1;
0097 break;
0098 }
0099 }
0100
0101 return (ret) ? f : NULL;
0102 }
0103
0104 static void __w1_family_put(struct w1_family *f)
0105 {
0106 atomic_dec(&f->refcnt);
0107 }
0108
0109 void w1_family_put(struct w1_family *f)
0110 {
0111 spin_lock(&w1_flock);
0112 __w1_family_put(f);
0113 spin_unlock(&w1_flock);
0114 }
0115
0116 #if 0
0117 void w1_family_get(struct w1_family *f)
0118 {
0119 spin_lock(&w1_flock);
0120 __w1_family_get(f);
0121 spin_unlock(&w1_flock);
0122 }
0123 #endif
0124
0125 void __w1_family_get(struct w1_family *f)
0126 {
0127 smp_mb__before_atomic();
0128 atomic_inc(&f->refcnt);
0129 smp_mb__after_atomic();
0130 }