On Thu, Feb 2, 2012 at 10:26 AM, Ilija Hadzic
<ihadzic at research.bell-labs.com> wrote:
> Evergreen and NI blit copy was broken if the buffer maps to a rectangle
> whose one dimension is 16384 (max dimension allowed by these chips).
> In the mainline kernel, the problem is exposed only when buffers are
> very large (1G), but it's still a problem. The problem could be exposed
> for smaller buffers if anyone modifies the algorithm for rectangle
> construction in r600_blit_create_rect() (the reason why someone would
> modify that algorithm is to tune the performance of buffer moves).
>
> The root cause was in i2f() function which only operated on range between
> 0 and 16383. Fix this by extending the range of i2f() function to 0 to
> 32767.
>
> While at it improve the function so that the range can be easily
> extended in the future (if it becomes necessary), cleanup lines
> over 80 characters, and replace in-line comments with one strategic
> comment that explains the crux of the function.
>
> Credits to michel at daenzer.net for pointing out the root cause of
> the bug.
>
> v2: Fix I2F_MAX_INPUT constant definition goof and warn only once
> ? ?if input argument is out of range. Edit the comment a little
> ? ?bit to avoid some linguistic confusion and make it look better
> ? ?in general.
>
> Signed-off-by: Ilija Hadzic <ihadzic at research.bell-labs.com>

Should probably CC stable as well.

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

> ---
> ?drivers/gpu/drm/radeon/r600_blit_kms.c | ? 35 ++++++++++++++++++++++---------
> ?1 files changed, 25 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c 
> b/drivers/gpu/drm/radeon/r600_blit_kms.c
> index d996f43..accc032 100644
> --- a/drivers/gpu/drm/radeon/r600_blit_kms.c
> +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
> @@ -468,27 +468,42 @@ set_default_state(struct radeon_device *rdev)
> ? ? ? ?radeon_ring_write(ring, sq_stack_resource_mgmt_2);
> ?}
>
> +#define I2F_MAX_BITS 15
> +#define I2F_MAX_INPUT ?((1 << I2F_MAX_BITS) - 1)
> +#define I2F_SHIFT (24 - I2F_MAX_BITS)
> +
> +/*
> + * Converts unsigned integer into 32-bit IEEE floating point representation.
> + * Conversion is not universal and only works for the range from 0
> + * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
> + * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
> + * I2F_MAX_BITS can be increased, but that will add to the loop iterations
> + * and slow us down. Conversion is done by shifting the input and counting
> + * down until the first 1 reaches bit position 23. The resulting counter
> + * and the shifted input are, respectively, the exponent and the fraction.
> + * The sign is always zero.
> + */
> ?static uint32_t i2f(uint32_t input)
> ?{
> ? ? ? ?u32 result, i, exponent, fraction;
>
> - ? ? ? if ((input & 0x3fff) == 0)
> - ? ? ? ? ? ? ? result = 0; /* 0 is a special case */
> + ? ? ? WARN_ON_ONCE(input > I2F_MAX_INPUT);
> +
> + ? ? ? if ((input & I2F_MAX_INPUT) == 0)
> + ? ? ? ? ? ? ? result = 0;
> ? ? ? ?else {
> - ? ? ? ? ? ? ? exponent = 140; /* exponent biased by 127; */
> - ? ? ? ? ? ? ? fraction = (input & 0x3fff) << 10; /* cheat and only
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? handle numbers below 
> 2^^15 */
> - ? ? ? ? ? ? ? for (i = 0; i < 14; i++) {
> + ? ? ? ? ? ? ? exponent = 126 + I2F_MAX_BITS;
> + ? ? ? ? ? ? ? fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
> +
> + ? ? ? ? ? ? ? for (i = 0; i < I2F_MAX_BITS; i++) {
> ? ? ? ? ? ? ? ? ? ? ? ?if (fraction & 0x800000)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ? ? ? ? ?else {
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fraction = fraction << 1; /* keep
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?shifting left 
> until top bit = 1 */
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fraction = fraction << 1;
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?exponent = exponent - 1;
> ? ? ? ? ? ? ? ? ? ? ? ?}
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? result = exponent << 23 | (fraction & 0x7fffff); /* mask
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? off top 
> bit; assumed 1 */
> + ? ? ? ? ? ? ? result = exponent << 23 | (fraction & 0x7fffff);
> ? ? ? ?}
> ? ? ? ?return result;
> ?}
> --
> 1.7.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to