On Thu, Feb 2, 2012 at 10:26 AM, Ilija Hadzic <ihadzic@xxxxxxxxxxxxxxxxxxxxxx> 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@xxxxxxxxxxx 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@xxxxxxxxxxxxxxxxxxxxxx> Should probably CC stable as well. Reviewed-by: Alex Deucher <alexander.deucher@xxxxxxx> > --- > 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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel