Commit 1a214ee6 authored by David Woodhouse's avatar David Woodhouse

Fix use-after-free bug in MTD partitioning code.

Define callback wrapper function mtd_erase_callback() to handle 
partition offsets during the callback, rather than attempting to 
fix them up in the freed erase_info structure after the callback 
has already happened.
parent 4ab06c9a
# $Id: Kconfig,v 1.5 2004/06/04 15:59:32 gleixner Exp $ # $Id: Kconfig,v 1.6 2004/08/09 13:19:42 dwmw2 Exp $
menu "Memory Technology Devices (MTD)" menu "Memory Technology Devices (MTD)"
...@@ -28,7 +28,7 @@ config MTD_DEBUG_VERBOSE ...@@ -28,7 +28,7 @@ config MTD_DEBUG_VERBOSE
Determines the verbosity level of the MTD debugging messages. Determines the verbosity level of the MTD debugging messages.
config MTD_PARTITIONS config MTD_PARTITIONS
tristate "MTD partitioning support" bool "MTD partitioning support"
depends on MTD depends on MTD
help help
If you have a device which needs to divide its flash chip(s) up If you have a device which needs to divide its flash chip(s) up
......
# #
# Makefile for the memory technology device drivers. # Makefile for the memory technology device drivers.
# #
# $Id: Makefile.common,v 1.3 2004/07/12 16:07:30 dwmw2 Exp $ # $Id: Makefile.common,v 1.4 2004/08/09 13:19:42 dwmw2 Exp $
# Core functionality. # Core functionality.
obj-$(CONFIG_MTD) += mtdcore.o mtd-y := mtdcore.o
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD) += $(mtd-y)
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Author: Jonas Holmberg <jonas.holmberg@axis.com> * Author: Jonas Holmberg <jonas.holmberg@axis.com>
* *
* $Id: amd_flash.c,v 1.24 2004/07/12 13:34:30 dwmw2 Exp $ * $Id: amd_flash.c,v 1.25 2004/08/09 13:19:43 dwmw2 Exp $
* *
* Copyright (c) 2001 Axis Communications AB * Copyright (c) 2001 Axis Communications AB
* *
...@@ -1307,9 +1307,7 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1307,9 +1307,7 @@ static int amd_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
} }
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) { mtd_erase_callback(instr);
instr->callback(instr);
}
return 0; return 0;
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
* (C) 2000 Red Hat. GPL'd * (C) 2000 Red Hat. GPL'd
* *
* $Id: cfi_cmdset_0001.c,v 1.153 2004/07/12 21:52:20 dwmw2 Exp $ * $Id: cfi_cmdset_0001.c,v 1.154 2004/08/09 13:19:43 dwmw2 Exp $
* *
* *
* 10/10/2000 Nicolas Pitre <nico@cam.org> * 10/10/2000 Nicolas Pitre <nico@cam.org>
...@@ -1554,8 +1554,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1554,8 +1554,7 @@ int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
return ret; return ret;
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* This code is GPL * This code is GPL
* *
* $Id: cfi_cmdset_0002.c,v 1.103 2004/07/14 16:24:03 dwmw2 Exp $ * $Id: cfi_cmdset_0002.c,v 1.106 2004/08/09 14:02:32 dwmw2 Exp $
* *
*/ */
...@@ -1420,8 +1420,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1420,8 +1420,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
return ret; return ret;
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
...@@ -1444,8 +1443,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1444,8 +1443,7 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr)
return ret; return ret;
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* *
* (C) 2000 Red Hat. GPL'd * (C) 2000 Red Hat. GPL'd
* *
* $Id: cfi_cmdset_0020.c,v 1.14 2004/07/20 02:44:25 dwmw2 Exp $ * $Id: cfi_cmdset_0020.c,v 1.15 2004/08/09 13:19:43 dwmw2 Exp $
* *
* 10/10/2000 Nicolas Pitre <nico@cam.org> * 10/10/2000 Nicolas Pitre <nico@cam.org>
* - completely revamped method functions so they are aware and * - completely revamped method functions so they are aware and
...@@ -966,8 +966,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ...@@ -966,8 +966,7 @@ int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
} }
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* not going to guess how to send commands to them, plus I expect they will * not going to guess how to send commands to them, plus I expect they will
* all speak CFI.. * all speak CFI..
* *
* $Id: jedec.c,v 1.20 2004/07/12 14:03:01 dwmw2 Exp $ * $Id: jedec.c,v 1.21 2004/08/09 13:19:43 dwmw2 Exp $
*/ */
#include <linux/init.h> #include <linux/init.h>
...@@ -780,8 +780,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -780,8 +780,7 @@ static int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
//printk("done\n"); //printk("done\n");
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
#undef flread #undef flread
......
/* /*
* Common code to handle map devices which are simple RAM * Common code to handle map devices which are simple RAM
* (C) 2000 Red Hat. GPL'd. * (C) 2000 Red Hat. GPL'd.
* $Id: map_ram.c,v 1.19 2004/07/12 21:58:44 dwmw2 Exp $ * $Id: map_ram.c,v 1.20 2004/08/09 13:19:43 dwmw2 Exp $
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -114,8 +114,7 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr) ...@@ -114,8 +114,7 @@ static int mapram_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Copyright 2000,2001 David A. Schleef <ds@schleef.org> * Copyright 2000,2001 David A. Schleef <ds@schleef.org>
* 2000,2001 Lineo, Inc. * 2000,2001 Lineo, Inc.
* *
* $Id: sharp.c,v 1.13 2004/07/12 14:06:34 dwmw2 Exp $ * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $
* *
* Devices supported: * Devices supported:
* LH28F016SCT Symmetrical block flash memory, 2Mx8 * LH28F016SCT Symmetrical block flash memory, 2Mx8
...@@ -425,8 +425,7 @@ static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -425,8 +425,7 @@ static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr)
} }
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if(instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
/* /*
* $Id: blkmtd-25.c,v 1.6 2004/07/15 15:09:15 dwmw2 Exp $ * $Id: blkmtd.c,v 1.23 2004/08/09 14:03:19 dwmw2 Exp $
* *
* blkmtd.c - use a block device as a fake MTD * blkmtd.c - use a block device as a fake MTD
* *
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
/* Default erase size in K, always make it a multiple of PAGE_SIZE */ /* Default erase size in K, always make it a multiple of PAGE_SIZE */
#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ #define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */
#define VERSION "$Revision: 1.6 $" #define VERSION "$Revision: 1.23 $"
/* Info for the block device */ /* Info for the block device */
struct blkmtd_dev { struct blkmtd_dev {
...@@ -435,9 +435,7 @@ static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -435,9 +435,7 @@ static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr)
} }
DEBUG(3, "blkmtd: erase: checking callback\n"); DEBUG(3, "blkmtd: erase: checking callback\n");
if (instr->callback) { mtd_erase_callback(instr);
(*(instr->callback))(instr);
}
DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err); DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err);
return err; return err;
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* (c) 1999 Machine Vision Holdings, Inc. * (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
* *
* $Id: doc2000.c,v 1.60 2004/04/07 08:30:04 gleixner Exp $ * $Id: doc2000.c,v 1.62 2004/08/09 14:04:02 dwmw2 Exp $
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -1277,8 +1277,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1277,8 +1277,7 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
callback: callback:
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
up(&this->lock); up(&this->lock);
return 0; return 0;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* (c) 1999 Machine Vision Holdings, Inc. * (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
* *
* $Id: doc2001.c,v 1.42 2004/04/04 12:36:45 gleixner Exp $ * $Id: doc2001.c,v 1.44 2004/08/09 14:04:24 dwmw2 Exp $
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -845,8 +845,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr) ...@@ -845,8 +845,7 @@ int doc_erase (struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
dummy = ReadDOC(docptr, LastDataRead); dummy = ReadDOC(docptr, LastDataRead);
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* (c) 1999 Machine Vision Holdings, Inc. * (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
* *
* $Id: doc2001plus.c,v 1.8 2004/04/04 12:36:45 gleixner Exp $ * $Id: doc2001plus.c,v 1.9 2004/08/09 13:19:44 dwmw2 Exp $
* *
* Released under GPL * Released under GPL
*/ */
...@@ -1111,8 +1111,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1111,8 +1111,7 @@ int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
/* Disable flash internally */ /* Disable flash internally */
WriteDOC(0, docptr, Mplus_FlashSelect); WriteDOC(0, docptr, Mplus_FlashSelect);
if (instr->callback) mtd_erase_callback(instr);
instr->callback(instr);
return 0; return 0;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* /*
* MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART. * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART.
* *
* $Id: lart.c,v 1.6 2004/07/14 17:21:38 dwmw2 Exp $ * $Id: lart.c,v 1.7 2004/08/09 13:19:44 dwmw2 Exp $
* *
* Author: Abraham vd Merwe <abraham@2d3d.co.za> * Author: Abraham vd Merwe <abraham@2d3d.co.za>
* *
...@@ -433,7 +433,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr) ...@@ -433,7 +433,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr)
} }
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) instr->callback (instr); mtd_erase_callback(instr);
return (0); return (0);
} }
......
/* /*
* mtdram - a test mtd device * mtdram - a test mtd device
* $Id: mtdram.c,v 1.32 2003/05/21 15:15:07 dwmw2 Exp $ * $Id: mtdram.c,v 1.33 2004/08/09 13:19:44 dwmw2 Exp $
* Author: Alexander Larsson <alex@cendio.se> * Author: Alexander Larsson <alex@cendio.se>
* *
* Copyright (c) 1999 Alexander Larsson <alex@cendio.se> * Copyright (c) 1999 Alexander Larsson <alex@cendio.se>
...@@ -57,9 +57,8 @@ ram_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -57,9 +57,8 @@ ram_erase(struct mtd_info *mtd, struct erase_info *instr)
memset((char *)mtd->priv + instr->addr, 0xff, instr->len); memset((char *)mtd->priv + instr->addr, 0xff, instr->len);
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
mtd_erase_callback(instr);
if (instr->callback)
(*(instr->callback))(instr);
return 0; return 0;
} }
......
/** /**
* *
* $Id: phram.c,v 1.1 2003/08/21 17:52:30 joern Exp $ * $Id: phram.c,v 1.2 2004/08/09 13:19:44 dwmw2 Exp $
* *
* Copyright (c) Jochen Schaeuble <psionic@psionic.de> * Copyright (c) Jochen Schaeuble <psionic@psionic.de>
* 07/2003 rewritten by Joern Engel <joern@wh.fh-wedel.de> * 07/2003 rewritten by Joern Engel <joern@wh.fh-wedel.de>
...@@ -55,10 +55,7 @@ int phram_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -55,10 +55,7 @@ int phram_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) mtd_erase_callback(instr);
(*(instr->callback))(instr);
else
kfree(instr);
return 0; return 0;
} }
......
/* /*
* $Id: pmc551.c,v 1.27 2004/07/20 02:44:26 dwmw2 Exp $ * $Id: pmc551.c,v 1.28 2004/08/09 13:19:44 dwmw2 Exp $
* *
* PMC551 PCI Mezzanine Ram Device * PMC551 PCI Mezzanine Ram Device
* *
...@@ -169,9 +169,7 @@ static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) ...@@ -169,9 +169,7 @@ static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr)
printk(KERN_DEBUG "pmc551_erase() done\n"); printk(KERN_DEBUG "pmc551_erase() done\n");
#endif #endif
if (instr->callback) { mtd_erase_callback(instr);
(*(instr->callback))(instr);
}
return 0; return 0;
} }
......
/*====================================================================== /*======================================================================
$Id: slram.c,v 1.30 2003/05/20 21:03:08 dwmw2 Exp $ $Id: slram.c,v 1.31 2004/08/09 13:19:44 dwmw2 Exp $
This driver provides a method to access memory not used by the kernel This driver provides a method to access memory not used by the kernel
itself (i.e. if the kernel commandline mem=xxx is used). To actually itself (i.e. if the kernel commandline mem=xxx is used). To actually
...@@ -98,12 +98,7 @@ int slram_erase(struct mtd_info *mtd, struct erase_info *instr) ...@@ -98,12 +98,7 @@ int slram_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->state = MTD_ERASE_DONE; instr->state = MTD_ERASE_DONE;
if (instr->callback) { mtd_erase_callback(instr);
(*(instr->callback))(instr);
}
else {
kfree(instr);
}
return(0); return(0);
} }
......
/* /*
* $Id: mtdchar.c,v 1.62 2004/07/14 13:20:42 dwmw2 Exp $ * $Id: mtdchar.c,v 1.64 2004/08/09 13:59:46 dwmw2 Exp $
* *
* Character-device access to raw MTD devices. * Character-device access to raw MTD devices.
* *
...@@ -262,7 +262,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count ...@@ -262,7 +262,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
IOCTL calls for getting device parameters. IOCTL calls for getting device parameters.
======================================================================*/ ======================================================================*/
static void mtd_erase_callback (struct erase_info *instr) static void mtdchar_erase_callback (struct erase_info *instr)
{ {
wake_up((wait_queue_head_t *)instr->priv); wake_up((wait_queue_head_t *)instr->priv);
} }
...@@ -336,7 +336,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, ...@@ -336,7 +336,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
return -EFAULT; return -EFAULT;
} }
erase->mtd = mtd; erase->mtd = mtd;
erase->callback = mtd_erase_callback; erase->callback = mtdchar_erase_callback;
erase->priv = (unsigned long)&waitq; erase->priv = (unsigned long)&waitq;
/* /*
...@@ -511,7 +511,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file, ...@@ -511,7 +511,6 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
} }
default: default:
DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %lx)\n", cmd, (unsigned long)MEMGETINFO);
ret = -ENOTTY; ret = -ENOTTY;
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* *
* This code is GPL * This code is GPL
* *
* $Id: mtdpart.c,v 1.46 2004/07/12 13:28:07 dwmw2 Exp $ * $Id: mtdpart.c,v 1.49 2004/08/10 13:41:27 dwmw2 Exp $
* *
* 02-21-2002 Thomas Gleixner <gleixner@autronix.de> * 02-21-2002 Thomas Gleixner <gleixner@autronix.de>
* added support for read_oob, write_oob * added support for read_oob, write_oob
...@@ -246,11 +246,22 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr) ...@@ -246,11 +246,22 @@ static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
return -EINVAL; return -EINVAL;
instr->addr += part->offset; instr->addr += part->offset;
ret = part->master->erase(part->master, instr); ret = part->master->erase(part->master, instr);
if (instr->fail_addr != 0xffffffff)
instr->fail_addr -= part->offset;
return ret; return ret;
} }
void mtd_erase_callback(struct erase_info *instr)
{
if (instr->mtd->erase == part_erase) {
struct mtd_part *part = PART(instr->mtd);
if (instr->fail_addr != 0xffffffff)
instr->fail_addr -= part->offset;
instr->addr -= part->offset;
}
if (instr->callback)
instr->callback(instr);
}
static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len)
{ {
struct mtd_part *part = PART(mtd); struct mtd_part *part = PART(mtd);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* The AG-AND chips have nice features for speed improvement, * The AG-AND chips have nice features for speed improvement,
* which are not supported yet. Read / program 4 pages in one go. * which are not supported yet. Read / program 4 pages in one go.
* *
* $Id: nand_base.c,v 1.113 2004/07/14 16:31:31 gleixner Exp $ * $Id: nand_base.c,v 1.115 2004/08/09 13:19:45 dwmw2 Exp $
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/io.h> #include <asm/io.h>
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) #ifdef CONFIG_MTD_PARTITIONS
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#endif #endif
...@@ -1284,12 +1284,12 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, ...@@ -1284,12 +1284,12 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
nand_release_chip(mtd); nand_release_chip(mtd);
/* /*
* Return success, if no ECC failures, else -EIO * Return success, if no ECC failures, else -EBADMSG
* fs driver will take care of that, because * fs driver will take care of that, because
* retlen == desired len and result == -EIO * retlen == desired len and result == -EBADMSG
*/ */
*retlen = read; *retlen = read;
return ecc_failed ? -EIO : 0; return ecc_failed ? -EBADMSG : 0;
} }
/** /**
...@@ -2108,8 +2108,8 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb ...@@ -2108,8 +2108,8 @@ int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbb
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
/* Do call back function */ /* Do call back function */
if (!ret && instr->callback) if (!ret)
instr->callback (instr); mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */ /* Deselect and wake up anyone waiting on the device */
nand_release_chip(mtd); nand_release_chip(mtd);
...@@ -2555,11 +2555,11 @@ void nand_release (struct mtd_info *mtd) ...@@ -2555,11 +2555,11 @@ void nand_release (struct mtd_info *mtd)
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE) #ifdef CONFIG_MTD_PARTITIONS
/* Unregister partitions */ /* Deregister partitions */
del_mtd_partitions (mtd); del_mtd_partitions (mtd);
#endif #endif
/* Unregister the device */ /* Deregister the device */
del_mtd_device (mtd); del_mtd_device (mtd);
/* Free bad block table memory, if allocated */ /* Free bad block table memory, if allocated */
......
/* /*
* $Id: mtd.h,v 1.54 2004/07/15 01:13:12 dwmw2 Exp $ * $Id: mtd.h,v 1.56 2004/08/09 18:46:04 dmarlin Exp $
* *
* Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
* *
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/mtd/compatmac.h>
#include <mtd/mtd-abi.h> #include <mtd/mtd-abi.h>
#define MTD_CHAR_MAJOR 90 #define MTD_CHAR_MAJOR 90
...@@ -192,6 +193,17 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, ...@@ -192,6 +193,17 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0)
#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
#else
static inline void mtd_erase_callback(struct erase_info *instr)
{
if (instr->callback)
instr->callback(instr);
}
#endif
/* /*
* Debugging macro and defines * Debugging macro and defines
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment