summaryrefslogtreecommitdiff
path: root/kernel-devel/linux-device
diff options
context:
space:
mode:
Diffstat (limited to 'kernel-devel/linux-device')
-rw-r--r--kernel-devel/linux-device/Makefile9
-rw-r--r--kernel-devel/linux-device/hints_linux-device_en.tex15
-rw-r--r--kernel-devel/linux-device/my_example.patch122
-rw-r--r--kernel-devel/linux-device/pres_linux-device_en.tex236
4 files changed, 382 insertions, 0 deletions
diff --git a/kernel-devel/linux-device/Makefile b/kernel-devel/linux-device/Makefile
new file mode 100644
index 0000000..be2c24b
--- /dev/null
+++ b/kernel-devel/linux-device/Makefile
@@ -0,0 +1,9 @@
+all:
+ for pdf in `ls -1 *.tex` ; do \
+ TEXINPUTS=`pwd`:`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \
+ TEXINPUTS=`pwd`:`pwd`/../..:.:..:$(TEXINPUTS) pdflatex $$pdf; \
+ done
+
+clean:
+ rm -f *.aux *.log *.pdf *.log *.snm *.toc *.vrb *.nav *.out
+
diff --git a/kernel-devel/linux-device/hints_linux-device_en.tex b/kernel-devel/linux-device/hints_linux-device_en.tex
new file mode 100644
index 0000000..20174ab
--- /dev/null
+++ b/kernel-devel/linux-device/hints_linux-device_en.tex
@@ -0,0 +1,15 @@
+\documentclass{article}
+\usepackage{german}
+\usepackage[utf8]{inputenc}
+
+\begin{document}
+
+\section*{Linux Device Structure\rq}
+
+\subsection*{Lernziele}
+\begin{itemize}
+\item Sinn und Zweck von 'struct device'
+\item wichtige Funktionen in Verbindung mit 'struct device'
+\end{itemize}
+
+\end{document}
diff --git a/kernel-devel/linux-device/my_example.patch b/kernel-devel/linux-device/my_example.patch
new file mode 100644
index 0000000..6e66c14
--- /dev/null
+++ b/kernel-devel/linux-device/my_example.patch
@@ -0,0 +1,122 @@
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index c779509..43ae42d 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -51,6 +51,11 @@ config AD525X_DPOT_SPI
+ To compile this driver as a module, choose M here: the
+ module will be called ad525x_dpot-spi.
+
++config MY
++ tristate "my driver example"
++ help
++ just an example for a simple driver dummy
++
+ config ATMEL_PWM
+ tristate "Atmel AT32/AT91 PWM support"
+ depends on HAVE_CLK
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 3e1d801..614a3a2 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -8,6 +8,7 @@ obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
+ obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
+ obj-$(CONFIG_INTEL_MID_PTI) += pti.o
+ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
++obj-$(CONFIG_MY) += my.o
+ obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
+ obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o
+ obj-$(CONFIG_BMP085) += bmp085.o
+diff --git a/drivers/misc/my.c b/drivers/misc/my.c
+new file mode 100644
+index 0000000..49759ad
+--- /dev/null
++++ b/drivers/misc/my.c
+@@ -0,0 +1,88 @@
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/types.h>
++
++#define DEVICE_NAME "mydev"
++static struct class *dummy;
++
++static ssize_t my_show_ro(struct device *my_dev,
++ struct device_attribute *my_attr, char *buf)
++{
++ return scnprintf(buf, PAGE_SIZE, "%s\n", "show some cool value");
++}
++
++static ssize_t my_show_rw(struct device *my_dev,
++ struct device_attribute *my_attr, char *buf)
++{
++ return scnprintf(buf, PAGE_SIZE, "%s\n", "write value and look at dmesg");
++}
++
++static ssize_t my_store_rw(struct device *my_dev,
++ struct device_attribute *my_attr, const char *buf, size_t count)
++{
++ printk(KERN_ERR "my_store_rw: %s", buf);
++ return count;
++}
++
++static DEVICE_ATTR(ro, S_IRUGO, my_show_ro, NULL);
++static DEVICE_ATTR(rw, S_IWUSR | S_IRUGO, my_show_rw, my_store_rw);
++
++static struct attribute *my_dev_attrs[] = {
++ &dev_attr_ro.attr,
++ &dev_attr_rw.attr,
++ NULL,
++};
++
++static struct attribute_group my_dev_attr_group = {
++ .attrs = my_dev_attrs,
++};
++
++static const struct attribute_group *my_dev_attr_groups[] = {
++ &my_dev_attr_group,
++ NULL,
++};
++
++static struct device my_dev = {
++ .init_name = "mydevice",
++};
++
++static int __init my_init(void)
++{
++ int ret = 0;
++
++ dummy = class_create(THIS_MODULE, "dummy");
++ device_initialize(&my_dev);
++ my_dev.groups = my_dev_attr_groups;
++ my_dev.parent = NULL;
++ my_dev.bus = NULL;
++ my_dev.class = dummy;
++ ret = device_add(&my_dev);
++ if (ret) {
++ printk(KERN_ERR "my: device register failed\n");
++ goto failed_dev;
++ }
++ return 0;
++
++failed_dev:
++ device_del(&my_dev);
++ class_destroy(dummy);
++
++ return ret;
++}
++
++static void __exit my_exit(void)
++{
++ device_del(&my_dev);
++ class_destroy(dummy);
++}
++
++MODULE_AUTHOR("Manuel Traut");
++MODULE_DESCRIPTION("just my example");
++MODULE_VERSION("20120412");
++MODULE_LICENSE("GPL");
++
++module_init(my_init);
++module_exit(my_exit);
diff --git a/kernel-devel/linux-device/pres_linux-device_en.tex b/kernel-devel/linux-device/pres_linux-device_en.tex
new file mode 100644
index 0000000..da4ca55
--- /dev/null
+++ b/kernel-devel/linux-device/pres_linux-device_en.tex
@@ -0,0 +1,236 @@
+\input{configpres}
+
+\title{struct device}
+\maketitle
+
+\subsection{basics}
+
+\begin{frame}
+\frametitle{aim}
+\begin{itemize}
+\item lowest level representation of every device in a Linux system
+\item hosts information that the device model core needs to model the system
+\item most subsystems track additional information about the devices they host
+\item it is rare for devices to be represented by bare device structures
+\item this struct is usually embedded within higher-level representation of
+ the device
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{name and type}
+for example a mouse device
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+include/linux/device.h:
+...
+struct device {
+ ...
+ const char *init_name;
+ const struct device_type *type;
+ ...
+\end{lstlisting}
+\end{tiny}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{connection of multiple devices}
+for example usb-hostcontroller1/usb-device3/usb-endpoint4/mouse
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+include/linux/device.h:
+...
+struct device {
+ ...
+ struct device *parent;
+ ...
+\end{lstlisting}
+\end{tiny}
+\begin{itemize}
+\item 'parent' is a ptr to the device to which this device is attached
+\item normaly a parent device is some sort of bus or host controller
+\item If parent is NULL, the device, is a top-level device, which is not
+ usually what you want
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{private data}
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+drivers/base/base.h
+...
+struct device_private {
+ struct klist klist_children; //containing all children of this device
+ struct klist_node knode_parent; //node in sibling list
+ struct klist_node knode_driver; //node in driver list
+ struct klist_node knode_bus; //node in bus list
+ struct list_head deferred_probe;//entry in deferred_probe_list
+ void *driver_data; //private pointer for driver specific info
+ struct device *device; //pointer back to the device
+};
+...
+include/linux/device.h:
+...
+struct device {
+ ...
+ struct device_private *p;
+ ...
+\end{lstlisting}
+\end{tiny}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{bus}
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+include/linux/device.h:
+...
+struct device {
+ ...
+ struct bus_type *bus;
+ ...
+\end{lstlisting}
+\end{tiny}
+\begin{itemize}
+\item used by driver core to link between bus - device
+\item hosts pointer for: probe, remove, suspend, \dots
+\item these functions are called by the driver core on bus state changes
+\item bus drivers need to implement these calls and normaly redirect them to
+ the associated devices
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{driver}
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+include/linux/device.h:
+...
+struct device {
+ ...
+ struct device_driver *driver;
+ ...
+\end{lstlisting}
+\end{tiny}
+\begin{itemize}
+\item used by driver core to link between driver - device
+\item hosts a table of device id, the driver is responsible for
+\item hosts pointer for: probe, remove, suspend, \dots
+\item these functions are called by the bus driver on bus state changes
+\item device drivers need to implement these calls
+\item e.g. after a succesful probe call a driver is responsible for a device
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{platform data}
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+include/linux/device.h:
+...
+struct device {
+ ...
+ void *platform_data;
+ ...
+\end{lstlisting}
+\end{tiny}
+\begin{itemize}
+\item structure is declared by the platform device driver
+\item structure is normally initialized by 'board support package'
+\item hosts for example how a specific device is connected (mem\_base, irq)
+\item can host informations about chip variants
+\item shrinks 'board support packages'
+\item reduces board specific \#ifdefs in driver code
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{misc}
+\begin{itemize}
+\item structs for device power management
+\item ptr to NUMA node this device is close to
+\item structs for DMA handling (if device is DMA capable)
+\item information about associated device node(s) (/dev/huhu)
+\item unique device id
+\item lock to protect device resources
+\item pointer to release() function of the device
+\end{itemize}
+\end{frame}
+
+\subsection{how is it used}
+
+\begin{frame}[fragile]
+\frametitle{initialization}
+The bus driver that discovers the device uses this to register the device with
+the core:
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+int device_register(struct device * dev);
+\end{lstlisting}
+\end{tiny}
+these fields should be initialized before calling the register function:
+\begin{itemize}
+\item parent
+\item name
+\item bus
+\item class
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{use by a driver}
+A device is removed from the core when its reference count goes to 0.
+The reference count can be adjusted using:
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+struct device * get_device(struct device * dev);
+void put_device(struct device * dev);
+\end{lstlisting}
+\end{tiny}
+The device lock can be accessed by:
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+void lock_device(struct device * dev);
+void unlock_device(struct device * dev);
+\end{lstlisting}
+\end{tiny}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{device attributes}
+Attributes can be exported to sysfs by the device driver.
+\begin{tiny}
+\begin{lstlisting}[frame=trBL]
+my.c:
+...
+static DEVICE_ATTR(ro_example, 0444, my_show_ro, NULL);
+static DEVICE_ATTR(rw_example, 0644, my_show_rw, my_store_rw);
+
+static struct attribute *my_dev_attrs[] = {
+ &dev_attr_ro_example.attr,
+ &dev_attr_rw_example.attr,
+ NULL,
+};
+
+static struct attribute_group my_dev_attr_group = {
+ .attrs = my_dev_attrs,
+};
+
+static const struct attribute_group *my_dev_attr_groups[] = {
+ &my_dev_attr_group,
+ NULL,
+};
+
+static int __init my_driver_init(struct device *my_dev)
+{
+ ...
+ my_dev->groups = my_dev_attr_groups;
+ device_register(my_dev);
+ ...
+}
+\end{lstlisting}
+\end{tiny}
+\end{frame}
+
+\input{tailpres}