All of lore.kernel.org
 help / color / mirror / Atom feed
From: "hinko.kocevar@cetrtapot.si" <hinko.kocevar@cetrtapot.si>
To: Linux MTD <linux-mtd@lists.infradead.org>
Subject: Memory leak
Date: Wed, 09 Apr 2008 15:54:03 +0200	[thread overview]
Message-ID: <47FCCA7B.7050104@cetrtapot.si> (raw)

Hello,

I've ported 2.6.12 NAND module driver for our board to git tree version
(2.6.25-rc8). While testing the module, I've noticed that memory gets
eaten with each insmod/rmmod cycle. Eg. in ~12 minutes Slab consumption
rises from 1632 kB to 8584 kB, which is soon fatal for our embedded
system with 16megs of ram.

In my NAND driver only mtd_info and nand_chip structs are allocated in
module init, and accordingly released in module cleanup. Step by step
commenting lines in init/cleanup I came up with the conclusion that if
my drivers calls add_mtd_partition(), it leaks! If I comment out call to
add_mtd_partition() no more leaks are seen!?!?!

Quick inspectiion of /proc/slabinfo shows that 'sysfs_dir_cache' entry
'active_objs' rises from 3788 to 10800 - which is suspicious.

I've attached /proc/meminfo and /proc/slabinfo for my test, which does:
while c < 100
 insmod nand driver
 rmmod nand driver
 save meminfo
 save slabinfo
 inc c
done

I've put the dumps on the public FTP server for you to retrieve (size
71940 b):
http://4thway.0catch.com/dumps.zip

Attached is out NAND driver ported to 2.6.25-rc8.
---
/*
 *  drivers/mtd/nand/carneol.c
 *
 *  Copyright (C) 2005 Simon Posnjak (simon.posnjak@cetrtapot.si)
 *
 *  Based on :
 *    drivers/mtd/nand/spia.c
 *    Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
 *
 * Pin fliping code was "borowed" from Hinko Kocevar's TCS2301 driver
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Overview:
 *   This is a device driver for the NAND flash device found on the
 *   Carneol board which utilizes the Toshiba TC58 part.
 */

#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
#include <linux/platform_device.h>
#else
#include <linux/config.h>
#endif

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/fs.h>

#include <asm/io.h>
#include <asm/cpot/carneol-platform.h>

static unsigned char mod_name[]		= "carneol-nand";
static unsigned char mod_version[]	= "08040801";

static struct mtd_info *tc58512_mtd = NULL;


/*
 * All NAND flash signals are connected to cris PGx ports.
 */

/*
 * Data signals are on PG1 port pins b0 - b7. Direction of data pins must be
 * set before starting byte read/write operation on data pins.
 */
//#define TC58512_DATA		CARNEOL_PG1		/* PORTG b8 - b15 */
//#define TC58512_DATA0	CARNEOL_PG1_IO0	/* PORTG b8 */
//#define TC58512_DATA1	CARNEOL_PG1_IO1	/* PORTG b9 */
//#define TC58512_DATA2	CARNEOL_PG1_IO2	/* PORTG b10 */
//#define TC58512_DATA3	CARNEOL_PG1_IO3	/* PORTG b11 */
//#define TC58512_DATA4	CARNEOL_PG1_IO4	/* PORTG b12 */
//#define TC58512_DATA5	CARNEOL_PG1_IO5	/* PORTG b13 */
//#define TC58512_DATA6	CARNEOL_PG1_IO6	/* PORTG b14 */
//#define TC58512_DATA7	CARNEOL_PG1_IO7	/* PORTG b15 */

/*
 * Control signals are on PG2 port pins b1 - b6. Direction of control pins
 * is set to output in init stage.
 *
 * NOTE: PG2 pins b0 and b7 are not used for NAND flash!
 */
//#define TC58512_CTRL		CARNEOL_PG2		/* PORTG b16 - b23 */
//#define TC58512_RE		CARNEOL_PG2_IO1	/* PORTG b17 */
//#define TC58512_CE		CARNEOL_PG2_IO2	/* PORTG b18 */
//#define TC58512_CLE		CARNEOL_PG2_IO3	/* PORTG b19 */
//#define TC58512_ALE		CARNEOL_PG2_IO4	/* PORTG b20 */
//#define TC58512_WE		CARNEOL_PG2_IO5	/* PORTG b21 */
//#define TC58512_WP		CARNEOL_PG2_IO6	/* PORTG b22 */

/*
 * Status signal (chip ready) is on PG3 pin b0. Direction of status pin
 * is set to input in init stage.
 */
//#define TC58512_STATUS	CARNEOL_PG3		/* PORTG b24 - b31 */
//#define TC58512_RYBY		CARNEOL_PG3_IO0	/* PORTG b24 */

#if defined(CONFIG_CPOT_PLATFORM_AFC2)
const static struct mtd_partition partition_info[] =
{
	{
	 .name = "Carneol NAND part1 (program)",
	 .offset = 0,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part2 (dataout)",
	 .offset = 4 * 1024 * 1024,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part3 (datain)",
	 .offset = 8	* 1024 * 1024,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part4 (backup)",
	 .offset = 12 * 1024 * 1024,
	 .size = 8 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part5 (upgrade)",
	 .offset = 20 * 1024 * 1024,
	 .size = 8 * 1024 * 1024
	}
};
#define NUM_PARTITIONS 5
#elif defined(CONFIG_CPOT_PLATFORM_CDU2)
const static struct mtd_partition partition_info[] =
{
	{
	 .name = "Carneol NAND part1 (program)",
	 .offset = 0,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part2 (dataout)",
	 .offset = 4 * 1024 * 1024,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part3 (datain)",
	 .offset = 8	* 1024 * 1024,
	 .size = 4 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part4 (disk1)",
	 .offset = 12	* 1024 * 1024,
	 .size = 8 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part5 (disk2)",
	 .offset = 20	* 1024 * 1024,
	 .size = 8 * 1024 * 1024
	},
	{
	 .name = "Carneol NAND part4 (backup)",
	 .offset = 28	* 1024 * 1024,
	 .size = 4 * 1024 * 1024
	},

};
#define NUM_PARTITIONS 6
#elif defined(CONFIG_CPOT_PLATFORM_TAA2)
const static struct mtd_partition partition_info[] =
{
	{
	 .name = "Carneol NAND part1 (program)",
	 .offset = 0,
	 .size = 4 * 1024 * 1024,
	},
	{
	 .name = "Carneol NAND part2 (dataout)",
	 .offset = 4 * 1024 * 1024,
	 .size = 8 * 1024 * 1024,
	},
	{
	 .name = "Carneol NAND part3 (datain)",
	 .offset = 12	* 1024 * 1024,
	 .size = 8 * 1024 * 1024,
	},
	{
	 .name = "Carneol NAND part4 (lib)",
	 .offset = 20 * 1024 * 1024,
	 .size = 8 * 1024 * 1024,
	},
	{
	 .name = "Carneol NAND part5 (usr)",
	 .offset = 28 * 1024 * 1024,
	 .size = 4 * 1024 * 1024,
	},
};
#define NUM_PARTITIONS 5
#endif	/* CONFIG_CPOT_PLATFORM_AFC2, CDU2, TAA2 */

static u_char tc58512_read_byte (struct mtd_info *mtd);
static void tc58512_write_byte (struct mtd_info *mtd, u_char byte);
static void tc58512_write_buf (struct mtd_info *mtd, const u_char * buf,
int len);
static void tc58512_read_buf (struct mtd_info *mtd, u_char * buf, int len);
static int tc58512_verify_buf (struct mtd_info *mtd, const u_char * buf,
int len);


#if 0
57 /* Select the chip by setting nCE to low */
58 #define NAND_NCE								0x01
59 /* Select the command latch by setting CLE to high */
60 #define NAND_CLE								0x02
61 /* Select the address latch by setting ALE to high */
62 #define NAND_ALE								0x04
63
64 #define NAND_CTRL_CLE					 (NAND_NCE | NAND_CLE)
65 #define NAND_CTRL_ALE					 (NAND_NCE | NAND_ALE)
66 #define NAND_CTRL_CHANGE				0x80
#endif

static void tc58512_cmd_ctrl (struct mtd_info *mtd, int cmd, unsigned
int ctrl)
{
	if (ctrl & NAND_CTRL_CHANGE)
	{
		if (ctrl & NAND_NCE)
			//carneol_pin_low(TC58512_CTRL, TC58512_CE);
			carneol_low_pg_18();
		else
			//carneol_pin_high(TC58512_CTRL, TC58512_CE);
			carneol_high_pg_18();

		if (ctrl & NAND_CLE)
			//carneol_pin_high(TC58512_CTRL, TC58512_CLE);
			carneol_high_pg_19();
		else
			//carneol_pin_low(TC58512_CTRL, TC58512_CLE);
			carneol_low_pg_19();
	
		if (ctrl & NAND_ALE)
			//carneol_pin_high(TC58512_CTRL, TC58512_ALE);
			carneol_high_pg_20();
		else
			//carneol_pin_low(TC58512_CTRL, TC58512_ALE);
			carneol_low_pg_20();
	}

	if (cmd != NAND_CMD_NONE)
	{
		tc58512_write_byte(mtd, (unsigned char)cmd);
	}
}

static int tc58512_device_ready (struct mtd_info *mtd)
{
	/* 1 - chip is ready, 0 - chip is busy. */
	//return (int) (carneol_pin_level(TC58512_STATUS, TC58512_RYBY));
	return carneol_is_high_pg_24();
}

static u_char tc58512_read_byte (struct mtd_info *mtd)
{
	u_int8_t val;

	//carneol_port_input(TC58512_DATA);
	carneol_input_pg_8();
	//carneol_pin_low(TC58512_CTRL, TC58512_RE);
	carneol_low_pg_17();

	//val = (unsigned char) carneol_port_read(TC58512_DATA);
	val = carneol_read_pg1();
	//carneol_pin_high(TC58512_CTRL, TC58512_RE);
	carneol_high_pg_17();

	return val;
}

static void tc58512_write_byte (struct mtd_info *mtd, u_char byte)
{
	//carneol_port_output(TC58512_DATA);
	carneol_output_pg_8();
	
	//carneol_port_write(TC58512_DATA, (unsigned char)byte);
	carneol_write_pg1((u_int8_t) byte);
		
	//carneol_pin_low(TC58512_CTRL, TC58512_WE);
	carneol_low_pg_21();
	//carneol_pin_high(TC58512_CTRL, TC58512_WE);
	carneol_high_pg_21();
}

static void tc58512_write_buf (struct mtd_info *mtd, const u_char * buf,
int len)
{
	int i;

	//carneol_port_output(TC58512_DATA);
	carneol_output_pg_8();

	for (i = 0; i < len; i++)
	{
		//carneol_port_write(TC58512_DATA, (unsigned char)buf[i]);
		carneol_write_pg1((u_int8_t) buf[i]);
		//carneol_pin_low(TC58512_CTRL, TC58512_WE);
		carneol_low_pg_21();
		//carneol_pin_high(TC58512_CTRL, TC58512_WE);
		carneol_high_pg_21();
	}
}

static void tc58512_read_buf (struct mtd_info *mtd, u_char * buf, int len)
{
	int i;

	//carneol_port_input(TC58512_DATA);
	carneol_input_pg_8();

	for (i = 0; i < len; i++)
	{
		//carneol_pin_low(TC58512_CTRL, TC58512_RE);
		carneol_low_pg_17();
		//buf[i] = (unsigned char) carneol_port_read(TC58512_DATA);
		buf[i] = carneol_read_pg1();
		//carneol_pin_high(TC58512_CTRL, TC58512_RE);
		carneol_high_pg_17();
	}
}

static int tc58512_verify_buf (struct mtd_info *mtd, const u_char * buf,
int len)
{
	int i;

	//carneol_port_input(TC58512_DATA);
	carneol_input_pg_8();

	for (i = 0; i < len; i++)
	{
		//carneol_pin_low(TC58512_CTRL, TC58512_RE);
		carneol_low_pg_17();
		//if ((u_char) buf[i] != (unsigned char) carneol_port_read(TC58512_DATA))
		if ((u_int8_t) buf[i] != (u_int8_t) carneol_read_pg1())
			return -EFAULT;
		//carneol_pin_high(TC58512_CTRL, TC58512_RE);
		carneol_high_pg_17();
	}
	return 0;
}


static int __init tc58512_init (void)
{
	struct nand_chip *this;

	printk("Carneol %s module %s, (C) 2005 - 2008 Simon Posnjak, Hinko
Kocevar\n", mod_name, mod_version);
	
	tc58512_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),
			 GFP_KERNEL);
	if (!tc58512_mtd)
	{
		printk(KERN_ERR "%s: Unable to allocate carneol NAND MTD device
structure.\n", __func__);
		return -ENOMEM;
	}

	this = (struct nand_chip *) (&tc58512_mtd[1]);

	memset((char *) tc58512_mtd, 0, sizeof(struct mtd_info));
	memset((char *) this, 0, sizeof(struct nand_chip));

	tc58512_mtd->priv = this;
	tc58512_mtd->owner = THIS_MODULE;

	//carneol_port_output(TC58512_CTRL);
	carneol_output_pg_16();
	//carneol_port_input(TC58512_DATA);
	carneol_input_pg_8();
	//carneol_port_input(TC58512_STATUS);
	carneol_input_pg_24();

	//carneol_pin_low(TC58512_CTRL, TC58512_CLE);
	carneol_low_pg_19();
	//carneol_pin_low(TC58512_CTRL, TC58512_ALE);
	carneol_low_pg_20();
	//carneol_pin_high(TC58512_CTRL, TC58512_CE);
	carneol_high_pg_18();
	//carneol_pin_high(TC58512_CTRL, TC58512_RE);
	carneol_high_pg_17();
	//carneol_pin_high(TC58512_CTRL, TC58512_WE);
	carneol_high_pg_21();
	//carneol_pin_high(TC58512_CTRL, TC58512_WP);
	carneol_high_pg_22();

	this->read_byte = tc58512_read_byte;
	//this->write_byte = tc58512_write_byte;
	this->write_buf = tc58512_write_buf;
	this->read_buf = tc58512_read_buf;
	this->verify_buf = tc58512_verify_buf;
	this->dev_ready = tc58512_device_ready;
	
	/* Set address of hardware control function */
	this->cmd_ctrl = tc58512_cmd_ctrl;
	/* 3 us command delay time */
	this->chip_delay = 3;
	this->ecc.mode = NAND_ECC_SOFT;
	
	/* Scan to find existence of the device */
	if (nand_scan(tc58512_mtd, 1))
	{
		kfree(tc58512_mtd);
		return -ENXIO;
	}

#ifdef CONFIG_MTD_PARTITIONS
	/* Register the partitions */
	add_mtd_partitions(tc58512_mtd, partition_info, NUM_PARTITIONS);
#endif
	return 0;
}

static void __exit tc58512_cleanup (void)
{
#if 0
	/* Release MTD partitions */
	del_mtd_partitions(tc58512_mtd);
#endif
	
	/* Release resources, unregister device */
	nand_release(tc58512_mtd);

	/* Free the MTD device structure */
	kfree(tc58512_mtd);

	printk("Carneol %s module version %s removed\n", mod_name, mod_version);
}

module_init(tc58512_init);
module_exit(tc58512_cleanup);

MODULE_AUTHOR("Simon Posnjak <simon.posnjak@cetrtapot.si>, Hinko Kocevar
<hinko.kocevar@cetrtapot.si>");
MODULE_DESCRIPTION("CPOT Carneol NAND flash module for TC58512
compatible flash");
MODULE_LICENSE("GPL");

---

Best regards,
Hinko



-- 
ČETRTA POT, d.o.o., Kranj
Planina 3
4000 Kranj
Slovenia, Europe
Tel. +386 (0) 4 280 66 03
E-mail: hinko.kocevar@cetrtapot.si
Http: www.cetrtapot.si

             reply	other threads:[~2008-04-09 13:54 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-09 13:54 hinko.kocevar [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-01-19  5:14 [PATCH v26 2/2] status: add status.compareBranches config for multiple branch comparisons Jeff King
2026-01-20  9:49 ` Memory leak Harald Nordgren
2026-01-20 13:22   ` Harald Nordgren
2026-01-20 21:42     ` Junio C Hamano
2026-01-21 18:47       ` Junio C Hamano
2026-01-21 20:49         ` Jeff King
2026-01-22 15:03         ` Harald Nordgren
2026-01-22 18:19           ` Junio C Hamano
2003-03-12 19:50 Memory Leak Aman
2003-03-12 20:29 ` Matt Porter
2003-03-09 16:46 Memory leak matsunaga
2003-03-09 17:37 ` Charles Manning
2003-03-09 19:10 ` Thomas Gleixner
2003-03-09 23:10   ` matsunaga
2003-03-10 14:53     ` Thomas Gleixner
2003-03-10 14:14       ` David Woodhouse
2003-03-10 15:48         ` matsunaga
2003-03-10 16:02           ` David Woodhouse
2003-03-10 16:26             ` matsunaga
2003-03-10 17:04               ` David Woodhouse
2003-03-11 15:52                 ` matsunaga
2003-03-11 18:39                   ` Thomas Gleixner
2003-03-10 15:36       ` matsunaga
2003-03-11 17:50 ` David Woodhouse
2002-06-20 15:06 diekema_jon
2002-06-20  7:52 Skip Gaede
2002-06-22  2:22 ` Skip Gaede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47FCCA7B.7050104@cetrtapot.si \
    --to=hinko.kocevar@cetrtapot.si \
    --cc=linux-mtd@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.