Commit Graph

1113 Commits

Author SHA1 Message Date
Dimitris Papastamos
38f6916976 regmap: Grab the lock in regcache_cache_only()
Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-28 13:57:36 +01:00
Dimitris Papastamos
ec8a365fe6 regmap: Modify map->cache_bypass directly
In preperation for the upcoming patches, modify map->cache_bypass
directly.  The helper functions will grab an exclusive lock.  Because
we'll have acquired the same lock we need to avoid a deadlock.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-28 13:56:39 +01:00
Dimitris Papastamos
a40c282362 regmap: Fix regcache_sync generic implementation
We want to use regmap_write() to actually write anything
to the HW.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-28 13:56:39 +01:00
Lars-Peter Clausen
3405addd22 regmap: rbtree-cache: Move cached rbnode handling into lookup function
Move the handling of the cached rbnode into regcache_rbtree_lookup. This allows
us to remove of some duplicated code sections in regcache_rbtree_read and
regcache_rbtree_write.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-28 13:18:22 +01:00
Lars-Peter Clausen
c5713004b3 regmap: regcache_rbtree_{set,get}_register: Use regcache_{set,get}_val
Use regcache_{set,get}_val in regcache_rbtree_{set,get}_register instead of
re-implementing its functionality.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-28 13:18:11 +01:00
Dimitris Papastamos
954757d767 regmap: Implement generic syncing functionality
In the absence of a sync callback, do it manually.  This of course
can't take advantange of the specific optimizations of each
cache type but it will do well enough in most cases.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-27 20:06:38 +01:00
Dimitris Papastamos
dfdc4448e0 regmap: Fix signed/unsigned comparison
Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-27 13:27:09 +01:00
Dimitris Papastamos
25ed1156dd regmap: Remove redundant member `word_size' from regcache_rbtree_node
Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-27 13:27:09 +01:00
Mark Brown
92afb286d7 regmap: Allow drivers to control cache_only flag
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:37 +01:00
Mark Brown
e7a6db30df regmap: A cache type of _NONE behaves like a bypassed cache
Avoid extra special casing by setting the cache_bypass flag when we're
not caching.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:36 +01:00
Dimitris Papastamos
5d1729e7f0 regmap: Incorporate the regcache core into regmap
This patch incorporates the regcache core code into regmap.  All previous
patches have been no-ops essentially up to this point.

The bulk read operation is not supported by regcache at the moment.  This
will be implemented incrementally.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Tested-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:35 +01:00
Dimitris Papastamos
5936008901 regmap: Add the regcache_sync trace event
Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:34 +01:00
Dimitris Papastamos
2cbbb579bc regmap: Add the LZO cache support
This patch adds support for LZO compression when storing the register
cache.

For a typical device whose register map would normally occupy 25kB or 50kB
by using the LZO compression technique, one can get down to ~5-7kB.  There
might be a performance penalty associated with each individual read/write
due to decompressing/compressing the underlying cache, however that should not
be noticeable.  These memory benefits depend on whether the target architecture
can get rid of the memory occupied by the original register defaults cache
which is marked as __devinitconst.  Nevertheless there will be some memory
gain even if the target architecture can't get rid of the original register
map, this should be around ~30-32kB instead of 50kB.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:33 +01:00
Dimitris Papastamos
28644c809f regmap: Add the rbtree cache support
This patch adds support for the rbtree cache compression type.

Each rbnode manages a variable length block of registers.  There can be no
two nodes with overlapping blocks.  Each block has a base register and a
currently top register, all the other registers, if any, lie in between these
two and in ascending order.

The reasoning behind the construction of this rbtree is simple.  In the
snd_soc_rbtree_cache_init() function, we iterate over the register defaults
provided by the regcache core.  For each register value that is non-zero we
insert it in the rbtree.  In order to determine in which rbnode we need
to add the register, we first look if there is another register already
added that is adjacent to the one we are about to add.  If that is the case
we append it in that rbnode block, otherwise we create a new rbnode
with a single register in its block and add it to the tree.

There are various optimizations across the implementation to speed up lookups
by caching the most recently used rbnode.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Tested-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:33 +01:00
Dimitris Papastamos
195af65ca9 regmap: Add the indexed cache support
This is the simplest form of a cache available in regcache.  Any
registers whose default value is 0 are ignored.  If any of those
registers are modified in the future, they will be placed in the
cache on demand.  The cache layout is essentially using the provided
register defaults by the regcache core directly and does not re-map
it to another representation.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:32 +01:00
Dimitris Papastamos
9fabe24e9b regmap: Introduce caching support
This patch introduces caching support for regmap.  The regcache API
has evolved essentially out of ASoC soc-cache so most of the actual
caching types (except LZO) have been tested in the past.

The purpose of regcache is to optimize in time and space the handling
of register caches.  Time optimization is achieved by not having to go
over a slow bus like I2C to read the value of a register, instead it is
cached locally in memory and can be retrieved faster.  Regarding space
optimization, some of the cache types are better at packing the caches,
for e.g. the rbtree and the LZO caches.  By doing this the sacrifice in
time still wins over doing I2C transactions.

Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
Tested-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-19 19:06:31 +01:00
Lars-Peter Clausen
bbcf61ca8d regmap: Make debugfs stubs static inline
Make the debugfs stubs static inline to avoid future compilation issues due to
duplicated symbols when CONFIG_DEBUG_FS=n once internal.h is included by
multiple source files.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-05 15:00:08 -07:00
Lars-Peter Clausen
6f306441e9 regmap: Add support for device specific write and read flag masks.
Some buses like SPI have no standard notation of read or write operations.
The general scheme here is to set or clear specific bits in the register
address to indicate whether the operation is a read or write. We already
support having a read flag mask per bus, but as there is no standard
the bits which need to be set or cleared differ between devices and vendors,
thus we need a mechanism to specify them per device.

This patch adds two new entries to the regmap_config struct, read_flag_mask and
write_flag_mask. These will be or'ed onto the top byte when doing a read or
write operation. If both masks are empty the device will fallback to the
regmap_bus masks.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-05 14:55:57 -07:00
Mark Brown
d813ae9a10 regmap: Include the last register in debugfs output
Off by one in the array iteration.

Reported-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-05 10:58:31 -07:00
Mark Brown
5b457e3910 regmap: Remove redundant owner field from the bus type struct
No longer used as users link directly with the bus types so the core
module infrastructure does refcounting for us.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-05 10:57:04 -07:00
Mark Brown
a7ace561f1 Merge branch 'regmap-linus' into regmap-next 2011-09-05 10:56:57 -07:00
Mark Brown
5204f5e3f5 regmap: Remove bitrotted module_put()s
The conversion to per bus type registration functions means we don't need
to do module_get()s to hold the bus types in memory (their users will link
to them) so we removed all those calls. This left module_put() calls in
the cleanup paths which aren't needed and which cause unbalanced puts if
we ever try to unload anything.

Reported-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-09-05 10:55:58 -07:00
Mark Brown
449e38427f regmap: Provide access information via debugfs
Let userspace know what the access map for the device is. This is helpful
for verifying that the access map is correctly configured and could also
be useful for programs that try to work with the data. File format is:

register: R W V P

where R, W, V and P are 'y' or 'n' showing readable, writable, volatile
and precious respectively.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-14 19:51:16 +09:00
Mark Brown
21f5554456 regmap: Share some of the debugfs infrastructure ready for more files
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-14 19:51:14 +09:00
Mark Brown
8de2f081ef regmap: Add functions to check for access on registers
We're going to be using these in quite a few places so factor out the
readable/writable/volatile/precious checks.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-14 19:51:11 +09:00
Mark Brown
13c54137f7 Merge branch 'regmap-linus' into regmap-next 2011-08-12 10:43:15 +09:00
Stephen Warren
b33f9cbd67 regmap: Specify a module license
CONFIG_REGMAP_I2C/SPI are set to m when selected by a tristate config
option that's set to m. The regmap modules don't specify a license, so
fail to link to regmap_init at load time, since that is EXPORT_SYMBOL_GPL.
Fix this by specifying a license for the regmap modules.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-12 10:42:02 +09:00
Mark Brown
790923e56b regmap: Remove unused type and list fields from bus interface
We no longer enumerate the bus types, we rely on the driver telling us
this on init.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-10 00:26:38 +09:00
Mark Brown
cb3c2dcfa3 regmap: Fix type of field width specifiers for x86_64
x86_64 size_t is not an int but the printf format specifier for size_t
should be an int.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
2011-08-10 00:26:38 +09:00
Mark Brown
2efe1642b7 regmap: Skip precious registers when dumping registers via debugfs
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:57:35 +09:00
Mark Brown
31244e396f regmap: Provide register map dump via debugfs
Copy over the read parts of the ASoC debugfs implementation into regmap,
allowing users to see what the register values the device has are at
runtime. The implementation, especially the support for seeking, is
mostly due to Dimitris Papastamos' work in ASoC.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:57:00 +09:00
Mark Brown
93de91245b regmap: Use a local header for API internals
Allowing the implementation to be multi-file.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:56:50 +09:00
Mark Brown
7330478127 regmap: Implement writable register checks
This is mainly intended to be used by devices which can dynamically
block register writes at runtime, for other devices there is usually
limited value.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:56:41 +09:00
Mark Brown
fb2736bbae regmap: Add basic tracepoints
Trace single register reads and writes, plus start/stop tracepoints for
the actual I/O to see where we're spending time. This makes it easy to
have always on logging without overwhelming the logs and also lets us take
advantage of all the context and time information that the trace subsystem
collects for us.

We don't currently trace register values for bulk operations as this would
add complexity and overhead parsing the cooked data that's being worked
with.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:56:16 +09:00
Mark Brown
555fedacc3 Merge branches 'regmap-linus' and 'regmap-interface' into regmap-next 2011-08-08 15:55:53 +09:00
Mark Brown
2547e201b3 regmap: Just send the buffer directly for single register writes
When doing a single register write we use work_buf for both the register
and the value with the buffer formatted for sending directly to the device
so we can just do a write() directly. This saves allocating a temporary
buffer if we can't do gather writes and is likely to be faster than doing
a gather write.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:52:25 +09:00
Mark Brown
2e2ae66df3 regmap: Allow devices to specify which registers are accessible
This is currently unused but we need to know which registers exist and
their properties in order to implement diagnostics like register map
dumps and the cache features.

We use callbacks partly because properties can vary at runtime (eg, through
access locks on registers) and partly because big switch statements are a
good compromise between readable code and small data size for providing
information on big register maps.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-08-08 15:47:00 +09:00
Kevin Hilman
02b26774af PM / Runtime: Allow _put_sync() from interrupts-disabled context
Currently the use of pm_runtime_put_sync() is not safe from
interrupts-disabled context because rpm_idle() will release the
spinlock and enable interrupts for the idle callbacks.  This enables
interrupts during a time where interrupts were expected to be
disabled, and can have strange side effects on drivers that expected
interrupts to be disabled.

This is not a bug since the documentation clearly states that only
_put_sync_suspend() is safe in IRQ-safe mode.

However, pm_runtime_put_sync() could be made safe when in IRQ-safe
mode by releasing the spinlock but not re-enabling interrupts, which
is what this patch aims to do.

Problem was found when using some buggy drivers that set
pm_runtime_irq_safe() and used _put_sync() in interrupts-disabled
context.

Reported-by: Colin Cross <ccross@google.com>
Tested-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-05 21:45:20 +02:00
Rafael J. Wysocki
fe202fde50 PM / Domains: Fix pm_genpd_poweron()
The local variable ret is defined twice in pm_genpd_poweron(), which
causes this function to always return 0, even if the PM domain's
.power_on() callback fails, in which case an error code should be
returned.

Remove the wrong second definition of ret and additionally remove an
unnecessary definition of wait from pm_genpd_poweron().

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
2011-08-05 21:45:11 +02:00
Al Viro
9d108d2548 devtmpfs: missing initialialization in never-hit case
create_path() on something without a single / in it will return err
without initializing it.  It actually can't happen (we call that thing
only if create on the same path returns -ENOENT, which won't happen
happen for single-component path), but in this case initializing err
to 0 is more than making compiler to STFU - would be the right thing
to return on such paths; the function creates a parent directory of
given pathname and in that case it has no work to do...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-07-27 22:27:33 -04:00
Arun Sharma
60063497a9 atomic: use <linux/atomic.h>
This allows us to move duplicated code in <asm/atomic.h>
(atomic_inc_not_zero() for now) to <linux/atomic.h>

Signed-off-by: Arun Sharma <asharma@fb.com>
Reviewed-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: David Miller <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-07-26 16:49:47 -07:00
Jonghwan Choi
fc92805a8e drivers/base/power/opp.c: fix dev_opp initial value
Dev_opp initial value shoule be ERR_PTR(), IS_ERR() is used to check
error.

Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-07-26 16:49:41 -07:00
Linus Torvalds
f0deb97ab1 Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6:
  updated Documentation/ja_JP/SubmittingPatches
  debugfs: add documentation for debugfs_create_x64
  uio: uio_pdrv_genirq: Add OF support
  firmware: gsmi: remove sysfs entries when unload the module
  Documentation/zh_CN: Fix messy code file email-clients.txt
  driver core: add more help description for "path to uevent helper"
  driver-core: modify FIRMWARE_IN_KERNEL help message
  driver-core: Kconfig grammar corrections in firmware configuration
  DOCUMENTATION: Replace create_device() with device_create().
  DOCUMENTATION: Update overview.txt in Doc/driver-model.
  pti: pti_tty_install documentation mispelling.
2011-07-25 23:06:24 -07:00
Linus Torvalds
184475029a Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (99 commits)
  drivers/virt: add missing linux/interrupt.h to fsl_hypervisor.c
  powerpc/85xx: fix mpic configuration in CAMP mode
  powerpc: Copy back TIF flags on return from softirq stack
  powerpc/64: Make server perfmon only built on ppc64 server devices
  powerpc/pseries: Fix hvc_vio.c build due to recent changes
  powerpc: Exporting boot_cpuid_phys
  powerpc: Add CFAR to oops output
  hvc_console: Add kdb support
  powerpc/pseries: Fix hvterm_raw_get_chars to accept < 16 chars, fixing xmon
  powerpc/irq: Quieten irq mapping printks
  powerpc: Enable lockup and hung task detectors in pseries and ppc64 defeconfigs
  powerpc: Add mpt2sas driver to pseries and ppc64 defconfig
  powerpc: Disable IRQs off tracer in ppc64 defconfig
  powerpc: Sync pseries and ppc64 defconfigs
  powerpc/pseries/hvconsole: Fix dropped console output
  hvc_console: Improve tty/console put_chars handling
  powerpc/kdump: Fix timeout in crash_kexec_wait_realmode
  powerpc/mm: Fix output of total_ram.
  powerpc/cpufreq: Add cpufreq driver for Momentum Maple boards
  powerpc: Correct annotations of pmu registration functions
  ...

Fix up trivial Kconfig/Makefile conflicts in arch/powerpc, drivers, and
drivers/cpufreq
2011-07-25 22:59:39 -07:00
Linus Torvalds
0003230e82 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  fs: take the ACL checks to common code
  bury posix_acl_..._masq() variants
  kill boilerplates around posix_acl_create_masq()
  generic_acl: no need to clone acl just to push it to set_cached_acl()
  kill boilerplate around posix_acl_chmod_masq()
  reiserfs: cache negative ACLs for v1 stat format
  xfs: cache negative ACLs if there is no attribute fork
  9p: do no return 0 from ->check_acl without actually checking
  vfs: move ACL cache lookup into generic code
  CIFS: Fix oops while mounting with prefixpath
  xfs: Fix wrong return value of xfs_file_aio_write
  fix devtmpfs race
  caam: don't pass bogus S_IFCHR to debugfs_create_...()
  get rid of create_proc_entry() abuses - proc_mkdir() is there for purpose
  asus-wmi: ->is_visible() can't return negative
  fix jffs2 ACLs on big-endian with 16bit mode_t
  9p: close ACL leaks
  ocfs2_init_acl(): fix a leak
  VFS : mount lock scalability for internal mounts
2011-07-25 12:53:15 -07:00
Al Viro
e13889bab3 fix devtmpfs race
After we's done complete(&req->done), there's nothing to prevent the
scope containing *req from being gone and *req overwritten by any
kind of junk.  So we must read req->next before that...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-07-25 14:15:50 -04:00
Mark Brown
40c5cc2639 regmap: Fix bulk reads
We should be reading the number of bytes we were asked for, not the size
of a single register.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2011-07-24 22:44:51 +01:00
Linus Torvalds
f5fc87905e Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regulator: Convert tps65023 to use regmap API
  regmap: Add SPI bus support
  regmap: Add I2C bus support
  regmap: Add generic non-memory mapped register access API
2011-07-23 11:14:47 -07:00
Mark Brown
a676f08306 regmap: Add SPI bus support
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
2011-07-23 07:56:59 +01:00
Mark Brown
9943fa300a regmap: Add I2C bus support
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@ti.com>
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
2011-07-23 07:56:39 +01:00