You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
kernel_samsung_sm7125/drivers/samsung/debug/sec_bootstat.c

712 lines
19 KiB

// SPDX-License-Identifier: GPL-2.0
/*
* drivers/samsung/debug/sec_bootstat.c
*
* COPYRIGHT(C) 2014-2019 Samsung Electronics Co., Ltd. All Right Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ":%s() " fmt, __func__
#include <linux/version.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
#include <soc/qcom/boot_stats.h>
#endif
#include <linux/sec_class.h>
#include <linux/sec_bootstat.h>
#include "sec_debug_internal.h"
#define BOOT_EVT_PREFIX "!@Boot"
#define BOOT_EVT_PREFIX_NONE ""
#define BOOT_EVT_PREFIX_PLATFORM ": "
#define BOOT_EVT_PREFIX_RIL "_SVC : "
#define BOOT_EVT_PREFIX_DEBUG "_DEBUG: "
#define BOOT_EVT_PREFIX_SYSTEMSERVER "_SystemServer: "
#define DEFAULT_BOOT_STAT_FREQ 32768
#define DELAY_TIME_EBS 10000
#define MAX_EVENTS_EBS 100
static struct device *sec_bsp_dev;
static unsigned int __is_boot_recovery;
static bool bootcompleted = false;
static bool ebs_finished = false;
static unsigned int boot_complete_time = 0;
static int events_ebs = 0;
static const char *boot_prefix[16] = {
BOOT_EVT_PREFIX BOOT_EVT_PREFIX_PLATFORM,
BOOT_EVT_PREFIX BOOT_EVT_PREFIX_RIL,
BOOT_EVT_PREFIX BOOT_EVT_PREFIX_DEBUG,
BOOT_EVT_PREFIX BOOT_EVT_PREFIX_SYSTEMSERVER,
BOOT_EVT_PREFIX_NONE
};
enum boot_events_prefix {
EVT_PLATFORM,
EVT_RIL,
EVT_DEBUG,
EVT_SYSTEMSERVER,
EVT_INVALID,
};
enum boot_events_type {
SYSTEM_START_UEFI,
SYSTEM_START_LINUXLOADER,
SYSTEM_START_LINUX,
SYSTEM_START_INIT_PROCESS,
PLATFORM_START_PRELOAD,
PLATFORM_END_PRELOAD,
PLATFORM_START_INIT_AND_LOOP,
PLATFORM_START_PACKAGEMANAGERSERVICE,
PLATFORM_END_PACKAGEMANAGERSERVICE,
PLATFORM_START_NETWORK,
PLATFORM_END_NETWORK,
PLATFORM_END_INIT_AND_LOOP,
PLATFORM_PERFORMENABLESCREEN,
PLATFORM_ENABLE_SCREEN,
PLATFORM_BOOT_COMPLETE,
PLATFORM_FINISH_USER_UNLOCKED_COMPLETED,
PLATFORM_SET_ICON_VISIBILITY,
PLATFORM_LAUNCHER_ONCREATE,
PLATFORM_LAUNCHER_ONRESUME,
PLATFORM_LAUNCHER_LOADERTASK_RUN,
PLATFORM_LAUNCHER_FINISHFIRSTBIND,
PLATFORM_VOICE_SVC,
PLATFORM_DATA_SVC,
PLATFORM_PHONEAPP_ONCREATE,
RIL_UNSOL_RIL_CONNECTED,
RIL_SETRADIOPOWER_ON,
RIL_SETUICCSUBSCRIPTION,
RIL_SIM_RECORDSLOADED,
RIL_RUIM_RECORDSLOADED,
RIL_SETUPDATA_RECORDSLOADED,
RIL_SETUPDATACALL,
RIL_RESPONSE_SETUPDATACALL,
RIL_DATA_CONNECTION_ATTACHED,
RIL_DCT_IMSI_READY,
RIL_COMPLETE_CONNECTION,
RIL_CS_REG,
RIL_GPRS_ATTACH,
#ifdef CONFIG_SEC_FACTORY
FACTORY_BOOT_COMPLETE,
#endif /* CONFIG_SEC_FACTORY */
NUM_BOOT_EVENTS,
};
struct boot_event {
enum boot_events_type type;
enum boot_events_prefix prefix;
const char *string;
unsigned int time;
unsigned int ktime;
};
static struct boot_event boot_initcall[] = {
{0, EVT_INVALID, "early",},
{0, EVT_INVALID, "core",},
{0, EVT_INVALID, "postcore",},
{0, EVT_INVALID, "arch",},
{0, EVT_INVALID, "subsys",},
{0, EVT_INVALID, "fs",},
{0, EVT_INVALID, "device",},
{0, EVT_INVALID, "late",},
{0, EVT_INVALID, NULL,}
};
static int num_events;
static int boot_events_seq[NUM_BOOT_EVENTS];
static struct boot_event boot_events[] = {
{SYSTEM_START_UEFI, EVT_INVALID,
"Uefi start", 0, 0},
{SYSTEM_START_LINUXLOADER, EVT_INVALID,
"Linux loader start", 0, 0},
{SYSTEM_START_LINUX, EVT_INVALID,
"Linux start", 0, 0},
{SYSTEM_START_INIT_PROCESS, EVT_PLATFORM,
"start init process", 0, 0},
{PLATFORM_START_PRELOAD, EVT_PLATFORM,
"Begin of preload()", 0, 0},
{PLATFORM_END_PRELOAD, EVT_PLATFORM,
"End of preload()", 0, 0},
{PLATFORM_START_INIT_AND_LOOP, EVT_PLATFORM,
"Entered the Android system server!", 0, 0},
{PLATFORM_START_PACKAGEMANAGERSERVICE, EVT_PLATFORM,
"Start PackageManagerService", 0, 0},
{PLATFORM_END_PACKAGEMANAGERSERVICE, EVT_PLATFORM,
"End PackageManagerService", 0, 0},
{PLATFORM_START_NETWORK, EVT_DEBUG,
"start networkManagement", 0, 0},
{PLATFORM_END_NETWORK, EVT_DEBUG,
"end networkManagement", 0, 0},
{PLATFORM_END_INIT_AND_LOOP, EVT_PLATFORM,
"Loop forever", 0, 0},
{PLATFORM_PERFORMENABLESCREEN, EVT_PLATFORM,
"performEnableScreen", 0, 0},
{PLATFORM_ENABLE_SCREEN, EVT_PLATFORM,
"Enabling Screen!", 0, 0},
{PLATFORM_BOOT_COMPLETE, EVT_PLATFORM,
"bootcomplete", 0, 0},
{PLATFORM_FINISH_USER_UNLOCKED_COMPLETED, EVT_DEBUG,
"finishUserUnlockedCompleted", 0, 0},
{PLATFORM_SET_ICON_VISIBILITY, EVT_PLATFORM,
"setIconVisibility: ims_volte: [SHOW]", 0, 0},
{PLATFORM_LAUNCHER_ONCREATE, EVT_DEBUG,
"Launcher.onCreate()", 0, 0},
{PLATFORM_LAUNCHER_ONRESUME, EVT_DEBUG,
"Launcher.onResume()", 0, 0},
{PLATFORM_LAUNCHER_LOADERTASK_RUN, EVT_DEBUG,
"Launcher.LoaderTask.run() start", 0, 0},
{PLATFORM_LAUNCHER_FINISHFIRSTBIND, EVT_DEBUG,
"Launcher - FinishFirstBind", 0, 0},
{PLATFORM_VOICE_SVC, EVT_PLATFORM,
"Voice SVC is acquired", 0, 0},
{PLATFORM_DATA_SVC, EVT_PLATFORM,
"Data SVC is acquired", 0, 0},
{PLATFORM_PHONEAPP_ONCREATE, EVT_RIL,
"PhoneApp OnCrate", 0, 0},
{RIL_UNSOL_RIL_CONNECTED, EVT_RIL,
"RIL_UNSOL_RIL_CONNECTED", 0, 0},
{RIL_SETRADIOPOWER_ON, EVT_RIL,
"setRadioPower on", 0, 0},
{RIL_SETUICCSUBSCRIPTION, EVT_RIL,
"setUiccSubscription", 0, 0},
{RIL_SIM_RECORDSLOADED, EVT_RIL,
"SIM onAllRecordsLoaded", 0, 0},
{RIL_RUIM_RECORDSLOADED, EVT_RIL,
"RUIM onAllRecordsLoaded", 0, 0},
{RIL_SETUPDATA_RECORDSLOADED, EVT_RIL,
"SetupDataRecordsLoaded", 0, 0},
{RIL_SETUPDATACALL, EVT_RIL,
"setupDataCall", 0, 0},
{RIL_RESPONSE_SETUPDATACALL, EVT_RIL,
"Response setupDataCall", 0, 0},
{RIL_DATA_CONNECTION_ATTACHED, EVT_RIL,
"onDataConnectionAttached", 0, 0},
{RIL_DCT_IMSI_READY, EVT_RIL,
"IMSI Ready", 0, 0},
{RIL_COMPLETE_CONNECTION, EVT_RIL,
"completeConnection", 0, 0},
{RIL_CS_REG, EVT_RIL,
"CS Registered", 0, 0},
{RIL_GPRS_ATTACH, EVT_RIL,
"GPRS Attached", 0, 0},
#ifdef CONFIG_SEC_FACTORY
{FACTORY_BOOT_COMPLETE, EVT_PLATFORM,
"Factory Process [Boot Completed]", 0, 0},
#endif /* CONFIG_SEC_FACTORY */
{0, EVT_INVALID, NULL, 0, 0},
};
struct suspend_resume_event {
unsigned int type;
unsigned int state;
const char *string;
unsigned int cnt;
unsigned int time;
unsigned int ktime;
};
static unsigned int suspend_resume_cnt;
enum suspend_resume_type {
TYPE_SUSPEND,
TYPE_RESUME,
};
enum suspend_resume_state {
SUSPEND_EVENT_1,
SUSPEND_EVENT_2,
RESUME_EVENT_1,
RESUME_EVENT_2,
};
static struct suspend_resume_event suspend_resume_event[] = {
{TYPE_SUSPEND, SUSPEND_EVENT_1, "Syncing FS+", 0, 0, 0},
{TYPE_SUSPEND, SUSPEND_EVENT_2, "Syncing FS-", 0, 0, 0},
{TYPE_RESUME, RESUME_EVENT_1, "Freeze User Process+", 0, 0, 0},
{TYPE_RESUME, RESUME_EVENT_2, "Freeze User Process-", 0, 0, 0},
{TYPE_SUSPEND, SUSPEND_EVENT_1, "Freeze Remaining+", 0, 0, 0},
{TYPE_SUSPEND, SUSPEND_EVENT_1, "Freeze Remaining-", 0, 0, 0},
{TYPE_SUSPEND, SUSPEND_EVENT_1, "Suspending console", 0, 0, 0},
{0, 0, NULL, 0, 0, 0},
};
struct enhanced_boot_time {
struct list_head next;
char buf[MAX_LENGTH_OF_SYSTEMSERVER_LOG];
unsigned int time;
unsigned int ktime;
};
LIST_HEAD(device_init_time_list);
LIST_HEAD(systemserver_init_time_list);
LIST_HEAD(enhanced_boot_time_list);
static DEFINE_SPINLOCK(enhanced_boot_time_list_lock);
static int __init boot_recovery(char *str)
{
int temp = 0;
if (get_option(&str, &temp)) {
__is_boot_recovery = temp;
return 0;
}
return -EINVAL;
}
early_param("androidboot.boot_recovery", boot_recovery);
unsigned int is_boot_recovery(void)
{
return __is_boot_recovery;
}
static int sec_boot_stat_proc_show(struct seq_file *m, void *v)
{
size_t i;
unsigned long delta;
unsigned long freq = (unsigned long)get_boot_stat_freq();
unsigned long time, ktime, prev_time;
char boot_string[256];
struct device_init_time_entry *entry;
struct systemserver_init_time_entry *systemserver_entry;
if (!freq)
freq = DEFAULT_BOOT_STAT_FREQ;
seq_printf(m, "%-48s%s%13s%13s\n", "boot event", "time(msec)",
"ktime(msec)", "delta(msec)");
seq_puts(m, "------------------------------------------");
seq_puts(m, "-----------------------------------------\n");
/* print boot_events logged */
for (i = 0, prev_time = 0; i < num_events; i++) {
int seq = boot_events_seq[i];
time = (unsigned long)boot_events[seq].time * 1000 / freq;
ktime = (unsigned long)boot_events[seq].ktime;
delta = i ? time - prev_time : 0;
snprintf(boot_string, ARRAY_SIZE(boot_string), "%s%s",
boot_prefix[boot_events[seq].prefix],
boot_events[seq].string);
seq_printf(m, "%-45s : %9lu %9lu %9lu\n",
boot_string, time, ktime, delta);
prev_time = time;
}
seq_puts(m, "------------------------------------------");
seq_puts(m, "-----------------------------------------\n");
seq_puts(m, "kernel extra info\n\n");
for (i = 0, prev_time = 0; boot_initcall[i].string; i++) {
time = (unsigned long)boot_initcall[i].time * 1000 / freq;
ktime = (unsigned long)boot_initcall[i].ktime;
delta = ktime - prev_time;
seq_printf(m, "%-45s : %9lu %9lu %9lu\n",
boot_initcall[i].string, time, ktime, delta);
prev_time = ktime;
}
seq_printf(m, "\ndevice init time over %d ms\n\n",
DEVICE_INIT_TIME_100MS / 1000);
list_for_each_entry(entry, &device_init_time_list, next)
seq_printf(m, "%-20s : %lld usces\n",
entry->buf, entry->duration);
seq_puts(m, "------------------------------------------");
seq_puts(m, "-----------------------------------------\n");
seq_puts(m, "SystemServer services that took long time\n\n");
list_for_each_entry(systemserver_entry,
&systemserver_init_time_list, next)
seq_printf(m, "%s\n", systemserver_entry->buf);
return 0;
}
static int sec_boot_stat_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, sec_boot_stat_proc_show, NULL);
}
static const struct file_operations sec_boot_stat_proc_fops = {
.open = sec_boot_stat_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void sec_bootstat_add_initcall(const char *s)
{
size_t i = 0;
u64 t;
while (boot_initcall[i].string != NULL) {
if (!strcmp(s, boot_initcall[i].string)) {
t = local_clock();
do_div(t, 1000000ULL);
boot_initcall[i].ktime = (unsigned int)t;
break;
}
i = i + 1;
}
}
void sec_boot_stat_record_systemserver(const char *c)
{
struct systemserver_init_time_entry *entry;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
strlcpy(entry->buf, c, MAX_LENGTH_OF_SYSTEMSERVER_LOG);
entry->buf[MAX_LENGTH_OF_SYSTEMSERVER_LOG - 1] = 0;
list_add(&entry->next, &systemserver_init_time_list);
}
void sec_boot_stat_record(int idx, int time)
{
u64 t;
boot_events[idx].time = time;
if (idx >= SYSTEM_START_INIT_PROCESS && idx < NUM_BOOT_EVENTS) {
t = local_clock();
do_div(t, 1000000ULL);
boot_events[idx].ktime = (unsigned int)t;
}
boot_events_seq[num_events++] = idx;
}
void sec_enhanced_boot_stat_record(const char *buf)
{
u64 t;
int time = get_boot_stat_time();
struct enhanced_boot_time *entry;
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return;
strncpy(entry->buf, buf, MAX_LENGTH_OF_SYSTEMSERVER_LOG);
entry->buf[MAX_LENGTH_OF_SYSTEMSERVER_LOG - 1] = 0;
entry->time = time;
t = local_clock();
do_div(t, 1000000ULL);
entry->ktime = (unsigned int)t;
spin_lock(&enhanced_boot_time_list_lock);
list_add(&entry->next, &enhanced_boot_time_list);
spin_unlock(&enhanced_boot_time_list_lock);
events_ebs++;
}
void sec_boot_stat_add(const char *c)
{
size_t i;
unsigned int prefix;
char *android_log;
u64 t;
// Collect Boot_EBS from java side
if (bootcompleted && !ebs_finished) {
t = local_clock();
do_div(t, 1000000ULL);
if (t - boot_complete_time >= DELAY_TIME_EBS)
ebs_finished = true;
}
if (!ebs_finished && events_ebs < MAX_EVENTS_EBS) {
if(!strncmp(c, "!@Boot_EBS: ", 12)) {
sec_enhanced_boot_stat_record(c + 12);
return;
}
if(!strncmp(c, "!@Boot_EBS_", 11)) {
sec_enhanced_boot_stat_record(c);
return;
}
}
if (strncmp(c, BOOT_EVT_PREFIX, strlen(BOOT_EVT_PREFIX)))
return;
android_log = (char *)(c + strlen(BOOT_EVT_PREFIX));
if (!strncmp(android_log, BOOT_EVT_PREFIX_PLATFORM, 2)) {
prefix = EVT_PLATFORM;
android_log = (char *)(android_log + 2);
if (!strncmp(android_log, "bootcomplete", 12)) {
bootcompleted = true;
t = local_clock();
do_div(t, 1000000ULL);
boot_complete_time = (unsigned int)t;
}
} else if (!strncmp(android_log, BOOT_EVT_PREFIX_RIL, 7)) {
prefix = EVT_RIL;
android_log = (char *)(android_log + 7);
} else if (!strncmp(android_log, BOOT_EVT_PREFIX_DEBUG, 8)) {
prefix = EVT_DEBUG;
android_log = (char *)(android_log + 8);
} else if (!strncmp(android_log, BOOT_EVT_PREFIX_SYSTEMSERVER, 15)) {
prefix = EVT_SYSTEMSERVER;
android_log = (char *)(android_log + 15);
if (bootcompleted == false)
sec_boot_stat_record_systemserver(android_log);
return;
} else
return;
for (i = 0; boot_events[i].string; i++) {
if (!strcmp(android_log, boot_events[i].string)) {
if (!boot_events[i].time)
sec_boot_stat_record(i, get_boot_stat_time());
break;
}
}
}
static int sec_enhanced_boot_stat_proc_show(struct seq_file *m, void *v)
{
size_t i;
unsigned long delta;
unsigned long freq = (unsigned long)get_boot_stat_freq();
unsigned long time, ktime, prev_time;
struct enhanced_boot_time *enhanced_boot_time_entry;
if (!freq)
freq = DEFAULT_BOOT_STAT_FREQ;
seq_printf(m, "%-90s %6s %6s %6s\n", "boot event", "time",
"ktime", "delta");
seq_puts(m, "--------------------------------------------------------");
seq_puts(m, "-------------------------------------------------------\n");
seq_puts(m, "BOOTLOADER - KERNEL\n");
seq_puts(m, "--------------------------------------------------------");
seq_puts(m, "-------------------------------------------------------\n");
for (i = 0, prev_time = 0; boot_initcall[i].string; i++) {
time = (unsigned long)boot_initcall[i].time * 1000 / freq;
ktime = (unsigned long)boot_initcall[i].ktime;
delta = ktime - prev_time;
seq_printf(m, "%-90s %6lu %6lu %6lu\n",
boot_initcall[i].string, time, ktime, delta);
prev_time = ktime;
}
seq_puts(m, "--------------------------------------------------------");
seq_puts(m, "-------------------------------------------------------\n");
seq_puts(m, "FRAMEWORK\n");
seq_puts(m, "--------------------------------------------------------");
seq_puts(m, "-------------------------------------------------------\n");
list_for_each_entry_reverse (enhanced_boot_time_entry, &enhanced_boot_time_list, next) {
time = (unsigned long)enhanced_boot_time_entry->time * 1000 / freq;
ktime = (unsigned long)enhanced_boot_time_entry->ktime;
if (enhanced_boot_time_entry->buf[0] == '!') {
delta = ktime - prev_time;
seq_printf(m, "%-90s %6lu %6lu %6lu\n", enhanced_boot_time_entry->buf, time, ktime, delta);
prev_time = ktime;
} else {
seq_printf(m, "%-90s %6lu %6lu\n", enhanced_boot_time_entry->buf, time, ktime);
}
}
return 0;
}
static int sec_enhanced_boot_stat_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, sec_enhanced_boot_stat_proc_show, NULL);
}
static const struct file_operations sec_enhanced_boot_stat_proc_fops = {
.open = sec_enhanced_boot_stat_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int sec_suspend_resume_proc_show(struct seq_file *m, void *v)
{
unsigned long freq = (unsigned long)get_boot_stat_freq();
size_t i;
if (!freq)
freq = DEFAULT_BOOT_STAT_FREQ;
seq_printf(m, "%-53s : %6s %s\n",
"Suspend Resume Progress(Count)", "time", "ktime");
seq_puts(m, "------------------------------------------");
seq_puts(m, "-----------------------------------------\n");
for (i = 0; suspend_resume_event[i].string != NULL; i++) {
seq_printf(m, "%-45s(%6d) : %6d %6d\n",
suspend_resume_event[i].string,
suspend_resume_event[i].cnt,
suspend_resume_event[i].time * 1000 / (int)freq,
suspend_resume_event[i].ktime);
}
return 0;
}
static int sec_suspend_resume_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, sec_suspend_resume_proc_show, NULL);
}
static const struct file_operations sec_suspend_resume_proc_fops = {
.open = sec_suspend_resume_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
void sec_bootstat_suspend_resume_add(const char *c)
{
size_t i;
u64 t;
for (i = 0; suspend_resume_event[i].string != NULL; i++) {
if (!strcmp(c, suspend_resume_event[i].string)) {
if (!strcmp(c, "Suspending console"))
suspend_resume_cnt =
(suspend_resume_cnt + 1) % 1000;
suspend_resume_event[i].cnt = suspend_resume_cnt;
suspend_resume_event[i].time = get_boot_stat_time();
t = local_clock();
do_div(t, 1000000ULL);
suspend_resume_event[i].ktime = (unsigned int)t;
break;
}
}
}
static ssize_t store_boot_stat(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
if (!ebs_finished && events_ebs < MAX_EVENTS_EBS) {
if (!strncmp(buf, "!@Boot_EBS_", 11)) {
sec_enhanced_boot_stat_record(buf);
return count;
}
if (!strncmp(buf, "!@Boot_EBS: ", 12)) {
sec_enhanced_boot_stat_record(buf + 12);
return count;
}
}
if (!strncmp(buf, "!@Boot: start init process",
strlen("!@Boot: start init process")))
sec_boot_stat_record(SYSTEM_START_INIT_PROCESS,
get_boot_stat_time());
return count;
}
static DEVICE_ATTR(boot_stat, 0220, NULL, store_boot_stat);
static ssize_t store_suspend_resume(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
static uint64_t t;
t++;
return count;
}
static DEVICE_ATTR(suspend_resume, 0220, NULL, store_suspend_resume);
static struct attribute *sec_bsp_attributes[] = {
&dev_attr_boot_stat.attr,
&dev_attr_suspend_resume.attr,
NULL,
};
static const struct attribute_group sec_bsp_attribute_group = {
.attrs = sec_bsp_attributes,
};
static int __init sec_bsp_init(void)
{
int err;
struct proc_dir_entry *entry;
struct proc_dir_entry *enhanced_entry;
entry = proc_create("boot_stat", 0444, NULL,
&sec_boot_stat_proc_fops);
if (!entry)
return -ENOMEM;
sec_boot_stat_record(SYSTEM_START_UEFI, bs_uefi_start);
sec_boot_stat_record(SYSTEM_START_LINUXLOADER, bs_linuxloader_start);
sec_boot_stat_record(SYSTEM_START_LINUX, bs_linux_start);
enhanced_entry = proc_create("enhanced_boot_stat", 0444, NULL,
&sec_enhanced_boot_stat_proc_fops);
if (!enhanced_entry)
return -ENOMEM;
sec_bsp_dev = ___sec_device_create(NULL, "bsp");
if (unlikely(IS_ERR(sec_bsp_dev))) {
pr_err("Failed to create devce\n");
err = PTR_ERR(sec_bsp_dev);
goto err_dev_create;
}
err = sysfs_create_group(&sec_bsp_dev->kobj, &sec_bsp_attribute_group);
if (unlikely(err)) {
pr_err("Failed to create device files!\n");
goto err_dev_create_file;
}
/* Power State Logging */
entry = proc_create("suspend_resume", 0444, NULL,
&sec_suspend_resume_proc_fops);
if (unlikely(!entry)) {
err = -ENOMEM;
goto err_dev_crate_proc;
}
return 0;
err_dev_crate_proc:
sysfs_remove_group(&sec_bsp_dev->kobj, &sec_bsp_attribute_group);
err_dev_create_file:
sec_device_destroy(sec_bsp_dev->devt);
err_dev_create:
proc_remove(entry);
return err;
}
module_init(sec_bsp_init);