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

devres.c (7453B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * drivers/extcon/devres.c - EXTCON device's resource management
      4 *
      5 * Copyright (C) 2016 Samsung Electronics
      6 * Author: Chanwoo Choi <cw00.choi@samsung.com>
      7 */
      8
      9#include "extcon.h"
     10
     11static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
     12{
     13	struct extcon_dev **r = res;
     14
     15	if (WARN_ON(!r || !*r))
     16		return 0;
     17
     18	return *r == data;
     19}
     20
     21static void devm_extcon_dev_release(struct device *dev, void *res)
     22{
     23	extcon_dev_free(*(struct extcon_dev **)res);
     24}
     25
     26
     27static void devm_extcon_dev_unreg(struct device *dev, void *res)
     28{
     29	extcon_dev_unregister(*(struct extcon_dev **)res);
     30}
     31
     32struct extcon_dev_notifier_devres {
     33	struct extcon_dev *edev;
     34	unsigned int id;
     35	struct notifier_block *nb;
     36};
     37
     38static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res)
     39{
     40	struct extcon_dev_notifier_devres *this = res;
     41
     42	extcon_unregister_notifier(this->edev, this->id, this->nb);
     43}
     44
     45static void devm_extcon_dev_notifier_all_unreg(struct device *dev, void *res)
     46{
     47	struct extcon_dev_notifier_devres *this = res;
     48
     49	extcon_unregister_notifier_all(this->edev, this->nb);
     50}
     51
     52/**
     53 * devm_extcon_dev_allocate - Allocate managed extcon device
     54 * @dev:		the device owning the extcon device being created
     55 * @supported_cable:	the array of the supported external connectors
     56 *			ending with EXTCON_NONE.
     57 *
     58 * This function manages automatically the memory of extcon device using device
     59 * resource management and simplify the control of freeing the memory of extcon
     60 * device.
     61 *
     62 * Returns the pointer memory of allocated extcon_dev if success
     63 * or ERR_PTR(err) if fail
     64 */
     65struct extcon_dev *devm_extcon_dev_allocate(struct device *dev,
     66					const unsigned int *supported_cable)
     67{
     68	struct extcon_dev **ptr, *edev;
     69
     70	ptr = devres_alloc(devm_extcon_dev_release, sizeof(*ptr), GFP_KERNEL);
     71	if (!ptr)
     72		return ERR_PTR(-ENOMEM);
     73
     74	edev = extcon_dev_allocate(supported_cable);
     75	if (IS_ERR(edev)) {
     76		devres_free(ptr);
     77		return edev;
     78	}
     79
     80	edev->dev.parent = dev;
     81
     82	*ptr = edev;
     83	devres_add(dev, ptr);
     84
     85	return edev;
     86}
     87EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate);
     88
     89/**
     90 * devm_extcon_dev_free() - Resource-managed extcon_dev_unregister()
     91 * @dev:	the device owning the extcon device being created
     92 * @edev:	the extcon device to be freed
     93 *
     94 * Free the memory that is allocated with devm_extcon_dev_allocate()
     95 * function.
     96 */
     97void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev)
     98{
     99	WARN_ON(devres_release(dev, devm_extcon_dev_release,
    100			       devm_extcon_dev_match, edev));
    101}
    102EXPORT_SYMBOL_GPL(devm_extcon_dev_free);
    103
    104/**
    105 * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
    106 * @dev:	the device owning the extcon device being created
    107 * @edev:	the extcon device to be registered
    108 *
    109 * this function, that extcon device is automatically unregistered on driver
    110 * detach. Internally this function calls extcon_dev_register() function.
    111 * To get more information, refer that function.
    112 *
    113 * If extcon device is registered with this function and the device needs to be
    114 * unregistered separately, devm_extcon_dev_unregister() should be used.
    115 *
    116 * Returns 0 if success or negaive error number if failure.
    117 */
    118int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
    119{
    120	struct extcon_dev **ptr;
    121	int ret;
    122
    123	ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
    124	if (!ptr)
    125		return -ENOMEM;
    126
    127	ret = extcon_dev_register(edev);
    128	if (ret) {
    129		devres_free(ptr);
    130		return ret;
    131	}
    132
    133	*ptr = edev;
    134	devres_add(dev, ptr);
    135
    136	return 0;
    137}
    138EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
    139
    140/**
    141 * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
    142 * @dev:	the device owning the extcon device being created
    143 * @edev:	the extcon device to unregistered
    144 *
    145 * Unregister extcon device that is registered with devm_extcon_dev_register()
    146 * function.
    147 */
    148void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
    149{
    150	WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
    151			       devm_extcon_dev_match, edev));
    152}
    153EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
    154
    155/**
    156 * devm_extcon_register_notifier() - Resource-managed extcon_register_notifier()
    157 * @dev:	the device owning the extcon device being created
    158 * @edev:	the extcon device
    159 * @id:		the unique id among the extcon enumeration
    160 * @nb:		a notifier block to be registered
    161 *
    162 * This function manages automatically the notifier of extcon device using
    163 * device resource management and simplify the control of unregistering
    164 * the notifier of extcon device.
    165 *
    166 * Note that the second parameter given to the callback of nb (val) is
    167 * "old_state", not the current state. The current state can be retrieved
    168 * by looking at the third pameter (edev pointer)'s state value.
    169 *
    170 * Returns 0 if success or negaive error number if failure.
    171 */
    172int devm_extcon_register_notifier(struct device *dev, struct extcon_dev *edev,
    173				unsigned int id, struct notifier_block *nb)
    174{
    175	struct extcon_dev_notifier_devres *ptr;
    176	int ret;
    177
    178	ptr = devres_alloc(devm_extcon_dev_notifier_unreg, sizeof(*ptr),
    179				GFP_KERNEL);
    180	if (!ptr)
    181		return -ENOMEM;
    182
    183	ret = extcon_register_notifier(edev, id, nb);
    184	if (ret) {
    185		devres_free(ptr);
    186		return ret;
    187	}
    188
    189	ptr->edev = edev;
    190	ptr->id = id;
    191	ptr->nb = nb;
    192	devres_add(dev, ptr);
    193
    194	return 0;
    195}
    196EXPORT_SYMBOL(devm_extcon_register_notifier);
    197
    198/**
    199 * devm_extcon_unregister_notifier()
    200 *			- Resource-managed extcon_unregister_notifier()
    201 * @dev:	the device owning the extcon device being created
    202 * @edev:	the extcon device
    203 * @id:		the unique id among the extcon enumeration
    204 * @nb:		a notifier block to be registered
    205 */
    206void devm_extcon_unregister_notifier(struct device *dev,
    207				struct extcon_dev *edev, unsigned int id,
    208				struct notifier_block *nb)
    209{
    210	WARN_ON(devres_release(dev, devm_extcon_dev_notifier_unreg,
    211			       devm_extcon_dev_match, edev));
    212}
    213EXPORT_SYMBOL(devm_extcon_unregister_notifier);
    214
    215/**
    216 * devm_extcon_register_notifier_all()
    217 *		- Resource-managed extcon_register_notifier_all()
    218 * @dev:	the device owning the extcon device being created
    219 * @edev:	the extcon device
    220 * @nb:		a notifier block to be registered
    221 *
    222 * This function manages automatically the notifier of extcon device using
    223 * device resource management and simplify the control of unregistering
    224 * the notifier of extcon device. To get more information, refer that function.
    225 *
    226 * Returns 0 if success or negaive error number if failure.
    227 */
    228int devm_extcon_register_notifier_all(struct device *dev, struct extcon_dev *edev,
    229				struct notifier_block *nb)
    230{
    231	struct extcon_dev_notifier_devres *ptr;
    232	int ret;
    233
    234	ptr = devres_alloc(devm_extcon_dev_notifier_all_unreg, sizeof(*ptr),
    235				GFP_KERNEL);
    236	if (!ptr)
    237		return -ENOMEM;
    238
    239	ret = extcon_register_notifier_all(edev, nb);
    240	if (ret) {
    241		devres_free(ptr);
    242		return ret;
    243	}
    244
    245	ptr->edev = edev;
    246	ptr->nb = nb;
    247	devres_add(dev, ptr);
    248
    249	return 0;
    250}
    251EXPORT_SYMBOL(devm_extcon_register_notifier_all);
    252
    253/**
    254 * devm_extcon_unregister_notifier_all()
    255 *		- Resource-managed extcon_unregister_notifier_all()
    256 * @dev:	the device owning the extcon device being created
    257 * @edev:	the extcon device
    258 * @nb:		a notifier block to be registered
    259 */
    260void devm_extcon_unregister_notifier_all(struct device *dev,
    261				struct extcon_dev *edev,
    262				struct notifier_block *nb)
    263{
    264	WARN_ON(devres_release(dev, devm_extcon_dev_notifier_all_unreg,
    265			       devm_extcon_dev_match, edev));
    266}
    267EXPORT_SYMBOL(devm_extcon_unregister_notifier_all);