2012年6月27日 星期三

linux : debugfs

We can find out /sys/kernel/debug folder and we can create folder to debug our driver


Below is example code to create new folder and file in /sys/kernel/debug path

#include "linux/platform_device.h"
#include "linux/debugfs.h"
#include "linux/seq_file.h"
#include "linux/fs.h"
#include "linux/stat.h"

#define DEBUGFS 1
void foo_debug_dump_version(struct seq_file *s)
{
    int tmp=1.0;
    seq_printf(s, "==============\n %s \n", "foo_debug_dump_version");
    seq_printf(s,"version: %d \n",tmp);
  
}

static int foo_debugfs_show(struct seq_file *s, void *data)
{
    printk("%s \n", __func__);
    void (*func)(struct seq_file *) = s->private;
    func(s);
    //seq_printf(s,"version: %s \n","1.0");
    return 0;
}

static int foo_debugfs_open(struct inode *inode, struct file *file)
{
    printk("%s \n", __func__);
    return single_open(file, foo_debugfs_show, inode->i_private);
}


static const struct file_operations foo_debugfs_fops = {
    .open = foo_debugfs_open,
    .read = seq_read,
    .llseek = seq_lseek,
    .release = single_ release,
};

//step 1
struct dentry *foo_debugfs_dir;

static int foo_probe(struct platform_device *pdev)
{
    printk("%s", __func__);
//debugfs
    foo_debugfs_dir = debugfs_create_dir("foo_debug",NULL);
    if (IS_ERR(foo_debugfs_dir)) {
        goto err_node;
    }

    debugfs_create_file("foo_version", ( S_IRUGO | S_IWUSR ), foo_debugfs_dir,
                &foo_debug_dump_version, &foo_debugfs_fops);
    pr_info(" debugfs entries created ");
    return 0;
//~debugfs 
err_node:
    debugfs_remove_recursive(foo_debugfs_dir);
    foo_debugfs_dir = NULL;
    pr_err(" debugfs entries creation failed ");
    return -EIO;

}

static int foo_remove(struct platform_device *pdev)
{
    printk("%s", __func__);
    debugfs_remove_recursive(foo_debugfs_dir);
    return 0;
}

static struct platform_driver foo_driver = {
    .probe = foo_probe,
    .remove = foo_remove,
    .driver =  {
        .name = "foo_device",
        .owner = THIS_MODULE,
    },
};
static int __init foo_init(void)
{
    return platform_driver_register(&foo_driver);
}

static void __exit foo_exit(void)
{
    return platform_driver_unregister(&foo_driver);
}

module_init(foo_init);
module_exit(foo_exit);

MODULE_DESCRIPTION("foo driver ");


2012年6月26日 星期二

Linux driver :platform devices and driver

find out at /sys/bus/platform/devices and /sys/bus/platform/drivers

ex:
./arch/arm/board-file.c
+static struct platform_device foo_device = {
+       .name       = "foo_device",
+       .id     = -1,
+       .dev        = {
+               .platform_data = NULL,
+       },
+};

This will create foo_device at /sys/devices/platform/

ex:
./driver/misc/foo.c

static struct platform_driver foo_driver = {
    .probe = foo_probe,
    .driver =  {
        .name = "foo_device",
        .owner = THIS_MODULE,
    },
};
static int __init foo_init(void)
{  
    return platform_driver_register(&foo_driver);


static void __exit foo_exit(void)
{
    return platform_driver_unregister(&foo_driver);


This will find the foo_device folder at /sys/bus/platform/drivers




/sys/bus/platform/drivers/foo_device # ls
bind             foo_device  uevent           unbind

/sys/bus/platform/drivers/foo_device # ls foo_device/
driver     modalias   power      subsystem  uevent




2012年6月1日 星期五

android reboot process

  1. frameworks/base/core/java/android/os/Power.java  android_os_Power_reboot()
  2. frameworks/base/core/jni/android_os_Power.cpp 
    reboot()
  3. bionic/libc/unistd/reboot.c
    reboot(__reboot)
  4. bionic/libc/arch-arm/syscalls/__reboot.S
  5. kernel/arch/sh/kernel/reboot.c
    struct machine_ops machine_ops = {
        .power_off  = native_machine_power_off,
        .shutdown   = native_machine_shutdown,
        .restart    = native_machine_restart,
        .halt       = native_machine_halt,
    }
  6. bionic/libc/include/sys/linux-syscalls.h
    #define __NR_reboot                       (__NR_SYSCALL_BASE + 88)
  7. ./arch/arm/kernel/calls.S
    __NR_reboot 就是系统函数sys_reboot
  8. ./kernel/sys.c

    kernel_restart
    {
          kernel_restart_prepare(cmd);  
        if (!cmd)
            printk(KERN_EMERG "Restarting system.\n");
        else
            printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);
        kmsg_dump(KMSG_DUMP_RESTART); 
        machine_restart(cmd);

    }

    void kernel_restart_prepare(char *cmd)
    {
        blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
        system_state = SYSTEM_RESTART;
        usermodehelper_disable();
        device_shutdown();
        syscore_shutdown();
    }

    void kernel_power_off(void)
    {
        kernel_shutdown_prepare(SYSTEM_POWER_OFF);
        if (pm_power_off_prepare)
            pm_power_off_prepare();
        disable_nonboot_cpus();
        syscore_shutdown();
        printk(KERN_EMERG "Power down.\n");
        kmsg_dump(KMSG_DUMP_POWEROFF);
        machine_power_off();
    }


  9. kernel/arch/arm/kernel/process.c
    void machine_shutdown(void)
    {
    #ifdef CONFIG_SMP
        smp_send_stop();
    #endif
    }

    void machine_halt(void)
    {
        machine_shutdown();
        while (1);
    }

    void machine_power_off(void)
    {
        machine_shutdown();
        if (pm_power_off)
            pm_power_off();
    }

    void machine_restart(char *cmd)
    {
        machine_shutdown();
        arm_pm_restart(reboot_mode, cmd);
    }
  10. If you would like to trace power_off
    kernel/driver/mfd/xxxx_poweroff.c
    You will see:
    pm_power_off=xxxx_poweroff