summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/rheap.c
diff options
context:
space:
mode:
authorLi Yang <leoli@freescale.com>2006-09-29 12:15:52 +0200
committerPaul Mackerras <paulus@samba.org>2006-10-02 12:27:47 +0200
commit5e980823581682d1566e7b5089cf827ddd5f3c94 (patch)
tree62cb2475517700805ac473ea3f1752ff9eb6bed6 /arch/powerpc/lib/rheap.c
parent[POWERPC] Use check_legacy_ioport() for ISAPnP (diff)
downloadlinux-5e980823581682d1566e7b5089cf827ddd5f3c94.tar.xz
linux-5e980823581682d1566e7b5089cf827ddd5f3c94.zip
[POWERPC] Fix rheap alignment problem
Honor alignment parameter in the rheap allocator. This is needed by qe_lib. Remove compile warning. Signed-off-by: Pantelis Antoniou <pantelis@embeddedalley.com> Signed-off-by: Li Yang <leoli@freescale.com> Acked-by: Kumar Galak <galak@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/lib/rheap.c')
-rw-r--r--arch/powerpc/lib/rheap.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 31e511856dc5..57bf991ccd6e 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -423,17 +423,21 @@ void *rh_detach_region(rh_info_t * info, void *start, int size)
return (void *)s;
}
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
+void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
{
struct list_head *l;
rh_block_t *blk;
rh_block_t *newblk;
void *start;
- /* Validate size */
- if (size <= 0)
+ /* Validate size, (must be power of two) */
+ if (size <= 0 || (alignment & (alignment - 1)) != 0)
return ERR_PTR(-EINVAL);
+ /* given alignment larger that default rheap alignment */
+ if (alignment > info->alignment)
+ size += alignment - 1;
+
/* Align to configured alignment */
size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
@@ -476,15 +480,27 @@ void *rh_alloc(rh_info_t * info, int size, const char *owner)
attach_taken_block(info, newblk);
+ /* for larger alignment return fixed up pointer */
+ /* this is no problem with the deallocator since */
+ /* we scan for pointers that lie in the blocks */
+ if (alignment > info->alignment)
+ start = (void *)(((unsigned long)start + alignment - 1) &
+ ~(alignment - 1));
+
return start;
}
+void *rh_alloc(rh_info_t * info, int size, const char *owner)
+{
+ return rh_alloc_align(info, size, info->alignment, owner);
+}
+
/* allocate at precisely the given address */
void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
{
struct list_head *l;
rh_block_t *blk, *newblk1, *newblk2;
- unsigned long s, e, m, bs, be;
+ unsigned long s, e, m, bs = 0, be = 0;
/* Validate size */
if (size <= 0)