Tuesday, February 28, 2017

Linux Device Tree (DT)

Device tree

Earlier kernel was containing the entire description of the hardware
bootloader loads the single binary, kernel image uimage or zimage, it contained the hardware information
bootloader loads it by passing below additional inform
r1= machine type
r2 = ATAGS

With Device tree, description of the hardware it is located in seperate binary - device tree blob
Seperate compilation of kernel image is not required.
Bootloader passed the below information to load kernel.
r1 = don't care
r2 = pointer to DTB

A device tree is a tree data structure with nodes that describes the physical devices in a system. 

Device tree files are kept at location
/arch/arm/boot/dts

Basic Device Tree: Tree syntax and compilation




In dts file
it starts with /, root node
It inherits several dtsi file.

Below are the few major APIs in current kernel (4.3) for reading the various properties from DTS.

of_address_to_resource: Reads the memory address of device defined by res property

irq_of_parse_and_map: Attach the interrupt handler, provided by the properties interrupt and interrupt-parent

of_find_property(np, propname, NULL): To find if property named in argument2 is present or not.

of_property_read_bool: To read a bool property named in argument 2, as it is a bool property it just like searching if that property present or not. Returns true or false

of_get_property: For reading any property named in argument 2

of_property_read_u32: To read a 32 bit property, populate into 3rd argument. Doesn’t set anything to 3rd argument in case of error.

of_property_read_string: To read string property

of_match_device: Sanity check for device that device is matching with the node, highly optional, I don’t see much use of it.

Links for more reference:-
https://saurabhsengarblog.wordpress.com/2015/11/28/device-tree-tutorial-arm/
http://elinux.org/Device_Tree_Usage
https://events.linuxfoundation.org/sites/events/files/slides/petazzoni-device-tree-dummies.pdf

Monday, February 27, 2017

Creating Syfs Entry


The sysfs filesystem is an in-memory virtual filesystem that provides a view of the kobject hierarachy. It enables users to view the device topology.
The magic behind sysfs is simply tying kobjects to directory entries via the dentry member inside each kobject.

Adding and Removing kobjects from sysfs

int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt) ..
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent);
void kobject_del(struct kobject *kobj)
</linux/kobject.h>

Default Attributes
A default set of files is provided via ktype field in kobjects and ksets.
</linux/sysfs.h>
struct attribute
{
const char *name;
struct module *owner;
mode_t mode;
};

struct sysfs_ops{
ssize_t (*show) (struct kobject *kobj, struct attribute *attr, char *buffer);
ssize_t (*store) (struct kobject *kobj, struct attribute *attr, const char *buffer, size_t size);
}

Creating and Destroying New Attributes
int sysfs_create_file(struct kobject *kobj, const struct attribute *attr);
int sysfs_create_link(struct kobject *kobj, struct kobject *target, char *name);

void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
void sysfs_remove_link(struct kobject *kobj, char *name);

Example1:-

..
static ssize_t top_off_threshold_current_show(struct device *dev,struct device_attribute *attr, char *buf){

}
static ssize_t top_off_threshold_current_store(struct device *dev,struct device_attribute *attr, char *buf,size_t count){
}
..
static DEVICE_ATTR_RW(top_off_threshold_current);
..
probe()
{

..
 ret = device_create_file(&pdev->dev,&dev_attr_top_off_threshold_current);  
// NOTE:- device_create_file internally calls sysfs_create_file
     if (ret) {
             dev_err(&pdev->dev, "failed: create top off current sysfs entry\n");
               goto err;

    }
..
err: device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
}
remove()
{
device_remove_file(&pdev->dev, &dev_attr_top_off_threshold_current);
}

Example2:- 

static DEVICE_ATTR_RW(top_off_threshold_current);
..
..
static struct attribute *max77693_charger_attribute[] = {
&dev_attr_fast_charge_timer.attr,
&dev_attr_top_off_threshold_current.attr,
&dev_attr_top_off_timer.attr,
NULL,
};

static const struct attribute_group max77693_attr_group = {
.attrs = max77693_charger_attribute,

};

probe()
{
..
ret = sysfs_create_group(&pdev->dev.kobj, &max77693_attr_group);
if (ret != 0) {
dev_err(&pdev->dev, "Can't create sysfs entries\n");
return ret;

}
..
}
remove()
{
sysfs_remove_group(&pdev->dev.kobj, &max77693_attr_group);
}


Example3:- 

#include <linux/module.h>
#include <linux/printk.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/string.h>
static struct kobject *example_kobject;
static int foo;

static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
                      char *buf)
{
        return sprintf(buf, "%d\n", foo);
}

static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
                      char *buf, size_t count)
{
        sscanf(buf, "%du", &foo);
        return count;
}


static struct kobj_attribute foo_attribute =__ATTR(foo, 0660, foo_show,
                                                   foo_store);

static int __init mymodule_init (void)
{
        int error = 0;

        pr_debug("Module initialized successfully \n");

        example_kobject = kobject_create_and_add("kobject_example",
                                                 kernel_kobj);   //kernel_kobj is the parent
        if(!example_kobject)
                return -ENOMEM;

        error = sysfs_create_file(example_kobject, &foo_attribute.attr);
        if (error) {
                pr_debug("failed to create the foo file in /sys/kernel/kobject_example \n");
        }

        return error;
}

static void __exit mymodule_exit (void)
{
        pr_debug ("Module un initialized successfully \n");
        kobject_put(example_kobject);

}

Linux Device Model (LDM)


Explain about the Linux Device Model (LDM)? 

In 2.6 Linux Kernel there was a addition of unified device model.
The device model provides a single mechanism for representing devices and describing their topology in the system.

Such system provide several benefits:-
1. Minimization of code duplication
2. A mechanism for providing common facility such as reference counting. 
3. The capability to enumerate all the devices in the system, view their status and see to what bus they attach.
4. The capability to generate a complete and valid tree of the entire device structure of the system, including all buses and interconnections.
5. The capability to link devices to their drivers and vice-versa.
6. The capability to categorise devices by their class, such as input device, without the need to understand the physical device topology.
7. The capability to walk the tree of devices from the leaves up to the root, powering down devices in the correct order. 


Explain about about ksets, kobjects and ktypes. How are they related?

Kobjects:- 
At the heart of the device model is the kobjects, short for kernel objects, which is represented by struct object and defined  /include/linux/kobject.h
http://lxr.free-electrons.com/source/include/linux/kobject.h













Kobject is similar to object class in object-oriented languages such as C# or Java.
It provides basic facilities such as reference counting, a name, a parent pointer, enabling creation of the hierarchy. 
->Name pointer points to the name of this kobject.
-> The parent pointer points to this kobject's parent. In this way it developed hierarachy.
(Sysfs is a user-space filesystem representation of the kobject hierarchy inside the kernel) 
-> The sd pointer points to a sysfs_dirent structure that represents this kobjects in sysfs.
-> kref - reference count


Kobjects are usually embedded in other structure and are generally not interesting on their own.
Instead a more important structure such as struct device, defined in /include/linux/device.h
http://lxr.free-electrons.com/source/include/linux/device.h#L32



















Ktypes:- 
Kobjects are associated with a specific type, called a ktype, short for kernel object type.
Ktypes are represented by struct kobj_type and defined in /linux/kobject.h
Ktypes have the simple job of describing default behaviour for a family of kobjects. 
Instead of each kobject defining its own behaviour is stored in a ktype, and kobjects of the same type points at the same ktype structure, this sharing the same behaviour.








->release pointer points to the decontructor called when a kobject's reference count reaches zero. 
This function is responsible for freeing any memory associated with this kobject and otherwise cleanup. 
->sysfsops variable points to a sysfs_ops structure. This structure describes the behaviour of sysfs files on read and write.
->default_attrs points to an array of attribute structures. these structurees define the default attributes assocaited with this kobjects. 

Ksets:- 

Ksets short for kernel objects sets, are aggregate collections of kobjects. Ksets work as the base container class for a set of kernel objects, collecting related kobjects, such as "all block devices". 

Ksets might sound similar to Ktypes, but they are different. 
Ksets group related kernel objects together, whereas ktypes enable kernel objects (functionally related or not) to share common operations. 























Relation of kobjects, ktypes and ksets

The important key object is the kobject, represented by struct kobject. The kobject introduces basic object properties—such as reference counting, parent-child relationship, and naming—to kernel data structures.The kobject structure provides these features in a standard unified way. Kobjects, in and of themselves, are not particularly useful. Instead, kobjects are typically embedded in other data structures, giving those containing structures the features of the kobject.

Kobjects are associated with a specific ktype, which is represented by struct kobj_type and pointed at by the ktype variable inside of the kobject. ktypes define some default properties of related kobjects: destruction behavior, sysfs behavior, and default attributes.The ktype structure is not well named; think of ktypes not as a grouping but as a set of shared operations.

Kobjects are then grouped into sets, called ksets, which are represented by struct kset. Ksets provide two functions. First, their embedded kobject acts as a base class for a group of kobjects. Second, ksets aggregate together related kobjects. In sysfs, kobjects are the individual directories in the filesystem. Related directories—say, perhaps all subdirectories of a given directory—might be in the same kset.