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