Commit cae2f9c4 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 09f345da 8118a859
...@@ -11,7 +11,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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(); ...@@ -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. ...@@ -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) ...@@ -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) ...@@ -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,
......
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); ...@@ -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)
......
...@@ -13,14 +13,29 @@ extern void device_shutdown(void); ...@@ -13,14 +13,29 @@ extern void device_shutdown(void);
extern struct list_head dpm_active; /* The active device list */ extern struct list_head dpm_active; /* The active device list */
static inline struct device * to_device(struct list_head * entry) 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 *); ...@@ -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 device_pm_add(struct device * dev) static inline int dpm_sysfs_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 ...@@ -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 ...@@ -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;
......
...@@ -313,8 +313,8 @@ int kobject_rename(struct kobject * kobj, const char *new_name) ...@@ -313,8 +313,8 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
struct kobject *temp_kobj; struct kobject *temp_kobj;
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' can not 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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment