cregit-Linux how code gets into the kernel

Release 4.11 drivers/power/reset/reboot-mode.c

/*
 * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/reboot.h>
#include "reboot-mode.h"


#define PREFIX "mode-"


struct mode_info {
	
const char *mode;
	
u32 magic;
	
struct list_head list;
};


static unsigned int get_reboot_mode_magic(struct reboot_mode_driver *reboot, const char *cmd) { const char *normal = "normal"; int magic = 0; struct mode_info *info; if (!cmd) cmd = normal; list_for_each_entry(info, &reboot->head, list) { if (!strcmp(info->mode, cmd)) { magic = info->magic; break; } } return magic; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Yan77100.00%1100.00%
Total77100.00%1100.00%


static int reboot_mode_notify(struct notifier_block *this, unsigned long mode, void *cmd) { struct reboot_mode_driver *reboot; unsigned int magic; reboot = container_of(this, struct reboot_mode_driver, reboot_notifier); magic = get_reboot_mode_magic(reboot, cmd); if (magic) reboot->write(reboot, magic); return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Yan65100.00%1100.00%
Total65100.00%1100.00%

/** * reboot_mode_register - register a reboot mode driver * @reboot: reboot mode driver * * Returns: 0 on success or a negative error code on failure. */
int reboot_mode_register(struct reboot_mode_driver *reboot) { struct mode_info *info; struct property *prop; struct device_node *np = reboot->dev->of_node; size_t len = strlen(PREFIX); int ret; INIT_LIST_HEAD(&reboot->head); for_each_property_of_node(np, prop) { if (strncmp(prop->name, PREFIX, len)) continue; info = devm_kzalloc(reboot->dev, sizeof(*info), GFP_KERNEL); if (!info) { ret = -ENOMEM; goto error; } if (of_property_read_u32(np, prop->name, &info->magic)) { dev_err(reboot->dev, "reboot mode %s without magic number\n", info->mode); devm_kfree(reboot->dev, info); continue; } info->mode = kstrdup_const(prop->name + len, GFP_KERNEL); if (!info->mode) { ret = -ENOMEM; goto error; } else if (info->mode[0] == '\0') { kfree_const(info->mode); ret = -EINVAL; dev_err(reboot->dev, "invalid mode name(%s): too short!\n", prop->name); goto error; } list_add_tail(&info->list, &reboot->head); } reboot->reboot_notifier.notifier_call = reboot_mode_notify; register_reboot_notifier(&reboot->reboot_notifier); return 0; error: list_for_each_entry(info, &reboot->head, list) kfree_const(info->mode); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Yan271100.00%1100.00%
Total271100.00%1100.00%

EXPORT_SYMBOL_GPL(reboot_mode_register); /** * reboot_mode_unregister - unregister a reboot mode driver * @reboot: reboot mode driver */
int reboot_mode_unregister(struct reboot_mode_driver *reboot) { struct mode_info *info; unregister_reboot_notifier(&reboot->reboot_notifier); list_for_each_entry(info, &reboot->head, list) kfree_const(info->mode); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Yan41100.00%1100.00%
Total41100.00%1100.00%

EXPORT_SYMBOL_GPL(reboot_mode_unregister);
static void devm_reboot_mode_release(struct device *dev, void *res) { reboot_mode_unregister(*(struct reboot_mode_driver **)res); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson27100.00%1100.00%
Total27100.00%1100.00%

/** * devm_reboot_mode_register() - resource managed reboot_mode_register() * @dev: device to associate this resource with * @reboot: reboot mode driver * * Returns: 0 on success or a negative error code on failure. */
int devm_reboot_mode_register(struct device *dev, struct reboot_mode_driver *reboot) { struct reboot_mode_driver **dr; int rc; dr = devres_alloc(devm_reboot_mode_release, sizeof(*dr), GFP_KERNEL); if (!dr) return -ENOMEM; rc = reboot_mode_register(reboot); if (rc) { devres_free(dr); return rc; } *dr = reboot; devres_add(dev, dr); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson84100.00%1100.00%
Total84100.00%1100.00%

EXPORT_SYMBOL_GPL(devm_reboot_mode_register);
static int devm_reboot_mode_match(struct device *dev, void *res, void *data) { struct reboot_mode_driver **p = res; if (WARN_ON(!p || !*p)) return 0; return *p == data; }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson48100.00%1100.00%
Total48100.00%1100.00%

/** * devm_reboot_mode_unregister() - resource managed reboot_mode_unregister() * @dev: device to associate this resource with * @reboot: reboot mode driver */
void devm_reboot_mode_unregister(struct device *dev, struct reboot_mode_driver *reboot) { WARN_ON(devres_release(dev, devm_reboot_mode_release, devm_reboot_mode_match, reboot)); }

Contributors

PersonTokensPropCommitsCommitProp
Björn Andersson29100.00%1100.00%
Total29100.00%1100.00%

EXPORT_SYMBOL_GPL(devm_reboot_mode_unregister); MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com"); MODULE_DESCRIPTION("System reboot mode core library"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
Andy Yan52472.38%150.00%
Björn Andersson20027.62%150.00%
Total724100.00%2100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.