Commit Graph

89 Commits

Author SHA1 Message Date
Jerome Glisse 466476dfdc drm/radeon: Always flush the VM
This is slightly cleaned up version of Jerome's patch.
There seems to be an issue tracking the last flush of
the VM which results in hangs in certain cases when
VM is used.  For now just flush the VM for every IB.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=62959
https://bugs.freedesktop.org/show_bug.cgi?id=62997

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2013-04-16 16:15:28 -04:00
Christian König f2ba57b5ea drm/radeon: UVD bringup v8
Just everything needed to decode videos using UVD.

v6: just all the bugfixes and support for R7xx-SI merged in one patch
v7: UVD_CGC_GATE is a write only register, lockup detection fix
v8: split out VRAM fallback changes, remove support for RV770,
    add support for HEMLOCK, add buffer sizes checks

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2013-04-09 10:31:33 -04:00
Alex Deucher 43f1214aa0 drm/radeon: use IBs for VM page table updates v2
For very large page table updates, we can exceed the
size of the ring.  To avoid this, use an IB to perform
the page table update.

v2(ck): cleanup the IB infrastructure and the use it instead
        of filling the struct ourself.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
2013-02-01 13:57:10 -05:00
Alex Deucher fd5d93a001 drm/radeon: prevent crash in the ring space allocation
If the requested number of DWs on the ring is larger than
the size of the ring itself, return an error.

In testing with large VM updates, we've seen crashes when we
try and allocate more space on the ring than the total size
of the ring without checking.

This prevents the crash but for large VM updates or bo moves
of very large buffers, we will need to break the transaction
down into multiple batches.  I have patches to use IBs for
the next kernel.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
2013-01-31 16:14:16 -05:00
Jerome Glisse 5f0839c11e drm/radeon: improve semaphore debugging on lockup
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2013-01-15 09:07:13 -05:00
Jerome Glisse 4d0091904c drm/radeon: improve ring debugfs printing
Print 32dword before last know rptr as problem most likely comes
from previous command. Also small cosmetic change to the printing.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2013-01-03 13:18:40 -05:00
Jerome Glisse 74795486b2 drm/radeon: add debugfs file for dma rings
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2013-01-03 13:18:39 -05:00
Paul Bolle 501f9d4c1d radeon: Fix typo and copy/paste error in comments
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2012-11-26 14:28:44 +01:00
Thomas Friebel 8ad33cdf97 drm/radeon: fix spelling typos in debugging output
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2012-10-15 13:21:02 -04:00
Linus Torvalds 612a9aab56 Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge (part 1) from Dave Airlie:
 "So first of all my tree and uapi stuff has a conflict mess, its my
  fault as the nouveau stuff didn't hit -next as were trying to rebase
  regressions out of it before we merged.

  Highlights:
   - SH mobile modesetting driver and associated helpers
   - some DRM core documentation
   - i915 modesetting rework, haswell hdmi, haswell and vlv fixes, write
     combined pte writing, ilk rc6 support,
   - nouveau: major driver rework into a hw core driver, makes features
     like SLI a lot saner to implement,
   - psb: add eDP/DP support for Cedarview
   - radeon: 2 layer page tables, async VM pte updates, better PLL
     selection for > 2 screens, better ACPI interactions

  The rest is general grab bag of fixes.

  So why part 1? well I have the exynos pull req which came in a bit
  late but was waiting for me to do something they shouldn't have and it
  looks fairly safe, and David Howells has some more header cleanups
  he'd like me to pull, that seem like a good idea, but I'd like to get
  this merge out of the way so -next dosen't get blocked."

Tons of conflicts mostly due to silly include line changes, but mostly
mindless.  A few other small semantic conflicts too, noted from Dave's
pre-merged branch.

* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (447 commits)
  drm/nv98/crypt: fix fuc build with latest envyas
  drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering
  drm/nv41/vm: fix and enable use of "real" pciegart
  drm/nv44/vm: fix and enable use of "real" pciegart
  drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie
  drm/nouveau: store supported dma mask in vmmgr
  drm/nvc0/ibus: initial implementation of subdev
  drm/nouveau/therm: add support for fan-control modes
  drm/nouveau/hwmon: rename pwm0* to pmw1* to follow hwmon's rules
  drm/nouveau/therm: calculate the pwm divisor on nv50+
  drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster
  drm/nouveau/therm: move thermal-related functions to the therm subdev
  drm/nouveau/bios: parse the pwm divisor from the perf table
  drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices
  drm/nouveau/therm: rework thermal table parsing
  drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table
  drm/nouveau: fix pm initialization order
  drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it
  drm/nouveau: log channel debug/error messages from client object rather than drm client
  drm/nouveau: have drm debugging macros build on top of core macros
  ...
2012-10-03 23:29:23 -07:00
Alex Deucher 498522b455 drm/radeon: rework the vm_flush interface
Pass the vm and ring index rather than an IB.  This allows
us to use the vm_flush interface for non-IB cases in the
future.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
2012-10-02 15:01:21 -04:00
David Howells 760285e7e7 UAPI: (Scripted) Convert #include "..." to #include <path/...> in drivers/gpu/
Convert #include "..." to #include <path/...> in drivers/gpu/.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Dave Airlie <airlied@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Dave Jones <davej@redhat.com>
2012-10-02 18:01:07 +01:00
Christian König ca19f21ece drm/radeon: move IB pool to 1MB offset
Even GPUs can have a null pointer dereference, so move
the IB pool to another offset to catch those.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
2012-09-20 13:10:42 -04:00
Lauri Kasanen 1109ca09b9 drm/radeon: Mark all possible functions / structs as static
Let's allow GCC to optimize better.

This exposed some five unused functions, but this patch doesn't remove them.

Signed-off-by: Lauri Kasanen <cand@gmx.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
2012-09-20 13:10:41 -04:00
Christian König 9b40e5d842 drm/radeon: make VM flushs a ring operation
Move flushing the VMs as function into the rings.
First step to make VM operations async.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
2012-09-20 13:10:39 -04:00
Christian König 4bf3dd9264 drm/radeon: cleanup VM id handling a bit
Store a reference to the VM into the IB structure, that
makes calculating the IBs address a bit less complicated.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
2012-09-20 13:10:38 -04:00
Christian König 48c0ac9911 drm/radeon: init lockup timeout on ring init
Reset the lockup timeout on ring (re-)initialisation.

Otherwise we get error messages like this on gpu resets:
[ 1559.949177] radeon 0000:01:00.0: GPU lockup CP stall for more than 1482270msec

Signed-off-by: Christian König <deathsimple@vodafone.de>
cc: stable@vger.kernel.org
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
2012-08-20 11:09:48 -04:00
Dan Carpenter 1e179d4e28 drm/radeon: check for allocation failure in radeon_ring_backup()
Static checkers complain if this we don't check for allocation failure.
Also we can use the new kmalloc_array() function here as a cleanup.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-07-25 14:12:17 +10:00
Alex Deucher 75923280e5 drm/radeon: document radeon_ring.c (v4)
Adds documentation to most of the functions in
radeon_ring.c

v2: adjust per Christian's suggestions
v3: adjust per Christian's latest patches
v4: adjust per my latest changes

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
2012-07-18 13:53:38 +02:00
Alex Deucher 89d35807fb drm/radeon: update rptr saving logic for memory buffers
Add support for using memory buffers rather than
scratch registers.  Some rings may not be able to
write to scratch registers.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
2012-07-18 13:53:17 +02:00
Alex Deucher 8b25ed3482 drm/radeon: remove radeon_ring_index()
Just store the index in the ring structure.
Idea taken from one of Jerome's wip rptr patches.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
2012-07-18 13:33:54 +02:00
Christian König 4ef72566f1 drm/radeon: fix const IB handling v2
Const IBs are executed on the CE not the CP, so we can't
fence them in the normal way.

So submit them directly before the IB instead, just as
the documentation says.

v2: keep the extra documentation

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
2012-07-18 13:17:49 +02:00
Christian König 55d7c22192 drm/radeon: implement ring saving on reset v4
Try to save whatever is on the rings when
we encounter an lockup.

v2: Fix spelling error. Free saved ring data if reset fails.
    Add documentation for the new functions.
v3: Some more spelling fixes
v4: It doesn't make sense to save anything if all fences
    are signaled

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
2012-07-17 10:33:15 +02:00
Christian König 45df68035c drm/radeon: record what is next valid wptr for each ring v4
Before emitting any indirect buffer, emit the offset of the next
valid ring content if any. This allow code that want to resume
ring to resume ring right after ib that caused GPU lockup.

v2: use scratch registers instead of storing it into memory
v3: skip over the surface sync for ni and si as well
v4: use SET_CONFIG_REG instead of PACKET0

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
2012-07-17 10:33:09 +02:00
Christian König 2898c348e5 drm/radeon: remove ip_pool start/suspend
The IB pool is in gart memory, so it is completely
superfluous to unpin / repin it on suspend / resume.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
2012-07-17 10:32:41 +02:00
Christian König 07a713305a drm/radeon: fix ring commit padding
We don't need to pad anything if the number of dwords
written to the ring already matches the requirements.

Fixes some "writting more dword to ring than expected"
warnings.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
2012-07-17 10:32:08 +02:00
Christian König 220907d983 drm/radeon: rework ring syncing code
Move inter ring syncing with semaphores into the
existing ring allocations, with that we need to
lock the ring mutex only once.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
2012-06-21 09:38:40 +02:00
Christian König 876dc9f329 drm/radeon: remove radeon_fence_create
It is completely unnecessary to create fences
before they are emitted, so remove it and a bunch
of checks if fences are emitted or not.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
2012-06-21 09:38:35 +02:00
Dave Airlie c4c7f3149b radeon: make radeon_cs_update_pages static.
Just move its only caller into the same file as it and make it static.

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-29 11:01:45 +01:00
Alex Deucher 40f5cf9969 drm/radeon: add PRIME support (v2)
This adds prime->fd and fd->prime support to radeon.
It passes the sg object to ttm and then populates
the gart entries using it.

Compile tested only.

v2: stub kmap + use new helpers + add reimporting

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-23 10:47:11 +01:00
Jerome Glisse f2e3922106 drm/radeon: make the ib an inline object
No need to malloc it any more.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:55 +01:00
Jerome Glisse 68470ae7e6 drm/radeon: move the semaphore from the fence into the ib
It never really belonged there in the first place.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:49 +01:00
Jerome Glisse c507f7ef30 drm/radeon: rip out the ib pool
It isn't necessary any more and the suballocator seems to perform
even better.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:41 +01:00
Christian König c3b7fe8b8a drm/radeon: multiple ring allocator v3
A startover with a new idea for a multiple ring allocator.
Should perform as well as a normal ring allocator as long
as only one ring does somthing, but falls back to a more
complex algorithm if more complex things start to happen.

We store the last allocated bo in last, we always try to allocate
after the last allocated bo. Principle is that in a linear GPU ring
progression was is after last is the oldest bo we allocated and thus
the first one that should no longer be in use by the GPU.

If it's not the case we skip over the bo after last to the closest
done bo if such one exist. If none exist and we are not asked to
block we report failure to allocate.

If we are asked to block we wait on all the oldest fence of all
rings. We just wait for any of those fence to complete.

v2: We need to be able to let hole point to the list_head, otherwise
    try free will never free the first allocation of the list. Also
    stop calling radeon_fence_signalled more than necessary.

v3: Don't free allocations without considering them as a hole,
    otherwise we might lose holes. Also return ENOMEM instead of ENOENT
    when running out of fences to wait for. Limit the number of holes
    we try for each ring to 3.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:39 +01:00
Christian König 557017a0e2 drm/radeon: define new SA interface v3
Define the interface without modifying the allocation
algorithm in any way.

v2: rebase on top of fence new uint64 patch
v3: add ring to debugfs output

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:37 +01:00
Christian König 2e0d99103e drm/radeon: make sa bo a stand alone object
Allocating and freeing it seperately.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:35 +01:00
Christian König 711a972933 drm/radeon: add sub allocator debugfs file
Dumping the current allocations.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:33 +01:00
Christian König dd8bea2111 drm/radeon: use inline functions to calc sa_bo addr
Instead of hacking the calculation multiple times.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:31 +01:00
Christian König 8a47cc9ec1 drm/radeon: rework locking ring emission mutex in fence deadlock detection v2
Some callers illegal called fence_wait_next/empty
while holding the ring emission mutex. So don't
relock the mutex in that cases, and move the actual
locking into the fence code.

v2: Don't try to unlock the mutex if it isn't locked.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:20 +01:00
Jerome Glisse bb63556729 drm/radeon: convert fence to uint64_t v4
This convert fence to use uint64_t sequence number intention is
to use the fact that uin64_t is big enough that we don't need to
care about wrap around.

Tested with and without writeback using 0xFFFFF000 as initial
fence sequence and thus allowing to test the wrap around from
32bits to 64bits.

v2: Add comment about possible race btw CPU & GPU, add comment
    stressing that we need 2 dword aligned for R600_WB_EVENT_OFFSET
    Read fence sequenc in reverse order of GPU write them so we
    mitigate the race btw CPU and GPU.

v3: Drop the need for ring to emit the 64bits fence, and just have
    each ring emit the lower 32bits of the fence sequence. We
    handle the wrap over 32bits in fence_process.

v4: Just a small optimization: Don't reread the last_seq value
    if loop restarts, since we already know its value anyway.
    Also start at zero not one for seq value and use pre instead
    of post increment in emmit, otherwise wait_empty will deadlock.

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:17 +01:00
Christian König d6999bc7b5 drm/radeon: replace the per ring mutex with a global one
A single global mutex for ring submissions seems sufficient.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-09 17:22:14 +01:00
Christian König 7b9ef16bd1 drm/radeon: make forcing ring activity a common function
Nothing chipset or ring specific with it,
so also move it to radon_ring.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:38 +01:00
Christian König 67e3c78768 drm/radeon: unlock the ring mutex while waiting for the next fence
Fixing just another deadlock problem with gpu reset tests.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:37 +01:00
Christian König 3368ff0cf4 drm/radeon: make lockup timeout a module param
Don't hard code the 10 seconds timeout. Compute jobs
can run much longer.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:35 +01:00
Christian König 069211e555 drm/radeon: move lockup detection code into radeon_ring.c
It isn't chipset specific, so it makes no sense
to have that inside r100.c.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:33 +01:00
Christian König 7bd560e885 drm/radeon: use central function for IB testing
Removing all the different error messages and
having just one standard behaviour over all
chipset generations.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:10 +01:00
Christian König ec1a6cce77 drm/radeon: register ring debugfs handlers on init
Just register the debugfs files on init instead of
checking the chipset type multiple times.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-05-03 09:16:06 +01:00
Alex Deucher dfcf5f3652 drm/radeon/kms: add support for the CONST IB to the CS ioctl
This adds a new chunk id to the CS ioctl to support the
INDIRECT_BUFFER_CONST packet.

On SI, the CP adds a new engine called the CE (Constant Engine)
which runs simulatenously with the DE (Drawing Engine, formerly
called the ME).  This allows the CP to process two related IBs
simultaneously.  The CE is tasked with loading the constant data
(constant buffers, resource descriptors, samplers, etc.) while
the DE loads context register state and issues drawing commands.
It's up to the userspace application to sychronize the CE and the
DE using special synchronization packets.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-03-21 06:55:53 +00:00
Dave Airlie 8229c885fe drm: Merge tag 'v3.3-rc7' into drm-core-next
Merge the fixes so far into core-next, needed to test
intel driver.

Conflicts:
	drivers/gpu/drm/i915/intel_ringbuffer.c
2012-03-15 10:24:32 +00:00
Christian König 293f9fd53a drm/radeon: fix IB debugfs files for multiple cards
Storing pointers to the IBs in a static var just
leads to giving the same content back for all
cards in the system.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Jerome Glisse <jglisse@redhat.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-02-29 10:11:54 +00:00