* [PATCH] OneNAND: Simple Bad Block handling support
@ 2005-08-18 8:16 Kyungmin Park
2005-08-23 13:56 ` Bernhard Priewasser
0 siblings, 1 reply; 12+ messages in thread
From: Kyungmin Park @ 2005-08-18 8:16 UTC (permalink / raw)
To: linux-mtd; +Cc: 'Thomas Gleixner'
[-- Attachment #1: Type: text/plain, Size: 589 bytes --]
Hi
As I mentioned before we want to use another bad block handling method.
But now we have to push OneNAND to official MTD not experimental
so I implement simple bad block table (BBT) routine
It's almost same as NAND does.
After merge. we have to split BBT into core and chip specific code.
As the first step, I add bad block header file (bbm.h). It has bad block
data structure, macro and etc.
I don't know which directory are used as bbt_core.c(?) location?
Please let me know how to use as official OneNAND MTD support and when?
Any comments are welcome.
Thank you.
Kyungmin Park
[-- Attachment #2: onenand-bbm.patch --]
[-- Type: application/octet-stream, Size: 19614 bytes --]
diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile
--- a/drivers/mtd/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
@@ -3,7 +3,9 @@
#
# Core functionality.
-obj-$(CONFIG_MTD_ONENAND) += onenand_base.o
+obj-$(CONFIG_MTD_ONENAND) += onenand.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
+
+onenand-objs = onenand_base.o onenand_bbt.o
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -311,19 +311,21 @@ static int onenand_wait(struct mtd_info
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl);
- return -EAGAIN;
+ /* It maybe occur at initial bad block */
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
+ /* Clear other interrupt bits for preventing ECC error */
+ interrupt &= ONENAND_INT_MASTER;
}
if (ctrl & ONENAND_CTRL_LOCK) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl);
- return -EIO;
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ return -EACCES;
}
if (interrupt & ONENAND_INT_READ) {
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc);
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
return -EBADMSG;
}
}
@@ -1060,6 +1062,25 @@ static int onenand_writev(struct mtd_inf
}
/**
+ * onenand_block_checkbad - [GENERIC] Check if a block is marked bad
+ * @param mtd MTD device structure
+ * @param ofs offset from device start
+ * @param getchip 0, if the chip is already selected
+ * @param allowbbt 1, if its allowed to access the bbt area
+ *
+ * Check, if the block is bad. Either by reading the bad block table or
+ * calling of the scan function.
+ */
+static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+
+ /* Return info from the table */
+ return bbm->isbad_bbt(mtd, ofs, allowbbt);
+}
+
+/**
* onenand_erase - [MTD Interface] erase block(s)
* @param mtd MTD device structure
* @param instr erase instruction
@@ -1109,7 +1130,12 @@ static int onenand_erase(struct mtd_info
while (len) {
- /* TODO Check badblock */
+ /* Check if we have a bad block, we do not erase bad blocks */
+ if (onenand_block_checkbad(mtd, addr, 0, 0)) {
+ printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr);
+ instr->state = MTD_ERASE_FAILED;
+ goto erase_exit;
+ }
this->command(mtd, ONENAND_CMD_ERASE, addr, block_size);
@@ -1161,34 +1187,70 @@ static void onenand_sync(struct mtd_info
onenand_release_device(mtd);
}
+
/**
* onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Check whether the block is bad
*/
static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
- /*
- * TODO
- * 1. Bad block table (BBT)
- * -> using NAND BBT to support JFFS2
- * 2. Bad block management (BBM)
- * -> bad block replace scheme
- *
- * Currently we do nothing
- */
- return 0;
+ /* Check for invalid offset */
+ if (ofs > mtd->size)
+ return -EINVAL;
+
+ return onenand_block_checkbad(mtd, ofs, 1, 0);
+}
+
+/**
+ * onenand_default_block_markbad - [DEFAULT] mark a block bad
+ * @param mtd MTD device structure
+ * @param ofs offset from device start
+ *
+ * This is the default implementation, which can be overridden by
+ * a hardware specific driver.
+ */
+static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ u_char buf[2] = {0, 0};
+ size_t retlen;
+ int block;
+
+ /* Get block number */
+ block = ((int) ofs) >> bbm->bbt_erase_shift;
+ if (bbm->bbt)
+ bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+
+ /* We write two bytes, so we dont have to mess with 16 bit access */
+ ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
+ return mtd->write_oob(mtd, ofs , 2, &retlen, buf);
}
/**
* onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
* @param mtd MTD device structure
* @param ofs offset relative to mtd start
+ *
+ * Mark the block as bad
*/
static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
- /* see above */
- return 0;
+ struct onenand_chip *this = mtd->priv;
+ int ret;
+
+ ret = onenand_block_isbad(mtd, ofs);
+ if (ret) {
+ /* If it was bad already, return success and do nothing */
+ if (ret > 0)
+ return 0;
+ return ret;
+ }
+
+ return this->block_markbad(mtd, ofs);
}
/**
@@ -1411,6 +1473,11 @@ int onenand_scan(struct mtd_info *mtd, i
if (!this->write_bufferram)
this->write_bufferram = onenand_write_bufferram;
+ if (!this->block_markbad)
+ this->block_markbad = onenand_default_block_markbad;
+ if (!this->scan_bbt)
+ this->scan_bbt = onenand_default_bbt;
+
if (onenand_probe(mtd))
return -ENXIO;
@@ -1472,7 +1539,7 @@ int onenand_scan(struct mtd_info *mtd, i
/* Unlock whole block */
mtd->unlock(mtd, 0x0, this->chipsize);
- return 0;
+ return this->scan_bbt(mtd);
}
/**
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
new file mode 100644
--- /dev/null
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -0,0 +1,246 @@
+/*
+ * linux/drivers/mtd/onenand/onenand_bbt.c
+ *
+ * Bad Block Table support for the OneNAND driver
+ *
+ * Copyright(c) 2005 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Derived from nand_bbt.c
+ *
+ * TODO:
+ * Split BBT core and chip specific BBT.
+ */
+
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/compatmac.h>
+
+/**
+ * check_short_pattern - [GENERIC] check if a pattern is in the buffer
+ * @param buf the buffer to search
+ * @param len the length of buffer to search
+ * @param paglen the pagelength
+ * @param td search pattern descriptor
+ *
+ * Check for a pattern at the given place. Used to search bad block
+ * tables and good / bad block identifiers. Same as check_pattern, but
+ * no optional empty check and the pattern is expected to start
+ * at offset 0.
+ *
+ */
+static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
+{
+ int i;
+ uint8_t *p = buf;
+
+ /* Compare the pattern */
+ for (i = 0; i < td->len; i++) {
+ if (p[i] != td->pattern[i])
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * create_bbt - [GENERIC] Create a bad block table by scanning the device
+ * @param mtd MTD device structure
+ * @param buf temporary buffer
+ * @param bd descriptor for the good/bad block search pattern
+ * @param chip create the table for a specific chip, -1 read all chips.
+ * Applies only if NAND_BBT_PERCHIP option is set
+ *
+ * Create a bad block table by scanning the device
+ * for the given good/bad block identify pattern
+ */
+static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int i, j, numblocks, len, scanlen;
+ int startblock;
+ loff_t from;
+ size_t readlen, ooblen;
+
+ printk(KERN_INFO "Scanning device for bad blocks\n");
+
+ len = 1;
+
+ /* We need only read few bytes from the OOB area */
+ scanlen = ooblen = 0;
+ readlen = bd->len;
+
+ /* chip == -1 case only */
+ /* Note that numblocks is 2 * (real numblocks) here;
+ * see i += 2 below as it makses shifting and masking less painful
+ */
+ numblocks = mtd->size >> (bbm->bbt_erase_shift - 1);
+ startblock = 0;
+ from = 0;
+
+ for (i = startblock; i < numblocks; ) {
+ int ret;
+
+ for (j = 0; j < len; j++) {
+ size_t retlen;
+
+ /* No need to read pages fully,
+ * just read required OOB bytes */
+ ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,
+ readlen, &retlen, &buf[0]);
+
+ if (ret)
+ return ret;
+
+ if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+ bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
+ printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+ i >> 1, (unsigned int) from);
+ break;
+ }
+ }
+ i += 2;
+ from += (1 << bbm->bbt_erase_shift);
+ }
+
+ return 0;
+}
+
+
+/**
+ * onenand_memory_bbt - [GENERIC] create a memory based bad block table
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function creates a memory based bbt by scanning the device
+ * for manufacturer / software marked good / bad blocks
+ */
+static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ unsigned char data_buf[mtd->oobblock + mtd->oobsize];
+
+ bd->options &= ~NAND_BBT_SCANEMPTY;
+ return create_bbt(mtd, data_buf, bd, -1);
+}
+
+/**
+ * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad
+ * @param mtd MTD device structure
+ * @param offs offset in the device
+ * @param allowbbt allow access to bad block table region
+ */
+static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int block;
+ uint8_t res;
+
+ /* Get block number * 2 */
+ block = (int) (offs >> (bbm->bbt_erase_shift - 1));
+ res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03;
+
+ DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+ (unsigned int) offs, block >> 1, res);
+
+ switch ((int) res) {
+ case 0x00: return 0;
+ case 0x01: return 1;
+ case 0x02: return allowbbt ? 0 : 1;
+ }
+
+ return 1;
+}
+
+/**
+ * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s)
+ * @param mtd MTD device structure
+ * @param bd descriptor for the good/bad block search pattern
+ *
+ * The function checks, if a bad block table(s) is/are already
+ * available. If not it scans the device for manufacturer
+ * marked good / bad blocks and writes the bad block table(s) to
+ * the selected place.
+ *
+ * The bad block table memory is allocated here. It must be freed
+ * by calling the onenand_free_bbt function.
+ *
+ */
+int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm = this->bbm;
+ int len, ret = 0;
+
+ len = mtd->size >> (this->erase_shift + 2);
+ /* Allocate memory (2bit per block) */
+ bbm->bbt = kmalloc(len, GFP_KERNEL);
+ if (!bbm->bbt) {
+ printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+ return -ENOMEM;
+ }
+ /* Clear the memory bad block table */
+ memset(bbm->bbt, 0x00, len);
+
+ /* Set the bad block position */
+ bbm->badblockpos = ONENAND_BADBLOCK_POS;
+
+ /* Set erase shift */
+ bbm->bbt_erase_shift = this->erase_shift;
+
+ if (!bbm->isbad_bbt)
+ bbm->isbad_bbt = onenand_isbad_bbt;
+
+ /* Scan the device to build a memory based bad block table */
+ if ((ret = onenand_memory_bbt(mtd, bd))) {
+ printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n");
+ kfree(bbm->bbt);
+ bbm->bbt = NULL;
+ }
+
+ return ret;
+}
+
+/*
+ * Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks.
+ */
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr largepage_memorybased = {
+ .options = 0,
+ .offs = 0,
+ .len = 2,
+ .pattern = scan_ff_pattern,
+};
+
+/**
+ * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device
+ * @param mtd MTD device structure
+ *
+ * This function selects the default bad block table
+ * support for the device and calls the onenand_scan_bbt function
+ */
+int onenand_default_bbt(struct mtd_info *mtd)
+{
+ struct onenand_chip *this = mtd->priv;
+ struct bbm_info *bbm;
+
+ this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL);
+ if (!this->bbm)
+ return -ENOMEM;
+
+ bbm = this->bbm;
+
+ memset(bbm, 0, sizeof(struct bbm_info));
+
+ /* 1KB page has same configuration as 2KB page */
+ if (!bbm->badblock_pattern)
+ bbm->badblock_pattern = &largepage_memorybased;
+
+ return onenand_scan_bbt(mtd, bbm->badblock_pattern);
+}
+
+EXPORT_SYMBOL(onenand_scan_bbt);
+EXPORT_SYMBOL(onenand_default_bbt);
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
new file mode 100644
--- /dev/null
+++ b/include/linux/mtd/bbm.h
@@ -0,0 +1,122 @@
+/*
+ * linux/include/linux/mtd/bbm.h
+ *
+ * NAND family Bad Block Management (BBM) header file
+ * - Bad Block Table (BBT) implementation
+ *
+ * Copyright (c) 2005 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * Copyright (c) 2000-2005
+ * Thomas Gleixner <tglx@linuxtronix.de>
+ *
+ */
+#ifndef __LINUX_MTD_BBM_H
+#define __LINUX_MTD_BBM_H
+
+/* The maximum number of NAND chips in an array */
+#define NAND_MAX_CHIPS 8
+
+/**
+ * struct nand_bbt_descr - bad block table descriptor
+ * @param options options for this descriptor
+ * @param pages the page(s) where we find the bbt, used with
+ * option BBT_ABSPAGE when bbt is searched,
+ * then we store the found bbts pages here.
+ * Its an array and supports up to 8 chips now
+ * @param offs offset of the pattern in the oob area of the page
+ * @param veroffs offset of the bbt version counter in the oob are of the page
+ * @param version version read from the bbt page during scan
+ * @param len length of the pattern, if 0 no pattern check is performed
+ * @param maxblocks maximum number of blocks to search for a bbt. This number of
+ * blocks is reserved at the end of the device
+ * where the tables are written.
+ * @param reserved_block_code if non-0, this pattern denotes a reserved
+ * (rather than bad) block in the stored bbt
+ * @param pattern pattern to identify bad block table or factory marked
+ * good / bad blocks, can be NULL, if len = 0
+ *
+ * Descriptor for the bad block table marker and the descriptor for the
+ * pattern which identifies good and bad blocks. The assumption is made
+ * that the pattern and the version count are always located in the oob area
+ * of the first block.
+ */
+struct nand_bbt_descr {
+ int options;
+ int pages[NAND_MAX_CHIPS];
+ int offs;
+ int veroffs;
+ uint8_t version[NAND_MAX_CHIPS];
+ int len;
+ int maxblocks;
+ int reserved_block_code;
+ uint8_t *pattern;
+};
+
+/* Options for the bad block table descriptors */
+
+/* The number of bits used per block in the bbt on the device */
+#define NAND_BBT_NRBITS_MSK 0x0000000F
+#define NAND_BBT_1BIT 0x00000001
+#define NAND_BBT_2BIT 0x00000002
+#define NAND_BBT_4BIT 0x00000004
+#define NAND_BBT_8BIT 0x00000008
+/* The bad block table is in the last good block of the device */
+#define NAND_BBT_LASTBLOCK 0x00000010
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_ABSPAGE 0x00000020
+/* The bbt is at the given page, else we must scan for the bbt */
+#define NAND_BBT_SEARCH 0x00000040
+/* bbt is stored per chip on multichip devices */
+#define NAND_BBT_PERCHIP 0x00000080
+/* bbt has a version counter at offset veroffs */
+#define NAND_BBT_VERSION 0x00000100
+/* Create a bbt if none axists */
+#define NAND_BBT_CREATE 0x00000200
+/* Search good / bad pattern through all pages of a block */
+#define NAND_BBT_SCANALLPAGES 0x00000400
+/* Scan block empty during good / bad block scan */
+#define NAND_BBT_SCANEMPTY 0x00000800
+/* Write bbt if neccecary */
+#define NAND_BBT_WRITE 0x00001000
+/* Read and write back block contents when writing bbt */
+#define NAND_BBT_SAVECONTENT 0x00002000
+/* Search good / bad pattern on the first and the second page */
+#define NAND_BBT_SCAN2NDPAGE 0x00004000
+
+/* The maximum number of blocks to scan for a bbt */
+#define NAND_BBT_SCAN_MAXBLOCKS 4
+
+/*
+ * Constants for oob configuration
+ */
+#define ONENAND_BADBLOCK_POS 0
+
+/**
+ * struct bbt_info - [GENERIC] Bad Block Table data structure
+ * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
+ * @param badblockpos [INTERN] position of the bad block marker in the oob area
+ * @param bbt [INTERN] bad block table pointer
+ * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan
+ * @param priv [OPTIONAL] pointer to private bbm date
+ */
+struct bbm_info {
+ int bbt_erase_shift;
+ int badblockpos;
+ int options;
+
+ uint8_t *bbt;
+
+ int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt);
+
+ /* TODO Add more NAND specific fileds */
+ struct nand_bbt_descr *badblock_pattern;
+
+ void *priv;
+};
+
+/* OneNAND BBT interface */
+extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int onenand_default_bbt(struct mtd_info *mtd);
+
+#endif /* __LINUX_MTD_BBM_H */
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/mtd/onenand_regs.h>
+#include <linux/mtd/bbm.h>
#define MAX_BUFFERRAM 2
@@ -67,10 +68,14 @@ struct onenand_bufferram {
* @param wait [REPLACEABLE] hardware specific function for wait on ready
* @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
* @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area
+ * @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND
+ * @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND
+ * @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table
* @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip
* @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress
* @param state [INTERN] the current state of the OneNAND device
* @param autooob [REPLACEABLE] the default (auto)placement scheme
+ * @param bbm [REPLACEABLE] pointer to Bad Block Management
* @param priv [OPTIONAL] pointer to private chip date
*/
struct onenand_chip {
@@ -96,6 +101,8 @@ struct onenand_chip {
unsigned short (*read_word)(void __iomem *addr);
void (*write_word)(unsigned short value, void __iomem *addr);
void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
+ int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
+ int (*scan_bbt)(struct mtd_info *mtd);
spinlock_t chip_lock;
wait_queue_head_t wq;
@@ -103,6 +110,8 @@ struct onenand_chip {
struct nand_oobinfo *autooob;
+ void *bbm;
+
void *priv;
};
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-18 8:16 [PATCH] OneNAND: Simple Bad Block handling support Kyungmin Park
@ 2005-08-23 13:56 ` Bernhard Priewasser
2005-08-23 23:42 ` Kyungmin Park
0 siblings, 1 reply; 12+ messages in thread
From: Bernhard Priewasser @ 2005-08-23 13:56 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
Hi,
trying patching a today's snapshot I get:
patch -p1 < onenand-bbm.patch
patching file drivers/mtd/onenand/Makefile
Hunk #1 FAILED at 3.
1 out of 1 hunk FAILED -- saving rejects to file
drivers/mtd/onenand/Makefile.rej
patching file drivers/mtd/onenand/onenand_base.c
Hunk #1 FAILED at 311.
Hunk #2 succeeded at 1033 (offset -29 lines).
Hunk #3 succeeded at 1101 (offset -29 lines).
Hunk #4 succeeded at 1158 (offset -29 lines).
Hunk #5 succeeded at 1444 (offset -29 lines).
Hunk #6 succeeded at 1504 (offset -35 lines).
1 out of 6 hunks FAILED -- saving rejects to file
drivers/mtd/onenand/onenand_base.c.rej
patching file drivers/mtd/onenand/onenand_bbt.c
patching file include/linux/mtd/bbm.h
patching file include/linux/mtd/onenand.h
Hunk #3 FAILED at 101.
Hunk #4 succeeded at 109 (offset -1 lines).
1 out of 4 hunks FAILED -- saving rejects to file
include/linux/mtd/onenand.h.rej
.rej files are available.
Perhaps it's a silly fault... I'm new to diff/patch, sorry.
Regards,
Bernhard
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-23 13:56 ` Bernhard Priewasser
@ 2005-08-23 23:42 ` Kyungmin Park
2005-08-24 9:24 ` Bernhard Priewasser
2005-08-24 10:49 ` Bernhard Priewasser
0 siblings, 2 replies; 12+ messages in thread
From: Kyungmin Park @ 2005-08-23 23:42 UTC (permalink / raw)
To: 'Bernhard Priewasser'; +Cc: linux-mtd
Hi
Which directory are you patch? MTD-CVS or kernel?
In MTD-CVS I also have similar message
$ patch --dry-run -p1 < ../onenand-bbm.patch
patching file drivers/mtd/onenand/Makefile
Hunk #1 FAILED at 3.
1 out of 1 hunk FAILED -- saving rejects to file
drivers/mtd/onenand/Makefile.rej
patching file drivers/mtd/onenand/onenand_base.c
Hunk #1 FAILED at 311.
Hunk #2 succeeded at 1033 (offset -29 lines).
Hunk #4 succeeded at 1158 (offset -29 lines).
Hunk #6 succeeded at 1504 (offset -35 lines).
1 out of 6 hunks FAILED -- saving rejects to file
drivers/mtd/onenand/onenand_base.c.rej
patching file drivers/mtd/onenand/onenand_bbt.c
patching file include/linux/mtd/bbm.h
patching file include/linux/mtd/onenand.h
Hunk #3 FAILED at 101.
Hunk #4 succeeded at 109 (offset -1 lines).
1 out of 4 hunks FAILED -- saving rejects to file
include/linux/mtd/onenand.h.rej
I think the patch scenario is following
1. patching onenand-syncread.patch (check previous e-mail)
2. onenand-bbm.patch
3. omap-onenand.patch
Try again and If you have same problem. please let me know
In my test there's two .rej file
./drivers/mtd/onenand/Makefile.rej
./drivers/mtd/onenand/onenand_base.c.rej
***************
*** 3,9 ****
#
# Core functionality.
- obj-$(CONFIG_MTD_ONENAND) += onenand_base.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
--- 3,11 ----
#
# Core functionality.
+ obj-$(CONFIG_MTD_ONENAND) += onenand.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o
+
+ onenand-objs = onenand_base.o onenand_bbt.o
***************
*** 311,329 ****
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error =
0x%04x", ctrl);
- return -EAGAIN;
}
if (ctrl & ONENAND_CTRL_LOCK) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error =
0x%04x", ctrl);
- return -EIO;
}
if (interrupt & ONENAND_INT_READ) {
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error =
0x%04x", ecc);
return -EBADMSG;
}
}
--- 311,331 ----
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
+ /* It maybe occur at initial bad block */
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error =
0x%04x\n", ctrl);
+ /* Clear other interrupt bits for preventing ECC error */
+ interrupt &= ONENAND_INT_MASTER;
}
if (ctrl & ONENAND_CTRL_LOCK) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error =
0x%04x\n", ctrl);
+ return -EACCES;
}
if (interrupt & ONENAND_INT_READ) {
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error =
0x%04x\n", ecc);
return -EBADMSG;
}
}
I tried to solve this problem
Thank you
Kyungmin Park
> -----Original Message-----
> From: Bernhard Priewasser [mailto:priewasser@gmail.com]
> Sent: Tuesday, August 23, 2005 10:57 PM
> To: kyungmin.park@samsung.com
> Cc: linux-mtd@lists.infradead.org
> Subject: Re: [PATCH] OneNAND: Simple Bad Block handling support
>
> Hi,
>
> trying patching a today's snapshot I get:
>
> patch -p1 < onenand-bbm.patch
> patching file drivers/mtd/onenand/Makefile
> Hunk #1 FAILED at 3.
> 1 out of 1 hunk FAILED -- saving rejects to file
> drivers/mtd/onenand/Makefile.rej
> patching file drivers/mtd/onenand/onenand_base.c
> Hunk #1 FAILED at 311.
> Hunk #2 succeeded at 1033 (offset -29 lines).
> Hunk #3 succeeded at 1101 (offset -29 lines).
> Hunk #4 succeeded at 1158 (offset -29 lines).
> Hunk #5 succeeded at 1444 (offset -29 lines).
> Hunk #6 succeeded at 1504 (offset -35 lines).
> 1 out of 6 hunks FAILED -- saving rejects to file
> drivers/mtd/onenand/onenand_base.c.rej
> patching file drivers/mtd/onenand/onenand_bbt.c
> patching file include/linux/mtd/bbm.h
> patching file include/linux/mtd/onenand.h
> Hunk #3 FAILED at 101.
> Hunk #4 succeeded at 109 (offset -1 lines).
> 1 out of 4 hunks FAILED -- saving rejects to file
> include/linux/mtd/onenand.h.rej
>
> .rej files are available.
> Perhaps it's a silly fault... I'm new to diff/patch, sorry.
>
> Regards,
> Bernhard
>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-23 23:42 ` Kyungmin Park
@ 2005-08-24 9:24 ` Bernhard Priewasser
2005-08-24 10:49 ` Bernhard Priewasser
1 sibling, 0 replies; 12+ messages in thread
From: Bernhard Priewasser @ 2005-08-24 9:24 UTC (permalink / raw)
To: kyungmin.park, linux-mtd
> Which directory are you patch? MTD-CVS or kernel?
I ran it outside the kernel tree:
[...]/mtd/> patch -p1 onenand-bbm.patch
Trying it inside the kernel tree results in the same errors:
/usr/src/linux> patch -p1 /[...]/mtd/onenand-bbm.patch
> 1. patching onenand-syncread.patch (check previous e-mail)
> 2. onenand-bbm.patch
> 3. omap-onenand.patch
This order works better in some way: fewer fails :-) But errors anyway.
Did you try to apply the patches? In which way exactly? Applying them in
the correct order helps a bit, but I can't see any difference between
inside/outside kernel tree. Should I?...
But I'm not sure, because:
> Perhaps it's a silly fault... I'm new to diff/patch, sorry.
:-)
Ah, one thing: inline mail attaching onenand-syncread.patch causes some
incorrect line wrappings which have to be corrected manually before
running patch. Perhaps it would be better to send them really as .patch
files.
Regards,
Bernhard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-23 23:42 ` Kyungmin Park
2005-08-24 9:24 ` Bernhard Priewasser
@ 2005-08-24 10:49 ` Bernhard Priewasser
2005-08-24 23:36 ` Kyungmin Park
1 sibling, 1 reply; 12+ messages in thread
From: Bernhard Priewasser @ 2005-08-24 10:49 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1400 bytes --]
OK, sync read patch seems to work when applied directly to the kernel
tree, e.g.
> /usr/src/linux> patch -p1 < onenand-syncread_20050813.patch
BBM patch, e.g.
> /usr/src/linux> patch -p1 < onenand-bbm_20050818.patch
runs through nearly successful. I get a rej in onenand_base.c, line 311
(see attached file).
On line 315 you are looking for "return -EAGAIN;", but there's a "return
-EIO;" -> patch fails.
I don't know what's wrong with line 319/320, the patch fails anyway...
Same thing for line 326.
Is the following code valid (assuming patch has been run)?
> ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
> if (ctrl & ONENAND_CTRL_ERROR) {
> /* It maybe occur at initial bad block */
> DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n",
ctrl);
> /* Clear other interrupt bits for preventing ECC error */
> interrupt &= ONENAND_INT_MASTER;
> }
> if (ctrl & ONENAND_CTRL_LOCK) {
> DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error =
0x%04x\n", ctrl);
> return -EACCES;
> }
> if (interrupt & ONENAND_INT_READ) {
> ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
> if (ecc & ONENAND_ECC_2BIT_ALL) {
> DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
> return -EBADMSG;
> }
> }
1) interrupt &= ONENAND_INT_MASTER instead of return?
2) return -EACCES instead of return -EIO?
Bernhard
[-- Attachment #2: onenand_base.c.rej --]
[-- Type: text/plain, Size: 1413 bytes --]
*************** static int onenand_wait(struct mtd_info
*** 311,329 ****
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl);
- return -EAGAIN;
}
if (ctrl & ONENAND_CTRL_LOCK) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl);
- return -EIO;
}
if (interrupt & ONENAND_INT_READ) {
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc);
return -EBADMSG;
}
}
--- 311,331 ----
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
if (ctrl & ONENAND_CTRL_ERROR) {
+ /* It maybe occur at initial bad block */
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
+ /* Clear other interrupt bits for preventing ECC error */
+ interrupt &= ONENAND_INT_MASTER;
}
if (ctrl & ONENAND_CTRL_LOCK) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ return -EACCES;
}
if (interrupt & ONENAND_INT_READ) {
ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
if (ecc & ONENAND_ECC_2BIT_ALL) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
return -EBADMSG;
}
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-24 10:49 ` Bernhard Priewasser
@ 2005-08-24 23:36 ` Kyungmin Park
2005-08-25 7:56 ` Bernhard Priewasser
2005-09-01 9:30 ` Bernhard Priewasser
0 siblings, 2 replies; 12+ messages in thread
From: Kyungmin Park @ 2005-08-24 23:36 UTC (permalink / raw)
To: 'Bernhard Priewasser'; +Cc: linux-mtd
Thank you for replay and check the code
>
> Is the following code valid (assuming patch has been run)?
> > ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
>
> > if (ctrl & ONENAND_CTRL_ERROR) {
> > /* It maybe occur at initial bad block */
> > DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error
> = 0x%04x\n",
> ctrl);
> > /* Clear other interrupt bits for preventing ECC error */
> > interrupt &= ONENAND_INT_MASTER;
> > }
>
> > if (ctrl & ONENAND_CTRL_LOCK) {
> > DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error =
> 0x%04x\n", ctrl);
> > return -EACCES;
> > }
>
> > if (interrupt & ONENAND_INT_READ) {
> > ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
> > if (ecc & ONENAND_ECC_2BIT_ALL) {
> > DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC
> error = 0x%04x\n", ecc);
> > return -EBADMSG;
> > }
> > }
>
> 1) interrupt &= ONENAND_INT_MASTER instead of return?
=> Yes It's valid. During the initial bad block scanning, the
OneNAND controller return ctrl error. If we use return -EIO then OneNAND
scan failed, then we can't detect OneNAND chip. So we don't return any ctrl
error.
=> interrupt &= ONENAND_INT_MASTER. we always set master interrupt
bit in any case
> 2) return -EACCES instead of return -EIO?
=> I don't know which error code are correct. but I think locked
block access is EACCES instead of EIO
Kyungmin Park
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-24 23:36 ` Kyungmin Park
@ 2005-08-25 7:56 ` Bernhard Priewasser
2005-09-01 9:30 ` Bernhard Priewasser
1 sibling, 0 replies; 12+ messages in thread
From: Bernhard Priewasser @ 2005-08-25 7:56 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
Alright.
1) You could update your mtd sources and diff again, OR
simply replace BBM patch's line 23 "return -EAGAIN" with "return -EIO".
2) In syncread-patch you add "void (*mmcontrol)" on line 103 of
include/linux/onenand.h.
BBM patch is looking for this "void (*mmcontrol)" to add some new stuff
here. E.g. it doesn't search the "original" onenand.h (official MTD) but
the already syncread-patched onenand.h, bbm-patch cannot be run before
sync-patch was run.
No problem at all if one know's all this :-) Perhaps it would be good to
change the struct onenand_chip declaration order in a way that both
patches can be run independent of each other. Until they are put to MTD
CVS anyway...
-> THE RULES:
+ Run all the patches inside the kernel tree
+ Be aware of the right order:
1. onenand-syncread.patch
2. onenand-bbm.patch
3. omap-onenand.patch
Regards,
Bernhard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-08-24 23:36 ` Kyungmin Park
2005-08-25 7:56 ` Bernhard Priewasser
@ 2005-09-01 9:30 ` Bernhard Priewasser
2005-09-01 10:03 ` Kyungmin Park
1 sibling, 1 reply; 12+ messages in thread
From: Bernhard Priewasser @ 2005-09-01 9:30 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
Hi Kyungmin,
please let me bother you with another question.
It's about scanning for bad blocks during reading/writing flash (/* TODO
handling oob */...)
What's the possibility of having a bad block at r/w? OneNAND spec isn't
very extensive regarding handling bad blocks beside the initial scan.
Which things must/should be done by the flash driver, which ones by the
file system in this case?
I would be very grateful if you could give me a brief outline, I'm
afraid BBM is a bit "too new" for us because we are used to operate on
plain NOR... :-)
Thanks,
Bernhard
PS: Kyungmin, sorry for double mail
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] OneNAND: Simple Bad Block handling support
2005-09-01 9:30 ` Bernhard Priewasser
@ 2005-09-01 10:03 ` Kyungmin Park
2005-09-01 10:09 ` Bernhard Priewasser
2005-09-07 8:09 ` Bernhard Priewasser
0 siblings, 2 replies; 12+ messages in thread
From: Kyungmin Park @ 2005-09-01 10:03 UTC (permalink / raw)
To: 'Bernhard Priewasser'; +Cc: linux-mtd
Hi
>
> please let me bother you with another question.
> It's about scanning for bad blocks during reading/writing
> flash (/* TODO
> handling oob */...)
'TODO handling oob' is for YAFFS filesystem
In JFFS2, they only use erase mark at oob area
But YAFFS use some many files,
We needs to test YAFFS. currently not yet run and tested.
> What's the possibility of having a bad block at r/w?
OneNAND spec isn't
> very extensive regarding handling bad blocks beside the initial scan.
> Which things must/should be done by the flash driver, which
> ones by the
> file system in this case?
I don't know the exactly but I heard that JFFS2 handles runtime badblock
internally.
So OneNAND MTD don't care badblock handling in read/write function.
MTD only care the initial bad block at erase operation.
> I would be very grateful if you could give me a brief outline, I'm
> afraid BBM is a bit "too new" for us because we are used to
> operate on
> plain NOR... :-)
In our commercial software, we use another bad block handling, known as Bad
Block Management (BBM) based on replace instead of skip as BBT
So we don't care the intial bad and runtime bad.
Now we are trying to implement our scheme and will be released at open
source. But not yet available in this time.
If do you have any question. please let me know :)
Regards.
Kyungmin Park
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-09-01 10:03 ` Kyungmin Park
@ 2005-09-01 10:09 ` Bernhard Priewasser
2005-09-07 8:09 ` Bernhard Priewasser
1 sibling, 0 replies; 12+ messages in thread
From: Bernhard Priewasser @ 2005-09-01 10:09 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
> I don't know the exactly but I heard that JFFS2 handles runtime
> badblock internally.
> So OneNAND MTD don't care badblock handling in read/write function.
> MTD only care the initial bad block at erase operation.
Isn't this rather important? :-) As I said, I'm rather new to the bad
block stuff, so I'm ashamed of don't knowing it at all. Can JFFS2
recognize a bad block without OneNAND driver explicitely reporting one??
I'm very interested in this thing; presumably it may be easy to find out
having a look on the list's NAND BBT threads...
> In our commercial software, we use another bad block handling, known
> as Bad Block Management (BBM) based on replace instead of skip as BBT
> So we don't care the intial bad and runtime bad.
> Now we are trying to implement our scheme and will be released at open
> source. But not yet available in this time.
You are speaking about RFS? I'm wondering for quite a time about the
technical and commercial parallels/differences of MTD/JFFS2 and RFS...
Do you have any (public) comment on the occurence of (runtime) bad
blocks? When, why, ...?
> If do you have any question. please let me know :)
Too many to write down, but I'll try ;-)
Regards,
Bernhard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] OneNAND: Simple Bad Block handling support
2005-09-01 10:03 ` Kyungmin Park
2005-09-01 10:09 ` Bernhard Priewasser
@ 2005-09-07 8:09 ` Bernhard Priewasser
2005-09-07 11:44 ` Kyungmin Park
1 sibling, 1 reply; 12+ messages in thread
From: Bernhard Priewasser @ 2005-09-07 8:09 UTC (permalink / raw)
To: kyungmin.park; +Cc: linux-mtd
Hi all,
Kyungmin, I'm still not completely clear about your bad block handling,
sorry for bothering you another time.
In onenand_scan() you call scan_bbt() which calls onenand_memory_bbt()
which calls create_bbt() which builds the BBT using OOB data.
Fine so far.
But: the only time onenand_block_checkbad() is called is in
onenand_erase() before issueing the (erase-)command to prevent erasing
already scanned bad blocks.
Question: what about reading and writing (onenand_write_ecc(),
onenand_read_ecc())? There is no onenand_block_checkbad() before
issueing the write/read command. Shouldn't this be done??
scan_bbt() is only called on initial scan, e.g. device boot. What if
this happens very rarely and bad blocks due to wear occur; that meant
you cannot provide data integrity.
I wonder why this is not done in nand_base.c too. I'm afraid I missed
some BBT stuff to gather in my investigations :-)... So please kindly
excuse me if I'm wrong with my very limited MTD/OneNAND experience!
Best Regards,
Bernhard
^ permalink raw reply [flat|nested] 12+ messages in thread
* RE: [PATCH] OneNAND: Simple Bad Block handling support
2005-09-07 8:09 ` Bernhard Priewasser
@ 2005-09-07 11:44 ` Kyungmin Park
0 siblings, 0 replies; 12+ messages in thread
From: Kyungmin Park @ 2005-09-07 11:44 UTC (permalink / raw)
To: 'Bernhard Priewasser'; +Cc: linux-mtd
>
> Kyungmin, I'm still not completely clear about your bad block
> handling,
> sorry for bothering you another time.
>
> In onenand_scan() you call scan_bbt() which calls
> onenand_memory_bbt()
> which calls create_bbt() which builds the BBT using OOB data.
> Fine so far.
>
> But: the only time onenand_block_checkbad() is called is in
> onenand_erase() before issueing the (erase-)command to
> prevent erasing
> already scanned bad blocks.
>
> Question: what about reading and writing (onenand_write_ecc(),
> onenand_read_ecc())? There is no onenand_block_checkbad() before
> issueing the write/read command. Shouldn't this be done??
> scan_bbt() is only called on initial scan, e.g. device boot. What if
> this happens very rarely and bad blocks due to wear occur; that meant
> you cannot provide data integrity.
>
> I wonder why this is not done in nand_base.c too. I'm afraid I missed
> some BBT stuff to gather in my investigations :-)... So please kindly
> excuse me if I'm wrong with my very limited MTD/OneNAND experience!
>
Yes, The bbt scheme is same as NAND does. and OneNAND bbt is subset of NAND
bbt.
IMHO, There's some historical reason. If I was worng. please correct it
MTD only provides basic operations and handles initial badblock.
The rest is the part of FTL or Filesystem. Is it right?
Regards,
Kyungmin Park
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-09-07 11:46 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-18 8:16 [PATCH] OneNAND: Simple Bad Block handling support Kyungmin Park
2005-08-23 13:56 ` Bernhard Priewasser
2005-08-23 23:42 ` Kyungmin Park
2005-08-24 9:24 ` Bernhard Priewasser
2005-08-24 10:49 ` Bernhard Priewasser
2005-08-24 23:36 ` Kyungmin Park
2005-08-25 7:56 ` Bernhard Priewasser
2005-09-01 9:30 ` Bernhard Priewasser
2005-09-01 10:03 ` Kyungmin Park
2005-09-01 10:09 ` Bernhard Priewasser
2005-09-07 8:09 ` Bernhard Priewasser
2005-09-07 11:44 ` Kyungmin Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox