Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net>
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  * w1_register_family() - register a device family driver
0019  * @newf:   family to register
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     /* check default devices against the new set of drivers */
0044     w1_reconnect_slaves(newf, 1);
0045 
0046     return ret;
0047 }
0048 EXPORT_SYMBOL(w1_register_family);
0049 
0050 /**
0051  * w1_unregister_family() - unregister a device family driver
0052  * @fent:   family to unregister
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     /* deatch devices using this family code */
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  * Should be called under w1_flock held.
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  /*  0  */
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 }