From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S263033AbVCQJ5s (ORCPT ); Thu, 17 Mar 2005 04:57:48 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S263035AbVCQJ5s (ORCPT ); Thu, 17 Mar 2005 04:57:48 -0500 Received: from smtp1.adl2.internode.on.net ([203.16.214.181]:27663 "EHLO smtp1.adl2.internode.on.net") by vger.kernel.org with ESMTP id S263033AbVCQJ5H (ORCPT ); Thu, 17 Mar 2005 04:57:07 -0500 From: Michael Ellerman Reply-To: michael@ellerman.id.au Organization: IBM LTC To: linux-kernel@vger.kernel.org, linuxppc64-dev@ozlabs.org Subject: Why no bigphysarea in mainline? Date: Thu, 17 Mar 2005 20:57:04 +1100 User-Agent: KMail/1.7.2 MIME-Version: 1.0 Content-Type: multipart/signed; boundary="nextPart1411995.Goe5pq5K6y"; protocol="application/pgp-signature"; micalg=pgp-sha1 Content-Transfer-Encoding: 7bit Message-Id: <200503172057.06570.michael@ellerman.id.au> Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org --nextPart1411995.Goe5pq5K6y Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi all, Can anyone recall if there's ever been a discussion about merging the bigphysarea patch (see below) into mainline? I couldn't find much of interest on google. I realise bigphysarea is a bit of a hack, but it's no where near as big a hack as using mem=X to limit the kernel's memory and then using the rest of memory for your device driver. The reason I'm curious is because I've gotten several queries about the mem=X option on PPC64 and whether it will support this hack, which it won't. If no one has any fundamental objections I think it'd be good to get this merged into mainline so people start using it rather than mem=X hacks. To that end please let me know what you think is wrong with the patch as it stands (below). cheers Nick Martin's version for 2.6.9 (which applies to 2.6.11): http://www.ussg.iu.edu/hypermail/linux/kernel/0411.1/2076.html And the guts of it: Index: 2.6.11-bigphysarea/mm/bigphysarea.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ 2.6.11-bigphysarea/mm/bigphysarea.c 2005-03-17 19:15:08.256421832 +1100 @@ -0,0 +1,353 @@ +/* linux/mm/bigphysarea.c, M. Welsh (mdw@xxxxxxxxxxxxxx) + * Copyright (c) 1996 by Matt Welsh. + * Extended by Roger Butenuth (butenuth@xxxxxxxxxxxxxxxx), October 1997 + * Extended for linux-2.1.121 till 2.4.0 (June 2000) + * by Pauline Middelink + * Extended for linux-2.6.9 (November 2004) + * by Nick Martin + * + * This is a set of routines which allow you to reserve a large (?) + * amount of physical memory at boot-time, which can be allocated/deallocated + * by drivers. This memory is intended to be used for devices such as + * video framegrabbers which need a lot of physical RAM (above the amount + * allocated by kmalloc). This is by no means efficient or recommended; + * to be used only in extreme circumstances. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int get_info(char* buf, char**, off_t, int); + +typedef struct range_struct { + struct range_struct *next; + caddr_t base; /* base of allocated block */ + size_t size; /* size in bytes */ +} range_t; + +/* + * 0: nothing initialized + * 1: bigphysarea_pages initialized + * 2: free list initialized + */ +static int init_level = 0; +static int bigphysarea_pages = 0; +static caddr_t bigphysarea = 0; +static range_t *free_list = NULL; +static range_t *used_list = NULL; +static struct resource mem_resource = { "Bigphysarea", 0, 0, IORESOURCE_MEM|IORESOURCE_BUSY }; + +static +int __init bigphysarea_init(void) +{ + if (bigphysarea_pages == 0 || bigphysarea == 0) + return -EINVAL; + + /* create to /proc entry for it */ + if (!create_proc_info_entry("bigphysarea",0444,NULL,get_info)) { + // ohoh, no way to free the allocated memory! + // continue without proc support, it not fatal in itself +// free_bootmem((unsigned long)bigphysarea>>PAGE_SHIFT,bigphysarea_pages<next; + /* + * The free-list is sorted by address, search insertion point + * and insert block in free list. + */ + for (range_ptr = &free_list, prev = NULL; + *range_ptr != NULL; + prev = *range_ptr, range_ptr = &(*range_ptr)->next) + if ((*range_ptr)->base >= base) + break; + range->next = *range_ptr; + *range_ptr = range; + /* + * Concatenate free range with neighbors, if possible. + * Try for upper neighbor (next in list) first, then + * for lower neighbor (predecessor in list). + */ + if (range->next != NULL && + range->base + range->size == range->next->base) { + next = range->next; + range->size += range->next->size; + range->next = next->next; + kfree(next); + } + if (prev != NULL && + prev->base + prev->size == range->base) { + prev->size += prev->next->size; + prev->next = range->next; + kfree(range); + } +} +EXPORT_SYMBOL(bigphysarea_free_pages); + +caddr_t bigphysarea_alloc(int size) +{ + int pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + + return bigphysarea_alloc_pages(pages, 1, GFP_KERNEL); +} +EXPORT_SYMBOL(bigphysarea_alloc); + + +void bigphysarea_free(caddr_t addr, int size) +{ + (void)size; + bigphysarea_free_pages(addr); +} +EXPORT_SYMBOL(bigphysarea_free); + +static +int get_info(char *buf, char **a, off_t b, int c) +{ + char *p = buf; + range_t *ptr; + int free_count, free_total, free_max; + int used_count, used_total, used_max; + + if (init_level == 1) + init2(GFP_KERNEL); + + free_count = 0; + free_total = 0; + free_max = 0; + for (ptr = free_list; ptr != NULL; ptr = ptr->next) { + free_count++; + free_total += ptr->size; + if (ptr->size > free_max) + free_max = ptr->size; + } + + used_count = 0; + used_total = 0; + used_max = 0; + for (ptr = used_list; ptr != NULL; ptr = ptr->next) { + used_count++; + used_total += ptr->size; + if (ptr->size > used_max) + used_max = ptr->size; + } + + if (bigphysarea_pages == 0) { + p += sprintf(p, "No big physical area allocated!\n"); + return p - buf; + } + + p += sprintf(p, "Big physical area, size %ld kB\n", + bigphysarea_pages * PAGE_SIZE / 1024); + p += sprintf(p, " free list: used list:\n"); + p += sprintf(p, "number of blocks: %8d %8d\n", + free_count, used_count); + p += sprintf(p, "size of largest block: %8d kB %8d kB\n", + free_max / 1024, used_max / 1024); + p += sprintf(p, "total: %8d kB %8d kB\n", + free_total / 1024, used_total /1024); + + return p - buf; +} --nextPart1411995.Goe5pq5K6y Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQBCOVRydSjSd0sB4dIRAna3AKCLi4DKPPsQdS2ixUwiwFVmO0ElAwCffUqk M7mGJdV4NUO5LDn+xTx/0kQ= =vg9H -----END PGP SIGNATURE----- --nextPart1411995.Goe5pq5K6y--