Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6: sysfs: fix off-by-one error in fill_read_buffer() kobject: two typo fixes UIO: add UIO documentation target to DocBook Makefile UIO: fix up the UIO documentation create /sys/.../power when CONFIG_PM is set allow LEGACY_PTYS to be set to 0
This commit is contained in:
@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
|
|||||||
procfs-guide.xml writing_usb_driver.xml \
|
procfs-guide.xml writing_usb_driver.xml \
|
||||||
kernel-api.xml filesystems.xml lsm.xml usb.xml \
|
kernel-api.xml filesystems.xml lsm.xml usb.xml \
|
||||||
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||||
genericirq.xml s390-drivers.xml
|
genericirq.xml s390-drivers.xml uio-howto.xml
|
||||||
|
|
||||||
###
|
###
|
||||||
# The build process is as follows (targets):
|
# The build process is as follows (targets):
|
||||||
|
@@ -29,6 +29,12 @@
|
|||||||
</abstract>
|
</abstract>
|
||||||
|
|
||||||
<revhistory>
|
<revhistory>
|
||||||
|
<revision>
|
||||||
|
<revnumber>0.4</revnumber>
|
||||||
|
<date>2007-11-26</date>
|
||||||
|
<authorinitials>hjk</authorinitials>
|
||||||
|
<revremark>Removed section about uio_dummy.</revremark>
|
||||||
|
</revision>
|
||||||
<revision>
|
<revision>
|
||||||
<revnumber>0.3</revnumber>
|
<revnumber>0.3</revnumber>
|
||||||
<date>2007-04-29</date>
|
<date>2007-04-29</date>
|
||||||
@@ -94,6 +100,26 @@ interested in translating it, please email me
|
|||||||
user space. This simplifies development and reduces the risk of
|
user space. This simplifies development and reduces the risk of
|
||||||
serious bugs within a kernel module.
|
serious bugs within a kernel module.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
Please note that UIO is not an universal driver interface. Devices
|
||||||
|
that are already handled well by other kernel subsystems (like
|
||||||
|
networking or serial or USB) are no candidates for an UIO driver.
|
||||||
|
Hardware that is ideally suited for an UIO driver fulfills all of
|
||||||
|
the following:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>The device has memory that can be mapped. The device can be
|
||||||
|
controlled completely by writing to this memory.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>The device usually generates interrupts.</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>The device does not fit into one of the standard kernel
|
||||||
|
subsystems.</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="thanks">
|
<sect1 id="thanks">
|
||||||
@@ -174,8 +200,9 @@ interested in translating it, please email me
|
|||||||
For cards that don't generate interrupts but need to be
|
For cards that don't generate interrupts but need to be
|
||||||
polled, there is the possibility to set up a timer that
|
polled, there is the possibility to set up a timer that
|
||||||
triggers the interrupt handler at configurable time intervals.
|
triggers the interrupt handler at configurable time intervals.
|
||||||
See <filename>drivers/uio/uio_dummy.c</filename> for an
|
This interrupt simulation is done by calling
|
||||||
example of this technique.
|
<function>uio_event_notify()</function>
|
||||||
|
from the timer's event handler.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -263,63 +290,11 @@ offset = N * getpagesize();
|
|||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="using-uio_dummy" xreflabel="Using uio_dummy">
|
|
||||||
<?dbhtml filename="using-uio_dummy.html"?>
|
|
||||||
<title>Using uio_dummy</title>
|
|
||||||
<para>
|
|
||||||
Well, there is no real use for uio_dummy. Its only purpose is
|
|
||||||
to test most parts of the UIO system (everything except
|
|
||||||
hardware interrupts), and to serve as an example for the
|
|
||||||
kernel module that you will have to write yourself.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect1 id="what_uio_dummy_does">
|
|
||||||
<title>What uio_dummy does</title>
|
|
||||||
<para>
|
|
||||||
The kernel module <filename>uio_dummy.ko</filename> creates a
|
|
||||||
device that uses a timer to generate periodic interrupts. The
|
|
||||||
interrupt handler does nothing but increment a counter. The
|
|
||||||
driver adds two custom attributes, <varname>count</varname>
|
|
||||||
and <varname>freq</varname>, that appear under
|
|
||||||
<filename>/sys/devices/platform/uio_dummy/</filename>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The attribute <varname>count</varname> can be read and
|
|
||||||
written. The associated file
|
|
||||||
<filename>/sys/devices/platform/uio_dummy/count</filename>
|
|
||||||
appears as a normal text file and contains the total number of
|
|
||||||
timer interrupts. If you look at it (e.g. using
|
|
||||||
<function>cat</function>), you'll notice it is slowly counting
|
|
||||||
up.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The attribute <varname>freq</varname> can be read and written.
|
|
||||||
The content of
|
|
||||||
<filename>/sys/devices/platform/uio_dummy/freq</filename>
|
|
||||||
represents the number of system timer ticks between two timer
|
|
||||||
interrupts. The default value of <varname>freq</varname> is
|
|
||||||
the value of the kernel variable <varname>HZ</varname>, which
|
|
||||||
gives you an interval of one second. Lower values will
|
|
||||||
increase the frequency. Try the following:
|
|
||||||
</para>
|
|
||||||
<programlisting format="linespecific">
|
|
||||||
cd /sys/devices/platform/uio_dummy/
|
|
||||||
echo 100 > freq
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
Use <function>cat count</function> to see how the interrupt
|
|
||||||
frequency changes.
|
|
||||||
</para>
|
|
||||||
</sect1>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="custom_kernel_module" xreflabel="Writing your own kernel module">
|
<chapter id="custom_kernel_module" xreflabel="Writing your own kernel module">
|
||||||
<?dbhtml filename="custom_kernel_module.html"?>
|
<?dbhtml filename="custom_kernel_module.html"?>
|
||||||
<title>Writing your own kernel module</title>
|
<title>Writing your own kernel module</title>
|
||||||
<para>
|
<para>
|
||||||
Please have a look at <filename>uio_dummy.c</filename> as an
|
Please have a look at <filename>uio_cif.c</filename> as an
|
||||||
example. The following paragraphs explain the different
|
example. The following paragraphs explain the different
|
||||||
sections of this file.
|
sections of this file.
|
||||||
</para>
|
</para>
|
||||||
@@ -354,9 +329,8 @@ See the description below for details.
|
|||||||
interrupt, it's your modules task to determine the irq number during
|
interrupt, it's your modules task to determine the irq number during
|
||||||
initialization. If you don't have a hardware generated interrupt but
|
initialization. If you don't have a hardware generated interrupt but
|
||||||
want to trigger the interrupt handler in some other way, set
|
want to trigger the interrupt handler in some other way, set
|
||||||
<varname>irq</varname> to <varname>UIO_IRQ_CUSTOM</varname>. The
|
<varname>irq</varname> to <varname>UIO_IRQ_CUSTOM</varname>.
|
||||||
uio_dummy module does this as it triggers the event mechanism in a timer
|
If you had no interrupt at all, you could set
|
||||||
routine. If you had no interrupt at all, you could set
|
|
||||||
<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
|
<varname>irq</varname> to <varname>UIO_IRQ_NONE</varname>, though this
|
||||||
rarely makes sense.
|
rarely makes sense.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
|
@@ -770,9 +770,10 @@ int device_add(struct device *dev)
|
|||||||
error = device_add_attrs(dev);
|
error = device_add_attrs(dev);
|
||||||
if (error)
|
if (error)
|
||||||
goto AttrsError;
|
goto AttrsError;
|
||||||
error = device_pm_add(dev);
|
error = dpm_sysfs_add(dev);
|
||||||
if (error)
|
if (error)
|
||||||
goto PMError;
|
goto PMError;
|
||||||
|
device_pm_add(dev);
|
||||||
error = bus_add_device(dev);
|
error = bus_add_device(dev);
|
||||||
if (error)
|
if (error)
|
||||||
goto BusError;
|
goto BusError;
|
||||||
@@ -797,6 +798,7 @@ int device_add(struct device *dev)
|
|||||||
return error;
|
return error;
|
||||||
BusError:
|
BusError:
|
||||||
device_pm_remove(dev);
|
device_pm_remove(dev);
|
||||||
|
dpm_sysfs_remove(dev);
|
||||||
PMError:
|
PMError:
|
||||||
if (dev->bus)
|
if (dev->bus)
|
||||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
obj-y := shutdown.o
|
obj-y := shutdown.o
|
||||||
obj-$(CONFIG_PM_SLEEP) += main.o sysfs.o
|
obj-$(CONFIG_PM) += sysfs.o
|
||||||
|
obj-$(CONFIG_PM_SLEEP) += main.o
|
||||||
obj-$(CONFIG_PM_TRACE) += trace.o
|
obj-$(CONFIG_PM_TRACE) += trace.o
|
||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
||||||
|
@@ -38,20 +38,14 @@ static DEFINE_MUTEX(dpm_list_mtx);
|
|||||||
int (*platform_enable_wakeup)(struct device *dev, int is_on);
|
int (*platform_enable_wakeup)(struct device *dev, int is_on);
|
||||||
|
|
||||||
|
|
||||||
int device_pm_add(struct device *dev)
|
void device_pm_add(struct device *dev)
|
||||||
{
|
{
|
||||||
int error;
|
|
||||||
|
|
||||||
pr_debug("PM: Adding info for %s:%s\n",
|
pr_debug("PM: Adding info for %s:%s\n",
|
||||||
dev->bus ? dev->bus->name : "No Bus",
|
dev->bus ? dev->bus->name : "No Bus",
|
||||||
kobject_name(&dev->kobj));
|
kobject_name(&dev->kobj));
|
||||||
mutex_lock(&dpm_list_mtx);
|
mutex_lock(&dpm_list_mtx);
|
||||||
list_add_tail(&dev->power.entry, &dpm_active);
|
list_add_tail(&dev->power.entry, &dpm_active);
|
||||||
error = dpm_sysfs_add(dev);
|
|
||||||
if (error)
|
|
||||||
list_del(&dev->power.entry);
|
|
||||||
mutex_unlock(&dpm_list_mtx);
|
mutex_unlock(&dpm_list_mtx);
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_pm_remove(struct device *dev)
|
void device_pm_remove(struct device *dev)
|
||||||
|
@@ -18,9 +18,24 @@ static inline struct device * to_device(struct list_head * entry)
|
|||||||
return container_of(entry, struct device, power.entry);
|
return container_of(entry, struct device, power.entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int device_pm_add(struct device *);
|
extern void device_pm_add(struct device *);
|
||||||
extern void device_pm_remove(struct device *);
|
extern void device_pm_remove(struct device *);
|
||||||
|
|
||||||
|
#else /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
|
||||||
|
static inline void device_pm_add(struct device *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void device_pm_remove(struct device *dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sysfs.c
|
* sysfs.c
|
||||||
*/
|
*/
|
||||||
@@ -28,16 +43,15 @@ extern void device_pm_remove(struct device *);
|
|||||||
extern int dpm_sysfs_add(struct device *);
|
extern int dpm_sysfs_add(struct device *);
|
||||||
extern void dpm_sysfs_remove(struct device *);
|
extern void dpm_sysfs_remove(struct device *);
|
||||||
|
|
||||||
#else /* CONFIG_PM_SLEEP */
|
#else /* CONFIG_PM */
|
||||||
|
|
||||||
|
static inline int dpm_sysfs_add(struct device *dev)
|
||||||
static inline int device_pm_add(struct device * dev)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static inline void device_pm_remove(struct device * dev)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
static inline void dpm_sysfs_remove(struct device *dev)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -457,7 +457,7 @@ config LEGACY_PTYS
|
|||||||
config LEGACY_PTY_COUNT
|
config LEGACY_PTY_COUNT
|
||||||
int "Maximum number of legacy PTY in use"
|
int "Maximum number of legacy PTY in use"
|
||||||
depends on LEGACY_PTYS
|
depends on LEGACY_PTYS
|
||||||
range 1 256
|
range 0 256
|
||||||
default "256"
|
default "256"
|
||||||
---help---
|
---help---
|
||||||
The maximum number of legacy PTYs that can be used at any one time.
|
The maximum number of legacy PTYs that can be used at any one time.
|
||||||
|
@@ -119,7 +119,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
|
|||||||
|
|
||||||
sysfs_put_active_two(attr_sd);
|
sysfs_put_active_two(attr_sd);
|
||||||
|
|
||||||
BUG_ON(count > (ssize_t)PAGE_SIZE);
|
/*
|
||||||
|
* The code works fine with PAGE_SIZE return but it's likely to
|
||||||
|
* indicate truncated result or overflow in normal use cases.
|
||||||
|
*/
|
||||||
|
BUG_ON(count >= (ssize_t)PAGE_SIZE);
|
||||||
if (count >= 0) {
|
if (count >= 0) {
|
||||||
buffer->needs_read_fill = 0;
|
buffer->needs_read_fill = 0;
|
||||||
buffer->count = count;
|
buffer->count = count;
|
||||||
|
@@ -314,7 +314,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
|
|||||||
temp_kobj = kset_find_obj(kobj->kset, new_name);
|
temp_kobj = kset_find_obj(kobj->kset, new_name);
|
||||||
if (temp_kobj) {
|
if (temp_kobj) {
|
||||||
printk(KERN_WARNING "kobject '%s' cannot be renamed "
|
printk(KERN_WARNING "kobject '%s' cannot be renamed "
|
||||||
"to '%s' as '%s' is already in existance.\n",
|
"to '%s' as '%s' is already in existence.\n",
|
||||||
kobject_name(kobj), new_name, new_name);
|
kobject_name(kobj), new_name, new_name);
|
||||||
kobject_put(temp_kobj);
|
kobject_put(temp_kobj);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
Reference in New Issue
Block a user