Commit Graph

134795 Commits

Author SHA1 Message Date
marius
4894db0d57 o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
  at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
  gem_bitwait() to ensure the respective bit has been written before we
  starting polling on it and poll for the right bits to change, f.e. even
  though we only reset RX we have to actually wait for both GEM_RESET_RX
  and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
  places we've been missing them according to the GEM documentation.
  Along with this some excessive DELAYs, which probably only were added
  because of bugs in gem_bitwait() and its use in the first place, as
  well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
  were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
  more gracefully as unlike gem_init_locked() it resets the RX DMA engine
  only, causing no link loss and the FIFOs not to be cleared. Also use it
  deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
  This was based on information obtained from the Linux GEM and OpenSolaris
  ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
  This was based on information obtained from the Darwin GMAC and Linux GEM
  drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
  This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
  - kicking the receiver as soon as we've a spare descriptor in gem_rint()
    again instead of just once after all the ready ones have been handled;
  - kicking the receiver the right way, i.e. as outlined in the GEM
    documentation in batches of 4 and by pointing it to the descriptor
    after the last valid one;
  - calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
    take quite a while;
  - doubling the size of the RX ring to 256 descriptors.
  Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
  from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
  before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
  fails we'll free the newly allocated mbuf, unable to recycle the
  previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
  Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
  defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
  every kick of the transmitter and not just once after enqueuing all
  packets as the NIC might instantly start transmitting after we kicked
  it the first time.
o Keep state of the link state and use it to enable or disable the MAC
  in gem_mii_statchg() accordingly as well as to return early from
  gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
  gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
  group mode on and don't clear the flag if we've disabled promiscuous
  group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
  device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
  legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
  that actually enables it as this needs more testing and mainly a proper
  framework to support it.
o Correct and add some conversions from hard-coded functions names to
  __func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
  the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
  module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
  never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
  respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
  hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
  Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
  for cards based on GEM to gem(4). This mainly consists of adding support
  for the TBI of these chips. Along with this the PHY selection code was
  rewritten to hardcode the PHY number for certain configurations as for
  example the PHY of the on-board ERI of Blade 1000 shows up twice causing
  no link as the second incarnation is isolated.
  These changes were ported from OpenBSD with some additional improvements
  and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
  systems without Open Firmware.
  This is an improved version of my variant of the respective code in
  if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.

Pointed out by:	yongari [1]
Suggested by:	rwatson [2], yongari [3]
Tested on:	i386 (GEM), powerpc (GMACs by marcel and yongari),
		sparc64 (ERI and GEM)
Reviewed by:	yongari
Approved by:	re (kensmith)
2007-09-26 21:14:18 +00:00
marius
6cdd0265f8 - Use the actual clock frequency of the PCI bus instead of assuming
33MHz for calculating the latency timer values for its children.
  Inspired by NetBSD doing the same and Linux as well as OpenSolaris
  using a similar approach.
  While at it rename a variable and change its type to be more
  appropriate fuer values of PCI properties so the variable can be
  more easily reused.
- Initialize the cache line size register of PCI devices to a
  legal value; the cache line size is limited to 64 bytes by the
  Fireplane/Safari, JBus and UPA interconnection busses. Setting
  it to an unsupported value caused bad performance at least with
  GEM as it causes them to not do cache line bursts and to not
  issue cache line commands on the PCI bus.

Approved by:	re (kensmith)
MFC after:	1 week
2007-09-26 20:10:36 +00:00
brueffer
26461bf019 Use the correct expanded name for SCTP.
PR:		116496
Submitted by:	koitsu
Reviewed by:	rrs
Approved by:	re (kensmith)
2007-09-26 20:05:07 +00:00
ru
78adc698af Fix the description of the formula used to autosize the number of
buffers in the buffer cache.

Approved by:	re (kensmith)
2007-09-26 11:22:23 +00:00
ru
f192630113 Mention that autoboot_delay also accepts the "NO" value.
Approved by:	re (kensmith)
2007-09-26 08:38:25 +00:00
marcel
88e1757c25 Force -O1 compilation when targeted for ia64. GCC 4 generates
bad code at -O2. Since this is likely caused by the low-level
optimizer, testing TARGET_ARCH rather than MACHINE_ARCH should
handle ia64 cross-compilation as well. With this work-around
in place, we can release using the current GCC and Binutils
code at the default optimization level on ia64.

Approved by: re (kensmith)
2007-09-26 01:31:28 +00:00
edwin
c2ea759143 Fix possible uninitialized variable insert due to previous commit.
Pointy hat to: me and my absence of -Wall in my CFLAGS.

MFC will happen at the same time of the earlier commit.

Thanks to ru@ for spotting.

Approved by:	re (Ken Smith), grog@ (mentor)
2007-09-25 21:41:22 +00:00
mohans
422753af04 Fix for a very rare race, caused by the nfsiod wakeup and nfsiod idle
timeout occurring at exactly the same time. If this happens, the nfsiod
exits although there may be a queued async IO request for it.

Found by : Kris Kennaway
Approved by: re
2007-09-25 21:08:49 +00:00
imp
0d59ddbedf if_axe.c 1.54 and if_axereg.h 1.15 were obtained from OpenBSD.
Pointed out by: sam@
Obtained from: openbsd (prev rev)
Approved by: re@
Pointy stick to the eye: imp@
2007-09-25 21:08:33 +00:00
alc
b72c80753d Correct an error in the previous revision, specifically,
vm_object_madvise() should request that the reactivated, cached page
not be busied.

Reported by: Rink Springer
Approved by: re (kensmith)
2007-09-25 21:01:10 +00:00
imp
babc4bf64a Add support for the AX88178 and AX88772 based devices.
Submitted by: sam@
Approved by: re@ (blanket)
2007-09-25 20:47:24 +00:00
brueffer
a55c6d7bef Assorted spelling, punctuation and mdoc fixes.
Approved by:	re (blanket)
2007-09-25 16:48:08 +00:00
sam
a0d2ad9bdb o enable use of EAP methods w/o modification to the base system; use
WPA_SUPPLICANT_CFLAGS, etc. (consult the Makefile's for details)
o enable ipv6 support in hostapd (for communication w/ a radius backend)

PR:		bin/116164
Submitted by:	"Scot Hetzel" <swhetzel@gmail.com>
Approved by:	re (gnn)
MFC after:	2 weeks
2007-09-25 16:08:16 +00:00
brueffer
d09501e276 - Use the correct expanded name for SCTP (1)
- Remove empty section

PR:		116496 (1)
Submitted by:	koitsu
Approved by:	re (blanket)
2007-09-25 16:03:10 +00:00
alc
d1bce06c64 Change the management of cached pages (PQ_CACHE) in two fundamental
ways:

(1) Cached pages are no longer kept in the object's resident page
splay tree and memq.  Instead, they are kept in a separate per-object
splay tree of cached pages.  However, access to this new per-object
splay tree is synchronized by the _free_ page queues lock, not to be
confused with the heavily contended page queues lock.  Consequently, a
cached page can be reclaimed by vm_page_alloc(9) without acquiring the
object's lock or the page queues lock.

This solves a problem independently reported by tegge@ and Isilon.
Specifically, they observed the page daemon consuming a great deal of
CPU time because of pages bouncing back and forth between the cache
queue (PQ_CACHE) and the inactive queue (PQ_INACTIVE).  The source of
this problem turned out to be a deadlock avoidance strategy employed
when selecting a cached page to reclaim in vm_page_select_cache().
However, the root cause was really that reclaiming a cached page
required the acquisition of an object lock while the page queues lock
was already held.  Thus, this change addresses the problem at its
root, by eliminating the need to acquire the object's lock.

Moreover, keeping cached pages in the object's primary splay tree and
memq was, in effect, optimizing for the uncommon case.  Cached pages
are reclaimed far, far more often than they are reactivated.  Instead,
this change makes reclamation cheaper, especially in terms of
synchronization overhead, and reactivation more expensive, because
reactivated pages will have to be reentered into the object's primary
splay tree and memq.

(2) Cached pages are now stored alongside free pages in the physical
memory allocator's buddy queues, increasing the likelihood that large
allocations of contiguous physical memory (i.e., superpages) will
succeed.

Finally, as a result of this change long-standing restrictions on when
and where a cached page can be reclaimed and returned by
vm_page_alloc(9) are eliminated.  Specifically, calls to
vm_page_alloc(9) specifying VM_ALLOC_INTERRUPT can now reclaim and
return a formerly cached page.  Consequently, a call to malloc(9)
specifying M_NOWAIT is less likely to fail.

Discussed with: many over the course of the summer, including jeff@,
   Justin Husted @ Isilon, peter@, tegge@
Tested by: an earlier version by kris@
Approved by: re (kensmith)
2007-09-25 06:25:06 +00:00
jhb
0cf1ea80ad Allow the ia32 resource limits (compat.ia32.max{dsiz,ssiz,vmem} to be
set via loader tunables.  They are already tunable via sysctl.

MFC after:	1 week
Approved by:	re (kensmith)
2007-09-24 20:49:39 +00:00
jkim
18e70fea3e This commit was generated by cvs2svn to compensate for changes in r172314,
which included commits to RCS files with non-trunk default branches.
2007-09-24 17:12:36 +00:00
jkim
f7e7ed217a Fix global lock recursion bug.
This patch was part of ACPI-CA 20070508 release and the
following is excerpt from its change log:

Fixed a problem where the Global Lock handle was not properly
updated if a thread that acquired the Global Lock via executing
AML code then attempted to acquire the lock via the
AcpiAcquireGlobalLock interface. Reported by Joe Liu.

Approved by:	re (kensmith)
Tested by:	ambrisko
Obtained from:	Intel
2007-09-24 17:12:36 +00:00
njl
b50224d3f9 Rewrite the EC driver event model. The main goal is to avoid
polling/interrupt-driven fallback and instead use polling only during
boot and pure interrupt-driven mode after boot.  Polled mode could be
relegated completely to a legacy role if we could enable interrupts
during boot.  Polled mode can be forced after boot by setting
debug.acpi.ec.polled="1", i.e. if there are timeouts.

- Use polling only during boot, shutdown, or if requested by the user.
  Otherwise, use a generation count of GPEs, incremented atomically.  This
  prevents an old status value from being used if the EC is really slow
  and the same condition (i.e. multiple IBEs for a write transaction) is
  being checked.
- Check for and run the query handler directly if the SCI bit is set in
  the status register during boot.  Previously, the query handler wouldn't
  run until interrupts were finally enabled late in boot.
- During boot and after starting a command, check if the event appears
  to already have occurred before we even start waiting.  If so, it's
  possible the EC is very slow and we might accept an old status value.
  Print a warning in this case.  Once we've booted, interrupt-driven mode
  should work just fine but polled mode could be unreliable.  There's not
  much more we can do about this until interrupts are enabled during boot.
- In the above case, we also do one final check if the interrupt-driven
  mode gets a timeout.  If the status is complete, it will force the
  system back into polled mode since interrupt mode doesn't work.  For
  polled mode during boot, if the status appears to be already complete
  before beginning the check loop, it waits 10 us before actually checking
  the status, just in case the EC is really slow and hasn't gotten to work
  on the new request yet.
- Use upper-case hex for the _Qxx method
- Use device_printf for errors, don't hide them under verbose
- Increase default total timeout to 750 ms and decrease polling interval
  to 5 us.
- Don't pass the status value via the softc.  Just read it directly.
- Remove the mutex. We use the sx lock for transaction serialization
  with the query handler.
- Remove the Intel copyright notice as no code of theirs was ever
  present in this file (verified against rev 1.1)
- Allow KTR module-only builds for ease of testing

Thanks to jkim and Alexey Starikovskiy for helpful discussions and testing.

Approved by:	re
MFC after:	2 weeks
2007-09-24 16:59:06 +00:00
kib
dd74194c9c Revert rev. 1.94. After recent tcp backouts, tcp_close() may return NULL.
Check the return value of tcp_close() being NULL before dereferencing it
in #ifdef TCPDEBUG block.

Reviewed by:	rwatson
Approved by:	re (gnn)
2007-09-24 14:46:27 +00:00
pjd
b555b05b37 Forced commit to note, that the last commit fixed my bug, and was not
because of differences between how tinderbox compile LINT - after this
change I only compiled LINT on i386 and the bug shows up on 64bit platforms.

Requested by:	des
Approved by:	re (implicitly)
2007-09-24 06:14:27 +00:00
silby
5fb86a6fa7 Two changes:
- Reintegrate the ANSI C function declaration change
  from tcp_timer.c rev 1.92

- Reorganize the tcpcb structure so that it has a single
  pointer to the "tcp_timer" structure which contains all
  of the tcp timer callouts.  This change means that when
  the single tcp timer change is reintegrated, tcpcb will
  not change in size, and therefore the ABI between
  netstat and the kernel will not change.

Neither of these changes should have any functional
impact.

Reviewed by: bmah, rrs
Approved by: re (bmah)
2007-09-24 05:26:24 +00:00
jeff
ea91086eb3 - Bound the interactivity score so that it cannot become negative.
Approved by:	re
2007-09-24 00:28:54 +00:00
csjp
5328bd11db Certain consumers of rtalloc like gif(4) and if_stf(4) lookup the
route and once they are done with it, call rtfree().  rtfree() should
only be used when we are certain we hold the last reference to the
route.  This bug results in console messages like the following:

rtfree: 0xc40f7000 has 1 refs

This patch switches the rtfree() to use RTFREE_LOCKED() instead,
which should handle the reference counting on the route better.

Approved by:	re@ (gnn)
Reviewed by:	bms
Reported by:	many via net@ and current@
Tested by:	many
2007-09-23 17:50:17 +00:00
maxim
9f9cc8d8af o Cosmetic: fix the issue when "ipfw(8) show" produces "not" twice:
$ ipfw -n add 1 allow layer2 not mac-type ip
00001 allow ip from any to any layer2 not not mac-type 0x0800

PR:		bin/115372
Submitted by:	Andrey V. Elsukov
Approved by:	re (hrs)
MFC after:	3 weeks
2007-09-23 16:29:22 +00:00
maxim
816792f7c8 o s/filesystem/file system/g.
Pointed out by:	ru
Approved by:	re (bmah)
MFC after:	3 days
2007-09-23 16:06:37 +00:00
pjd
581e534e82 LINT compiled just fine for me, but it seems it breaks tinerbox way of
compiling LINT.

Approved by:	re (implicitly)
2007-09-23 15:10:48 +00:00
bde
5cdc06872e Remove some of the pessimizations involving writing the fsi sector.
All active fields in fsi are advisory/optional, so we shouldn't do
extra work to make them valid at all times, but instead we write to
the fsi too often (we still do), and we searched for a free cluster
for fsinxtfree too often.

This commit just removes the whole search and its results, so that we
write out our in-core copy of fsinxtfree instead of writing a "fixed"
copy and clobbering our in-core copy.  This saves fixing 3 bugs:
- off-by-1 error for the end of the search, resulting in fsinxtfree
  not actually being adjusted iff only the last cluster is free.
- missing adjustment when no clusters are free.
- off-by-many error for the start of the search.  Starting the search
  at 0 instead of at (the in-core copy of) fsinxtfree did more than
  defeat the reasons for existence of fsinxtfree.  fsinxtfree exists
  mainly to avoid having to start at 0 for just the first search per
  mount, but has the side effect of reducing bias towards allocating
  near cluster 0.  The bias would normally only be generated by the
  first search per mount (if fsinxtfree is not supported), but since
  we also adjusted the in-core copy of fsinxtfree here, we were doing
  extra work to maximize the bias.

Approved by:	re (kensmith)
2007-09-23 14:49:32 +00:00
pjd
27bd800e61 Bring in the GEOM Virtualisation class, which allows to create huge GEOM
providers with limited physical storage and add physical storage as
needed.

Submitted by:	Ivan Voras
Sponsored by:	Google Summer of Code 2006
Approved by:	re (kensmith)
2007-09-23 07:34:23 +00:00
pjd
a4c30a2063 Now that we have CDDLed code in the tree, add CDDL license.
Discussed with:	core
Approved by:	re (kensmith)
2007-09-23 07:04:50 +00:00
cognet
6055cf1f83 Make sure we do not call _arm_bzero() or _arm_memcpy() if the size is not at
least the minimum asked by the driver.

Approved by:	re (blanket)
2007-09-22 22:47:48 +00:00
cognet
20a45c5c15 Add various macros for the ADMA unit.
Approved by:	re (blanket)
2007-09-22 22:25:24 +00:00
mlaier
b333fcfd21 Remove PF_MPSAFE_UGID leftover.
Spotted by:	bz
Approved by:	re (gnn)
2007-09-22 18:22:31 +00:00
cognet
6b6ebc8c90 Add a driver for the 7seg found on the CRB board, largely based on the
IQ31244 version.

Approved by:	re (blanket)
2007-09-22 16:25:43 +00:00
cognet
910d500785 Twist the RAS logic a bit to avoid branching.
MFC After:	1 week
Approved by:	re (blanket)
2007-09-22 14:23:52 +00:00
scf
c96f51e4b8 The precision for a string argument in a call to warnx() needs to be cast
to an int to remove the warning from using a size_t variable on 64-bit
platforms.

Submitted by:	Xin LI <delphij@FreeBSD.org>
Approved by:	wes
Approved by:	re (kensmith)
2007-09-22 02:30:44 +00:00
jeff
280a86b2ee - Improve grammar. s/it's/its/.
- Improve load long-term load balancer by always IPIing exactly once.
   Previously the delay after rebalancing could cause problems with
   uneven workloads.
 - Allow nice to have a linear effect on the interactivity score.  This
   allows negatively niced programs to stay interactive longer.  It may be
   useful with very expensive Xorg servers under high loads.  In general
   it should not be necessary to alter the nice level to improve interactive
   response.  We may also want to consider never allowing positively niced
   processes to become interactive at all.
 - Initialize ccpu to 0 rather than 0.0.  The decimal point was leftover
   from when the code was copied from 4bsd.  ccpu is 0 in ULE because ULE
   only exports weighted cpu values.

Reported by:	Steve Kargl (Load balancing problem)
Approved by:	re
2007-09-22 02:20:14 +00:00
rodrigc
b2b7d089f7 Disable multiple ntfs mounts to the same mountpoint.
Eliminates panics due to locking issues.
Idea taken from src/sys/gnu/fs/xfs/FreeBSD/xfs_super.c.

PR:	89966, 92000, 104393
Reported by:	H. Matsuo <hiroshi50000 yahoo co jp>,
		Chris <m2chrischou gmail.com>,
		Andrey V. Elsukov <bu7cher yandex ru>,
		Jan Henrik Sylvester <me janh de>
Approved by:	re (kensmith)
2007-09-21 23:50:15 +00:00
edwin
4ec928319a Update to calendar/calendars/hr_HR.ISO_8859-2/calendar.praznici
with fixes and new dates.

PR:		conf/26658
Submitted by:	Josip Rodin <joy@gkvk.hr>
Approved by:	re@ (bmah), grog@ (mentor)
MFC after:	1 week
2007-09-21 23:43:03 +00:00
marcel
51f2b5019d Translate partitions of type "PART" to chunks of the same type
as they would have been translated from partitions of type "GPT".
This fixes sysinstall, now that geom_part has taken over from
geom_gpt.

Approved by: re (kensmith)
2007-09-21 16:24:01 +00:00
marcel
876d6af999 On PowerPC, geom_part has taken over the partitioning from geom_apple.
Translate partitions of type "PART" to chunks of type "apple" on
PowerPC. This fixes sysinstall.

Approved by: re (kensmith)
2007-09-21 16:19:50 +00:00
obrien
4f7380b135 Add FreeBSD history.
Approved by:	re(ken)
2007-09-21 14:05:26 +00:00
tabthorpe
ba7a4abe3c - added in missing \n for my entry
Submitted by:	breueffer@
Approved by:	re, miwi (mentor)
2007-09-21 13:03:24 +00:00
tabthorpe
0e9f94b568 - add my entry
Approved by:	re (bmah), clsung/miwi (mentors)
2007-09-21 12:12:13 +00:00
pjd
763f7449dc Fix some locking cases where we ask for exclusively locked vnode, but we get
shared locked vnode in instead when vfs.lookup_shared is set to 1.

Discussed with:	kib, kris
Tested by:	kris
Approved by:	re (kensmith)
2007-09-21 10:16:56 +00:00
pjd
427fb1f9be For arguments declared as numbers always use expand_number(3).
This allows to use numbers in human-readable form in many geom(8)
utilities. Such a simple change and makes live so much nicer.
Some examples:

	gstripe label -s 16k
	gmirror label -s 4k
	gnop create -o 1g -s 128m -S 2k
	gjournal label -s 2g
	geli label -i 128k -s 4k

Approved by:	re (kensmith)
2007-09-21 10:00:05 +00:00
pjd
5f96c6e1c1 Use 'val' function argument instead of 'optarg' global variable.
This doesn't fix any real bug, because in those tw ocases we always
passed 'optarg' as 'val'.

Approved by:	re (kensmith)
2007-09-21 09:52:43 +00:00
mav
1f0cbf5a23 Dead code removal.
Approved by:	re (kensmith), glebius (mentor)
2007-09-21 08:25:55 +00:00
mav
01f9f69635 This is optimization of ether and debug hooks determination. It
simplifies code and should speedup pppoe_findsession() function which is
called for every incoming packet.

Approved by:	re (kensmith), glebius (mentor)
2007-09-21 08:24:08 +00:00
mav
14a66bdd4b This patch fixes thread unsafe usage of global pkt_hdr
variable. Second part is not so important, but IMO is also good.

Approved by:	re (kensmith), glebius (mentor)
2007-09-21 08:16:33 +00:00