cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

w1_family.c (2563B)


      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
     14DEFINE_SPINLOCK(w1_flock);
     15static LIST_HEAD(w1_families);
     16
     17/**
     18 * w1_register_family() - register a device family driver
     19 * @newf:	family to register
     20 */
     21int 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}
     48EXPORT_SYMBOL(w1_register_family);
     49
     50/**
     51 * w1_unregister_family() - unregister a device family driver
     52 * @fent:	family to unregister
     53 */
     54void 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}
     81EXPORT_SYMBOL(w1_unregister_family);
     82
     83/*
     84 * Should be called under w1_flock held.
     85 */
     86struct 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
    104static void __w1_family_put(struct w1_family *f)
    105{
    106	atomic_dec(&f->refcnt);
    107}
    108
    109void 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
    117void 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
    125void __w1_family_get(struct w1_family *f)
    126{
    127	smp_mb__before_atomic();
    128	atomic_inc(&f->refcnt);
    129	smp_mb__after_atomic();
    130}